diff --git a/.github/dictionary.txt b/.github/dictionary.txt index bb41cdce..777dfd4a 100644 --- a/.github/dictionary.txt +++ b/.github/dictionary.txt @@ -1,6 +1,8 @@ -async +Async CJS +Changelog CLI +CodeClimate CommonJS CommonMark config @@ -8,6 +10,7 @@ dotfiles formatter formatters Formatters +GitLab Globbing globby Homebrew @@ -15,6 +18,7 @@ JSON JSONC JUnit markdownlint-cli2 +markdownlint-cli2-formatter-codequality markdownlint-cli2-formatter-default markdownlint-cli2-formatter-json markdownlint-cli2-formatter-junit diff --git a/.github/workflows/checkers.yml b/.github/workflows/checkers.yml index 5a33d7ba..783dfd22 100644 --- a/.github/workflows/checkers.yml +++ b/.github/workflows/checkers.yml @@ -3,6 +3,8 @@ name: Checkers on: pull_request: push: + branches-ignore: + - 'dependabot/**' schedule: - cron: '30 12 * * *' workflow_dispatch: @@ -16,7 +18,7 @@ jobs: - uses: JustinBeckwith/linkinator-action@v1.10.4 with: linksToSkip: '^https://github.com/.*/search\?q= ^https://opensource.org/' - paths: '*.md formatter-default/*.md formatter-json/*.md formatter-junit/*.md formatter-pretty/*.md formatter-summarize/*.md' + paths: '*.md doc/*.md formatter-*/*.md' spellcheck: runs-on: ubuntu-latest @@ -25,4 +27,4 @@ jobs: - uses: tbroadley/spellchecker-cli-action@v1 with: dictionaries: '.github/dictionary.txt' - files: '*.md formatter-default/*.md formatter-json/*.md formatter-junit/*.md formatter-pretty/*.md formatter-summarize/*.md' + files: '*.md doc/*.md formatter-*/*.md' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0f4ad306..7f6ad1b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ name: CI on: pull_request: push: + branches-ignore: + - 'dependabot/**' schedule: - cron: '30 12 * * *' workflow_dispatch: @@ -14,11 +16,14 @@ jobs: strategy: fail-fast: false matrix: - os: [macos-latest, ubuntu-latest, windows-latest] - node-version: [14.x, 16.x, 18.x] + os: [ macos-latest, ubuntu-latest, windows-latest ] + node-version: [ 14, 16, 18, 20 ] steps: - uses: actions/checkout@v3 + - name: Edit .npmrc to avoid setup-node issue with Node 14 + if: ${{ matrix.node-version == '14' }} + run: perl -i -p -e 's/(ignore-scripts=true)/# $1/' .npmrc && git add .npmrc - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 842c4f59..d3691d40 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -3,6 +3,8 @@ name: CodeQL on: pull_request: push: + branches-ignore: + - 'dependabot/**' schedule: - cron: '30 12 * * *' workflow_dispatch: diff --git a/.github/workflows/publish-container-image.yml b/.github/workflows/publish-container-image.yml index 0da6c9ea..f01b45c4 100644 --- a/.github/workflows/publish-container-image.yml +++ b/.github/workflows/publish-container-image.yml @@ -36,7 +36,7 @@ jobs: images: ${{ github.repository }} - name: Build container image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . file: docker/Dockerfile @@ -48,7 +48,7 @@ jobs: run: docker run --rm -v $PWD:/workdir local:test "*.md" - name: Push container image - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: context: . file: docker/Dockerfile @@ -56,3 +56,21 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} push: true + + - name: Extract tags and labels for -rules + id: meta-rules + uses: docker/metadata-action@v4 + with: + images: ${{ github.repository }}-rules + + - name: Build and push container image for -rules + uses: docker/build-push-action@v4 + with: + context: . + file: docker/Dockerfile-rules + platforms: linux/arm64,linux/amd64 + tags: ${{ steps.meta-rules.outputs.tags }} + labels: ${{ steps.meta-rules.outputs.labels }} + build-args: | + VERSION=${{ steps.meta.outputs.version }} + push: true diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 1ef6ff45..f82842c4 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -40,3 +40,24 @@ language: docker_image types: [markdown] minimum_pre_commit_version: 0.15.0 +- id: markdownlint-cli2-rules-docker + name: markdownlint-cli2-rules-docker + description: "Checks the style of Markdown/CommonMark files." + entry: davidanson/markdownlint-cli2-rules + language: docker_image + types: [markdown] + minimum_pre_commit_version: 0.15.0 +- id: markdownlint-cli2-config-rules-docker + name: markdownlint-cli2-config-rules-docker + description: "Checks the style of Markdown/CommonMark files with a non-root configuration." + entry: davidanson/markdownlint-cli2-rules markdownlint-cli2-config + language: docker_image + types: [markdown] + minimum_pre_commit_version: 0.15.0 +- id: markdownlint-cli2-fix-rules-docker + name: markdownlint-cli2-fix-rules-docker + description: "Checks and fixes the style of Markdown/CommonMark files." + entry: davidanson/markdownlint-cli2-rules markdownlint-cli2-fix + language: docker_image + types: [markdown] + minimum_pre_commit_version: 0.15.0 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..85849239 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,120 @@ +# Changelog + +## 0.7.0 + +- Add support for `extends` in `config` property of `.markdownlint-cli2.*` files +- Build and publish `davidanson/markdownlint-cli2-rules` Docker container image +- Update dependencies (including `markdownlint`) + +## 0.6.0 + +- Update dependencies (including `markdownlint`) + +## 0.5.1 + +- Update dependencies + +## 0.5.0 + +- New rules +- Support modules (MJS) everywhere +- Include dotfiles + +## 0.4.0 + +- New rules +- Async custom rules +- Explicit config +- CJS (breaking) + +## 0.3.2 + +- Extensibility/Windows/consistency improvements + +## 0.3.1 + +- Extensibility tweaks + +## 0.3.0 + +- Add Docker container +- Update dependencies + +## 0.2.0 + +- Improve handling of Windows paths using backslash + +## 0.1.3 + +- Support rule collections + +## 0.1.2 + +- Update use of `require` to be more flexible + +## 0.1.1 + +- Restore previous use of `require` + +## 0.1.0 + +- Simplify use of `require` +- Increment minor version + +## 0.0.15 + +- Improve extensibility + +## 0.0.14 + +- Update dependencies (including `markdownlint`) + +## 0.0.13 + +- Add `markdownlint-cli2-fix` command + +## 0.0.12 + +- Update dependencies (including `markdownlint`) + +## 0.0.11 + +- Improve performance of `fix` +- Update banner + +## 0.0.10 + +- Improve performance and configuration + +## 0.0.9 + +- Improve configuration file handling + +## 0.0.8 + +- Support `.markdownlint-cli2.yaml` +- Add progress + +## 0.0.7 + +- Support `.markdownlint-cli2.js` and `.markdownlint.js` + +## 0.0.6 + +- Improve handling of very large directory trees + +## 0.0.5 + +- Improve support for ignoring files + +## 0.0.4 + +- Support output formatters and `markdown-it` plugins + +## 0.0.3 + +- Feature parity with `markdownlint-cli` + +## 0.0.2 + +- Initial release diff --git a/LICENSE b/LICENSE index 18caa9a6..75c778e5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 David Anson +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 diff --git a/README.md b/README.md index 311de50a..0f25920e 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ As a [GitHub Action][github-action] via ```yaml - name: markdownlint-cli2-action - uses: DavidAnson/markdownlint-cli2-action + uses: DavidAnson/markdownlint-cli2-action@v9 ``` ## Overview @@ -145,7 +145,7 @@ A container image [`davidanson/markdownlint-cli2`][docker-hub-markdownlint-cli2] can also be used (e.g., as part of a CI pipeline): ```bash -docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.6.0 "**/*.md" "#node_modules" +docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.7.0 "**/*.md" "#node_modules" ``` Notes: @@ -162,16 +162,25 @@ Notes: - A custom working directory can be specified with Docker's `-w` flag: ```bash - docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.6.0 "**/*.md" "#node_modules" + docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.7.0 "**/*.md" "#node_modules" ``` To invoke the `markdownlint-cli2-config` or `markdownlint-cli2-fix` commands instead, use Docker's `--entrypoint` flag: ```bash -docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:v0.6.0 "**/*.md" "#node_modules" +docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:v0.7.0 "**/*.md" "#node_modules" ``` +For convenience, the container image +[`davidanson/markdownlint-cli2-rules`][docker-hub-markdownlint-cli2-rules] +includes the latest versions of custom rules published to npm with the tag +[`markdownlint-rule`][markdownlint-rule]. These rules are installed globally +onto the base image `davidanson/markdownlint-cli2`. + +**Note**: This container image exists for convenience and is not an endorsement +of the rules within. + ### Exit Codes - `0`: Linting was successful and there were no errors @@ -193,11 +202,20 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark - See the [Configuration][markdownlint-configuration] section of the `markdownlint` documentation for information about the inline comment syntax for enabling and disabling rules with HTML comments. -- In general, glob expressions match files under the current directory and the - configuration for that directory applies to the entire tree. +- In general, glob expressions should match files under the current directory; + the configuration for that directory will apply to the entire tree. - When glob expressions match files *not* under the current directory, configuration for the current directory is applied to the closest common parent directory. +- There are two kinds of configuration file (both detailed below): + - Configuration files like `.markdownlint-cli2.*` allow complete control of + `markdownlint-cli2` behavior and are also used by `vscode-markdownlint`. + - Configuration files like `.markdownlint.*` allow control over only the + `markdownlint` `config` object and tend to be supported more broadly (such + as by `markdownlint-cli`). +- The VS Code extension `vscode-markdownlint` includes a schema definition for + the `JSON(C)` configuration files described below. This adds auto-complete and + can make it easier to define proper structure. ### `.markdownlint-cli2.jsonc` @@ -208,6 +226,8 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark rules for this part of the directory tree - If a `.markdownlint.{jsonc,json,yaml,yml,js}` file (see below) is present in the same directory, it overrides the value of this property + - If the `config` object contains an `extends` property, it will be resolved + the same as `.markdownlint.{jsonc,json,yaml,yml,js}` (see below) - `customRules`: `Array` of `String`s (or `Array`s of `String`s) of module names/paths of [custom rules][markdownlint-custom-rules] to load and use when linting @@ -358,7 +378,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like: ```yaml - repo: https://github.com/DavidAnson/markdownlint-cli2 - rev: v0.6.0 + rev: v0.7.0 hooks: - id: markdownlint-cli2 ``` @@ -368,32 +388,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like: ## History -- 0.0.2 - Initial release -- 0.0.3 - Feature parity with `markdownlint-cli` -- 0.0.4 - Support output formatters and `markdown-it` plugins -- 0.0.5 - Improve support for ignoring files -- 0.0.6 - Improve handling of very large directory trees -- 0.0.7 - Support `.markdownlint-cli2.js` and `.markdownlint.js` -- 0.0.8 - Support `.markdownlint-cli2.yaml`, add progress -- 0.0.9 - Improve configuration file handling -- 0.0.10 - Improve performance and configuration -- 0.0.11 - Improve performance of `fix`, update banner -- 0.0.12 - Update dependencies (including `markdownlint`) -- 0.0.13 - Add `markdownlint-cli2-fix` command -- 0.0.14 - Update dependencies (including `markdownlint`) -- 0.0.15 - Improve extensibility -- 0.1.0 - Simplify use of `require`, increment minor version - - 0.1.1 - Restore previous use of `require` - - 0.1.2 - Update use of `require` to be more flexible - - 0.1.3 - Support rule collections -- 0.2.0 - Improve handling of Windows paths using backslash -- 0.3.0 - Add Docker container, update dependencies - - 0.3.1 - Extensibility tweaks - - 0.3.2 - Extensibility/Windows/consistency improvements -- 0.4.0 - New rules, async custom rules, explicit config, CJS (breaking) -- 0.5.0 - New rules, support modules (MJS) everywhere, include dotfiles - - 0.5.1 - Update dependencies -- 0.6.0 - Update dependencies (including `markdownlint`) +See [CHANGELOG.md](CHANGELOG.md). @@ -403,6 +398,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like: [docker]: https://www.docker.com [docker-bind-mounts]: https://docs.docker.com/storage/bind-mounts/ [docker-hub-markdownlint-cli2]: https://hub.docker.com/r/davidanson/markdownlint-cli2 +[docker-hub-markdownlint-cli2-rules]: https://hub.docker.com/r/davidanson/markdownlint-cli2-rules [front-matter]: https://jekyllrb.com/docs/frontmatter/ [github-action]: https://docs.github.com/actions [globby]: https://www.npmjs.com/package/globby diff --git a/doc/OutputFormatters.md b/doc/OutputFormatters.md index d63537ce..2acd8f97 100644 --- a/doc/OutputFormatters.md +++ b/doc/OutputFormatters.md @@ -20,8 +20,8 @@ module.exports = (options, params) => { ... } Where `options` is an object that looks like: -- `results`: `Array` of [`markdownlint` `LintError` objects][markdownlint-d-ts] - - [Example `results` object][output-formatters-json] +- `results`: `Array` of [`markdownlint` `LintError` objects][markdownlint-d-ts], + each with an added `String` property `fileName` containing a relative path - `logMessage`: `Function` that takes a single `String` argument and logs it to standard output - `logError`: `Function` that takes a single `String` argument and logs it to @@ -62,4 +62,3 @@ For a `.markdownlint-cli2.jsonc` like: [formatter-junit]: ../formatter-junit/markdownlint-cli2-formatter-junit.js [markdownlint-cli2-formatter]: https://www.npmjs.com/search?q=keywords:markdownlint-cli2-formatter [markdownlint-d-ts]: https://github.com/DavidAnson/markdownlint/blob/main/lib/markdownlint.d.ts -[output-formatters-json]: ../test/outputFormatters.formatter.json diff --git a/docker/Dockerfile-rules b/docker/Dockerfile-rules new file mode 100644 index 00000000..e8a33bad --- /dev/null +++ b/docker/Dockerfile-rules @@ -0,0 +1,23 @@ +ARG VERSION +FROM davidanson/markdownlint-cli2:${VERSION} + +USER root + +RUN npm install --global --no-package-lock --production \ + @github/markdownlint-github \ + markdownlint-rule-enhanced-proper-names \ + markdownlint-rule-github-admonition \ + markdownlint-rule-github-internal-links \ + markdownlint-rule-header-id \ + markdownlint-rule-list-duplicates \ + markdownlint-rule-max-one-sentence-per-line \ + markdownlint-rule-no-trailing-slash-in-links \ + markdownlint-rule-olstart \ + markdownlint-rule-relative-links \ + markdownlint-rule-search-replace \ + markdownlint-rule-titlecase \ + markdownlint-rule-trace-template-headers \ + markdownlint-rules-foliant \ + markdownlint-rules-grav-pages + +USER node diff --git a/export-markdownlint-helpers.js b/export-markdownlint-helpers.js new file mode 100644 index 00000000..44cfe31a --- /dev/null +++ b/export-markdownlint-helpers.js @@ -0,0 +1,5 @@ +// @ts-check + +"use strict"; + +module.exports = require("markdownlint/helpers"); diff --git a/export-markdownlint.js b/export-markdownlint.js new file mode 100644 index 00000000..b3f98eb0 --- /dev/null +++ b/export-markdownlint.js @@ -0,0 +1,5 @@ +// @ts-check + +"use strict"; + +module.exports = require("markdownlint"); diff --git a/formatter-codequality/LICENSE b/formatter-codequality/LICENSE index 18caa9a6..75c778e5 100644 --- a/formatter-codequality/LICENSE +++ b/formatter-codequality/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 David Anson +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 diff --git a/formatter-codequality/README.md b/formatter-codequality/README.md index b54947bc..5588f353 100644 --- a/formatter-codequality/README.md +++ b/formatter-codequality/README.md @@ -15,7 +15,8 @@ npm install markdownlint-cli2-formatter-codequality --save-dev ## Use -Use the following `.markdownlint-cli2.jsonc`: +For the default output file name of `"markdownlint-cli2-codequality.json"`, use +the following `.markdownlint-cli2.jsonc`: ```json { @@ -25,6 +26,16 @@ Use the following `.markdownlint-cli2.jsonc`: } ``` +To customize the output file name, use the following `.markdownlint-cli2.jsonc`: + +```json +{ + "outputFormatters": [ + [ "markdownlint-cli2-formatter-codequality", { "name": "custom-name.json" } ] + ] +} +``` + ## Use in GitLab CI ```yaml diff --git a/formatter-codequality/markdownlint-cli2-formatter-codequality.js b/formatter-codequality/markdownlint-cli2-formatter-codequality.js index 3ac3b7dc..32c1a2f2 100644 --- a/formatter-codequality/markdownlint-cli2-formatter-codequality.js +++ b/formatter-codequality/markdownlint-cli2-formatter-codequality.js @@ -19,8 +19,9 @@ const createFingerprint = function createFingerprint (violation) { // Writes markdownlint-cli2 results to a GitLab Code Quality report JSON file. // eslint-disable-next-line max-len // See: https://docs.gitlab.com/ee/ci/testing/code_quality.html#implementing-a-custom-tool -const outputFormatter = (options) => { +const outputFormatter = (options, params) => { const { directory, results } = options; + const { name } = (params || {}); const issues = []; for (const errorInfo of results) { @@ -62,7 +63,7 @@ const outputFormatter = (options) => { path.resolve( // eslint-disable-next-line no-inline-comments directory /* c8 ignore next */ || "", - "markdownlint-cli2-codequality.json" + name || "markdownlint-cli2-codequality.json" ), content, "utf8" diff --git a/formatter-codequality/package.json b/formatter-codequality/package.json index ca594164..c4540575 100644 --- a/formatter-codequality/package.json +++ b/formatter-codequality/package.json @@ -1,6 +1,6 @@ { "name": "markdownlint-cli2-formatter-codequality", - "version": "0.0.2", + "version": "0.0.4", "description": "An output formatter for markdownlint-cli2 that writes results to a GitLab Code Quality report artifact JSON file", "author": { "name": "Matthias Schoettle", diff --git a/formatter-default/LICENSE b/formatter-default/LICENSE index 18caa9a6..75c778e5 100644 --- a/formatter-default/LICENSE +++ b/formatter-default/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 David Anson +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 diff --git a/formatter-default/package.json b/formatter-default/package.json index 33c9dadf..df692c58 100644 --- a/formatter-default/package.json +++ b/formatter-default/package.json @@ -1,6 +1,6 @@ { "name": "markdownlint-cli2-formatter-default", - "version": "0.0.3", + "version": "0.0.4", "description": "An output formatter for markdownlint-cli2 that produces the same output as markdownlint-cli", "author": { "name": "David Anson", diff --git a/formatter-json/LICENSE b/formatter-json/LICENSE index 18caa9a6..75c778e5 100644 --- a/formatter-json/LICENSE +++ b/formatter-json/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 David Anson +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 diff --git a/formatter-json/package.json b/formatter-json/package.json index f93db4be..c9da723f 100644 --- a/formatter-json/package.json +++ b/formatter-json/package.json @@ -1,6 +1,6 @@ { "name": "markdownlint-cli2-formatter-json", - "version": "0.0.6", + "version": "0.0.7", "description": "An output formatter for markdownlint-cli2 that writes results to a file in JSON format", "author": { "name": "David Anson", diff --git a/formatter-junit/LICENSE b/formatter-junit/LICENSE index 18caa9a6..75c778e5 100644 --- a/formatter-junit/LICENSE +++ b/formatter-junit/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 David Anson +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 diff --git a/formatter-junit/markdownlint-cli2-formatter-junit.js b/formatter-junit/markdownlint-cli2-formatter-junit.js index 9beb651c..98700b46 100644 --- a/formatter-junit/markdownlint-cli2-formatter-junit.js +++ b/formatter-junit/markdownlint-cli2-formatter-junit.js @@ -12,10 +12,11 @@ const outputFormatter = (options, params) => { const { name } = (params || {}); // Get a new builder instance because the default builder is shared const builder = junitReportBuilder.newBuilder(); + const outputFormatterName = path.basename(__filename).replace(/\.js$/u, ""); const suite = builder. testSuite(). - name(path.basename(__filename).replace(/\.js$/u, "")). + name(outputFormatterName). time(0); for (const errorInfo of results) { const { fileName, lineNumber, ruleNames, ruleDescription, errorDetail, @@ -38,6 +39,7 @@ const outputFormatter = (options, params) => { if (results.length === 0) { suite. testCase(). + name(outputFormatterName). time(0); } const content = builder.build(); diff --git a/formatter-junit/package.json b/formatter-junit/package.json index a40590ad..8f04e27d 100644 --- a/formatter-junit/package.json +++ b/formatter-junit/package.json @@ -1,6 +1,6 @@ { "name": "markdownlint-cli2-formatter-junit", - "version": "0.0.5", + "version": "0.0.6", "description": "An output formatter for markdownlint-cli2 that writes results to a file in JUnit XML format", "author": { "name": "David Anson", diff --git a/formatter-pretty/LICENSE b/formatter-pretty/LICENSE index 18caa9a6..75c778e5 100644 --- a/formatter-pretty/LICENSE +++ b/formatter-pretty/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 David Anson +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 diff --git a/formatter-pretty/package.json b/formatter-pretty/package.json index 225ef186..f3f88e24 100644 --- a/formatter-pretty/package.json +++ b/formatter-pretty/package.json @@ -1,6 +1,6 @@ { "name": "markdownlint-cli2-formatter-pretty", - "version": "0.0.3", + "version": "0.0.4", "description": "An output formatter for markdownlint-cli2 that looks like markdownlint-cli2-formatter-default with color and clickable links", "author": { "name": "David Anson", diff --git a/formatter-summarize/LICENSE b/formatter-summarize/LICENSE index 18caa9a6..75c778e5 100644 --- a/formatter-summarize/LICENSE +++ b/formatter-summarize/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020-2022 David Anson +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 diff --git a/formatter-summarize/package.json b/formatter-summarize/package.json index 91ada788..0a30537b 100644 --- a/formatter-summarize/package.json +++ b/formatter-summarize/package.json @@ -1,6 +1,6 @@ { "name": "markdownlint-cli2-formatter-summarize", - "version": "0.0.5", + "version": "0.0.6", "description": "An output formatter for markdownlint-cli2 that summarizes the results", "author": { "name": "David Anson", diff --git a/markdownlint-cli2.js b/markdownlint-cli2.js index ee2dc807..d82426e7 100755 --- a/markdownlint-cli2.js +++ b/markdownlint-cli2.js @@ -13,8 +13,11 @@ const dynamicRequire = (typeof __non_webpack_require__ === "undefined") ? requir const path = require("node:path"); const { pathToFileURL } = require("node:url"); const markdownlintLibrary = require("markdownlint"); -const { markdownlint, "readConfig": markdownlintReadConfig } = - markdownlintLibrary.promises; +const { + markdownlint, + "extendConfig": markdownlintExtendConfig, + "readConfig": markdownlintReadConfig +} = markdownlintLibrary.promises; const markdownlintRuleHelpers = require("markdownlint/helpers"); const appendToArray = require("./append-to-array"); const mergeOptions = require("./merge-options"); @@ -22,7 +25,7 @@ const resolveAndRequire = require("./resolve-and-require"); // Variables const packageName = "markdownlint-cli2"; -const packageVersion = "0.6.0"; +const packageVersion = "0.7.0"; const libraryName = "markdownlint"; const libraryVersion = markdownlintLibrary.getVersion(); const dotOnlySubstitute = "*.{md,markdown}"; @@ -242,105 +245,121 @@ $ markdownlint-cli2 "**/*.md" "#node_modules"` // Get (creating if necessary) and process a directory's info object const getAndProcessDirInfo = -(fs, tasks, dirToDirInfo, dir, relativeDir, noRequire, func) => { - let dirInfo = dirToDirInfo[dir]; - if (!dirInfo) { - dirInfo = { - dir, - relativeDir, - "parent": null, - "files": [], - "markdownlintConfig": null, - "markdownlintOptions": null - }; - dirToDirInfo[dir] = dirInfo; - - // Load markdownlint-cli2 object(s) - const markdownlintCli2Jsonc = - path.posix.join(dir, ".markdownlint-cli2.jsonc"); - const markdownlintCli2Yaml = - path.posix.join(dir, ".markdownlint-cli2.yaml"); - tasks.push( - fs.promises.access(markdownlintCli2Jsonc). - then( - () => fs.promises. - readFile(markdownlintCli2Jsonc, utf8). - then( - (content) => getJsoncParse(). - then((jsoncParse) => jsoncParse(content)) - ), - () => fs.promises.access(markdownlintCli2Yaml). - then( - () => fs.promises. - readFile(markdownlintCli2Yaml, utf8). - then(yamlParse), - importOrRequireConfig( - fs, - dir, - ".markdownlint-cli2.cjs", - noRequire, + (fs, tasks, dirToDirInfo, dir, relativeDir, noRequire, func) => { + let dirInfo = dirToDirInfo[dir]; + if (!dirInfo) { + dirInfo = { + dir, + relativeDir, + "parent": null, + "files": [], + "markdownlintConfig": null, + "markdownlintOptions": null + }; + dirToDirInfo[dir] = dirInfo; + + // Load markdownlint-cli2 object(s) + const markdownlintCli2Jsonc = + path.posix.join(dir, ".markdownlint-cli2.jsonc"); + const markdownlintCli2Yaml = + path.posix.join(dir, ".markdownlint-cli2.yaml"); + tasks.push( + fs.promises.access(markdownlintCli2Jsonc). + then( + () => fs.promises. + readFile(markdownlintCli2Jsonc, utf8). + then( + (content) => getJsoncParse(). + then((jsoncParse) => jsoncParse(content)) + ), + () => fs.promises.access(markdownlintCli2Yaml). + then( + () => fs.promises. + readFile(markdownlintCli2Yaml, utf8). + then(yamlParse), importOrRequireConfig( fs, dir, - ".markdownlint-cli2.mjs", + ".markdownlint-cli2.cjs", noRequire, - noop + importOrRequireConfig( + fs, + dir, + ".markdownlint-cli2.mjs", + noRequire, + noop + ) ) ) - ) - ). - then((options) => { - dirInfo.markdownlintOptions = options; - }) - ); + ). + then((options) => { + dirInfo.markdownlintOptions = options; + return options && + options.config && + options.config.extends && + getJsoncParse(). + then( + (jsoncParse) => markdownlintExtendConfig( + options.config, + // Just needs to identify a file in the right directory + markdownlintCli2Jsonc, + [ jsoncParse, yamlParse ], + fs + ) + ). + then((config) => { + options.config = config; + }); + }) + ); - // Load markdownlint object(s) - const readConfigs = - readConfig( - fs, - dir, - ".markdownlint.jsonc", + // Load markdownlint object(s) + const readConfigs = readConfig( fs, dir, - ".markdownlint.json", + ".markdownlint.jsonc", readConfig( fs, dir, - ".markdownlint.yaml", + ".markdownlint.json", readConfig( fs, dir, - ".markdownlint.yml", - importOrRequireConfig( + ".markdownlint.yaml", + readConfig( fs, dir, - ".markdownlint.cjs", - noRequire, + ".markdownlint.yml", importOrRequireConfig( fs, dir, - ".markdownlint.mjs", + ".markdownlint.cjs", noRequire, - noop + importOrRequireConfig( + fs, + dir, + ".markdownlint.mjs", + noRequire, + noop + ) ) ) ) ) - ) + ); + tasks.push( + readConfigs(). + then((config) => { + dirInfo.markdownlintConfig = config; + }) ); - tasks.push( - readConfigs(). - then((config) => { - dirInfo.markdownlintConfig = config; - }) - ); - } - if (func) { - func(dirInfo); - } - return dirInfo; -}; + } + if (func) { + func(dirInfo); + } + return dirInfo; + }; // Get base markdownlint-cli2 options object const getBaseOptions = async ( @@ -367,7 +386,10 @@ const getBaseOptions = async ( // eslint-disable-next-line no-multi-assign const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions = mergeOptions( - mergeOptions(options, { "fix": fixDefault }), + mergeOptions( + { "fix": fixDefault }, + options + ), dirToDirInfo[baseDir].markdownlintOptions ); @@ -391,81 +413,81 @@ const getBaseOptions = async ( // Enumerate files from globs and build directory infos const enumerateFiles = -// eslint-disable-next-line max-len -async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => { - const tasks = []; - const globbyOptions = { - "absolute": true, - "cwd": baseDir, - "dot": true, - "expandDirectories": false, - fs - }; - if (noErrors) { - globbyOptions.suppressErrors = true; - } - // Special-case literal files - const literalFiles = []; - const filteredGlobPatterns = globPatterns.filter( - (globPattern) => { - if (globPattern.startsWith(":")) { - literalFiles.push( - posixPath(path.resolve(baseDirSystem, globPattern.slice(1))) - ); - return false; - } - return true; + // eslint-disable-next-line max-len + async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => { + const tasks = []; + const globbyOptions = { + "absolute": true, + "cwd": baseDir, + "dot": true, + "expandDirectories": false, + fs + }; + if (noErrors) { + globbyOptions.suppressErrors = true; } - ).map((globPattern) => globPattern.replace(/^\\:/u, ":")); - const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions; - const globsForIgnore = - (baseMarkdownlintOptions.globs || []). - filter((glob) => glob.startsWith("!")); - const filteredLiteralFiles = - ((literalFiles.length > 0) && (globsForIgnore.length > 0)) - ? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore) - : literalFiles; - // Manually expand directories to avoid globby call to dir-glob.sync - const expandedDirectories = await Promise.all( - filteredGlobPatterns.map((globPattern) => { - const barePattern = - globPattern.startsWith("!") - ? globPattern.slice(1) - : globPattern; - const globPath = - (path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern)) - ? barePattern - : path.posix.join(baseDir, barePattern); - return fs.promises.stat(globPath). - then((stats) => (stats.isDirectory() - ? path.posix.join(globPattern, "**") - : globPattern)). - catch(() => globPattern); - }) - ); - // Process glob patterns - // eslint-disable-next-line no-inline-comments - const { globby } = await import(/* webpackMode: "eager" */ "globby"); - const files = [ - ...await globby(expandedDirectories, globbyOptions), - ...filteredLiteralFiles - ]; - for (const file of files) { - const dir = path.posix.dirname(file); - getAndProcessDirInfo( - fs, - tasks, - dirToDirInfo, - dir, - null, - noRequire, - (dirInfo) => { - dirInfo.files.push(file); + // Special-case literal files + const literalFiles = []; + const filteredGlobPatterns = globPatterns.filter( + (globPattern) => { + if (globPattern.startsWith(":")) { + literalFiles.push( + posixPath(path.resolve(baseDirSystem, globPattern.slice(1))) + ); + return false; + } + return true; } + ).map((globPattern) => globPattern.replace(/^\\:/u, ":")); + const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions; + const globsForIgnore = + (baseMarkdownlintOptions.globs || []). + filter((glob) => glob.startsWith("!")); + const filteredLiteralFiles = + ((literalFiles.length > 0) && (globsForIgnore.length > 0)) + ? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore) + : literalFiles; + // Manually expand directories to avoid globby call to dir-glob.sync + const expandedDirectories = await Promise.all( + filteredGlobPatterns.map((globPattern) => { + const barePattern = + globPattern.startsWith("!") + ? globPattern.slice(1) + : globPattern; + const globPath = + (path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern)) + ? barePattern + : path.posix.join(baseDir, barePattern); + return fs.promises.stat(globPath). + then((stats) => (stats.isDirectory() + ? path.posix.join(globPattern, "**") + : globPattern)). + catch(() => globPattern); + }) ); - } - await Promise.all(tasks); -}; + // Process glob patterns + // eslint-disable-next-line no-inline-comments + const { globby } = await import(/* webpackMode: "eager" */ "globby"); + const files = [ + ...await globby(expandedDirectories, globbyOptions), + ...filteredLiteralFiles + ]; + for (const file of files) { + const dir = path.posix.dirname(file); + getAndProcessDirInfo( + fs, + tasks, + dirToDirInfo, + dir, + null, + noRequire, + (dirInfo) => { + dirInfo.files.push(file); + } + ); + } + await Promise.all(tasks); + }; // Enumerate (possibly missing) parent directories and update directory infos const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => { @@ -514,135 +536,135 @@ const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => { // Create directory info objects by enumerating file globs const createDirInfos = -// eslint-disable-next-line max-len -async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => { - await enumerateFiles( - fs, - baseDirSystem, - baseDir, - globPatterns, - dirToDirInfo, - noErrors, - noRequire - ); - await enumerateParents( - fs, - baseDir, - dirToDirInfo, - noRequire - ); - - // Merge file lists with identical configuration - const dirs = Object.keys(dirToDirInfo); - dirs.sort((a, b) => b.length - a.length); - const dirInfos = []; - const noConfigDirInfo = - // eslint-disable-next-line unicorn/consistent-function-scoping - (dirInfo) => ( - dirInfo.parent && - !dirInfo.markdownlintConfig && - !dirInfo.markdownlintOptions + // eslint-disable-next-line max-len + async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => { + await enumerateFiles( + fs, + baseDirSystem, + baseDir, + globPatterns, + dirToDirInfo, + noErrors, + noRequire ); - const tasks = []; - for (const dir of dirs) { - const dirInfo = dirToDirInfo[dir]; - if (noConfigDirInfo(dirInfo)) { - if (dirInfo.parent) { - appendToArray(dirInfo.parent.files, dirInfo.files); - } - dirToDirInfo[dir] = null; - } else { - const { markdownlintOptions, relativeDir } = dirInfo; - if (markdownlintOptions && markdownlintOptions.customRules) { - tasks.push( - importOrRequireIds( - relativeDir || dir, - markdownlintOptions.customRules, - noRequire - ).then((customRules) => { - // Expand nested arrays (for packages that export multiple rules) - markdownlintOptions.customRules = customRules.flat(); - }) - ); - } - if (markdownlintOptions && markdownlintOptions.markdownItPlugins) { - tasks.push( - importOrRequireIdsAndParams( - relativeDir || dir, - markdownlintOptions.markdownItPlugins, - noRequire - ).then((markdownItPlugins) => { - markdownlintOptions.markdownItPlugins = markdownItPlugins; - }) - ); + await enumerateParents( + fs, + baseDir, + dirToDirInfo, + noRequire + ); + + // Merge file lists with identical configuration + const dirs = Object.keys(dirToDirInfo); + dirs.sort((a, b) => b.length - a.length); + const dirInfos = []; + const noConfigDirInfo = + // eslint-disable-next-line unicorn/consistent-function-scoping + (dirInfo) => ( + dirInfo.parent && + !dirInfo.markdownlintConfig && + !dirInfo.markdownlintOptions + ); + const tasks = []; + for (const dir of dirs) { + const dirInfo = dirToDirInfo[dir]; + if (noConfigDirInfo(dirInfo)) { + if (dirInfo.parent) { + appendToArray(dirInfo.parent.files, dirInfo.files); + } + dirToDirInfo[dir] = null; + } else { + const { markdownlintOptions, relativeDir } = dirInfo; + if (markdownlintOptions && markdownlintOptions.customRules) { + tasks.push( + importOrRequireIds( + relativeDir || dir, + markdownlintOptions.customRules, + noRequire + ).then((customRules) => { + // Expand nested arrays (for packages that export multiple rules) + markdownlintOptions.customRules = customRules.flat(); + }) + ); + } + if (markdownlintOptions && markdownlintOptions.markdownItPlugins) { + tasks.push( + importOrRequireIdsAndParams( + relativeDir || dir, + markdownlintOptions.markdownItPlugins, + noRequire + ).then((markdownItPlugins) => { + markdownlintOptions.markdownItPlugins = markdownItPlugins; + }) + ); + } + dirInfos.push(dirInfo); } - dirInfos.push(dirInfo); } - } - await Promise.all(tasks); - for (const dirInfo of dirInfos) { - while (dirInfo.parent && !dirToDirInfo[dirInfo.parent.dir]) { - dirInfo.parent = dirInfo.parent.parent; + await Promise.all(tasks); + for (const dirInfo of dirInfos) { + while (dirInfo.parent && !dirToDirInfo[dirInfo.parent.dir]) { + dirInfo.parent = dirInfo.parent.parent; + } } - } - // Verify dirInfos is simplified - // if ( - // dirInfos.filter( - // (di) => di.parent && !dirInfos.includes(di.parent) - // ).length > 0 - // ) { - // throw new Error("Extra parent"); - // } - // if ( - // dirInfos.filter( - // (di) => !di.parent && (di.dir !== baseDir) - // ).length > 0 - // ) { - // throw new Error("Missing parent"); - // } - // if ( - // dirInfos.filter( - // (di) => di.parent && - // !((di.markdownlintConfig ? 1 : 0) ^ (di.markdownlintOptions ? 1 : 0)) - // ).length > 0 - // ) { - // throw new Error("Missing object"); - // } - // if (dirInfos.filter((di) => di.dir === "/").length > 0) { - // throw new Error("Includes root"); - // } - - // Merge configuration by inheritance - for (const dirInfo of dirInfos) { - let markdownlintOptions = dirInfo.markdownlintOptions || {}; - let { markdownlintConfig } = dirInfo; - let parent = dirInfo; - // eslint-disable-next-line prefer-destructuring - while ((parent = parent.parent)) { - if (parent.markdownlintOptions) { - markdownlintOptions = mergeOptions( - parent.markdownlintOptions, - markdownlintOptions - ); - } - if ( - !markdownlintConfig && - parent.markdownlintConfig && - !markdownlintOptions.config - ) { - // eslint-disable-next-line prefer-destructuring - markdownlintConfig = parent.markdownlintConfig; + // Verify dirInfos is simplified + // if ( + // dirInfos.filter( + // (di) => di.parent && !dirInfos.includes(di.parent) + // ).length > 0 + // ) { + // throw new Error("Extra parent"); + // } + // if ( + // dirInfos.filter( + // (di) => !di.parent && (di.dir !== baseDir) + // ).length > 0 + // ) { + // throw new Error("Missing parent"); + // } + // if ( + // dirInfos.filter( + // (di) => di.parent && + // !((di.markdownlintConfig ? 1 : 0) ^ (di.markdownlintOptions ? 1 : 0)) + // ).length > 0 + // ) { + // throw new Error("Missing object"); + // } + // if (dirInfos.filter((di) => di.dir === "/").length > 0) { + // throw new Error("Includes root"); + // } + + // Merge configuration by inheritance + for (const dirInfo of dirInfos) { + let markdownlintOptions = dirInfo.markdownlintOptions || {}; + let { markdownlintConfig } = dirInfo; + let parent = dirInfo; + // eslint-disable-next-line prefer-destructuring + while ((parent = parent.parent)) { + if (parent.markdownlintOptions) { + markdownlintOptions = mergeOptions( + parent.markdownlintOptions, + markdownlintOptions + ); + } + if ( + !markdownlintConfig && + parent.markdownlintConfig && + !markdownlintOptions.config + ) { + // eslint-disable-next-line prefer-destructuring + markdownlintConfig = parent.markdownlintConfig; + } } + dirInfo.markdownlintOptions = mergeOptions( + markdownlintOptions, + optionsOverride + ); + dirInfo.markdownlintConfig = markdownlintConfig; } - dirInfo.markdownlintOptions = mergeOptions( - markdownlintOptions, - optionsOverride - ); - dirInfo.markdownlintConfig = markdownlintConfig; - } - return dirInfos; -}; + return dirInfos; + }; // Lint files in groups by shared configuration const lintFiles = async (fs, dirInfos, fileContents) => { diff --git a/package.json b/package.json index d8b155bc..ee1bd3e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "markdownlint-cli2", - "version": "0.6.0", + "version": "0.7.0", "description": "A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the `markdownlint` library", "author": { "name": "David Anson", @@ -9,7 +9,11 @@ "license": "MIT", "type": "commonjs", "main": "./markdownlint-cli2.js", - "exports": "./markdownlint-cli2.js", + "exports": { + ".": "./markdownlint-cli2.js", + "./markdownlint": "./export-markdownlint.js", + "./markdownlint/helpers": "./export-markdownlint-helpers.js" + }, "bin": { "markdownlint-cli2": "markdownlint-cli2.js", "markdownlint-cli2-config": "markdownlint-cli2-config.js", @@ -23,6 +27,7 @@ "bugs": "https://github.com/DavidAnson/markdownlint-cli2/issues", "scripts": { "build-docker-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker build -t davidanson/markdownlint-cli2:v$VERSION -f docker/Dockerfile --label org.opencontainers.image.version=v$VERSION .", + "build-docker-image-rules": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker build -t davidanson/markdownlint-cli2-rules:v$VERSION -f docker/Dockerfile-rules --build-arg VERSION=v$VERSION --label org.opencontainers.image.version=v$VERSION .", "ci": "npm-run-all --continue-on-error --parallel test-cover lint", "docker-npm-install": "docker run --rm --tty --name npm-install --volume $PWD:/home/workdir --workdir /home/workdir --user node node:16 npm install", "docker-npm-run-upgrade": "docker run --rm --tty --name npm-run-upgrade --volume $PWD:/home/workdir --workdir /home/workdir --user node node:16 npm run upgrade", @@ -32,10 +37,12 @@ "publish-docker-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker buildx build --platform linux/arm64,linux/amd64 -t davidanson/markdownlint-cli2:v$VERSION -t davidanson/markdownlint-cli2:latest -f docker/Dockerfile --push .", "test": "ava --timeout=1m test/append-to-array-test.js test/fs-mock-test.js test/markdownlint-cli2-test.js test/markdownlint-cli2-test-exec.js test/markdownlint-cli2-test-fs.js test/markdownlint-cli2-test-main.js test/merge-options-test.js test/resolve-and-require-test.js", "test-docker-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2:v$VERSION \"*.md\"", + "test-docker-image-rules": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2-rules:v$VERSION \"*.md\"", "test-docker-hub-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker image rm davidanson/markdownlint-cli2:v$VERSION davidanson/markdownlint-cli2:latest || true && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2:v$VERSION \"*.md\" && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2:latest \"*.md\"", + "test-docker-hub-image-rules": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker image rm davidanson/markdownlint-cli2-rules:v$VERSION davidanson/markdownlint-cli2-rules:latest || true && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2-rules:v$VERSION \"*.md\" && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2-rules:latest \"*.md\"", "test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test", "test-watch": "git ls-files | entr npm run test", - "update-snapshots": "ava --update-snapshots test/markdownlint-cli2-test-exec.js test/markdownlint-cli2-test-fs.js test/markdownlint-cli2-test-main.js", + "update-snapshots": "ava --timeout=1m --update-snapshots test/markdownlint-cli2-test-exec.js test/markdownlint-cli2-test-fs.js test/markdownlint-cli2-test-main.js", "upgrade": "npx --yes npm-check-updates --upgrade", "webworker": "cd webworker && webpack --mode none", "webworker-install": "npm run docker-npm-install -- --no-save path-browserify process setimmediate stream-browserify url util webpack-cli" @@ -45,6 +52,8 @@ }, "files": [ "append-to-array.js", + "export-markdownlint.js", + "export-markdownlint-helpers.js", "markdownlint-cli2.js", "markdownlint-cli2-config.js", "markdownlint-cli2-fix.js", @@ -52,30 +61,30 @@ "resolve-and-require.js" ], "dependencies": { - "globby": "13.1.3", - "markdownlint": "0.27.0", - "markdownlint-cli2-formatter-default": "0.0.3", + "globby": "13.1.4", + "markdownlint": "0.28.1", + "markdownlint-cli2-formatter-default": "0.0.4", "micromatch": "4.0.5", "strip-json-comments": "5.0.0", "yaml": "2.2.1" }, "devDependencies": { "@iktakahiro/markdown-it-katex": "4.0.1", - "ava": "5.1.0", - "c8": "7.12.0", + "ava": "5.2.0", + "c8": "7.13.0", "cpy": "9.0.1", "del": "7.0.0", - "eslint": "8.30.0", - "eslint-plugin-n": "15.6.0", - "eslint-plugin-unicorn": "45.0.2", - "execa": "6.1.0", + "eslint": "8.38.0", + "eslint-plugin-n": "15.7.0", + "eslint-plugin-unicorn": "46.0.0", + "execa": "7.1.1", "markdown-it-emoji": "2.0.2", "markdown-it-for-inline": "0.1.1", - "markdownlint-cli2-formatter-codequality": "0.0.1", - "markdownlint-cli2-formatter-json": "0.0.6", - "markdownlint-cli2-formatter-junit": "0.0.5", - "markdownlint-cli2-formatter-pretty": "0.0.3", - "markdownlint-cli2-formatter-summarize": "0.0.5", + "markdownlint-cli2-formatter-codequality": "0.0.4", + "markdownlint-cli2-formatter-json": "0.0.7", + "markdownlint-cli2-formatter-junit": "0.0.6", + "markdownlint-cli2-formatter-pretty": "0.0.4", + "markdownlint-cli2-formatter-summarize": "0.0.6", "markdownlint-rule-titlecase": "0.1.0", "npm-run-all": "4.1.5" }, diff --git a/test/config-with-fix/.markdownlint-cli2.jsonc b/test/config-with-fix/.markdownlint-cli2.jsonc new file mode 100644 index 00000000..3df10b6a --- /dev/null +++ b/test/config-with-fix/.markdownlint-cli2.jsonc @@ -0,0 +1,5 @@ +{ + "config": { + "single-title": false + } +} diff --git a/test/config-with-fix/config/.markdownlint-cli2.jsonc b/test/config-with-fix/config/.markdownlint-cli2.jsonc new file mode 100644 index 00000000..dd8d364b --- /dev/null +++ b/test/config-with-fix/config/.markdownlint-cli2.jsonc @@ -0,0 +1,6 @@ +{ + "fix": true, + "config": { + "first-line-heading": false + } +} diff --git a/test/config-with-fix/info.md b/test/config-with-fix/info.md new file mode 100644 index 00000000..fc9dba79 --- /dev/null +++ b/test/config-with-fix/info.md @@ -0,0 +1,3 @@ +## Information +Text ` code1` text `code2 ` text + diff --git a/test/config-with-fix/viewme.md b/test/config-with-fix/viewme.md new file mode 100644 index 00000000..d60ebf5a --- /dev/null +++ b/test/config-with-fix/viewme.md @@ -0,0 +1,14 @@ +# Title + +> Tagline + + +# Description + +Text text text +Text text text +Text text text + +## Summary + +Text text text \ No newline at end of file diff --git a/test/markdownlint-cli2-extends/cjs/.markdownlint-cli2.cjs b/test/markdownlint-cli2-extends/cjs/.markdownlint-cli2.cjs new file mode 100644 index 00000000..557ba6bc --- /dev/null +++ b/test/markdownlint-cli2-extends/cjs/.markdownlint-cli2.cjs @@ -0,0 +1,10 @@ +// @ts-check + +"use strict"; + +module.exports = { + "config": { + "extends": "../outer.jsonc", + "no-multiple-blanks": false + } +}; diff --git a/test/markdownlint-cli2-extends/cjs/viewme.md b/test/markdownlint-cli2-extends/cjs/viewme.md new file mode 100644 index 00000000..d60ebf5a --- /dev/null +++ b/test/markdownlint-cli2-extends/cjs/viewme.md @@ -0,0 +1,14 @@ +# Title + +> Tagline + + +# Description + +Text text text +Text text text +Text text text + +## Summary + +Text text text \ No newline at end of file diff --git a/test/markdownlint-cli2-extends/inner.yaml b/test/markdownlint-cli2-extends/inner.yaml new file mode 100644 index 00000000..f8c5f42f --- /dev/null +++ b/test/markdownlint-cli2-extends/inner.yaml @@ -0,0 +1 @@ +single-trailing-newline: false diff --git a/test/markdownlint-cli2-extends/jsonc/.markdownlint-cli2.jsonc b/test/markdownlint-cli2-extends/jsonc/.markdownlint-cli2.jsonc new file mode 100644 index 00000000..5302f859 --- /dev/null +++ b/test/markdownlint-cli2-extends/jsonc/.markdownlint-cli2.jsonc @@ -0,0 +1,6 @@ +{ + "config": { + "extends": "../outer.jsonc", + "no-multiple-blanks": false + } +} diff --git a/test/markdownlint-cli2-extends/jsonc/viewme.md b/test/markdownlint-cli2-extends/jsonc/viewme.md new file mode 100644 index 00000000..d60ebf5a --- /dev/null +++ b/test/markdownlint-cli2-extends/jsonc/viewme.md @@ -0,0 +1,14 @@ +# Title + +> Tagline + + +# Description + +Text text text +Text text text +Text text text + +## Summary + +Text text text \ No newline at end of file diff --git a/test/markdownlint-cli2-extends/outer.jsonc b/test/markdownlint-cli2-extends/outer.jsonc new file mode 100644 index 00000000..d74a01bc --- /dev/null +++ b/test/markdownlint-cli2-extends/outer.jsonc @@ -0,0 +1,4 @@ +{ + "extends": "./inner.yaml", + "single-title": false +} diff --git a/test/markdownlint-cli2-extends/package/.markdownlint-cli2.jsonc b/test/markdownlint-cli2-extends/package/.markdownlint-cli2.jsonc new file mode 100644 index 00000000..5ecf259c --- /dev/null +++ b/test/markdownlint-cli2-extends/package/.markdownlint-cli2.jsonc @@ -0,0 +1,5 @@ +{ + "config": { + "extends": "markdownlint/style/prettier" + } +} diff --git a/test/markdownlint-cli2-extends/package/viewme.md b/test/markdownlint-cli2-extends/package/viewme.md new file mode 100644 index 00000000..d60ebf5a --- /dev/null +++ b/test/markdownlint-cli2-extends/package/viewme.md @@ -0,0 +1,14 @@ +# Title + +> Tagline + + +# Description + +Text text text +Text text text +Text text text + +## Summary + +Text text text \ No newline at end of file diff --git a/test/markdownlint-cli2-extends/yaml/.markdownlint-cli2.yaml b/test/markdownlint-cli2-extends/yaml/.markdownlint-cli2.yaml new file mode 100644 index 00000000..a9d12adf --- /dev/null +++ b/test/markdownlint-cli2-extends/yaml/.markdownlint-cli2.yaml @@ -0,0 +1,3 @@ +config: + extends: '../outer.jsonc' + no-multiple-blanks: false diff --git a/test/markdownlint-cli2-extends/yaml/viewme.md b/test/markdownlint-cli2-extends/yaml/viewme.md new file mode 100644 index 00000000..d60ebf5a --- /dev/null +++ b/test/markdownlint-cli2-extends/yaml/viewme.md @@ -0,0 +1,14 @@ +# Title + +> Tagline + + +# Description + +Text text text +Text text text +Text text text + +## Summary + +Text text text \ No newline at end of file diff --git a/test/markdownlint-cli2-test-cases.js b/test/markdownlint-cli2-test-cases.js index 285b2a33..f989f79b 100644 --- a/test/markdownlint-cli2-test-cases.js +++ b/test/markdownlint-cli2-test-cases.js @@ -41,6 +41,10 @@ const testCases = path.join(directory, "markdownlint-cli2-codequality.json"), "utf8" ).catch(empty), + fs.readFile( + path.join(directory, "custom-name-codequality.json"), + "utf8" + ).catch(empty), fs.readFile( path.join(directory, "markdownlint-cli2-results.json"), "utf8" @@ -64,6 +68,7 @@ const testCases = const [ child, formatterOutputCodeQuality, + formatterOutputCodeQualityCustom, formatterOutputJson, formatterOutputJsonCustom, formatterOutputJunit, @@ -73,7 +78,11 @@ const testCases = "exitCode": child.exitCode, "stdout": sanitize(child.stdout), "stderr": sanitize(child.stderr), - "formatterCodeQuality": sanitize(formatterOutputCodeQuality), + "formatterCodeQuality": + sanitize( + formatterOutputCodeQuality || + formatterOutputCodeQualityCustom + ), "formatterJson": sanitize(formatterOutputJson || formatterOutputJsonCustom), "formatterJunit": @@ -266,7 +275,7 @@ const testCases = testCase({ "name": "markdownlint-json-invalid", "args": [ ".*" ], - "stderrRe": /Unexpected end of JSON input/u + "stderrRe": /(?:Unexpected end)|(?:Expected property name)/u }); testCase({ @@ -306,7 +315,7 @@ const testCases = testCase({ "name": "markdownlint-cli2-jsonc-invalid", "args": [ ".*" ], - "stderrRe": /Unexpected end of JSON input/u + "stderrRe": /(?:Unexpected end)|(?:Expected property name)/u }); testCase({ @@ -355,6 +364,12 @@ const testCases = "usesRequire": true }); + testCase({ + "name": "markdownlint-cli2-extends", + "args": [ "**/*.md" ], + "usesRequire": true + }); + testCase({ "name": "config-overrides-options", "args": [ "viewme.md" ] @@ -487,10 +502,16 @@ const testCases = } const invalidConfigFiles = [ - [ "invalid.markdownlint-cli2.jsonc", /Unexpected end of JSON input/u ], + [ + "invalid.markdownlint-cli2.jsonc", + /(?:Unexpected end)|(?:Expected property name)/u + ], [ "invalid.markdownlint-cli2.cjs", /Unexpected end of input/u ], [ "invalid.markdownlint-cli2.mjs", /Unexpected end of input/u ], - [ "invalid.markdownlint.json", /Unexpected end of JSON input/u ], + [ + "invalid.markdownlint.json", + /(?:Unexpected end)|(?:Expected property name)/u + ], [ "invalid.markdownlint.yaml", /Map keys must be unique/u ], [ "invalid.markdownlint.cjs", /Unexpected end of input/u ], [ "invalid.markdownlint.mjs", /Unexpected end of input/u ] @@ -553,6 +574,16 @@ const testCases = "usesScript": true }); + testCase({ + "name": "config-with-fix", + "script": "markdownlint-cli2-config.js", + "args": [ "config/.markdownlint-cli2.jsonc", "viewme.md", "info.md" ], + "cwd": directoryName("config-with-fix"), + "pre": copyDirectory, + "post": deleteDirectory, + "usesScript": true + }); + testCase({ "name": "customRules", "args": [ "**/*.md" ], diff --git a/test/markdownlint-cli2-test.js b/test/markdownlint-cli2-test.js index 6d9f67e9..99de0ebf 100644 --- a/test/markdownlint-cli2-test.js +++ b/test/markdownlint-cli2-test.js @@ -36,6 +36,7 @@ test("README files", (t) => { t.plan(1); const uncalled = (msg) => t.fail(`message logged: ${msg}`); const argv = [ + "CHANGELOG.md", "README.md", "./doc/OutputFormatters.md", "./formatter-default/README.md", diff --git a/test/outputFormatters-params-absolute/.markdownlint-cli2.cjs b/test/outputFormatters-params-absolute/.markdownlint-cli2.cjs index 713e9a88..8794a5ea 100644 --- a/test/outputFormatters-params-absolute/.markdownlint-cli2.cjs +++ b/test/outputFormatters-params-absolute/.markdownlint-cli2.cjs @@ -6,6 +6,12 @@ const path = require("path"); module.exports = { "outputFormatters": [ + [ + "../../formatter-codequality", + { + "name": path.resolve(__dirname, "custom-name-codequality.json") + } + ], [ "../../formatter-json", { diff --git a/test/outputFormatters-params/.markdownlint-cli2.jsonc b/test/outputFormatters-params/.markdownlint-cli2.jsonc index 4be335f3..5b2bab02 100644 --- a/test/outputFormatters-params/.markdownlint-cli2.jsonc +++ b/test/outputFormatters-params/.markdownlint-cli2.jsonc @@ -1,5 +1,6 @@ { "outputFormatters": [ + [ "../../formatter-codequality", { "name": "custom-name-codequality.json" } ], [ "../../formatter-json", { "name": "custom-name.json", "spaces": 1 } ], [ "../../formatter-junit", { "name": "custom-name.xml" } ] ] diff --git a/test/snapshots/markdownlint-cli2-test-exec.js.md b/test/snapshots/markdownlint-cli2-test-exec.js.md index 78a5d575..4b644ca3 100644 --- a/test/snapshots/markdownlint-cli2-test-exec.js.md +++ b/test/snapshots/markdownlint-cli2-test-exec.js.md @@ -1071,6 +1071,31 @@ Generated by [AVA](https://avajs.dev). `, } +## markdownlint-cli2-extends (exec) + +> Snapshot 1 + + { + exitCode: 1, + formatterCodeQuality: '', + formatterJson: '', + formatterJunit: '', + stderr: `cjs/viewme.md:3:10 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]␊ + cjs/viewme.md:12:1 MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading [Context: "## Summary"]␊ + jsonc/viewme.md:3:10 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]␊ + jsonc/viewme.md:12:1 MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading [Context: "## Summary"]␊ + package/viewme.md:6 MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "# Description"]␊ + package/viewme.md:14:14 MD047/single-trailing-newline Files should end with a single newline character␊ + yaml/viewme.md:3:10 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]␊ + yaml/viewme.md:12:1 MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading [Context: "## Summary"]␊ + `, + stdout: `markdownlint-cli2 vX.Y.Z (markdownlint vX.Y.Z)␊ + Finding: **/*.md␊ + Linting: 4 file(s)␊ + Summary: 8 error(s)␊ + `, + } + ## config-overrides-options (exec) > Snapshot 1 @@ -2267,6 +2292,23 @@ Generated by [AVA](https://avajs.dev). `, } +## config-with-fix (exec) + +> Snapshot 1 + + { + exitCode: 0, + formatterCodeQuality: '', + formatterJson: '', + formatterJunit: '', + stderr: '', + stdout: `markdownlint-cli2-config vX.Y.Z (markdownlint vX.Y.Z)␊ + Finding: viewme.md info.md␊ + Linting: 2 file(s)␊ + Summary: 0 error(s)␊ + `, + } + ## customRules (exec) > Snapshot 1 @@ -3424,7 +3466,73 @@ Generated by [AVA](https://avajs.dev). { exitCode: 1, - formatterCodeQuality: '', + formatterCodeQuality: `[␊ + {␊ + "type": "issue",␊ + "check_name": "MD009/no-trailing-spaces",␊ + "description": "MD009/no-trailing-spaces: Trailing spaces [Expected: 0 or 2; Actual: 1]",␊ + "severity": "minor",␊ + "fingerprint": "f34a01e4a119d7df262993933665d4c97cc601702eeca2814ccad9606a3ccb48",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 3␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD012/no-multiple-blanks",␊ + "description": "MD012/no-multiple-blanks: Multiple consecutive blank lines [Expected: 1; Actual: 2]",␊ + "severity": "minor",␊ + "fingerprint": "a3d9b647ce8d929904e64fbbb0a47223617e8985d0a4d31e674b22f919f736fb",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 5␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD025/single-title/single-h1",␊ + "description": "MD025/single-title/single-h1: Multiple top-level headings in the same document",␊ + "severity": "minor",␊ + "fingerprint": "ef26889ac26be010b8bb6d2bd8c846c70bccf90506c0adffb763bef774f93f80",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 6␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD019/no-multiple-space-atx",␊ + "description": "MD019/no-multiple-space-atx: Multiple spaces after hash on atx style heading",␊ + "severity": "minor",␊ + "fingerprint": "244fe04169875709c7854fc0ddef5c2639aa57bad8a9319e3a9ed6a5f8504c89",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 12␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD047/single-trailing-newline",␊ + "description": "MD047/single-trailing-newline: Files should end with a single newline character",␊ + "severity": "minor",␊ + "fingerprint": "bf74eade0ee3301ccaa826907651e0d6925b60d517e1110c29b081c7b6ce1acf",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 14␊ + }␊ + }␊ + }␊ + ]`, formatterJson: `[␊ {␊ "fileName": "viewme.md",␊ @@ -3552,7 +3660,73 @@ Generated by [AVA](https://avajs.dev). { exitCode: 1, - formatterCodeQuality: '', + formatterCodeQuality: `[␊ + {␊ + "type": "issue",␊ + "check_name": "MD009/no-trailing-spaces",␊ + "description": "MD009/no-trailing-spaces: Trailing spaces [Expected: 0 or 2; Actual: 1]",␊ + "severity": "minor",␊ + "fingerprint": "f34a01e4a119d7df262993933665d4c97cc601702eeca2814ccad9606a3ccb48",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 3␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD012/no-multiple-blanks",␊ + "description": "MD012/no-multiple-blanks: Multiple consecutive blank lines [Expected: 1; Actual: 2]",␊ + "severity": "minor",␊ + "fingerprint": "a3d9b647ce8d929904e64fbbb0a47223617e8985d0a4d31e674b22f919f736fb",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 5␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD025/single-title/single-h1",␊ + "description": "MD025/single-title/single-h1: Multiple top-level headings in the same document",␊ + "severity": "minor",␊ + "fingerprint": "ef26889ac26be010b8bb6d2bd8c846c70bccf90506c0adffb763bef774f93f80",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 6␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD019/no-multiple-space-atx",␊ + "description": "MD019/no-multiple-space-atx: Multiple spaces after hash on atx style heading",␊ + "severity": "minor",␊ + "fingerprint": "244fe04169875709c7854fc0ddef5c2639aa57bad8a9319e3a9ed6a5f8504c89",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 12␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD047/single-trailing-newline",␊ + "description": "MD047/single-trailing-newline: Files should end with a single newline character",␊ + "severity": "minor",␊ + "fingerprint": "bf74eade0ee3301ccaa826907651e0d6925b60d517e1110c29b081c7b6ce1acf",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 14␊ + }␊ + }␊ + }␊ + ]`, formatterJson: `[␊ {␊ "fileName": "viewme.md",␊ @@ -3794,7 +3968,7 @@ Generated by [AVA](https://avajs.dev). formatterJunit: `␊ - ␊ + `, stderr: '', diff --git a/test/snapshots/markdownlint-cli2-test-exec.js.snap b/test/snapshots/markdownlint-cli2-test-exec.js.snap index b2d19e3a..6b2aa522 100644 Binary files a/test/snapshots/markdownlint-cli2-test-exec.js.snap and b/test/snapshots/markdownlint-cli2-test-exec.js.snap differ diff --git a/test/snapshots/markdownlint-cli2-test-main.js.md b/test/snapshots/markdownlint-cli2-test-main.js.md index c30c10a9..6d89734a 100644 --- a/test/snapshots/markdownlint-cli2-test-main.js.md +++ b/test/snapshots/markdownlint-cli2-test-main.js.md @@ -921,6 +921,31 @@ Generated by [AVA](https://avajs.dev). `, } +## markdownlint-cli2-extends (main) + +> Snapshot 1 + + { + exitCode: 1, + formatterCodeQuality: '', + formatterJson: '', + formatterJunit: '', + stderr: `cjs/viewme.md:3:10 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]␊ + cjs/viewme.md:12:1 MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading [Context: "## Summary"]␊ + jsonc/viewme.md:3:10 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]␊ + jsonc/viewme.md:12:1 MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading [Context: "## Summary"]␊ + package/viewme.md:6 MD025/single-title/single-h1 Multiple top-level headings in the same document [Context: "# Description"]␊ + package/viewme.md:14:14 MD047/single-trailing-newline Files should end with a single newline character␊ + yaml/viewme.md:3:10 MD009/no-trailing-spaces Trailing spaces [Expected: 0 or 2; Actual: 1]␊ + yaml/viewme.md:12:1 MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading [Context: "## Summary"]␊ + `, + stdout: `markdownlint-cli2 vX.Y.Z (markdownlint vX.Y.Z)␊ + Finding: **/*.md␊ + Linting: 4 file(s)␊ + Summary: 8 error(s)␊ + `, + } + ## config-overrides-options (main) > Snapshot 1 @@ -1847,7 +1872,73 @@ Generated by [AVA](https://avajs.dev). { exitCode: 1, - formatterCodeQuality: '', + formatterCodeQuality: `[␊ + {␊ + "type": "issue",␊ + "check_name": "MD009/no-trailing-spaces",␊ + "description": "MD009/no-trailing-spaces: Trailing spaces [Expected: 0 or 2; Actual: 1]",␊ + "severity": "minor",␊ + "fingerprint": "f34a01e4a119d7df262993933665d4c97cc601702eeca2814ccad9606a3ccb48",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 3␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD012/no-multiple-blanks",␊ + "description": "MD012/no-multiple-blanks: Multiple consecutive blank lines [Expected: 1; Actual: 2]",␊ + "severity": "minor",␊ + "fingerprint": "a3d9b647ce8d929904e64fbbb0a47223617e8985d0a4d31e674b22f919f736fb",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 5␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD025/single-title/single-h1",␊ + "description": "MD025/single-title/single-h1: Multiple top-level headings in the same document",␊ + "severity": "minor",␊ + "fingerprint": "ef26889ac26be010b8bb6d2bd8c846c70bccf90506c0adffb763bef774f93f80",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 6␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD019/no-multiple-space-atx",␊ + "description": "MD019/no-multiple-space-atx: Multiple spaces after hash on atx style heading",␊ + "severity": "minor",␊ + "fingerprint": "244fe04169875709c7854fc0ddef5c2639aa57bad8a9319e3a9ed6a5f8504c89",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 12␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD047/single-trailing-newline",␊ + "description": "MD047/single-trailing-newline: Files should end with a single newline character",␊ + "severity": "minor",␊ + "fingerprint": "bf74eade0ee3301ccaa826907651e0d6925b60d517e1110c29b081c7b6ce1acf",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 14␊ + }␊ + }␊ + }␊ + ]`, formatterJson: `[␊ {␊ "fileName": "viewme.md",␊ @@ -1975,7 +2066,73 @@ Generated by [AVA](https://avajs.dev). { exitCode: 1, - formatterCodeQuality: '', + formatterCodeQuality: `[␊ + {␊ + "type": "issue",␊ + "check_name": "MD009/no-trailing-spaces",␊ + "description": "MD009/no-trailing-spaces: Trailing spaces [Expected: 0 or 2; Actual: 1]",␊ + "severity": "minor",␊ + "fingerprint": "f34a01e4a119d7df262993933665d4c97cc601702eeca2814ccad9606a3ccb48",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 3␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD012/no-multiple-blanks",␊ + "description": "MD012/no-multiple-blanks: Multiple consecutive blank lines [Expected: 1; Actual: 2]",␊ + "severity": "minor",␊ + "fingerprint": "a3d9b647ce8d929904e64fbbb0a47223617e8985d0a4d31e674b22f919f736fb",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 5␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD025/single-title/single-h1",␊ + "description": "MD025/single-title/single-h1: Multiple top-level headings in the same document",␊ + "severity": "minor",␊ + "fingerprint": "ef26889ac26be010b8bb6d2bd8c846c70bccf90506c0adffb763bef774f93f80",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 6␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD019/no-multiple-space-atx",␊ + "description": "MD019/no-multiple-space-atx: Multiple spaces after hash on atx style heading",␊ + "severity": "minor",␊ + "fingerprint": "244fe04169875709c7854fc0ddef5c2639aa57bad8a9319e3a9ed6a5f8504c89",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 12␊ + }␊ + }␊ + },␊ + {␊ + "type": "issue",␊ + "check_name": "MD047/single-trailing-newline",␊ + "description": "MD047/single-trailing-newline: Files should end with a single newline character",␊ + "severity": "minor",␊ + "fingerprint": "bf74eade0ee3301ccaa826907651e0d6925b60d517e1110c29b081c7b6ce1acf",␊ + "location": {␊ + "path": "viewme.md",␊ + "lines": {␊ + "begin": 14␊ + }␊ + }␊ + }␊ + ]`, formatterJson: `[␊ {␊ "fileName": "viewme.md",␊ @@ -2217,7 +2374,7 @@ Generated by [AVA](https://avajs.dev). formatterJunit: `␊ - ␊ + `, stderr: '', diff --git a/test/snapshots/markdownlint-cli2-test-main.js.snap b/test/snapshots/markdownlint-cli2-test-main.js.snap index 09cdc89e..6f3dfaef 100644 Binary files a/test/snapshots/markdownlint-cli2-test-main.js.snap and b/test/snapshots/markdownlint-cli2-test-main.js.snap differ