markdownlint-rule-relative-links
Advanced tools
Comparing version 2.2.0 to 2.3.0
{ | ||
"name": "markdownlint-rule-relative-links", | ||
"version": "2.2.0", | ||
"version": "2.3.0", | ||
"public": true, | ||
@@ -40,5 +40,5 @@ "description": "Custom rule for markdownlint to validate relative links.", | ||
"lint:staged": "lint-staged", | ||
"test": "node --test --experimental-test-coverage", | ||
"test": "node --test", | ||
"release": "semantic-release", | ||
"_postinstall": "husky install", | ||
"_postinstall": "husky", | ||
"prepublishOnly": "pinst --disable", | ||
@@ -51,6 +51,6 @@ "postpublish": "pinst --enable" | ||
"devDependencies": { | ||
"@commitlint/cli": "18.4.4", | ||
"@commitlint/config-conventional": "18.4.4", | ||
"@commitlint/cli": "18.6.0", | ||
"@commitlint/config-conventional": "18.6.0", | ||
"@types/markdown-it": "13.0.7", | ||
"@types/node": "20.11.0", | ||
"@types/node": "20.11.10", | ||
"editorconfig-checker": "5.1.2", | ||
@@ -64,11 +64,11 @@ "eslint": "8.56.0", | ||
"eslint-plugin-unicorn": "50.0.1", | ||
"husky": "8.0.3", | ||
"husky": "9.0.7", | ||
"lint-staged": "15.2.0", | ||
"markdownlint": "0.33.0", | ||
"markdownlint-cli2": "0.11.0", | ||
"markdownlint-cli2": "0.12.1", | ||
"pinst": "3.0.0", | ||
"prettier": "3.1.1", | ||
"semantic-release": "22.0.12", | ||
"prettier": "3.2.4", | ||
"semantic-release": "23.0.0", | ||
"typescript": "5.3.3" | ||
} | ||
} |
@@ -69,3 +69,3 @@ <h1 align="center">markdownlint-rule-relative-links</h1> | ||
- [Node.js](https://nodejs.org/) >= 16.0.0 | ||
[Node.js](https://nodejs.org/) >= 16.0.0 | ||
@@ -92,3 +92,3 @@ ## Installation | ||
}, | ||
"globs": ["**/*.{md,mdx}"], | ||
"globs": ["**/*.md"], | ||
"ignores": ["**/node_modules"], | ||
@@ -95,0 +95,0 @@ "customRules": ["markdownlint-rule-relative-links"] |
@@ -11,2 +11,5 @@ "use strict" | ||
getMarkdownIdOrAnchorNameFragments, | ||
isValidIntegerString, | ||
getNumberOfLines, | ||
getLineNumberStringFromFragment, | ||
} = require("./utils.js") | ||
@@ -76,3 +79,3 @@ | ||
if (hrefSrc.includes("#")) { | ||
if (type !== "link_open") { | ||
if (type === "image") { | ||
onError({ | ||
@@ -94,3 +97,3 @@ lineNumber, | ||
if (type !== "link_open") { | ||
if (type === "image") { | ||
onError({ | ||
@@ -103,2 +106,6 @@ lineNumber, | ||
if (!url.pathname.endsWith(".md")) { | ||
continue | ||
} | ||
const fileContent = fs.readFileSync(url, { encoding: "utf8" }) | ||
@@ -124,3 +131,31 @@ const headings = getMarkdownHeadings(fileContent) | ||
if (!fragmentsHTML.includes(url.hash)) { | ||
if (!fragmentsHTML.includes(url.hash.toLowerCase())) { | ||
if (url.hash.startsWith("#L")) { | ||
const lineNumberFragmentString = getLineNumberStringFromFragment( | ||
url.hash, | ||
) | ||
const hasOnlyDigits = isValidIntegerString(lineNumberFragmentString) | ||
if (!hasOnlyDigits) { | ||
onError({ | ||
lineNumber, | ||
detail: `${detail} should have a valid fragment identifier`, | ||
}) | ||
continue | ||
} | ||
const lineNumberFragment = Number.parseInt( | ||
lineNumberFragmentString, | ||
10, | ||
) | ||
const numberOfLines = getNumberOfLines(fileContent) | ||
if (lineNumberFragment > numberOfLines) { | ||
onError({ | ||
lineNumber, | ||
detail: `${detail} should have a valid fragment identifier, ${detail} should have at least ${lineNumberFragment} lines to be valid`, | ||
}) | ||
continue | ||
} | ||
} | ||
onError({ | ||
@@ -127,0 +162,0 @@ lineNumber, |
@@ -5,2 +5,4 @@ const MarkdownIt = require("markdown-it") | ||
const markdownIt = new MarkdownIt({ html: true }) | ||
/** | ||
@@ -41,3 +43,2 @@ * Converts a Markdown heading into an HTML fragment according to the rules | ||
const getMarkdownHeadings = (content) => { | ||
const markdownIt = new MarkdownIt({ html: true }) | ||
const tokens = markdownIt.parse(content, {}) | ||
@@ -91,3 +92,2 @@ | ||
const getMarkdownIdOrAnchorNameFragments = (content) => { | ||
const markdownIt = new MarkdownIt({ html: true }) | ||
const tokens = markdownIt.parse(content, {}) | ||
@@ -120,2 +120,38 @@ | ||
/** | ||
* Checks if a string is a valid integer. | ||
* | ||
* Using `Number.parseInt` combined with `Number.isNaN` will not be sufficient enough because `Number.parseInt("1abc", 10)` will return `1` (a valid number) instead of `NaN`. | ||
* | ||
* @param {string} value | ||
* @returns {boolean} | ||
* @example isValidIntegerString("1") // true | ||
* @example isValidIntegerString("45") // true | ||
* @example isValidIntegerString("1abc") // false | ||
* @example isValidIntegerString("1.0") // false | ||
*/ | ||
const isValidIntegerString = (value) => { | ||
const regex = /^\d+$/ | ||
return regex.test(value) | ||
} | ||
/** | ||
* Gets the number of lines in a string, based on the number of `\n` characters. | ||
* @param {string} content | ||
* @returns {number} | ||
*/ | ||
const getNumberOfLines = (content) => { | ||
return content.split("\n").length | ||
} | ||
/** | ||
* Gets the line number string from a fragment. | ||
* @param {string} fragment | ||
* @returns {string} | ||
* @example getLineNumberStringFromFragment("#L50") // 50 | ||
*/ | ||
const getLineNumberStringFromFragment = (fragment) => { | ||
return fragment.slice(2) | ||
} | ||
module.exports = { | ||
@@ -125,2 +161,5 @@ convertHeadingToHTMLFragment, | ||
getMarkdownIdOrAnchorNameFragments, | ||
isValidIntegerString, | ||
getNumberOfLines, | ||
getLineNumberStringFromFragment, | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
17713
312