mirror of
				https://github.com/theoludwig/markdownlint-rule-relative-links.git
				synced 2025-09-09 19:39:29 +02:00 
			
		
		
		
	refactor: early conditions first
This commit is contained in:
		
							
								
								
									
										122
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								src/index.js
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ const { | |||||||
|   filterTokens, |   filterTokens, | ||||||
|   convertHeadingToHTMLFragment, |   convertHeadingToHTMLFragment, | ||||||
|   getMarkdownHeadings, |   getMarkdownHeadings, | ||||||
|   getMarkdownAnchorHTMLFragments, |   getMarkdownIdOrAnchorNameFragments, | ||||||
| } = require("./utils.js") | } = require("./utils.js") | ||||||
|  |  | ||||||
| /** @typedef {import('markdownlint').Rule} MarkdownLintRule */ | /** @typedef {import('markdownlint').Rule} MarkdownLintRule */ | ||||||
| @@ -46,65 +46,83 @@ const customRule = { | |||||||
|           } |           } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (hrefSrc != null) { |         if (hrefSrc == null) { | ||||||
|           const url = new URL(hrefSrc, pathToFileURL(params.name)) |           continue | ||||||
|           const isRelative = |         } | ||||||
|             url.protocol === "file:" && |  | ||||||
|             !hrefSrc.startsWith("/") && |  | ||||||
|             !hrefSrc.startsWith("#") |  | ||||||
|           if (isRelative) { |  | ||||||
|             const detail = `"${hrefSrc}"` |  | ||||||
|  |  | ||||||
|             if (!fs.existsSync(url)) { |         const url = new URL(hrefSrc, pathToFileURL(params.name)) | ||||||
|  |         const isRelative = | ||||||
|  |           url.protocol === "file:" && | ||||||
|  |           !hrefSrc.startsWith("/") && | ||||||
|  |           !hrefSrc.startsWith("#") | ||||||
|  |  | ||||||
|  |         if (!isRelative) { | ||||||
|  |           continue | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const detail = `"${hrefSrc}"` | ||||||
|  |  | ||||||
|  |         if (!fs.existsSync(url)) { | ||||||
|  |           onError({ | ||||||
|  |             lineNumber, | ||||||
|  |             detail: `${detail} should exist in the file system`, | ||||||
|  |           }) | ||||||
|  |           continue | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (url.hash.length <= 0) { | ||||||
|  |           if (hrefSrc.includes("#")) { | ||||||
|  |             if (type !== "link_open") { | ||||||
|               onError({ |               onError({ | ||||||
|                 lineNumber, |                 lineNumber, | ||||||
|                 detail: `${detail} should exist in the file system`, |                 detail: `${detail} should not have a fragment identifier as it is an image`, | ||||||
|               }) |               }) | ||||||
|               continue |               continue | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (type !== "link_open") { |             onError({ | ||||||
|               continue |               lineNumber, | ||||||
|             } |               detail: `${detail} should have a valid fragment identifier`, | ||||||
|  |             }) | ||||||
|             if (url.hash.length <= 0) { |             continue | ||||||
|               if (hrefSrc.includes("#")) { |  | ||||||
|                 onError({ |  | ||||||
|                   lineNumber, |  | ||||||
|                   detail: `${detail} should have a valid fragment identifier`, |  | ||||||
|                 }) |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (url.hash.length > 0) { |  | ||||||
|               const fileContent = fs.readFileSync(url, { encoding: "utf8" }) |  | ||||||
|               const headings = getMarkdownHeadings(fileContent) |  | ||||||
|               const anchorHTMLFragments = |  | ||||||
|                 getMarkdownAnchorHTMLFragments(fileContent) |  | ||||||
|  |  | ||||||
|               /** @type {Map<string, number>} */ |  | ||||||
|               const fragments = new Map() |  | ||||||
|  |  | ||||||
|               const headingsHTMLFragments = headings.map((heading) => { |  | ||||||
|                 const fragment = convertHeadingToHTMLFragment(heading) |  | ||||||
|                 const count = fragments.get(fragment) ?? 0 |  | ||||||
|                 fragments.set(fragment, count + 1) |  | ||||||
|                 if (count !== 0) { |  | ||||||
|                   return `${fragment}-${count}` |  | ||||||
|                 } |  | ||||||
|                 return fragment |  | ||||||
|               }) |  | ||||||
|  |  | ||||||
|               headingsHTMLFragments.push(...anchorHTMLFragments) |  | ||||||
|  |  | ||||||
|               if (!headingsHTMLFragments.includes(url.hash)) { |  | ||||||
|                 onError({ |  | ||||||
|                   lineNumber, |  | ||||||
|                   detail: `${detail} should have a valid fragment identifier`, |  | ||||||
|                 }) |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|           } |           } | ||||||
|  |           continue | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (type !== "link_open") { | ||||||
|  |           onError({ | ||||||
|  |             lineNumber, | ||||||
|  |             detail: `${detail} should not have a fragment identifier as it is an image`, | ||||||
|  |           }) | ||||||
|  |           continue | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const fileContent = fs.readFileSync(url, { encoding: "utf8" }) | ||||||
|  |         const headings = getMarkdownHeadings(fileContent) | ||||||
|  |         const idOrAnchorNameHTMLFragments = | ||||||
|  |           getMarkdownIdOrAnchorNameFragments(fileContent) | ||||||
|  |  | ||||||
|  |         /** @type {Map<string, number>} */ | ||||||
|  |         const fragments = new Map() | ||||||
|  |  | ||||||
|  |         const fragmentsHTML = headings.map((heading) => { | ||||||
|  |           const fragment = convertHeadingToHTMLFragment(heading) | ||||||
|  |           const count = fragments.get(fragment) ?? 0 | ||||||
|  |           fragments.set(fragment, count + 1) | ||||||
|  |           if (count !== 0) { | ||||||
|  |             return `${fragment}-${count}` | ||||||
|  |           } | ||||||
|  |           return fragment | ||||||
|  |         }) | ||||||
|  |  | ||||||
|  |         fragmentsHTML.push(...idOrAnchorNameHTMLFragments) | ||||||
|  |  | ||||||
|  |         if (!fragmentsHTML.includes(url.hash)) { | ||||||
|  |           onError({ | ||||||
|  |             lineNumber, | ||||||
|  |             detail: `${detail} should have a valid fragment identifier`, | ||||||
|  |           }) | ||||||
|  |           continue | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|   | |||||||
| @@ -119,7 +119,7 @@ const getMarkdownIdOrAnchorNameFragments = (content) => { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     const anchorIdOrName = anchorMatch[1] |     const anchorIdOrName = anchorMatch[1] | ||||||
|     if (anchorIdOrName === undefined) { |     if (anchorIdOrName.length <= 0) { | ||||||
|       continue |       continue | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -136,5 +136,5 @@ module.exports = { | |||||||
|   filterTokens, |   filterTokens, | ||||||
|   convertHeadingToHTMLFragment, |   convertHeadingToHTMLFragment, | ||||||
|   getMarkdownHeadings, |   getMarkdownHeadings, | ||||||
|   getMarkdownAnchorHTMLFragments: getMarkdownIdOrAnchorNameFragments, |   getMarkdownIdOrAnchorNameFragments, | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ const assert = require("node:assert/strict") | |||||||
| const { | const { | ||||||
|   convertHeadingToHTMLFragment, |   convertHeadingToHTMLFragment, | ||||||
|   getMarkdownHeadings, |   getMarkdownHeadings, | ||||||
|   getMarkdownAnchorHTMLFragments, |   getMarkdownIdOrAnchorNameFragments, | ||||||
| } = require("../src/utils.js") | } = require("../src/utils.js") | ||||||
|  |  | ||||||
| test("utils", async (t) => { | test("utils", async (t) => { | ||||||
| @@ -36,18 +36,22 @@ test("utils", async (t) => { | |||||||
|     ) |     ) | ||||||
|   }) |   }) | ||||||
|  |  | ||||||
|   await t.test("getMarkdownAnchorHTMLFragments", async () => { |   await t.test("getMarkdownIdOrAnchorNameFragments", async () => { | ||||||
|     assert.deepStrictEqual( |     assert.deepStrictEqual( | ||||||
|       getMarkdownAnchorHTMLFragments( |       getMarkdownIdOrAnchorNameFragments( | ||||||
|         '<a name="anchorName" id="anchorId">Link</a>', |         '<a name="anchorName" id="anchorId">Link</a>', | ||||||
|       ), |       ), | ||||||
|       ["#anchorId"], |       ["#anchorId"], | ||||||
|     ) |     ) | ||||||
|     assert.deepStrictEqual( |     assert.deepStrictEqual( | ||||||
|       getMarkdownAnchorHTMLFragments('<a name="anchorName">Link</a>'), |       getMarkdownIdOrAnchorNameFragments('<a name="anchorName">Link</a>'), | ||||||
|       ["#anchorName"], |       ["#anchorName"], | ||||||
|     ) |     ) | ||||||
|     assert.deepStrictEqual(getMarkdownAnchorHTMLFragments("<a>Link</a>"), []) |     assert.deepStrictEqual( | ||||||
|     assert.deepStrictEqual(getMarkdownAnchorHTMLFragments("<a>"), []) |       getMarkdownIdOrAnchorNameFragments("<a>Link</a>"), | ||||||
|  |       [], | ||||||
|  |     ) | ||||||
|  |     assert.deepStrictEqual(getMarkdownIdOrAnchorNameFragments("<a>"), []) | ||||||
|  |     assert.deepStrictEqual(getMarkdownIdOrAnchorNameFragments("<a id=>"), []) | ||||||
|   }) |   }) | ||||||
| }) | }) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user