mirror of
				https://github.com/theoludwig/markdownlint-rule-relative-links.git
				synced 2025-11-01 00:49:07 +01:00 
			
		
		
		
	fix: cleaner code + better error messages
This commit is contained in:
		
							
								
								
									
										1
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							@@ -26,3 +26,4 @@ jobs:
 | 
				
			|||||||
      - run: "npm run lint:markdown"
 | 
					      - run: "npm run lint:markdown"
 | 
				
			||||||
      - run: "npm run lint:eslint"
 | 
					      - run: "npm run lint:eslint"
 | 
				
			||||||
      - run: "npm run lint:prettier"
 | 
					      - run: "npm run lint:prettier"
 | 
				
			||||||
 | 
					      - run: "npm run lint:javascript"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,4 +2,5 @@
 | 
				
			|||||||
. "$(dirname "$0")/_/husky.sh"
 | 
					. "$(dirname "$0")/_/husky.sh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
npm run lint:staged
 | 
					npm run lint:staged
 | 
				
			||||||
 | 
					npm run lint:javascript
 | 
				
			||||||
npm run test
 | 
					npm run test
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,7 +43,7 @@ With `awesome.md` content:
 | 
				
			|||||||
Running [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) with `markdownlint-rule-relative-links` will output:
 | 
					Running [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) with `markdownlint-rule-relative-links` will output:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```sh
 | 
					```sh
 | 
				
			||||||
awesome.md:3 relative-links Relative links should be valid [Link "./invalid.txt" should exist in the file system]
 | 
					awesome.md:3 relative-links Relative links should be valid ["./invalid.txt" should exist in the file system]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Additional features
 | 
					### Additional features
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								jsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								jsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "lib": ["ESNext"],
 | 
				
			||||||
 | 
					    "target": "ESNext",
 | 
				
			||||||
 | 
					    "module": "CommonJS",
 | 
				
			||||||
 | 
					    "moduleResolution": "Node",
 | 
				
			||||||
 | 
					    "checkJs": true,
 | 
				
			||||||
 | 
					    "allowJs": true,
 | 
				
			||||||
 | 
					    "noEmit": true,
 | 
				
			||||||
 | 
					    "rootDir": ".",
 | 
				
			||||||
 | 
					    "baseUrl": ".",
 | 
				
			||||||
 | 
					    "strict": true,
 | 
				
			||||||
 | 
					    "allowUnusedLabels": false,
 | 
				
			||||||
 | 
					    "allowUnreachableCode": false,
 | 
				
			||||||
 | 
					    "noFallthroughCasesInSwitch": true,
 | 
				
			||||||
 | 
					    "noImplicitAny": true,
 | 
				
			||||||
 | 
					    "noImplicitOverride": true,
 | 
				
			||||||
 | 
					    "noImplicitReturns": true,
 | 
				
			||||||
 | 
					    "noUncheckedIndexedAccess": true,
 | 
				
			||||||
 | 
					    "noUnusedLocals": true,
 | 
				
			||||||
 | 
					    "noUnusedParameters": true,
 | 
				
			||||||
 | 
					    "forceConsistentCasingInFileNames": true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										27
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -15,6 +15,7 @@
 | 
				
			|||||||
      "devDependencies": {
 | 
					      "devDependencies": {
 | 
				
			||||||
        "@commitlint/cli": "18.4.4",
 | 
					        "@commitlint/cli": "18.4.4",
 | 
				
			||||||
        "@commitlint/config-conventional": "18.4.4",
 | 
					        "@commitlint/config-conventional": "18.4.4",
 | 
				
			||||||
 | 
					        "@types/markdown-it": "13.0.7",
 | 
				
			||||||
        "@types/node": "20.10.8",
 | 
					        "@types/node": "20.10.8",
 | 
				
			||||||
        "editorconfig-checker": "5.1.2",
 | 
					        "editorconfig-checker": "5.1.2",
 | 
				
			||||||
        "eslint": "8.56.0",
 | 
					        "eslint": "8.56.0",
 | 
				
			||||||
@@ -30,7 +31,8 @@
 | 
				
			|||||||
        "markdownlint-cli2": "0.11.0",
 | 
					        "markdownlint-cli2": "0.11.0",
 | 
				
			||||||
        "pinst": "3.0.0",
 | 
					        "pinst": "3.0.0",
 | 
				
			||||||
        "prettier": "3.1.1",
 | 
					        "prettier": "3.1.1",
 | 
				
			||||||
        "semantic-release": "22.0.12"
 | 
					        "semantic-release": "22.0.12",
 | 
				
			||||||
 | 
					        "typescript": "5.3.3"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "engines": {
 | 
					      "engines": {
 | 
				
			||||||
        "node": ">=16.0.0",
 | 
					        "node": ">=16.0.0",
 | 
				
			||||||
@@ -1294,6 +1296,28 @@
 | 
				
			|||||||
      "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
 | 
					      "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@types/linkify-it": {
 | 
				
			||||||
 | 
					      "version": "3.0.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@types/markdown-it": {
 | 
				
			||||||
 | 
					      "version": "13.0.7",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.7.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA==",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@types/linkify-it": "*",
 | 
				
			||||||
 | 
					        "@types/mdurl": "*"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@types/mdurl": {
 | 
				
			||||||
 | 
					      "version": "1.0.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==",
 | 
				
			||||||
 | 
					      "dev": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/@types/minimist": {
 | 
					    "node_modules/@types/minimist": {
 | 
				
			||||||
      "version": "1.2.5",
 | 
					      "version": "1.2.5",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
 | 
				
			||||||
@@ -10351,7 +10375,6 @@
 | 
				
			|||||||
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
 | 
					      "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "peer": true,
 | 
					 | 
				
			||||||
      "bin": {
 | 
					      "bin": {
 | 
				
			||||||
        "tsc": "bin/tsc",
 | 
					        "tsc": "bin/tsc",
 | 
				
			||||||
        "tsserver": "bin/tsserver"
 | 
					        "tsserver": "bin/tsserver"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,7 @@
 | 
				
			|||||||
    "lint:markdown": "markdownlint-cli2",
 | 
					    "lint:markdown": "markdownlint-cli2",
 | 
				
			||||||
    "lint:eslint": "eslint . --max-warnings 0 --report-unused-disable-directives --ignore-path .gitignore",
 | 
					    "lint:eslint": "eslint . --max-warnings 0 --report-unused-disable-directives --ignore-path .gitignore",
 | 
				
			||||||
    "lint:prettier": "prettier . --check --ignore-path .gitignore",
 | 
					    "lint:prettier": "prettier . --check --ignore-path .gitignore",
 | 
				
			||||||
 | 
					    "lint:javascript": "tsc --project jsconfig.json --noEmit",
 | 
				
			||||||
    "lint:staged": "lint-staged",
 | 
					    "lint:staged": "lint-staged",
 | 
				
			||||||
    "test": "node --test ./test",
 | 
					    "test": "node --test ./test",
 | 
				
			||||||
    "release": "semantic-release",
 | 
					    "release": "semantic-release",
 | 
				
			||||||
@@ -48,6 +49,7 @@
 | 
				
			|||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@commitlint/cli": "18.4.4",
 | 
					    "@commitlint/cli": "18.4.4",
 | 
				
			||||||
    "@commitlint/config-conventional": "18.4.4",
 | 
					    "@commitlint/config-conventional": "18.4.4",
 | 
				
			||||||
 | 
					    "@types/markdown-it": "13.0.7",
 | 
				
			||||||
    "@types/node": "20.10.8",
 | 
					    "@types/node": "20.10.8",
 | 
				
			||||||
    "editorconfig-checker": "5.1.2",
 | 
					    "editorconfig-checker": "5.1.2",
 | 
				
			||||||
    "eslint": "8.56.0",
 | 
					    "eslint": "8.56.0",
 | 
				
			||||||
@@ -63,6 +65,7 @@
 | 
				
			|||||||
    "markdownlint-cli2": "0.11.0",
 | 
					    "markdownlint-cli2": "0.11.0",
 | 
				
			||||||
    "pinst": "3.0.0",
 | 
					    "pinst": "3.0.0",
 | 
				
			||||||
    "prettier": "3.1.1",
 | 
					    "prettier": "3.1.1",
 | 
				
			||||||
    "semantic-release": "22.0.12"
 | 
					    "semantic-release": "22.0.12",
 | 
				
			||||||
 | 
					    "typescript": "5.3.3"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								src/index.js
									
									
									
									
									
								
							@@ -5,22 +5,27 @@ const fs = require("node:fs")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const {
 | 
					const {
 | 
				
			||||||
  filterTokens,
 | 
					  filterTokens,
 | 
				
			||||||
  addError,
 | 
					 | 
				
			||||||
  convertHeadingToHTMLFragment,
 | 
					  convertHeadingToHTMLFragment,
 | 
				
			||||||
  getMarkdownHeadings,
 | 
					  getMarkdownHeadings,
 | 
				
			||||||
} = require("./utils.js")
 | 
					} = require("./utils.js")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @typedef {import('markdownlint').Rule} MarkdownLintRule */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @type {MarkdownLintRule}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
const customRule = {
 | 
					const customRule = {
 | 
				
			||||||
  names: ["relative-links"],
 | 
					  names: ["relative-links"],
 | 
				
			||||||
  description: "Relative links should be valid",
 | 
					  description: "Relative links should be valid",
 | 
				
			||||||
  tags: ["links"],
 | 
					  tags: ["links"],
 | 
				
			||||||
  function: (params, onError) => {
 | 
					  function: (params, onError) => {
 | 
				
			||||||
    filterTokens(params, "inline", (token) => {
 | 
					    filterTokens(params, "inline", (token) => {
 | 
				
			||||||
      for (const child of token.children) {
 | 
					      const children = token.children ?? []
 | 
				
			||||||
        const { lineNumber, type, attrs } = child
 | 
					      for (const child of children) {
 | 
				
			||||||
 | 
					        const { type, attrs, lineNumber } = child
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /** @type {string | null} */
 | 
					        /** @type {string | undefined} */
 | 
				
			||||||
        let hrefSrc = null
 | 
					        let hrefSrc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (type === "link_open") {
 | 
					        if (type === "link_open") {
 | 
				
			||||||
          for (const attr of attrs) {
 | 
					          for (const attr of attrs) {
 | 
				
			||||||
@@ -45,14 +50,13 @@ const customRule = {
 | 
				
			|||||||
          const isRelative =
 | 
					          const isRelative =
 | 
				
			||||||
            url.protocol === "file:" && !hrefSrc.startsWith("/")
 | 
					            url.protocol === "file:" && !hrefSrc.startsWith("/")
 | 
				
			||||||
          if (isRelative) {
 | 
					          if (isRelative) {
 | 
				
			||||||
            const detail = `Link "${hrefSrc}"`
 | 
					            const detail = `"${hrefSrc}"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!fs.existsSync(url)) {
 | 
					            if (!fs.existsSync(url)) {
 | 
				
			||||||
              addError(
 | 
					              onError({
 | 
				
			||||||
                onError,
 | 
					 | 
				
			||||||
                lineNumber,
 | 
					                lineNumber,
 | 
				
			||||||
                `${detail} should exist in the file system`,
 | 
					                detail: `${detail} should exist in the file system`,
 | 
				
			||||||
              )
 | 
					              })
 | 
				
			||||||
              continue
 | 
					              continue
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,11 +78,10 @@ const customRule = {
 | 
				
			|||||||
              })
 | 
					              })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              if (!headingsHTMLFragments.includes(url.hash)) {
 | 
					              if (!headingsHTMLFragments.includes(url.hash)) {
 | 
				
			||||||
                addError(
 | 
					                onError({
 | 
				
			||||||
                  onError,
 | 
					 | 
				
			||||||
                  lineNumber,
 | 
					                  lineNumber,
 | 
				
			||||||
                  `${detail} should have a valid fragment`,
 | 
					                  detail: `${detail} should have a valid fragment identifier`,
 | 
				
			||||||
                )
 | 
					                })
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								src/utils.js
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								src/utils.js
									
									
									
									
									
								
							@@ -1,11 +1,14 @@
 | 
				
			|||||||
const MarkdownIt = require("markdown-it")
 | 
					const MarkdownIt = require("markdown-it")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @typedef {import('markdownlint').RuleParams} MarkdownLintRuleParams */
 | 
				
			||||||
 | 
					/** @typedef {import('markdownlint').MarkdownItToken} MarkdownItToken */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Calls the provided function for each matching token.
 | 
					 * Calls the provided function for each matching token.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {object} params RuleParams instance.
 | 
					 * @param {MarkdownLintRuleParams} params RuleParams instance.
 | 
				
			||||||
 * @param {string} type Token type identifier.
 | 
					 * @param {string} type Token type identifier.
 | 
				
			||||||
 * @param {Function} handler Callback function.
 | 
					 * @param {(token: MarkdownItToken) => void} handler Callback function.
 | 
				
			||||||
 * @returns {void}
 | 
					 * @returns {void}
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const filterTokens = (params, type, handler) => {
 | 
					const filterTokens = (params, type, handler) => {
 | 
				
			||||||
@@ -16,27 +19,6 @@ const filterTokens = (params, type, handler) => {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Adds a generic error object via the onError callback.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param {object} onError RuleOnError instance.
 | 
					 | 
				
			||||||
 * @param {number} lineNumber Line number.
 | 
					 | 
				
			||||||
 * @param {string} [detail] Error details.
 | 
					 | 
				
			||||||
 * @param {string} [context] Error context.
 | 
					 | 
				
			||||||
 * @param {number[]} [range] Column and length of error.
 | 
					 | 
				
			||||||
 * @param {object} [fixInfo] RuleOnErrorFixInfo instance.
 | 
					 | 
				
			||||||
 * @returns {void}
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
const addError = (onError, lineNumber, detail, context, range, fixInfo) => {
 | 
					 | 
				
			||||||
  onError({
 | 
					 | 
				
			||||||
    lineNumber,
 | 
					 | 
				
			||||||
    detail,
 | 
					 | 
				
			||||||
    context,
 | 
					 | 
				
			||||||
    range,
 | 
					 | 
				
			||||||
    fixInfo,
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Converts a Markdown heading into an HTML fragment according to the rules
 | 
					 * Converts a Markdown heading into an HTML fragment according to the rules
 | 
				
			||||||
 * used by GitHub.
 | 
					 * used by GitHub.
 | 
				
			||||||
@@ -98,8 +80,10 @@ const getMarkdownHeadings = (content) => {
 | 
				
			|||||||
      continue
 | 
					      continue
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const children = token.children ?? []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    headings.push(
 | 
					    headings.push(
 | 
				
			||||||
      `${token.children
 | 
					      `${children
 | 
				
			||||||
        .map((token) => {
 | 
					        .map((token) => {
 | 
				
			||||||
          return token.content
 | 
					          return token.content
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
@@ -112,7 +96,6 @@ const getMarkdownHeadings = (content) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
  filterTokens,
 | 
					  filterTokens,
 | 
				
			||||||
  addError,
 | 
					 | 
				
			||||||
  convertHeadingToHTMLFragment,
 | 
					  convertHeadingToHTMLFragment,
 | 
				
			||||||
  getMarkdownHeadings,
 | 
					  getMarkdownHeadings,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
const test = require("node:test")
 | 
					const { test } = require("node:test")
 | 
				
			||||||
const assert = require("node:assert/strict")
 | 
					const assert = require("node:assert/strict")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { markdownlint } = require("markdownlint").promises
 | 
					const { markdownlint } = require("markdownlint").promises
 | 
				
			||||||
@@ -14,33 +14,33 @@ test("ensure the rule validate correctly", async () => {
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    customRules: [relativeLinks],
 | 
					    customRules: [relativeLinks],
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
  assert.equal(lintResults["test/fixtures/Valid.md"].length, 0)
 | 
					  assert.equal(lintResults["test/fixtures/Valid.md"]?.length, 0)
 | 
				
			||||||
  assert.equal(lintResults["test/fixtures/Invalid.md"].length, 3)
 | 
					  assert.equal(lintResults["test/fixtures/Invalid.md"]?.length, 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  assert.equal(
 | 
					  assert.equal(
 | 
				
			||||||
    lintResults["test/fixtures/Invalid.md"][0]?.ruleDescription,
 | 
					    lintResults["test/fixtures/Invalid.md"]?.[0]?.ruleDescription,
 | 
				
			||||||
    "Relative links should be valid",
 | 
					    "Relative links should be valid",
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  assert.equal(
 | 
					  assert.equal(
 | 
				
			||||||
    lintResults["test/fixtures/Invalid.md"][0]?.errorDetail,
 | 
					    lintResults["test/fixtures/Invalid.md"]?.[0]?.errorDetail,
 | 
				
			||||||
    'Link "./basic.test.js" should exist in the file system',
 | 
					    '"./basic.test.js" should exist in the file system',
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  assert.equal(
 | 
					  assert.equal(
 | 
				
			||||||
    lintResults["test/fixtures/Invalid.md"][1]?.ruleDescription,
 | 
					    lintResults["test/fixtures/Invalid.md"]?.[1]?.ruleDescription,
 | 
				
			||||||
    "Relative links should be valid",
 | 
					    "Relative links should be valid",
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  assert.equal(
 | 
					  assert.equal(
 | 
				
			||||||
    lintResults["test/fixtures/Invalid.md"][1]?.errorDetail,
 | 
					    lintResults["test/fixtures/Invalid.md"]?.[1]?.errorDetail,
 | 
				
			||||||
    'Link "../image.png" should exist in the file system',
 | 
					    '"../image.png" should exist in the file system',
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  assert.equal(
 | 
					  assert.equal(
 | 
				
			||||||
    lintResults["test/fixtures/Invalid.md"][2]?.ruleDescription,
 | 
					    lintResults["test/fixtures/Invalid.md"]?.[2]?.ruleDescription,
 | 
				
			||||||
    "Relative links should be valid",
 | 
					    "Relative links should be valid",
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  assert.equal(
 | 
					  assert.equal(
 | 
				
			||||||
    lintResults["test/fixtures/Invalid.md"][2]?.errorDetail,
 | 
					    lintResults["test/fixtures/Invalid.md"]?.[2]?.errorDetail,
 | 
				
			||||||
    'Link "./Valid.md#not-existing-heading" should have a valid fragment',
 | 
					    '"./Valid.md#not-existing-heading" should have a valid fragment identifier',
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
const test = require("node:test")
 | 
					const { test } = require("node:test")
 | 
				
			||||||
const assert = require("node:assert/strict")
 | 
					const assert = require("node:assert/strict")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const {
 | 
					const {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user