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