From 3efa2a57449fde2649cc83f63128db7c84f16d38 Mon Sep 17 00:00:00 2001 From: David Anson Date: Thu, 28 Nov 2024 20:36:44 -0800 Subject: [PATCH] wip --- .github/workflows/ci.yml | 8 - .gitignore | 9 +- .npmignore | 4 +- README.md | 20 +- demo/browser-exports.mjs | 9 + demo/default.htm | 2 - demo/default.js | 17 +- demo/markdownlint-browser.js | 7144 ----------------- demo/markdownlint-exports.js | 8 - demo/module-stub.cjs | 8 + .../{webpack.config.js => webpack.config.mjs} | 39 +- doc-build/build-rules.mjs | 6 +- doc/CustomRules.md | 8 +- eslint.config.mjs | 45 +- example/Gruntfile.cjs | 28 + example/Gruntfile.js | 28 - example/gulpfile.cjs | 24 + example/gulpfile.js | 23 - example/{standalone.js => standalone.mjs} | 11 +- example/typescript/type-check.ts | 32 +- helpers/.npmignore | 2 +- helpers/{helpers.js => helpers.cjs} | 14 +- helpers/micromark-helpers.cjs | 8 +- ...icromark-parse.cjs => micromark-parse.mjs} | 62 +- helpers/micromark-types.d.mts | 11 + helpers/package.json | 11 +- helpers/{shared.js => shared.cjs} | 0 helpers/test.cjs | 2 +- lib/{cache.js => cache.mjs} | 26 +- lib/configuration.d.ts | 2 +- lib/{constants.js => constants.mjs} | 10 +- lib/markdownit.cjs | 14 +- lib/{markdownlint.d.ts => markdownlint.d.mts} | 195 +- lib/{markdownlint.js => markdownlint.mjs} | 57 +- lib/{md001.js => md001.mjs} | 14 +- lib/{md003.js => md003.mjs} | 14 +- lib/{md004.js => md004.mjs} | 14 +- lib/{md005.js => md005.mjs} | 12 +- lib/{md007.js => md007.mjs} | 21 +- lib/{md009.js => md009.mjs} | 14 +- lib/{md010.js => md010.mjs} | 19 +- lib/{md011.js => md011.mjs} | 16 +- lib/{md012.js => md012.mjs} | 14 +- lib/{md013.js => md013.mjs} | 15 +- lib/{md014.js => md014.mjs} | 12 +- lib/{md018.js => md018.mjs} | 14 +- lib/{md019-md021.js => md019-md021.mjs} | 18 +- lib/{md020.js => md020.mjs} | 14 +- lib/{md022.js => md022.mjs} | 14 +- lib/{md023.js => md023.mjs} | 12 +- lib/{md024.js => md024.mjs} | 14 +- lib/{md025.js => md025.mjs} | 14 +- lib/{md026.js => md026.mjs} | 14 +- lib/{md027.js => md027.mjs} | 12 +- lib/{md028.js => md028.mjs} | 12 +- lib/{md029.js => md029.mjs} | 14 +- lib/{md030.js => md030.mjs} | 12 +- lib/{md031.js => md031.mjs} | 18 +- lib/{md032.js => md032.mjs} | 14 +- lib/{md033.js => md033.mjs} | 14 +- lib/{md034.js => md034.mjs} | 12 +- lib/{md035.js => md035.mjs} | 12 +- lib/{md036.js => md036.mjs} | 14 +- lib/{md037.js => md037.mjs} | 12 +- lib/{md038.js => md038.mjs} | 14 +- lib/{md039.js => md039.mjs} | 14 +- lib/{md040.js => md040.mjs} | 14 +- lib/{md041.js => md041.mjs} | 13 +- lib/{md042.js => md042.mjs} | 14 +- lib/{md043.js => md043.mjs} | 14 +- lib/{md044.js => md044.mjs} | 20 +- lib/{md045.js => md045.mjs} | 14 +- lib/{md046.js => md046.mjs} | 12 +- lib/{md047.js => md047.mjs} | 10 +- lib/{md048.js => md048.mjs} | 14 +- lib/{md049-md050.js => md049-md050.mjs} | 20 +- lib/{md051.js => md051.mjs} | 17 +- lib/{md052.js => md052.mjs} | 12 +- lib/{md053.js => md053.mjs} | 12 +- lib/{md054.js => md054.mjs} | 14 +- lib/{md055.js => md055.mjs} | 12 +- lib/{md056.js => md056.mjs} | 14 +- lib/{md058.js => md058.mjs} | 14 +- lib/rules.js | 74 - lib/rules.mjs | 118 + micromark/.npmignore | 6 - micromark/.npmrc | 2 - micromark/LICENSE | 21 - micromark/README.md | 10 - micromark/api-extractor.json | 40 - micromark/exports-html.mjs | 10 - micromark/exports.mjs | 14 - micromark/micromark.d.cts | 1758 ---- micromark/package.json | 46 - micromark/types.d.ts | 34 - micromark/webpack.config.js | 127 - package.json | 41 +- ...ig-example.js => build-config-example.mjs} | 15 +- ...nfig-schema.js => build-config-schema.mjs} | 27 +- scripts/index.js | 29 - scripts/index.mjs | 24 + test/esm-helpers.mjs | 38 + test/harness.mjs | 4 +- ...config.js => markdownlint-test-config.mjs} | 19 +- ....js => markdownlint-test-custom-rules.mjs} | 170 +- ...e.js => markdownlint-test-extra-parse.mjs} | 8 +- ...pe.js => markdownlint-test-extra-type.mjs} | 10 +- ...t-fixes.js => markdownlint-test-fixes.mjs} | 6 +- ...lpers.js => markdownlint-test-helpers.mjs} | 21 +- test/markdownlint-test-micromark.mjs | 10 +- ...llel.js => markdownlint-test-parallel.mjs} | 20 +- ...> markdownlint-test-repos-dotnet-docs.mjs} | 9 +- ...> markdownlint-test-repos-mdn-content.mjs} | 9 +- ...l.js => markdownlint-test-repos-small.mjs} | 9 +- ...t-repos.js => markdownlint-test-repos.mjs} | 23 +- ...js => markdownlint-test-result-object.mjs} | 12 +- ...ios.js => markdownlint-test-scenarios.mjs} | 21 +- test/markdownlint-test-worker.js | 16 - test/markdownlint-test-worker.mjs | 13 + ...downlint-test.js => markdownlint-test.mjs} | 90 +- test/profile-fixture.mjs | 2 +- .../{any-blockquote.js => any-blockquote.cjs} | 2 +- .../{every-n-lines.js => every-n-lines.cjs} | 2 +- test/rules/{first-line.js => first-line.cjs} | 2 +- .../rules/{letters-E-X.js => letters-E-X.cjs} | 2 +- ...lint-javascript.js => lint-javascript.cjs} | 2 +- test/rules/npm/sample-rule.js | 2 +- test/rules/{rules.js => rules.cjs} | 12 +- .../{validate-json.js => validate-json.cjs} | 2 +- ... => markdownlint-test-custom-rules.mjs.md} | 4 +- ...> markdownlint-test-custom-rules.mjs.snap} | Bin ...arkdownlint-test-repos-dotnet-docs.mjs.md} | 4 +- ...kdownlint-test-repos-dotnet-docs.mjs.snap} | Bin ...arkdownlint-test-repos-mdn-content.mjs.md} | 4 +- ...kdownlint-test-repos-mdn-content.mjs.snap} | Bin ...d => markdownlint-test-repos-small.mjs.md} | 4 +- ...=> markdownlint-test-repos-small.mjs.snap} | Bin ....md => markdownlint-test-scenarios.mjs.md} | 4 +- ...p => markdownlint-test-scenarios.mjs.snap} | Bin 139 files changed, 1066 insertions(+), 10466 deletions(-) create mode 100644 demo/browser-exports.mjs delete mode 100644 demo/markdownlint-browser.js delete mode 100644 demo/markdownlint-exports.js create mode 100644 demo/module-stub.cjs rename demo/{webpack.config.js => webpack.config.mjs} (70%) create mode 100644 example/Gruntfile.cjs delete mode 100644 example/Gruntfile.js create mode 100644 example/gulpfile.cjs delete mode 100644 example/gulpfile.js rename example/{standalone.js => standalone.mjs} (68%) rename helpers/{helpers.js => helpers.cjs} (96%) rename helpers/{micromark-parse.cjs => micromark-parse.mjs} (84%) create mode 100644 helpers/micromark-types.d.mts rename helpers/{shared.js => shared.cjs} (100%) rename lib/{cache.js => cache.mjs} (62%) rename lib/{constants.js => constants.mjs} (60%) rename lib/{markdownlint.d.ts => markdownlint.d.mts} (84%) rename lib/{markdownlint.js => markdownlint.mjs} (97%) rename lib/{md001.js => md001.mjs} (67%) rename lib/{md003.js => md003.mjs} (81%) rename lib/{md004.js => md004.mjs} (87%) rename lib/{md005.js => md005.mjs} (90%) rename lib/{md007.js => md007.mjs} (83%) rename lib/{md009.js => md009.mjs} (91%) rename lib/{md010.js => md010.mjs} (84%) rename lib/{md011.js => md011.mjs} (83%) rename lib/{md012.js => md012.mjs} (77%) rename lib/{md013.js => md013.mjs} (91%) rename lib/{md014.js => md014.mjs} (86%) rename lib/{md018.js => md018.mjs} (78%) rename lib/{md019-md021.js => md019-md021.mjs} (81%) rename lib/{md020.js => md020.mjs} (87%) rename lib/{md022.js => md022.mjs} (88%) rename lib/{md023.js => md023.mjs} (81%) rename lib/{md024.js => md024.mjs} (78%) rename lib/{md025.js => md025.mjs} (74%) rename lib/{md026.js => md026.mjs} (79%) rename lib/{md027.js => md027.mjs} (82%) rename lib/{md028.js => md028.mjs} (84%) rename lib/{md029.js => md029.mjs} (87%) rename lib/{md030.js => md030.mjs} (89%) rename lib/{md031.js => md031.mjs} (80%) rename lib/{md032.js => md032.mjs} (85%) rename lib/{md033.js => md033.mjs} (75%) rename lib/{md034.js => md034.mjs} (90%) rename lib/{md035.js => md035.mjs} (70%) rename lib/{md036.js => md036.mjs} (80%) rename lib/{md037.js => md037.mjs} (92%) rename lib/{md038.js => md038.mjs} (91%) rename lib/{md039.js => md039.mjs} (87%) rename lib/{md040.js => md040.mjs} (78%) rename lib/{md041.js => md041.mjs} (78%) rename lib/{md042.js => md042.mjs} (86%) rename lib/{md043.js => md043.mjs} (85%) rename lib/{md044.js => md044.mjs} (87%) rename lib/{md045.js => md045.mjs} (81%) rename lib/{md046.js => md046.mjs} (75%) rename lib/{md047.js => md047.mjs} (77%) rename lib/{md048.js => md048.mjs} (79%) rename lib/{md049-md050.js => md049-md050.mjs} (84%) rename lib/{md051.js => md051.mjs} (92%) rename lib/{md052.js => md052.mjs} (84%) rename lib/{md053.js => md053.mjs} (88%) rename lib/{md054.js => md054.mjs} (92%) rename lib/{md055.js => md055.mjs} (92%) rename lib/{md056.js => md056.mjs} (81%) rename lib/{md058.js => md058.mjs} (81%) delete mode 100644 lib/rules.js create mode 100644 lib/rules.mjs delete mode 100644 micromark/.npmignore delete mode 100644 micromark/.npmrc delete mode 100644 micromark/LICENSE delete mode 100644 micromark/README.md delete mode 100644 micromark/api-extractor.json delete mode 100644 micromark/exports-html.mjs delete mode 100644 micromark/exports.mjs delete mode 100644 micromark/micromark.d.cts delete mode 100644 micromark/package.json delete mode 100644 micromark/types.d.ts delete mode 100644 micromark/webpack.config.js rename schema/{build-config-example.js => build-config-example.mjs} (79%) rename schema/{build-config-schema.js => build-config-schema.mjs} (95%) delete mode 100644 scripts/index.js create mode 100644 scripts/index.mjs create mode 100644 test/esm-helpers.mjs rename test/{markdownlint-test-config.js => markdownlint-test-config.mjs} (96%) rename test/{markdownlint-test-custom-rules.js => markdownlint-test-custom-rules.mjs} (91%) rename test/{markdownlint-test-extra-parse.js => markdownlint-test-extra-parse.mjs} (61%) rename test/{markdownlint-test-extra-type.js => markdownlint-test-extra-type.mjs} (76%) rename test/{markdownlint-test-fixes.js => markdownlint-test-fixes.mjs} (98%) rename test/{markdownlint-test-helpers.js => markdownlint-test-helpers.mjs} (96%) rename test/{markdownlint-test-parallel.js => markdownlint-test-parallel.mjs} (63%) rename test/{markdownlint-test-repos-dotnet-docs.js => markdownlint-test-repos-dotnet-docs.mjs} (64%) rename test/{markdownlint-test-repos-mdn-content.js => markdownlint-test-repos-mdn-content.mjs} (64%) rename test/{markdownlint-test-repos-small.js => markdownlint-test-repos-small.mjs} (94%) rename test/{markdownlint-test-repos.js => markdownlint-test-repos.mjs} (77%) rename test/{markdownlint-test-result-object.js => markdownlint-test-result-object.mjs} (98%) rename test/{markdownlint-test-scenarios.js => markdownlint-test-scenarios.mjs} (88%) delete mode 100644 test/markdownlint-test-worker.js create mode 100644 test/markdownlint-test-worker.mjs rename test/{markdownlint-test.js => markdownlint-test.mjs} (93%) rename test/rules/{any-blockquote.js => any-blockquote.cjs} (96%) rename test/rules/{every-n-lines.js => every-n-lines.cjs} (88%) rename test/rules/{first-line.js => first-line.cjs} (85%) rename test/rules/{letters-E-X.js => letters-E-X.cjs} (93%) rename test/rules/{lint-javascript.js => lint-javascript.cjs} (94%) rename test/rules/{rules.js => rules.cjs} (57%) rename test/rules/{validate-json.js => validate-json.cjs} (94%) rename test/snapshots/{markdownlint-test-custom-rules.js.md => markdownlint-test-custom-rules.mjs.md} (99%) rename test/snapshots/{markdownlint-test-custom-rules.js.snap => markdownlint-test-custom-rules.mjs.snap} (100%) rename test/snapshots/{markdownlint-test-repos-dotnet-docs.js.md => markdownlint-test-repos-dotnet-docs.mjs.md} (98%) rename test/snapshots/{markdownlint-test-repos-dotnet-docs.js.snap => markdownlint-test-repos-dotnet-docs.mjs.snap} (100%) rename test/snapshots/{markdownlint-test-repos-mdn-content.js.md => markdownlint-test-repos-mdn-content.mjs.md} (92%) rename test/snapshots/{markdownlint-test-repos-mdn-content.js.snap => markdownlint-test-repos-mdn-content.mjs.snap} (100%) rename test/snapshots/{markdownlint-test-repos-small.js.md => markdownlint-test-repos-small.mjs.md} (99%) rename test/snapshots/{markdownlint-test-repos-small.js.snap => markdownlint-test-repos-small.mjs.snap} (100%) rename test/snapshots/{markdownlint-test-scenarios.js.md => markdownlint-test-scenarios.mjs.md} (99%) rename test/snapshots/{markdownlint-test-scenarios.js.snap => markdownlint-test-scenarios.mjs.snap} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71575beba..caf1600be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,11 +30,3 @@ jobs: run: npm install --no-package-lock - name: Run CI Tests run: npm run ci - - name: Install markdownlint-micromark Dependencies - run: npm run install-micromark - - name: Build markdownlint-micromark - run: npm run build-micromark - - name: Install local markdownlint-micromark - run: npm install --no-package-lock ./micromark - - name: Test with local markdownlint-micromark - run: npm test diff --git a/.gitignore b/.gitignore index 7fbbcd55d..7a56a13be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,7 @@ coverage demo/markdown-it.min.js +demo/markdownlint-browser.js demo/markdownlint-browser.min.js -demo/micromark-browser.js -demo/micromark-html-browser.js -micromark/micromark.cjs -micromark/micromark.dev.cjs -micromark/micromark-browser.js -micromark/micromark-browser.dev.js -micromark/micromark-html-browser.js -micromark/micromark-html-browser.dev.js node_modules !test/node_modules npm-debug.log diff --git a/.npmignore b/.npmignore index 0b1a6d4f0..a1867b2ad 100644 --- a/.npmignore +++ b/.npmignore @@ -5,13 +5,11 @@ .vscode coverage demo/* -!demo/markdownlint-browser.js doc-build eslint.config.mjs example -micromark npm-debug.log -schema/*.js +schema/*.mjs scripts test test-repos diff --git a/README.md b/README.md index 1aa0d77c3..b91b9baf6 100644 --- a/README.md +++ b/README.md @@ -798,12 +798,10 @@ function applyFixes(input, errors) { ... } Invoking `applyFixes` with the results of a call to lint can be done like so: ```javascript -const { "sync": markdownlintSync, applyFixes } = require("markdownlint"); +import markdownlint from "../lib/markdownlint.mjs"; -function fixMarkdownlintViolations(content) { - const fixResults = markdownlintSync({ strings: { content } }); - return applyFixes(content, fixResults.content); -} +const fixResults = markdownlint.sync({ "strings": { "content": original } }); +const fixed = markdownlint.applyFixes(original, fixResults.content); ``` ## Usage @@ -811,7 +809,7 @@ function fixMarkdownlintViolations(content) { Invoke `markdownlint` and use the `result` object's `toString` method: ```javascript -const markdownlint = require("markdownlint"); +import markdownlint from "../lib/markdownlint.mjs"; const options = { "files": [ "good.md", "bad.md" ], @@ -897,10 +895,10 @@ Output: ``` Integration with the [gulp](https://gulpjs.com/) build system is -straightforward: [`gulpfile.js`](example/gulpfile.js). +straightforward: [`gulpfile.cjs`](example/gulpfile.cjs). Integration with the [Grunt](https://gruntjs.com/) build system is similar: -[`Gruntfile.js`](example/Gruntfile.js). +[`Gruntfile.cjs`](example/Gruntfile.cjs). ## Browser @@ -912,11 +910,9 @@ Generate normal and minified scripts with: npm run build-demo ``` -Then reference `markdownlint` and `micromark` scripts: +Then reference the `markdownlint` script: ```html - - ``` @@ -928,7 +924,7 @@ const options = { "content": "Some Markdown to lint." } }; -const results = window.markdownlint.sync(options).toString(); +const results = window.markdownlint.markdownlint.sync(options).toString(); ``` ## Examples diff --git a/demo/browser-exports.mjs b/demo/browser-exports.mjs new file mode 100644 index 000000000..b1e8acf2d --- /dev/null +++ b/demo/browser-exports.mjs @@ -0,0 +1,9 @@ +// @ts-check + +export { default as markdownlint } from "../lib/markdownlint.mjs"; +export { compile, parse, postprocess, preprocess } from "micromark"; +export { directive, directiveHtml } from "micromark-extension-directive"; +export { gfmAutolinkLiteral, gfmAutolinkLiteralHtml } from "micromark-extension-gfm-autolink-literal"; +export { gfmFootnote, gfmFootnoteHtml } from "micromark-extension-gfm-footnote"; +export { gfmTable, gfmTableHtml } from "micromark-extension-gfm-table"; +export { math, mathHtml } from "micromark-extension-math"; diff --git a/demo/default.htm b/demo/default.htm index 32a8f2045..4c1bc442b 100644 --- a/demo/default.htm +++ b/demo/default.htm @@ -34,8 +34,6 @@ - - diff --git a/demo/default.js b/demo/default.js index 73eeaa653..27fffc510 100644 --- a/demo/default.js +++ b/demo/default.js @@ -3,9 +3,8 @@ (function main() { // Dependencies var markdownit = globalThis.markdownit; - var markdownlint = globalThis.markdownlint.library; - var micromark = globalThis.micromarkBrowser; - var micromarkHtml = globalThis.micromarkHtmlBrowser; + var markdownlint = globalThis.markdownlint.markdownlint; + var micromark = globalThis.markdownlint; // DOM elements var markdown = document.getElementById("markdown"); @@ -70,15 +69,15 @@ const compileOptions = { "allowDangerousHtml": true, "htmlExtensions": [ - micromarkHtml.directiveHtml({ "*": handleDirective }), - micromarkHtml.gfmAutolinkLiteralHtml(), - micromarkHtml.gfmFootnoteHtml(), - micromarkHtml.gfmTableHtml(), - micromarkHtml.mathHtml() + micromark.directiveHtml({ "*": handleDirective }), + micromark.gfmAutolinkLiteralHtml(), + micromark.gfmFootnoteHtml(), + micromark.gfmTableHtml(), + micromark.mathHtml() ] }; try { - return micromarkHtml.compile(compileOptions)(events); + return micromark.compile(compileOptions)(events); } catch (error) { return `[Exception: "${error}"]`; } diff --git a/demo/markdownlint-browser.js b/demo/markdownlint-browser.js deleted file mode 100644 index 5a3ee76a7..000000000 --- a/demo/markdownlint-browser.js +++ /dev/null @@ -1,7144 +0,0 @@ -/*! markdownlint 0.36.1 https://github.com/DavidAnson/markdownlint @license MIT */ -var markdownlint; -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ "../helpers/helpers.js": -/*!*****************************!*\ - !*** ../helpers/helpers.js ***! - \*****************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const micromark = __webpack_require__(/*! ./micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); - -const { newLineRe, nextLinesRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js"); - -module.exports.newLineRe = newLineRe; -module.exports.nextLinesRe = nextLinesRe; - -/** @typedef {import("../lib/markdownlint.js").RuleOnError} RuleOnError */ -/** @typedef {import("../lib/markdownlint.js").RuleOnErrorFixInfo} RuleOnErrorFixInfo */ - -// Regular expression for matching common front matter (YAML and TOML) -module.exports.frontMatterRe = - /((^---[^\S\r\n\u2028\u2029]*$[\s\S]+?^---\s*)|(^\+\+\+[^\S\r\n\u2028\u2029]*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{[^\S\r\n\u2028\u2029]*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m; - -// Regular expression for matching the start of inline disable/enable comments -const inlineCommentStartRe = - /()/gi; -module.exports.inlineCommentStartRe = inlineCommentStartRe; - -// Regular expression for identifying an HTML entity at the end of a line -module.exports.endOfLineHtmlEntityRe = - /&(?:#\d+|#[xX][\da-fA-F]+|[a-zA-Z]{2,31}|blk\d{2}|emsp1[34]|frac\d{2}|sup\d|there4);$/; - -// Regular expression for identifying a GitHub emoji code at the end of a line -module.exports.endOfLineGemojiCodeRe = - /:(?:[abmovx]|[-+]1|100|1234|(?:1st|2nd|3rd)_place_medal|8ball|clock\d{1,4}|e-mail|non-potable_water|o2|t-rex|u5272|u5408|u55b6|u6307|u6708|u6709|u6e80|u7121|u7533|u7981|u7a7a|[a-z]{2,15}2?|[a-z]{1,14}(?:_[a-z\d]{1,16})+):$/; - -// All punctuation characters (normal and full-width) -const allPunctuation = ".,;:!?。,;:!?"; -module.exports.allPunctuation = allPunctuation; - -// All punctuation characters without question mark (normal and full-width) -module.exports.allPunctuationNoQuestion = allPunctuation.replace(/[??]/gu, ""); - -/** - * Returns true iff the input is a Number. - * - * @param {Object} obj Object of unknown type. - * @returns {boolean} True iff obj is a Number. - */ -function isNumber(obj) { - return typeof obj === "number"; -} -module.exports.isNumber = isNumber; - -/** - * Returns true iff the input is a String. - * - * @param {Object} obj Object of unknown type. - * @returns {boolean} True iff obj is a String. - */ -function isString(obj) { - return typeof obj === "string"; -} -module.exports.isString = isString; - -/** - * Returns true iff the input String is empty. - * - * @param {string} str String of unknown length. - * @returns {boolean} True iff the input String is empty. - */ -function isEmptyString(str) { - return str.length === 0; -} -module.exports.isEmptyString = isEmptyString; - -/** - * Returns true iff the input is an Object. - * - * @param {Object} obj Object of unknown type. - * @returns {boolean} True iff obj is an Object. - */ -function isObject(obj) { - return !!obj && (typeof obj === "object") && !Array.isArray(obj); -} -module.exports.isObject = isObject; - -/** - * Returns true iff the input is a URL. - * - * @param {Object} obj Object of unknown type. - * @returns {boolean} True iff obj is a URL. - */ -function isUrl(obj) { - return !!obj && (Object.getPrototypeOf(obj) === URL.prototype); -} -module.exports.isUrl = isUrl; - -/** - * Clones the input if it is an Array. - * - * @param {Object} arr Object of unknown type. - * @returns {Object} Clone of obj iff obj is an Array. - */ -function cloneIfArray(arr) { - return Array.isArray(arr) ? [ ...arr ] : arr; -} -module.exports.cloneIfArray = cloneIfArray; - -/** - * Clones the input if it is a URL. - * - * @param {Object} url Object of unknown type. - * @returns {Object} Clone of obj iff obj is a URL. - */ -function cloneIfUrl(url) { - return isUrl(url) ? new URL(url) : url; -} -module.exports.cloneIfUrl = cloneIfUrl; - -/** - * Gets a Regular Expression for matching the specified HTML attribute. - * - * @param {string} name HTML attribute name. - * @returns {RegExp} Regular Expression for matching. - */ -module.exports.getHtmlAttributeRe = function getHtmlAttributeRe(name) { - return new RegExp(`\\s${name}\\s*=\\s*['"]?([^'"\\s>]*)`, "iu"); -}; - -/** - * Returns true iff the input line is blank (contains nothing, whitespace, or - * comments (unclosed start/end comments allowed)). - * - * @param {string} line Input line. - * @returns {boolean} True iff line is blank. - */ -function isBlankLine(line) { - const startComment = ""; - const removeComments = (s) => { - while (true) { - const start = s.indexOf(startComment); - const end = s.indexOf(endComment); - if ((end !== -1) && ((start === -1) || (end < start))) { - // Unmatched end comment is first - s = s.slice(end + endComment.length); - } else if ((start !== -1) && (end !== -1)) { - // Start comment is before end comment - s = s.slice(0, start) + s.slice(end + endComment.length); - } else if ((start !== -1) && (end === -1)) { - // Unmatched start comment is last - s = s.slice(0, start); - } else { - // No more comments to remove - return s; - } - } - }; - return ( - !line || - !line.trim() || - !removeComments(line).replace(/>/g, "").trim() - ); -} -module.exports.isBlankLine = isBlankLine; - -// Replaces the content of properly-formatted CommonMark comments with "." -// This preserves the line/column information for the rest of the document -// https://spec.commonmark.org/0.29/#html-blocks -// https://spec.commonmark.org/0.29/#html-comment -const htmlCommentBegin = ""; -const safeCommentCharacter = "."; -const startsWithPipeRe = /^ *\|/; -const notCrLfRe = /[^\r\n]/g; -const notSpaceCrLfRe = /[^ \r\n]/g; -const trailingSpaceRe = / +[\r\n]/g; -const replaceTrailingSpace = (s) => s.replace(notCrLfRe, safeCommentCharacter); -module.exports.clearHtmlCommentText = function clearHtmlCommentText(text) { - let i = 0; - while ((i = text.indexOf(htmlCommentBegin, i)) !== -1) { - const j = text.indexOf(htmlCommentEnd, i + 2); - if (j === -1) { - // Un-terminated comments are treated as text - break; - } - // If the comment has content... - if (j > i + htmlCommentBegin.length) { - const content = text.slice(i + htmlCommentBegin.length, j); - const lastLf = text.lastIndexOf("\n", i) + 1; - const preText = text.slice(lastLf, i); - const isBlock = preText.trim().length === 0; - const couldBeTable = startsWithPipeRe.test(preText); - const spansTableCells = couldBeTable && content.includes("\n"); - const isValid = - isBlock || - !( - spansTableCells || - content.startsWith(">") || - content.startsWith("->") || - content.endsWith("-") || - content.includes("--") - ); - // If a valid block/inline comment... - if (isValid) { - const clearedContent = content - .replace(notSpaceCrLfRe, safeCommentCharacter) - .replace(trailingSpaceRe, replaceTrailingSpace); - text = - text.slice(0, i + htmlCommentBegin.length) + - clearedContent + - text.slice(j); - } - } - i = j + htmlCommentEnd.length; - } - return text; -}; - -// Escapes a string for use in a RegExp -module.exports.escapeForRegExp = function escapeForRegExp(str) { - return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); -}; - -/** - * Adds ellipsis to the left/right/middle of the specified text. - * - * @param {string} text Text to ellipsify. - * @param {boolean} [start] True iff the start of the text is important. - * @param {boolean} [end] True iff the end of the text is important. - * @returns {string} Ellipsified text. - */ -function ellipsify(text, start, end) { - if (text.length <= 30) { - // Nothing to do - } else if (start && end) { - text = text.slice(0, 15) + "..." + text.slice(-15); - } else if (end) { - text = "..." + text.slice(-30); - } else { - text = text.slice(0, 30) + "..."; - } - return text; -} -module.exports.ellipsify = ellipsify; - -/** - * Adds a generic error object via the onError callback. - * - * @param {RuleOnError} 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 {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance. - * @returns {void} - */ -function addError(onError, lineNumber, detail, context, range, fixInfo) { - onError({ - lineNumber, - detail, - context, - range, - fixInfo - }); -} -module.exports.addError = addError; - -/** - * Adds an error object with details conditionally via the onError callback. - * - * @param {RuleOnError} onError RuleOnError instance. - * @param {number} lineNumber Line number. - * @param {Object} expected Expected value. - * @param {Object} actual Actual value. - * @param {string} [detail] Error details. - * @param {string} [context] Error context. - * @param {number[]} [range] Column and length of error. - * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance. - * @returns {void} - */ -function addErrorDetailIf( - onError, lineNumber, expected, actual, detail, context, range, fixInfo) { - if (expected !== actual) { - addError( - onError, - lineNumber, - "Expected: " + expected + "; Actual: " + actual + - (detail ? "; " + detail : ""), - context, - range, - fixInfo); - } -} -module.exports.addErrorDetailIf = addErrorDetailIf; - -/** - * Adds an error object with context via the onError callback. - * - * @param {RuleOnError} onError RuleOnError instance. - * @param {number} lineNumber Line number. - * @param {string} context Error context. - * @param {boolean} [start] True iff the start of the text is important. - * @param {boolean} [end] True iff the end of the text is important. - * @param {number[]} [range] Column and length of error. - * @param {RuleOnErrorFixInfo} [fixInfo] RuleOnErrorFixInfo instance. - * @returns {void} - */ -function addErrorContext( - onError, lineNumber, context, start, end, range, fixInfo) { - context = ellipsify(context, start, end); - addError(onError, lineNumber, undefined, context, range, fixInfo); -} -module.exports.addErrorContext = addErrorContext; - -/** - * Defines a range within a file (start line/column to end line/column, subset of MicromarkToken). - * - * @typedef {Object} FileRange - * @property {number} startLine Start line (1-based). - * @property {number} startColumn Start column (1-based). - * @property {number} endLine End line (1-based). - * @property {number} endColumn End column (1-based). - */ - -/** - * Returns whether line/column A is less than or equal to line/column B. - * - * @param {number} lineA Line A. - * @param {number} columnA Column A. - * @param {number} lineB Line B. - * @param {number} columnB Column B. - * @returns {boolean} True iff A is less than or equal to B. - */ -const positionLessThanOrEqual = (lineA, columnA, lineB, columnB) => ( - (lineA < lineB) || - ((lineA === lineB) && (columnA <= columnB)) -); - -/** - * Returns whether two ranges (or MicromarkTokens) overlap anywhere. - * - * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeA Range A. - * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeB Range B. - * @returns {boolean} True iff the two ranges overlap. - */ -module.exports.hasOverlap = function hasOverlap(rangeA, rangeB) { - const lte = positionLessThanOrEqual(rangeA.startLine, rangeA.startColumn, rangeB.startLine, rangeB.startColumn); - const first = lte ? rangeA : rangeB; - const second = lte ? rangeB : rangeA; - return positionLessThanOrEqual(second.startLine, second.startColumn, first.endLine, first.endColumn); -}; - -// Determines if the front matter includes a title -module.exports.frontMatterHasTitle = - function frontMatterHasTitle(frontMatterLines, frontMatterTitlePattern) { - const ignoreFrontMatter = - (frontMatterTitlePattern !== undefined) && !frontMatterTitlePattern; - const frontMatterTitleRe = - new RegExp( - String(frontMatterTitlePattern || "^\\s*\"?title\"?\\s*[:=]"), - "i" - ); - return !ignoreFrontMatter && - frontMatterLines.some((line) => frontMatterTitleRe.test(line)); - }; - -/** - * Returns an object with information about reference links and images. - * - * @param {import("../helpers/micromark-helpers.cjs").Token[]} tokens Micromark tokens. - * @returns {Object} Reference link/image data. - */ -function getReferenceLinkImageData(tokens) { - const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " "); - const references = new Map(); - const shortcuts = new Map(); - const addReferenceToDictionary = (token, label, isShortcut) => { - const referenceDatum = [ - token.startLine - 1, - token.startColumn - 1, - token.text.length - ]; - const reference = normalizeReference(label); - const dictionary = isShortcut ? shortcuts : references; - const referenceData = dictionary.get(reference) || []; - referenceData.push(referenceDatum); - dictionary.set(reference, referenceData); - }; - const definitions = new Map(); - const definitionLineIndices = []; - const duplicateDefinitions = []; - const filteredTokens = - micromark.filterByTypes( - tokens, - [ - // definitionLineIndices - "definition", "gfmFootnoteDefinition", - // definitions and definitionLineIndices - "definitionLabelString", "gfmFootnoteDefinitionLabelString", - // references and shortcuts - "gfmFootnoteCall", "image", "link", - // undefined link labels - "undefinedReferenceCollapsed", "undefinedReferenceFull", "undefinedReferenceShortcut" - ] - ); - for (const token of filteredTokens) { - let labelPrefix = ""; - // eslint-disable-next-line default-case - switch (token.type) { - case "definition": - case "gfmFootnoteDefinition": - // definitionLineIndices - for (let i = token.startLine; i <= token.endLine; i++) { - definitionLineIndices.push(i - 1); - } - break; - case "gfmFootnoteDefinitionLabelString": - labelPrefix = "^"; - case "definitionLabelString": // eslint-disable-line no-fallthrough - { - // definitions and definitionLineIndices - const reference = normalizeReference(`${labelPrefix}${token.text}`); - if (definitions.has(reference)) { - duplicateDefinitions.push([ reference, token.startLine - 1 ]); - } else { - const parent = - micromark.getParentOfType(token, [ "definition" ]); - const destinationString = parent && - micromark.getDescendantsByType(parent, [ "definitionDestination", "definitionDestinationRaw", "definitionDestinationString" ])[0]?.text; - definitions.set( - reference, - [ token.startLine - 1, destinationString ] - ); - } - } - break; - case "gfmFootnoteCall": - case "image": - case "link": - { - // Identify if shortcut or full/collapsed - let isShortcut = (token.children.length === 1); - const isFullOrCollapsed = (token.children.length === 2) && !token.children.some((t) => t.type === "resource"); - const [ labelText ] = micromark.getDescendantsByType(token, [ "label", "labelText" ]); - const [ referenceString ] = micromark.getDescendantsByType(token, [ "reference", "referenceString" ]); - let label = labelText?.text; - // Identify if footnote - if (!isShortcut && !isFullOrCollapsed) { - const [ footnoteCallMarker, footnoteCallString ] = token.children.filter( - (t) => [ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ].includes(t.type) - ); - if (footnoteCallMarker && footnoteCallString) { - label = `${footnoteCallMarker.text}${footnoteCallString.text}`; - isShortcut = true; - } - } - // Track link (handle shortcuts separately due to ambiguity in "text [text] text") - if (isShortcut || isFullOrCollapsed) { - addReferenceToDictionary(token, referenceString?.text || label, isShortcut); - } - } - break; - case "undefinedReferenceCollapsed": - case "undefinedReferenceFull": - case "undefinedReferenceShortcut": - { - const undefinedReference = micromark.getDescendantsByType(token, [ "undefinedReference" ])[0]; - const label = undefinedReference.children.map((t) => t.text).join(""); - const isShortcut = (token.type === "undefinedReferenceShortcut"); - addReferenceToDictionary(token, label, isShortcut); - } - break; - } - } - return { - references, - shortcuts, - definitions, - duplicateDefinitions, - definitionLineIndices - }; -} -module.exports.getReferenceLinkImageData = getReferenceLinkImageData; - -/** - * Gets the most common line ending, falling back to the platform default. - * - * @param {string} input Markdown content to analyze. - * @param {Object} [os] Node.js "os" module. - * @returns {string} Preferred line ending. - */ -function getPreferredLineEnding(input, os) { - let cr = 0; - let lf = 0; - let crlf = 0; - const endings = input.match(newLineRe) || []; - for (const ending of endings) { - // eslint-disable-next-line default-case - switch (ending) { - case "\r": - cr++; - break; - case "\n": - lf++; - break; - case "\r\n": - crlf++; - break; - } - } - let preferredLineEnding = null; - if (!cr && !lf && !crlf) { - preferredLineEnding = (os && os.EOL) || "\n"; - } else if ((lf >= crlf) && (lf >= cr)) { - preferredLineEnding = "\n"; - } else if (crlf >= cr) { - preferredLineEnding = "\r\n"; - } else { - preferredLineEnding = "\r"; - } - return preferredLineEnding; -} -module.exports.getPreferredLineEnding = getPreferredLineEnding; - -/** - * Expands a path with a tilde to an absolute path. - * - * @param {string} file Path that may begin with a tilde. - * @param {Object} os Node.js "os" module. - * @returns {string} Absolute path (or original path). - */ -function expandTildePath(file, os) { - const homedir = os && os.homedir && os.homedir(); - return homedir ? file.replace(/^~($|\/|\\)/, `${homedir}$1`) : file; -} -module.exports.expandTildePath = expandTildePath; - - -/***/ }), - -/***/ "../helpers/shared.js": -/*!****************************!*\ - !*** ../helpers/shared.js ***! - \****************************/ -/***/ ((module) => { - -"use strict"; -// @ts-check - - - -// Symbol for identifing the flat tokens array from micromark parse -module.exports.flatTokensSymbol = Symbol("flat-tokens"); - -// Symbol for identifying the htmlFlow token from micromark parse -module.exports.htmlFlowSymbol = Symbol("html-flow"); - -// Regular expression for matching common newline characters -// See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js -module.exports.newLineRe = /\r\n?|\n/g; - -// Regular expression for matching next lines -module.exports.nextLinesRe = /[\r\n][\s\S]*$/; - - -/***/ }), - -/***/ "../lib sync recursive": -/*!********************!*\ - !*** ../lib/ sync ***! - \********************/ -/***/ ((module) => { - -function webpackEmptyContext(req) { - var e = new Error("Cannot find module '" + req + "'"); - e.code = 'MODULE_NOT_FOUND'; - throw e; -} -webpackEmptyContext.keys = () => ([]); -webpackEmptyContext.resolve = webpackEmptyContext; -webpackEmptyContext.id = "../lib sync recursive"; -module.exports = webpackEmptyContext; - -/***/ }), - -/***/ "markdown-it": -/*!*****************************!*\ - !*** external "markdownit" ***! - \*****************************/ -/***/ ((module) => { - -"use strict"; -module.exports = markdownit; - -/***/ }), - -/***/ "markdownlint-micromark": -/*!***********************************!*\ - !*** external "micromarkBrowser" ***! - \***********************************/ -/***/ ((module) => { - -"use strict"; -module.exports = micromarkBrowser; - -/***/ }), - -/***/ "?d0ee": -/*!*************************!*\ - !*** node:fs (ignored) ***! - \*************************/ -/***/ (() => { - -/* (ignored) */ - -/***/ }), - -/***/ "?e6c4": -/*!*************************!*\ - !*** node:os (ignored) ***! - \*************************/ -/***/ (() => { - -/* (ignored) */ - -/***/ }), - -/***/ "?9a52": -/*!***************************!*\ - !*** node:path (ignored) ***! - \***************************/ -/***/ (() => { - -/* (ignored) */ - -/***/ }), - -/***/ "?39e5": -/*!***************************!*\ - !*** node:util (ignored) ***! - \***************************/ -/***/ (() => { - -/* (ignored) */ - -/***/ }), - -/***/ "./markdownlint-exports.js": -/*!*********************************!*\ - !*** ./markdownlint-exports.js ***! - \*********************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -module.exports = { - "library": __webpack_require__(/*! .. */ "../lib/markdownlint.js"), - "helpers": __webpack_require__(/*! ../helpers */ "../helpers/helpers.js") -}; - - -/***/ }), - -/***/ "../helpers/micromark-helpers.cjs": -/*!****************************************!*\ - !*** ../helpers/micromark-helpers.cjs ***! - \****************************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { flatTokensSymbol, htmlFlowSymbol } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js"); - -/** @typedef {import("markdownlint-micromark").TokenType} TokenType */ -/** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */ - -/** - * Determines if a Micromark token is within an htmlFlow type. - * - * @param {Token} token Micromark token. - * @returns {boolean} True iff the token is within an htmlFlow type. - */ -function inHtmlFlow(token) { - return Boolean(token[htmlFlowSymbol]); -} - -/** - * Returns whether a token is an htmlFlow type containing an HTML comment. - * - * @param {Token} token Micromark token. - * @returns {boolean} True iff token is htmlFlow containing a comment. - */ -function isHtmlFlowComment(token) { - const { text, type } = token; - if ( - (type === "htmlFlow") && - text.startsWith("") - ) { - const comment = text.slice(4, -3); - return ( - !comment.startsWith(">") && - !comment.startsWith("->") && - !comment.endsWith("-") - // The following condition from the CommonMark specification is commented - // to avoid parsing HTML comments that include "--" because that is NOT a - // condition of the HTML specification. - // https://spec.commonmark.org/0.30/#raw-html - // https://html.spec.whatwg.org/multipage/syntax.html#comments - // && !comment.includes("--") - ); - } - return false; -} - -/** - * Adds a range of numbers to a set. - * - * @param {Set} set Set of numbers. - * @param {number} start Starting number. - * @param {number} end Ending number. - * @returns {void} - */ -function addRangeToSet(set, start, end) { - for (let i = start; i <= end; i++) { - set.add(i); - } -} - -/** - * @callback AllowedPredicate - * @param {Token} token Micromark token. - * @returns {boolean} True iff allowed. - */ - -/** - * @callback TransformPredicate - * @param {Token} token Micromark token. - * @returns {Token[]} Child tokens. - */ - -/** - * Filter a list of Micromark tokens by predicate. - * - * @param {Token[]} tokens Micromark tokens. - * @param {AllowedPredicate} [allowed] Allowed token predicate. - * @param {TransformPredicate} [transformChildren] Transform predicate. - * @returns {Token[]} Filtered tokens. - */ -function filterByPredicate(tokens, allowed, transformChildren) { - allowed = allowed || (() => true); - const result = []; - const queue = [ - { - "array": tokens, - "index": 0 - } - ]; - while (queue.length > 0) { - const current = queue[queue.length - 1]; - const { array, index } = current; - if (index < array.length) { - const token = array[current.index++]; - if (allowed(token)) { - result.push(token); - } - const { children } = token; - if (children.length > 0) { - const transformed = - transformChildren ? transformChildren(token) : children; - queue.push( - { - "array": transformed, - "index": 0 - } - ); - } - } else { - queue.pop(); - } - } - return result; -} - -/** - * Filter a list of Micromark tokens by type. - * - * @param {Token[]} tokens Micromark tokens. - * @param {TokenType[]} types Types to allow. - * @param {boolean} [htmlFlow] Whether to include htmlFlow content. - * @returns {Token[]} Filtered tokens. - */ -function filterByTypes(tokens, types, htmlFlow) { - const predicate = (token) => types.includes(token.type) && (htmlFlow || !inHtmlFlow(token)); - const flatTokens = tokens[flatTokensSymbol]; - if (flatTokens) { - return flatTokens.filter(predicate); - } - return filterByPredicate(tokens, predicate); -} - -/** - * Gets the blockquote prefix text (if any) for the specified line number. - * - * @param {Token[]} tokens Micromark tokens. - * @param {number} lineNumber Line number to examine. - * @param {number} [count] Number of times to repeat. - * @returns {string} Blockquote prefix text. - */ -function getBlockQuotePrefixText(tokens, lineNumber, count = 1) { - return filterByTypes(tokens, [ "blockQuotePrefix", "linePrefix" ]) - .filter((prefix) => prefix.startLine === lineNumber) - .map((prefix) => prefix.text) - .join("") - .trimEnd() - // eslint-disable-next-line unicorn/prefer-spread - .concat("\n") - .repeat(count); -}; - -/** - * Gets a list of nested Micromark token descendants by type path. - * - * @param {Token|Token[]} parent Micromark token parent or parents. - * @param {(TokenType|TokenType[])[]} typePath Micromark token type path. - * @returns {Token[]} Micromark token descendants. - */ -function getDescendantsByType(parent, typePath) { - let tokens = Array.isArray(parent) ? parent : [ parent ]; - for (const type of typePath) { - const predicate = (token) => Array.isArray(type) ? type.includes(token.type) : (type === token.type); - tokens = tokens.flatMap((t) => t.children.filter(predicate)); - } - return tokens; -} - -/** - * Gets the heading level of a Micromark heading tokan. - * - * @param {Token} heading Micromark heading token. - * @returns {number} Heading level. - */ -function getHeadingLevel(heading) { - let level = 1; - const headingSequence = heading.children.find( - (child) => [ "atxHeadingSequence", "setextHeadingLine" ].includes(child.type) - ); - // @ts-ignore - const { text } = headingSequence; - if (text[0] === "#") { - level = Math.min(text.length, 6); - } else if (text[0] === "-") { - level = 2; - } - return level; -} - -/** - * Gets the heading style of a Micromark heading tokan. - * - * @param {Token} heading Micromark heading token. - * @returns {"atx" | "atx_closed" | "setext"} Heading style. - */ -function getHeadingStyle(heading) { - if (heading.type === "setextHeading") { - return "setext"; - } - const atxHeadingSequenceLength = heading.children.filter( - (child) => child.type === "atxHeadingSequence" - ).length; - if (atxHeadingSequenceLength === 1) { - return "atx"; - } - return "atx_closed"; -} - -/** - * Gets the heading text of a Micromark heading token. - * - * @param {Token} heading Micromark heading token. - * @returns {string} Heading text. - */ -function getHeadingText(heading) { - const headingTexts = getDescendantsByType(heading, [ [ "atxHeadingText", "setextHeadingText" ] ]); - return headingTexts[0]?.text.replace(/[\r\n]+/g, " ") || ""; -} - -/** - * HTML tag information. - * - * @typedef {Object} HtmlTagInfo - * @property {boolean} close True iff close tag. - * @property {string} name Tag name. - */ - -/** - * Gets information about the tag in an HTML token. - * - * @param {Token} token Micromark token. - * @returns {HtmlTagInfo | null} HTML tag information. - */ -function getHtmlTagInfo(token) { - const htmlTagNameRe = /^<([^!>][^/\s>]*)/; - if (token.type === "htmlText") { - const match = htmlTagNameRe.exec(token.text); - if (match) { - const name = match[1]; - const close = name.startsWith("/"); - return { - close, - "name": close ? name.slice(1) : name - }; - } - } - return null; -} - -/** - * Gets the nearest parent of the specified type for a Micromark token. - * - * @param {Token} token Micromark token. - * @param {TokenType[]} types Types to allow. - * @returns {Token | null} Parent token. - */ -function getParentOfType(token, types) { - /** @type {Token | null} */ - let current = token; - while ((current = current.parent) && !types.includes(current.type)) { - // Empty - } - return current; -} - -/** - * Set containing token types that do not contain content. - * - * @type {Set} - */ -const nonContentTokens = new Set([ - "blockQuoteMarker", - "blockQuotePrefix", - "blockQuotePrefixWhitespace", - "lineEnding", - "lineEndingBlank", - "linePrefix", - "listItemIndent" -]); - -module.exports = { - addRangeToSet, - filterByPredicate, - filterByTypes, - getBlockQuotePrefixText, - getDescendantsByType, - getHeadingLevel, - getHeadingStyle, - getHeadingText, - getHtmlTagInfo, - getParentOfType, - inHtmlFlow, - isHtmlFlowComment, - nonContentTokens -}; - - -/***/ }), - -/***/ "../helpers/micromark-parse.cjs": -/*!**************************************!*\ - !*** ../helpers/micromark-parse.cjs ***! - \**************************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const micromark = __webpack_require__(/*! markdownlint-micromark */ "markdownlint-micromark"); -const { isHtmlFlowComment } = __webpack_require__(/*! ./micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { flatTokensSymbol, htmlFlowSymbol, newLineRe } = __webpack_require__(/*! ./shared.js */ "../helpers/shared.js"); - -/** @typedef {import("markdownlint-micromark").Construct} Construct */ -/** @typedef {import("markdownlint-micromark").Event} Event */ -/** @typedef {import("markdownlint-micromark").ParseOptions} MicromarkParseOptions */ -/** @typedef {import("markdownlint-micromark").State} State */ -/** @typedef {import("markdownlint-micromark").Token} Token */ -/** @typedef {import("markdownlint-micromark").Tokenizer} Tokenizer */ -/** @typedef {import("../lib/markdownlint.js").MicromarkToken} MicromarkToken */ - -/** - * Parse options. - * - * @typedef {Object} ParseOptions - * @property {boolean} [freezeTokens] Whether to freeze output Tokens. - */ - -/** - * Parses a Markdown document and returns Micromark events. - * - * @param {string} markdown Markdown document. - * @param {MicromarkParseOptions} [micromarkParseOptions] Options for micromark. - * @returns {Event[]} Micromark events. - */ -function getEvents( - markdown, - micromarkParseOptions = {} -) { - // Customize extensions list to add useful extensions - const extensions = [ - micromark.directive(), - micromark.gfmAutolinkLiteral(), - micromark.gfmFootnote(), - micromark.gfmTable(), - micromark.math(), - ...(micromarkParseOptions.extensions || []) - ]; - - // // Shim labelEnd to identify undefined link labels - /** @type {Event[][]} */ - const artificialEventLists = []; - /** @type {Construct} */ - const labelEnd = - // @ts-ignore - micromark.labelEnd; - const tokenizeOriginal = labelEnd.tokenize; - - /** @type {Tokenizer} */ - function tokenizeShim(effects, okOriginal, nokOriginal) { - // eslint-disable-next-line consistent-this, unicorn/no-this-assignment, no-invalid-this - const tokenizeContext = this; - const events = tokenizeContext.events; - - /** @type {State} */ - const nokShim = (code) => { - // Find start of label (image or link) - let indexStart = events.length; - while (--indexStart >= 0) { - const event = events[indexStart]; - const [ kind, token ] = event; - if (kind === "enter") { - const { type } = token; - if ((type === "labelImage") || (type === "labelLink")) { - // Found it - break; - } - } - } - - // If found... - if (indexStart >= 0) { - // Create artificial enter/exit events and replicate all data/lineEnding events within - const eventStart = events[indexStart]; - const [ , eventStartToken ] = eventStart; - const eventEnd = events[events.length - 1]; - const [ , eventEndToken ] = eventEnd; - /** @type {Token} */ - const undefinedReferenceType = { - "type": "undefinedReferenceShortcut", - "start": eventStartToken.start, - "end": eventEndToken.end - }; - /** @type {Token} */ - const undefinedReference = { - "type": "undefinedReference", - "start": eventStartToken.start, - "end": eventEndToken.end - }; - const eventsToReplicate = events - .slice(indexStart) - .filter((event) => { - const [ , eventToken ] = event; - const { type } = eventToken; - return (type === "data") || (type === "lineEnding"); - }); - - // Determine the type of the undefined reference - const previousUndefinedEvent = (artificialEventLists.length > 0) && artificialEventLists[artificialEventLists.length - 1][0]; - const previousUndefinedToken = previousUndefinedEvent && previousUndefinedEvent[1]; - if ( - previousUndefinedToken && - (previousUndefinedToken.end.line === undefinedReferenceType.start.line) && - (previousUndefinedToken.end.column === undefinedReferenceType.start.column) - ) { - // Previous undefined reference event is immediately before this one - if (eventsToReplicate.length === 0) { - // The pair represent a collapsed reference (ex: [...][]) - previousUndefinedToken.type = "undefinedReferenceCollapsed"; - previousUndefinedToken.end = eventEndToken.end; - } else { - // The pair represent a full reference (ex: [...][...]) - undefinedReferenceType.type = "undefinedReferenceFull"; - undefinedReferenceType.start = previousUndefinedToken.start; - artificialEventLists.pop(); - } - } - - // Create artificial event list and replicate content - const text = eventsToReplicate - .filter((event) => event[0] === "enter") - .map((event) => tokenizeContext.sliceSerialize(event[1])) - .join("") - .trim(); - if ((text.length > 0) && !text.includes("]")) { - /** @type {Event[]} */ - const artificialEvents = []; - artificialEvents.push( - [ "enter", undefinedReferenceType, tokenizeContext ], - [ "enter", undefinedReference, tokenizeContext ] - ); - for (const event of eventsToReplicate) { - const [ kind, token ] = event; - // Copy token because the current object will get modified by the parser - artificialEvents.push([ kind, { ...token }, tokenizeContext ]); - } - artificialEvents.push( - [ "exit", undefinedReference, tokenizeContext ], - [ "exit", undefinedReferenceType, tokenizeContext ] - ); - artificialEventLists.push(artificialEvents); - } - } - - // Continue with original behavior - return nokOriginal(code); - }; - - // Shim nok handler of labelEnd's tokenize - return tokenizeOriginal.call(tokenizeContext, effects, okOriginal, nokShim); - } - - try { - // Shim labelEnd behavior to detect undefined references - labelEnd.tokenize = tokenizeShim; - - // Use micromark to parse document into Events - const encoding = undefined; - const eol = true; - const parseContext = micromark.parse({ ...micromarkParseOptions, extensions }); - const chunks = micromark.preprocess()(markdown, encoding, eol); - const events = micromark.postprocess(parseContext.document().write(chunks)); - - // Append artificial events and return all events - // eslint-disable-next-line unicorn/prefer-spread - return events.concat(...artificialEventLists); - } finally { - // Restore shimmed labelEnd behavior - labelEnd.tokenize = tokenizeOriginal; - } -} - -/** - * Parses a Markdown document and returns micromark tokens (internal). - * - * @param {string} markdown Markdown document. - * @param {ParseOptions} [parseOptions] Options. - * @param {MicromarkParseOptions} [micromarkParseOptions] Options for micromark. - * @param {number} [lineDelta] Offset for start/end line. - * @param {MicromarkToken} [ancestor] Parent of top-most tokens. - * @returns {MicromarkToken[]} Micromark tokens. - */ -function parseInternal( - markdown, - parseOptions = {}, - micromarkParseOptions = {}, - lineDelta = 0, - ancestor = undefined -) { - // Get options - const freezeTokens = Boolean(parseOptions.freezeTokens); - - // Use micromark to parse document into Events - const events = getEvents(markdown, micromarkParseOptions); - - // Create Token objects - const document = []; - let flatTokens = []; - /** @type {MicromarkToken} */ - const root = { - "type": "data", - "startLine": -1, - "startColumn": -1, - "endLine": -1, - "endColumn": -1, - "text": "ROOT", - "children": document, - "parent": null - }; - const history = [ root ]; - let current = root; - // eslint-disable-next-line jsdoc/valid-types - /** @type MicromarkParseOptions | null */ - let reparseOptions = null; - let lines = null; - let skipHtmlFlowChildren = false; - for (const event of events) { - const [ kind, token, context ] = event; - const { type, start, end } = token; - const { "column": startColumn, "line": startLine } = start; - const { "column": endColumn, "line": endLine } = end; - const text = context.sliceSerialize(token); - if ((kind === "enter") && !skipHtmlFlowChildren) { - const previous = current; - history.push(previous); - current = { - type, - "startLine": startLine + lineDelta, - startColumn, - "endLine": endLine + lineDelta, - endColumn, - text, - "children": [], - "parent": ((previous === root) ? (ancestor || null) : previous) - }; - if (ancestor) { - Object.defineProperty(current, htmlFlowSymbol, { "value": true }); - } - previous.children.push(current); - flatTokens.push(current); - if ((current.type === "htmlFlow") && !isHtmlFlowComment(current)) { - skipHtmlFlowChildren = true; - if (!reparseOptions || !lines) { - reparseOptions = { - ...micromarkParseOptions, - "extensions": [ - { - "disable": { - "null": [ "codeIndented", "htmlFlow" ] - } - } - ] - }; - lines = markdown.split(newLineRe); - } - const reparseMarkdown = lines - .slice(current.startLine - 1, current.endLine) - .join("\n"); - const tokens = parseInternal( - reparseMarkdown, - parseOptions, - reparseOptions, - current.startLine - 1, - current - ); - current.children = tokens; - // Avoid stack overflow of Array.push(...spread) - // eslint-disable-next-line unicorn/prefer-spread - flatTokens = flatTokens.concat(tokens[flatTokensSymbol]); - } - } else if (kind === "exit") { - if (type === "htmlFlow") { - skipHtmlFlowChildren = false; - } - if (!skipHtmlFlowChildren) { - if (freezeTokens) { - Object.freeze(current.children); - Object.freeze(current); - } - // @ts-ignore - current = history.pop(); - } - } - } - - // Return document - Object.defineProperty(document, flatTokensSymbol, { "value": flatTokens }); - if (freezeTokens) { - Object.freeze(document); - } - return document; -} - -/** - * Parses a Markdown document and returns micromark tokens. - * - * @param {string} markdown Markdown document. - * @param {ParseOptions} [parseOptions] Options. - * @returns {MicromarkToken[]} Micromark tokens. - */ -function parse(markdown, parseOptions) { - return parseInternal(markdown, parseOptions); -} - -module.exports = { - getEvents, - parse -}; - - -/***/ }), - -/***/ "../lib/cache.js": -/*!***********************!*\ - !*** ../lib/cache.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const helpers = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypes } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); - -/** @type {Map} */ -const map = new Map(); -let params = undefined; - -/** - * Initializes (resets) the cache. - * - * @param {import("./markdownlint").RuleParams} [p] Rule parameters object. - * @returns {void} - */ -function initialize(p) { - map.clear(); - params = p; -} - -/** - * Gets a cached object value - computes it and caches it. - * - * @param {string} name Cache object name. - * @param {Function} getValue Getter for object value. - * @returns {Object} Object value. - */ -function getCached(name, getValue) { - if (map.has(name)) { - return map.get(name); - } - const value = getValue(); - map.set(name, value); - return value; -} - -/** - * Filters a list of Micromark tokens by type and caches the result. - * - * @param {import("./markdownlint").MicromarkTokenType[]} types Types to allow. - * @param {boolean} [htmlFlow] Whether to include htmlFlow content. - * @returns {import("./markdownlint").MicromarkToken[]} Filtered tokens. - */ -function filterByTypesCached(types, htmlFlow) { - return getCached( - // eslint-disable-next-line prefer-rest-params - JSON.stringify(arguments), - () => filterByTypes(params.parsers.micromark.tokens, types, htmlFlow) - ); -} - -/** - * Gets a reference link and image data object. - * - * @returns {Object} Reference link and image data object. - */ -function getReferenceLinkImageData() { - return getCached( - getReferenceLinkImageData.name, - () => helpers.getReferenceLinkImageData(params.parsers.micromark.tokens) - ); -} - -module.exports = { - initialize, - filterByTypesCached, - getReferenceLinkImageData -}; - - -/***/ }), - -/***/ "../lib/constants.js": -/*!***************************!*\ - !*** ../lib/constants.js ***! - \***************************/ -/***/ ((module) => { - -"use strict"; -// @ts-check - - - -module.exports.deprecatedRuleNames = []; -module.exports.fixableRuleNames = [ - "MD004", "MD005", "MD007", "MD009", "MD010", "MD011", - "MD012", "MD014", "MD018", "MD019", "MD020", "MD021", - "MD022", "MD023", "MD026", "MD027", "MD030", "MD031", - "MD032", "MD034", "MD037", "MD038", "MD039", "MD044", - "MD047", "MD049", "MD050", "MD051", "MD053", "MD054", - "MD058" -]; -module.exports.homepage = "https://github.com/DavidAnson/markdownlint"; -module.exports.version = "0.36.1"; - - -/***/ }), - -/***/ "../lib/markdownit.cjs": -/*!*****************************!*\ - !*** ../lib/markdownit.cjs ***! - \*****************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { newLineRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); - -/** - * @callback InlineCodeSpanCallback - * @param {string} code Code content. - * @param {number} lineIndex Line index (0-based). - * @param {number} columnIndex Column index (0-based). - * @param {number} ticks Count of backticks. - * @returns {void} - */ - -/** - * Calls the provided function for each inline code span's content. - * - * @param {string} input Markdown content. - * @param {InlineCodeSpanCallback} handler Callback function taking (code, - * lineIndex, columnIndex, ticks). - * @returns {void} - */ -function forEachInlineCodeSpan(input, handler) { - const backtickRe = /`+/g; - let match = null; - const backticksLengthAndIndex = []; - while ((match = backtickRe.exec(input)) !== null) { - backticksLengthAndIndex.push([ match[0].length, match.index ]); - } - const newLinesIndex = []; - while ((match = newLineRe.exec(input)) !== null) { - newLinesIndex.push(match.index); - } - let lineIndex = 0; - let lineStartIndex = 0; - let k = 0; - for (let i = 0; i < backticksLengthAndIndex.length - 1; i++) { - const [ startLength, startIndex ] = backticksLengthAndIndex[i]; - if ((startIndex === 0) || (input[startIndex - 1] !== "\\")) { - for (let j = i + 1; j < backticksLengthAndIndex.length; j++) { - const [ endLength, endIndex ] = backticksLengthAndIndex[j]; - if (startLength === endLength) { - for (; k < newLinesIndex.length; k++) { - const newLineIndex = newLinesIndex[k]; - if (startIndex < newLineIndex) { - break; - } - lineIndex++; - lineStartIndex = newLineIndex + 1; - } - const columnIndex = startIndex - lineStartIndex + startLength; - handler( - input.slice(startIndex + startLength, endIndex), - lineIndex, - columnIndex, - startLength - ); - i = j; - break; - } - } - } - } -} - -/** - * Freeze all freeze-able members of a token and its children. - * - * @param {import("./markdownlint").MarkdownItToken} token A markdown-it token. - * @returns {void} - */ -function freezeToken(token) { - if (token.attrs) { - for (const attr of token.attrs) { - Object.freeze(attr); - } - Object.freeze(token.attrs); - } - if (token.children) { - for (const child of token.children) { - freezeToken(child); - } - Object.freeze(token.children); - } - if (token.map) { - Object.freeze(token.map); - } - Object.freeze(token); -} - -/** - * Annotate tokens with line/lineNumber and freeze them. - * - * @param {Object[]} tokens Array of markdown-it tokens. - * @param {string[]} lines Lines of Markdown content. - * @returns {void} - */ -function annotateAndFreezeTokens(tokens, lines) { - let trMap = null; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("./markdownlint").MarkdownItToken[] */ - // @ts-ignore - const markdownItTokens = tokens; - for (const token of markdownItTokens) { - // Provide missing maps for table content - if (token.type === "tr_open") { - trMap = token.map; - } else if (token.type === "tr_close") { - trMap = null; - } - if (!token.map && trMap) { - token.map = [ ...trMap ]; - } - // Update token metadata - if (token.map) { - token.line = lines[token.map[0]]; - token.lineNumber = token.map[0] + 1; - // Trim bottom of token to exclude whitespace lines - while (token.map[1] && !((lines[token.map[1] - 1] || "").trim())) { - token.map[1]--; - } - } - // Annotate children with lineNumber - if (token.children) { - const codeSpanExtraLines = []; - if (token.children.some((child) => child.type === "code_inline")) { - forEachInlineCodeSpan(token.content, (code) => { - codeSpanExtraLines.push(code.split(newLineRe).length - 1); - }); - } - let lineNumber = token.lineNumber; - for (const child of token.children) { - child.lineNumber = lineNumber; - child.line = lines[lineNumber - 1]; - if ((child.type === "softbreak") || (child.type === "hardbreak")) { - lineNumber++; - } else if (child.type === "code_inline") { - lineNumber += codeSpanExtraLines.shift(); - } - } - } - freezeToken(token); - } - Object.freeze(tokens); -} - -/** - * Gets an array of markdown-it tokens for the input. - * - * @param {import("./markdownlint").Plugin[]} markdownItPlugins Additional plugins. - * @param {string} content Markdown content. - * @param {string[]} lines Lines of Markdown content. - * @returns {import("../lib/markdownlint").MarkdownItToken} Array of markdown-it tokens. - */ -function getMarkdownItTokens(markdownItPlugins, content, lines) { - const markdownit = __webpack_require__(/*! markdown-it */ "markdown-it"); - const md = markdownit({ "html": true }); - for (const plugin of markdownItPlugins) { - // @ts-ignore - md.use(...plugin); - } - const tokens = md.parse(content, {}); - annotateAndFreezeTokens(tokens, lines); - // @ts-ignore - return tokens; -}; - -module.exports = { - forEachInlineCodeSpan, - getMarkdownItTokens -}; - - -/***/ }), - -/***/ "../lib/markdownlint.js": -/*!******************************!*\ - !*** ../lib/markdownlint.js ***! - \******************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const path = __webpack_require__(/*! node:path */ "?9a52"); -const { promisify } = __webpack_require__(/*! node:util */ "?39e5"); -const micromark = __webpack_require__(/*! ../helpers/micromark-parse.cjs */ "../helpers/micromark-parse.cjs"); -const { version } = __webpack_require__(/*! ./constants */ "../lib/constants.js"); -const rules = __webpack_require__(/*! ./rules */ "../lib/rules.js"); -const helpers = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const cache = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// @ts-ignore -// eslint-disable-next-line camelcase, no-inline-comments, no-undef -const dynamicRequire = (typeof require === "undefined") ? __webpack_require__("../lib sync recursive") : /* c8 ignore next */ require; -// Capture native require implementation for dynamic loading of modules - -/** - * Validate the list of rules for structure and reuse. - * - * @param {Rule[]} ruleList List of rules. - * @param {boolean} synchronous Whether to execute synchronously. - * @returns {Error | null} Error message if validation fails. - */ -function validateRuleList(ruleList, synchronous) { - let result = null; - if (ruleList.length === rules.length) { - // No need to validate if only using built-in rules - return result; - } - const allIds = {}; - for (const [ index, rule ] of ruleList.entries()) { - const customIndex = index - rules.length; - // eslint-disable-next-line jsdoc/require-jsdoc - function newError(property, value) { - return new Error( - `Property '${property}' of custom rule at index ${customIndex} is incorrect: '${value}'.`); - } - for (const property of [ "names", "tags" ]) { - const value = rule[property]; - if (!result && - (!value || !Array.isArray(value) || (value.length === 0) || - !value.every(helpers.isString) || value.some(helpers.isEmptyString))) { - result = newError(property, value); - } - } - for (const propertyInfo of [ - [ "description", "string" ], - [ "function", "function" ] - ]) { - const property = propertyInfo[0]; - const value = rule[property]; - if (!result && (!value || (typeof value !== propertyInfo[1]))) { - result = newError(property, value); - } - } - if ( - !result && - (rule.parser !== undefined) && - (rule.parser !== "markdownit") && - (rule.parser !== "micromark") && - (rule.parser !== "none") - ) { - result = newError("parser", rule.parser); - } - if ( - !result && - rule.information && - !helpers.isUrl(rule.information) - ) { - result = newError("information", rule.information); - } - if ( - !result && - (rule.asynchronous !== undefined) && - (typeof rule.asynchronous !== "boolean") - ) { - result = newError("asynchronous", rule.asynchronous); - } - if (!result && rule.asynchronous && synchronous) { - result = new Error( - "Custom rule " + rule.names.join("/") + " at index " + customIndex + - " is asynchronous and can not be used in a synchronous context." - ); - } - if (!result) { - for (const name of rule.names) { - const nameUpper = name.toUpperCase(); - if (!result && (allIds[nameUpper] !== undefined)) { - result = new Error("Name '" + name + "' of custom rule at index " + - customIndex + " is already used as a name or tag."); - } - allIds[nameUpper] = true; - } - for (const tag of rule.tags) { - const tagUpper = tag.toUpperCase(); - if (!result && allIds[tagUpper]) { - result = new Error("Tag '" + tag + "' of custom rule at index " + - customIndex + " is already used as a name."); - } - allIds[tagUpper] = false; - } - } - } - return result; -} - -/** - * Creates a LintResults instance with toString for pretty display. - * - * @param {Rule[]} ruleList List of rules. - * @returns {LintResults} New LintResults instance. - */ -function newResults(ruleList) { - const lintResults = {}; - // eslint-disable-next-line jsdoc/require-jsdoc - function toString(useAlias) { - let ruleNameToRule = null; - const results = []; - const keys = Object.keys(lintResults); - keys.sort(); - for (const file of keys) { - const fileResults = lintResults[file]; - if (Array.isArray(fileResults)) { - for (const result of fileResults) { - const ruleMoniker = result.ruleNames ? - result.ruleNames.join("/") : - (result.ruleName + "/" + result.ruleAlias); - results.push( - file + ": " + - result.lineNumber + ": " + - ruleMoniker + " " + - result.ruleDescription + - (result.errorDetail ? - " [" + result.errorDetail + "]" : - "") + - (result.errorContext ? - " [Context: \"" + result.errorContext + "\"]" : - "")); - } - } else { - if (!ruleNameToRule) { - ruleNameToRule = {}; - for (const rule of ruleList) { - const ruleName = rule.names[0].toUpperCase(); - ruleNameToRule[ruleName] = rule; - } - } - for (const [ ruleName, ruleResults ] of Object.entries(fileResults)) { - const rule = ruleNameToRule[ruleName.toUpperCase()]; - for (const lineNumber of ruleResults) { - // @ts-ignore - const nameIndex = Math.min(useAlias ? 1 : 0, rule.names.length - 1); - const result = - file + ": " + - lineNumber + ": " + - // @ts-ignore - rule.names[nameIndex] + " " + - // @ts-ignore - rule.description; - results.push(result); - } - } - } - } - return results.join("\n"); - } - Object.defineProperty(lintResults, "toString", { "value": toString }); - // @ts-ignore - return lintResults; -} - -/** - * Remove front matter (if present at beginning of content). - * - * @param {string} content Markdown content. - * @param {RegExp | null} frontMatter Regular expression to match front matter. - * @returns {Object} Trimmed content and front matter lines. - */ -function removeFrontMatter(content, frontMatter) { - let frontMatterLines = []; - if (frontMatter) { - const frontMatterMatch = content.match(frontMatter); - if (frontMatterMatch && !frontMatterMatch.index) { - const contentMatched = frontMatterMatch[0]; - content = content.slice(contentMatched.length); - frontMatterLines = contentMatched.split(helpers.newLineRe); - if ((frontMatterLines.length > 0) && - (frontMatterLines[frontMatterLines.length - 1] === "")) { - frontMatterLines.length--; - } - } - } - return { - "content": content, - "frontMatterLines": frontMatterLines - }; -} - -/** - * Map rule names/tags to canonical rule name. - * - * @param {Rule[]} ruleList List of rules. - * @returns {Object.} Map of alias to rule name. - */ -function mapAliasToRuleNames(ruleList) { - const aliasToRuleNames = {}; - // const tagToRuleNames = {}; - for (const rule of ruleList) { - const ruleName = rule.names[0].toUpperCase(); - // The following is useful for updating README.md: - // console.log( - // "* **[" + ruleName + "](doc/Rules.md#" + ruleName.toLowerCase() + - // ")** *" + rule.names.slice(1).join("/") + "* - " + rule.description); - for (const name of rule.names) { - const nameUpper = name.toUpperCase(); - aliasToRuleNames[nameUpper] = [ ruleName ]; - } - for (const tag of rule.tags) { - const tagUpper = tag.toUpperCase(); - const ruleNames = aliasToRuleNames[tagUpper] || []; - ruleNames.push(ruleName); - aliasToRuleNames[tagUpper] = ruleNames; - // tagToRuleNames[tag] = ruleName; - } - } - // The following is useful for updating README.md: - // Object.keys(tagToRuleNames).sort().forEach(function forTag(tag) { - // console.log("* **" + tag + "** - " + - // aliasToRuleNames[tag.toUpperCase()].join(", ")); - // }); - // @ts-ignore - return aliasToRuleNames; -} - -/** - * Apply (and normalize) configuration object. - * - * @param {Rule[]} ruleList List of rules. - * @param {Configuration} config Configuration object. - * @param {Object.} aliasToRuleNames Map of alias to rule - * names. - * @returns {Configuration} Effective configuration. - */ -function getEffectiveConfig(ruleList, config, aliasToRuleNames) { - const defaultKey = Object.keys(config).filter( - (key) => key.toUpperCase() === "DEFAULT" - ); - const ruleDefault = (defaultKey.length === 0) || !!config[defaultKey[0]]; - /** @type {Configuration} */ - const effectiveConfig = {}; - for (const rule of ruleList) { - const ruleName = rule.names[0].toUpperCase(); - effectiveConfig[ruleName] = ruleDefault; - } - // for (const ruleName of deprecatedRuleNames) { - // effectiveConfig[ruleName] = false; - // } - for (const key of Object.keys(config)) { - let value = config[key]; - if (value) { - if (!(value instanceof Object)) { - value = {}; - } - } else { - value = false; - } - const keyUpper = key.toUpperCase(); - for (const ruleName of (aliasToRuleNames[keyUpper] || [])) { - effectiveConfig[ruleName] = value; - } - } - return effectiveConfig; -} - -/** - * Parse the content of a configuration file. - * - * @param {string} name Name of the configuration file. - * @param {string} content Configuration content. - * @param {ConfigurationParser[] | null} [parsers] Parsing function(s). - * @returns {Object} Configuration object and error message. - */ -function parseConfiguration(name, content, parsers) { - let config = null; - let message = ""; - const errors = []; - let index = 0; - // Try each parser - (parsers || [ JSON.parse ]).every((parser) => { - try { - config = parser(content); - } catch (error) { - errors.push(`Parser ${index++}: ${error.message}`); - } - return !config; - }); - // Message if unable to parse - if (!config) { - errors.unshift(`Unable to parse '${name}'`); - message = errors.join("; "); - } - return { - config, - message - }; -} - -/** - * Create a mapping of enabled rules per line. - * - * @param {Rule[]} ruleList List of rules. - * @param {string[]} lines List of content lines. - * @param {string[]} frontMatterLines List of front matter lines. - * @param {boolean} noInlineConfig Whether to allow inline configuration. - * @param {Configuration} config Configuration object. - * @param {ConfigurationParser[] | null} configParsers Configuration parsers. - * @param {Object.} aliasToRuleNames Map of alias to rule - * names. - * @returns {Object} Effective configuration and enabled rules per line number. - */ -function getEnabledRulesPerLineNumber( - ruleList, - lines, - frontMatterLines, - noInlineConfig, - config, - configParsers, - aliasToRuleNames) { - // Shared variables - let enabledRules = {}; - let capturedRules = {}; - const allRuleNames = []; - const enabledRulesPerLineNumber = new Array(1 + frontMatterLines.length); - // Helper functions - // eslint-disable-next-line jsdoc/require-jsdoc - function handleInlineConfig(input, forEachMatch, forEachLine) { - for (const [ lineIndex, line ] of input.entries()) { - if (!noInlineConfig) { - let match = null; - while ((match = helpers.inlineCommentStartRe.exec(line))) { - const action = match[2].toUpperCase(); - const startIndex = match.index + match[1].length; - const endIndex = line.indexOf("-->", startIndex); - if (endIndex === -1) { - break; - } - const parameter = line.slice(startIndex, endIndex); - forEachMatch(action, parameter, lineIndex + 1); - } - } - if (forEachLine) { - forEachLine(); - } - } - } - // eslint-disable-next-line jsdoc/require-jsdoc - function configureFile(action, parameter) { - if (action === "CONFIGURE-FILE") { - const { "config": parsed } = parseConfiguration( - "CONFIGURE-FILE", parameter, configParsers - ); - if (parsed) { - config = { - ...config, - ...parsed - }; - } - } - } - // eslint-disable-next-line jsdoc/require-jsdoc - function applyEnableDisable(action, parameter, state) { - state = { ...state }; - const enabled = (action.startsWith("ENABLE")); - const trimmed = parameter && parameter.trim(); - const items = trimmed ? trimmed.toUpperCase().split(/\s+/) : allRuleNames; - for (const nameUpper of items) { - for (const ruleName of (aliasToRuleNames[nameUpper] || [])) { - state[ruleName] = enabled; - } - } - return state; - } - // eslint-disable-next-line jsdoc/require-jsdoc - function enableDisableFile(action, parameter) { - if ((action === "ENABLE-FILE") || (action === "DISABLE-FILE")) { - enabledRules = applyEnableDisable(action, parameter, enabledRules); - } - } - // eslint-disable-next-line jsdoc/require-jsdoc - function captureRestoreEnableDisable(action, parameter) { - if (action === "CAPTURE") { - capturedRules = enabledRules; - } else if (action === "RESTORE") { - enabledRules = capturedRules; - } else if ((action === "ENABLE") || (action === "DISABLE")) { - enabledRules = applyEnableDisable(action, parameter, enabledRules); - } - } - // eslint-disable-next-line jsdoc/require-jsdoc - function updateLineState() { - enabledRulesPerLineNumber.push(enabledRules); - } - // eslint-disable-next-line jsdoc/require-jsdoc - function disableLineNextLine(action, parameter, lineNumber) { - const disableLine = (action === "DISABLE-LINE"); - const disableNextLine = (action === "DISABLE-NEXT-LINE"); - if (disableLine || disableNextLine) { - const nextLineNumber = - frontMatterLines.length + lineNumber + (disableNextLine ? 1 : 0); - enabledRulesPerLineNumber[nextLineNumber] = - applyEnableDisable( - action, - parameter, - enabledRulesPerLineNumber[nextLineNumber] - ); - } - } - // Handle inline comments - handleInlineConfig([ lines.join("\n") ], configureFile); - const effectiveConfig = getEffectiveConfig( - ruleList, config, aliasToRuleNames); - for (const rule of ruleList) { - const ruleName = rule.names[0].toUpperCase(); - allRuleNames.push(ruleName); - enabledRules[ruleName] = !!effectiveConfig[ruleName]; - } - capturedRules = enabledRules; - handleInlineConfig(lines, enableDisableFile); - handleInlineConfig(lines, captureRestoreEnableDisable, updateLineState); - handleInlineConfig(lines, disableLineNextLine); - // Create the list of rules that are used at least once - const enabledRuleList = []; - for (const [ index, ruleName ] of allRuleNames.entries()) { - if (enabledRulesPerLineNumber.some((enabledRulesForLine) => enabledRulesForLine[ruleName])) { - enabledRuleList.push(ruleList[index]); - } - } - // Return results - return { - effectiveConfig, - enabledRulesPerLineNumber, - enabledRuleList - }; -} - -/** - * Lints a string containing Markdown content. - * - * @param {Rule[]} ruleList List of rules. - * @param {Object.} aliasToRuleNames Map of alias to rule - * names. - * @param {string} name Identifier for the content. - * @param {string} content Markdown content. - * @param {Plugin[]} markdownItPlugins Additional plugins. - * @param {Configuration} config Configuration object. - * @param {ConfigurationParser[] | null} configParsers Configuration parsers. - * @param {RegExp | null} frontMatter Regular expression for front matter. - * @param {boolean} handleRuleFailures Whether to handle exceptions in rules. - * @param {boolean} noInlineConfig Whether to allow inline configuration. - * @param {number} resultVersion Version of the LintResults object to return. - * @param {LintContentCallback} callback Callback (err, result) function. - * @returns {void} - */ -function lintContent( - ruleList, - aliasToRuleNames, - name, - content, - markdownItPlugins, - config, - configParsers, - frontMatter, - handleRuleFailures, - noInlineConfig, - resultVersion, - callback) { - // Remove UTF-8 byte order marker (if present) - content = content.replace(/^\uFEFF/, ""); - // Remove front matter - const removeFrontMatterResult = removeFrontMatter(content, frontMatter); - const { frontMatterLines } = removeFrontMatterResult; - content = removeFrontMatterResult.content; - // Get enabled rules per line (with HTML comments present) - const { effectiveConfig, enabledRulesPerLineNumber, enabledRuleList } = - getEnabledRulesPerLineNumber( - ruleList, - content.split(helpers.newLineRe), - frontMatterLines, - noInlineConfig, - config, - configParsers, - aliasToRuleNames - ); - const needMarkdownItTokens = enabledRuleList.some( - (rule) => (rule.parser === "markdownit") || (rule.parser === undefined) - ); - const customRulesPresent = (ruleList.length !== rules.length); - // Parse content into parser tokens - const micromarkTokens = micromark.parse( - content, - { "freezeTokens": customRulesPresent } - ); - // Hide the content of HTML comments from rules - const preClearedContent = content; - content = helpers.clearHtmlCommentText(content); - // Parse content into lines and get markdown-it tokens - const lines = content.split(helpers.newLineRe); - const markdownitTokens = needMarkdownItTokens ? - (__webpack_require__(/*! ./markdownit.cjs */ "../lib/markdownit.cjs").getMarkdownItTokens)(markdownItPlugins, preClearedContent, lines) : - []; - // Create (frozen) parameters for rules - /** @type {MarkdownParsers} */ - // @ts-ignore - const parsersMarkdownIt = Object.freeze({ - "markdownit": Object.freeze({ - "tokens": markdownitTokens - }) - }); - /** @type {MarkdownParsers} */ - // @ts-ignore - const parsersMicromark = Object.freeze({ - "micromark": Object.freeze({ - "tokens": micromarkTokens - }) - }); - /** @type {MarkdownParsers} */ - // @ts-ignore - const parsersNone = Object.freeze({}); - const paramsBase = { - name, - version, - "lines": Object.freeze(lines), - "frontMatterLines": Object.freeze(frontMatterLines) - }; - cache.initialize({ - ...paramsBase, - "parsers": parsersMicromark, - "config": null - }); - // Function to run for each rule - let results = []; - /** - * @param {Rule} rule Rule. - * @returns {Promise | null} Promise. - */ - const forRule = (rule) => { - // Configure rule - const ruleName = rule.names[0].toUpperCase(); - const tokens = {}; - let parsers = parsersNone; - if (rule.parser === undefined) { - tokens.tokens = markdownitTokens; - parsers = parsersMarkdownIt; - } else if (rule.parser === "markdownit") { - parsers = parsersMarkdownIt; - } else if (rule.parser === "micromark") { - parsers = parsersMicromark; - } - const params = { - ...paramsBase, - ...tokens, - parsers, - "config": effectiveConfig[ruleName] - }; - // eslint-disable-next-line jsdoc/require-jsdoc - function throwError(property) { - throw new Error( - `Value of '${property}' passed to onError by '${ruleName}' is incorrect for '${name}'.`); - } - // eslint-disable-next-line jsdoc/require-jsdoc - function onError(errorInfo) { - if (!errorInfo || - !helpers.isNumber(errorInfo.lineNumber) || - (errorInfo.lineNumber < 1) || - (errorInfo.lineNumber > lines.length)) { - throwError("lineNumber"); - } - const lineNumber = errorInfo.lineNumber + frontMatterLines.length; - if (!enabledRulesPerLineNumber[lineNumber][ruleName]) { - return; - } - if (errorInfo.detail && - !helpers.isString(errorInfo.detail)) { - throwError("detail"); - } - if (errorInfo.context && - !helpers.isString(errorInfo.context)) { - throwError("context"); - } - if (errorInfo.information && - !helpers.isUrl(errorInfo.information)) { - throwError("information"); - } - if (errorInfo.range && - (!Array.isArray(errorInfo.range) || - (errorInfo.range.length !== 2) || - !helpers.isNumber(errorInfo.range[0]) || - (errorInfo.range[0] < 1) || - !helpers.isNumber(errorInfo.range[1]) || - (errorInfo.range[1] < 1) || - ((errorInfo.range[0] + errorInfo.range[1] - 1) > - lines[errorInfo.lineNumber - 1].length))) { - throwError("range"); - } - const fixInfo = errorInfo.fixInfo; - const cleanFixInfo = {}; - if (fixInfo) { - if (!helpers.isObject(fixInfo)) { - throwError("fixInfo"); - } - if (fixInfo.lineNumber !== undefined) { - if ((!helpers.isNumber(fixInfo.lineNumber) || - (fixInfo.lineNumber < 1) || - (fixInfo.lineNumber > lines.length))) { - throwError("fixInfo.lineNumber"); - } - cleanFixInfo.lineNumber = - fixInfo.lineNumber + frontMatterLines.length; - } - const effectiveLineNumber = fixInfo.lineNumber || errorInfo.lineNumber; - if (fixInfo.editColumn !== undefined) { - if ((!helpers.isNumber(fixInfo.editColumn) || - (fixInfo.editColumn < 1) || - (fixInfo.editColumn > - lines[effectiveLineNumber - 1].length + 1))) { - throwError("fixInfo.editColumn"); - } - cleanFixInfo.editColumn = fixInfo.editColumn; - } - if (fixInfo.deleteCount !== undefined) { - if ((!helpers.isNumber(fixInfo.deleteCount) || - (fixInfo.deleteCount < -1) || - (fixInfo.deleteCount > - lines[effectiveLineNumber - 1].length))) { - throwError("fixInfo.deleteCount"); - } - cleanFixInfo.deleteCount = fixInfo.deleteCount; - } - if (fixInfo.insertText !== undefined) { - if (!helpers.isString(fixInfo.insertText)) { - throwError("fixInfo.insertText"); - } - cleanFixInfo.insertText = fixInfo.insertText; - } - } - const information = errorInfo.information || rule.information; - results.push({ - lineNumber, - "ruleName": rule.names[0], - "ruleNames": rule.names, - "ruleDescription": rule.description, - "ruleInformation": information ? information.href : null, - "errorDetail": errorInfo.detail || null, - "errorContext": errorInfo.context || null, - "errorRange": errorInfo.range ? [ ...errorInfo.range ] : null, - "fixInfo": fixInfo ? cleanFixInfo : null - }); - } - // Call (possibly external) rule function to report errors - const catchCallsOnError = (error) => onError({ - "lineNumber": 1, - "detail": `This rule threw an exception: ${error.message || error}` - }); - const invokeRuleFunction = () => rule.function(params, onError); - if (rule.asynchronous) { - // Asynchronous rule, ensure it returns a Promise - const ruleFunctionPromise = - Promise.resolve().then(invokeRuleFunction); - return handleRuleFailures ? - ruleFunctionPromise.catch(catchCallsOnError) : - ruleFunctionPromise; - } - // Synchronous rule - try { - invokeRuleFunction(); - } catch (error) { - if (handleRuleFailures) { - catchCallsOnError(error); - } else { - throw error; - } - } - return null; - }; - // eslint-disable-next-line jsdoc/require-jsdoc - function formatResults() { - // Sort results by rule name by line number - results.sort((a, b) => ( - a.ruleName.localeCompare(b.ruleName) || - a.lineNumber - b.lineNumber - )); - if (resultVersion < 3) { - // Remove fixInfo and multiple errors for the same rule and line number - const noPrevious = { - "ruleName": null, - "lineNumber": -1 - }; - results = results.filter((error, index, array) => { - delete error.fixInfo; - const previous = array[index - 1] || noPrevious; - return ( - (error.ruleName !== previous.ruleName) || - (error.lineNumber !== previous.lineNumber) - ); - }); - } - if (resultVersion === 0) { - // Return a dictionary of rule->[line numbers] - const dictionary = {}; - for (const error of results) { - const ruleLines = dictionary[error.ruleName] || []; - ruleLines.push(error.lineNumber); - dictionary[error.ruleName] = ruleLines; - } - // @ts-ignore - results = dictionary; - } else if (resultVersion === 1) { - // Use ruleAlias instead of ruleNames - for (const error of results) { - error.ruleAlias = error.ruleNames[1] || error.ruleName; - delete error.ruleNames; - } - } else { - // resultVersion 2 or 3: Remove unwanted ruleName - for (const error of results) { - delete error.ruleName; - } - } - return results; - } - // Run all rules - const ruleListAsync = enabledRuleList.filter((rule) => rule.asynchronous); - const ruleListSync = enabledRuleList.filter((rule) => !rule.asynchronous); - const ruleListAsyncFirst = [ - ...ruleListAsync, - ...ruleListSync - ]; - const callbackSuccess = () => callback(null, formatResults()); - const callbackError = - (error) => callback(error instanceof Error ? error : new Error(error)); - try { - const ruleResults = ruleListAsyncFirst.map(forRule); - if (ruleListAsync.length > 0) { - Promise.all(ruleResults.slice(0, ruleListAsync.length)) - .then(callbackSuccess) - .catch(callbackError); - } else { - callbackSuccess(); - } - } catch (error) { - callbackError(error); - } finally { - cache.initialize(); - } -} - -/** - * Lints a file containing Markdown content. - * - * @param {Rule[]} ruleList List of rules. - * @param {Object.} aliasToRuleNames Map of alias to rule - * names. - * @param {string} file Path of file to lint. - * @param {Plugin[]} markdownItPlugins Additional plugins. - * @param {Configuration} config Configuration object. - * @param {ConfigurationParser[] | null} configParsers Configuration parsers. - * @param {RegExp | null} frontMatter Regular expression for front matter. - * @param {boolean} handleRuleFailures Whether to handle exceptions in rules. - * @param {boolean} noInlineConfig Whether to allow inline configuration. - * @param {number} resultVersion Version of the LintResults object to return. - * @param {Object} fs File system implementation. - * @param {boolean} synchronous Whether to execute synchronously. - * @param {LintContentCallback} callback Callback (err, result) function. - * @returns {void} - */ -function lintFile( - ruleList, - aliasToRuleNames, - file, - markdownItPlugins, - config, - configParsers, - frontMatter, - handleRuleFailures, - noInlineConfig, - resultVersion, - fs, - synchronous, - callback) { - // eslint-disable-next-line jsdoc/require-jsdoc - function lintContentWrapper(err, content) { - if (err) { - return callback(err); - } - return lintContent( - ruleList, - aliasToRuleNames, - file, - content, - markdownItPlugins, - config, - configParsers, - frontMatter, - handleRuleFailures, - noInlineConfig, - resultVersion, - callback - ); - } - // Make a/synchronous call to read file - if (synchronous) { - lintContentWrapper(null, fs.readFileSync(file, "utf8")); - } else { - fs.readFile(file, "utf8", lintContentWrapper); - } -} - -/** - * Lint files and strings specified in the Options object. - * - * @param {Options | null} options Options object. - * @param {boolean} synchronous Whether to execute synchronously. - * @param {LintCallback} callback Callback (err, result) function. - * @returns {void} - */ -function lintInput(options, synchronous, callback) { - // Normalize inputs - options = options || {}; - callback = callback || function noop() {}; - const customRuleList = - [ options.customRules || [] ] - .flat() - .map((rule) => ({ - "names": helpers.cloneIfArray(rule.names), - "description": rule.description, - "information": helpers.cloneIfUrl(rule.information), - "tags": helpers.cloneIfArray(rule.tags), - "parser": rule.parser, - "asynchronous": rule.asynchronous, - "function": rule.function - })); - // eslint-disable-next-line unicorn/prefer-spread - const ruleList = rules.concat(customRuleList); - const ruleErr = validateRuleList(ruleList, synchronous); - if (ruleErr) { - callback(ruleErr); - return; - } - let files = []; - if (Array.isArray(options.files)) { - files = [ ...options.files ]; - } else if (options.files) { - files = [ String(options.files) ]; - } - const strings = options.strings || {}; - const stringsKeys = Object.keys(strings); - const config = options.config || { "default": true }; - const configParsers = options.configParsers || null; - const frontMatter = (options.frontMatter === undefined) ? - helpers.frontMatterRe : - options.frontMatter; - const handleRuleFailures = !!options.handleRuleFailures; - const noInlineConfig = !!options.noInlineConfig; - const resultVersion = (options.resultVersion === undefined) ? - 3 : - options.resultVersion; - const markdownItPlugins = options.markdownItPlugins || []; - const fs = options.fs || __webpack_require__(/*! node:fs */ "?d0ee"); - const aliasToRuleNames = mapAliasToRuleNames(ruleList); - const results = newResults(ruleList); - let done = false; - let concurrency = 0; - // eslint-disable-next-line jsdoc/require-jsdoc - function lintWorker() { - let currentItem = null; - // eslint-disable-next-line jsdoc/require-jsdoc - function lintWorkerCallback(err, result) { - concurrency--; - if (err) { - done = true; - return callback(err); - } - results[currentItem] = result; - if (!synchronous) { - lintWorker(); - } - return null; - } - if (done) { - // Abort for error or nothing left to do - } else if (files.length > 0) { - // Lint next file - concurrency++; - currentItem = files.shift(); - lintFile( - ruleList, - aliasToRuleNames, - currentItem, - markdownItPlugins, - config, - configParsers, - frontMatter, - handleRuleFailures, - noInlineConfig, - resultVersion, - fs, - synchronous, - lintWorkerCallback - ); - } else if ((currentItem = stringsKeys.shift())) { - // Lint next string - concurrency++; - lintContent( - ruleList, - aliasToRuleNames, - currentItem, - strings[currentItem] || "", - markdownItPlugins, - config, - configParsers, - frontMatter, - handleRuleFailures, - noInlineConfig, - resultVersion, - lintWorkerCallback - ); - } else if (concurrency === 0) { - // Finish - done = true; - return callback(null, results); - } - return null; - } - if (synchronous) { - while (!done) { - lintWorker(); - } - } else { - // Testing on a Raspberry Pi 4 Model B with an artificial 5ms file access - // delay suggests that a concurrency factor of 8 can eliminate the impact - // of that delay (i.e., total time is the same as with no delay). - lintWorker(); - lintWorker(); - lintWorker(); - lintWorker(); - lintWorker(); - lintWorker(); - lintWorker(); - lintWorker(); - } -} - -/** - * Lint specified Markdown files. - * - * @param {Options | null} options Configuration options. - * @param {LintCallback} callback Callback (err, result) function. - * @returns {void} - */ -function markdownlint(options, callback) { - return lintInput(options, false, callback); -} - -const markdownlintPromisify = promisify && promisify(markdownlint); - -/** - * Lint specified Markdown files. - * - * @param {Options} options Configuration options. - * @returns {Promise} Results object. - */ -function markdownlintPromise(options) { - // @ts-ignore - return markdownlintPromisify(options); -} - -/** - * Lint specified Markdown files synchronously. - * - * @param {Options | null} options Configuration options. - * @returns {LintResults} Results object. - */ -function markdownlintSync(options) { - let results = null; - lintInput(options, true, function callback(error, res) { - if (error) { - throw error; - } - results = res; - }); - // @ts-ignore - return results; -} - -/** - * Resolve referenced "extends" path in a configuration file - * using path.resolve() with require.resolve() as a fallback. - * - * @param {string} configFile Configuration file name. - * @param {string} referenceId Referenced identifier to resolve. - * @param {Object} fs File system implementation. - * @param {ResolveConfigExtendsCallback} callback Callback (err, result) - * function. - * @returns {void} - */ -function resolveConfigExtends(configFile, referenceId, fs, callback) { - const configFileDirname = path.dirname(configFile); - const resolvedExtendsFile = path.resolve(configFileDirname, referenceId); - fs.access(resolvedExtendsFile, (err) => { - if (err) { - // Not a file, try require.resolve - try { - return callback(null, dynamicRequire.resolve( - referenceId, - { "paths": [ configFileDirname ] } - )); - } catch { - // Unable to resolve, use resolvedExtendsFile - } - } - return callback(null, resolvedExtendsFile); - }); -} - -/** - * Resolve referenced "extends" path in a configuration file - * using path.resolve() with require.resolve() as a fallback. - * - * @param {string} configFile Configuration file name. - * @param {string} referenceId Referenced identifier to resolve. - * @param {Object} fs File system implementation. - * @returns {string} Resolved path to file. - */ -function resolveConfigExtendsSync(configFile, referenceId, fs) { - const configFileDirname = path.dirname(configFile); - const resolvedExtendsFile = path.resolve(configFileDirname, referenceId); - try { - fs.accessSync(resolvedExtendsFile); - return resolvedExtendsFile; - } catch { - // Not a file, try require.resolve - } - try { - return dynamicRequire.resolve( - referenceId, - { "paths": [ configFileDirname ] } - ); - } catch { - // Unable to resolve, return resolvedExtendsFile - } - return resolvedExtendsFile; -} - -/** - * Extend specified configuration object. - * - * @param {Configuration} config Configuration object. - * @param {string} file Configuration file name. - * @param {ConfigurationParser[]} parsers Parsing - * function(s). - * @param {Object} fs File system implementation. - * @param {ReadConfigCallback} callback Callback (err, result) function. - * @returns {void} - */ -function extendConfig(config, file, parsers, fs, callback) { - const configExtends = config.extends; - if (configExtends) { - return resolveConfigExtends( - file, - helpers.expandTildePath(configExtends, __webpack_require__(/*! node:os */ "?e6c4")), - fs, - // eslint-disable-next-line no-use-before-define - (_, resolvedExtends) => readConfig( - // @ts-ignore - resolvedExtends, - parsers, - fs, - (err, extendsConfig) => { - if (err) { - return callback(err); - } - const result = { - ...extendsConfig, - ...config - }; - delete result.extends; - return callback(null, result); - } - ) - ); - } - return callback(null, config); -} - -const extendConfigPromisify = promisify && promisify(extendConfig); - -/** - * Extend specified configuration object. - * - * @param {Configuration} config Configuration object. - * @param {string} file Configuration file name. - * @param {ConfigurationParser[]} [parsers] Parsing function(s). - * @param {Object} [fs] File system implementation. - * @returns {Promise} Configuration object. - */ -function extendConfigPromise(config, file, parsers, fs) { - // @ts-ignore - return extendConfigPromisify(config, file, parsers, fs); -} - -/** - * Read specified configuration file. - * - * @param {string} file Configuration file name. - * @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing - * function(s). - * @param {Object} [fs] File system implementation. - * @param {ReadConfigCallback} [callback] Callback (err, result) function. - * @returns {void} - */ -function readConfig(file, parsers, fs, callback) { - if (!callback) { - if (fs) { - callback = fs; - fs = null; - } else { - // @ts-ignore - callback = parsers; - // @ts-ignore - parsers = null; - } - } - if (!fs) { - fs = __webpack_require__(/*! node:fs */ "?d0ee"); - } - // Read file - file = helpers.expandTildePath(file, __webpack_require__(/*! node:os */ "?e6c4")); - fs.readFile(file, "utf8", (err, content) => { - if (err) { - // @ts-ignore - return callback(err); - } - // Try to parse file - // @ts-ignore - const { config, message } = parseConfiguration(file, content, parsers); - if (!config) { - // @ts-ignore - return callback(new Error(message)); - } - // Extend configuration - // @ts-ignore - return extendConfig(config, file, parsers, fs, callback); - }); -} - -const readConfigPromisify = promisify && promisify(readConfig); - -/** - * Read specified configuration file. - * - * @param {string} file Configuration file name. - * @param {ConfigurationParser[]} [parsers] Parsing function(s). - * @param {Object} [fs] File system implementation. - * @returns {Promise} Configuration object. - */ -function readConfigPromise(file, parsers, fs) { - // @ts-ignore - return readConfigPromisify(file, parsers, fs); -} - -/** - * Read specified configuration file synchronously. - * - * @param {string} file Configuration file name. - * @param {ConfigurationParser[]} [parsers] Parsing function(s). - * @param {Object} [fs] File system implementation. - * @returns {Configuration} Configuration object. - * @throws An Error if processing fails. - */ -function readConfigSync(file, parsers, fs) { - if (!fs) { - fs = __webpack_require__(/*! node:fs */ "?d0ee"); - } - // Read file - const os = __webpack_require__(/*! node:os */ "?e6c4"); - file = helpers.expandTildePath(file, os); - const content = fs.readFileSync(file, "utf8"); - // Try to parse file - const { config, message } = parseConfiguration(file, content, parsers); - if (!config) { - throw new Error(message); - } - // Extend configuration - const configExtends = config.extends; - if (configExtends) { - delete config.extends; - const resolvedExtends = resolveConfigExtendsSync( - file, - helpers.expandTildePath(configExtends, os), - fs - ); - return { - ...readConfigSync(resolvedExtends, parsers, fs), - ...config - }; - } - return config; -} - -/** - * Normalizes the fields of a RuleOnErrorFixInfo instance. - * - * @param {RuleOnErrorFixInfo} fixInfo RuleOnErrorFixInfo instance. - * @param {number} [lineNumber] Line number. - * @returns {RuleOnErrorFixInfoNormalized} Normalized RuleOnErrorFixInfo instance. - */ -function normalizeFixInfo(fixInfo, lineNumber = 0) { - return { - "lineNumber": fixInfo.lineNumber || lineNumber, - "editColumn": fixInfo.editColumn || 1, - "deleteCount": fixInfo.deleteCount || 0, - "insertText": fixInfo.insertText || "" - }; -} - -/** - * Applies the specified fix to a Markdown content line. - * - * @param {string} line Line of Markdown content. - * @param {RuleOnErrorFixInfo} fixInfo RuleOnErrorFixInfo instance. - * @param {string} [lineEnding] Line ending to use. - * @returns {string | null} Fixed content or null if deleted. - */ -function applyFix(line, fixInfo, lineEnding = "\n") { - const { editColumn, deleteCount, insertText } = normalizeFixInfo(fixInfo); - const editIndex = editColumn - 1; - return (deleteCount === -1) ? - null : - line.slice(0, editIndex) + insertText.replace(/\n/g, lineEnding) + line.slice(editIndex + deleteCount); -} - -/** - * Applies as many of the specified fixes as possible to Markdown content. - * - * @param {string} input Lines of Markdown content. - * @param {RuleOnErrorInfo[]} errors RuleOnErrorInfo instances. - * @returns {string} Fixed content. - */ -function applyFixes(input, errors) { - const lineEnding = helpers.getPreferredLineEnding(input, __webpack_require__(/*! node:os */ "?e6c4")); - const lines = input.split(helpers.newLineRe); - // Normalize fixInfo objects - let fixInfos = errors - .filter((error) => error.fixInfo) - // @ts-ignore - .map((error) => normalizeFixInfo(error.fixInfo, error.lineNumber)); - // Sort bottom-to-top, line-deletes last, right-to-left, long-to-short - fixInfos.sort((a, b) => { - const aDeletingLine = (a.deleteCount === -1); - const bDeletingLine = (b.deleteCount === -1); - return ( - (b.lineNumber - a.lineNumber) || - (aDeletingLine ? 1 : (bDeletingLine ? -1 : 0)) || - (b.editColumn - a.editColumn) || - (b.insertText.length - a.insertText.length) - ); - }); - // Remove duplicate entries (needed for following collapse step) - // eslint-disable-next-line jsdoc/valid-types - /** @type RuleOnErrorFixInfo */ - let lastFixInfo = {}; - fixInfos = fixInfos.filter((fixInfo) => { - const unique = ( - (fixInfo.lineNumber !== lastFixInfo.lineNumber) || - (fixInfo.editColumn !== lastFixInfo.editColumn) || - (fixInfo.deleteCount !== lastFixInfo.deleteCount) || - (fixInfo.insertText !== lastFixInfo.insertText) - ); - lastFixInfo = fixInfo; - return unique; - }); - // Collapse insert/no-delete and no-insert/delete for same line/column - lastFixInfo = { - "lineNumber": -1 - }; - for (const fixInfo of fixInfos) { - if ( - (fixInfo.lineNumber === lastFixInfo.lineNumber) && - (fixInfo.editColumn === lastFixInfo.editColumn) && - !fixInfo.insertText && - (fixInfo.deleteCount > 0) && - lastFixInfo.insertText && - !lastFixInfo.deleteCount) { - fixInfo.insertText = lastFixInfo.insertText; - lastFixInfo.lineNumber = 0; - } - lastFixInfo = fixInfo; - } - fixInfos = fixInfos.filter((fixInfo) => fixInfo.lineNumber); - // Apply all (remaining/updated) fixes - let lastLineIndex = -1; - let lastEditIndex = -1; - for (const fixInfo of fixInfos) { - const { lineNumber, editColumn, deleteCount } = fixInfo; - const lineIndex = lineNumber - 1; - const editIndex = editColumn - 1; - if ( - (lineIndex !== lastLineIndex) || - (deleteCount === -1) || - ((editIndex + deleteCount) <= - (lastEditIndex - ((deleteCount > 0) ? 0 : 1))) - ) { - // @ts-ignore - lines[lineIndex] = applyFix(lines[lineIndex], fixInfo, lineEnding); - } - lastLineIndex = lineIndex; - lastEditIndex = editIndex; - } - // Return corrected input - return lines.filter((line) => line !== null).join(lineEnding); -} - -/** - * Gets the (semantic) version of the library. - * - * @returns {string} SemVer string. - */ -function getVersion() { - return version; -} - -// Export a/synchronous/Promise APIs -markdownlint.sync = markdownlintSync; -markdownlint.readConfig = readConfig; -markdownlint.readConfigSync = readConfigSync; -markdownlint.getVersion = getVersion; -markdownlint.promises = { - "markdownlint": markdownlintPromise, - "extendConfig": extendConfigPromise, - "readConfig": readConfigPromise -}; -markdownlint.applyFix = applyFix; -markdownlint.applyFixes = applyFixes; -module.exports = markdownlint; - -// Type declarations - -/** - * Function to implement rule logic. - * - * @callback RuleFunction - * @param {RuleParams} params Rule parameters. - * @param {RuleOnError} onError Error-reporting callback. - * @returns {void} - */ - -/* eslint-disable jsdoc/valid-types */ - -/** - * Rule parameters. - * - * @typedef {Object} RuleParams - * @property {string} name File/string name. - * @property {MarkdownParsers} parsers Markdown parser data. - * @property {readonly string[]} lines File/string lines. - * @property {readonly string[]} frontMatterLines Front matter lines. - * @property {RuleConfiguration} config Rule configuration. - * @property {string} version Version of the markdownlint library. - */ - -/* eslint-enable jsdoc/valid-types */ - -/** - * Markdown parser data. - * - * @typedef {Object} MarkdownParsers - * @property {ParserMarkdownIt} markdownit Markdown parser data from markdown-it (only present when Rule.parser is "markdownit"). - * @property {ParserMicromark} micromark Markdown parser data from micromark (only present when Rule.parser is "micromark"). - */ - -/** - * Markdown parser data from markdown-it. - * - * @typedef {Object} ParserMarkdownIt - * @property {MarkdownItToken[]} tokens Token objects from markdown-it. - */ - -/** - * Markdown parser data from micromark. - * - * @typedef {Object} ParserMicromark - * @property {MicromarkToken[]} tokens Token objects from micromark. - */ - -/** - * markdown-it token. - * - * @typedef {Object} MarkdownItToken - * @property {string[][]} attrs HTML attributes. - * @property {boolean} block Block-level token. - * @property {MarkdownItToken[]} children Child nodes. - * @property {string} content Tag contents. - * @property {boolean} hidden Ignore element. - * @property {string} info Fence info. - * @property {number} level Nesting level. - * @property {number[]} map Beginning/ending line numbers. - * @property {string} markup Markup text. - * @property {Object} meta Arbitrary data. - * @property {number} nesting Level change. - * @property {string} tag HTML tag name. - * @property {string} type Token type. - * @property {number} lineNumber Line number (1-based). - * @property {string} line Line content. - */ - -/** @typedef {import("markdownlint-micromark").TokenType} MicromarkTokenType */ - -/** - * micromark token. - * - * @typedef {Object} MicromarkToken - * @property {MicromarkTokenType} type Token type. - * @property {number} startLine Start line (1-based). - * @property {number} startColumn Start column (1-based). - * @property {number} endLine End line (1-based). - * @property {number} endColumn End column (1-based). - * @property {string} text Token text. - * @property {MicromarkToken[]} children Child tokens. - * @property {MicromarkToken | null} parent Parent token. - */ - -/** - * Error-reporting callback. - * - * @callback RuleOnError - * @param {RuleOnErrorInfo} onErrorInfo Error information. - * @returns {void} - */ - -/** - * Fix information for RuleOnError callback. - * - * @typedef {Object} RuleOnErrorInfo - * @property {number} lineNumber Line number (1-based). - * @property {string} [detail] Detail about the error. - * @property {string} [context] Context for the error. - * @property {URL} [information] Link to more information. - * @property {number[]} [range] Column number (1-based) and length. - * @property {RuleOnErrorFixInfo} [fixInfo] Fix information. - */ - -/** - * Fix information for RuleOnErrorInfo. - * - * @typedef {Object} RuleOnErrorFixInfo - * @property {number} [lineNumber] Line number (1-based). - * @property {number} [editColumn] Column of the fix (1-based). - * @property {number} [deleteCount] Count of characters to delete. - * @property {string} [insertText] Text to insert (after deleting). - */ - -/** - * RuleOnErrorInfo with all optional properties present. - * - * @typedef {Object} RuleOnErrorFixInfoNormalized - * @property {number} lineNumber Line number (1-based). - * @property {number} editColumn Column of the fix (1-based). - * @property {number} deleteCount Count of characters to delete. - * @property {string} insertText Text to insert (after deleting). - */ - -/** - * Rule definition. - * - * @typedef {Object} Rule - * @property {string[]} names Rule name(s). - * @property {string} description Rule description. - * @property {URL} [information] Link to more information. - * @property {string[]} tags Rule tag(s). - * @property {"markdownit" | "micromark" | "none"} parser Parser used. - * @property {boolean} [asynchronous] True if asynchronous. - * @property {RuleFunction} function Rule implementation. - */ - -/** - * Configuration options. - * - * @typedef {Object} Options - * @property {Configuration} [config] Configuration object. - * @property {ConfigurationParser[]} [configParsers] Configuration parsers. - * @property {Rule[] | Rule} [customRules] Custom rules. - * @property {string[] | string} [files] Files to lint. - * @property {RegExp | null} [frontMatter] Front matter pattern. - * @property {Object} [fs] File system implementation. - * @property {boolean} [handleRuleFailures] True to catch exceptions. - * @property {Plugin[]} [markdownItPlugins] Additional plugins. - * @property {boolean} [noInlineConfig] True to ignore HTML directives. - * @property {number} [resultVersion] Results object version. - * @property {Object.} [strings] Strings to lint. - */ - -/** - * A markdown-it plugin. - * - * @typedef {Array} Plugin - */ - -/** - * Function to pretty-print lint results. - * - * @callback ToStringCallback - * @param {boolean} [ruleAliases] True to use rule aliases. - * @returns {string} - */ - -/** - * Lint results (for resultVersion 3). - * - * @typedef {Object.} LintResults - * @property {ToStringCallback} toString String representation. - */ - -/** - * Lint error. - * - * @typedef {Object} LintError - * @property {number} lineNumber Line number (1-based). - * @property {string[]} ruleNames Rule name(s). - * @property {string} ruleDescription Rule description. - * @property {string} ruleInformation Link to more information. - * @property {string} errorDetail Detail about the error. - * @property {string} errorContext Context for the error. - * @property {number[]} errorRange Column number (1-based) and length. - * @property {FixInfo} [fixInfo] Fix information. - */ - -/** - * Fix information. - * - * @typedef {Object} FixInfo - * @property {number} [lineNumber] Line number (1-based). - * @property {number} [editColumn] Column of the fix (1-based). - * @property {number} [deleteCount] Count of characters to delete. - * @property {string} [insertText] Text to insert (after deleting). - */ - -/** - * Called with the result of linting a string or document. - * - * @callback LintContentCallback - * @param {Error | null} error Error iff failed. - * @param {LintError[]} [result] Result iff successful. - * @returns {void} - */ - -/** - * Called with the result of the lint function. - * - * @callback LintCallback - * @param {Error | null} error Error object iff failed. - * @param {LintResults} [results] Lint results iff succeeded. - * @returns {void} - */ - -/** - * Configuration object for linting rules. For the JSON schema, see - * {@link ../schema/markdownlint-config-schema.json}. - * - * @typedef {import("./configuration").Configuration} Configuration - */ - -/** - * Configuration object for linting rules strictly. For the JSON schema, see - * {@link ../schema/markdownlint-config-schema-strict.json}. - * - * @typedef {import("./configuration-strict").ConfigurationStrict} ConfigurationStrict - */ - -/** - * Rule configuration object. - * - * @typedef {boolean | Object} RuleConfiguration Rule configuration. - */ - -/** - * Parses a configuration string and returns a configuration object. - * - * @callback ConfigurationParser - * @param {string} text Configuration string. - * @returns {Configuration} - */ - -/** - * Called with the result of the readConfig function. - * - * @callback ReadConfigCallback - * @param {Error | null} err Error object or null. - * @param {Configuration} [config] Configuration object. - * @returns {void} - */ - -/** - * Called with the result of the resolveConfigExtends function. - * - * @callback ResolveConfigExtendsCallback - * @param {Error | null} err Error object or null. - * @param {string} [path] Resolved path to file. - * @returns {void} - */ - - -/***/ }), - -/***/ "../lib/md001.js": -/*!***********************!*\ - !*** ../lib/md001.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD001", "heading-increment" ], - "description": "Heading levels should only increment by one level at a time", - "tags": [ "headings" ], - "parser": "micromark", - "function": function MD001(params, onError) { - let prevLevel = Number.MAX_SAFE_INTEGER; - for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) { - const level = getHeadingLevel(heading); - if (level > prevLevel) { - addErrorDetailIf( - onError, - heading.startLine, - `h${prevLevel + 1}`, - `h${level}` - ); - } - prevLevel = level; - } - } -}; - - -/***/ }), - -/***/ "../lib/md003.js": -/*!***********************!*\ - !*** ../lib/md003.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getHeadingLevel, getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD003", "heading-style" ], - "description": "Heading style", - "tags": [ "headings" ], - "parser": "micromark", - "function": function MD003(params, onError) { - let style = String(params.config.style || "consistent"); - for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) { - const styleForToken = getHeadingStyle(heading); - if (style === "consistent") { - style = styleForToken; - } - if (styleForToken !== style) { - const h12 = getHeadingLevel(heading) <= 2; - const setextWithAtx = - (style === "setext_with_atx") && - ((h12 && (styleForToken === "setext")) || - (!h12 && (styleForToken === "atx"))); - const setextWithAtxClosed = - (style === "setext_with_atx_closed") && - ((h12 && (styleForToken === "setext")) || - (!h12 && (styleForToken === "atx_closed"))); - if (!setextWithAtx && !setextWithAtxClosed) { - let expected = style; - if (style === "setext_with_atx") { - expected = h12 ? "setext" : "atx"; - } else if (style === "setext_with_atx_closed") { - expected = h12 ? "setext" : "atx_closed"; - } - addErrorDetailIf( - onError, - heading.startLine, - expected, - styleForToken - ); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md004.js": -/*!***********************!*\ - !*** ../lib/md004.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType, getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const markerToStyle = { - "-": "dash", - "+": "plus", - "*": "asterisk" -}; -const styleToMarker = { - "dash": "-", - "plus": "+", - "asterisk": "*" -}; -const differentItemStyle = { - "dash": "plus", - "plus": "asterisk", - "asterisk": "dash" -}; -const validStyles = new Set([ - "asterisk", - "consistent", - "dash", - "plus", - "sublist" -]); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD004", "ul-style" ], - "description": "Unordered list style", - "tags": [ "bullet", "ul" ], - "parser": "micromark", - "function": function MD004(params, onError) { - const style = String(params.config.style || "consistent"); - let expectedStyle = validStyles.has(style) ? style : "dash"; - const nestingStyles = []; - for (const listUnordered of filterByTypesCached([ "listUnordered" ])) { - let nesting = 0; - if (style === "sublist") { - /** @type {import("../helpers/micromark-helpers.cjs").Token | null} */ - let parent = listUnordered; - // @ts-ignore - while ((parent = getParentOfType(parent, [ "listOrdered", "listUnordered" ]))) { - nesting++; - } - } - const listItemMarkers = getDescendantsByType(listUnordered, [ "listItemPrefix", "listItemMarker" ]); - for (const listItemMarker of listItemMarkers) { - const itemStyle = markerToStyle[listItemMarker.text]; - if (style === "sublist") { - if (!nestingStyles[nesting]) { - nestingStyles[nesting] = - (itemStyle === nestingStyles[nesting - 1]) ? - differentItemStyle[itemStyle] : - itemStyle; - } - expectedStyle = nestingStyles[nesting]; - } else if (expectedStyle === "consistent") { - expectedStyle = itemStyle; - } - const column = listItemMarker.startColumn; - const length = listItemMarker.endColumn - listItemMarker.startColumn; - addErrorDetailIf( - onError, - listItemMarker.startLine, - expectedStyle, - itemStyle, - undefined, - undefined, - [ column, length ], - { - "editColumn": column, - "deleteCount": length, - "insertText": styleToMarker[expectedStyle] - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md005.js": -/*!***********************!*\ - !*** ../lib/md005.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD005", "list-indent" ], - "description": "Inconsistent indentation for list items at the same level", - "tags": [ "bullet", "ul", "indentation" ], - "parser": "micromark", - "function": function MD005(params, onError) { - for (const list of filterByTypesCached([ "listOrdered", "listUnordered" ])) { - const expectedIndent = list.startColumn - 1; - let expectedEnd = 0; - let endMatching = false; - const listItemPrefixes = - list.children.filter((token) => (token.type === "listItemPrefix")); - for (const listItemPrefix of listItemPrefixes) { - const lineNumber = listItemPrefix.startLine; - const actualIndent = listItemPrefix.startColumn - 1; - const range = [ 1, listItemPrefix.endColumn - 1 ]; - if (list.type === "listUnordered") { - addErrorDetailIf( - onError, - lineNumber, - expectedIndent, - actualIndent, - undefined, - undefined, - range - // No fixInfo; MD007 handles this scenario better - ); - } else { - const markerLength = listItemPrefix.text.trim().length; - const actualEnd = listItemPrefix.startColumn + markerLength - 1; - expectedEnd = expectedEnd || actualEnd; - if ((expectedIndent !== actualIndent) || endMatching) { - if (expectedEnd === actualEnd) { - endMatching = true; - } else { - const detail = endMatching ? - `Expected: (${expectedEnd}); Actual: (${actualEnd})` : - `Expected: ${expectedIndent}; Actual: ${actualIndent}`; - const expected = endMatching ? - expectedEnd - markerLength : - expectedIndent; - const actual = endMatching ? - actualEnd - markerLength : - actualIndent; - addError( - onError, - lineNumber, - detail, - undefined, - range, - { - "editColumn": Math.min(actual, expected) + 1, - "deleteCount": Math.max(actual - expected, 0), - "insertText": "".padEnd(Math.max(expected - actual, 0)) - } - ); - } - } - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md007.js": -/*!***********************!*\ - !*** ../lib/md007.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("markdownlint-micromark").TokenType[] */ -const unorderedListTypes = - [ "blockQuotePrefix", "listItemPrefix", "listUnordered" ]; -// eslint-disable-next-line jsdoc/valid-types -/** @type import("markdownlint-micromark").TokenType[] */ -const unorderedParentTypes = - [ "blockQuote", "listOrdered", "listUnordered" ]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD007", "ul-indent" ], - "description": "Unordered list indentation", - "tags": [ "bullet", "ul", "indentation" ], - "parser": "micromark", - "function": function MD007(params, onError) { - const indent = Number(params.config.indent || 2); - const startIndented = !!params.config.start_indented; - const startIndent = Number(params.config.start_indent || indent); - const unorderedListNesting = new Map(); - let lastBlockQuotePrefix = null; - const tokens = filterByTypesCached(unorderedListTypes); - for (const token of tokens) { - const { endColumn, parent, startColumn, startLine, type } = token; - if (type === "blockQuotePrefix") { - lastBlockQuotePrefix = token; - } else if (type === "listUnordered") { - let nesting = 0; - /** @type {import("../helpers/micromark-helpers.cjs").Token | null} */ - let current = token; - while ( - // @ts-ignore - (current = getParentOfType(current, unorderedParentTypes)) - ) { - if (current.type === "listUnordered") { - nesting++; - // eslint-disable-next-line no-continue - continue; - } else if (current.type === "listOrdered") { - nesting = -1; - } - break; - } - if (nesting >= 0) { - unorderedListNesting.set(token, nesting); - } - } else { - // listItemPrefix - const nesting = unorderedListNesting.get(parent); - if (nesting !== undefined) { - // listItemPrefix for listUnordered - const expectedIndent = - (startIndented ? startIndent : 0) + (nesting * indent); - const blockQuoteAdjustment = - (lastBlockQuotePrefix?.endLine === startLine) ? - (lastBlockQuotePrefix.endColumn - 1) : - 0; - const actualIndent = startColumn - 1 - blockQuoteAdjustment; - const range = [ 1, endColumn - 1 ]; - const fixInfo = { - "editColumn": startColumn - actualIndent, - "deleteCount": Math.max(actualIndent - expectedIndent, 0), - "insertText": "".padEnd(Math.max(expectedIndent - actualIndent, 0)) - }; - addErrorDetailIf( - onError, - startLine, - expectedIndent, - actualIndent, - undefined, - undefined, - range, - fixInfo - ); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md009.js": -/*!***********************!*\ - !*** ../lib/md009.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD009", "no-trailing-spaces" ], - "description": "Trailing spaces", - "tags": [ "whitespace" ], - "parser": "micromark", - "function": function MD009(params, onError) { - let brSpaces = params.config.br_spaces; - brSpaces = Number((brSpaces === undefined) ? 2 : brSpaces); - const listItemEmptyLines = !!params.config.list_item_empty_lines; - const strict = !!params.config.strict; - const codeBlockLineNumbers = new Set(); - for (const codeBlock of filterByTypesCached([ "codeFenced" ])) { - addRangeToSet(codeBlockLineNumbers, codeBlock.startLine + 1, codeBlock.endLine - 1); - } - for (const codeBlock of filterByTypesCached([ "codeIndented" ])) { - addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine); - } - const listItemLineNumbers = new Set(); - if (listItemEmptyLines) { - for (const listBlock of filterByTypesCached([ "listOrdered", "listUnordered" ])) { - addRangeToSet(listItemLineNumbers, listBlock.startLine, listBlock.endLine); - let trailingIndent = true; - for (let i = listBlock.children.length - 1; i >= 0; i--) { - const child = listBlock.children[i]; - switch (child.type) { - case "content": - trailingIndent = false; - break; - case "listItemIndent": - if (trailingIndent) { - listItemLineNumbers.delete(child.startLine); - } - break; - case "listItemPrefix": - trailingIndent = true; - break; - default: - break; - } - } - } - } - const paragraphLineNumbers = new Set(); - const codeInlineLineNumbers = new Set(); - if (strict) { - for (const paragraph of filterByTypesCached([ "paragraph" ])) { - addRangeToSet(paragraphLineNumbers, paragraph.startLine, paragraph.endLine - 1); - } - for (const codeText of filterByTypesCached([ "codeText" ])) { - addRangeToSet(codeInlineLineNumbers, codeText.startLine, codeText.endLine - 1); - } - } - const expected = (brSpaces < 2) ? 0 : brSpaces; - for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) { - const line = params.lines[lineIndex]; - const lineNumber = lineIndex + 1; - const trailingSpaces = line.length - line.trimEnd().length; - if ( - trailingSpaces && - !codeBlockLineNumbers.has(lineNumber) && - !listItemLineNumbers.has(lineNumber) && - ( - (expected !== trailingSpaces) || - (strict && - (!paragraphLineNumbers.has(lineNumber) || - codeInlineLineNumbers.has(lineNumber))) - ) - ) { - const column = line.length - trailingSpaces + 1; - addError( - onError, - lineNumber, - "Expected: " + (expected === 0 ? "" : "0 or ") + - expected + "; Actual: " + trailingSpaces, - undefined, - [ column, trailingSpaces ], - { - "editColumn": column, - "deleteCount": trailingSpaces - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md010.js": -/*!***********************!*\ - !*** ../lib/md010.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, hasOverlap } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const tabRe = /\t+/g; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD010", "no-hard-tabs" ], - "description": "Hard tabs", - "tags": [ "whitespace", "hard_tab" ], - "parser": "micromark", - "function": function MD010(params, onError) { - const codeBlocks = params.config.code_blocks; - const includeCode = (codeBlocks === undefined) ? true : !!codeBlocks; - const ignoreCodeLanguages = new Set( - (params.config.ignore_code_languages || []) - .map((language) => language.toLowerCase()) - ); - const spacesPerTab = params.config.spaces_per_tab; - const spaceMultiplier = (spacesPerTab === undefined) ? - 1 : - Math.max(0, Number(spacesPerTab)); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../helpers/micromark-helpers.cjs").TokenType[] */ - const exclusionTypes = []; - if (includeCode) { - if (ignoreCodeLanguages.size > 0) { - exclusionTypes.push("codeFenced"); - } - } else { - exclusionTypes.push("codeFenced", "codeIndented", "codeText"); - } - const codeTokens = filterByTypesCached(exclusionTypes).filter((token) => { - if ((token.type === "codeFenced") && (ignoreCodeLanguages.size > 0)) { - const fenceInfos = getDescendantsByType(token, [ "codeFencedFence", "codeFencedFenceInfo" ]); - return fenceInfos.every((fenceInfo) => ignoreCodeLanguages.has(fenceInfo.text.toLowerCase())); - } - return true; - }); - const codeRanges = codeTokens.map((token) => { - const { type, startLine, startColumn, endLine, endColumn } = token; - const codeFenced = (type === "codeFenced"); - return { - "startLine": startLine + (codeFenced ? 1 : 0), - "startColumn": codeFenced ? 0 : startColumn, - "endLine": endLine - (codeFenced ? 1 : 0), - "endColumn": codeFenced ? Number.MAX_SAFE_INTEGER : endColumn - }; - }); - for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) { - const line = params.lines[lineIndex]; - let match = null; - while ((match = tabRe.exec(line)) !== null) { - const lineNumber = lineIndex + 1; - const column = match.index + 1; - const length = match[0].length; - /** @type {import("../helpers").FileRange} */ - const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 }; - if (!codeRanges.some((codeRange) => hasOverlap(codeRange, range))) { - addError( - onError, - lineNumber, - "Column: " + column, - undefined, - [ column, length ], - { - "editColumn": column, - "deleteCount": length, - "insertText": "".padEnd(length * spaceMultiplier) - } - ); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md011.js": -/*!***********************!*\ - !*** ../lib/md011.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, hasOverlap } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const reversedLinkRe = - /(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD011", "no-reversed-links" ], - "description": "Reversed link syntax", - "tags": [ "links" ], - "parser": "micromark", - "function": function MD011(params, onError) { - const codeBlockLineNumbers = new Set(); - for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) { - addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine); - } - const codeTexts = filterByTypesCached([ "codeText" ]); - for (const [ lineIndex, line ] of params.lines.entries()) { - const lineNumber = lineIndex + 1; - if (!codeBlockLineNumbers.has(lineNumber)) { - let match = null; - while ((match = reversedLinkRe.exec(line)) !== null) { - const [ reversedLink, preChar, linkText, linkDestination ] = match; - if ( - !linkText.endsWith("\\") && - !linkDestination.endsWith("\\") - ) { - const column = match.index + preChar.length + 1; - const length = match[0].length - preChar.length; - /** @type {import("../helpers").FileRange} */ - const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 }; - if (!codeTexts.some((codeText) => hasOverlap(codeText, range))) { - addError( - onError, - lineNumber, - reversedLink.slice(preChar.length), - undefined, - [ column, length ], - { - "editColumn": column, - "deleteCount": length, - "insertText": `[${linkText}](${linkDestination})` - } - ); - } - } - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md012.js": -/*!***********************!*\ - !*** ../lib/md012.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD012", "no-multiple-blanks" ], - "description": "Multiple consecutive blank lines", - "tags": [ "whitespace", "blank_lines" ], - "parser": "micromark", - "function": function MD012(params, onError) { - const maximum = Number(params.config.maximum || 1); - const { lines } = params; - const codeBlockLineNumbers = new Set(); - for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) { - addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine); - } - let count = 0; - for (const [ lineIndex, line ] of lines.entries()) { - const inCode = codeBlockLineNumbers.has(lineIndex + 1); - count = (inCode || (line.trim().length > 0)) ? 0 : count + 1; - if (maximum < count) { - addErrorDetailIf( - onError, - lineIndex + 1, - maximum, - count, - undefined, - undefined, - undefined, - { - "deleteCount": -1 - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md013.js": -/*!***********************!*\ - !*** ../lib/md013.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getReferenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); -const { addRangeToSet, getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const longLineRePrefix = "^.{"; -const longLineRePostfixRelaxed = "}.*\\s.*$"; -const longLineRePostfixStrict = "}.+$"; -const sternModeRe = /^(?:[#>\s]*\s)?\S*$/; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD013", "line-length" ], - "description": "Line length", - "tags": [ "line_length" ], - "parser": "micromark", - "function": function MD013(params, onError) { - const lineLength = Number(params.config.line_length || 80); - const headingLineLength = - Number(params.config.heading_line_length || lineLength); - const codeLineLength = - Number(params.config.code_block_line_length || lineLength); - const strict = !!params.config.strict; - const stern = !!params.config.stern; - const longLineRePostfix = - (strict || stern) ? longLineRePostfixStrict : longLineRePostfixRelaxed; - const longLineRe = - new RegExp(longLineRePrefix + lineLength + longLineRePostfix); - const longHeadingLineRe = - new RegExp(longLineRePrefix + headingLineLength + longLineRePostfix); - const longCodeLineRe = - new RegExp(longLineRePrefix + codeLineLength + longLineRePostfix); - const codeBlocks = params.config.code_blocks; - const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks; - const tables = params.config.tables; - const includeTables = (tables === undefined) ? true : !!tables; - const headings = params.config.headings; - const includeHeadings = (headings === undefined) ? true : !!headings; - const headingLineNumbers = new Set(); - for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) { - addRangeToSet(headingLineNumbers, heading.startLine, heading.endLine); - } - const codeBlockLineNumbers = new Set(); - for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) { - addRangeToSet(codeBlockLineNumbers, codeBlock.startLine, codeBlock.endLine); - } - const tableLineNumbers = new Set(); - for (const table of filterByTypesCached([ "table" ])) { - addRangeToSet(tableLineNumbers, table.startLine, table.endLine); - } - const linkLineNumbers = new Set(); - for (const link of filterByTypesCached([ "autolink", "image", "link", "literalAutolink" ])) { - addRangeToSet(linkLineNumbers, link.startLine, link.endLine); - } - const paragraphDataLineNumbers = new Set(); - for (const paragraph of filterByTypesCached([ "paragraph" ])) { - for (const data of getDescendantsByType(paragraph, [ "data" ])) { - addRangeToSet(paragraphDataLineNumbers, data.startLine, data.endLine); - } - } - const linkOnlyLineNumbers = new Set(); - for (const lineNumber of linkLineNumbers) { - if (!paragraphDataLineNumbers.has(lineNumber)) { - linkOnlyLineNumbers.add(lineNumber); - } - } - const definitionLineIndices = new Set(getReferenceLinkImageData().definitionLineIndices); - for (let lineIndex = 0; lineIndex < params.lines.length; lineIndex++) { - const line = params.lines[lineIndex]; - const lineNumber = lineIndex + 1; - const isHeading = headingLineNumbers.has(lineNumber); - const inCode = codeBlockLineNumbers.has(lineNumber); - const inTable = tableLineNumbers.has(lineNumber); - const length = inCode ? - codeLineLength : - (isHeading ? headingLineLength : lineLength); - const lengthRe = inCode ? - longCodeLineRe : - (isHeading ? longHeadingLineRe : longLineRe); - if ((includeCodeBlocks || !inCode) && - (includeTables || !inTable) && - (includeHeadings || !isHeading) && - !definitionLineIndices.has(lineIndex) && - (strict || - (!(stern && sternModeRe.test(line)) && - !linkOnlyLineNumbers.has(lineNumber))) && - lengthRe.test(line)) { - addErrorDetailIf( - onError, - lineNumber, - length, - line.length, - undefined, - undefined, - [ length + 1, line.length - length ] - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md014.js": -/*!***********************!*\ - !*** ../lib/md014.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const dollarCommandRe = /^(\s*)(\$\s+)/; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD014", "commands-show-output" ], - "description": "Dollar signs used before commands without showing output", - "tags": [ "code" ], - "parser": "micromark", - "function": function MD014(params, onError) { - for (const codeBlock of filterByTypesCached([ "codeFenced", "codeIndented" ])) { - const codeFlowValues = codeBlock.children.filter((child) => child.type === "codeFlowValue"); - const dollarMatches = codeFlowValues - .map((codeFlowValue) => ({ - "result": codeFlowValue.text.match(dollarCommandRe), - "startColumn": codeFlowValue.startColumn, - "startLine": codeFlowValue.startLine, - "text": codeFlowValue.text - })) - .filter((dollarMatch) => dollarMatch.result); - if (dollarMatches.length === codeFlowValues.length) { - for (const dollarMatch of dollarMatches) { - // @ts-ignore - const column = dollarMatch.startColumn + dollarMatch.result[1].length; - // @ts-ignore - const length = dollarMatch.result[2].length; - addErrorContext( - onError, - dollarMatch.startLine, - dollarMatch.text, - undefined, - undefined, - [ column, length ], - { - "editColumn": column, - "deleteCount": length - } - ); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md018.js": -/*!***********************!*\ - !*** ../lib/md018.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD018", "no-missing-space-atx" ], - "description": "No space after hash on atx style heading", - "tags": [ "headings", "atx", "spaces" ], - "parser": "micromark", - "function": function MD018(params, onError) { - const { lines } = params; - const ignoreBlockLineNumbers = new Set(); - for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow" ])) { - addRangeToSet(ignoreBlockLineNumbers, ignoreBlock.startLine, ignoreBlock.endLine); - } - for (const [ lineIndex, line ] of lines.entries()) { - if ( - !ignoreBlockLineNumbers.has(lineIndex + 1) && - /^#+[^# \t]/.test(line) && - !/#\s*$/.test(line) && - !line.startsWith("#️⃣") - ) { - // @ts-ignore - const hashCount = /^#+/.exec(line)[0].length; - addErrorContext( - onError, - lineIndex + 1, - line.trim(), - undefined, - undefined, - [ 1, hashCount + 1 ], - { - "editColumn": hashCount + 1, - "insertText": " " - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md019-md021.js": -/*!*****************************!*\ - !*** ../lib/md019-md021.js ***! - \*****************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers/helpers */ "../helpers/helpers.js"); -const { getHeadingStyle } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -/** - * Validate heading sequence and whitespace length at start or end. - * - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. - * @param {import("./markdownlint").MicromarkToken} heading ATX heading token. - * @param {number} delta Direction to scan. - * @returns {void} - */ -function validateHeadingSpaces(onError, heading, delta) { - const { children, startLine, text } = heading; - let index = (delta > 0) ? 0 : (children.length - 1); - while ( - children[index] && - (children[index].type !== "atxHeadingSequence") - ) { - index += delta; - } - const headingSequence = children[index]; - const whitespace = children[index + delta]; - if ( - (headingSequence?.type === "atxHeadingSequence") && - (whitespace?.type === "whitespace") && - (whitespace.text.length > 1) - ) { - const column = whitespace.startColumn + 1; - const length = whitespace.endColumn - column; - addErrorContext( - onError, - startLine, - text.trim(), - delta > 0, - delta < 0, - [ column, length ], - { - "editColumn": column, - "deleteCount": length - } - ); - } -} - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule[] */ -module.exports = [ - { - "names": [ "MD019", "no-multiple-space-atx" ], - "description": "Multiple spaces after hash on atx style heading", - "tags": [ "headings", "atx", "spaces" ], - "parser": "micromark", - "function": function MD019(params, onError) { - const atxHeadings = filterByTypesCached([ "atxHeading" ]) - .filter((heading) => getHeadingStyle(heading) === "atx"); - for (const atxHeading of atxHeadings) { - validateHeadingSpaces(onError, atxHeading, 1); - } - } - }, - { - "names": [ "MD021", "no-multiple-space-closed-atx" ], - "description": "Multiple spaces inside hashes on closed atx style heading", - "tags": [ "headings", "atx_closed", "spaces" ], - "parser": "micromark", - "function": function MD021(params, onError) { - const atxClosedHeadings = filterByTypesCached([ "atxHeading" ]) - .filter((heading) => getHeadingStyle(heading) === "atx_closed"); - for (const atxClosedHeading of atxClosedHeadings) { - validateHeadingSpaces(onError, atxClosedHeading, 1); - validateHeadingSpaces(onError, atxClosedHeading, -1); - } - } - } -]; - - -/***/ }), - -/***/ "../lib/md020.js": -/*!***********************!*\ - !*** ../lib/md020.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { addRangeToSet } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD020", "no-missing-space-closed-atx" ], - "description": "No space inside hashes on closed atx style heading", - "tags": [ "headings", "atx_closed", "spaces" ], - "parser": "micromark", - "function": function MD020(params, onError) { - const { lines } = params; - const ignoreBlockLineNumbers = new Set(); - for (const ignoreBlock of filterByTypesCached([ "codeFenced", "codeIndented", "htmlFlow" ])) { - addRangeToSet(ignoreBlockLineNumbers, ignoreBlock.startLine, ignoreBlock.endLine); - } - for (const [ lineIndex, line ] of lines.entries()) { - if (!ignoreBlockLineNumbers.has(lineIndex + 1)) { - const match = - /^(#+)([ \t]*)([^# \t\\]|[^# \t][^#]*?[^# \t\\])([ \t]*)((?:\\#)?)(#+)(\s*)$/.exec(line); - if (match) { - const [ - , - leftHash, - { "length": leftSpaceLength }, - content, - { "length": rightSpaceLength }, - rightEscape, - rightHash, - { "length": trailSpaceLength } - ] = match; - const leftHashLength = leftHash.length; - const rightHashLength = rightHash.length; - const left = !leftSpaceLength; - const right = !rightSpaceLength || !!rightEscape; - const rightEscapeReplacement = rightEscape ? `${rightEscape} ` : ""; - if (left || right) { - const range = left ? - [ - 1, - leftHashLength + 1 - ] : - [ - line.length - trailSpaceLength - rightHashLength, - rightHashLength + 1 - ]; - addErrorContext( - onError, - lineIndex + 1, - line.trim(), - left, - right, - range, - { - "editColumn": 1, - "deleteCount": line.length, - "insertText": - `${leftHash} ${content} ${rightEscapeReplacement}${rightHash}` - } - ); - } - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md022.js": -/*!***********************!*\ - !*** ../lib/md022.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getBlockQuotePrefixText, getHeadingLevel } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const defaultLines = 1; - -const getLinesFunction = (linesParam) => { - if (Array.isArray(linesParam)) { - const linesArray = new Array(6).fill(defaultLines); - for (const [ index, value ] of [ ...linesParam.entries() ].slice(0, 6)) { - linesArray[index] = value; - } - return (heading) => linesArray[getHeadingLevel(heading) - 1]; - } - // Coerce linesParam to a number - const lines = (linesParam === undefined) ? defaultLines : Number(linesParam); - return () => lines; -}; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD022", "blanks-around-headings" ], - "description": "Headings should be surrounded by blank lines", - "tags": [ "headings", "blank_lines" ], - "parser": "micromark", - "function": function MD022(params, onError) { - const getLinesAbove = getLinesFunction(params.config.lines_above); - const getLinesBelow = getLinesFunction(params.config.lines_below); - const { lines } = params; - const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]); - for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) { - const { startLine, endLine } = heading; - const line = lines[startLine - 1].trim(); - - // Check lines above - const linesAbove = getLinesAbove(heading); - if (linesAbove >= 0) { - let actualAbove = 0; - for ( - let i = 0; - (i < linesAbove) && isBlankLine(lines[startLine - 2 - i]); - i++ - ) { - actualAbove++; - } - addErrorDetailIf( - onError, - startLine, - linesAbove, - actualAbove, - "Above", - line, - undefined, - { - "insertText": getBlockQuotePrefixText( - blockQuotePrefixes, - startLine - 1, - linesAbove - actualAbove - ) - } - ); - } - - // Check lines below - const linesBelow = getLinesBelow(heading); - if (linesBelow >= 0) { - let actualBelow = 0; - for ( - let i = 0; - (i < linesBelow) && isBlankLine(lines[endLine + i]); - i++ - ) { - actualBelow++; - } - addErrorDetailIf( - onError, - startLine, - linesBelow, - actualBelow, - "Below", - line, - undefined, - { - "lineNumber": endLine + 1, - "insertText": getBlockQuotePrefixText( - blockQuotePrefixes, - endLine + 1, - linesBelow - actualBelow - ) - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md023.js": -/*!***********************!*\ - !*** ../lib/md023.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD023", "heading-start-left" ], - "description": "Headings must start at the beginning of the line", - "tags": [ "headings", "spaces" ], - "parser": "micromark", - "function": function MD023(params, onError) { - const headings = filterByTypesCached([ "atxHeading", "linePrefix", "setextHeading" ]); - for (let i = 0; i < headings.length - 1; i++) { - if ( - (headings[i].type === "linePrefix") && - (headings[i + 1].type !== "linePrefix") && - (headings[i].startLine === headings[i + 1].startLine) - ) { - const { endColumn, startColumn, startLine } = headings[i]; - const length = endColumn - startColumn; - addErrorContext( - onError, - startLine, - params.lines[startLine - 1], - true, - false, - [ startColumn, length ], - { - "editColumn": startColumn, - "deleteCount": length - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md024.js": -/*!***********************!*\ - !*** ../lib/md024.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD024", "no-duplicate-heading" ], - "description": "Multiple headings with the same content", - "tags": [ "headings" ], - "parser": "micromark", - "function": function MD024(params, onError) { - const siblingsOnly = !!params.config.siblings_only || false; - const knownContents = [ null, [] ]; - let lastLevel = 1; - let knownContent = knownContents[lastLevel]; - for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) { - const headingText = getHeadingText(heading); - if (siblingsOnly) { - const newLevel = getHeadingLevel(heading); - while (lastLevel < newLevel) { - lastLevel++; - knownContents[lastLevel] = []; - } - while (lastLevel > newLevel) { - knownContents[lastLevel] = []; - lastLevel--; - } - knownContent = knownContents[newLevel]; - } - // @ts-ignore - if (knownContent.includes(headingText)) { - addErrorContext( - onError, - heading.startLine, - headingText.trim() - ); - } else { - // @ts-ignore - knownContent.push(headingText); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md025.js": -/*!***********************!*\ - !*** ../lib/md025.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD025", "single-title", "single-h1" ], - "description": "Multiple top-level headings in the same document", - "tags": [ "headings" ], - "parser": "micromark", - "function": function MD025(params, onError) { - const level = Number(params.config.level || 1); - const foundFrontMatterTitle = - frontMatterHasTitle( - params.frontMatterLines, - params.config.front_matter_title - ); - let hasTopLevelHeading = false; - for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) { - const headingLevel = getHeadingLevel(heading); - if (headingLevel === level) { - if (hasTopLevelHeading || foundFrontMatterTitle) { - const headingText = getHeadingText(heading); - addErrorContext( - onError, - heading.startLine, - headingText - ); - } else if (heading.startLine === 1) { - hasTopLevelHeading = true; - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md026.js": -/*!***********************!*\ - !*** ../lib/md026.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, allPunctuationNoQuestion, endOfLineGemojiCodeRe, - endOfLineHtmlEntityRe, escapeForRegExp } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD026", "no-trailing-punctuation" ], - "description": "Trailing punctuation in heading", - "tags": [ "headings" ], - "parser": "micromark", - "function": function MD026(params, onError) { - let punctuation = params.config.punctuation; - punctuation = String( - (punctuation === undefined) ? allPunctuationNoQuestion : punctuation - ); - const trailingPunctuationRe = - new RegExp("\\s*[" + escapeForRegExp(punctuation) + "]+$"); - const headings = filterByTypesCached([ "atxHeadingText", "setextHeadingText" ]); - for (const heading of headings) { - const { endColumn, endLine, text } = heading; - const match = trailingPunctuationRe.exec(text); - if ( - match && - !endOfLineHtmlEntityRe.test(text) && - !endOfLineGemojiCodeRe.test(text) - ) { - const fullMatch = match[0]; - const length = fullMatch.length; - const column = endColumn - length; - addError( - onError, - endLine, - `Punctuation: '${fullMatch}'`, - undefined, - [ column, length ], - { - "editColumn": column, - "deleteCount": length - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md027.js": -/*!***********************!*\ - !*** ../lib/md027.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD027", "no-multiple-space-blockquote" ], - "description": "Multiple spaces after blockquote symbol", - "tags": [ "blockquote", "whitespace", "indentation" ], - "parser": "micromark", - "function": function MD027(params, onError) { - const { tokens } = params.parsers.micromark; - for (const token of filterByTypesCached([ "linePrefix" ])) { - const parent = token.parent; - const codeIndented = parent?.type === "codeIndented"; - const siblings = parent?.children || tokens; - if ( - !codeIndented && - (siblings[siblings.indexOf(token) - 1]?.type === "blockQuotePrefix") - ) { - const { startColumn, startLine, text } = token; - const { length } = text; - const line = params.lines[startLine - 1]; - addErrorContext( - onError, - startLine, - line, - undefined, - undefined, - [ startColumn, length ], - { - "editColumn": startColumn, - "deleteCount": length - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md028.js": -/*!***********************!*\ - !*** ../lib/md028.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const ignoreTypes = new Set([ "lineEnding", "listItemIndent", "linePrefix" ]); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD028", "no-blanks-blockquote" ], - "description": "Blank line inside blockquote", - "tags": [ "blockquote", "whitespace" ], - "parser": "micromark", - "function": function MD028(params, onError) { - for (const token of filterByTypesCached([ "blockQuote" ])) { - const errorLineNumbers = []; - const siblings = token.parent?.children || params.parsers.micromark.tokens; - for (let i = siblings.indexOf(token) + 1; i < siblings.length; i++) { - const sibling = siblings[i]; - const { startLine, type } = sibling; - if (type === "lineEndingBlank") { - // Possible blank between blockquotes - errorLineNumbers.push(startLine); - } else if (ignoreTypes.has(type)) { - // Ignore invisible formatting - } else if (type === "blockQuote") { - // Blockquote followed by blockquote - for (const lineNumber of errorLineNumbers) { - addError(onError, lineNumber); - } - break; - } else { - // Blockquote not followed by blockquote - break; - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md029.js": -/*!***********************!*\ - !*** ../lib/md029.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const listStyleExamples = { - "one": "1/1/1", - "ordered": "1/2/3", - "zero": "0/0/0" -}; - -/** - * Gets the value of an ordered list item prefix token. - * - * @param {import("../helpers/micromark-helpers.cjs").Token} listItemPrefix List item prefix token. - * @returns {number} List item value. - */ -function getOrderedListItemValue(listItemPrefix) { - return Number(getDescendantsByType(listItemPrefix, [ "listItemValue" ])[0].text); -} - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD029", "ol-prefix" ], - "description": "Ordered list item prefix", - "tags": [ "ol" ], - "parser": "micromark", - "function": function MD029(params, onError) { - const style = String(params.config.style || "one_or_ordered"); - for (const listOrdered of filterByTypesCached([ "listOrdered" ])) { - const listItemPrefixes = getDescendantsByType(listOrdered, [ "listItemPrefix" ]); - let expected = 1; - let incrementing = false; - // Check for incrementing number pattern 1/2/3 or 0/1/2 - if (listItemPrefixes.length >= 2) { - const firstValue = getOrderedListItemValue(listItemPrefixes[0]); - const secondValue = getOrderedListItemValue(listItemPrefixes[1]); - if ((secondValue !== 1) || (firstValue === 0)) { - incrementing = true; - if (firstValue === 0) { - expected = 0; - } - } - } - // Determine effective style - let listStyle = style; - if (listStyle === "one_or_ordered") { - listStyle = incrementing ? "ordered" : "one"; - } else if (listStyle === "zero") { - expected = 0; - } else if (listStyle === "one") { - expected = 1; - } - // Validate each list item marker - for (const listItemPrefix of listItemPrefixes) { - const actual = getOrderedListItemValue(listItemPrefix); - addErrorDetailIf( - onError, - listItemPrefix.startLine, - expected, - actual, - "Style: " + listStyleExamples[listStyle], - undefined, - [ listItemPrefix.startColumn, listItemPrefix.endColumn - listItemPrefix.startColumn ] - ); - if (listStyle === "ordered") { - expected++; - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md030.js": -/*!***********************!*\ - !*** ../lib/md030.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD030", "list-marker-space" ], - "description": "Spaces after list markers", - "tags": [ "ol", "ul", "whitespace" ], - "parser": "micromark", - "function": function MD030(params, onError) { - const ulSingle = Number(params.config.ul_single || 1); - const olSingle = Number(params.config.ol_single || 1); - const ulMulti = Number(params.config.ul_multi || 1); - const olMulti = Number(params.config.ol_multi || 1); - for (const list of filterByTypesCached([ "listOrdered", "listUnordered" ])) { - const ordered = (list.type === "listOrdered"); - const listItemPrefixes = - list.children.filter((token) => (token.type === "listItemPrefix")); - const allSingleLine = - (list.endLine - list.startLine + 1) === listItemPrefixes.length; - const expectedSpaces = ordered ? - (allSingleLine ? olSingle : olMulti) : - (allSingleLine ? ulSingle : ulMulti); - for (const listItemPrefix of listItemPrefixes) { - const range = [ - listItemPrefix.startColumn, - listItemPrefix.endColumn - listItemPrefix.startColumn - ]; - const listItemPrefixWhitespaces = listItemPrefix.children.filter( - (token) => (token.type === "listItemPrefixWhitespace") - ); - for (const listItemPrefixWhitespace of listItemPrefixWhitespaces) { - const { endColumn, startColumn, startLine } = - listItemPrefixWhitespace; - const actualSpaces = endColumn - startColumn; - const fixInfo = { - "editColumn": startColumn, - "deleteCount": actualSpaces, - "insertText": "".padEnd(expectedSpaces) - }; - addErrorDetailIf( - onError, - startLine, - expectedSpaces, - actualSpaces, - undefined, - undefined, - range, - fixInfo - ); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md031.js": -/*!***********************!*\ - !*** ../lib/md031.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const codeFencePrefixRe = /^(.*?)[`~]/; - -// eslint-disable-next-line jsdoc/valid-types -/** @typedef {readonly string[]} ReadonlyStringArray */ - -/** - * Adds an error for the top or bottom of a code fence. - * - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. - * @param {ReadonlyStringArray} lines Lines of Markdown content. - * @param {number} lineNumber Line number. - * @param {boolean} top True iff top fence. - * @returns {void} - */ -function addError(onError, lines, lineNumber, top) { - const line = lines[lineNumber - 1]; - const [ , prefix ] = line.match(codeFencePrefixRe) || []; - const fixInfo = (prefix === undefined) ? - null : - { - "lineNumber": lineNumber + (top ? 0 : 1), - "insertText": `${prefix.replace(/[^>]/g, " ").trim()}\n` - }; - addErrorContext( - onError, - lineNumber, - line.trim(), - undefined, - undefined, - undefined, - fixInfo - ); -} - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD031", "blanks-around-fences" ], - "description": "Fenced code blocks should be surrounded by blank lines", - "tags": [ "code", "blank_lines" ], - "parser": "micromark", - "function": function MD031(params, onError) { - const listItems = params.config.list_items; - const includeListItems = (listItems === undefined) ? true : !!listItems; - const { lines } = params; - for (const codeBlock of filterByTypesCached([ "codeFenced" ])) { - if (includeListItems || !(getParentOfType(codeBlock, [ "listOrdered", "listUnordered" ]))) { - if (!isBlankLine(lines[codeBlock.startLine - 2])) { - addError(onError, lines, codeBlock.startLine, true); - } - if (!isBlankLine(lines[codeBlock.endLine]) && !isBlankLine(lines[codeBlock.endLine - 1])) { - addError(onError, lines, codeBlock.endLine, false); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md032.js": -/*!***********************!*\ - !*** ../lib/md032.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByPredicate, getBlockQuotePrefixText, nonContentTokens } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const isList = (token) => ( - (token.type === "listOrdered") || (token.type === "listUnordered") -); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD032", "blanks-around-lists" ], - "description": "Lists should be surrounded by blank lines", - "tags": [ "bullet", "ul", "ol", "blank_lines" ], - "parser": "micromark", - "function": function MD032(params, onError) { - const { lines, parsers } = params; - const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]); - - // For every top-level list... - const topLevelLists = filterByPredicate( - parsers.micromark.tokens, - isList, - (token) => ( - (isList(token) || (token.type === "htmlFlow")) ? [] : token.children - ) - ); - for (const list of topLevelLists) { - - // Look for a blank line above the list - const firstLineNumber = list.startLine; - if (!isBlankLine(lines[firstLineNumber - 2])) { - addErrorContext( - onError, - firstLineNumber, - lines[firstLineNumber - 1].trim(), - undefined, - undefined, - undefined, - { - "insertText": getBlockQuotePrefixText(blockQuotePrefixes, firstLineNumber) - } - ); - } - - // Find the "visual" end of the list - let endLine = list.endLine; - const flattenedChildren = filterByPredicate(list.children); - for (const child of flattenedChildren.reverse()) { - if (!nonContentTokens.has(child.type)) { - endLine = child.endLine; - break; - } - } - - // Look for a blank line below the list - const lastLineNumber = endLine; - if (!isBlankLine(lines[lastLineNumber])) { - addErrorContext( - onError, - lastLineNumber, - lines[lastLineNumber - 1].trim(), - undefined, - undefined, - undefined, - { - "lineNumber": lastLineNumber + 1, - "insertText": getBlockQuotePrefixText(blockQuotePrefixes, lastLineNumber) - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md033.js": -/*!***********************!*\ - !*** ../lib/md033.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD033", "no-inline-html" ], - "description": "Inline HTML", - "tags": [ "html" ], - "parser": "micromark", - "function": function MD033(params, onError) { - let allowedElements = params.config.allowed_elements; - allowedElements = Array.isArray(allowedElements) ? allowedElements : []; - allowedElements = allowedElements.map((element) => element.toLowerCase()); - for (const token of filterByTypesCached([ "htmlText" ], true)) { - const htmlTagInfo = getHtmlTagInfo(token); - if ( - htmlTagInfo && - !htmlTagInfo.close && - !allowedElements.includes(htmlTagInfo.name.toLowerCase()) - ) { - const range = [ - token.startColumn, - token.text.replace(nextLinesRe, "").length - ]; - addError( - onError, - token.startLine, - "Element: " + htmlTagInfo.name, - undefined, - range - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md034.js": -/*!***********************!*\ - !*** ../lib/md034.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByPredicate, getHtmlTagInfo, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD034", "no-bare-urls" ], - "description": "Bare URL used", - "tags": [ "links", "url" ], - "parser": "micromark", - "function": function MD034(params, onError) { - const literalAutolinks = (tokens) => ( - filterByPredicate( - tokens, - (token) => { - if ((token.type === "literalAutolink") && !inHtmlFlow(token)) { - // Detect and ignore https://github.com/micromark/micromark/issues/164 - const siblings = token.parent?.children; - const index = siblings?.indexOf(token); - // @ts-ignore - const prev = siblings?.at(index - 1); - // @ts-ignore - const next = siblings?.at(index + 1); - return !( - prev && - next && - (prev.type === "data") && - (next.type === "data") && - prev.text.endsWith("<") && - next.text.startsWith(">") - ); - } - return false; - }, - (token) => { - // Ignore content of inline HTML tags - const { children } = token; - const result = []; - for (let i = 0; i < children.length; i++) { - const current = children[i]; - const openTagInfo = getHtmlTagInfo(current); - if (openTagInfo && !openTagInfo.close) { - let count = 1; - for (let j = i + 1; j < children.length; j++) { - const candidate = children[j]; - const closeTagInfo = getHtmlTagInfo(candidate); - if (closeTagInfo && (openTagInfo.name === closeTagInfo.name)) { - if (closeTagInfo.close) { - count--; - if (count === 0) { - i = j; - break; - } - } else { - count++; - } - } - } - } else { - result.push(current); - } - } - return result; - } - ) - ); - for (const token of literalAutolinks(params.parsers.micromark.tokens)) { - const range = [ - token.startColumn, - token.endColumn - token.startColumn - ]; - const fixInfo = { - "editColumn": range[0], - "deleteCount": range[1], - "insertText": `<${token.text}>` - }; - addErrorContext( - onError, - token.startLine, - token.text, - undefined, - undefined, - range, - fixInfo - ); - } - } -}; - - -/***/ }), - -/***/ "../lib/md035.js": -/*!***********************!*\ - !*** ../lib/md035.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD035", "hr-style" ], - "description": "Horizontal rule style", - "tags": [ "hr" ], - "parser": "micromark", - "function": function MD035(params, onError) { - let style = String(params.config.style || "consistent").trim(); - const thematicBreaks = filterByTypesCached([ "thematicBreak" ]); - for (const token of thematicBreaks) { - const { startLine, text } = token; - if (style === "consistent") { - style = text; - } - addErrorDetailIf(onError, startLine, style, text); - } - } -}; - - -/***/ }), - -/***/ "../lib/md036.js": -/*!***********************!*\ - !*** ../lib/md036.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, allPunctuation } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -/** @typedef {import("../helpers/micromark-helpers.cjs").TokenType} TokenType */ -/** @type {TokenType[][]} */ -const emphasisTypes = [ - [ "emphasis", "emphasisText" ], - [ "strong", "strongText" ] -]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD036", "no-emphasis-as-heading" ], - "description": "Emphasis used instead of a heading", - "tags": [ "headings", "emphasis" ], - "parser": "micromark", - "function": function MD036(params, onError) { - let punctuation = params.config.punctuation; - punctuation = String((punctuation === undefined) ? allPunctuation : punctuation); - const punctuationRe = new RegExp("[" + punctuation + "]$"); - const paragraphTokens = - filterByTypesCached([ "paragraph" ]) - .filter((token) => - (token.parent?.type === "content") && !token.parent?.parent && (token.children.length === 1) - ); - for (const emphasisType of emphasisTypes) { - const textTokens = getDescendantsByType(paragraphTokens, emphasisType); - for (const textToken of textTokens) { - if ( - (textToken.children.length === 1) && - (textToken.children[0].type === "data") && - !punctuationRe.test(textToken.text) - ) { - addErrorContext(onError, textToken.startLine, textToken.text); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md037.js": -/*!***********************!*\ - !*** ../lib/md037.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByPredicate, inHtmlFlow } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD037", "no-space-in-emphasis" ], - "description": "Spaces inside emphasis markers", - "tags": [ "whitespace", "emphasis" ], - "parser": "micromark", - "function": function MD037(params, onError) { - - // Initialize variables - const { lines, parsers } = params; - const emphasisTokensByMarker = new Map(); - for (const marker of [ "_", "__", "___", "*", "**", "***" ]) { - emphasisTokensByMarker.set(marker, []); - } - const tokens = filterByPredicate( - parsers.micromark.tokens, - (token) => token.children.some((child) => child.type === "data") - ); - for (const token of tokens) { - - // Build lists of bare tokens for each emphasis marker type - for (const emphasisTokens of emphasisTokensByMarker.values()) { - emphasisTokens.length = 0; - } - for (const child of token.children) { - const { text, type } = child; - if ((type === "data") && (text.length <= 3)) { - const emphasisTokens = emphasisTokensByMarker.get(text); - if (emphasisTokens && !inHtmlFlow(child)) { - emphasisTokens.push(child); - } - } - } - - // Process bare tokens for each emphasis marker type - for (const entry of emphasisTokensByMarker.entries()) { - const [ marker, emphasisTokens ] = entry; - for (let i = 0; i + 1 < emphasisTokens.length; i += 2) { - - // Process start token of start/end pair - const startToken = emphasisTokens[i]; - const startLine = lines[startToken.startLine - 1]; - const startSlice = startLine.slice(startToken.endColumn - 1); - const startMatch = startSlice.match(/^\s+\S/); - if (startMatch) { - const [ startSpaceCharacter ] = startMatch; - const startContext = `${marker}${startSpaceCharacter}`; - addError( - onError, - startToken.startLine, - undefined, - startContext, - [ startToken.startColumn, startContext.length ], - { - "editColumn": startToken.endColumn, - "deleteCount": startSpaceCharacter.length - 1 - } - ); - } - - // Process end token of start/end pair - const endToken = emphasisTokens[i + 1]; - const endLine = lines[endToken.startLine - 1]; - const endSlice = endLine.slice(0, endToken.startColumn - 1); - const endMatch = endSlice.match(/\S\s+$/); - if (endMatch) { - const [ endSpaceCharacter ] = endMatch; - const endContext = `${endSpaceCharacter}${marker}`; - addError( - onError, - endToken.startLine, - undefined, - endContext, - [ endToken.endColumn - endContext.length, endContext.length ], - { - "editColumn": - endToken.startColumn - (endSpaceCharacter.length - 1), - "deleteCount": endSpaceCharacter.length - 1 - } - ); - } - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md038.js": -/*!***********************!*\ - !*** ../lib/md038.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const leftSpaceRe = /^\s(?:[^`]|$)/; -const rightSpaceRe = /[^`]\s$/; -const trimCodeText = (text, start, end) => { - text = text.replace(/^\s+$/, ""); - if (start) { - text = text.replace(/^\s+?(\s`|\S)/, "$1"); - } - if (end) { - text = text.replace(/(`\s|\S)\s+$/, "$1"); - } - return text; -}; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD038", "no-space-in-code" ], - "description": "Spaces inside code span elements", - "tags": [ "whitespace", "code" ], - "parser": "micromark", - "function": function MD038(params, onError) { - const codeTexts = filterByTypesCached([ "codeText" ]); - for (const codeText of codeTexts) { - const sequences = getDescendantsByType(codeText, [ "codeTextSequence" ]); - const startSequence = sequences[0]; - const endSequence = sequences[sequences.length - 1]; - const datas = getDescendantsByType(codeText, [ "codeTextData" ]); - const startData = datas[0]; - const endData = datas[datas.length - 1]; - if (startSequence && endSequence && startData && endData) { - const spaceLeft = leftSpaceRe.test(startData.text); - const spaceRight = rightSpaceRe.test(endData.text); - if (spaceLeft || spaceRight) { - let lineNumber = startSequence.startLine; - let range = undefined; - let fixInfo = undefined; - if (startSequence.startLine === endSequence.endLine) { - range = [ - startSequence.startColumn, - endSequence.endColumn - startSequence.startColumn - ]; - fixInfo = { - "editColumn": startSequence.endColumn, - "deleteCount": endSequence.startColumn - startSequence.endColumn, - "insertText": trimCodeText(startData.text, true, true) - }; - } else if (spaceLeft && (startSequence.endLine === startData.startLine)) { - range = [ - startSequence.startColumn, - startData.endColumn - startSequence.startColumn - ]; - fixInfo = { - "editColumn": startSequence.endColumn, - "deleteCount": startData.endColumn - startData.startColumn, - "insertText": trimCodeText(startData.text, true, false) - }; - } else if (spaceRight && (endData.text.trim().length > 0)) { - lineNumber = endSequence.endLine; - range = [ - endData.startColumn, - endSequence.endColumn - endData.startColumn - ]; - fixInfo = { - "editColumn": endData.startColumn, - "deleteCount": endData.endColumn - endData.startColumn, - "insertText": trimCodeText(endData.text, false, true) - }; - } - if (range) { - const context = params - .lines[lineNumber - 1] - .substring(range[0] - 1, range[0] - 1 + range[1]); - addErrorContext( - onError, - lineNumber, - context, - spaceLeft, - spaceRight, - range, - fixInfo - ); - } - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md039.js": -/*!***********************!*\ - !*** ../lib/md039.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getReferenceLinkImageData, filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -/** - * Adds an error for a label space issue. - * - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. - * @param {import("../helpers/micromark-helpers.cjs").Token} label Label token. - * @param {import("../helpers/micromark-helpers.cjs").Token} labelText LabelText token. - * @param {boolean} isStart True iff error is at the start of the link. - */ -function addLabelSpaceError(onError, label, labelText, isStart) { - const match = labelText.text.match(isStart ? /^[^\S\r\n]+/ : /[^\S\r\n]+$/); - const range = match ? - [ - (isStart ? (labelText.startColumn) : (labelText.endColumn - match[0].length)), - match[0].length - ] : - undefined; - addErrorContext( - onError, - isStart ? (labelText.startLine + (match ? 0 : 1)) : (labelText.endLine - (match ? 0 : 1)), - label.text.replace(/\s+/g, " "), - isStart, - !isStart, - range, - range ? - { - "editColumn": range[0], - "deleteCount": range[1] - } : - undefined - ); -} - -/** - * Determines if a link is a valid link (and not a fake shortcut link due to parser tricks). - * - * @param {import("../helpers/micromark-helpers.cjs").Token} label Label token. - * @param {import("../helpers/micromark-helpers.cjs").Token} labelText LabelText token. - * @param {Map} definitions Map of link definitions. - * @returns {boolean} True iff the link is valid. - */ -function validLink(label, labelText, definitions) { - return (label.parent?.children.length !== 1) || definitions.has(labelText.text.trim()); -} - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD039", "no-space-in-links" ], - "description": "Spaces inside link text", - "tags": [ "whitespace", "links" ], - "parser": "micromark", - "function": function MD039(params, onError) { - const { definitions } = getReferenceLinkImageData(); - const labels = filterByTypesCached([ "label" ]) - .filter((label) => label.parent?.type === "link"); - for (const label of labels) { - const labelTexts = label.children.filter((child) => child.type === "labelText"); - for (const labelText of labelTexts) { - if ( - (labelText.text.trimStart().length !== labelText.text.length) && - validLink(label, labelText, definitions) - ) { - addLabelSpaceError(onError, label, labelText, true); - } - if ( - (labelText.text.trimEnd().length !== labelText.text.length) && - validLink(label, labelText, definitions) - ) { - addLabelSpaceError(onError, label, labelText, false); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md040.js": -/*!***********************!*\ - !*** ../lib/md040.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD040", "fenced-code-language" ], - "description": "Fenced code blocks should have a language specified", - "tags": [ "code", "language" ], - "parser": "micromark", - "function": function MD040(params, onError) { - let allowed = params.config.allowed_languages; - allowed = Array.isArray(allowed) ? allowed : []; - const languageOnly = !!params.config.language_only; - const fencedCodes = filterByTypesCached([ "codeFenced" ]); - for (const fencedCode of fencedCodes) { - const openingFence = getDescendantsByType(fencedCode, [ "codeFencedFence" ])[0]; - const { startLine, text } = openingFence; - const info = getDescendantsByType(openingFence, [ "codeFencedFenceInfo" ])[0]?.text; - if (!info) { - addErrorContext(onError, startLine, text); - } else if ((allowed.length > 0) && !allowed.includes(info)) { - addError(onError, startLine, `"${info}" is not allowed`); - } - if (languageOnly && getDescendantsByType(openingFence, [ "codeFencedFenceMeta" ]).length > 0) { - addError(onError, startLine, `Info string contains more than language: "${text}"`); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md041.js": -/*!***********************!*\ - !*** ../lib/md041.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, frontMatterHasTitle } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } = - __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD041", "first-line-heading", "first-line-h1" ], - "description": "First line in a file should be a top-level heading", - "tags": [ "headings" ], - "parser": "micromark", - "function": function MD041(params, onError) { - const level = Number(params.config.level || 1); - if (!frontMatterHasTitle(params.frontMatterLines, params.config.front_matter_title)) { - params.parsers.micromark.tokens - .filter((token) => !nonContentTokens.has(token.type) && !isHtmlFlowComment(token)) - .every((token) => { - let isError = true; - if ((token.type === "atxHeading") || (token.type === "setextHeading")) { - isError = (getHeadingLevel(token) !== level); - } else if (token.type === "htmlFlow") { - const htmlTexts = filterByTypes(token.children, [ "htmlText" ], true); - const tagInfo = (htmlTexts.length > 0) && getHtmlTagInfo(htmlTexts[0]); - isError = !tagInfo || (tagInfo.name.toLowerCase() !== `h${level}`); - } - if (isError) { - addErrorContext(onError, token.startLine, params.lines[token.startLine - 1]); - } - return false; - }); - } - } -}; - - -/***/ }), - -/***/ "../lib/md042.js": -/*!***********************!*\ - !*** ../lib/md042.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { getReferenceLinkImageData, filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD042", "no-empty-links" ], - "description": "No empty links", - "tags": [ "links" ], - "parser": "micromark", - "function": function MD042(params, onError) { - const { definitions } = getReferenceLinkImageData(); - const isReferenceDefinitionHash = (token) => { - const definition = definitions.get(token.text.trim()); - return (definition && (definition[1] === "#")); - }; - const links = filterByTypesCached([ "link" ]); - for (const link of links) { - const labelText = getDescendantsByType(link, [ "label", "labelText" ]); - const reference = getDescendantsByType(link, [ "reference" ]); - const resource = getDescendantsByType(link, [ "resource" ]); - const referenceString = getDescendantsByType(reference, [ "referenceString" ]); - const resourceDestinationString = getDescendantsByType(resource, [ "resourceDestination", [ "resourceDestinationLiteral", "resourceDestinationRaw" ], "resourceDestinationString" ]); - const hasLabelText = labelText.length > 0; - const hasReference = reference.length > 0; - const hasResource = resource.length > 0; - const hasReferenceString = referenceString.length > 0; - const hasResourceDestinationString = resourceDestinationString.length > 0; - let error = false; - if ( - hasLabelText && - ((!hasReference && !hasResource) || (hasReference && !hasReferenceString)) - ) { - error = isReferenceDefinitionHash(labelText[0]); - } else if (hasReferenceString && !hasResourceDestinationString) { - error = isReferenceDefinitionHash(referenceString[0]); - } else if (!hasReferenceString && hasResourceDestinationString) { - error = (resourceDestinationString[0].text.trim() === "#"); - } else if (!hasReferenceString && !hasResourceDestinationString) { - error = true; - } - if (error) { - addErrorContext( - onError, - link.startLine, - link.text, - undefined, - undefined, - [ link.startColumn, link.endColumn - link.startColumn ] - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md043.js": -/*!***********************!*\ - !*** ../lib/md043.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getHeadingLevel, getHeadingText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD043", "required-headings" ], - "description": "Required heading structure", - "tags": [ "headings" ], - "parser": "micromark", - "function": function MD043(params, onError) { - const requiredHeadings = params.config.headings; - if (!Array.isArray(requiredHeadings)) { - // Nothing to check; avoid doing any work - return; - } - const matchCase = params.config.match_case || false; - let i = 0; - let matchAny = false; - let hasError = false; - let anyHeadings = false; - const getExpected = () => requiredHeadings[i++] || "[None]"; - const handleCase = (str) => (matchCase ? str : str.toLowerCase()); - for (const heading of filterByTypesCached([ "atxHeading", "setextHeading" ])) { - if (!hasError) { - const headingText = getHeadingText(heading); - const headingLevel = getHeadingLevel(heading); - anyHeadings = true; - const actual = `${"".padEnd(headingLevel, "#")} ${headingText}`; - const expected = getExpected(); - if (expected === "*") { - const nextExpected = getExpected(); - if (handleCase(nextExpected) !== handleCase(actual)) { - matchAny = true; - i--; - } - } else if (expected === "+") { - matchAny = true; - } else if (handleCase(expected) === handleCase(actual)) { - matchAny = false; - } else if (matchAny) { - i--; - } else { - addErrorDetailIf( - onError, - heading.startLine, - expected, - actual - ); - hasError = true; - } - } - } - const extraHeadings = requiredHeadings.length - i; - if ( - !hasError && - ((extraHeadings > 1) || - ((extraHeadings === 1) && (requiredHeadings[i] !== "*"))) && - (anyHeadings || !requiredHeadings.every((heading) => heading === "*")) - ) { - addErrorContext( - onError, - params.lines.length, - requiredHeadings[i] - ); - } - } -}; - - -/***/ }), - -/***/ "../lib/md044.js": -/*!***********************!*\ - !*** ../lib/md044.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf, escapeForRegExp, hasOverlap } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByPredicate, filterByTypes } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { parse } = __webpack_require__(/*! ../helpers/micromark-parse.cjs */ "../helpers/micromark-parse.cjs"); - -const ignoredChildTypes = new Set( - [ "codeFencedFence", "definition", "reference", "resource" ] -); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD044", "proper-names" ], - "description": "Proper names should have the correct capitalization", - "tags": [ "spelling" ], - "parser": "micromark", - "function": function MD044(params, onError) { - let names = params.config.names; - names = Array.isArray(names) ? names : []; - names.sort((a, b) => (b.length - a.length) || a.localeCompare(b)); - if (names.length === 0) { - // Nothing to check; avoid doing any work - return; - } - const codeBlocks = params.config.code_blocks; - const includeCodeBlocks = - (codeBlocks === undefined) ? true : !!codeBlocks; - const htmlElements = params.config.html_elements; - const includeHtmlElements = - (htmlElements === undefined) ? true : !!htmlElements; - const scannedTypes = new Set([ "data" ]); - if (includeCodeBlocks) { - scannedTypes.add("codeFlowValue"); - scannedTypes.add("codeTextData"); - } - if (includeHtmlElements) { - scannedTypes.add("htmlFlowData"); - scannedTypes.add("htmlTextData"); - } - const contentTokens = - filterByPredicate( - params.parsers.micromark.tokens, - (token) => scannedTypes.has(token.type), - (token) => ( - token.children.filter((t) => !ignoredChildTypes.has(t.type)) - ) - ); - /** @type {import("../helpers").FileRange[]} */ - const exclusions = []; - const scannedTokens = new Set(); - for (const name of names) { - const escapedName = escapeForRegExp(name); - const startNamePattern = /^\W/.test(name) ? "" : "\\b_*"; - const endNamePattern = /\W$/.test(name) ? "" : "_*\\b"; - const namePattern = `(${startNamePattern})(${escapedName})${endNamePattern}`; - const nameRe = new RegExp(namePattern, "gi"); - for (const token of contentTokens) { - let match = null; - while ((match = nameRe.exec(token.text)) !== null) { - const [ , leftMatch, nameMatch ] = match; - const column = token.startColumn + match.index + leftMatch.length; - const length = nameMatch.length; - const lineNumber = token.startLine; - /** @type {import("../helpers").FileRange} */ - const nameRange = { - "startLine": lineNumber, - "startColumn": column, - "endLine": lineNumber, - "endColumn": column + length - 1 - }; - if ( - !names.includes(nameMatch) && - !exclusions.some((exclusion) => hasOverlap(exclusion, nameRange)) - ) { - /** @type {import("../helpers").FileRange[]} */ - let autolinkRanges = []; - if (!scannedTokens.has(token)) { - autolinkRanges = filterByTypes(parse(token.text), [ "literalAutolink" ]) - .map((tok) => ({ - "startLine": lineNumber, - "startColumn": token.startColumn + tok.startColumn - 1, - "endLine": lineNumber, - "endColumn": token.endColumn + tok.endColumn - 1 - })); - exclusions.push(...autolinkRanges); - scannedTokens.add(token); - } - if (!autolinkRanges.some((autolinkRange) => hasOverlap(autolinkRange, nameRange))) { - addErrorDetailIf( - onError, - token.startLine, - name, - nameMatch, - undefined, - undefined, - [ column, length ], - { - "editColumn": column, - "deleteCount": length, - "insertText": name - } - ); - } - } - exclusions.push(nameRange); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md045.js": -/*!***********************!*\ - !*** ../lib/md045.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, getHtmlAttributeRe, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getHtmlTagInfo, getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const altRe = getHtmlAttributeRe("alt"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD045", "no-alt-text" ], - "description": "Images should have alternate text (alt text)", - "tags": [ "accessibility", "images" ], - "parser": "micromark", - "function": function MD045(params, onError) { - // Process Markdown images - const images = filterByTypesCached([ "image" ]); - for (const image of images) { - const labelTexts = getDescendantsByType(image, [ "label", "labelText" ]); - if (labelTexts.some((labelText) => labelText.text.length === 0)) { - const range = (image.startLine === image.endLine) ? - [ image.startColumn, image.endColumn - image.startColumn ] : - undefined; - addError( - onError, - image.startLine, - undefined, - undefined, - range - ); - } - } - - // Process HTML images - const htmlTexts = filterByTypesCached([ "htmlText" ], true); - for (const htmlText of htmlTexts) { - const { startColumn, startLine, text } = htmlText; - const htmlTagInfo = getHtmlTagInfo(htmlText); - if ( - htmlTagInfo && - !htmlTagInfo.close && - (htmlTagInfo.name.toLowerCase() === "img") && - !altRe.test(text) - ) { - const range = [ - startColumn, - text.replace(nextLinesRe, "").length - ]; - addError( - onError, - startLine, - undefined, - undefined, - range - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md046.js": -/*!***********************!*\ - !*** ../lib/md046.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const tokenTypeToStyle = { - "codeFenced": "fenced", - "codeIndented": "indented" -}; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD046", "code-block-style" ], - "description": "Code block style", - "tags": [ "code" ], - "parser": "micromark", - "function": function MD046(params, onError) { - let expectedStyle = String(params.config.style || "consistent"); - for (const token of filterByTypesCached([ "codeFenced", "codeIndented" ])) { - const { startLine, type } = token; - if (expectedStyle === "consistent") { - expectedStyle = tokenTypeToStyle[type]; - } - addErrorDetailIf( - onError, - startLine, - expectedStyle, - tokenTypeToStyle[type]); - } - } -}; - - -/***/ }), - -/***/ "../lib/md047.js": -/*!***********************!*\ - !*** ../lib/md047.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD047", "single-trailing-newline" ], - "description": "Files should end with a single newline character", - "tags": [ "blank_lines" ], - "parser": "none", - "function": function MD047(params, onError) { - const lastLineNumber = params.lines.length; - const lastLine = params.lines[lastLineNumber - 1]; - if (!isBlankLine(lastLine)) { - addError( - onError, - lastLineNumber, - undefined, - undefined, - [ lastLine.length, 1 ], - { - "insertText": "\n", - "editColumn": lastLine.length + 1 - } - ); - } - } -}; - - -/***/ }), - -/***/ "../lib/md048.js": -/*!***********************!*\ - !*** ../lib/md048.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -/** - * Return the string representation of a fence markup character. - * - * @param {string} markup Fence string. - * @returns {"tilde" | "backtick"} String representation. - */ -function fencedCodeBlockStyleFor(markup) { - switch (markup[0]) { - case "~": - return "tilde"; - default: - return "backtick"; - } -}; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD048", "code-fence-style" ], - "description": "Code fence style", - "tags": [ "code" ], - "parser": "micromark", - "function": function MD048(params, onError) { - const style = String(params.config.style || "consistent"); - let expectedStyle = style; - const codeFenceds = filterByTypesCached([ "codeFenced" ]); - for (const codeFenced of codeFenceds) { - const codeFencedFenceSequence = - getDescendantsByType(codeFenced, [ "codeFencedFence", "codeFencedFenceSequence" ])[0]; - const { startLine, text } = codeFencedFenceSequence; - if (expectedStyle === "consistent") { - expectedStyle = fencedCodeBlockStyleFor(text); - } - addErrorDetailIf( - onError, - startLine, - expectedStyle, - fencedCodeBlockStyleFor(text) - ); - } - } -}; - - -/***/ }), - -/***/ "../lib/md049-md050.js": -/*!*****************************!*\ - !*** ../lib/md049-md050.js ***! - \*****************************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByPredicate, getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); - -const intrawordRe = /^\w$/; - -/** - * Return the string representation of a emphasis or strong markup character. - * - * @param {string} markup Emphasis or strong string. - * @returns {"asterisk" | "underscore"} String representation. - */ -function emphasisOrStrongStyleFor(markup) { - switch (markup[0]) { - case "*": - return "asterisk"; - default: - return "underscore"; - } -}; - -/** - * @param {import("./markdownlint").RuleParams} params Rule parameters. - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. - * @param {import("markdownlint-micromark").TokenType} type Token type. - * @param {import("markdownlint-micromark").TokenType} typeSequence Token sequence type. - * @param {"*" | "**"} asterisk Asterisk kind. - * @param {"_" | "__"} underline Underline kind. - * @param {"asterisk" | "consistent" | "underscore"} style Style string. - */ -const impl = - (params, onError, type, typeSequence, asterisk, underline, style = "consistent") => { - const { lines, parsers } = params; - const emphasisTokens = filterByPredicate( - parsers.micromark.tokens, - (token) => token.type === type, - (token) => ((token.type === "htmlFlow") ? [] : token.children) - ); - for (const token of emphasisTokens) { - const sequences = getDescendantsByType(token, [ typeSequence ]); - const startSequence = sequences[0]; - const endSequence = sequences[sequences.length - 1]; - if (startSequence && endSequence) { - const markupStyle = emphasisOrStrongStyleFor(startSequence.text); - if (style === "consistent") { - style = markupStyle; - } - if (style !== markupStyle) { - const underscoreIntraword = (style === "underscore") && ( - intrawordRe.test( - lines[startSequence.startLine - 1][startSequence.startColumn - 2] - ) || - intrawordRe.test( - lines[endSequence.endLine - 1][endSequence.endColumn - 1] - ) - ); - if (!underscoreIntraword) { - for (const sequence of [ startSequence, endSequence ]) { - addError( - onError, - sequence.startLine, - `Expected: ${style}; Actual: ${markupStyle}`, - undefined, - [ sequence.startColumn, sequence.text.length ], - { - "editColumn": sequence.startColumn, - "deleteCount": sequence.text.length, - "insertText": (style === "asterisk") ? asterisk : underline - } - ); - } - } - } - } - } - }; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule[] */ -module.exports = [ - { - "names": [ "MD049", "emphasis-style" ], - "description": "Emphasis style", - "tags": [ "emphasis" ], - "parser": "micromark", - "function": function MD049(params, onError) { - return impl( - params, - onError, - "emphasis", - "emphasisSequence", - "*", - "_", - params.config.style || undefined - ); - } - }, - { - "names": [ "MD050", "strong-style" ], - "description": "Strong style", - "tags": [ "emphasis" ], - "parser": "micromark", - "function": function MD050(params, onError) { - return impl( - params, - onError, - "strong", - "strongSequence", - "**", - "__", - params.config.style || undefined - ); - } - } -]; - - -/***/ }), - -/***/ "../lib/md051.js": -/*!***********************!*\ - !*** ../lib/md051.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, getHtmlAttributeRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByPredicate, filterByTypes, getHtmlTagInfo } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// Regular expression for identifying HTML anchor names -const idRe = getHtmlAttributeRe("id"); -const nameRe = getHtmlAttributeRe("name"); -const anchorRe = /\{(#[a-z\d]+(?:[-_][a-z\d]+)*)\}/gu; -const lineFragmentRe = /^#(?:L\d+(?:C\d+)?-L\d+(?:C\d+)?|L\d+)$/; - -// Sets for filtering heading tokens during conversion -const childrenExclude = new Set([ "image", "reference", "resource" ]); -const tokensInclude = new Set( - [ "characterEscapeValue", "codeTextData", "data", "mathTextData" ] -); - -/** - * Converts a Markdown heading into an HTML fragment according to the rules - * used by GitHub. - * - * @param {import("../helpers/micromark-helpers.cjs").Token} headingText Heading text token. - * @returns {string} Fragment string for heading. - */ -function convertHeadingToHTMLFragment(headingText) { - const inlineText = - filterByPredicate( - headingText.children, - (token) => tokensInclude.has(token.type), - (token) => (childrenExclude.has(token.type) ? [] : token.children) - ) - .map((token) => token.text) - .join(""); - return "#" + encodeURIComponent( - inlineText - .toLowerCase() - // RegExp source with Ruby's \p{Word} expanded into its General Categories - // https://github.com/gjtorikian/html-pipeline/blob/main/lib/html/pipeline/toc_filter.rb - // https://ruby-doc.org/core-3.0.2/Regexp.html - .replace( - /[^\p{Letter}\p{Mark}\p{Number}\p{Connector_Punctuation}\- ]/gu, - "" - ) - .replace(/ /gu, "-") - ); -} - -/** - * Unescapes the text of a String-type micromark Token. - * - * @param {import("../helpers/micromark-helpers.cjs").Token} token String-type micromark Token. - * @returns {string} Unescaped token text. - */ -function unescapeStringTokenText(token) { - return filterByTypes(token.children, [ "characterEscapeValue", "data" ]) - .map((child) => child.text) - .join(""); -} - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD051", "link-fragments" ], - "description": "Link fragments should be valid", - "tags": [ "links" ], - "parser": "micromark", - "function": function MD051(params, onError) { - const ignoreCase = params.config.ignore_case || false; - const fragments = new Map(); - - // Process headings - const headingTexts = filterByTypesCached([ "atxHeadingText", "setextHeadingText" ]); - for (const headingText of headingTexts) { - const fragment = convertHeadingToHTMLFragment(headingText); - if (fragment !== "#") { - const count = fragments.get(fragment) || 0; - if (count) { - fragments.set(`${fragment}-${count}`, 0); - } - fragments.set(fragment, count + 1); - let match = null; - while ((match = anchorRe.exec(headingText.text)) !== null) { - const [ , anchor ] = match; - if (!fragments.has(anchor)) { - fragments.set(anchor, 1); - } - } - } - } - - // Process HTML anchors - for (const token of filterByTypesCached([ "htmlText" ], true)) { - const htmlTagInfo = getHtmlTagInfo(token); - if (htmlTagInfo && !htmlTagInfo.close) { - const anchorMatch = idRe.exec(token.text) || - (htmlTagInfo.name.toLowerCase() === "a" && nameRe.exec(token.text)); - if (anchorMatch && anchorMatch.length > 0) { - fragments.set(`#${anchorMatch[1]}`, 0); - } - } - } - - // Process link and definition fragments - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../helpers/micromark-helpers.cjs").TokenType[][] */ - const parentChilds = [ - [ "link", "resourceDestinationString" ], - [ "definition", "definitionDestinationString" ] - ]; - for (const [ parentType, definitionType ] of parentChilds) { - const links = filterByTypesCached([ parentType ]); - for (const link of links) { - const definitions = filterByTypes(link.children, [ definitionType ]); - for (const definition of definitions) { - const { endColumn, startColumn } = definition; - const text = unescapeStringTokenText(definition); - const encodedText = `#${encodeURIComponent(text.slice(1))}`; - if ( - (text.length > 1) && - text.startsWith("#") && - !fragments.has(encodedText) && - !lineFragmentRe.test(encodedText) - ) { - let context = undefined; - let range = undefined; - let fixInfo = undefined; - if (link.startLine === link.endLine) { - context = link.text; - range = [ link.startColumn, link.endColumn - link.startColumn ]; - fixInfo = { - "editColumn": startColumn, - "deleteCount": endColumn - startColumn - }; - } - const textLower = text.toLowerCase(); - const mixedCaseKey = [ ...fragments.keys() ] - .find((key) => textLower === key.toLowerCase()); - if (mixedCaseKey) { - // @ts-ignore - (fixInfo || {}).insertText = mixedCaseKey; - if (!ignoreCase && (mixedCaseKey !== text)) { - addError( - onError, - link.startLine, - `Expected: ${mixedCaseKey}; Actual: ${text}`, - context, - range, - fixInfo - ); - } - } else { - addError( - onError, - link.startLine, - undefined, - context, - range - ); - } - } - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md052.js": -/*!***********************!*\ - !*** ../lib/md052.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getReferenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD052", "reference-links-images" ], - "description": - "Reference links and images should use a label that is defined", - "tags": [ "images", "links" ], - "parser": "none", - "function": function MD052(params, onError) { - const { config, lines } = params; - const shortcutSyntax = config.shortcut_syntax || false; - const { definitions, references, shortcuts } = getReferenceLinkImageData(); - const entries = shortcutSyntax ? - [ ...references.entries(), ...shortcuts.entries() ] : - references.entries(); - // Look for links/images that use an undefined link reference - for (const reference of entries) { - const [ label, datas ] = reference; - if (!definitions.has(label)) { - for (const data of datas) { - const [ lineIndex, index, length ] = data; - // Context will be incomplete if reporting for a multi-line link - const context = lines[lineIndex].slice(index, index + length); - addError( - onError, - lineIndex + 1, - `Missing link or image reference definition: "${label}"`, - context, - [ index + 1, context.length ] - ); - } - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md053.js": -/*!***********************!*\ - !*** ../lib/md053.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addError, ellipsify } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getReferenceLinkImageData } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD053", "link-image-reference-definitions" ], - "description": "Link and image reference definitions should be needed", - "tags": [ "images", "links" ], - "parser": "none", - "function": function MD053(params, onError) { - const ignored = new Set(params.config.ignored_definitions || [ "//" ]); - const lines = params.lines; - const { references, shortcuts, definitions, duplicateDefinitions } = - getReferenceLinkImageData(); - const singleLineDefinition = (line) => ( - line.replace(linkReferenceDefinitionRe, "").trim().length > 0 - ); - const deleteFixInfo = { - "deleteCount": -1 - }; - // Look for unused link references (unreferenced by any link/image) - for (const definition of definitions.entries()) { - const [ label, [ lineIndex ] ] = definition; - if ( - !ignored.has(label) && - !references.has(label) && - !shortcuts.has(label) - ) { - const line = lines[lineIndex]; - addError( - onError, - lineIndex + 1, - `Unused link or image reference definition: "${label}"`, - ellipsify(line), - [ 1, line.length ], - singleLineDefinition(line) ? deleteFixInfo : undefined - ); - } - } - // Look for duplicate link references (defined more than once) - for (const duplicateDefinition of duplicateDefinitions) { - const [ label, lineIndex ] = duplicateDefinition; - if (!ignored.has(label)) { - const line = lines[lineIndex]; - addError( - onError, - lineIndex + 1, - `Duplicate link or image reference definition: "${label}"`, - ellipsify(line), - [ 1, line.length ], - singleLineDefinition(line) ? deleteFixInfo : undefined - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md054.js": -/*!***********************!*\ - !*** ../lib/md054.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, nextLinesRe } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getDescendantsByType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { getReferenceLinkImageData, filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g; -const removeBackslashEscapes = (text) => text.replace(backslashEscapeRe, "$1"); -const autolinkDisallowedRe = /[ <>]/; -const autolinkAble = (destination) => { - try { - // eslint-disable-next-line no-new - new URL(destination); - } catch { - // Not an absolute URL - return false; - } - return !autolinkDisallowedRe.test(destination); -}; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD054", "link-image-style" ], - "description": "Link and image style", - "tags": [ "images", "links" ], - "parser": "micromark", - "function": (params, onError) => { - const config = params.config; - const autolink = (config.autolink === undefined) || !!config.autolink; - const inline = (config.inline === undefined) || !!config.inline; - const full = (config.full === undefined) || !!config.full; - const collapsed = (config.collapsed === undefined) || !!config.collapsed; - const shortcut = (config.shortcut === undefined) || !!config.shortcut; - const urlInline = (config.url_inline === undefined) || !!config.url_inline; - if (autolink && inline && full && collapsed && shortcut && urlInline) { - // Everything allowed, nothing to check - return; - } - const { definitions } = getReferenceLinkImageData(); - const links = filterByTypesCached([ "autolink", "image", "link" ]); - for (const link of links) { - let label = null; - let destination = null; - const { - endColumn, endLine, startColumn, startLine, text, type - } = link; - const image = (type === "image"); - let isError = false; - if (type === "autolink") { - // link kind is an autolink - destination = getDescendantsByType(link, [ [ "autolinkEmail", "autolinkProtocol" ] ])[0]?.text; - label = destination; - isError = !autolink && Boolean(destination); - } else { - // link type is "image" or "link" - label = getDescendantsByType(link, [ "label", "labelText" ])[0].text; - destination = - getDescendantsByType(link, [ "resource", "resourceDestination", [ "resourceDestinationLiteral", "resourceDestinationRaw" ], "resourceDestinationString" ])[0]?.text; - if (destination) { - // link kind is an inline link - const title = getDescendantsByType(link, [ "resource", "resourceTitle", "resourceTitleString" ])[0]?.text; - isError = !inline || ( - !urlInline && - autolink && - !image && - !title && - (label === destination) && - autolinkAble(destination) - ); - } else { - // link kind is a full/collapsed/shortcut reference link - const isShortcut = getDescendantsByType(link, [ "reference" ]).length === 0; - const referenceString = getDescendantsByType(link, [ "reference", "referenceString" ])[0]?.text; - const isCollapsed = (referenceString === undefined); - const definition = definitions.get(referenceString || label); - destination = definition && definition[1]; - isError = destination && - (isShortcut ? !shortcut : (isCollapsed ? !collapsed : !full)); - } - } - if (isError) { - let range = undefined; - let fixInfo = undefined; - if (startLine === endLine) { - range = [ startColumn, endColumn - startColumn ]; - let insertText = null; - const canInline = (inline && label); - const canAutolink = (autolink && !image && autolinkAble(destination)); - if (canInline && (urlInline || !canAutolink)) { - // Most useful form - const prefix = (image ? "!" : ""); - // @ts-ignore - const escapedLabel = label.replace(/[[\]]/g, "\\$&"); - const escapedDestination = destination.replace(/[()]/g, "\\$&"); - insertText = `${prefix}[${escapedLabel}](${escapedDestination})`; - } else if (canAutolink) { - // Simplest form - insertText = `<${removeBackslashEscapes(destination)}>`; - } - if (insertText) { - fixInfo = { - "editColumn": range[0], - insertText, - "deleteCount": range[1] - }; - } - } - addErrorContext( - onError, - startLine, - text.replace(nextLinesRe, ""), - undefined, - undefined, - range, - fixInfo - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md055.js": -/*!***********************!*\ - !*** ../lib/md055.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]); -const ignoreWhitespace = (tokens) => tokens.filter( - (token) => !whitespaceTypes.has(token.type) -); -const firstOrNothing = (items) => items[0]; -const lastOrNothing = (items) => items[items.length - 1]; -const makeRange = (start, end) => [ start, end - start + 1 ]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD055", "table-pipe-style" ], - "description": "Table pipe style", - "tags": [ "table" ], - "parser": "micromark", - "function": function MD055(params, onError) { - const style = String(params.config.style || "consistent"); - let expectedStyle = style; - let expectedLeadingPipe = - ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "trailing_only")); - let expectedTrailingPipe = - ((expectedStyle !== "no_leading_or_trailing") && (expectedStyle !== "leading_only")); - const rows = filterByTypesCached([ "tableDelimiterRow", "tableRow" ]); - for (const row of rows) { - // The following uses of first/lastOrNothing lack fallback handling - // because it seems not to be possible (i.e., 0% coverage) - const firstCell = firstOrNothing(row.children); - const leadingToken = firstOrNothing(ignoreWhitespace(firstCell.children)); - const actualLeadingPipe = (leadingToken.type === "tableCellDivider"); - const lastCell = lastOrNothing(row.children); - const trailingToken = lastOrNothing(ignoreWhitespace(lastCell.children)); - const actualTrailingPipe = (trailingToken.type === "tableCellDivider"); - const actualStyle = actualLeadingPipe ? - (actualTrailingPipe ? "leading_and_trailing" : "leading_only") : - (actualTrailingPipe ? "trailing_only" : "no_leading_or_trailing"); - if (expectedStyle === "consistent") { - expectedStyle = actualStyle; - expectedLeadingPipe = actualLeadingPipe; - expectedTrailingPipe = actualTrailingPipe; - } - if (actualLeadingPipe !== expectedLeadingPipe) { - addErrorDetailIf( - onError, - firstCell.startLine, - expectedStyle, - actualStyle, - `${expectedLeadingPipe ? "Missing" : "Unexpected"} leading pipe`, - undefined, - makeRange(row.startColumn, firstCell.startColumn) - ); - } - if (actualTrailingPipe !== expectedTrailingPipe) { - addErrorDetailIf( - onError, - lastCell.endLine, - expectedStyle, - actualStyle, - `${expectedTrailingPipe ? "Missing" : "Unexpected"} trailing pipe`, - undefined, - makeRange(lastCell.endColumn - 1, row.endColumn - 1) - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/md056.js": -/*!***********************!*\ - !*** ../lib/md056.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorDetailIf } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getParentOfType } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -const makeRange = (start, end) => [ start, end - start + 1 ]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD056", "table-column-count" ], - "description": "Table column count", - "tags": [ "table" ], - "parser": "micromark", - "function": function MD056(params, onError) { - const rows = filterByTypesCached([ "tableDelimiterRow", "tableRow" ]); - let expectedCount = 0; - let currentTable = null; - for (const row of rows) { - const table = getParentOfType(row, [ "table" ]); - if (currentTable !== table) { - expectedCount = 0; - currentTable = table; - } - const cells = row.children.filter((child) => [ "tableData", "tableDelimiter", "tableHeader" ].includes(child.type)); - const actualCount = cells.length; - expectedCount ||= actualCount; - let detail = undefined; - let range = undefined; - if (actualCount < expectedCount) { - detail = "Too few cells, row will be missing data"; - range = [ row.endColumn - 1, 1 ]; - } else if (expectedCount < actualCount) { - detail = "Too many cells, extra data will be missing"; - range = makeRange(cells[expectedCount].startColumn, row.endColumn - 1); - } - addErrorDetailIf( - onError, - row.endLine, - expectedCount, - actualCount, - detail, - undefined, - range - ); - } - } -}; - - -/***/ }), - -/***/ "../lib/md058.js": -/*!***********************!*\ - !*** ../lib/md058.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { addErrorContext, isBlankLine } = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"); -const { getBlockQuotePrefixText } = __webpack_require__(/*! ../helpers/micromark-helpers.cjs */ "../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = __webpack_require__(/*! ./cache */ "../lib/cache.js"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { - "names": [ "MD058", "blanks-around-tables" ], - "description": "Tables should be surrounded by blank lines", - "tags": [ "table" ], - "parser": "micromark", - "function": function MD058(params, onError) { - const { lines } = params; - const blockQuotePrefixes = filterByTypesCached([ "blockQuotePrefix", "linePrefix" ]); - - // For every table... - const tables = filterByTypesCached([ "table" ]); - for (const table of tables) { - - // Look for a blank line above the table - const firstLineNumber = table.startLine; - if (!isBlankLine(lines[firstLineNumber - 2])) { - addErrorContext( - onError, - firstLineNumber, - lines[firstLineNumber - 1].trim(), - undefined, - undefined, - undefined, - { - "insertText": getBlockQuotePrefixText(blockQuotePrefixes, firstLineNumber) - } - ); - } - - // Look for a blank line below the table - const lastLineNumber = table.endLine; - if (!isBlankLine(lines[lastLineNumber])) { - addErrorContext( - onError, - lastLineNumber, - lines[lastLineNumber - 1].trim(), - undefined, - undefined, - undefined, - { - "lineNumber": lastLineNumber + 1, - "insertText": getBlockQuotePrefixText(blockQuotePrefixes, lastLineNumber) - } - ); - } - } - } -}; - - -/***/ }), - -/***/ "../lib/rules.js": -/*!***********************!*\ - !*** ../lib/rules.js ***! - \***********************/ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -"use strict"; -// @ts-check - - - -const { homepage, version } = __webpack_require__(/*! ./constants */ "../lib/constants.js"); - -// @ts-ignore -const [ md019, md021 ] = __webpack_require__(/*! ./md019-md021 */ "../lib/md019-md021.js"); -// @ts-ignore -const [ md049, md050 ] = __webpack_require__(/*! ./md049-md050 */ "../lib/md049-md050.js"); - -const rules = [ - __webpack_require__(/*! ./md001 */ "../lib/md001.js"), - // md002: Deprecated and removed - __webpack_require__(/*! ./md003 */ "../lib/md003.js"), - __webpack_require__(/*! ./md004 */ "../lib/md004.js"), - __webpack_require__(/*! ./md005 */ "../lib/md005.js"), - // md006: Deprecated and removed - __webpack_require__(/*! ./md007 */ "../lib/md007.js"), - __webpack_require__(/*! ./md009 */ "../lib/md009.js"), - __webpack_require__(/*! ./md010 */ "../lib/md010.js"), - __webpack_require__(/*! ./md011 */ "../lib/md011.js"), - __webpack_require__(/*! ./md012 */ "../lib/md012.js"), - __webpack_require__(/*! ./md013 */ "../lib/md013.js"), - __webpack_require__(/*! ./md014 */ "../lib/md014.js"), - __webpack_require__(/*! ./md018 */ "../lib/md018.js"), - md019, - __webpack_require__(/*! ./md020 */ "../lib/md020.js"), - md021, - __webpack_require__(/*! ./md022 */ "../lib/md022.js"), - __webpack_require__(/*! ./md023 */ "../lib/md023.js"), - __webpack_require__(/*! ./md024 */ "../lib/md024.js"), - __webpack_require__(/*! ./md025 */ "../lib/md025.js"), - __webpack_require__(/*! ./md026 */ "../lib/md026.js"), - __webpack_require__(/*! ./md027 */ "../lib/md027.js"), - __webpack_require__(/*! ./md028 */ "../lib/md028.js"), - __webpack_require__(/*! ./md029 */ "../lib/md029.js"), - __webpack_require__(/*! ./md030 */ "../lib/md030.js"), - __webpack_require__(/*! ./md031 */ "../lib/md031.js"), - __webpack_require__(/*! ./md032 */ "../lib/md032.js"), - __webpack_require__(/*! ./md033 */ "../lib/md033.js"), - __webpack_require__(/*! ./md034 */ "../lib/md034.js"), - __webpack_require__(/*! ./md035 */ "../lib/md035.js"), - __webpack_require__(/*! ./md036 */ "../lib/md036.js"), - __webpack_require__(/*! ./md037 */ "../lib/md037.js"), - __webpack_require__(/*! ./md038 */ "../lib/md038.js"), - __webpack_require__(/*! ./md039 */ "../lib/md039.js"), - __webpack_require__(/*! ./md040 */ "../lib/md040.js"), - __webpack_require__(/*! ./md041 */ "../lib/md041.js"), - __webpack_require__(/*! ./md042 */ "../lib/md042.js"), - __webpack_require__(/*! ./md043 */ "../lib/md043.js"), - __webpack_require__(/*! ./md044 */ "../lib/md044.js"), - __webpack_require__(/*! ./md045 */ "../lib/md045.js"), - __webpack_require__(/*! ./md046 */ "../lib/md046.js"), - __webpack_require__(/*! ./md047 */ "../lib/md047.js"), - __webpack_require__(/*! ./md048 */ "../lib/md048.js"), - md049, - md050, - __webpack_require__(/*! ./md051 */ "../lib/md051.js"), - __webpack_require__(/*! ./md052 */ "../lib/md052.js"), - __webpack_require__(/*! ./md053 */ "../lib/md053.js"), - __webpack_require__(/*! ./md054 */ "../lib/md054.js"), - __webpack_require__(/*! ./md055 */ "../lib/md055.js"), - __webpack_require__(/*! ./md056 */ "../lib/md056.js"), - // md057: See https://github.com/markdownlint/markdownlint - __webpack_require__(/*! ./md058 */ "../lib/md058.js") -]; -for (const rule of rules) { - const name = rule.names[0].toLowerCase(); - // eslint-disable-next-line dot-notation - rule["information"] = - new URL(`${homepage}/blob/v${version}/doc/${name}.md`); -} -module.exports = rules; - - -/***/ }) - -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __webpack_require__("./markdownlint-exports.js"); -/******/ markdownlint = __webpack_exports__; -/******/ -/******/ })() -; \ No newline at end of file diff --git a/demo/markdownlint-exports.js b/demo/markdownlint-exports.js deleted file mode 100644 index ef6fc84d8..000000000 --- a/demo/markdownlint-exports.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check - -"use strict"; - -module.exports = { - "library": require(".."), - "helpers": require("../helpers") -}; diff --git a/demo/module-stub.cjs b/demo/module-stub.cjs new file mode 100644 index 000000000..fec94871b --- /dev/null +++ b/demo/module-stub.cjs @@ -0,0 +1,8 @@ +// @ts-check + +"use strict"; + +module.exports = { + // @ts-ignore + "createRequire": () => require +}; diff --git a/demo/webpack.config.js b/demo/webpack.config.mjs similarity index 70% rename from demo/webpack.config.js rename to demo/webpack.config.mjs index 274b14037..2b6d931a3 100644 --- a/demo/webpack.config.js +++ b/demo/webpack.config.mjs @@ -1,11 +1,14 @@ // @ts-check -"use strict"; - -const webpack = require("webpack"); -const TerserPlugin = require("terser-webpack-plugin"); +import { createRequire } from "node:module"; +const require = createRequire(import.meta.url); +import webpack from "webpack"; +import TerserPlugin from "terser-webpack-plugin"; +import { __dirname, importWithTypeJson } from "../test/esm-helpers.mjs"; +const libraryPackageJson = await importWithTypeJson(import.meta, "../package.json"); const nodeModulePrefixRe = /^node:/u; +// eslint-disable-next-line jsdoc/require-jsdoc function config(options) { const { entry, filename, mode, optimization, packageJson } = options; const { name, version, homepage, license } = packageJson; @@ -13,8 +16,7 @@ function config(options) { "devtool": false, "entry": entry, "externals": { - "markdown-it": "markdownit", - "markdownlint-micromark": "micromarkBrowser" + "markdown-it": "markdownit" }, "mode": mode, "module": { @@ -33,7 +35,7 @@ function config(options) { "name": name.replace(/(-\w)/g, (m) => m.slice(1).toUpperCase()), "type": "var" }, - "path": __dirname + "path": __dirname(import.meta) }, "plugins": [ new webpack.NormalModuleReplacementPlugin( @@ -52,7 +54,8 @@ function config(options) { "fs": false, "os": false, "path": false, - "util": false + "util": false, + "module": require.resolve("./module-stub.cjs") } } }; @@ -77,14 +80,10 @@ const modeProduction = { } }; const entryLibrary = { - "entry": "./markdownlint-exports.js", - "packageJson": require("../package.json") + "entry": "./browser-exports.mjs", + "packageJson": libraryPackageJson }; -// const entryHelpers = { -// "entry": "../helpers/helpers.js", -// "packageJson": require("../helpers/package.json") -// }; -module.exports = [ +export default [ config({ ...entryLibrary, ...modeDevelopment, @@ -95,14 +94,4 @@ module.exports = [ ...modeProduction, "filename": "markdownlint-browser.min.js" }) - // config({ - // ...entryHelpers, - // ...modeDevelopment, - // "filename": "markdownlint-rule-helpers-browser.js" - // }), - // config({ - // ...entryHelpers, - // ...modeProduction, - // "filename": "markdownlint-rule-helpers-browser.min.js" - // }) ]; diff --git a/doc-build/build-rules.mjs b/doc-build/build-rules.mjs index fc50934ae..f6852bd2e 100644 --- a/doc-build/build-rules.mjs +++ b/doc-build/build-rules.mjs @@ -1,8 +1,8 @@ import { readFile, writeFile } from "node:fs/promises"; import { EOL } from "node:os"; -import { default as rules } from "../lib/rules.js"; -import { newLineRe } from "../helpers/helpers.js"; -import { deprecatedRuleNames, fixableRuleNames } from "../lib/constants.js"; +import { default as rules } from "../lib/rules.mjs"; +import { newLineRe } from "../helpers/helpers.cjs"; +import { deprecatedRuleNames, fixableRuleNames } from "../lib/constants.mjs"; const maxLineLength = 80; diff --git a/doc/CustomRules.md b/doc/CustomRules.md index bbbe606fd..1136d2caa 100644 --- a/doc/CustomRules.md +++ b/doc/CustomRules.md @@ -36,7 +36,7 @@ A simple rule implementation using the `micromark` parser to report a violation for any use of blockquotes might look like: ```javascript -/** @type import("markdownlint").Rule */ +/** @type {import("markdownlint").Rule} */ module.exports = { "names": [ "any-blockquote-micromark" ], "description": "Rule that reports an error for any blockquote", @@ -61,7 +61,7 @@ module.exports = { That same rule implemented using the `markdown-it` parser might look like: ```javascript -/** @type import("markdownlint").Rule */ +/** @type {import("markdownlint").Rule} */ module.exports = { "names": [ "any-blockquote-markdown-it" ], "description": "Rule that reports an error for any blockquote", @@ -187,8 +187,8 @@ exception. [markdown-it-token]: https://markdown-it.github.io/markdown-it/#Token [markdownlint-rule]: https://www.npmjs.com/search?q=keywords:markdownlint-rule [micromark]: https://github.com/micromark/micromark -[micromark-token]: ../lib/markdownlint.d.ts +[micromark-token]: ../lib/markdownlint.d.mts [rule-helpers]: https://www.npmjs.com/package/markdownlint-rule-helpers [options-custom-rules]: ../README.md#optionscustomrules [test-rules]: ../test/rules -[tokens]: ../test/snapshots/markdownlint-test-custom-rules.js.md +[tokens]: ../test/snapshots/markdownlint-test-custom-rules.mjs.md diff --git a/eslint.config.mjs b/eslint.config.mjs index 3409c6e51..62d20d0ed 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -25,20 +25,11 @@ export default [ "demo/markdown-it.min.js", "demo/markdownlint-browser.js", "demo/markdownlint-browser.min.js", - "demo/micromark-browser.js", - "demo/micromark-html-browser.js", "example/typescript/type-check.js", - "micromark/micromark.cjs", - "micromark/micromark.dev.cjs", - "micromark/micromark-browser.js", - "micromark/micromark-browser.dev.js", "test-repos/**" ] }, { - "languageOptions": { - "sourceType": "commonjs" - }, "linterOptions": { "reportUnusedDisableDirectives": true }, @@ -88,7 +79,6 @@ export default [ "unicorn/no-null": "off", "unicorn/no-useless-undefined": "off", "unicorn/prefer-at": "off", - "unicorn/prefer-module": "off", "unicorn/prefer-string-raw": "off", "unicorn/prefer-string-replace-all": "off", "unicorn/prefer-string-slice": "off", @@ -107,15 +97,20 @@ export default [ }, { "files": [ - "**/*.mjs" + "**/*.js", + "**/*.cjs" ], "languageOptions": { - "sourceType": "module" + "sourceType": "commonjs", + "globals": { + "module": "readonly", + "require": "readonly" + } } }, { "files": [ - "demo/*.js" + "demo/default.js" ], "languageOptions": { "globals": { @@ -131,26 +126,42 @@ export default [ "no-invalid-this": "off", "no-shadow": "off", "no-var": "off", + "unicorn/prefer-module": "off", "unicorn/prefer-query-selector": "off" } }, { "files": [ - "example/*.js" + "example/*.cjs" ], + "languageOptions": { + "sourceType": "commonjs" + }, "rules": { "n/no-missing-require": "off", "no-console": "off", - "no-invalid-this": "off", + "no-invalid-this": "off" + } + }, + { + "files": [ + "example/standalone.mjs" + ], + "rules": { + "no-console": "off", "no-shadow": "off" } }, { "files": [ - "test/rules/**/*.js" + "test/rules/**/*.js", + "test/rules/**/*.cjs" ], + "languageOptions": { + "sourceType": "commonjs" + }, "rules": { - "jsdoc/valid-types": "off" + "unicorn/prefer-module": "off" } } ]; diff --git a/example/Gruntfile.cjs b/example/Gruntfile.cjs new file mode 100644 index 000000000..615ac4620 --- /dev/null +++ b/example/Gruntfile.cjs @@ -0,0 +1,28 @@ +// @ts-check + +"use strict"; + +module.exports = function wrapper(grunt) { + grunt.initConfig({ + "markdownlint": { + "example": { + "src": [ "*.md" ] + } + } + }); + + grunt.registerMultiTask("markdownlint", function task() { + const done = this.async(); + import("../lib/markdownlint.mjs").then(({ "default": markdownlint }) => { + markdownlint( + { "files": this.filesSrc }, + function callback(err, result) { + const resultString = err || ((result || "").toString()); + if (resultString) { + grunt.fail.warn("\n" + resultString + "\n"); + } + done(!err || !resultString); + }); + }).catch(done); + }); +}; diff --git a/example/Gruntfile.js b/example/Gruntfile.js deleted file mode 100644 index 6da592328..000000000 --- a/example/Gruntfile.js +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-check - -"use strict"; - -const markdownlint = require("../lib/markdownlint"); - -module.exports = function wrapper(grunt) { - grunt.initConfig({ - "markdownlint": { - "example": { - "src": [ "*.md" ] - } - } - }); - - grunt.registerMultiTask("markdownlint", function task() { - const done = this.async(); - markdownlint( - { "files": this.filesSrc }, - function callback(err, result) { - const resultString = err || ((result || "").toString()); - if (resultString) { - grunt.fail.warn("\n" + resultString + "\n"); - } - done(!err || !resultString); - }); - }); -}; diff --git a/example/gulpfile.cjs b/example/gulpfile.cjs new file mode 100644 index 000000000..87856e6af --- /dev/null +++ b/example/gulpfile.cjs @@ -0,0 +1,24 @@ +// @ts-check + +"use strict"; + +const gulp = require("gulp"); +const through2 = require("through2"); + +// Simple task wrapper +gulp.task("markdownlint", function task() { + return gulp.src("*.md", { "read": false }) + .pipe(through2.obj(function obj(file, enc, next) { + import("../lib/markdownlint.mjs").then(({ "default": markdownlint }) => { + markdownlint( + { "files": [ file.relative ] }, + function callback(err, result) { + const resultString = (result || "").toString(); + if (resultString) { + console.log(resultString); + } + next(err, file); + }); + }).catch(next); + })); +}); diff --git a/example/gulpfile.js b/example/gulpfile.js deleted file mode 100644 index 7548cbb6d..000000000 --- a/example/gulpfile.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check - -"use strict"; - -const gulp = require("gulp"); -const through2 = require("through2"); -const markdownlint = require("../lib/markdownlint"); - -// Simple task wrapper -gulp.task("markdownlint", function task() { - return gulp.src("*.md", { "read": false }) - .pipe(through2.obj(function obj(file, enc, next) { - markdownlint( - { "files": [ file.relative ] }, - function callback(err, result) { - const resultString = (result || "").toString(); - if (resultString) { - console.log(resultString); - } - next(err, file); - }); - })); -}); diff --git a/example/standalone.js b/example/standalone.mjs similarity index 68% rename from example/standalone.js rename to example/standalone.mjs index 7f198fe84..58e0fabd0 100644 --- a/example/standalone.js +++ b/example/standalone.mjs @@ -1,8 +1,6 @@ // @ts-check -"use strict"; - -const markdownlint = require("../lib/markdownlint"); +import markdownlint from "../lib/markdownlint.mjs"; const options = { "files": [ "good.md", "bad.md" ], @@ -19,6 +17,7 @@ console.log(result.toString()); // Makes an asynchronous call markdownlint(options, function callback(err, result) { if (!err) { + // @ts-ignore console.log(result.toString()); } }); @@ -29,3 +28,9 @@ markdownlint(options, function callback(err, result) { console.dir(result, { "colors": true, "depth": null }); } }); + +// Fixes all supported violations in Markdown content +const original = "# Heading"; +const fixResults = markdownlint.sync({ "strings": { "content": original } }); +const fixed = markdownlint.applyFixes(original, fixResults.content); +console.log(fixed); diff --git a/example/typescript/type-check.ts b/example/typescript/type-check.ts index eb9c13b1a..1ab5cea15 100644 --- a/example/typescript/type-check.ts +++ b/example/typescript/type-check.ts @@ -1,25 +1,27 @@ -// Attempt to validate all the type declarations in markdownlint.d.ts +// Attempt to validate all the type declarations in markdownlint.d.mts -import markdownlint from "../.."; +import { default as markdownlint, Configuration, ConfigurationStrict, LintResults, Options, Rule, RuleParams, RuleOnError, RuleOnErrorInfo } from "../../lib/markdownlint.mjs"; -const assert = require("assert"); +import assert from "assert"; +// @ts-expect-error TS7016: Could not find a declaration file for module 'markdown-it-sub'. +import markdownItSub from "markdown-it-sub"; const markdownlintJsonPath = "../../.markdownlint.json"; const version: string = markdownlint.getVersion(); assert(/^\d+\.\d+\.\d+$/.test(version)); -function assertConfiguration(config: markdownlint.Configuration) { +function assertConfiguration(config: Configuration) { assert(!!config); assert.deepEqual(config["line-length"], { "strict": true, "code_blocks": false }); // config assignment is covered by markdownlint.Options } -function assertConfigurationCallback(err: Error | null, config?: markdownlint.Configuration) { +function assertConfigurationCallback(err: Error | null, config?: Configuration) { assert(!err); config && assertConfiguration(config); } -function assertLintResults(results: markdownlint.LintResults) { +function assertLintResults(results: LintResults) { assert(!!results); assert.equal(results["string"].length, 1); assert.equal(results["string"][0].lineNumber, 1); @@ -60,7 +62,7 @@ function assertLintResults(results: markdownlint.LintResults) { }; } -function assertLintResultsCallback(err: Error | null, results?: markdownlint.LintResults) { +function assertLintResultsCallback(err: Error | null, results?: LintResults) { assert(!err); results && assertLintResults(results); } @@ -76,7 +78,7 @@ markdownlint.readConfig(markdownlintJsonPath, [ JSON.parse ], assertConfiguratio assertConfigurationCallback(null, await markdownlint.promises.readConfig(markdownlintJsonPath, [ JSON.parse ])) })(); -let options: markdownlint.Options; +let options: Options; options = { "files": [ "../bad.md" ], "strings": { @@ -93,7 +95,7 @@ options = { "frontMatter": /---/, "handleRuleFailures": false, "noInlineConfig": false, - "markdownItPlugins": [ [ require("markdown-it-sub") ] ] + "markdownItPlugins": [ [ markdownItSub ] ] }; assertLintResults(markdownlint.sync(options)); @@ -109,16 +111,16 @@ markdownlint(options, assertLintResultsCallback); assertLintResultsCallback(null, await markdownlint.promises.markdownlint(options)); })(); -const testRule: markdownlint.Rule = { +const testRule: Rule = { "names": [ "test-rule" ], "description": "Test rule", "information": new URL("https://example.com/rule-information"), "tags": [ "test-tag" ], "parser": "none", - "function": function rule(params: markdownlint.RuleParams, onError: markdownlint.RuleOnError) { + "function": function rule(params: RuleParams, onError: RuleOnError) { assert(!!params); assert(!!onError); - let ruleParams: markdownlint.RuleParams; + let ruleParams: RuleParams; ruleParams = { "name": "name", "parsers": { @@ -140,7 +142,7 @@ const testRule: markdownlint.Rule = { "version": "1.2.3" }; assert(ruleParams); - let ruleOnErrorInfo: markdownlint.RuleOnErrorInfo; + let ruleOnErrorInfo: RuleOnErrorInfo; ruleOnErrorInfo = { "lineNumber": 1, "detail": "detail", @@ -196,7 +198,7 @@ assert.equal( "# Heading\n" ); -const configuration: markdownlint.Configuration = { +const configuration: Configuration = { "custom-rule": true, "no-hard-tabs": false, "heading-style": { @@ -204,7 +206,7 @@ const configuration: markdownlint.Configuration = { } }; assert(configuration); -const configurationStrict: markdownlint.ConfigurationStrict = { +const configurationStrict: ConfigurationStrict = { // "custom-rule": true, "no-hard-tabs": false, "heading-style": { diff --git a/helpers/.npmignore b/helpers/.npmignore index daa602947..73c5a2779 100644 --- a/helpers/.npmignore +++ b/helpers/.npmignore @@ -1 +1 @@ -test.js +test.cjs diff --git a/helpers/helpers.js b/helpers/helpers.cjs similarity index 96% rename from helpers/helpers.js rename to helpers/helpers.cjs index f52e48bd7..f35f94291 100644 --- a/helpers/helpers.js +++ b/helpers/helpers.cjs @@ -4,13 +4,17 @@ const micromark = require("./micromark-helpers.cjs"); -const { newLineRe, nextLinesRe } = require("./shared.js"); +const { newLineRe, nextLinesRe } = require("./shared.cjs"); module.exports.newLineRe = newLineRe; module.exports.nextLinesRe = nextLinesRe; -/** @typedef {import("../lib/markdownlint.js").RuleOnError} RuleOnError */ -/** @typedef {import("../lib/markdownlint.js").RuleOnErrorFixInfo} RuleOnErrorFixInfo */ +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/52529 +/** @typedef {import("../lib/markdownlint.mjs").RuleOnError} RuleOnError */ +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/52529 +/** @typedef {import("../lib/markdownlint.mjs").RuleOnErrorFixInfo} RuleOnErrorFixInfo */ +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/52529 +/** @typedef {import("../lib/markdownlint.mjs").MicromarkToken} MicromarkToken */ // Regular expression for matching common front matter (YAML and TOML) module.exports.frontMatterRe = @@ -336,8 +340,8 @@ const positionLessThanOrEqual = (lineA, columnA, lineB, columnB) => ( /** * Returns whether two ranges (or MicromarkTokens) overlap anywhere. * - * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeA Range A. - * @param {FileRange|import("../lib/markdownlint.js").MicromarkToken} rangeB Range B. + * @param {FileRange|MicromarkToken} rangeA Range A. + * @param {FileRange|MicromarkToken} rangeB Range B. * @returns {boolean} True iff the two ranges overlap. */ module.exports.hasOverlap = function hasOverlap(rangeA, rangeB) { diff --git a/helpers/micromark-helpers.cjs b/helpers/micromark-helpers.cjs index 6b4ff09c1..230279d9a 100644 --- a/helpers/micromark-helpers.cjs +++ b/helpers/micromark-helpers.cjs @@ -2,10 +2,12 @@ "use strict"; -const { flatTokensSymbol, htmlFlowSymbol } = require("./shared.js"); +const { flatTokensSymbol, htmlFlowSymbol } = require("./shared.cjs"); -/** @typedef {import("markdownlint-micromark").TokenType} TokenType */ -/** @typedef {import("../lib/markdownlint.js").MicromarkToken} Token */ +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/52529 +/** @typedef {import("micromark-util-types").TokenType} TokenType */ +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/52529 +/** @typedef {import("../lib/markdownlint.mjs").MicromarkToken} Token */ /** * Determines if a Micromark token is within an htmlFlow type. diff --git a/helpers/micromark-parse.cjs b/helpers/micromark-parse.mjs similarity index 84% rename from helpers/micromark-parse.cjs rename to helpers/micromark-parse.mjs index 0ca3373ed..27eedfb45 100644 --- a/helpers/micromark-parse.cjs +++ b/helpers/micromark-parse.mjs @@ -1,18 +1,24 @@ // @ts-check -"use strict"; +import { directive } from "micromark-extension-directive"; +import { gfmAutolinkLiteral } from "micromark-extension-gfm-autolink-literal"; +import { gfmFootnote } from "micromark-extension-gfm-footnote"; +import { gfmTable } from "micromark-extension-gfm-table"; +import { math } from "micromark-extension-math"; +import { parse as micromarkParse, postprocess as micromarkPostprocess, preprocess as micromarkPreprocess } from "micromark"; +// micromark-core-commonmark is not a dependency because this instance must match what's used by micromark +// eslint-disable-next-line n/no-extraneous-import +import { labelEnd } from "micromark-core-commonmark"; +import { isHtmlFlowComment } from "./micromark-helpers.cjs"; +import { flatTokensSymbol, htmlFlowSymbol, newLineRe } from "./shared.cjs"; -const micromark = require("markdownlint-micromark"); -const { isHtmlFlowComment } = require("./micromark-helpers.cjs"); -const { flatTokensSymbol, htmlFlowSymbol, newLineRe } = require("./shared.js"); - -/** @typedef {import("markdownlint-micromark").Construct} Construct */ -/** @typedef {import("markdownlint-micromark").Event} Event */ -/** @typedef {import("markdownlint-micromark").ParseOptions} MicromarkParseOptions */ -/** @typedef {import("markdownlint-micromark").State} State */ -/** @typedef {import("markdownlint-micromark").Token} Token */ -/** @typedef {import("markdownlint-micromark").Tokenizer} Tokenizer */ -/** @typedef {import("../lib/markdownlint.js").MicromarkToken} MicromarkToken */ +/** @typedef {import("micromark-util-types").Event} Event */ +/** @typedef {import("micromark-util-types").ParseOptions} MicromarkParseOptions */ +/** @typedef {import("micromark-util-types").State} State */ +/** @typedef {import("micromark-util-types").Token} Token */ +/** @typedef {import("micromark-util-types").Tokenizer} Tokenizer */ +/** @typedef {import("./micromark-types.d.mts")} */ +/** @typedef {import("../lib/markdownlint.mjs").MicromarkToken} MicromarkToken */ /** * Parse options. @@ -28,27 +34,23 @@ const { flatTokensSymbol, htmlFlowSymbol, newLineRe } = require("./shared.js"); * @param {MicromarkParseOptions} [micromarkParseOptions] Options for micromark. * @returns {Event[]} Micromark events. */ -function getEvents( +export function getEvents( markdown, micromarkParseOptions = {} ) { // Customize extensions list to add useful extensions const extensions = [ - micromark.directive(), - micromark.gfmAutolinkLiteral(), - micromark.gfmFootnote(), - micromark.gfmTable(), - micromark.math(), + directive(), + gfmAutolinkLiteral(), + gfmFootnote(), + gfmTable(), + math(), ...(micromarkParseOptions.extensions || []) ]; // // Shim labelEnd to identify undefined link labels /** @type {Event[][]} */ const artificialEventLists = []; - /** @type {Construct} */ - const labelEnd = - // @ts-ignore - micromark.labelEnd; const tokenizeOriginal = labelEnd.tokenize; /** @type {Tokenizer} */ @@ -162,9 +164,9 @@ function getEvents( // Use micromark to parse document into Events const encoding = undefined; const eol = true; - const parseContext = micromark.parse({ ...micromarkParseOptions, extensions }); - const chunks = micromark.preprocess()(markdown, encoding, eol); - const events = micromark.postprocess(parseContext.document().write(chunks)); + const parseContext = micromarkParse({ ...micromarkParseOptions, extensions }); + const chunks = micromarkPreprocess()(markdown, encoding, eol); + const events = micromarkPostprocess(parseContext.document().write(chunks)); // Append artificial events and return all events // eslint-disable-next-line unicorn/prefer-spread @@ -214,8 +216,7 @@ function parseInternal( }; const history = [ root ]; let current = root; - // eslint-disable-next-line jsdoc/valid-types - /** @type MicromarkParseOptions | null */ + /** @type {MicromarkParseOptions | null} */ let reparseOptions = null; let lines = null; let skipHtmlFlowChildren = false; @@ -303,11 +304,6 @@ function parseInternal( * @param {ParseOptions} [parseOptions] Options. * @returns {MicromarkToken[]} Micromark tokens. */ -function parse(markdown, parseOptions) { +export function parse(markdown, parseOptions) { return parseInternal(markdown, parseOptions); } - -module.exports = { - getEvents, - parse -}; diff --git a/helpers/micromark-types.d.mts b/helpers/micromark-types.d.mts new file mode 100644 index 000000000..6afc9d0ed --- /dev/null +++ b/helpers/micromark-types.d.mts @@ -0,0 +1,11 @@ +export {}; + +// Augment TokenTypeMap with markdownlint-specific types. +declare module "micromark-util-types" { + export interface TokenTypeMap { + undefinedReference: "undefinedReference" + undefinedReferenceCollapsed: "undefinedReferenceCollapsed" + undefinedReferenceFull: "undefinedReferenceFull" + undefinedReferenceShortcut: "undefinedReferenceShortcut" + } +} diff --git a/helpers/package.json b/helpers/package.json index 4790473f4..e047d252e 100644 --- a/helpers/package.json +++ b/helpers/package.json @@ -2,9 +2,9 @@ "name": "markdownlint-rule-helpers", "version": "0.27.0", "description": "A collection of markdownlint helper functions for custom rules", - "main": "./helpers.js", + "main": "./helpers.cjs", "exports": { - ".": "./helpers.js", + ".": "./helpers.cjs", "./micromark": "./micromark-helpers.cjs" }, "author": "David Anson (https://dlaa.me/)", @@ -20,7 +20,12 @@ "node": ">=18" }, "dependencies": { - "markdownlint-micromark": "0.1.2" + "micromark": "4.0.0", + "micromark-extension-directive": "3.0.2", + "micromark-extension-gfm-autolink-literal": "2.1.0", + "micromark-extension-gfm-footnote": "2.1.0", + "micromark-extension-gfm-table": "2.1.0", + "micromark-extension-math": "3.1.0" }, "keywords": [ "markdownlint", diff --git a/helpers/shared.js b/helpers/shared.cjs similarity index 100% rename from helpers/shared.js rename to helpers/shared.cjs diff --git a/helpers/test.cjs b/helpers/test.cjs index 340ae99d9..cf501b5c0 100644 --- a/helpers/test.cjs +++ b/helpers/test.cjs @@ -7,7 +7,7 @@ const test = require("ava").default; const { "exports": packageExports, name } = require("../helpers/package.json"); const exportMappings = new Map([ - [ ".", "../helpers/helpers.js" ], + [ ".", "../helpers/helpers.cjs" ], [ "./micromark", "../helpers/micromark-helpers.cjs" ] ]); diff --git a/lib/cache.js b/lib/cache.mjs similarity index 62% rename from lib/cache.js rename to lib/cache.mjs index 8d53f33f2..c4af0e977 100644 --- a/lib/cache.js +++ b/lib/cache.mjs @@ -1,9 +1,7 @@ // @ts-check -"use strict"; - -const helpers = require("../helpers"); -const { filterByTypes } = require("../helpers/micromark-helpers.cjs"); +import { getReferenceLinkImageData as helpersGetReferenceLinkImageData } from "../helpers/helpers.cjs"; +import { filterByTypes } from "../helpers/micromark-helpers.cjs"; /** @type {Map} */ const map = new Map(); @@ -12,10 +10,10 @@ let params = undefined; /** * Initializes (resets) the cache. * - * @param {import("./markdownlint").RuleParams} [p] Rule parameters object. + * @param {import("./markdownlint.mjs").RuleParams} [p] Rule parameters object. * @returns {void} */ -function initialize(p) { +export function initialize(p) { map.clear(); params = p; } @@ -39,11 +37,11 @@ function getCached(name, getValue) { /** * Filters a list of Micromark tokens by type and caches the result. * - * @param {import("./markdownlint").MicromarkTokenType[]} types Types to allow. + * @param {import("./markdownlint.mjs").MicromarkTokenType[]} types Types to allow. * @param {boolean} [htmlFlow] Whether to include htmlFlow content. - * @returns {import("./markdownlint").MicromarkToken[]} Filtered tokens. + * @returns {import("./markdownlint.mjs").MicromarkToken[]} Filtered tokens. */ -function filterByTypesCached(types, htmlFlow) { +export function filterByTypesCached(types, htmlFlow) { return getCached( // eslint-disable-next-line prefer-rest-params JSON.stringify(arguments), @@ -56,15 +54,9 @@ function filterByTypesCached(types, htmlFlow) { * * @returns {Object} Reference link and image data object. */ -function getReferenceLinkImageData() { +export function getReferenceLinkImageData() { return getCached( getReferenceLinkImageData.name, - () => helpers.getReferenceLinkImageData(params.parsers.micromark.tokens) + () => helpersGetReferenceLinkImageData(params.parsers.micromark.tokens) ); } - -module.exports = { - initialize, - filterByTypesCached, - getReferenceLinkImageData -}; diff --git a/lib/configuration.d.ts b/lib/configuration.d.ts index 2406f8758..f69918738 100644 --- a/lib/configuration.d.ts +++ b/lib/configuration.d.ts @@ -1,4 +1,4 @@ -import { ConfigurationStrict } from "./configuration-strict"; +import type { ConfigurationStrict } from "./configuration-strict.d.ts"; export interface Configuration extends ConfigurationStrict { /** diff --git a/lib/constants.js b/lib/constants.mjs similarity index 60% rename from lib/constants.js rename to lib/constants.mjs index cdfbfae47..b83a7d9b5 100644 --- a/lib/constants.js +++ b/lib/constants.mjs @@ -1,9 +1,7 @@ // @ts-check -"use strict"; - -module.exports.deprecatedRuleNames = []; -module.exports.fixableRuleNames = [ +export const deprecatedRuleNames = []; +export const fixableRuleNames = [ "MD004", "MD005", "MD007", "MD009", "MD010", "MD011", "MD012", "MD014", "MD018", "MD019", "MD020", "MD021", "MD022", "MD023", "MD026", "MD027", "MD030", "MD031", @@ -11,5 +9,5 @@ module.exports.fixableRuleNames = [ "MD047", "MD049", "MD050", "MD051", "MD053", "MD054", "MD058" ]; -module.exports.homepage = "https://github.com/DavidAnson/markdownlint"; -module.exports.version = "0.36.1"; +export const homepage = "https://github.com/DavidAnson/markdownlint"; +export const version = "0.36.1"; diff --git a/lib/markdownit.cjs b/lib/markdownit.cjs index 5c6349a82..5651dc081 100644 --- a/lib/markdownit.cjs +++ b/lib/markdownit.cjs @@ -4,6 +4,11 @@ const { newLineRe } = require("../helpers"); +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/52529 +/** @typedef {import("./markdownlint.mjs").MarkdownItToken} MarkdownItToken */ +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/52529 +/** @typedef {import("./markdownlint.mjs").Plugin} Plugin */ + /** * @callback InlineCodeSpanCallback * @param {string} code Code content. @@ -67,7 +72,7 @@ function forEachInlineCodeSpan(input, handler) { /** * Freeze all freeze-able members of a token and its children. * - * @param {import("./markdownlint").MarkdownItToken} token A markdown-it token. + * @param {MarkdownItToken} token A markdown-it token. * @returns {void} */ function freezeToken(token) { @@ -98,8 +103,7 @@ function freezeToken(token) { */ function annotateAndFreezeTokens(tokens, lines) { let trMap = null; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("./markdownlint").MarkdownItToken[] */ + /** @type {MarkdownItToken[]} */ // @ts-ignore const markdownItTokens = tokens; for (const token of markdownItTokens) { @@ -148,10 +152,10 @@ function annotateAndFreezeTokens(tokens, lines) { /** * Gets an array of markdown-it tokens for the input. * - * @param {import("./markdownlint").Plugin[]} markdownItPlugins Additional plugins. + * @param {Plugin[]} markdownItPlugins Additional plugins. * @param {string} content Markdown content. * @param {string[]} lines Lines of Markdown content. - * @returns {import("../lib/markdownlint").MarkdownItToken} Array of markdown-it tokens. + * @returns {MarkdownItToken} Array of markdown-it tokens. */ function getMarkdownItTokens(markdownItPlugins, content, lines) { const markdownit = require("markdown-it"); diff --git a/lib/markdownlint.d.ts b/lib/markdownlint.d.mts similarity index 84% rename from lib/markdownlint.d.ts rename to lib/markdownlint.d.mts index d12abe6be..55b425110 100644 --- a/lib/markdownlint.d.ts +++ b/lib/markdownlint.d.mts @@ -1,79 +1,12 @@ -export = markdownlint; -/** - * Lint specified Markdown files. - * - * @param {Options | null} options Configuration options. - * @param {LintCallback} callback Callback (err, result) function. - * @returns {void} - */ -declare function markdownlint(options: Options | null, callback: LintCallback): void; -declare namespace markdownlint { - export { markdownlintSync as sync, readConfig, readConfigSync, getVersion, promises, applyFix, applyFixes, RuleFunction, RuleParams, MarkdownParsers, ParserMarkdownIt, ParserMicromark, MarkdownItToken, MicromarkTokenType, MicromarkToken, RuleOnError, RuleOnErrorInfo, RuleOnErrorFixInfo, RuleOnErrorFixInfoNormalized, Rule, Options, Plugin, ToStringCallback, LintResults, LintError, FixInfo, LintContentCallback, LintCallback, Configuration, ConfigurationStrict, RuleConfiguration, ConfigurationParser, ReadConfigCallback, ResolveConfigExtendsCallback }; -} -/** - * Lint specified Markdown files synchronously. - * - * @param {Options | null} options Configuration options. - * @returns {LintResults} Results object. - */ -declare function markdownlintSync(options: Options | null): LintResults; -/** - * Read specified configuration file. - * - * @param {string} file Configuration file name. - * @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing - * function(s). - * @param {Object} [fs] File system implementation. - * @param {ReadConfigCallback} [callback] Callback (err, result) function. - * @returns {void} - */ -declare function readConfig(file: string, parsers: ConfigurationParser[] | ReadConfigCallback, fs?: any, callback?: ReadConfigCallback): void; -/** - * Read specified configuration file synchronously. - * - * @param {string} file Configuration file name. - * @param {ConfigurationParser[]} [parsers] Parsing function(s). - * @param {Object} [fs] File system implementation. - * @returns {Configuration} Configuration object. - * @throws An Error if processing fails. - */ -declare function readConfigSync(file: string, parsers?: ConfigurationParser[], fs?: any): Configuration; -/** - * Gets the (semantic) version of the library. - * - * @returns {string} SemVer string. - */ -declare function getVersion(): string; -declare namespace promises { - export { markdownlintPromise as markdownlint }; - export { extendConfigPromise as extendConfig }; - export { readConfigPromise as readConfig }; -} -/** - * Applies the specified fix to a Markdown content line. - * - * @param {string} line Line of Markdown content. - * @param {RuleOnErrorFixInfo} fixInfo RuleOnErrorFixInfo instance. - * @param {string} [lineEnding] Line ending to use. - * @returns {string | null} Fixed content or null if deleted. - */ -declare function applyFix(line: string, fixInfo: RuleOnErrorFixInfo, lineEnding?: string): string | null; -/** - * Applies as many of the specified fixes as possible to Markdown content. - * - * @param {string} input Lines of Markdown content. - * @param {RuleOnErrorInfo[]} errors RuleOnErrorInfo instances. - * @returns {string} Fixed content. - */ -declare function applyFixes(input: string, errors: RuleOnErrorInfo[]): string; +export default markdownlint; /** * Function to implement rule logic. */ -type RuleFunction = (params: RuleParams, onError: RuleOnError) => void; +export type RuleFunction = (params: RuleParams, onError: RuleOnError) => void; /** * Rule parameters. */ -type RuleParams = { +export type RuleParams = { /** * File/string name. */ @@ -102,7 +35,7 @@ type RuleParams = { /** * Markdown parser data. */ -type MarkdownParsers = { +export type MarkdownParsers = { /** * Markdown parser data from markdown-it (only present when Rule.parser is "markdownit"). */ @@ -115,7 +48,7 @@ type MarkdownParsers = { /** * Markdown parser data from markdown-it. */ -type ParserMarkdownIt = { +export type ParserMarkdownIt = { /** * Token objects from markdown-it. */ @@ -124,7 +57,7 @@ type ParserMarkdownIt = { /** * Markdown parser data from micromark. */ -type ParserMicromark = { +export type ParserMicromark = { /** * Token objects from micromark. */ @@ -133,7 +66,7 @@ type ParserMicromark = { /** * markdown-it token. */ -type MarkdownItToken = { +export type MarkdownItToken = { /** * HTML attributes. */ @@ -195,11 +128,11 @@ type MarkdownItToken = { */ line: string; }; -type MicromarkTokenType = import("markdownlint-micromark").TokenType; +export type MicromarkTokenType = import("micromark-util-types").TokenType; /** * micromark token. */ -type MicromarkToken = { +export type MicromarkToken = { /** * Token type. */ @@ -236,11 +169,11 @@ type MicromarkToken = { /** * Error-reporting callback. */ -type RuleOnError = (onErrorInfo: RuleOnErrorInfo) => void; +export type RuleOnError = (onErrorInfo: RuleOnErrorInfo) => void; /** * Fix information for RuleOnError callback. */ -type RuleOnErrorInfo = { +export type RuleOnErrorInfo = { /** * Line number (1-based). */ @@ -269,7 +202,7 @@ type RuleOnErrorInfo = { /** * Fix information for RuleOnErrorInfo. */ -type RuleOnErrorFixInfo = { +export type RuleOnErrorFixInfo = { /** * Line number (1-based). */ @@ -290,7 +223,7 @@ type RuleOnErrorFixInfo = { /** * RuleOnErrorInfo with all optional properties present. */ -type RuleOnErrorFixInfoNormalized = { +export type RuleOnErrorFixInfoNormalized = { /** * Line number (1-based). */ @@ -311,7 +244,7 @@ type RuleOnErrorFixInfoNormalized = { /** * Rule definition. */ -type Rule = { +export type Rule = { /** * Rule name(s). */ @@ -344,7 +277,7 @@ type Rule = { /** * Configuration options. */ -type Options = { +export type Options = { /** * Configuration object. */ @@ -395,21 +328,21 @@ type Options = { /** * A markdown-it plugin. */ -type Plugin = any[]; +export type Plugin = any[]; /** * Function to pretty-print lint results. */ -type ToStringCallback = (ruleAliases?: boolean) => string; +export type ToStringCallback = (ruleAliases?: boolean) => string; /** * Lint results (for resultVersion 3). */ -type LintResults = { +export type LintResults = { [x: string]: LintError[]; }; /** * Lint error. */ -type LintError = { +export type LintError = { /** * Line number (1-based). */ @@ -446,7 +379,7 @@ type LintError = { /** * Fix information. */ -type FixInfo = { +export type FixInfo = { /** * Line number (1-based). */ @@ -467,37 +400,92 @@ type FixInfo = { /** * Called with the result of linting a string or document. */ -type LintContentCallback = (error: Error | null, result?: LintError[]) => void; +export type LintContentCallback = (error: Error | null, result?: LintError[]) => void; /** * Called with the result of the lint function. */ -type LintCallback = (error: Error | null, results?: LintResults) => void; +export type LintCallback = (error: Error | null, results?: LintResults) => void; /** * Configuration object for linting rules. For the JSON schema, see * {@link ../schema/markdownlint-config-schema.json}. */ -type Configuration = import("./configuration").Configuration; +export type Configuration = import("./configuration.d.ts").Configuration; /** * Configuration object for linting rules strictly. For the JSON schema, see * {@link ../schema/markdownlint-config-schema-strict.json}. */ -type ConfigurationStrict = import("./configuration-strict").ConfigurationStrict; +export type ConfigurationStrict = import("./configuration-strict.d.ts").ConfigurationStrict; /** * Rule configuration. */ -type RuleConfiguration = boolean | any; +export type RuleConfiguration = boolean | any; /** * Parses a configuration string and returns a configuration object. */ -type ConfigurationParser = (text: string) => Configuration; +export type ConfigurationParser = (text: string) => Configuration; /** * Called with the result of the readConfig function. */ -type ReadConfigCallback = (err: Error | null, config?: Configuration) => void; +export type ReadConfigCallback = (err: Error | null, config?: Configuration) => void; /** * Called with the result of the resolveConfigExtends function. */ -type ResolveConfigExtendsCallback = (err: Error | null, path?: string) => void; +export type ResolveConfigExtendsCallback = (err: Error | null, path?: string) => void; +/** + * Lint specified Markdown files. + * + * @param {Options | null} options Configuration options. + * @param {LintCallback} callback Callback (err, result) function. + * @returns {void} + */ +declare function markdownlint(options: Options | null, callback: LintCallback): void; +declare namespace markdownlint { + export { markdownlintSync as sync }; + export { readConfig }; + export { readConfigSync }; + export { getVersion }; + export namespace promises { + export { markdownlintPromise as markdownlint }; + export { extendConfigPromise as extendConfig }; + export { readConfigPromise as readConfig }; + } + export { applyFix }; + export { applyFixes }; +} +/** + * Lint specified Markdown files synchronously. + * + * @param {Options | null} options Configuration options. + * @returns {LintResults} Results object. + */ +declare function markdownlintSync(options: Options | null): LintResults; +/** + * Read specified configuration file. + * + * @param {string} file Configuration file name. + * @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing + * function(s). + * @param {Object} [fs] File system implementation. + * @param {ReadConfigCallback} [callback] Callback (err, result) function. + * @returns {void} + */ +declare function readConfig(file: string, parsers: ConfigurationParser[] | ReadConfigCallback, fs?: any, callback?: ReadConfigCallback): void; +/** + * Read specified configuration file synchronously. + * + * @param {string} file Configuration file name. + * @param {ConfigurationParser[]} [parsers] Parsing function(s). + * @param {Object} [fs] File system implementation. + * @returns {Configuration} Configuration object. + * @throws An Error if processing fails. + */ +declare function readConfigSync(file: string, parsers?: ConfigurationParser[], fs?: any): Configuration; +/** + * Gets the (semantic) version of the library. + * + * @returns {string} SemVer string. + */ +declare function getVersion(): string; /** * Lint specified Markdown files. * @@ -524,3 +512,20 @@ declare function extendConfigPromise(config: Configuration, file: string, parser * @returns {Promise} Configuration object. */ declare function readConfigPromise(file: string, parsers?: ConfigurationParser[], fs?: any): Promise; +/** + * Applies the specified fix to a Markdown content line. + * + * @param {string} line Line of Markdown content. + * @param {RuleOnErrorFixInfo} fixInfo RuleOnErrorFixInfo instance. + * @param {string} [lineEnding] Line ending to use. + * @returns {string | null} Fixed content or null if deleted. + */ +declare function applyFix(line: string, fixInfo: RuleOnErrorFixInfo, lineEnding?: string): string | null; +/** + * Applies as many of the specified fixes as possible to Markdown content. + * + * @param {string} input Lines of Markdown content. + * @param {RuleOnErrorInfo[]} errors RuleOnErrorInfo instances. + * @returns {string} Fixed content. + */ +declare function applyFixes(input: string, errors: RuleOnErrorInfo[]): string; diff --git a/lib/markdownlint.js b/lib/markdownlint.mjs similarity index 97% rename from lib/markdownlint.js rename to lib/markdownlint.mjs index 685f0911b..9e2d505b5 100644 --- a/lib/markdownlint.js +++ b/lib/markdownlint.mjs @@ -1,19 +1,16 @@ // @ts-check -"use strict"; - -const path = require("node:path"); -const { promisify } = require("node:util"); -const micromark = require("../helpers/micromark-parse.cjs"); -const { version } = require("./constants"); -const rules = require("./rules"); -const helpers = require("../helpers"); -const cache = require("./cache"); - -// @ts-ignore -// eslint-disable-next-line camelcase, no-inline-comments, no-undef -const dynamicRequire = (typeof __non_webpack_require__ === "undefined") ? require : /* c8 ignore next */ __non_webpack_require__; -// Capture native require implementation for dynamic loading of modules +import * as nodeFs from "node:fs"; +import { createRequire } from "node:module"; +const dynamicRequire = createRequire(import.meta.url); +import * as os from "node:os"; +import path from "node:path"; +import { promisify } from "node:util"; +import { initialize as cacheInitialize } from "./cache.mjs"; +import { version } from "./constants.mjs"; +import rules from "./rules.mjs"; +import { parse as micromarkParse } from "../helpers/micromark-parse.mjs"; +import * as helpers from "../helpers/helpers.cjs"; /** * Validate the list of rules for structure and reuse. @@ -497,7 +494,7 @@ function lintContent( ); const customRulesPresent = (ruleList.length !== rules.length); // Parse content into parser tokens - const micromarkTokens = micromark.parse( + const micromarkTokens = micromarkParse( content, { "freezeTokens": customRulesPresent } ); @@ -507,7 +504,7 @@ function lintContent( // Parse content into lines and get markdown-it tokens const lines = content.split(helpers.newLineRe); const markdownitTokens = needMarkdownItTokens ? - require("./markdownit.cjs").getMarkdownItTokens(markdownItPlugins, preClearedContent, lines) : + dynamicRequire("./markdownit.cjs").getMarkdownItTokens(markdownItPlugins, preClearedContent, lines) : []; // Create (frozen) parameters for rules /** @type {MarkdownParsers} */ @@ -533,7 +530,7 @@ function lintContent( "lines": Object.freeze(lines), "frontMatterLines": Object.freeze(frontMatterLines) }; - cache.initialize({ + cacheInitialize({ ...paramsBase, "parsers": parsersMicromark, "config": null @@ -751,7 +748,7 @@ function lintContent( } catch (error) { callbackError(error); } finally { - cache.initialize(); + cacheInitialize(); } } @@ -866,7 +863,7 @@ function lintInput(options, synchronous, callback) { 3 : options.resultVersion; const markdownItPlugins = options.markdownItPlugins || []; - const fs = options.fs || require("node:fs"); + const fs = options.fs || nodeFs; const aliasToRuleNames = mapAliasToRuleNames(ruleList); const results = newResults(ruleList); let done = false; @@ -1068,7 +1065,7 @@ function extendConfig(config, file, parsers, fs, callback) { if (configExtends) { return resolveConfigExtends( file, - helpers.expandTildePath(configExtends, require("node:os")), + helpers.expandTildePath(configExtends, os), fs, // eslint-disable-next-line no-use-before-define (_, resolvedExtends) => readConfig( @@ -1132,10 +1129,10 @@ function readConfig(file, parsers, fs, callback) { } } if (!fs) { - fs = require("node:fs"); + fs = nodeFs; } // Read file - file = helpers.expandTildePath(file, require("node:os")); + file = helpers.expandTildePath(file, os); fs.readFile(file, "utf8", (err, content) => { if (err) { // @ts-ignore @@ -1180,10 +1177,9 @@ function readConfigPromise(file, parsers, fs) { */ function readConfigSync(file, parsers, fs) { if (!fs) { - fs = require("node:fs"); + fs = nodeFs; } // Read file - const os = require("node:os"); file = helpers.expandTildePath(file, os); const content = fs.readFileSync(file, "utf8"); // Try to parse file @@ -1248,7 +1244,7 @@ function applyFix(line, fixInfo, lineEnding = "\n") { * @returns {string} Fixed content. */ function applyFixes(input, errors) { - const lineEnding = helpers.getPreferredLineEnding(input, require("node:os")); + const lineEnding = helpers.getPreferredLineEnding(input, os); const lines = input.split(helpers.newLineRe); // Normalize fixInfo objects let fixInfos = errors @@ -1267,8 +1263,7 @@ function applyFixes(input, errors) { ); }); // Remove duplicate entries (needed for following collapse step) - // eslint-disable-next-line jsdoc/valid-types - /** @type RuleOnErrorFixInfo */ + /** @type {RuleOnErrorFixInfo} */ let lastFixInfo = {}; fixInfos = fixInfos.filter((fixInfo) => { const unique = ( @@ -1342,7 +1337,7 @@ markdownlint.promises = { }; markdownlint.applyFix = applyFix; markdownlint.applyFixes = applyFixes; -module.exports = markdownlint; +export default markdownlint; // Type declarations @@ -1414,7 +1409,7 @@ module.exports = markdownlint; * @property {string} line Line content. */ -/** @typedef {import("markdownlint-micromark").TokenType} MicromarkTokenType */ +/** @typedef {import("micromark-util-types").TokenType} MicromarkTokenType */ /** * micromark token. @@ -1567,14 +1562,14 @@ module.exports = markdownlint; * Configuration object for linting rules. For the JSON schema, see * {@link ../schema/markdownlint-config-schema.json}. * - * @typedef {import("./configuration").Configuration} Configuration + * @typedef {import("./configuration.d.ts").Configuration} Configuration */ /** * Configuration object for linting rules strictly. For the JSON schema, see * {@link ../schema/markdownlint-config-schema-strict.json}. * - * @typedef {import("./configuration-strict").ConfigurationStrict} ConfigurationStrict + * @typedef {import("./configuration-strict.d.ts").ConfigurationStrict} ConfigurationStrict */ /** diff --git a/lib/md001.js b/lib/md001.mjs similarity index 67% rename from lib/md001.js rename to lib/md001.mjs index 1befb179c..cbbc5f876 100644 --- a/lib/md001.js +++ b/lib/md001.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getHeadingLevel } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getHeadingLevel } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD001", "heading-increment" ], "description": "Heading levels should only increment by one level at a time", "tags": [ "headings" ], diff --git a/lib/md003.js b/lib/md003.mjs similarity index 81% rename from lib/md003.js rename to lib/md003.mjs index a4c21f6bb..24caa3d75 100644 --- a/lib/md003.js +++ b/lib/md003.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getHeadingLevel, getHeadingStyle } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getHeadingLevel, getHeadingStyle } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD003", "heading-style" ], "description": "Heading style", "tags": [ "headings" ], diff --git a/lib/md004.js b/lib/md004.mjs similarity index 87% rename from lib/md004.js rename to lib/md004.mjs index 79e06eb7d..3162702c1 100644 --- a/lib/md004.js +++ b/lib/md004.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getDescendantsByType, getParentOfType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getDescendantsByType, getParentOfType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const markerToStyle = { "-": "dash", @@ -28,10 +26,8 @@ const validStyles = new Set([ "plus", "sublist" ]); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD004", "ul-style" ], "description": "Unordered list style", "tags": [ "bullet", "ul" ], diff --git a/lib/md005.js b/lib/md005.mjs similarity index 90% rename from lib/md005.js rename to lib/md005.mjs index e439ba3aa..010d57bb1 100644 --- a/lib/md005.js +++ b/lib/md005.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addError, addErrorDetailIf } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError, addErrorDetailIf } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD005", "list-indent" ], "description": "Inconsistent indentation for list items at the same level", "tags": [ "bullet", "ul", "indentation" ], diff --git a/lib/md007.js b/lib/md007.mjs similarity index 83% rename from lib/md007.js rename to lib/md007.mjs index 8d9078562..947fca737 100644 --- a/lib/md007.js +++ b/lib/md007.mjs @@ -1,23 +1,16 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getParentOfType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("markdownlint-micromark").TokenType[] */ +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getParentOfType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("micromark-util-types").TokenType[]} */ const unorderedListTypes = [ "blockQuotePrefix", "listItemPrefix", "listUnordered" ]; -// eslint-disable-next-line jsdoc/valid-types -/** @type import("markdownlint-micromark").TokenType[] */ +/** @type {import("micromark-util-types").TokenType[]} */ const unorderedParentTypes = [ "blockQuote", "listOrdered", "listUnordered" ]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD007", "ul-indent" ], "description": "Unordered list indentation", "tags": [ "bullet", "ul", "indentation" ], diff --git a/lib/md009.js b/lib/md009.mjs similarity index 91% rename from lib/md009.js rename to lib/md009.mjs index f51f31392..bab4af83a 100644 --- a/lib/md009.js +++ b/lib/md009.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addError } = require("../helpers"); -const { addRangeToSet } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError } from "../helpers/helpers.cjs"; +import { addRangeToSet } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD009", "no-trailing-spaces" ], "description": "Trailing spaces", "tags": [ "whitespace" ], diff --git a/lib/md010.js b/lib/md010.mjs similarity index 84% rename from lib/md010.js rename to lib/md010.mjs index 61e1aa46d..2f1b1c7cd 100644 --- a/lib/md010.js +++ b/lib/md010.mjs @@ -1,16 +1,12 @@ // @ts-check -"use strict"; - -const { addError, hasOverlap } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addError, hasOverlap } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const tabRe = /\t+/g; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD010", "no-hard-tabs" ], "description": "Hard tabs", "tags": [ "whitespace", "hard_tab" ], @@ -26,8 +22,7 @@ module.exports = { const spaceMultiplier = (spacesPerTab === undefined) ? 1 : Math.max(0, Number(spacesPerTab)); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../helpers/micromark-helpers.cjs").TokenType[] */ + /** @type {import("../helpers/micromark-helpers.cjs").TokenType[]} */ const exclusionTypes = []; if (includeCode) { if (ignoreCodeLanguages.size > 0) { @@ -60,7 +55,7 @@ module.exports = { const lineNumber = lineIndex + 1; const column = match.index + 1; const length = match[0].length; - /** @type {import("../helpers").FileRange} */ + /** @type {import("../helpers/helpers.cjs").FileRange} */ const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 }; if (!codeRanges.some((codeRange) => hasOverlap(codeRange, range))) { addError( diff --git a/lib/md011.js b/lib/md011.mjs similarity index 83% rename from lib/md011.js rename to lib/md011.mjs index 126c56a5a..16ec176b6 100644 --- a/lib/md011.js +++ b/lib/md011.mjs @@ -1,17 +1,13 @@ // @ts-check -"use strict"; - -const { addError, hasOverlap } = require("../helpers"); -const { addRangeToSet } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addError, hasOverlap } from "../helpers/helpers.cjs"; +import { addRangeToSet } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const reversedLinkRe = /(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD011", "no-reversed-links" ], "description": "Reversed link syntax", "tags": [ "links" ], @@ -34,7 +30,7 @@ module.exports = { ) { const column = match.index + preChar.length + 1; const length = match[0].length - preChar.length; - /** @type {import("../helpers").FileRange} */ + /** @type {import("../helpers/helpers.cjs").FileRange} */ const range = { "startLine": lineNumber, "startColumn": column, "endLine": lineNumber, "endColumn": column + length - 1 }; if (!codeTexts.some((codeText) => hasOverlap(codeText, range))) { addError( diff --git a/lib/md012.js b/lib/md012.mjs similarity index 77% rename from lib/md012.js rename to lib/md012.mjs index 817263618..cfd4927cd 100644 --- a/lib/md012.js +++ b/lib/md012.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { addRangeToSet } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { addRangeToSet } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD012", "no-multiple-blanks" ], "description": "Multiple consecutive blank lines", "tags": [ "whitespace", "blank_lines" ], diff --git a/lib/md013.js b/lib/md013.mjs similarity index 91% rename from lib/md013.js rename to lib/md013.mjs index 67cac7566..06e9fc5ea 100644 --- a/lib/md013.js +++ b/lib/md013.mjs @@ -1,20 +1,15 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getReferenceLinkImageData } = require("./cache"); -const { addRangeToSet, getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { filterByTypesCached, getReferenceLinkImageData } from "./cache.mjs"; +import { addRangeToSet, getDescendantsByType } from "../helpers/micromark-helpers.cjs"; const longLineRePrefix = "^.{"; const longLineRePostfixRelaxed = "}.*\\s.*$"; const longLineRePostfixStrict = "}.+$"; const sternModeRe = /^(?:[#>\s]*\s)?\S*$/; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD013", "line-length" ], "description": "Line length", "tags": [ "line_length" ], diff --git a/lib/md014.js b/lib/md014.mjs similarity index 86% rename from lib/md014.js rename to lib/md014.mjs index 532ecd72a..285b75428 100644 --- a/lib/md014.js +++ b/lib/md014.mjs @@ -1,15 +1,11 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); +import { addErrorContext } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const dollarCommandRe = /^(\s*)(\$\s+)/; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD014", "commands-show-output" ], "description": "Dollar signs used before commands without showing output", "tags": [ "code" ], diff --git a/lib/md018.js b/lib/md018.mjs similarity index 78% rename from lib/md018.js rename to lib/md018.mjs index 271eceb83..1c2a844b2 100644 --- a/lib/md018.js +++ b/lib/md018.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { addRangeToSet } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext } from "../helpers/helpers.cjs"; +import { addRangeToSet } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD018", "no-missing-space-atx" ], "description": "No space after hash on atx style heading", "tags": [ "headings", "atx", "spaces" ], diff --git a/lib/md019-md021.js b/lib/md019-md021.mjs similarity index 81% rename from lib/md019-md021.js rename to lib/md019-md021.mjs index 4811936f4..a4f1d3bbb 100644 --- a/lib/md019-md021.js +++ b/lib/md019-md021.mjs @@ -1,16 +1,14 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers/helpers"); -const { getHeadingStyle } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorContext } from "../helpers/helpers.cjs"; +import { getHeadingStyle } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; /** * Validate heading sequence and whitespace length at start or end. * - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. - * @param {import("./markdownlint").MicromarkToken} heading ATX heading token. + * @param {import("./markdownlint.mjs").RuleOnError} onError Error-reporting callback. + * @param {import("./markdownlint.mjs").MicromarkToken} heading ATX heading token. * @param {number} delta Direction to scan. * @returns {void} */ @@ -46,10 +44,8 @@ function validateHeadingSpaces(onError, heading, delta) { ); } } - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule[] */ -module.exports = [ +/** @type {import("./markdownlint.mjs").Rule[]} */ +export default [ { "names": [ "MD019", "no-multiple-space-atx" ], "description": "Multiple spaces after hash on atx style heading", diff --git a/lib/md020.js b/lib/md020.mjs similarity index 87% rename from lib/md020.js rename to lib/md020.mjs index 5bd2a099b..f9b524e27 100644 --- a/lib/md020.js +++ b/lib/md020.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { addRangeToSet } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext } from "../helpers/helpers.cjs"; +import { addRangeToSet } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD020", "no-missing-space-closed-atx" ], "description": "No space inside hashes on closed atx style heading", "tags": [ "headings", "atx_closed", "spaces" ], diff --git a/lib/md022.js b/lib/md022.mjs similarity index 88% rename from lib/md022.js rename to lib/md022.mjs index dbe2e0205..6ddab0588 100644 --- a/lib/md022.js +++ b/lib/md022.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf, isBlankLine } = require("../helpers"); -const { getBlockQuotePrefixText, getHeadingLevel } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf, isBlankLine } from "../helpers/helpers.cjs"; +import { getBlockQuotePrefixText, getHeadingLevel } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const defaultLines = 1; @@ -20,10 +18,8 @@ const getLinesFunction = (linesParam) => { const lines = (linesParam === undefined) ? defaultLines : Number(linesParam); return () => lines; }; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD022", "blanks-around-headings" ], "description": "Headings should be surrounded by blank lines", "tags": [ "headings", "blank_lines" ], diff --git a/lib/md023.js b/lib/md023.mjs similarity index 81% rename from lib/md023.js rename to lib/md023.mjs index f00dacf55..efe8c9dad 100644 --- a/lib/md023.js +++ b/lib/md023.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD023", "heading-start-left" ], "description": "Headings must start at the beginning of the line", "tags": [ "headings", "spaces" ], diff --git a/lib/md024.js b/lib/md024.mjs similarity index 78% rename from lib/md024.js rename to lib/md024.mjs index e43b326dc..3d0a062e5 100644 --- a/lib/md024.js +++ b/lib/md024.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { getHeadingLevel, getHeadingText } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext } from "../helpers/helpers.cjs"; +import { getHeadingLevel, getHeadingText } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD024", "no-duplicate-heading" ], "description": "Multiple headings with the same content", "tags": [ "headings" ], diff --git a/lib/md025.js b/lib/md025.mjs similarity index 74% rename from lib/md025.js rename to lib/md025.mjs index d7350be55..ee31bc338 100644 --- a/lib/md025.js +++ b/lib/md025.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorContext, frontMatterHasTitle } = require("../helpers"); -const { getHeadingLevel, getHeadingText } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext, frontMatterHasTitle } from "../helpers/helpers.cjs"; +import { getHeadingLevel, getHeadingText } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD025", "single-title", "single-h1" ], "description": "Multiple top-level headings in the same document", "tags": [ "headings" ], diff --git a/lib/md026.js b/lib/md026.mjs similarity index 79% rename from lib/md026.js rename to lib/md026.mjs index 1ab4b6b02..d5f4461b4 100644 --- a/lib/md026.js +++ b/lib/md026.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addError, allPunctuationNoQuestion, endOfLineGemojiCodeRe, - endOfLineHtmlEntityRe, escapeForRegExp } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError, allPunctuationNoQuestion, endOfLineGemojiCodeRe, + endOfLineHtmlEntityRe, escapeForRegExp } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD026", "no-trailing-punctuation" ], "description": "Trailing punctuation in heading", "tags": [ "headings" ], diff --git a/lib/md027.js b/lib/md027.mjs similarity index 82% rename from lib/md027.js rename to lib/md027.mjs index 6c19b1a20..4bc02ecfc 100644 --- a/lib/md027.js +++ b/lib/md027.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD027", "no-multiple-space-blockquote" ], "description": "Multiple spaces after blockquote symbol", "tags": [ "blockquote", "whitespace", "indentation" ], diff --git a/lib/md028.js b/lib/md028.mjs similarity index 84% rename from lib/md028.js rename to lib/md028.mjs index 8ca3c2a23..428927160 100644 --- a/lib/md028.js +++ b/lib/md028.mjs @@ -1,15 +1,11 @@ // @ts-check -"use strict"; - -const { addError } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); +import { addError } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const ignoreTypes = new Set([ "lineEnding", "listItemIndent", "linePrefix" ]); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD028", "no-blanks-blockquote" ], "description": "Blank line inside blockquote", "tags": [ "blockquote", "whitespace" ], diff --git a/lib/md029.js b/lib/md029.mjs similarity index 87% rename from lib/md029.js rename to lib/md029.mjs index 5cf34c1f3..4500d60f0 100644 --- a/lib/md029.js +++ b/lib/md029.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const listStyleExamples = { "one": "1/1/1", @@ -21,10 +19,8 @@ const listStyleExamples = { function getOrderedListItemValue(listItemPrefix) { return Number(getDescendantsByType(listItemPrefix, [ "listItemValue" ])[0].text); } - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD029", "ol-prefix" ], "description": "Ordered list item prefix", "tags": [ "ol" ], diff --git a/lib/md030.js b/lib/md030.mjs similarity index 89% rename from lib/md030.js rename to lib/md030.mjs index 7defdd90f..05b9e5c60 100644 --- a/lib/md030.js +++ b/lib/md030.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD030", "list-marker-space" ], "description": "Spaces after list markers", "tags": [ "ol", "ul", "whitespace" ], diff --git a/lib/md031.js b/lib/md031.mjs similarity index 80% rename from lib/md031.js rename to lib/md031.mjs index fff6031b7..5e010bc6d 100644 --- a/lib/md031.js +++ b/lib/md031.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorContext, isBlankLine } = require("../helpers"); -const { getParentOfType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorContext, isBlankLine } from "../helpers/helpers.cjs"; +import { getParentOfType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const codeFencePrefixRe = /^(.*?)[`~]/; @@ -14,7 +12,7 @@ const codeFencePrefixRe = /^(.*?)[`~]/; /** * Adds an error for the top or bottom of a code fence. * - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. + * @param {import("./markdownlint.mjs").RuleOnError} onError Error-reporting callback. * @param {ReadonlyStringArray} lines Lines of Markdown content. * @param {number} lineNumber Line number. * @param {boolean} top True iff top fence. @@ -24,7 +22,7 @@ function addError(onError, lines, lineNumber, top) { const line = lines[lineNumber - 1]; const [ , prefix ] = line.match(codeFencePrefixRe) || []; const fixInfo = (prefix === undefined) ? - null : + undefined : { "lineNumber": lineNumber + (top ? 0 : 1), "insertText": `${prefix.replace(/[^>]/g, " ").trim()}\n` @@ -39,10 +37,8 @@ function addError(onError, lines, lineNumber, top) { fixInfo ); } - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD031", "blanks-around-fences" ], "description": "Fenced code blocks should be surrounded by blank lines", "tags": [ "code", "blank_lines" ], diff --git a/lib/md032.js b/lib/md032.mjs similarity index 85% rename from lib/md032.js rename to lib/md032.mjs index a1d6b32c9..1d3b57303 100644 --- a/lib/md032.js +++ b/lib/md032.mjs @@ -1,18 +1,14 @@ // @ts-check -"use strict"; - -const { addErrorContext, isBlankLine } = require("../helpers"); -const { filterByPredicate, getBlockQuotePrefixText, nonContentTokens } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorContext, isBlankLine } from "../helpers/helpers.cjs"; +import { filterByPredicate, getBlockQuotePrefixText, nonContentTokens } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const isList = (token) => ( (token.type === "listOrdered") || (token.type === "listUnordered") ); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD032", "blanks-around-lists" ], "description": "Lists should be surrounded by blank lines", "tags": [ "bullet", "ul", "ol", "blank_lines" ], diff --git a/lib/md033.js b/lib/md033.mjs similarity index 75% rename from lib/md033.js rename to lib/md033.mjs index e0906b404..efe4ccc50 100644 --- a/lib/md033.js +++ b/lib/md033.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addError, nextLinesRe } = require("../helpers"); -const { getHtmlTagInfo } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError, nextLinesRe } from "../helpers/helpers.cjs"; +import { getHtmlTagInfo } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD033", "no-inline-html" ], "description": "Inline HTML", "tags": [ "html" ], diff --git a/lib/md034.js b/lib/md034.mjs similarity index 90% rename from lib/md034.js rename to lib/md034.mjs index c8a5dc7f4..f2a0dec53 100644 --- a/lib/md034.js +++ b/lib/md034.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { filterByPredicate, getHtmlTagInfo, inHtmlFlow } = require("../helpers/micromark-helpers.cjs"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext } from "../helpers/helpers.cjs"; +import { filterByPredicate, getHtmlTagInfo, inHtmlFlow } from "../helpers/micromark-helpers.cjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD034", "no-bare-urls" ], "description": "Bare URL used", "tags": [ "links", "url" ], diff --git a/lib/md035.js b/lib/md035.mjs similarity index 70% rename from lib/md035.js rename to lib/md035.mjs index 23192212a..edc96755b 100644 --- a/lib/md035.js +++ b/lib/md035.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD035", "hr-style" ], "description": "Horizontal rule style", "tags": [ "hr" ], diff --git a/lib/md036.js b/lib/md036.mjs similarity index 80% rename from lib/md036.js rename to lib/md036.mjs index 95f83e270..f5a8e6260 100644 --- a/lib/md036.js +++ b/lib/md036.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorContext, allPunctuation } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorContext, allPunctuation } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; /** @typedef {import("../helpers/micromark-helpers.cjs").TokenType} TokenType */ /** @type {TokenType[][]} */ @@ -12,10 +10,8 @@ const emphasisTypes = [ [ "emphasis", "emphasisText" ], [ "strong", "strongText" ] ]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD036", "no-emphasis-as-heading" ], "description": "Emphasis used instead of a heading", "tags": [ "headings", "emphasis" ], diff --git a/lib/md037.js b/lib/md037.mjs similarity index 92% rename from lib/md037.js rename to lib/md037.mjs index 3dfe667ad..884285c12 100644 --- a/lib/md037.js +++ b/lib/md037.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addError } = require("../helpers"); -const { filterByPredicate, inHtmlFlow } = require("../helpers/micromark-helpers.cjs"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError } from "../helpers/helpers.cjs"; +import { filterByPredicate, inHtmlFlow } from "../helpers/micromark-helpers.cjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD037", "no-space-in-emphasis" ], "description": "Spaces inside emphasis markers", "tags": [ "whitespace", "emphasis" ], diff --git a/lib/md038.js b/lib/md038.mjs similarity index 91% rename from lib/md038.js rename to lib/md038.mjs index 404d1f14d..d472405e6 100644 --- a/lib/md038.js +++ b/lib/md038.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorContext } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const leftSpaceRe = /^\s(?:[^`]|$)/; const rightSpaceRe = /[^`]\s$/; @@ -18,10 +16,8 @@ const trimCodeText = (text, start, end) => { } return text; }; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD038", "no-space-in-code" ], "description": "Spaces inside code span elements", "tags": [ "whitespace", "code" ], diff --git a/lib/md039.js b/lib/md039.mjs similarity index 87% rename from lib/md039.js rename to lib/md039.mjs index 56c3aedc4..bca59462b 100644 --- a/lib/md039.js +++ b/lib/md039.mjs @@ -1,14 +1,12 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { getReferenceLinkImageData, filterByTypesCached } = require("./cache"); +import { addErrorContext } from "../helpers/helpers.cjs"; +import { getReferenceLinkImageData, filterByTypesCached } from "./cache.mjs"; /** * Adds an error for a label space issue. * - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. + * @param {import("./markdownlint.mjs").RuleOnError} onError Error-reporting callback. * @param {import("../helpers/micromark-helpers.cjs").Token} label Label token. * @param {import("../helpers/micromark-helpers.cjs").Token} labelText LabelText token. * @param {boolean} isStart True iff error is at the start of the link. @@ -48,10 +46,8 @@ function addLabelSpaceError(onError, label, labelText, isStart) { function validLink(label, labelText, definitions) { return (label.parent?.children.length !== 1) || definitions.has(labelText.text.trim()); } - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD039", "no-space-in-links" ], "description": "Spaces inside link text", "tags": [ "whitespace", "links" ], diff --git a/lib/md040.js b/lib/md040.mjs similarity index 78% rename from lib/md040.js rename to lib/md040.mjs index 69ae47e16..81183a1c0 100644 --- a/lib/md040.js +++ b/lib/md040.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addError, addErrorContext } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError, addErrorContext } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD040", "fenced-code-language" ], "description": "Fenced code blocks should have a language specified", "tags": [ "code", "language" ], diff --git a/lib/md041.js b/lib/md041.mjs similarity index 78% rename from lib/md041.js rename to lib/md041.mjs index d44223a3e..7039a7f4b 100644 --- a/lib/md041.js +++ b/lib/md041.mjs @@ -1,14 +1,9 @@ // @ts-check -"use strict"; - -const { addErrorContext, frontMatterHasTitle } = require("../helpers"); -const { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } = - require("../helpers/micromark-helpers.cjs"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext, frontMatterHasTitle } from "../helpers/helpers.cjs"; +import { filterByTypes, getHeadingLevel, getHtmlTagInfo, isHtmlFlowComment, nonContentTokens } from "../helpers/micromark-helpers.cjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD041", "first-line-heading", "first-line-h1" ], "description": "First line in a file should be a top-level heading", "tags": [ "headings" ], diff --git a/lib/md042.js b/lib/md042.mjs similarity index 86% rename from lib/md042.js rename to lib/md042.mjs index efc65d1c3..8b4445c3b 100644 --- a/lib/md042.js +++ b/lib/md042.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorContext } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { getReferenceLinkImageData, filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { getReferenceLinkImageData, filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD042", "no-empty-links" ], "description": "No empty links", "tags": [ "links" ], diff --git a/lib/md043.js b/lib/md043.mjs similarity index 85% rename from lib/md043.js rename to lib/md043.mjs index eafe9f0bc..4562c5ee6 100644 --- a/lib/md043.js +++ b/lib/md043.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorContext, addErrorDetailIf } = require("../helpers"); -const { getHeadingLevel, getHeadingText } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext, addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getHeadingLevel, getHeadingText } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD043", "required-headings" ], "description": "Required heading structure", "tags": [ "headings" ], diff --git a/lib/md044.js b/lib/md044.mjs similarity index 87% rename from lib/md044.js rename to lib/md044.mjs index 320731d25..6e70ab2f5 100644 --- a/lib/md044.js +++ b/lib/md044.mjs @@ -1,18 +1,14 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf, escapeForRegExp, hasOverlap } = require("../helpers"); -const { filterByPredicate, filterByTypes } = require("../helpers/micromark-helpers.cjs"); -const { parse } = require("../helpers/micromark-parse.cjs"); +import { addErrorDetailIf, escapeForRegExp, hasOverlap } from "../helpers/helpers.cjs"; +import { filterByPredicate, filterByTypes } from "../helpers/micromark-helpers.cjs"; +import { parse } from "../helpers/micromark-parse.mjs"; const ignoredChildTypes = new Set( [ "codeFencedFence", "definition", "reference", "resource" ] ); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD044", "proper-names" ], "description": "Proper names should have the correct capitalization", "tags": [ "spelling" ], @@ -48,7 +44,7 @@ module.exports = { token.children.filter((t) => !ignoredChildTypes.has(t.type)) ) ); - /** @type {import("../helpers").FileRange[]} */ + /** @type {import("../helpers/helpers.cjs").FileRange[]} */ const exclusions = []; const scannedTokens = new Set(); for (const name of names) { @@ -64,7 +60,7 @@ module.exports = { const column = token.startColumn + match.index + leftMatch.length; const length = nameMatch.length; const lineNumber = token.startLine; - /** @type {import("../helpers").FileRange} */ + /** @type {import("../helpers/helpers.cjs").FileRange} */ const nameRange = { "startLine": lineNumber, "startColumn": column, @@ -75,7 +71,7 @@ module.exports = { !names.includes(nameMatch) && !exclusions.some((exclusion) => hasOverlap(exclusion, nameRange)) ) { - /** @type {import("../helpers").FileRange[]} */ + /** @type {import("../helpers/helpers.cjs").FileRange[]} */ let autolinkRanges = []; if (!scannedTokens.has(token)) { autolinkRanges = filterByTypes(parse(token.text), [ "literalAutolink" ]) diff --git a/lib/md045.js b/lib/md045.mjs similarity index 81% rename from lib/md045.js rename to lib/md045.mjs index 5d1abcb44..ed51234b2 100644 --- a/lib/md045.js +++ b/lib/md045.mjs @@ -1,16 +1,12 @@ // @ts-check -"use strict"; - -const { addError, getHtmlAttributeRe, nextLinesRe } = require("../helpers"); -const { getHtmlTagInfo, getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addError, getHtmlAttributeRe, nextLinesRe } from "../helpers/helpers.cjs"; +import { getHtmlTagInfo, getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const altRe = getHtmlAttributeRe("alt"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD045", "no-alt-text" ], "description": "Images should have alternate text (alt text)", "tags": [ "accessibility", "images" ], diff --git a/lib/md046.js b/lib/md046.mjs similarity index 75% rename from lib/md046.js rename to lib/md046.mjs index 4b6cb8a7d..4b21d18bd 100644 --- a/lib/md046.js +++ b/lib/md046.mjs @@ -1,18 +1,14 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const tokenTypeToStyle = { "codeFenced": "fenced", "codeIndented": "indented" }; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD046", "code-block-style" ], "description": "Code block style", "tags": [ "code" ], diff --git a/lib/md047.js b/lib/md047.mjs similarity index 77% rename from lib/md047.js rename to lib/md047.mjs index 85288821d..35204e868 100644 --- a/lib/md047.js +++ b/lib/md047.mjs @@ -1,12 +1,8 @@ // @ts-check -"use strict"; - -const { addError, isBlankLine } = require("../helpers"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError, isBlankLine } from "../helpers/helpers.cjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD047", "single-trailing-newline" ], "description": "Files should end with a single newline character", "tags": [ "blank_lines" ], diff --git a/lib/md048.js b/lib/md048.mjs similarity index 79% rename from lib/md048.js rename to lib/md048.mjs index 5b46833dd..c22a6e7f9 100644 --- a/lib/md048.js +++ b/lib/md048.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; /** * Return the string representation of a fence markup character. @@ -20,10 +18,8 @@ function fencedCodeBlockStyleFor(markup) { return "backtick"; } }; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD048", "code-fence-style" ], "description": "Code fence style", "tags": [ "code" ], diff --git a/lib/md049-md050.js b/lib/md049-md050.mjs similarity index 84% rename from lib/md049-md050.js rename to lib/md049-md050.mjs index a117b077c..effb79a6a 100644 --- a/lib/md049-md050.js +++ b/lib/md049-md050.mjs @@ -1,9 +1,7 @@ // @ts-check -"use strict"; - -const { addError } = require("../helpers"); -const { filterByPredicate, getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); +import { addError } from "../helpers/helpers.cjs"; +import { filterByPredicate, getDescendantsByType } from "../helpers/micromark-helpers.cjs"; const intrawordRe = /^\w$/; @@ -23,10 +21,10 @@ function emphasisOrStrongStyleFor(markup) { }; /** - * @param {import("./markdownlint").RuleParams} params Rule parameters. - * @param {import("./markdownlint").RuleOnError} onError Error-reporting callback. - * @param {import("markdownlint-micromark").TokenType} type Token type. - * @param {import("markdownlint-micromark").TokenType} typeSequence Token sequence type. + * @param {import("./markdownlint.mjs").RuleParams} params Rule parameters. + * @param {import("./markdownlint.mjs").RuleOnError} onError Error-reporting callback. + * @param {import("micromark-util-types").TokenType} type Token type. + * @param {import("micromark-util-types").TokenType} typeSequence Token sequence type. * @param {"*" | "**"} asterisk Asterisk kind. * @param {"_" | "__"} underline Underline kind. * @param {"asterisk" | "consistent" | "underscore"} style Style string. @@ -77,10 +75,8 @@ const impl = } } }; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule[] */ -module.exports = [ +/** @type {import("./markdownlint.mjs").Rule[]} */ +export default [ { "names": [ "MD049", "emphasis-style" ], "description": "Emphasis style", diff --git a/lib/md051.js b/lib/md051.mjs similarity index 92% rename from lib/md051.js rename to lib/md051.mjs index e3eef0d80..6f527e7d0 100644 --- a/lib/md051.js +++ b/lib/md051.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addError, getHtmlAttributeRe } = require("../helpers"); -const { filterByPredicate, filterByTypes, getHtmlTagInfo } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addError, getHtmlAttributeRe } from "../helpers/helpers.cjs"; +import { filterByPredicate, filterByTypes, getHtmlTagInfo } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; // Regular expression for identifying HTML anchor names const idRe = getHtmlAttributeRe("id"); @@ -59,10 +57,8 @@ function unescapeStringTokenText(token) { .map((child) => child.text) .join(""); } - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD051", "link-fragments" ], "description": "Link fragments should be valid", "tags": [ "links" ], @@ -104,8 +100,7 @@ module.exports = { } // Process link and definition fragments - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../helpers/micromark-helpers.cjs").TokenType[][] */ + /** @type {import("../helpers/micromark-helpers.cjs").TokenType[][]} */ const parentChilds = [ [ "link", "resourceDestinationString" ], [ "definition", "definitionDestinationString" ] diff --git a/lib/md052.js b/lib/md052.mjs similarity index 84% rename from lib/md052.js rename to lib/md052.mjs index 26ed5383f..62afd2535 100644 --- a/lib/md052.js +++ b/lib/md052.mjs @@ -1,13 +1,9 @@ // @ts-check -"use strict"; - -const { addError } = require("../helpers"); -const { getReferenceLinkImageData } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addError } from "../helpers/helpers.cjs"; +import { getReferenceLinkImageData } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD052", "reference-links-images" ], "description": "Reference links and images should use a label that is defined", diff --git a/lib/md053.js b/lib/md053.mjs similarity index 88% rename from lib/md053.js rename to lib/md053.mjs index 67de4316a..e6426e4e3 100644 --- a/lib/md053.js +++ b/lib/md053.mjs @@ -1,15 +1,11 @@ // @ts-check -"use strict"; - -const { addError, ellipsify } = require("../helpers"); -const { getReferenceLinkImageData } = require("./cache"); +import { addError, ellipsify } from "../helpers/helpers.cjs"; +import { getReferenceLinkImageData } from "./cache.mjs"; const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD053", "link-image-reference-definitions" ], "description": "Link and image reference definitions should be needed", "tags": [ "images", "links" ], diff --git a/lib/md054.js b/lib/md054.mjs similarity index 92% rename from lib/md054.js rename to lib/md054.mjs index 21c147d68..c6f572f4d 100644 --- a/lib/md054.js +++ b/lib/md054.mjs @@ -1,10 +1,8 @@ // @ts-check -"use strict"; - -const { addErrorContext, nextLinesRe } = require("../helpers"); -const { getDescendantsByType } = require("../helpers/micromark-helpers.cjs"); -const { getReferenceLinkImageData, filterByTypesCached } = require("./cache"); +import { addErrorContext, nextLinesRe } from "../helpers/helpers.cjs"; +import { getDescendantsByType } from "../helpers/micromark-helpers.cjs"; +import { getReferenceLinkImageData, filterByTypesCached } from "./cache.mjs"; const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g; const removeBackslashEscapes = (text) => text.replace(backslashEscapeRe, "$1"); @@ -19,10 +17,8 @@ const autolinkAble = (destination) => { } return !autolinkDisallowedRe.test(destination); }; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD054", "link-image-style" ], "description": "Link and image style", "tags": [ "images", "links" ], diff --git a/lib/md055.js b/lib/md055.mjs similarity index 92% rename from lib/md055.js rename to lib/md055.mjs index a4d0f1ee9..b48f4543b 100644 --- a/lib/md055.js +++ b/lib/md055.mjs @@ -1,9 +1,7 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const whitespaceTypes = new Set([ "linePrefix", "whitespace" ]); const ignoreWhitespace = (tokens) => tokens.filter( @@ -12,10 +10,8 @@ const ignoreWhitespace = (tokens) => tokens.filter( const firstOrNothing = (items) => items[0]; const lastOrNothing = (items) => items[items.length - 1]; const makeRange = (start, end) => [ start, end - start + 1 ]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD055", "table-pipe-style" ], "description": "Table pipe style", "tags": [ "table" ], diff --git a/lib/md056.js b/lib/md056.mjs similarity index 81% rename from lib/md056.js rename to lib/md056.mjs index 0a58860dc..c501111a6 100644 --- a/lib/md056.js +++ b/lib/md056.mjs @@ -1,16 +1,12 @@ // @ts-check -"use strict"; - -const { addErrorDetailIf } = require("../helpers"); -const { getParentOfType } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); +import { addErrorDetailIf } from "../helpers/helpers.cjs"; +import { getParentOfType } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; const makeRange = (start, end) => [ start, end - start + 1 ]; - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD056", "table-column-count" ], "description": "Table column count", "tags": [ "table" ], diff --git a/lib/md058.js b/lib/md058.mjs similarity index 81% rename from lib/md058.js rename to lib/md058.mjs index 423674231..57dbbc948 100644 --- a/lib/md058.js +++ b/lib/md058.mjs @@ -1,14 +1,10 @@ // @ts-check -"use strict"; - -const { addErrorContext, isBlankLine } = require("../helpers"); -const { getBlockQuotePrefixText } = require("../helpers/micromark-helpers.cjs"); -const { filterByTypesCached } = require("./cache"); - -// eslint-disable-next-line jsdoc/valid-types -/** @type import("./markdownlint").Rule */ -module.exports = { +import { addErrorContext, isBlankLine } from "../helpers/helpers.cjs"; +import { getBlockQuotePrefixText } from "../helpers/micromark-helpers.cjs"; +import { filterByTypesCached } from "./cache.mjs"; +/** @type {import("./markdownlint.mjs").Rule} */ +export default { "names": [ "MD058", "blanks-around-tables" ], "description": "Tables should be surrounded by blank lines", "tags": [ "table" ], diff --git a/lib/rules.js b/lib/rules.js deleted file mode 100644 index cbdbd9fbb..000000000 --- a/lib/rules.js +++ /dev/null @@ -1,74 +0,0 @@ -// @ts-check - -"use strict"; - -const { homepage, version } = require("./constants"); - -// @ts-ignore -const [ md019, md021 ] = require("./md019-md021"); -// @ts-ignore -const [ md049, md050 ] = require("./md049-md050"); - -const rules = [ - require("./md001"), - // md002: Deprecated and removed - require("./md003"), - require("./md004"), - require("./md005"), - // md006: Deprecated and removed - require("./md007"), - require("./md009"), - require("./md010"), - require("./md011"), - require("./md012"), - require("./md013"), - require("./md014"), - require("./md018"), - md019, - require("./md020"), - md021, - require("./md022"), - require("./md023"), - require("./md024"), - require("./md025"), - require("./md026"), - require("./md027"), - require("./md028"), - require("./md029"), - require("./md030"), - require("./md031"), - require("./md032"), - require("./md033"), - require("./md034"), - require("./md035"), - require("./md036"), - require("./md037"), - require("./md038"), - require("./md039"), - require("./md040"), - require("./md041"), - require("./md042"), - require("./md043"), - require("./md044"), - require("./md045"), - require("./md046"), - require("./md047"), - require("./md048"), - md049, - md050, - require("./md051"), - require("./md052"), - require("./md053"), - require("./md054"), - require("./md055"), - require("./md056"), - // md057: See https://github.com/markdownlint/markdownlint - require("./md058") -]; -for (const rule of rules) { - const name = rule.names[0].toLowerCase(); - // eslint-disable-next-line dot-notation - rule["information"] = - new URL(`${homepage}/blob/v${version}/doc/${name}.md`); -} -module.exports = rules; diff --git a/lib/rules.mjs b/lib/rules.mjs new file mode 100644 index 000000000..ccdcdd563 --- /dev/null +++ b/lib/rules.mjs @@ -0,0 +1,118 @@ +// @ts-check + +import { homepage, version } from "./constants.mjs"; + +import md001 from "./md001.mjs"; +import md003 from "./md003.mjs"; +import md004 from "./md004.mjs"; +import md005 from "./md005.mjs"; +import md007 from "./md007.mjs"; +import md009 from "./md009.mjs"; +import md010 from "./md010.mjs"; +import md011 from "./md011.mjs"; +import md012 from "./md012.mjs"; +import md013 from "./md013.mjs"; +import md014 from "./md014.mjs"; +import md018 from "./md018.mjs"; +import md019md021 from "./md019-md021.mjs"; +const [ md019, md021 ] = md019md021; +import md020 from "./md020.mjs"; +import md022 from "./md022.mjs"; +import md023 from "./md023.mjs"; +import md024 from "./md024.mjs"; +import md025 from "./md025.mjs"; +import md026 from "./md026.mjs"; +import md027 from "./md027.mjs"; +import md028 from "./md028.mjs"; +import md029 from "./md029.mjs"; +import md030 from "./md030.mjs"; +import md031 from "./md031.mjs"; +import md032 from "./md032.mjs"; +import md033 from "./md033.mjs"; +import md034 from "./md034.mjs"; +import md035 from "./md035.mjs"; +import md036 from "./md036.mjs"; +import md037 from "./md037.mjs"; +import md038 from "./md038.mjs"; +import md039 from "./md039.mjs"; +import md040 from "./md040.mjs"; +import md041 from "./md041.mjs"; +import md042 from "./md042.mjs"; +import md043 from "./md043.mjs"; +import md044 from "./md044.mjs"; +import md045 from "./md045.mjs"; +import md046 from "./md046.mjs"; +import md047 from "./md047.mjs"; +import md048 from "./md048.mjs"; +import md049md050 from "./md049-md050.mjs"; +const [ md049, md050 ] = md049md050; +import md051 from "./md051.mjs"; +import md052 from "./md052.mjs"; +import md053 from "./md053.mjs"; +import md054 from "./md054.mjs"; +import md055 from "./md055.mjs"; +import md056 from "./md056.mjs"; +import md058 from "./md058.mjs"; + +const rules = [ + md001, + // md002: Deprecated and removed + md003, + md004, + md005, + // md006: Deprecated and removed + md007, + md009, + md010, + md011, + md012, + md013, + md014, + md018, + md019, + md020, + md021, + md022, + md023, + md024, + md025, + md026, + md027, + md028, + md029, + md030, + md031, + md032, + md033, + md034, + md035, + md036, + md037, + md038, + md039, + md040, + md041, + md042, + md043, + md044, + md045, + md046, + md047, + md048, + md049, + md050, + md051, + md052, + md053, + md054, + md055, + md056, + // md057: See https://github.com/markdownlint/markdownlint + md058 +]; +for (const rule of rules) { + const name = rule.names[0].toLowerCase(); + // eslint-disable-next-line dot-notation + rule["information"] = new URL(`${homepage}/blob/v${version}/doc/${name}.md`); +} +export default rules; diff --git a/micromark/.npmignore b/micromark/.npmignore deleted file mode 100644 index 4947c297c..000000000 --- a/micromark/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -exports.mjs -exports-html.mjs -micromark.dev.cjs -micromark-browser.dev.js -micromark-html-browser.dev.js -webpack.config.js diff --git a/micromark/.npmrc b/micromark/.npmrc deleted file mode 100644 index 3757b3046..000000000 --- a/micromark/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -ignore-scripts=true -package-lock=false diff --git a/micromark/LICENSE b/micromark/LICENSE deleted file mode 100644 index 71ff07a3e..000000000 --- a/micromark/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) David Anson - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/micromark/README.md b/micromark/README.md deleted file mode 100644 index a9834c41c..000000000 --- a/micromark/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# markdownlint-micromark - -> A trivial package that re-exports some [`micromark`][micromark] functionality -> as a CommonJS module - -This package is unlikely to be of any use beyond a specific scenario used by -[`markdownlint`][markdownlint]. - -[markdownlint]: https://github.com/DavidAnson/markdownlint -[micromark]: https://github.com/micromark/micromark diff --git a/micromark/api-extractor.json b/micromark/api-extractor.json deleted file mode 100644 index 105981e25..000000000 --- a/micromark/api-extractor.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "projectFolder": ".", - "mainEntryPointFilePath": "/types.d.ts", - "bundledPackages": [ "*" ], - "newlineKind": "os", - "compiler": { - "overrideTsconfig": {} - }, - "apiReport": { - "enabled": false - }, - "docModel": { - "enabled": false - }, - "dtsRollup": { - "enabled": true, - "untrimmedFilePath": "/micromark.d.cts" - }, - "tsdocMetadata": { - "enabled": false - }, - "messages": { - "compilerMessageReporting": { - "default": { - "logLevel": "warning" - } - }, - "extractorMessageReporting": { - "default": { - "logLevel": "warning" - } - }, - "tsdocMessageReporting": { - "default": { - "logLevel": "warning" - } - } - } -} diff --git a/micromark/exports-html.mjs b/micromark/exports-html.mjs deleted file mode 100644 index 88d29bf7d..000000000 --- a/micromark/exports-html.mjs +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check - -/* eslint-disable n/no-missing-import */ - -export { compile } from "micromark"; -export { directiveHtml } from "micromark-extension-directive"; -export { gfmAutolinkLiteralHtml } from "micromark-extension-gfm-autolink-literal"; -export { gfmFootnoteHtml } from "micromark-extension-gfm-footnote"; -export { gfmTableHtml } from "micromark-extension-gfm-table"; -export { mathHtml } from "micromark-extension-math"; diff --git a/micromark/exports.mjs b/micromark/exports.mjs deleted file mode 100644 index fcf10df53..000000000 --- a/micromark/exports.mjs +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check - -/* eslint-disable n/no-missing-import */ - -export { directive } from "micromark-extension-directive"; -export { gfmAutolinkLiteral } from "micromark-extension-gfm-autolink-literal"; -export { gfmFootnote } from "micromark-extension-gfm-footnote"; -export { gfmTable } from "micromark-extension-gfm-table"; -export { math } from "micromark-extension-math"; -export { parse } from "micromark"; -export { postprocess } from "micromark"; -export { preprocess } from "micromark"; -// micromark-core-commonmark is not a dev/dependency because this instance must match what's used by micromark -export { labelEnd } from "micromark-core-commonmark"; diff --git a/micromark/micromark.d.cts b/micromark/micromark.d.cts deleted file mode 100644 index 276805703..000000000 --- a/micromark/micromark.d.cts +++ /dev/null @@ -1,1758 +0,0 @@ -/** - * Attempt deals with several values, and tries to parse according to those - * values. - * - * If a value resulted in `ok`, it worked, the tokens that were made are used, - * and `ok` is switched to. - * If the result is `nok`, the attempt failed, so we revert to the original - * state, and `nok` is used. - * - * @param construct - * Construct(s) to try. - * @param ok - * State to move to when successful. - * @param nok - * State to move to when unsuccessful. - * @returns - * Next state. - */ -declare type Attempt = ( -construct: Array | Construct | ConstructRecord, -ok: State, -nok?: State | undefined -) => State - -/** - * Directive attribute. - */ -declare interface Attributes { - /** - * Key to value. - */ - [key: string]: string -} - -/** - * Generate a back label dynamically. - * - * For the following markdown: - * - * ```markdown - * Alpha[^micromark], bravo[^micromark], and charlie[^remark]. - * - * [^remark]: things about remark - * [^micromark]: things about micromark - * ``` - * - * This function will be called with: - * - * * `0` and `0` for the backreference from `things about micromark` to - * `alpha`, as it is the first used definition, and the first call to it - * * `0` and `1` for the backreference from `things about micromark` to - * `bravo`, as it is the first used definition, and the second call to it - * * `1` and `0` for the backreference from `things about remark` to - * `charlie`, as it is the second used definition - * - * @param referenceIndex - * Index of the definition in the order that they are first referenced, - * 0-indexed. - * @param rereferenceIndex - * Index of calls to the same definition, 0-indexed. - * @returns - * Back label to use when linking back from definitions to their reference. - */ -declare type BackLabelTemplate = ( -referenceIndex: number, -rereferenceIndex: number -) => string - -/** - * A chunk is either a character code or a slice of a buffer in the form of a - * string. - * - * Chunks are used because strings are more efficient storage that character - * codes, but limited in what they can represent. - */ -declare type Chunk = Code | string - -declare type Chunk_2 = Chunk - -/** - * A character code. - * - * This is often the same as what `String#charCodeAt()` yields but micromark - * adds meaning to certain other values. - * - * `null` represents the end of the input stream (called eof). - * Negative integers are used instead of certain sequences of characters (such - * as line endings and tabs). - */ -declare type Code = number | null - -declare type Compile = Compile_2 - -/** - * @param {CompileOptions | null | undefined} [options] - * @returns {Compile} - */ -export declare function compile(options?: CompileOptions_2 | null | undefined): Compile - -/** - * Serialize micromark events as HTML. - */ -declare type Compile_2 = (events: Array) => string - -/** - * HTML compiler context. - */ -declare type CompileContext = { - /** - * Configuration passed by the user. - */ - options: CompileOptions - - /** - * Set data into the key-value store. - * - * @param key - * Key. - * @param value - * Value. - * @returns - * Nothing. - */ - setData: ( - key: Key, - value?: CompileData[Key] - ) => undefined - - /** - * Get data from the key-value store. - * - * @param key - * Key. - * @returns - * Value at `key` in compile data. - */ - getData: (key: Key) => CompileData[Key] - - /** - * Output an extra line ending if the previous value wasn’t EOF/EOL. - * - * @returns - * Nothing. - */ - lineEndingIfNeeded: () => undefined - - /** - * Make a value safe for injection in HTML (except w/ `ignoreEncode`). - * - * @param value - * Raw value. - * @returns - * Safe value. - */ - encode: (value: string) => string - - /** - * Capture some of the output data. - * - * @returns - * Nothing. - */ - buffer: () => undefined - - /** - * Stop capturing and access the output data. - * - * @returns - * Captured data. - */ - resume: () => string - - /** - * Output raw data. - * - * @param value - * Raw value. - * @returns - * Nothing. - */ - raw: (value: string) => undefined - - /** - * Output (parts of) HTML tags. - * - * @param value - * Raw value. - * @returns - * Nothing. - */ - tag: (value: string) => undefined - - /** - * Get the string value of a token. - * - * @param token - * Start/end in stream. - * @param expandTabs - * Whether to expand tabs. - * @returns - * Serialized chunks. - */ - sliceSerialize: TokenizeContext['sliceSerialize'] -} - -/** - * State tracked to compile events as HTML. - */ -export declare interface CompileData { - /** - * Whether the last emitted value was a tag. - */ - lastWasTag?: boolean | undefined - - /** - * Whether the first list item is expected, used by lists. - */ - expectFirstItem?: boolean | undefined - - /** - * Whether to slurp the next line ending (resets itself on the next line - * ending). - */ - slurpOneLineEnding?: boolean | undefined - - /** - * Whether to slurp all future line endings (has to be unset manually). - */ - slurpAllLineEndings?: boolean | undefined - - /** - * Whether we’re in fenced code, used by code (fenced). - */ - fencedCodeInside?: boolean | undefined - - /** - * Number of fences that were seen, used by code (fenced). - */ - fencesCount?: number | undefined - - /** - * Whether we’ve seen code data, used by code (fenced, indented). - */ - flowCodeSeenData?: boolean | undefined - - /** - * Ignore encoding unsafe characters, used for example for URLs which are - * first percent encoded, or by HTML when supporting it. - */ - ignoreEncode?: boolean | undefined - - /** - * Current heading rank, used by heading (atx, setext). - */ - headingRank?: number | undefined - - /** - * Whether we’re in code data, used by code (text). - */ - inCodeText?: boolean | undefined - - /** - * Current character reference kind. - */ - characterReferenceType?: string | undefined - - /** - * Stack of containers, whether they’re tight or not. - */ - tightStack: Array - - /** - * Collected definitions. - */ - definitions: Record -} - -/** - * Compile options. - */ -declare interface CompileOptions { - /** - * Whether to allow (dangerous) HTML (`boolean`, default: `false`). - * - * The default is `false`, which still parses the HTML according to - * `CommonMark` but shows the HTML as text instead of as elements. - * - * Pass `true` for trusted content to get actual HTML elements. - */ - allowDangerousHtml?: boolean | null | undefined - - /** - * Whether to allow dangerous protocols in links and images (`boolean`, - * default: `false`). - * - * The default is `false`, which drops URLs in links and images that use - * dangerous protocols. - * - * Pass `true` for trusted content to support all protocols. - * - * URLs that have no protocol (which means it’s relative to the current page, - * such as `./some/page.html`) and URLs that have a safe protocol (for - * images: `http`, `https`; for links: `http`, `https`, `irc`, `ircs`, - * `mailto`, `xmpp`), are safe. - * All other URLs are dangerous and dropped. - */ - allowDangerousProtocol?: boolean | null | undefined - - /** - * Default line ending to use when compiling to HTML, for line endings not in - * `value`. - * - * Generally, `micromark` copies line endings (`\r`, `\n`, `\r\n`) in the - * markdown document over to the compiled HTML. - * In some cases, such as `> a`, CommonMark requires that extra line endings - * are added: `
\n

a

\n
`. - * - * To create that line ending, the document is checked for the first line - * ending that is used. - * If there is no line ending, `defaultLineEnding` is used. - * If that isn’t configured, `\n` is used. - */ - defaultLineEnding?: LineEnding | null | undefined - - /** - * Array of HTML extensions (default: `[]`). - */ - htmlExtensions?: Array | null | undefined -} - -declare type CompileOptions_2 = CompileOptions - -/** - * An object describing how to parse a markdown construct. - */ -export declare type Construct = { - /** - * Set up a state machine to handle character codes streaming in. - */ - tokenize: Tokenizer - - /** - * Guard whether the previous character can come before the construct. - */ - previous?: Previous | undefined - - /** - * For containers, a continuation construct. - */ - continuation?: Construct | undefined - - /** - * For containers, a final hook. - */ - exit?: Exiter | undefined - - /** - * Name of the construct, used to toggle constructs off. - * - * Named constructs must not be `partial`. - */ - name?: string | undefined - - /** - * Whether this construct represents a partial construct. - * - * Partial constructs must not have a `name`. - */ - partial?: boolean | undefined - - /** - * Resolve the events parsed by `tokenize`. - * - * For example, if we’re currently parsing a link title and this construct - * parses character references, then `resolve` is called with the events - * ranging from the start to the end of a character reference each time one is - * found. - */ - resolve?: Resolver | undefined - - /** - * Resolve the events from the start of the content (which includes other - * constructs) to the last one parsed by `tokenize`. - * - * For example, if we’re currently parsing a link title and this construct - * parses character references, then `resolveTo` is called with the events - * ranging from the start of the link title to the end of a character - * reference each time one is found. - */ - resolveTo?: Resolver | undefined - - /** - * Resolve all events when the content is complete, from the start to the end. - * Only used if `tokenize` is successful once in the content. - * - * For example, if we’re currently parsing a link title and this construct - * parses character references, then `resolveAll` is called *if* at least one - * character reference is found, ranging from the start to the end of the link - * title to the end. - */ - resolveAll?: Resolver | undefined - - /** - * Concrete constructs cannot be interrupted by more containers. - * - * For example, when parsing the document (containers, such as block quotes - * and lists) and this construct is parsing fenced code: - * - * ````markdown - * > ```js - * > - list? - * ```` - * - * …then `- list?` cannot form if this fenced code construct is concrete. - * - * An example of a construct that is not concrete is a GFM table: - * - * ````markdown - * | a | - * | - | - * > | b | - * ```` - * - * …`b` is not part of the table. - */ - concrete?: boolean | undefined - - /** - * Whether the construct, when in a `ConstructRecord`, precedes over existing - * constructs for the same character code when merged. - * - * The default is that new constructs precede over existing ones. - */ - add?: 'after' | 'before' | undefined -} - -/** - * Several constructs, mapped from their initial codes. - */ -declare type ConstructRecord = Record< -string, -Array | Construct | undefined -> - -/** - * Deal with the character and move to the next. - * - * @param code - * Current code. - */ -declare type Consume = (code: Code) => undefined - -/** - * State shared between container calls. - */ -declare interface ContainerState { - /** - * Special field to close the current flow (or containers). - */ - _closeFlow?: boolean | undefined - - /** - * Used by block quotes. - */ - open?: boolean | undefined - - /** - * Current marker, used by lists. - */ - marker?: Code | undefined - - /** - * Current token type, used by lists. - */ - type?: TokenType | undefined - - /** - * Current size, used by lists. - */ - size?: number | undefined - - /** - * Whether there first line is blank, used by lists. - */ - initialBlankLine?: boolean | undefined - - /** - * Whether there are further blank lines, used by lists. - */ - furtherBlankLines?: boolean | undefined -} - -/** - * Enumeration of the content types. - * - * Technically `document` is also a content type, which includes containers - * (lists, block quotes) and flow. - * As `ContentType` is used on tokens to define the type of subcontent but - * `document` is the highest level of content, so it’s not listed here. - * - * Containers in markdown come from the margin and include more constructs - * on the lines that define them. - * Take for example a block quote with a paragraph inside it (such as - * `> asd`). - * - * `flow` represents the sections, such as headings, code, and content, which - * is also parsed per line - * An example is HTML, which has a certain starting condition (such as - * ` - * ``` - * - * The above example shows that elements are made available by browsers, by - * their ID, on the `window` object. - * This is a security risk because you might be expecting some other variable - * at that place. - * It can also break polyfills. - * Using a prefix solves these problems. - */ - clobberPrefix?: string | null | undefined - /** - * Textual label to use for the footnotes section (default: `'Footnotes'`). - * - * Change it when the markdown is not in English. - * - * This label is typically hidden visually (assuming a `sr-only` CSS class - * is defined that does that) and so affects screen readers only. - * If you do have such a class, but want to show this section to everyone, - * pass different attributes with the `labelAttributes` option. - */ - label?: string | null | undefined - /** - * Attributes to use on the footnote label (default: `'class="sr-only"'`). - * - * Change it to show the label and add other attributes. - * - * This label is typically hidden visually (assuming an `sr-only` CSS class - * is defined that does that) and so affects screen readers only. - * If you do have such a class, but want to show this section to everyone, - * pass an empty string. - * You can also add different attributes. - * - * > 👉 **Note**: `id="footnote-label"` is always added, because footnote - * > calls use it with `aria-describedby` to provide an accessible label. - */ - labelAttributes?: string | null | undefined - /** - * HTML tag name to use for the footnote label element (default: `'h2'`). - * - * Change it to match your document structure. - * - * This label is typically hidden visually (assuming a `sr-only` CSS class - * is defined that does that) and so affects screen readers only. - * If you do have such a class, but want to show this section to everyone, - * pass different attributes with the `labelAttributes` option. - */ - labelTagName?: string | null | undefined - /** - * Textual label to describe the backreference back to references (default: - * `defaultBackLabel`). - * - * The default value is: - * - * ```js - * function defaultBackLabel(referenceIndex, rereferenceIndex) { - * return ( - * 'Back to reference ' + - * (referenceIndex + 1) + - * (rereferenceIndex > 1 ? '-' + rereferenceIndex : '') - * ) - * } - * ``` - * - * Change it when the markdown is not in English. - * - * This label is used in the `aria-label` attribute on each backreference - * (the `↩` links). - * It affects users of assistive technology. - */ - backLabel?: BackLabelTemplate | string | null | undefined -} - -/** - * Configuration for HTML output. - * - * > 👉 **Note**: passed to `katex.renderToString`. - * > `displayMode` is overwritten by this plugin, to `false` for math in - * > text (inline), and `true` for math in flow (block). - */ -declare interface HtmlOptions_3 extends Object { - /** - * The field `displayMode` cannot be passed to `micromark-extension-math`. - * It is overwritten by it, - * to `false` for math in text (inline) and `true` for math in flow (block). - */ - displayMode?: never -} - -/** - * Type of line ending in markdown. - */ -declare type LineEnding = '\r' | '\n' | '\r\n' - -/** - * Create an extension for `micromark` to enable math syntax. - * - * @param {Options | null | undefined} [options={}] - * Configuration (default: `{}`). - * @returns {Extension} - * Extension for `micromark` that can be passed in `extensions`, to - * enable math syntax. - */ -export declare function math(options?: Options | null | undefined): Extension; - -/** - * Create an extension for `micromark` to support math when serializing to - * HTML. - * - * > 👉 **Note**: this uses KaTeX to render math. - * - * @param {Options | null | undefined} [options={}] - * Configuration (default: `{}`). - * @returns {HtmlExtension} - * Extension for `micromark` that can be passed in `htmlExtensions`, to - * support math when serializing to HTML. - */ -export declare function mathHtml(options?: HtmlOptions_3 | null | undefined): HtmlExtension; - -/** - * Configuration. - */ -declare interface Options { - /** - * Whether to support math (text) with a single dollar (default: `true`). - * - * Single dollars work in Pandoc and many other places, but often interfere - * with “normal” dollars in text. - * If you turn this off, you can use two or more dollars for text math. - */ - singleDollarTextMath?: boolean | null | undefined -} - -/** - * @param {ParseOptions | null | undefined} [options] - * @returns {ParseContext} - */ -export declare function parse(options?: ParseOptions_2 | null | undefined): ParseContext_2 - -/** - * A context object that helps w/ parsing markdown. - */ -declare interface ParseContext { - /** - * All constructs. - */ - constructs: FullNormalizedExtension - - /** - * Create a content tokenizer. - */ - content: Create - - /** - * Create a document tokenizer. - */ - document: Create - - /** - * Create a flow tokenizer. - */ - flow: Create - - /** - * Create a string tokenizer. - */ - string: Create - - /** - * Create a text tokenizer. - */ - text: Create - - /** - * List of defined identifiers. - */ - defined: Array - - /** - * Map of line numbers to whether they are lazy (as opposed to the line before - * them). - * Take for example: - * - * ```markdown - * > a - * b - * ``` - * - * L1 here is not lazy, L2 is. - */ - lazy: Record -} - -declare type ParseContext_2 = ParseContext - -/** - * Config defining how to parse. - */ -export declare interface ParseOptions { - /** - * Array of syntax extensions (default: `[]`). - */ - extensions?: Array | null | undefined -} - -declare type ParseOptions_2 = ParseOptions - -/** - * A location in the document (`line`/`column`/`offset`) and chunk (`_index`, - * `_bufferIndex`). - * - * `_bufferIndex` is `-1` when `_index` points to a code chunk and it’s a - * non-negative integer when pointing to a string chunk. - * - * The interface for the location in the document comes from unist `Point`: - * - */ -declare type Point = { - /** - * Position in a string chunk (or `-1` when pointing to a numeric chunk). - */ - _bufferIndex: number - - /** - * Position in a list of chunks. - */ - _index: number - - /** - * 1-indexed column number. - */ - column: number - - /** - * 1-indexed line number. - */ - line: number - - /** - * 0-indexed position in the document. - */ - offset: number -} - -/** - * @param {Array} events - * @returns {Array} - */ -export declare function postprocess( -events: Array -): Array - -/** - * @returns {Preprocessor} - */ -export declare function preprocess(): Preprocessor - -declare type Preprocessor = ( -value: Value, -encoding?: Encoding | null | undefined, -end?: boolean | null | undefined -) => Array - -/** - * Guard whether `code` can come before the construct. - * - * In certain cases a construct can hook into many potential start characters. - * Instead of setting up an attempt to parse that construct for most - * characters, this is a speedy way to reduce that. - * - * @param this - * Tokenize context. - * @param code - * Previous code. - * @returns - * Whether `code` is allowed before. - */ -declare type Previous = (this: TokenizeContext, code: Code) => boolean - -/** - * A resolver handles and cleans events coming from `tokenize`. - * - * @param events - * List of events. - * @param context - * Tokenize context. - * @returns - * The given, modified, events. - */ -declare type Resolver = ( -events: Array, -context: TokenizeContext -) => Array - -/** - * The main unit in the state machine: a function that gets a character code - * and has certain effects. - * - * A state function should return another function: the next - * state-as-a-function to go to. - * - * But there is one case where they return `undefined`: for the eof character - * code (at the end of a value). - * The reason being: well, there isn’t any state that makes sense, so - * `undefined` works well. - * Practically that has also helped: if for some reason it was a mistake, then - * an exception is throw because there is no next function, meaning it - * surfaces early. - * - * @param code - * Current code. - * @returns - * Next state. - */ -export declare type State = (code: Code) => State | undefined - -/** - * A token: a span of chunks. - * - * Tokens are what the core of micromark produces: the built in HTML compiler - * or other tools can turn them into different things. - * - * Tokens are essentially names attached to a slice of chunks, such as - * `lineEndingBlank` for certain line endings, or `codeFenced` for a whole - * fenced code. - * - * Sometimes, more info is attached to tokens, such as `_open` and `_close` - * by `attention` (strong, emphasis) to signal whether the sequence can open - * or close an attention run. - * - * Linked tokens are used because outer constructs are parsed first. - * Take for example: - * - * ```markdown - * > *a - * b*. - * ``` - * - * 1. The block quote marker and the space after it is parsed first - * 2. The rest of the line is a `chunkFlow` token - * 3. The two spaces on the second line are a `linePrefix` - * 4. The rest of the line is another `chunkFlow` token - * - * The two `chunkFlow` tokens are linked together. - * The chunks they span are then passed through the flow tokenizer. - */ -export declare interface Token { - /** - * Token type. - */ - type: TokenType - - /** - * Point where the token starts. - */ - start: Point - - /** - * Point where the token ends. - */ - end: Point - - /** - * The previous token in a list of linked tokens. - */ - previous?: Token | undefined - - /** - * The next token in a list of linked tokens. - */ - next?: Token | undefined - - /** - * Declares a token as having content of a certain type. - */ - contentType?: ContentType | undefined - - /** - * Connected tokenizer. - * - * Used when dealing with linked tokens. - * A child tokenizer is needed to tokenize them, which is stored on those - * tokens. - */ - _tokenizer?: TokenizeContext | undefined - - /** - * Field to help parse attention. - * - * Depending on the character before sequences (`**`), the sequence can open, - * close, both, or none. - */ - _open?: boolean | undefined - - /** - * Field to help parse attention. - * - * Depending on the character before sequences (`**`), the sequence can open, - * close, both, or none. - */ - _close?: boolean | undefined - - /** - * Field to help parse GFM task lists. - * - * This boolean is used internally to figure out if a token is in the first - * content of a list item construct. - */ - _isInFirstContentOfListItem?: boolean | undefined - - /** - * Field to help parse containers. - * - * This boolean is used internally to figure out if a token is a container - * token. - */ - _container?: boolean | undefined - - /** - * Field to help parse lists. - * - * This boolean is used internally to figure out if a list is loose or not. - */ - _loose?: boolean | undefined - - /** - * Field to help parse links. - * - * This boolean is used internally to figure out if a link opening - * can’t be used (because links in links are incorrect). - */ - _inactive?: boolean | undefined - - /** - * Field to help parse links. - * - * This boolean is used internally to figure out if a link opening is - * balanced: it’s not a link opening but has a balanced closing. - */ - _balanced?: boolean | undefined -} - -/** - * A context object that helps w/ tokenizing markdown constructs. - */ -declare interface TokenizeContext { - /** - * The previous code. - */ - previous: Code - - /** - * Current code. - */ - code: Code - - /** - * Whether we’re currently interrupting. - * - * Take for example: - * - * ```markdown - * a - * # b - * ``` - * - * At 2:1, we’re “interrupting”. - */ - interrupt?: boolean | undefined - - /** - * The current construct. - * - * Constructs that are not `partial` are set here. - */ - currentConstruct?: Construct | undefined - - /** - * share state set when parsing containers. - * - * Containers are parsed in separate phases: their first line (`tokenize`), - * continued lines (`continuation.tokenize`), and finally `exit`. - * This record can be used to store some information between these hooks. - */ - containerState?: ContainerState | undefined - - /** - * Current list of events. - */ - events: Array - - /** - * The relevant parsing context. - */ - parser: ParseContext - - /** - * Get the chunks that span a token (or location). - * - * @param token - * Start/end in stream. - * @returns - * List of chunks. - */ - sliceStream: (token: Pick) => Array - - /** - * Get the source text that spans a token (or location). - * - * @param token - * Start/end in stream. - * @param expandTabs - * Whether to expand tabs. - * @returns - * Serialized chunks. - */ - sliceSerialize: ( - token: Pick, - expandTabs?: boolean | undefined - ) => string - - /** - * Get the current place. - * - * @returns - * Current point. - */ - now: () => Point - - /** - * Define a skip - * - * As containers (block quotes, lists), “nibble” a prefix from the margins, - * where a line starts after that prefix is defined here. - * When the tokenizers moves after consuming a line ending corresponding to - * the line number in the given point, the tokenizer shifts past the prefix - * based on the column in the shifted point. - * - * @param point - * Skip. - * @returns - * Nothing. - */ - defineSkip: (point: Point) => undefined - - /** - * Write a slice of chunks. - * - * The eof code (`null`) can be used to signal the end of the stream. - * - * @param slice - * Chunks. - * @returns - * Events. - */ - write: (slice: Array) => Array - - /** - * Internal boolean shared with `micromark-extension-gfm-task-list-item` to - * signal whether the tokenizer is tokenizing the first content of a list item - * construct. - */ - _gfmTasklistFirstContentOfListItem?: boolean | undefined - - // To do: next major: remove `_gfmTableDynamicInterruptHack` (no longer - // needed in micromark-extension-gfm-table@1.0.6). - /** - * Internal boolean shared with `micromark-extension-gfm-table` whose body - * rows are not affected by normal interruption rules. - * “Normal” rules are, for example, that an empty list item can’t interrupt: - * - * ````markdown - * a - * * - * ```` - * - * The above is one paragraph. - * These rules don’t apply to table body rows: - * - * ````markdown - * | a | - * | - | - * * - * ```` - * - * The above list interrupts the table. - */ - _gfmTableDynamicInterruptHack?: boolean -} - -/** - * A tokenize function sets up a state machine to handle character codes streaming in. - * - * @param this - * Tokenize context. - * @param effects - * Effects. - * @param ok - * State to go to when successful. - * @param nok - * State to go to when unsuccessful. - * @returns - * First state. - */ -export declare type Tokenizer = ( -this: TokenizeContext, -effects: Effects, -ok: State, -nok: State -) => State - -/** - * Enum of allowed token types. - */ -export declare type TokenType = keyof TokenTypeMap - -/** - * Map of allowed token types. - */ -export declare interface TokenTypeMap { - // Note: these are compiled away. - attentionSequence: 'attentionSequence' // To do: remove. - space: 'space' // To do: remove. - - data: 'data' - whitespace: 'whitespace' - lineEnding: 'lineEnding' - lineEndingBlank: 'lineEndingBlank' - linePrefix: 'linePrefix' - lineSuffix: 'lineSuffix' - atxHeading: 'atxHeading' - atxHeadingSequence: 'atxHeadingSequence' - atxHeadingText: 'atxHeadingText' - autolink: 'autolink' - autolinkEmail: 'autolinkEmail' - autolinkMarker: 'autolinkMarker' - autolinkProtocol: 'autolinkProtocol' - characterEscape: 'characterEscape' - characterEscapeValue: 'characterEscapeValue' - characterReference: 'characterReference' - characterReferenceMarker: 'characterReferenceMarker' - characterReferenceMarkerNumeric: 'characterReferenceMarkerNumeric' - characterReferenceMarkerHexadecimal: 'characterReferenceMarkerHexadecimal' - characterReferenceValue: 'characterReferenceValue' - codeFenced: 'codeFenced' - codeFencedFence: 'codeFencedFence' - codeFencedFenceSequence: 'codeFencedFenceSequence' - codeFencedFenceInfo: 'codeFencedFenceInfo' - codeFencedFenceMeta: 'codeFencedFenceMeta' - codeFlowValue: 'codeFlowValue' - codeIndented: 'codeIndented' - codeText: 'codeText' - codeTextData: 'codeTextData' - codeTextPadding: 'codeTextPadding' - codeTextSequence: 'codeTextSequence' - content: 'content' - definition: 'definition' - definitionDestination: 'definitionDestination' - definitionDestinationLiteral: 'definitionDestinationLiteral' - definitionDestinationLiteralMarker: 'definitionDestinationLiteralMarker' - definitionDestinationRaw: 'definitionDestinationRaw' - definitionDestinationString: 'definitionDestinationString' - definitionLabel: 'definitionLabel' - definitionLabelMarker: 'definitionLabelMarker' - definitionLabelString: 'definitionLabelString' - definitionMarker: 'definitionMarker' - definitionTitle: 'definitionTitle' - definitionTitleMarker: 'definitionTitleMarker' - definitionTitleString: 'definitionTitleString' - emphasis: 'emphasis' - emphasisSequence: 'emphasisSequence' - emphasisText: 'emphasisText' - escapeMarker: 'escapeMarker' - hardBreakEscape: 'hardBreakEscape' - hardBreakTrailing: 'hardBreakTrailing' - htmlFlow: 'htmlFlow' - htmlFlowData: 'htmlFlowData' - htmlText: 'htmlText' - htmlTextData: 'htmlTextData' - image: 'image' - label: 'label' - labelText: 'labelText' - labelLink: 'labelLink' - labelImage: 'labelImage' - labelMarker: 'labelMarker' - labelImageMarker: 'labelImageMarker' - labelEnd: 'labelEnd' - link: 'link' - paragraph: 'paragraph' - reference: 'reference' - referenceMarker: 'referenceMarker' - referenceString: 'referenceString' - resource: 'resource' - resourceDestination: 'resourceDestination' - resourceDestinationLiteral: 'resourceDestinationLiteral' - resourceDestinationLiteralMarker: 'resourceDestinationLiteralMarker' - resourceDestinationRaw: 'resourceDestinationRaw' - resourceDestinationString: 'resourceDestinationString' - resourceMarker: 'resourceMarker' - resourceTitle: 'resourceTitle' - resourceTitleMarker: 'resourceTitleMarker' - resourceTitleString: 'resourceTitleString' - setextHeading: 'setextHeading' - setextHeadingText: 'setextHeadingText' - setextHeadingLine: 'setextHeadingLine' - setextHeadingLineSequence: 'setextHeadingLineSequence' - strong: 'strong' - strongSequence: 'strongSequence' - strongText: 'strongText' - thematicBreak: 'thematicBreak' - thematicBreakSequence: 'thematicBreakSequence' - blockQuote: 'blockQuote' - blockQuotePrefix: 'blockQuotePrefix' - blockQuoteMarker: 'blockQuoteMarker' - blockQuotePrefixWhitespace: 'blockQuotePrefixWhitespace' - listOrdered: 'listOrdered' - listUnordered: 'listUnordered' - listItemIndent: 'listItemIndent' - listItemMarker: 'listItemMarker' - listItemPrefix: 'listItemPrefix' - listItemPrefixWhitespace: 'listItemPrefixWhitespace' - listItemValue: 'listItemValue' - chunkDocument: 'chunkDocument' - chunkContent: 'chunkContent' - chunkFlow: 'chunkFlow' - chunkText: 'chunkText' - chunkString: 'chunkString' -} - -declare type Value = Value_2 - -/** - * Contents of the file. - * - * Can either be text, or a `Uint8Array` like structure. - */ -declare type Value_2 = Uint8Array | string - -export { } - -// Source: node_modules/micromark-extension-directive/index.d.ts - -export declare interface TokenTypeMap { - directiveContainer: 'directiveContainer' - directiveContainerAttributes: 'directiveContainerAttributes' - directiveContainerAttributesMarker: 'directiveContainerAttributesMarker' - directiveContainerAttribute: 'directiveContainerAttribute' - directiveContainerAttributeId: 'directiveContainerAttributeId' - directiveContainerAttributeIdValue: 'directiveContainerAttributeIdValue' - directiveContainerAttributeClass: 'directiveContainerAttributeClass' - directiveContainerAttributeClassValue: 'directiveContainerAttributeClassValue' - directiveContainerAttributeName: 'directiveContainerAttributeName' - directiveContainerAttributeInitializerMarker: 'directiveContainerAttributeInitializerMarker' - directiveContainerAttributeValueLiteral: 'directiveContainerAttributeValueLiteral' - directiveContainerAttributeValue: 'directiveContainerAttributeValue' - directiveContainerAttributeValueMarker: 'directiveContainerAttributeValueMarker' - directiveContainerAttributeValueData: 'directiveContainerAttributeValueData' - directiveContainerContent: 'directiveContainerContent' - directiveContainerFence: 'directiveContainerFence' - directiveContainerLabel: 'directiveContainerLabel' - directiveContainerLabelMarker: 'directiveContainerLabelMarker' - directiveContainerLabelString: 'directiveContainerLabelString' - directiveContainerName: 'directiveContainerName' - directiveContainerSequence: 'directiveContainerSequence' - - directiveLeaf: 'directiveLeaf' - directiveLeafAttributes: 'directiveLeafAttributes' - directiveLeafAttributesMarker: 'directiveLeafAttributesMarker' - directiveLeafAttribute: 'directiveLeafAttribute' - directiveLeafAttributeId: 'directiveLeafAttributeId' - directiveLeafAttributeIdValue: 'directiveLeafAttributeIdValue' - directiveLeafAttributeClass: 'directiveLeafAttributeClass' - directiveLeafAttributeClassValue: 'directiveLeafAttributeClassValue' - directiveLeafAttributeName: 'directiveLeafAttributeName' - directiveLeafAttributeInitializerMarker: 'directiveLeafAttributeInitializerMarker' - directiveLeafAttributeValueLiteral: 'directiveLeafAttributeValueLiteral' - directiveLeafAttributeValue: 'directiveLeafAttributeValue' - directiveLeafAttributeValueMarker: 'directiveLeafAttributeValueMarker' - directiveLeafAttributeValueData: 'directiveLeafAttributeValueData' - directiveLeafLabel: 'directiveLeafLabel' - directiveLeafLabelMarker: 'directiveLeafLabelMarker' - directiveLeafLabelString: 'directiveLeafLabelString' - directiveLeafName: 'directiveLeafName' - directiveLeafSequence: 'directiveLeafSequence' - - directiveText: 'directiveText' - directiveTextAttributes: 'directiveTextAttributes' - directiveTextAttributesMarker: 'directiveTextAttributesMarker' - directiveTextAttribute: 'directiveTextAttribute' - directiveTextAttributeId: 'directiveTextAttributeId' - directiveTextAttributeIdValue: 'directiveTextAttributeIdValue' - directiveTextAttributeClass: 'directiveTextAttributeClass' - directiveTextAttributeClassValue: 'directiveTextAttributeClassValue' - directiveTextAttributeName: 'directiveTextAttributeName' - directiveTextAttributeInitializerMarker: 'directiveTextAttributeInitializerMarker' - directiveTextAttributeValueLiteral: 'directiveTextAttributeValueLiteral' - directiveTextAttributeValue: 'directiveTextAttributeValue' - directiveTextAttributeValueMarker: 'directiveTextAttributeValueMarker' - directiveTextAttributeValueData: 'directiveTextAttributeValueData' - directiveTextLabel: 'directiveTextLabel' - directiveTextLabelMarker: 'directiveTextLabelMarker' - directiveTextLabelString: 'directiveTextLabelString' - directiveTextMarker: 'directiveTextMarker' - directiveTextName: 'directiveTextName' -} - -// Source: node_modules/micromark-extension-gfm-autolink-literal/index.d.ts - -export declare interface TokenTypeMap { - literalAutolink: 'literalAutolink' - literalAutolinkEmail: 'literalAutolinkEmail' - literalAutolinkHttp: 'literalAutolinkHttp' - literalAutolinkWww: 'literalAutolinkWww' -} - -// Source: node_modules/micromark-extension-gfm-footnote/index.d.ts - -export declare interface TokenTypeMap { - gfmFootnoteCall: 'gfmFootnoteCall' - gfmFootnoteCallLabelMarker: 'gfmFootnoteCallLabelMarker' - gfmFootnoteCallMarker: 'gfmFootnoteCallMarker' - gfmFootnoteCallString: 'gfmFootnoteCallString' - gfmFootnoteDefinition: 'gfmFootnoteDefinition' - gfmFootnoteDefinitionIndent: 'gfmFootnoteDefinitionIndent' - gfmFootnoteDefinitionLabel: 'gfmFootnoteDefinitionLabel' - gfmFootnoteDefinitionLabelMarker: 'gfmFootnoteDefinitionLabelMarker' - gfmFootnoteDefinitionLabelString: 'gfmFootnoteDefinitionLabelString' - gfmFootnoteDefinitionMarker: 'gfmFootnoteDefinitionMarker' - gfmFootnoteDefinitionWhitespace: 'gfmFootnoteDefinitionWhitespace' -} - -// Source: node_modules/micromark-extension-gfm-table/index.d.ts - -export declare interface TokenTypeMap { - table: 'table' - tableBody: 'tableBody' - tableCellDivider: 'tableCellDivider' - tableContent: 'tableContent' - tableData: 'tableData' - tableDelimiter: 'tableDelimiter' - tableDelimiterFiller: 'tableDelimiterFiller' - tableDelimiterMarker: 'tableDelimiterMarker' - tableDelimiterRow: 'tableDelimiterRow' - tableHead: 'tableHead' - tableHeader: 'tableHeader' - tableRow: 'tableRow' -} - -// Source: node_modules/micromark-extension-math/index.d.ts - -export declare interface TokenTypeMap { - mathFlow: 'mathFlow' - mathFlowFence: 'mathFlowFence' - mathFlowFenceMeta: 'mathFlowFenceMeta' - mathFlowFenceSequence: 'mathFlowFenceSequence' - mathFlowValue: 'mathFlowValue' - mathText: 'mathText' - mathTextData: 'mathTextData' - mathTextPadding: 'mathTextPadding' - mathTextSequence: 'mathTextSequence' -} - -// Source: Custom types generated by markdownlint in getEvents - -export declare interface TokenTypeMap { - undefinedReference: 'undefinedReference' - undefinedReferenceCollapsed: 'undefinedReferenceCollapsed' - undefinedReferenceFull: 'undefinedReferenceFull' - undefinedReferenceShortcut: 'undefinedReferenceShortcut' -} diff --git a/micromark/package.json b/micromark/package.json deleted file mode 100644 index 58c50af56..000000000 --- a/micromark/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "markdownlint-micromark", - "version": "0.1.12", - "description": "A trivial package that re-exports some micromark functionality as a CommonJS module", - "type": "commonjs", - "exports": "./micromark.cjs", - "types": "./micromark.d.cts", - "author": "David Anson (https://dlaa.me/)", - "license": "MIT", - "homepage": "https://github.com/DavidAnson/markdownlint", - "repository": { - "type": "git", - "url": "git+https://github.com/DavidAnson/markdownlint.git" - }, - "bugs": "https://github.com/DavidAnson/markdownlint/issues", - "funding": "https://github.com/sponsors/DavidAnson", - "scripts": { - "build": "webpack --stats minimal", - "types": "api-extractor run --local" - }, - "engines": { - "node": ">=18" - }, - "files": [ - "LICENSE", - "micromark-browser.js", - "micromark-html-browser.js", - "micromark.cjs", - "micromark.d.cts", - "package.json", - "README.md" - ], - "devDependencies": { - "@microsoft/api-extractor": "7.47.12", - "micromark": "4.0.1", - "micromark-extension-directive": "3.0.2", - "micromark-extension-gfm-autolink-literal": "2.1.0", - "micromark-extension-gfm-footnote": "2.1.0", - "micromark-extension-gfm-table": "2.1.0", - "micromark-extension-math": "3.1.0", - "micromark-util-types": "2.0.1", - "terser-webpack-plugin": "5.3.10", - "webpack": "5.96.1", - "webpack-cli": "5.1.4" - } -} diff --git a/micromark/types.d.ts b/micromark/types.d.ts deleted file mode 100644 index e146e23e3..000000000 --- a/micromark/types.d.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Manually update due to api-extractor limitations including: -// - https://github.com/microsoft/rushstack/issues/1709 -// - ERROR: Failed to fetch entity for import() type node: import('micromark-util-types').ParseContext -// - Unwillingness to treat "katex" as one of bundledPackages -// -// 1. npm install -// 2. Comment-out micromark-util-types/ParseContext in micromark/node_modules/micromark-extension-gfm-footnote/index.d.ts -// 3. npm run types -// 4. Remove "import type { KatexOptions } from 'katex';" in micromark/micromark.d.cts -// 5. Replace "KatexOptions" with "Object" in micromark/micromark.d.cts -// 6. Append "declare module 'micromark-util-types' { interface TokenTypeMap { ... } }" in micromark/micromark.d.cts from: -// - micromark/node_modules/micromark-extension-directive/index.d.ts -// - micromark/node_modules/micromark-extension-gfm-autolink-literal/index.d.ts -// - micromark/node_modules/micromark-extension-gfm-footnote/index.d.ts -// - micromark/node_modules/micromark-extension-gfm-table/index.d.ts -// - micromark/node_modules/micromark-extension-math/index.d.ts -// - export declare interface TokenTypeMap { -// undefinedReference: 'undefinedReference' -// undefinedReferenceCollapsed: 'undefinedReferenceCollapsed' -// undefinedReferenceFull: 'undefinedReferenceFull' -// undefinedReferenceShortcut: 'undefinedReferenceShortcut' -// } -// 7. Update version number in package.json and stage changes -// 8. Test: npm run build, npm pack, npm install ./micromark/markdownlint-micromark-0.1.11.tgz, npm run ci, verify types like gfmFootnote* in getReferenceLinkImageData(...) -// 9. Publish: git clean -dfx, npm install, npm run build, npm publish ., git push - -export type { directive, directiveHtml } from "micromark-extension-directive"; -export type { gfmAutolinkLiteral, gfmAutolinkLiteralHtml } from "micromark-extension-gfm-autolink-literal"; -export type { gfmFootnote, gfmFootnoteHtml } from "micromark-extension-gfm-footnote"; -export type { gfmTable, gfmTableHtml } from "micromark-extension-gfm-table"; -export type { math, mathHtml } from "micromark-extension-math"; -export type { compile, parse, postprocess, preprocess } from "micromark"; - -export type { CompileData, Construct, Event, ParseOptions, State, Token, TokenType, TokenTypeMap, Tokenizer } from "micromark-util-types"; diff --git a/micromark/webpack.config.js b/micromark/webpack.config.js deleted file mode 100644 index 3cc2c28bd..000000000 --- a/micromark/webpack.config.js +++ /dev/null @@ -1,127 +0,0 @@ -// @ts-check - -"use strict"; - -const webpack = require("webpack"); -const TerserPlugin = require("terser-webpack-plugin"); -const { name, version, homepage } = require("./package.json"); - -const htmlEntry = "./exports-html.mjs"; -const htmlName = "micromarkHtmlBrowser"; - -const base = { - "entry": "./exports.mjs", - "output": { - "path": __dirname - }, - "plugins": [ - new webpack.BannerPlugin({ - "banner": `${name} ${version} ${homepage}` - }) - ] -}; - -const commonjs = { - ...base, - "output": { - ...base.output, - "library": { - "type": "commonjs" - } - }, - "target": "node" -}; - -const web = { - ...base, - "output": { - ...base.output, - "library": { - "name": "micromarkBrowser", - "type": "var" - } - }, - "target": "web" -}; - -const production = { - "mode": "production", - "optimization": { - "minimizer": [ - new TerserPlugin({ - "extractComments": false, - "terserOptions": { - "compress": { - "passes": 2 - } - } - }) - ] - } -}; - -const development = { - "devtool": false, - "mode": "development" -}; - -module.exports = [ - { - ...commonjs, - ...production, - "output": { - ...commonjs.output, - "filename": "micromark.cjs" - } - }, - { - ...commonjs, - ...development, - "output": { - ...commonjs.output, - "filename": "micromark.dev.cjs" - } - }, - { - ...web, - ...production, - "output": { - ...web.output, - "filename": "micromark-browser.js" - } - }, - { - ...web, - ...development, - "output": { - ...web.output, - "filename": "micromark-browser.dev.js" - } - }, - { - ...web, - ...production, - "entry": htmlEntry, - "output": { - ...web.output, - "library": { - ...web.output.library, - "name": htmlName - }, - "filename": "micromark-html-browser.js" - } - }, - { - ...web, - ...development, - "entry": htmlEntry, - "output": { - ...web.output, - "library": { - ...web.output.library, - "name": htmlName - }, - "filename": "micromark-html-browser.dev.js" - } - } -]; diff --git a/package.json b/package.json index 243823c7c..a7ac62bc2 100644 --- a/package.json +++ b/package.json @@ -2,17 +2,16 @@ "name": "markdownlint", "version": "0.36.1", "description": "A Node.js style checker and lint tool for Markdown/CommonMark files.", - "type": "commonjs", - "main": "./lib/markdownlint.js", + "type": "module", "exports": { - ".": "./lib/markdownlint.js", - "./helpers": "./helpers/helpers.js", + ".": "./lib/markdownlint.mjs", + "./helpers": "./helpers/helpers.cjs", "./style/all": "./style/all.json", "./style/cirosantilli": "./style/cirosantilli.json", "./style/prettier": "./style/prettier.json", "./style/relaxed": "./style/relaxed.json" }, - "types": "./lib/markdownlint.d.ts", + "types": "./lib/markdownlint.d.mts", "author": "David Anson (https://dlaa.me/)", "license": "MIT", "homepage": "https://github.com/DavidAnson/markdownlint", @@ -24,10 +23,10 @@ "funding": "https://github.com/sponsors/DavidAnson", "scripts": { "build-config": "npm run build-config-schema && npm run build-config-example", - "build-config-example": "node schema/build-config-example.js", - "build-config-schema": "node schema/build-config-schema.js", - "build-declaration": "tsc --allowJs --declaration --emitDeclarationOnly --module commonjs --outDir dts --resolveJsonModule --target es2015 lib/markdownlint.js && node scripts copy dts/lib/markdownlint.d.ts lib/markdownlint.d.ts && node scripts remove dts", - "build-demo": "node scripts copy node_modules/markdown-it/dist/markdown-it.min.js demo/markdown-it.min.js && node scripts copy node_modules/markdownlint-micromark/micromark-browser.js demo/micromark-browser.js && node scripts copy node_modules/markdownlint-micromark/micromark-html-browser.js demo/micromark-html-browser.js && cd demo && webpack --no-stats", + "build-config-example": "node schema/build-config-example.mjs", + "build-config-schema": "node schema/build-config-schema.mjs", + "build-declaration": "tsc --allowJs --declaration --emitDeclarationOnly --module nodenext --outDir dts --target es2015 lib/markdownlint.mjs && node scripts/index.mjs copy dts/lib/markdownlint.d.mts lib/markdownlint.d.mts && node scripts/index.mjs remove dts", + "build-demo": "node scripts/index.mjs copy node_modules/markdown-it/dist/markdown-it.min.js demo/markdown-it.min.js && cd demo && webpack --no-stats", "build-docs": "node doc-build/build-rules.mjs", "build-example": "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2", "build-micromark": "cd micromark && npm run build", @@ -45,20 +44,18 @@ "clone-test-repos-webpack-webpack-js-org": "cd test-repos && git clone https://github.com/webpack/webpack.js.org webpack-webpack-js-org --depth 1 --no-tags --quiet", "clone-test-repos": "mkdir test-repos && cd test-repos && npm run clone-test-repos-apache-airflow && npm run clone-test-repos-dotnet-docs && npm run clone-test-repos-electron-electron && npm run clone-test-repos-eslint-eslint && npm run clone-test-repos-mdn-content && npm run clone-test-repos-mkdocs-mkdocs && npm run clone-test-repos-mochajs-mocha && npm run clone-test-repos-pi-hole-docs && npm run clone-test-repos-v8-v8-dev && npm run clone-test-repos-webhintio-hint && npm run clone-test-repos-webpack-webpack-js-org", "declaration": "npm run build-declaration && npm run test-declaration", - "example": "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint", - "docker-npm-install": "docker run --rm --tty --name npm-install --volume $PWD:/home/workdir --workdir /home/workdir --user node node:latest npm install", - "docker-npm-run-upgrade": "docker run --rm --tty --name npm-run-upgrade --volume $PWD:/home/workdir --workdir /home/workdir --user node node:latest npm run upgrade", + "example": "cd example && node standalone.mjs && grunt markdownlint --force && gulp markdownlint", "install-micromark": "cd micromark && npm install", "lint": "eslint --max-warnings 0", - "lint-test-repos": "ava --timeout=10m test/markdownlint-test-repos-*.js", + "lint-test-repos": "ava --timeout=10m test/markdownlint-test-repos-*.mjs", "serial-config-docs": "npm run build-config && npm run build-docs", "serial-declaration-demo": "npm run build-declaration && npm-run-all --continue-on-error --parallel build-demo test-declaration", - "test": "ava --timeout=30s test/markdownlint-test.js test/markdownlint-test-config.js test/markdownlint-test-custom-rules.js test/markdownlint-test-fixes.js test/markdownlint-test-helpers.js test/markdownlint-test-micromark.mjs test/markdownlint-test-result-object.js test/markdownlint-test-scenarios.js helpers/test.cjs", + "test": "ava --timeout=30s test/markdownlint-test.mjs test/markdownlint-test-config.mjs test/markdownlint-test-custom-rules.mjs test/markdownlint-test-fixes.mjs test/markdownlint-test-helpers.mjs test/markdownlint-test-micromark.mjs test/markdownlint-test-result-object.mjs test/markdownlint-test-scenarios.mjs helpers/test.cjs", "test-cover": "c8 --100 npm test", - "test-declaration": "cd example/typescript && tsc --module nodenext && tsc --module commonjs && node type-check.js", - "test-extra": "ava --timeout=10m test/markdownlint-test-extra-parse.js test/markdownlint-test-extra-type.js", - "update-snapshots": "ava --update-snapshots test/markdownlint-test-custom-rules.js test/markdownlint-test-micromark.mjs test/markdownlint-test-scenarios.js", - "update-snapshots-test-repos": "ava --timeout=10m --update-snapshots test/markdownlint-test-repos-*.js", + "test-declaration": "cd example/typescript && tsc --module commonjs && tsc --module nodenext && node type-check.js", + "test-extra": "ava --timeout=10m test/markdownlint-test-extra-parse.mjs test/markdownlint-test-extra-type.mjs", + "update-snapshots": "ava --update-snapshots test/markdownlint-test-custom-rules.mjs test/markdownlint-test-micromark.mjs test/markdownlint-test-scenarios.mjs", + "update-snapshots-test-repos": "ava --timeout=10m --update-snapshots test/markdownlint-test-repos-*.mjs", "upgrade": "npx --yes npm-check-updates --upgrade" }, "engines": { @@ -66,7 +63,13 @@ }, "dependencies": { "markdown-it": "14.1.0", - "markdownlint-micromark": "0.1.12" + "micromark": "4.0.0", + "micromark-extension-directive": "3.0.2", + "micromark-extension-gfm-autolink-literal": "2.1.0", + "micromark-extension-gfm-footnote": "2.1.0", + "micromark-extension-gfm-table": "2.1.0", + "micromark-extension-math": "3.1.0", + "micromark-util-types": "2.0.0" }, "devDependencies": { "@eslint/js": "9.15.0", diff --git a/schema/build-config-example.js b/schema/build-config-example.mjs similarity index 79% rename from schema/build-config-example.js rename to schema/build-config-example.mjs index bc75f7e19..bd595ab21 100644 --- a/schema/build-config-example.js +++ b/schema/build-config-example.mjs @@ -1,11 +1,10 @@ // @ts-check -"use strict"; - -const fs = require("node:fs"); -const path = require("node:path"); -const yaml = require("js-yaml"); -const configSchema = require("./markdownlint-config-schema.json"); +import fs from "node:fs"; +import path from "node:path"; +import yaml from "js-yaml"; +import { __dirname, importWithTypeJson } from "../test/esm-helpers.mjs"; +const configSchema = await importWithTypeJson(import.meta, "../schema/markdownlint-config-schema.json"); const configExample = {}; for (const rule in configSchema.properties) { @@ -36,7 +35,7 @@ const transformComments = (input, commentPrefix) => ( const configStringJson = JSON.stringify(configExample, null, 2); fs.writeFileSync( - path.join(__dirname, ".markdownlint.jsonc"), + path.join(__dirname(import.meta), ".markdownlint.jsonc"), transformComments(configStringJson, "//"), "utf8" ); @@ -50,7 +49,7 @@ const configStringYaml = yaml.dump( } ); fs.writeFileSync( - path.join(__dirname, ".markdownlint.yaml"), + path.join(__dirname(import.meta), ".markdownlint.yaml"), transformComments(configStringYaml, "#"), "utf8" ); diff --git a/schema/build-config-schema.js b/schema/build-config-schema.mjs similarity index 95% rename from schema/build-config-schema.js rename to schema/build-config-schema.mjs index b967ad1c0..5ea5fb35d 100644 --- a/schema/build-config-schema.js +++ b/schema/build-config-schema.mjs @@ -1,13 +1,12 @@ // @ts-check -"use strict"; - -const fs = require("node:fs"); -const path = require("node:path"); -/** @type {import("../lib/markdownlint").Rule[]} */ -const rules = require("../lib/rules"); -const jsonSchemaToTypeScript = require("json-schema-to-typescript"); -const { version } = require("../lib/constants"); +import fs from "node:fs"; +import path from "node:path"; +/** @type {import("../lib/markdownlint.mjs").Rule[]} */ +import rules from "../lib/rules.mjs"; +import jsonSchemaToTypeScript from "json-schema-to-typescript"; +import { version } from "../lib/constants.mjs"; +import { __dirname } from "../test/esm-helpers.mjs"; const schemaName = "markdownlint-config-schema.json"; const schemaUri = `https://raw.githubusercontent.com/DavidAnson/markdownlint/v${version}/schema/${schemaName}`; @@ -586,7 +585,7 @@ for (const [ tag, tagTags ] of Object.entries(tags)) { } // Write schema -const schemaFile = path.join(__dirname, schemaName); +const schemaFile = path.join(__dirname(import.meta), schemaName); fs.writeFileSync(schemaFile, JSON.stringify(schema, null, " ")); // Create and write strict schema @@ -595,15 +594,15 @@ const schemaStrict = { "$id": schemaStrictUri, "additionalProperties": false }; -const schemaFileStrict = path.join(__dirname, schemaStrictName); +const schemaFileStrict = path.join(__dirname(import.meta), schemaStrictName); fs.writeFileSync(schemaFileStrict, JSON.stringify(schemaStrict, null, " ")); // Write TypeScript declaration file -const declarationStrictName = path.join(__dirname, "..", "lib", "configuration-strict.d.ts"); +const declarationStrictName = path.join(__dirname(import.meta), "..", "lib", "configuration-strict.d.ts"); schemaStrict.title = "ConfigurationStrict"; -jsonSchemaToTypeScript.compile( +const declaration = await jsonSchemaToTypeScript.compile( // @ts-ignore schemaStrict, "UNUSED" - // eslint-disable-next-line unicorn/prefer-top-level-await -).then((declaration) => fs.writeFileSync(declarationStrictName, declaration)); +); +fs.writeFileSync(declarationStrictName, declaration); diff --git a/scripts/index.js b/scripts/index.js deleted file mode 100644 index 03ef88a07..000000000 --- a/scripts/index.js +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-check - -"use strict"; - -const fs = require("node:fs").promises; - -const [ command, ...args ] = process.argv.slice(2); - -// eslint-disable-next-line unicorn/prefer-top-level-await -(async() => { - if (command === "copy") { - const [ src, dest ] = args; - await fs.copyFile(src, dest); - } else if (command === "delete") { - const { globby } = await import("globby"); - await Promise.all( - args.flatMap( - (glob) => globby(glob) - .then( - (files) => files.map((file) => fs.unlink(file)) - ) - ) - ); - } else if (command === "remove") { - await Promise.all(args.map((dir) => fs.rm(dir, { "recursive": true }))); - } else { - throw new Error(`Unsupported command: ${command}`); - } -})(); diff --git a/scripts/index.mjs b/scripts/index.mjs new file mode 100644 index 000000000..9e9ff6b4e --- /dev/null +++ b/scripts/index.mjs @@ -0,0 +1,24 @@ +// @ts-check + +import fs from "node:fs/promises"; +import { globby } from "globby"; + +const [ command, ...args ] = process.argv.slice(2); + +if (command === "copy") { + const [ src, dest ] = args; + await fs.copyFile(src, dest); +} else if (command === "delete") { + await Promise.all( + args.flatMap( + (glob) => globby(glob) + .then( + (files) => files.map((file) => fs.unlink(file)) + ) + ) + ); +} else if (command === "remove") { + await Promise.all(args.map((dir) => fs.rm(dir, { "recursive": true }))); +} else { + throw new Error(`Unsupported command: ${command}`); +} diff --git a/test/esm-helpers.mjs b/test/esm-helpers.mjs new file mode 100644 index 000000000..be66c9940 --- /dev/null +++ b/test/esm-helpers.mjs @@ -0,0 +1,38 @@ +// @ts-check + +import fs from "node:fs/promises"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +/** + * Gets the file name of the current module. + * Shims import.meta.filename for Node 18. + * + * @param {Object} meta ESM import.meta object. + * @returns {string} File name. + */ +// eslint-disable-next-line no-underscore-dangle +export const __filename = (meta) => fileURLToPath(meta.url); + +/** + * Gets the directory name of the current module. + * Shims import.meta.dirname for Node 18. + * + * @param {Object} meta ESM import.meta object. + * @returns {string} Directory name. + */ +// eslint-disable-next-line no-underscore-dangle +export const __dirname = (meta) => path.dirname(__filename(meta)); + +/** + * Imports a file as JSON. + * Avoids "ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time". + * + * @param {Object} meta ESM import.meta object. + * @param {string} file JSON file to import. + * @returns {Promise} JSON object. + */ +export const importWithTypeJson = async(meta, file) => ( + // @ts-ignore + JSON.parse(await fs.readFile(path.resolve(__dirname(meta), file))) +); diff --git a/test/harness.mjs b/test/harness.mjs index 712e5ede3..65fe54d4e 100644 --- a/test/harness.mjs +++ b/test/harness.mjs @@ -1,6 +1,6 @@ import { readFile } from "node:fs/promises"; -import { parse } from "../helpers/micromark-parse.cjs"; -import library from "../lib/markdownlint.js"; +import { parse } from "../helpers/micromark-parse.mjs"; +import library from "../lib/markdownlint.mjs"; const markdownlint = library.promises.markdownlint; /* eslint-disable no-await-in-loop, no-console */ diff --git a/test/markdownlint-test-config.js b/test/markdownlint-test-config.mjs similarity index 96% rename from test/markdownlint-test-config.js rename to test/markdownlint-test-config.mjs index 123f165f8..eb1308ec5 100644 --- a/test/markdownlint-test-config.js +++ b/test/markdownlint-test-config.mjs @@ -1,13 +1,14 @@ // @ts-check -"use strict"; +import { createRequire } from "node:module"; +const require = createRequire(import.meta.url); +import os from "node:os"; +import path from "node:path"; +import test from "ava"; +import markdownlint from "../lib/markdownlint.mjs"; +import { __dirname } from "./esm-helpers.mjs"; -const os = require("node:os"); -const path = require("node:path"); -const test = require("ava").default; -const markdownlint = require("../lib/markdownlint"); - -const sameFileSystem = (path.relative(os.homedir(), __dirname) !== __dirname); +const sameFileSystem = (path.relative(os.homedir(), __dirname(import.meta)) !== __dirname(import.meta)); test("configSingle", (t) => new Promise((resolve) => { t.plan(2); @@ -22,7 +23,7 @@ test("configSingle", (t) => new Promise((resolve) => { test("configAbsolute", (t) => new Promise((resolve) => { t.plan(2); - markdownlint.readConfig(path.join(__dirname, "config", "config-child.json"), + markdownlint.readConfig(path.join(__dirname(import.meta), "config", "config-child.json"), function callback(err, actual) { t.falsy(err); const expected = require("./config/config-child.json"); @@ -268,7 +269,7 @@ test("configSingleSync", (t) => { test("configAbsoluteSync", (t) => { t.plan(1); const actual = markdownlint.readConfigSync( - path.join(__dirname, "config", "config-child.json")); + path.join(__dirname(import.meta), "config", "config-child.json")); const expected = require("./config/config-child.json"); t.deepEqual(actual, expected, "Config object not correct."); }); diff --git a/test/markdownlint-test-custom-rules.js b/test/markdownlint-test-custom-rules.mjs similarity index 91% rename from test/markdownlint-test-custom-rules.js rename to test/markdownlint-test-custom-rules.mjs index ec805ed51..c6cf367d5 100644 --- a/test/markdownlint-test-custom-rules.js +++ b/test/markdownlint-test-custom-rules.mjs @@ -1,19 +1,20 @@ // @ts-check -"use strict"; - -const fs = require("node:fs").promises; -const test = require("ava").default; -const markdownlint = require("../lib/markdownlint"); -const customRules = require("./rules/rules.js"); -const { homepage, version } = require("../package.json"); -const { newLineRe } = require("../helpers/helpers.js"); +import fs from "node:fs/promises"; +import { createRequire } from "node:module"; +const require = createRequire(import.meta.url); +import test from "ava"; +import markdownlint from "../lib/markdownlint.mjs"; +import customRules from "./rules/rules.cjs"; +import { newLineRe } from "../helpers/helpers.cjs"; +import { __filename, importWithTypeJson } from "./esm-helpers.mjs"; +const packageJson = await importWithTypeJson(import.meta, "../package.json"); +const { homepage, version } = packageJson; test("customRulesV0", (t) => new Promise((resolve) => { t.plan(4); const customRulesMd = "./test/custom-rules.md"; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": customRules.all, "files": [ customRulesMd ], @@ -85,8 +86,7 @@ test("customRulesV0", (t) => new Promise((resolve) => { test("customRulesV1", (t) => new Promise((resolve) => { t.plan(3); const customRulesMd = "./test/custom-rules.md"; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": customRules.all, "files": [ customRulesMd ], @@ -217,8 +217,7 @@ test("customRulesV1", (t) => new Promise((resolve) => { test("customRulesV2", (t) => new Promise((resolve) => { t.plan(3); const customRulesMd = "./test/custom-rules.md"; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": customRules.all, "files": [ customRulesMd ], @@ -339,8 +338,7 @@ test("customRulesV2", (t) => new Promise((resolve) => { test("customRulesConfig", (t) => new Promise((resolve) => { t.plan(2); const customRulesMd = "./test/custom-rules.md"; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": customRules.all, "files": [ customRulesMd ], @@ -370,8 +368,7 @@ test("customRulesConfig", (t) => new Promise((resolve) => { test("customRulesNpmPackage", (t) => new Promise((resolve) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ require("./rules/npm"), @@ -434,8 +431,7 @@ test("customRulesBadProperty", (t) => { for (const propertyValue of propertyValues) { const badRule = { ...customRules.firstLine }; badRule[propertyName] = propertyValue; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ badRule ] }; @@ -456,8 +452,7 @@ test("customRulesBadProperty", (t) => { test("customRulesUsedNameName", (t) => new Promise((resolve) => { t.plan(4); markdownlint({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name", "NO-missing-SPACE-atx" ], @@ -483,8 +478,7 @@ test("customRulesUsedNameName", (t) => new Promise((resolve) => { test("customRulesUsedNameTag", (t) => new Promise((resolve) => { t.plan(4); markdownlint({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name", "HtMl" ], @@ -509,8 +503,7 @@ test("customRulesUsedNameTag", (t) => new Promise((resolve) => { test("customRulesUsedTagName", (t) => new Promise((resolve) => { t.plan(4); markdownlint({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "filler" ], @@ -542,8 +535,7 @@ test("customRulesUsedTagName", (t) => new Promise((resolve) => { test("customRulesParserUndefined", (t) => { t.plan(5); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ // @ts-ignore @@ -570,8 +562,7 @@ test("customRulesParserUndefined", (t) => { test("customRulesParserNone", (t) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -595,8 +586,7 @@ test("customRulesParserNone", (t) => { test("customRulesParserMarkdownIt", (t) => { t.plan(5); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -623,8 +613,7 @@ test("customRulesParserMarkdownIt", (t) => { test("customRulesParserMicromark", (t) => { t.plan(5); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -651,8 +640,7 @@ test("customRulesParserMicromark", (t) => { test("customRulesMarkdownItParamsTokensSameObject", (t) => { t.plan(1); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ // @ts-ignore @@ -676,8 +664,7 @@ test("customRulesMarkdownItParamsTokensSameObject", (t) => { test("customRulesMarkdownItTokensSnapshot", (t) => { t.plan(1); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -703,8 +690,7 @@ test("customRulesMarkdownItTokensSnapshot", (t) => { test("customRulesMicromarkTokensSnapshot", (t) => { t.plan(1); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -730,8 +716,7 @@ test("customRulesMicromarkTokensSnapshot", (t) => { test("customRulesDefinitionStatic", (t) => new Promise((resolve) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -781,8 +766,7 @@ test("customRulesThrowForFile", (t) => new Promise((resolve) => { t.plan(4); const exceptionMessage = "Test exception message"; markdownlint({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -812,8 +796,7 @@ test("customRulesThrowForFileSync", (t) => { t.throws( function customRuleThrowsCall() { markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -839,8 +822,7 @@ test("customRulesThrowForString", (t) => new Promise((resolve) => { t.plan(4); const exceptionMessage = "Test exception message"; markdownlint({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -872,8 +854,7 @@ test("customRulesThrowForStringSync", (t) => { t.throws( function customRuleThrowsCall() { markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -900,8 +881,7 @@ test("customRulesThrowForStringSync", (t) => { test("customRulesOnErrorNull", (t) => new Promise((resolve) => { t.plan(4); markdownlint({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -934,8 +914,7 @@ test("customRulesOnErrorNull", (t) => new Promise((resolve) => { test("customRulesOnErrorNullSync", (t) => { t.plan(1); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1026,8 +1005,7 @@ test("customRulesOnErrorBad", (t) => { badObject[propertyName] = propertyValue; propertyNames = propertyName; } - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1099,8 +1077,7 @@ test("customRulesOnErrorInvalid", (t) => { badObject[propertyName] = propertyValue; propertyNames = propertyName; } - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1175,8 +1152,7 @@ test("customRulesOnErrorValid", (t) => { } else { goodObject[propertyName] = propertyValue; } - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1201,8 +1177,7 @@ test("customRulesOnErrorValid", (t) => { test("customRulesOnErrorLazy", (t) => new Promise((resolve) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1259,8 +1234,7 @@ test("customRulesOnErrorModified", (t) => new Promise((resolve) => { "insertText": "text" } }; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1313,8 +1287,7 @@ test("customRulesOnErrorModified", (t) => new Promise((resolve) => { test("customRulesOnErrorInvalidHandled", (t) => new Promise((resolve) => { t.plan(2); markdownlint({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1357,8 +1330,7 @@ test("customRulesOnErrorInvalidHandled", (t) => new Promise((resolve) => { test("customRulesOnErrorInvalidHandledSync", (t) => { t.plan(1); const actualResult = markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1398,8 +1370,7 @@ test("customRulesOnErrorInvalidHandledSync", (t) => { test("customRulesVersion", (t) => new Promise((resolve) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1422,8 +1393,7 @@ test("customRulesVersion", (t) => new Promise((resolve) => { test("customRulesFileName", (t) => new Promise((resolve) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1446,8 +1416,7 @@ test("customRulesFileName", (t) => new Promise((resolve) => { test("customRulesStringName", (t) => new Promise((resolve) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1473,8 +1442,7 @@ test("customRulesStringName", (t) => new Promise((resolve) => { test("customRulesOnErrorInformationNotRuleNotError", (t) => { t.plan(1); const actualResult = markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1498,8 +1466,7 @@ test("customRulesOnErrorInformationNotRuleNotError", (t) => { test("customRulesOnErrorInformationRuleNotError", (t) => { t.plan(1); const actualResult = markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1528,8 +1495,7 @@ test("customRulesOnErrorInformationRuleNotError", (t) => { test("customRulesOnErrorInformationNotRuleError", (t) => { t.plan(1); const actualResult = markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1558,8 +1524,7 @@ test("customRulesOnErrorInformationNotRuleError", (t) => { test("customRulesOnErrorInformationRuleError", (t) => { t.plan(1); const actualResult = markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1589,8 +1554,7 @@ test("customRulesOnErrorInformationRuleError", (t) => { test("customRulesOnErrorInformationRuleErrorUndefined", (t) => { t.plan(1); const actualResult = markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1620,8 +1584,7 @@ test("customRulesOnErrorInformationRuleErrorUndefined", (t) => { test("customRulesOnErrorInformationRuleErrorMultiple", (t) => { t.plan(6); const actualResult = markdownlint.sync({ - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ "customRules": [ { "names": [ "name" ], @@ -1697,8 +1660,7 @@ test("customRulesDoc", (t) => new Promise((resolve) => { test("customRulesLintJavaScript", (t) => new Promise((resolve) => { t.plan(2); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": customRules.lintJavaScript, "files": "test/lint-javascript.md" @@ -1726,8 +1688,7 @@ test("customRulesLintJavaScript", (t) => new Promise((resolve) => { test("customRulesValidateJson", (t) => new Promise((resolve) => { t.plan(3); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": customRules.validateJson, "files": "test/validate-json.md" @@ -1760,8 +1721,7 @@ test("customRulesValidateJson", (t) => new Promise((resolve) => { test("customRulesAsyncThrowsInSyncContext", (t) => { t.plan(1); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1805,8 +1765,7 @@ test("customRulesParamsAreFrozen", (t) => { } } }; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1840,8 +1799,7 @@ test("customRulesParamsAreStable", (t) => { t.plan(4); const config1 = { "value1": 10 }; const config2 = { "value2": 20 }; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "config": { "MD010": true, @@ -1907,8 +1865,7 @@ test("customRulesParamsAreStable", (t) => { test("customRulesAsyncReadFiles", (t) => { t.plan(3); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1919,7 +1876,7 @@ test("customRulesAsyncReadFiles", (t) => { "asynchronous": true, "parser": "none", "function": - (params, onError) => fs.readFile(__filename, "utf8").then( + (params, onError) => fs.readFile(__filename(import.meta), "utf8").then( (content) => { t.true(content.length > 0); onError({ @@ -1939,7 +1896,7 @@ test("customRulesAsyncReadFiles", (t) => { "parser": "none", "function": async(params, onError) => { - const content = await fs.readFile(__filename, "utf8"); + const content = await fs.readFile(__filename(import.meta), "utf8"); t.true(content.length > 0); onError({ "lineNumber": 1, @@ -1996,8 +1953,7 @@ test("customRulesAsyncReadFiles", (t) => { test("customRulesAsyncIgnoresSyncReturn", (t) => { t.plan(1); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -2088,8 +2044,7 @@ for (const flavor of [ ] ]) { const [ name, func ] = flavor; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule[] */ + /** @type {import("../lib/markdownlint.mjs").Rule[]} */ const customRule = [ { "names": [ "name" ], @@ -2202,7 +2157,7 @@ for (const flavor of [ ], [ "customRulesAsyncDeferredString", - () => fs.readFile(__filename, "utf8").then( + () => fs.readFile(__filename(import.meta), "utf8").then( () => { throw errorMessage; } @@ -2210,7 +2165,7 @@ for (const flavor of [ ], [ "customRulesAsyncDeferredError", - () => fs.readFile(__filename, "utf8").then( + () => fs.readFile(__filename(import.meta), "utf8").then( () => { throw new Error(errorMessage); } @@ -2226,8 +2181,7 @@ for (const flavor of [ ] ]) { const [ name, func ] = flavor; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Rule */ + /** @type {import("../lib/markdownlint.mjs").Rule} */ const customRule = { "names": [ "name" ], "description": "description", diff --git a/test/markdownlint-test-extra-parse.js b/test/markdownlint-test-extra-parse.mjs similarity index 61% rename from test/markdownlint-test-extra-parse.js rename to test/markdownlint-test-extra-parse.mjs index 9552566ad..976014484 100644 --- a/test/markdownlint-test-extra-parse.js +++ b/test/markdownlint-test-extra-parse.mjs @@ -1,14 +1,12 @@ // @ts-check -"use strict"; - -const test = require("ava").default; -const markdownlint = require("../lib/markdownlint"); +import test from "ava"; +import { globby } from "globby"; +import markdownlint from "../lib/markdownlint.mjs"; // Parses all Markdown files in all package dependencies test("parseAllFiles", async(t) => { t.plan(1); - const { globby } = await import("globby"); const files = await globby("**/*.{md,markdown}"); await markdownlint.promises.markdownlint({ files }); t.pass(); diff --git a/test/markdownlint-test-extra-type.js b/test/markdownlint-test-extra-type.mjs similarity index 76% rename from test/markdownlint-test-extra-type.js rename to test/markdownlint-test-extra-type.mjs index 59b094a46..e18b36cb0 100644 --- a/test/markdownlint-test-extra-type.js +++ b/test/markdownlint-test-extra-type.mjs @@ -1,11 +1,9 @@ // @ts-check -"use strict"; - -const fs = require("node:fs"); -const path = require("node:path"); -const test = require("ava").default; -const markdownlint = require("../lib/markdownlint"); +import fs from "node:fs"; +import path from "node:path"; +import test from "ava"; +import markdownlint from "../lib/markdownlint.mjs"; // Simulates typing each test file to validate handling of partial input const files = fs diff --git a/test/markdownlint-test-fixes.js b/test/markdownlint-test-fixes.mjs similarity index 98% rename from test/markdownlint-test-fixes.js rename to test/markdownlint-test-fixes.mjs index 94ef5f7e0..4db880d32 100644 --- a/test/markdownlint-test-fixes.js +++ b/test/markdownlint-test-fixes.mjs @@ -1,9 +1,7 @@ // @ts-check -"use strict"; - -const test = require("ava").default; -const markdownlint = require("../lib/markdownlint"); +import test from "ava"; +import markdownlint from "../lib/markdownlint.mjs"; test("applyFix", (t) => { t.plan(4); diff --git a/test/markdownlint-test-helpers.js b/test/markdownlint-test-helpers.mjs similarity index 96% rename from test/markdownlint-test-helpers.js rename to test/markdownlint-test-helpers.mjs index abc2f9072..4dd1c4d4c 100644 --- a/test/markdownlint-test-helpers.js +++ b/test/markdownlint-test-helpers.mjs @@ -1,14 +1,13 @@ // @ts-check -"use strict"; - -const os = require("node:os"); -const path = require("node:path"); -const test = require("ava").default; -const helpers = require("../helpers"); -const libMarkdownlint = require("../lib/markdownlint"); +import os from "node:os"; +import path from "node:path"; +import test from "ava"; +import helpers from "../helpers/helpers.cjs"; +import libMarkdownlint from "../lib/markdownlint.mjs"; const { markdownlint } = libMarkdownlint.promises; -const { forEachInlineCodeSpan } = require("../lib/markdownit.cjs"); +import { forEachInlineCodeSpan } from "../lib/markdownit.cjs"; +import { getReferenceLinkImageData } from "../lib/cache.mjs"; test("clearHtmlCommentTextValid", (t) => { t.plan(1); @@ -386,8 +385,7 @@ test("expandTildePath", (t) => { test("getReferenceLinkImageData().shortcuts", (t) => { t.plan(1); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -397,7 +395,6 @@ test("getReferenceLinkImageData().shortcuts", (t) => { "parser": "none", "function": () => { - const { getReferenceLinkImageData } = require("../lib/cache"); const { shortcuts } = getReferenceLinkImageData(); t.is(shortcuts.size, 0, [ ...shortcuts.keys() ].join(", ")); } @@ -447,7 +444,7 @@ test("ellipsify", (t) => { test("hasOverlap", (t) => { t.plan(32); - /** @type {import("../helpers").FileRange[][]} */ + /** @type {import("../helpers/helpers.cjs").FileRange[][]} */ const trueTestCases = [ // Same line [ diff --git a/test/markdownlint-test-micromark.mjs b/test/markdownlint-test-micromark.mjs index 7abe21394..fa44360cd 100644 --- a/test/markdownlint-test-micromark.mjs +++ b/test/markdownlint-test-micromark.mjs @@ -2,9 +2,9 @@ import fs from "node:fs/promises"; import test from "ava"; -import { newLineRe } from "../helpers/helpers.js"; +import { newLineRe } from "../helpers/helpers.cjs"; import { filterByPredicate, filterByTypes } from "../helpers/micromark-helpers.cjs"; -import { getEvents, parse } from "../helpers/micromark-parse.cjs"; +import { getEvents, parse } from "../helpers/micromark-parse.mjs"; const testContent = new Promise((resolve, reject) => { fs @@ -49,8 +49,7 @@ test("getEvents/filterByPredicate", async(t) => { test("filterByTypes, htmlFlow false", async(t) => { t.plan(7); const tokens = await testTokens; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../micromark/micromark.cjs").TokenType[] */ + /** @type {import("micromark-util-types").TokenType[]} */ const types = [ "atxHeadingText", "codeText", "htmlText", "setextHeadingText" ]; const filtered = filterByTypes(tokens, types); // Using flat tokens @@ -67,8 +66,7 @@ test("filterByTypes, htmlFlow false", async(t) => { test("filterByTypes, htmlFlow true", async(t) => { t.plan(9); const tokens = await testTokens; - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../micromark/micromark.cjs").TokenType[] */ + /** @type {import("micromark-util-types").TokenType[]} */ const types = [ "atxHeadingText", "codeText", "htmlText", "setextHeadingText" ]; // Using flat tokens const filtered = filterByTypes(tokens, types, true); diff --git a/test/markdownlint-test-parallel.js b/test/markdownlint-test-parallel.mjs similarity index 63% rename from test/markdownlint-test-parallel.js rename to test/markdownlint-test-parallel.mjs index d0f0a6383..615b464e6 100644 --- a/test/markdownlint-test-parallel.js +++ b/test/markdownlint-test-parallel.mjs @@ -1,19 +1,19 @@ // @ts-check -"use strict"; - // eslint-disable-next-line n/no-unsupported-features/node-builtins -const { availableParallelism } = require("node:os"); -const { Worker } = require("node:worker_threads"); -const markdownlintSync = require("../lib/markdownlint").sync; +import { availableParallelism } from "node:os"; +import { Worker } from "node:worker_threads"; +import { __filename } from "./esm-helpers.mjs"; +import markdownlint from "../lib/markdownlint.mjs"; +const markdownlintSync = markdownlint.sync; /** * Lint specified Markdown files (using multiple threads). * - * @param {import("../lib/markdownlint").Options} options Configuration options. - * @returns {Promise} Results object. + * @param {import("../lib/markdownlint.mjs").Options} options Configuration options. + * @returns {Promise} Results object. */ -function markdownlintParallel(options) { +export function markdownlintParallel(options) { const workerCount = availableParallelism(); const files = options.files || []; const chunkSize = Math.ceil(files.length / workerCount); @@ -24,7 +24,7 @@ function markdownlintParallel(options) { ...options, "files": files.slice(i * chunkSize, (i + 1) * chunkSize) }; - const worker = new Worker(__filename.replace(/parallel\.js$/, "worker.js"), { workerData }); + const worker = new Worker(__filename(import.meta).replace(/parallel\.mjs$/, "worker.mjs"), { workerData }); worker.on("message", resolve); worker.on("error", reject); })); @@ -40,5 +40,3 @@ function markdownlintParallel(options) { return combinedResults; }); } - -module.exports = markdownlintParallel; diff --git a/test/markdownlint-test-repos-dotnet-docs.js b/test/markdownlint-test-repos-dotnet-docs.mjs similarity index 64% rename from test/markdownlint-test-repos-dotnet-docs.js rename to test/markdownlint-test-repos-dotnet-docs.mjs index 87decdf21..b3a1ec419 100644 --- a/test/markdownlint-test-repos-dotnet-docs.js +++ b/test/markdownlint-test-repos-dotnet-docs.mjs @@ -1,10 +1,9 @@ // @ts-check -"use strict"; - -const { join } = require("node:path").posix; -const test = require("ava").default; -const { lintTestRepo } = require("./markdownlint-test-repos"); +import path from "node:path"; +const { join } = path.posix; +import test from "ava"; +import { lintTestRepo } from "./markdownlint-test-repos.mjs"; test("https://github.com/dotnet/docs", (t) => { const rootDir = "./test-repos/dotnet-docs"; diff --git a/test/markdownlint-test-repos-mdn-content.js b/test/markdownlint-test-repos-mdn-content.mjs similarity index 64% rename from test/markdownlint-test-repos-mdn-content.js rename to test/markdownlint-test-repos-mdn-content.mjs index 08f103fe8..71d579684 100644 --- a/test/markdownlint-test-repos-mdn-content.js +++ b/test/markdownlint-test-repos-mdn-content.mjs @@ -1,10 +1,9 @@ // @ts-check -"use strict"; - -const { join } = require("node:path").posix; -const test = require("ava").default; -const { lintTestRepo } = require("./markdownlint-test-repos"); +import path from "node:path"; +const { join } = path.posix; +import test from "ava"; +import { lintTestRepo } from "./markdownlint-test-repos.mjs"; test("https://github.com/mdn/content", (t) => { const rootDir = "./test-repos/mdn-content"; diff --git a/test/markdownlint-test-repos-small.js b/test/markdownlint-test-repos-small.mjs similarity index 94% rename from test/markdownlint-test-repos-small.js rename to test/markdownlint-test-repos-small.mjs index 812a39799..541654efe 100644 --- a/test/markdownlint-test-repos-small.js +++ b/test/markdownlint-test-repos-small.mjs @@ -1,10 +1,9 @@ // @ts-check -"use strict"; - -const { join } = require("node:path").posix; -const test = require("ava").default; -const { excludeGlobs, lintTestRepo } = require("./markdownlint-test-repos"); +import path from "node:path"; +const { join } = path.posix; +import test from "ava"; +import { excludeGlobs, lintTestRepo } from "./markdownlint-test-repos.mjs"; // Run markdownlint the same way the corresponding repositories do diff --git a/test/markdownlint-test-repos.js b/test/markdownlint-test-repos.mjs similarity index 77% rename from test/markdownlint-test-repos.js rename to test/markdownlint-test-repos.mjs index 7c8143311..c9183c62c 100644 --- a/test/markdownlint-test-repos.js +++ b/test/markdownlint-test-repos.mjs @@ -1,12 +1,12 @@ // @ts-check -"use strict"; - -const { join } = require("node:path").posix; -const jsoncParser = require("jsonc-parser"); -const jsYaml = require("js-yaml"); -const { markdownlint, readConfig } = require("../lib/markdownlint").promises; -const markdownlintParallel = require("./markdownlint-test-parallel"); +import path from "node:path"; +const { join } = path.posix; +import jsoncParser from "jsonc-parser"; +import jsYaml from "js-yaml"; +import library from "../lib/markdownlint.mjs"; +const { markdownlint, readConfig } = library.promises; +import { markdownlintParallel } from "./markdownlint-test-parallel.mjs"; /** * Lints a test repository. @@ -17,7 +17,7 @@ const markdownlintParallel = require("./markdownlint-test-parallel"); * @param {boolean} [parallel] True to lint in parallel. * @returns {Promise} Test result. */ -async function lintTestRepo(t, globPatterns, configPath, parallel) { +export async function lintTestRepo(t, globPatterns, configPath, parallel) { t.plan(1); const { globby } = await import("globby"); const jsoncParse = (json) => { @@ -59,11 +59,6 @@ async function lintTestRepo(t, globPatterns, configPath, parallel) { * @param {...string} globs Globs to exclude. * @returns {string[]} Array of excluded globs. */ -function excludeGlobs(rootDir, ...globs) { +export function excludeGlobs(rootDir, ...globs) { return globs.map((glob) => "!" + join(rootDir, glob)); } - -module.exports = { - excludeGlobs, - lintTestRepo -}; diff --git a/test/markdownlint-test-result-object.js b/test/markdownlint-test-result-object.mjs similarity index 98% rename from test/markdownlint-test-result-object.js rename to test/markdownlint-test-result-object.mjs index 7118f431b..3f4b549df 100644 --- a/test/markdownlint-test-result-object.js +++ b/test/markdownlint-test-result-object.mjs @@ -1,12 +1,10 @@ // @ts-check -"use strict"; - -const test = require("ava").default; -const packageJson = require("../package.json"); -const markdownlint = require("../lib/markdownlint"); -const homepage = packageJson.homepage; -const version = packageJson.version; +import test from "ava"; +import markdownlint from "../lib/markdownlint.mjs"; +import { importWithTypeJson } from "./esm-helpers.mjs"; +const packageJson = await importWithTypeJson(import.meta, "../package.json"); +const { homepage, version } = packageJson; test("resultObjectToStringNotEnumerable", (t) => new Promise((resolve) => { t.plan(2); diff --git a/test/markdownlint-test-scenarios.js b/test/markdownlint-test-scenarios.mjs similarity index 88% rename from test/markdownlint-test-scenarios.js rename to test/markdownlint-test-scenarios.mjs index ae563db57..76f60f870 100644 --- a/test/markdownlint-test-scenarios.js +++ b/test/markdownlint-test-scenarios.mjs @@ -1,15 +1,13 @@ // @ts-check -"use strict"; - -const fs = require("node:fs").promises; -const path = require("node:path"); -const test = require("ava").default; -const libMarkdownlint = require("../lib/markdownlint"); +import fs from "node:fs/promises"; +import path from "node:path"; +import test from "ava"; +import libMarkdownlint from "../lib/markdownlint.mjs"; const { applyFixes, promises } = libMarkdownlint; const { markdownlint } = promises; -const helpers = require("../helpers"); -const constants = require("../lib/constants"); +import helpers from "../helpers/helpers.cjs"; +import { fixableRuleNames } from "../lib/constants.mjs"; const numericalSortCompareFn = (a, b) => a - b; @@ -75,7 +73,7 @@ function createTestForFile(file) { indices.push(error.lineNumber); } t.true( - !error.fixInfo || constants.fixableRuleNames.includes(rule), + !error.fixInfo || fixableRuleNames.includes(rule), `Fixable rule ${rule} is not tagged as such.` ); } @@ -104,9 +102,8 @@ function createTestForFile(file) { ); } -const files = require("node:fs") - .readdirSync("./test") - .filter((file) => /\.md$/.test(file)); +const dir = await fs.readdir("./test"); +const files = dir.filter((file) => /\.md$/.test(file)); for (const file of files) { // @ts-ignore test( diff --git a/test/markdownlint-test-worker.js b/test/markdownlint-test-worker.js deleted file mode 100644 index 5ddee358f..000000000 --- a/test/markdownlint-test-worker.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check - -"use strict"; - -const { parentPort, workerData } = require("node:worker_threads"); -const markdownlint = require("../lib/markdownlint").promises.markdownlint; - -// eslint-disable-next-line unicorn/prefer-top-level-await -markdownlint(workerData).then((lintResults) => { - // @ts-ignore - parentPort - // eslint-disable-next-line unicorn/require-post-message-target-origin - .postMessage(lintResults); - // eslint-disable-next-line n/no-process-exit - process.exit(); -}); diff --git a/test/markdownlint-test-worker.mjs b/test/markdownlint-test-worker.mjs new file mode 100644 index 000000000..a2c7a9db1 --- /dev/null +++ b/test/markdownlint-test-worker.mjs @@ -0,0 +1,13 @@ +// @ts-check + +import { parentPort, workerData } from "node:worker_threads"; +import library from "../lib/markdownlint.mjs"; +const { markdownlint } = library.promises; + +const lintResults = await markdownlint(workerData); +// @ts-ignore +parentPort + // eslint-disable-next-line unicorn/require-post-message-target-origin + .postMessage(lintResults); +// eslint-disable-next-line n/no-process-exit +process.exit(); diff --git a/test/markdownlint-test.js b/test/markdownlint-test.mjs similarity index 93% rename from test/markdownlint-test.js rename to test/markdownlint-test.mjs index df907687a..c572ad7cc 100644 --- a/test/markdownlint-test.js +++ b/test/markdownlint-test.mjs @@ -1,24 +1,25 @@ // @ts-check -"use strict"; - -const fs = require("node:fs"); -const path = require("node:path"); -const Ajv = require("ajv"); -const jsoncParser = require("jsonc-parser"); -const jsYaml = require("js-yaml"); -const md = require("markdown-it")(); -const pluginInline = require("markdown-it-for-inline"); -const pluginSub = require("markdown-it-sub"); -const pluginSup = require("markdown-it-sup"); -const test = require("ava").default; -const { "exports": packageExports, homepage, name, version } = require("../package.json"); -const markdownlint = require("../lib/markdownlint"); -const constants = require("../lib/constants"); -const rules = require("../lib/rules"); -const customRules = require("./rules/rules.js"); -const configSchema = require("../schema/markdownlint-config-schema.json"); -const configSchemaStrict = require("../schema/markdownlint-config-schema-strict.json"); +import fs from "node:fs"; +import { createRequire } from "node:module"; +const require = createRequire(import.meta.url); +import path from "node:path"; +import Ajv from "ajv"; +import jsoncParser from "jsonc-parser"; +import jsYaml from "js-yaml"; +import markdownIt from "markdown-it"; +import pluginInline from "markdown-it-for-inline"; +import pluginSub from "markdown-it-sub"; +import pluginSup from "markdown-it-sup"; +import test from "ava"; +import markdownlint from "../lib/markdownlint.mjs"; +import * as constants from "../lib/constants.mjs"; +import rules from "../lib/rules.mjs"; +import customRules from "./rules/rules.cjs"; +import { __dirname, importWithTypeJson } from "./esm-helpers.mjs"; +const packageJson = await importWithTypeJson(import.meta, "../package.json"); +const configSchema = await importWithTypeJson(import.meta, "../schema/markdownlint-config-schema.json"); +const configSchemaStrict = await importWithTypeJson(import.meta, "../schema/markdownlint-config-schema-strict.json"); const deprecatedRuleNames = new Set(constants.deprecatedRuleNames); const ajvOptions = { @@ -82,7 +83,7 @@ test("projectFiles", (t) => { return import("globby") .then((module) => module.globby(projectFiles)) .then((files) => { - t.is(files.length, 61); + t.is(files.length, 60); const options = { files, "config": require("../.markdownlint.json") @@ -109,7 +110,7 @@ test("projectFilesExtendedAscii", (t) => { "!doc/md036.md" ])) .then((files) => { - t.is(files.length, 57); + t.is(files.length, 56); const options = { files, "config": require("../.markdownlint.json"), @@ -450,7 +451,7 @@ test("styleFiles", async(t) => { t.truthy(require(path.join("../style", file)), "Unable to load/parse."); const exportValue = `./style/${file}`; const exportKey = exportValue.replace(/\.json$/, ""); - t.is(packageExports[exportKey], exportValue); + t.is(packageJson.exports[exportKey], exportValue); } }); @@ -884,7 +885,7 @@ test("readme", async(t) => { let seenTags = false; let inTags = false; // @ts-ignore - for (const token of md.parse(contents, {})) { + for (const token of markdownIt().parse(contents, {})) { if ( (token.type === "bullet_list_open") && (token.level === 0) @@ -1035,14 +1036,14 @@ test("validateConfigExampleJson", (t) => { const validateSchema = ajv.compile(configSchema); t.is( configSchema.$id.replace(/^.*\/v(?\d+\.\d+\.\d+)\/.*$/u, "$"), - version + packageJson.version ); t.is(configSchema.$id, configSchema.properties.$schema.default); // Validate JSONC const fileJson = ".markdownlint.jsonc"; const dataJson = fs.readFileSync( - path.join(__dirname, "../schema", fileJson), + path.join(__dirname(import.meta), "../schema", fileJson), "utf8" ); const jsonObject = jsoncParser.parse(dataJson); @@ -1055,7 +1056,7 @@ test("validateConfigExampleJson", (t) => { // Validate YAML const fileYaml = ".markdownlint.yaml"; const dataYaml = fs.readFileSync( - path.join(__dirname, "../schema", fileYaml), + path.join(__dirname(import.meta), "../schema", fileYaml), "utf8" ); const yamlObject = jsYaml.load(dataYaml); @@ -1074,7 +1075,7 @@ test("allBuiltInRulesHaveValidUrl", (t) => { t.is( // @ts-ignore rule.information.href, - `${homepage}/blob/v${version}/doc/${ruleName}.md` + `${packageJson.homepage}/blob/v${packageJson.version}/doc/${ruleName}.md` ); } }); @@ -1087,12 +1088,12 @@ test("someCustomRulesHaveValidUrl", (t) => { if (rule === customRules.anyBlockquote) { t.is( rule.information?.href, - `${homepage}/blob/main/test/rules/any-blockquote.js` + `${packageJson.homepage}/blob/main/test/rules/any-blockquote.js` ); } else if (rule === customRules.lettersEX) { t.is( rule.information?.href, - `${homepage}/blob/main/test/rules/letters-E-X.js` + `${packageJson.homepage}/blob/main/test/rules/letters-E-X.js` ); } } @@ -1205,8 +1206,7 @@ Text with: [^footnote] test("token-map-spans", (t) => { t.plan(38); - // eslint-disable-next-line jsdoc/valid-types - /** @type import("../lib/markdownlint").Options */ + /** @type {import("../lib/markdownlint.mjs").Options} */ const options = { "customRules": [ { @@ -1351,21 +1351,21 @@ test("configParsersTOML", async(t) => { test("getVersion", (t) => { t.plan(1); const actual = markdownlint.getVersion(); - const expected = version; + const expected = packageJson.version; t.is(actual, expected, "Version string not correct."); }); test("constants", (t) => { t.plan(2); // @ts-ignore - t.is(constants.homepage, homepage); + t.is(constants.homepage, packageJson.homepage); // @ts-ignore - t.is(constants.version, version); + t.is(constants.version, packageJson.version); }); const exportMappings = new Map([ - [ ".", "../lib/markdownlint.js" ], - [ "./helpers", "../helpers/helpers.js" ], + [ ".", "../lib/markdownlint.mjs" ], + [ "./helpers", "../helpers/helpers.cjs" ], [ "./style/all", "../style/all.json" ], [ "./style/cirosantilli", "../style/cirosantilli.json" ], [ "./style/prettier", "../style/prettier.json" ], @@ -1374,16 +1374,22 @@ const exportMappings = new Map([ test("exportMappings", (t) => { t.deepEqual( - Object.keys(packageExports), + Object.keys(packageJson.exports), [ ...exportMappings.keys() ] ); }); +// const commonJsRe = /\.js$/u; +const jsonRe = /\.json$/u; +const importOptionsJson = { "with": { "type": "json" } }; + for (const [ exportName, exportPath ] of exportMappings) { - test(exportName, (t) => { - t.is( - require(exportName.replace(/^\./u, name)), - require(exportPath) - ); + test(exportName, async(t) => { + // const commonJs = !commonJsRe.test(exportPath); + const json = jsonRe.test(exportPath); + const importOptions = json ? importOptionsJson : undefined; + const importExportName = await import(exportName.replace(/^\./u, packageJson.name), importOptions); + const importExportPath = await import(exportPath, importOptions); + t.is(importExportName, importExportPath); }); } diff --git a/test/profile-fixture.mjs b/test/profile-fixture.mjs index 9dbad7b7b..ca191235d 100644 --- a/test/profile-fixture.mjs +++ b/test/profile-fixture.mjs @@ -1,5 +1,5 @@ import { readFile } from "node:fs/promises"; -import library from "../lib/markdownlint.js"; +import library from "../lib/markdownlint.mjs"; const markdownlint = library.promises.markdownlint; const strings = { diff --git a/test/rules/any-blockquote.js b/test/rules/any-blockquote.cjs similarity index 96% rename from test/rules/any-blockquote.js rename to test/rules/any-blockquote.cjs index 0362242a8..f1b16085f 100644 --- a/test/rules/any-blockquote.js +++ b/test/rules/any-blockquote.cjs @@ -2,7 +2,7 @@ "use strict"; -/** @type import("../../lib/markdownlint").Rule[] */ +/** @type {import("../../lib/markdownlint.mjs").Rule[]} */ module.exports = [ // micromark parser (preferred) diff --git a/test/rules/every-n-lines.js b/test/rules/every-n-lines.cjs similarity index 88% rename from test/rules/every-n-lines.js rename to test/rules/every-n-lines.cjs index 337ad5518..5f579f61d 100644 --- a/test/rules/every-n-lines.js +++ b/test/rules/every-n-lines.cjs @@ -2,7 +2,7 @@ "use strict"; -/** @type import("../../lib/markdownlint").Rule */ +/** @type {import("../../lib/markdownlint.mjs").Rule} */ module.exports = { "names": [ "every-n-lines" ], "description": "Rule that reports an error every N lines", diff --git a/test/rules/first-line.js b/test/rules/first-line.cjs similarity index 85% rename from test/rules/first-line.js rename to test/rules/first-line.cjs index e80e2aa64..8b979d16e 100644 --- a/test/rules/first-line.js +++ b/test/rules/first-line.cjs @@ -2,7 +2,7 @@ "use strict"; -/** @type import("../../lib/markdownlint").Rule */ +/** @type {import("../../lib/markdownlint.mjs").Rule} */ module.exports = { "names": [ "first-line" ], "description": "Rule that reports an error for the first line", diff --git a/test/rules/letters-E-X.js b/test/rules/letters-E-X.cjs similarity index 93% rename from test/rules/letters-E-X.js rename to test/rules/letters-E-X.cjs index d6b6b339d..45733d6f4 100644 --- a/test/rules/letters-E-X.js +++ b/test/rules/letters-E-X.cjs @@ -2,7 +2,7 @@ "use strict"; -/** @type import("../../lib/markdownlint").Rule */ +/** @type {import("../../lib/markdownlint.mjs").Rule} */ module.exports = { "names": [ "letters-E-X", "letter-E-letter-X", "contains-ex" ], "description": "Rule that reports an error for lines with the letters 'EX'", diff --git a/test/rules/lint-javascript.js b/test/rules/lint-javascript.cjs similarity index 94% rename from test/rules/lint-javascript.js rename to test/rules/lint-javascript.cjs index 9a10812d7..911c78f7a 100644 --- a/test/rules/lint-javascript.js +++ b/test/rules/lint-javascript.cjs @@ -7,7 +7,7 @@ const eslint = require("eslint"); const linter = new eslint.Linter(); const languageJavaScript = /js|javascript/i; -/** @type import("../../lib/markdownlint").Rule */ +/** @type {import("../../lib/markdownlint.mjs").Rule} */ module.exports = { "names": [ "lint-javascript" ], "description": "Rule that lints JavaScript code", diff --git a/test/rules/npm/sample-rule.js b/test/rules/npm/sample-rule.js index 56681ddd0..f15bd322a 100644 --- a/test/rules/npm/sample-rule.js +++ b/test/rules/npm/sample-rule.js @@ -2,7 +2,7 @@ "use strict"; -/** @type import("../../../lib/markdownlint").Rule */ +/** @type {import("../../../lib/markdownlint.mjs").Rule} */ module.exports = { "names": [ "sample-rule" ], "description": "Sample rule", diff --git a/test/rules/rules.js b/test/rules/rules.cjs similarity index 57% rename from test/rules/rules.js rename to test/rules/rules.cjs index 6b7650d2f..b344b63b7 100644 --- a/test/rules/rules.js +++ b/test/rules/rules.cjs @@ -2,22 +2,22 @@ "use strict"; -const anyBlockquote = require("./any-blockquote"); +const anyBlockquote = require("./any-blockquote.cjs"); module.exports.anyBlockquote = anyBlockquote[1]; -const everyNLines = require("./every-n-lines"); +const everyNLines = require("./every-n-lines.cjs"); module.exports.everyNLines = everyNLines; -const firstLine = require("./first-line"); +const firstLine = require("./first-line.cjs"); module.exports.firstLine = firstLine; -const lettersEX = require("./letters-E-X"); +const lettersEX = require("./letters-E-X.cjs"); module.exports.lettersEX = lettersEX; -const lintJavaScript = require("./lint-javascript"); +const lintJavaScript = require("./lint-javascript.cjs"); module.exports.lintJavaScript = lintJavaScript; -const validateJson = require("./validate-json"); +const validateJson = require("./validate-json.cjs"); module.exports.validateJson = validateJson; module.exports.all = [ diff --git a/test/rules/validate-json.js b/test/rules/validate-json.cjs similarity index 94% rename from test/rules/validate-json.js rename to test/rules/validate-json.cjs index 4a88e1ad6..11c8ed7b2 100644 --- a/test/rules/validate-json.js +++ b/test/rules/validate-json.cjs @@ -4,7 +4,7 @@ const { parse, printParseErrorCode } = require("jsonc-parser"); -/** @type import("../../lib/markdownlint").Rule */ +/** @type {import("../../lib/markdownlint.mjs").Rule} */ module.exports = { "names": [ "validate-json" ], "description": "Rule that validates JSON code", diff --git a/test/snapshots/markdownlint-test-custom-rules.js.md b/test/snapshots/markdownlint-test-custom-rules.mjs.md similarity index 99% rename from test/snapshots/markdownlint-test-custom-rules.js.md rename to test/snapshots/markdownlint-test-custom-rules.mjs.md index 32e2c57c7..abf7e9ea5 100644 --- a/test/snapshots/markdownlint-test-custom-rules.js.md +++ b/test/snapshots/markdownlint-test-custom-rules.mjs.md @@ -1,6 +1,6 @@ -# Snapshot report for `test/markdownlint-test-custom-rules.js` +# Snapshot report for `test/markdownlint-test-custom-rules.mjs` -The actual snapshot is saved in `markdownlint-test-custom-rules.js.snap`. +The actual snapshot is saved in `markdownlint-test-custom-rules.mjs.snap`. Generated by [AVA](https://avajs.dev). diff --git a/test/snapshots/markdownlint-test-custom-rules.js.snap b/test/snapshots/markdownlint-test-custom-rules.mjs.snap similarity index 100% rename from test/snapshots/markdownlint-test-custom-rules.js.snap rename to test/snapshots/markdownlint-test-custom-rules.mjs.snap diff --git a/test/snapshots/markdownlint-test-repos-dotnet-docs.js.md b/test/snapshots/markdownlint-test-repos-dotnet-docs.mjs.md similarity index 98% rename from test/snapshots/markdownlint-test-repos-dotnet-docs.js.md rename to test/snapshots/markdownlint-test-repos-dotnet-docs.mjs.md index 79b115789..98553d4b6 100644 --- a/test/snapshots/markdownlint-test-repos-dotnet-docs.js.md +++ b/test/snapshots/markdownlint-test-repos-dotnet-docs.mjs.md @@ -1,6 +1,6 @@ -# Snapshot report for `test/markdownlint-test-repos-dotnet-docs.js` +# Snapshot report for `test/markdownlint-test-repos-dotnet-docs.mjs` -The actual snapshot is saved in `markdownlint-test-repos-dotnet-docs.js.snap`. +The actual snapshot is saved in `markdownlint-test-repos-dotnet-docs.mjs.snap`. Generated by [AVA](https://avajs.dev). diff --git a/test/snapshots/markdownlint-test-repos-dotnet-docs.js.snap b/test/snapshots/markdownlint-test-repos-dotnet-docs.mjs.snap similarity index 100% rename from test/snapshots/markdownlint-test-repos-dotnet-docs.js.snap rename to test/snapshots/markdownlint-test-repos-dotnet-docs.mjs.snap diff --git a/test/snapshots/markdownlint-test-repos-mdn-content.js.md b/test/snapshots/markdownlint-test-repos-mdn-content.mjs.md similarity index 92% rename from test/snapshots/markdownlint-test-repos-mdn-content.js.md rename to test/snapshots/markdownlint-test-repos-mdn-content.mjs.md index 61c39483d..ce511ed6e 100644 --- a/test/snapshots/markdownlint-test-repos-mdn-content.js.md +++ b/test/snapshots/markdownlint-test-repos-mdn-content.mjs.md @@ -1,6 +1,6 @@ -# Snapshot report for `test/markdownlint-test-repos-mdn-content.js` +# Snapshot report for `test/markdownlint-test-repos-mdn-content.mjs` -The actual snapshot is saved in `markdownlint-test-repos-mdn-content.js.snap`. +The actual snapshot is saved in `markdownlint-test-repos-mdn-content.mjs.snap`. Generated by [AVA](https://avajs.dev). diff --git a/test/snapshots/markdownlint-test-repos-mdn-content.js.snap b/test/snapshots/markdownlint-test-repos-mdn-content.mjs.snap similarity index 100% rename from test/snapshots/markdownlint-test-repos-mdn-content.js.snap rename to test/snapshots/markdownlint-test-repos-mdn-content.mjs.snap diff --git a/test/snapshots/markdownlint-test-repos-small.js.md b/test/snapshots/markdownlint-test-repos-small.mjs.md similarity index 99% rename from test/snapshots/markdownlint-test-repos-small.js.md rename to test/snapshots/markdownlint-test-repos-small.mjs.md index 11feae1bf..d2ec5a21f 100644 --- a/test/snapshots/markdownlint-test-repos-small.js.md +++ b/test/snapshots/markdownlint-test-repos-small.mjs.md @@ -1,6 +1,6 @@ -# Snapshot report for `test/markdownlint-test-repos-small.js` +# Snapshot report for `test/markdownlint-test-repos-small.mjs` -The actual snapshot is saved in `markdownlint-test-repos-small.js.snap`. +The actual snapshot is saved in `markdownlint-test-repos-small.mjs.snap`. Generated by [AVA](https://avajs.dev). diff --git a/test/snapshots/markdownlint-test-repos-small.js.snap b/test/snapshots/markdownlint-test-repos-small.mjs.snap similarity index 100% rename from test/snapshots/markdownlint-test-repos-small.js.snap rename to test/snapshots/markdownlint-test-repos-small.mjs.snap diff --git a/test/snapshots/markdownlint-test-scenarios.js.md b/test/snapshots/markdownlint-test-scenarios.mjs.md similarity index 99% rename from test/snapshots/markdownlint-test-scenarios.js.md rename to test/snapshots/markdownlint-test-scenarios.mjs.md index 6d3649651..bc383b6e3 100644 --- a/test/snapshots/markdownlint-test-scenarios.js.md +++ b/test/snapshots/markdownlint-test-scenarios.mjs.md @@ -1,6 +1,6 @@ -# Snapshot report for `test/markdownlint-test-scenarios.js` +# Snapshot report for `test/markdownlint-test-scenarios.mjs` -The actual snapshot is saved in `markdownlint-test-scenarios.js.snap`. +The actual snapshot is saved in `markdownlint-test-scenarios.mjs.snap`. Generated by [AVA](https://avajs.dev). diff --git a/test/snapshots/markdownlint-test-scenarios.js.snap b/test/snapshots/markdownlint-test-scenarios.mjs.snap similarity index 100% rename from test/snapshots/markdownlint-test-scenarios.js.snap rename to test/snapshots/markdownlint-test-scenarios.mjs.snap