markdownlint-cli2 0.3.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +80 -41
- package/markdownlint-cli2-config.js +11 -0
- package/markdownlint-cli2-fix.js +2 -1
- package/markdownlint-cli2.js +282 -97
- package/package.json +42 -33
- package/resolve-and-require.js +3 -4
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -20,8 +20,11 @@ As a development dependency of the current package:
|
|
|
20
20
|
npm install markdownlint-cli2 --save-dev
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
Or
|
|
24
|
-
|
|
23
|
+
Or as a Docker container image:
|
|
24
|
+
|
|
25
|
+
```shell
|
|
26
|
+
docker pull davidanson/markdownlint-cli2
|
|
27
|
+
```
|
|
25
28
|
|
|
26
29
|
## Overview
|
|
27
30
|
|
|
@@ -51,13 +54,16 @@ markdownlint-cli2 vX.Y.Z (markdownlint vX.Y.Z)
|
|
|
51
54
|
https://github.com/DavidAnson/markdownlint-cli2
|
|
52
55
|
|
|
53
56
|
Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN]
|
|
57
|
+
markdownlint-cli2-fix glob0 [glob1] [...] [globN]
|
|
58
|
+
markdownlint-cli2-config config-file glob0 [glob1] [...] [globN]
|
|
54
59
|
|
|
55
60
|
Glob expressions (from the globby library):
|
|
56
61
|
- * matches any number of characters, but not /
|
|
57
62
|
- ? matches a single character, but not /
|
|
58
|
-
- ** matches any number of characters, including /
|
|
63
|
+
- ** matches any number of characters, including /
|
|
59
64
|
- {} allows for a comma-separated list of "or" expressions
|
|
60
65
|
- ! or # at the beginning of a pattern negate the match
|
|
66
|
+
- : at the beginning identifies a literal file path
|
|
61
67
|
|
|
62
68
|
Dot-only glob:
|
|
63
69
|
- The command "markdownlint-cli2 ." would lint every file in the current directory tree which is probably not intended
|
|
@@ -67,10 +73,10 @@ Dot-only glob:
|
|
|
67
73
|
Configuration via:
|
|
68
74
|
- .markdownlint-cli2.jsonc
|
|
69
75
|
- .markdownlint-cli2.yaml
|
|
70
|
-
- .markdownlint-cli2.
|
|
76
|
+
- .markdownlint-cli2.cjs or .markdownlint-cli2.mjs
|
|
71
77
|
- .markdownlint.jsonc or .markdownlint.json
|
|
72
78
|
- .markdownlint.yaml or .markdownlint.yml
|
|
73
|
-
- .markdownlint.
|
|
79
|
+
- .markdownlint.cjs or .markdownlint.mjs
|
|
74
80
|
|
|
75
81
|
Cross-platform compatibility:
|
|
76
82
|
- UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
|
|
@@ -79,31 +85,45 @@ Cross-platform compatibility:
|
|
|
79
85
|
- Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
|
|
80
86
|
- The path separator is forward slash (/) on all platforms; backslash (\) is automatically converted
|
|
81
87
|
|
|
82
|
-
|
|
88
|
+
The most compatible syntax for cross-platform support:
|
|
83
89
|
$ markdownlint-cli2 "**/*.md" "#node_modules"
|
|
84
90
|
```
|
|
85
91
|
|
|
86
92
|
For scenarios where it is preferable to specify glob expressions in a
|
|
87
|
-
configuration file, the `globs` property of `.markdownlint-cli2.jsonc
|
|
88
|
-
`.
|
|
89
|
-
|
|
93
|
+
configuration file, the `globs` property of `.markdownlint-cli2.jsonc`, `.yaml`,
|
|
94
|
+
`.cjs`, or `.mjs` may be used instead of (or in addition to) passing
|
|
95
|
+
`glob0 ... globN` on the command-line.
|
|
90
96
|
|
|
91
|
-
As shown above,
|
|
97
|
+
As shown above, a typical command-line for `markdownlint-cli2` looks something
|
|
92
98
|
like:
|
|
93
99
|
|
|
94
100
|
```bash
|
|
95
101
|
markdownlint-cli2 "**/*.md" "#node_modules"
|
|
96
102
|
```
|
|
97
103
|
|
|
98
|
-
|
|
104
|
+
Because sharing the same configuration between "normal" and "fix" modes is
|
|
99
105
|
common, the following command defaults the `fix` property (see below) to `true`:
|
|
100
106
|
|
|
101
107
|
```bash
|
|
102
108
|
markdownlint-cli2-fix "**/*.md" "#node_modules"
|
|
103
109
|
```
|
|
104
110
|
|
|
105
|
-
Other than the default behavior of the `fix` property (which can be overridden
|
|
106
|
-
|
|
111
|
+
Other than the default behavior of the `fix` property (which can be overridden),
|
|
112
|
+
these two commands behave identically.
|
|
113
|
+
|
|
114
|
+
In cases where it is not convenient to store a configuration file in the root
|
|
115
|
+
of a project, the `markdownlint-cli2-config` command can be used. This command
|
|
116
|
+
accepts a path to any supported configuration file as its first argument:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
markdownlint-cli2-config "config/.markdownlint-cli2.jsonc" "**/*.md" "#node_modules"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The configuration file name must be (or end with) one of the supported types
|
|
123
|
+
above. For example, `.markdownlint.json` or `example.markdownlint-cli2.jsonc`.
|
|
124
|
+
The specified configuration file will be loaded, parsed, and applied as a base
|
|
125
|
+
configuration for the current directory - which will then be handled normally.
|
|
126
|
+
Otherwise, this command behaves identically to `markdownlint-cli2`.
|
|
107
127
|
|
|
108
128
|
### Container Image
|
|
109
129
|
|
|
@@ -111,7 +131,7 @@ A container image [`davidanson/markdownlint-cli2`][docker-hub-markdownlint-cli2]
|
|
|
111
131
|
can also be used (e.g., as part of a CI pipeline):
|
|
112
132
|
|
|
113
133
|
```bash
|
|
114
|
-
docker run -v $PWD:/workdir davidanson/markdownlint-cli2:0.
|
|
134
|
+
docker run -v $PWD:/workdir davidanson/markdownlint-cli2:0.5.1 "**/*.md" "#node_modules"
|
|
115
135
|
```
|
|
116
136
|
|
|
117
137
|
Notes:
|
|
@@ -123,19 +143,19 @@ Notes:
|
|
|
123
143
|
runs with restricted permissions. If it is necessary to run as `root`, pass
|
|
124
144
|
the `-u root` option when invoking `docker`.
|
|
125
145
|
- By default, `markdownlint-cli2` will execute within the `/workdir` directory
|
|
126
|
-
|
|
146
|
+
*inside the container*. So, as shown above, [bind mount][docker-bind-mounts]
|
|
127
147
|
the project's directory there.
|
|
128
148
|
- A custom working directory can be specified with Docker's `-w` flag:
|
|
129
149
|
|
|
130
150
|
```bash
|
|
131
|
-
docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:0.
|
|
151
|
+
docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:0.5.1 "**/*.md" "#node_modules"
|
|
132
152
|
```
|
|
133
153
|
|
|
134
|
-
To invoke the `markdownlint-cli2-
|
|
135
|
-
`--entrypoint` flag:
|
|
154
|
+
To invoke the `markdownlint-cli2-config` or `markdownlint-cli2-fix` commands
|
|
155
|
+
instead, use Docker's `--entrypoint` flag:
|
|
136
156
|
|
|
137
157
|
```bash
|
|
138
|
-
docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:0.
|
|
158
|
+
docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:0.5.1 "**/*.md" "#node_modules"
|
|
139
159
|
```
|
|
140
160
|
|
|
141
161
|
### Exit Codes
|
|
@@ -159,11 +179,11 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
|
|
|
159
179
|
- See the [Configuration][markdownlint-configuration] section of the
|
|
160
180
|
`markdownlint` documentation for information about the inline comment syntax
|
|
161
181
|
for enabling and disabling rules with HTML comments.
|
|
162
|
-
- In general, glob expressions match files under the current directory and
|
|
163
|
-
configuration for that
|
|
182
|
+
- In general, glob expressions match files under the current directory and the
|
|
183
|
+
configuration for that directory applies to the entire tree.
|
|
164
184
|
- When glob expressions match files *not* under the current directory,
|
|
165
|
-
configuration for the current
|
|
166
|
-
|
|
185
|
+
configuration for the current directory is applied to the closest common
|
|
186
|
+
parent directory.
|
|
167
187
|
|
|
168
188
|
### `.markdownlint-cli2.jsonc`
|
|
169
189
|
|
|
@@ -177,8 +197,6 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
|
|
|
177
197
|
- `customRules`: `Array` of `String`s (or `Array`s of `String`s) of module
|
|
178
198
|
names/paths of [custom rules][markdownlint-custom-rules] to load and use
|
|
179
199
|
when linting
|
|
180
|
-
- Each `String` is passed as the `id` parameter to Node's
|
|
181
|
-
[require function][nodejs-require]
|
|
182
200
|
- Relative paths are resolved based on the location of the `JSONC` file
|
|
183
201
|
- Search [`markdownlint-rule` on npm][markdownlint-rule]
|
|
184
202
|
- `fix`: `Boolean` value to enable fixing of linting errors reported by rules
|
|
@@ -229,9 +247,16 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
|
|
|
229
247
|
- This top-level setting is valid **only** in the directory from which
|
|
230
248
|
`markdownlint-cli2` is run
|
|
231
249
|
- Search [`markdownlint-cli2-formatter` on npm][markdownlint-cli2-formatter]
|
|
250
|
+
- When referencing a module via the `customRules`, `markdownItPlugins`, or
|
|
251
|
+
`outputFormatters` properties, each `String` identifier is passed to Node's
|
|
252
|
+
[`require` function][nodejs-require] then (if that failed) its
|
|
253
|
+
[`import` expression][nodejs-import-expression]
|
|
254
|
+
- Importing a locally-installed module using a bare specifier (ex:
|
|
255
|
+
`package-name`) or using a directory name (ex: `./package-dir`) will not
|
|
256
|
+
work until [`import.meta.resolve`][nodejs-import-meta-resolve] is available
|
|
232
257
|
- Settings in this file apply to the directory it is in and all subdirectories.
|
|
233
258
|
- Settings **merge with** those applied by any versions of this file in a parent
|
|
234
|
-
directory.
|
|
259
|
+
directory (up to the current directory).
|
|
235
260
|
- For example: [`.markdownlint-cli2.jsonc`][markdownlint-cli2-jsonc] with all
|
|
236
261
|
properties set
|
|
237
262
|
|
|
@@ -245,17 +270,20 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
|
|
|
245
270
|
- For example: [`.markdownlint-cli2.yaml`][markdownlint-cli2-yaml] with all
|
|
246
271
|
properties set
|
|
247
272
|
|
|
248
|
-
### `.markdownlint-cli2.
|
|
273
|
+
### `.markdownlint-cli2.cjs` or `.markdownlint-cli2.mjs`
|
|
249
274
|
|
|
250
|
-
- The format of this file is a [CommonJS module][commonjs-module]
|
|
251
|
-
|
|
275
|
+
- The format of this file is a [CommonJS module][commonjs-module] (`.cjs`) or
|
|
276
|
+
[ECMAScript module][ecmascript-module] (`.mjs`) that exports the object
|
|
277
|
+
described above for `.markdownlint-cli2.jsonc`.
|
|
252
278
|
- Instead of passing a `String` to identify the module name/path to load for
|
|
253
279
|
`customRules`, `markdownItPlugins`, and `outputFormatters`, the corresponding
|
|
254
280
|
`Object` or `Function` can be provided directly.
|
|
255
281
|
- Other details are the same as for `.markdownlint-cli2.jsonc` described above.
|
|
256
282
|
- If a `.markdownlint-cli2.jsonc` or `.markdownlint-cli2.yaml` file is present
|
|
257
|
-
in the same directory, it takes precedence.
|
|
258
|
-
|
|
283
|
+
in the same directory, it takes precedence; `.markdownlint-cli2.cjs` takes
|
|
284
|
+
precedence over `.markdownlint-cli2.mjs`.
|
|
285
|
+
- For example: [`.markdownlint-cli2.cjs`][markdownlint-cli2-cjs] or
|
|
286
|
+
[`.markdownlint-cli2.mjs`][markdownlint-cli2-mjs]
|
|
259
287
|
|
|
260
288
|
### `.markdownlint.jsonc` or `.markdownlint.json`
|
|
261
289
|
|
|
@@ -263,7 +291,7 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
|
|
|
263
291
|
the [`markdownlint` `config` object][markdownlint-config].
|
|
264
292
|
- Settings in this file apply to the directory it is in and all subdirectories
|
|
265
293
|
- Settings **override** those applied by any versions of this file in a parent
|
|
266
|
-
directory.
|
|
294
|
+
directory (up to the current directory).
|
|
267
295
|
- If `jsonc` and `json` files are present in the same directory, the `jsonc`
|
|
268
296
|
version takes precedence.
|
|
269
297
|
- To merge the settings of these files or share configuration, use the `extends`
|
|
@@ -282,14 +310,17 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
|
|
|
282
310
|
precedence.
|
|
283
311
|
- For example: [`.markdownlint.yaml`][markdownlint-yaml]
|
|
284
312
|
|
|
285
|
-
### `.markdownlint.
|
|
313
|
+
### `.markdownlint.cjs` or `.markdownlint.mjs`
|
|
286
314
|
|
|
287
|
-
- The format of this file is a [CommonJS module][commonjs-module]
|
|
288
|
-
|
|
315
|
+
- The format of this file is a [CommonJS module][commonjs-module] (`.cjs`) or
|
|
316
|
+
[ECMAScript module][ecmascript-module] (`.mjs`) that exports the
|
|
317
|
+
[`markdownlint` `config` object][markdownlint-config].
|
|
289
318
|
- Other details are the same as for `jsonc`/`json` files described above.
|
|
290
|
-
- If a
|
|
291
|
-
it takes precedence.
|
|
292
|
-
|
|
319
|
+
- If a `.markdownlint.jsonc`, `.json`, `.yaml`, or `.yml` file is present in the
|
|
320
|
+
same directory, it takes precedence; `.markdownlint.cjs` takes precedence over
|
|
321
|
+
`.markdownlint.mjs`.
|
|
322
|
+
- For example: [`.markdownlint.cjs`][markdownlint-cjs] or
|
|
323
|
+
[`.markdownlint.mjs`][markdownlint-mjs]
|
|
293
324
|
|
|
294
325
|
## Compatibility
|
|
295
326
|
|
|
@@ -313,7 +344,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
|
|
|
313
344
|
|
|
314
345
|
```yaml
|
|
315
346
|
- repo: https://github.com/DavidAnson/markdownlint-cli2
|
|
316
|
-
rev: v0.
|
|
347
|
+
rev: v0.5.1
|
|
317
348
|
hooks:
|
|
318
349
|
- id: markdownlint-cli2
|
|
319
350
|
```
|
|
@@ -345,11 +376,15 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
|
|
|
345
376
|
- 0.3.0 - Add Docker container, update dependencies
|
|
346
377
|
- 0.3.1 - Extensibility tweaks
|
|
347
378
|
- 0.3.2 - Extensibility/Windows/consistency improvements
|
|
379
|
+
- 0.4.0 - New rules, async custom rules, explicit config, CJS (breaking)
|
|
380
|
+
- 0.5.0 - New rules, support modules (MJS) everywhere, include dotfiles
|
|
381
|
+
- 0.5.1 - Update dependencies
|
|
348
382
|
|
|
349
383
|
<!-- markdownlint-disable line-length -->
|
|
350
384
|
|
|
351
385
|
[commonmark]: https://commonmark.org/
|
|
352
386
|
[commonjs-module]: https://nodejs.org/api/modules.html#modules_modules_commonjs_modules
|
|
387
|
+
[ecmascript-module]: https://nodejs.org/api/esm.html#modules-ecmascript-modules
|
|
353
388
|
[docker-bind-mounts]: https://docs.docker.com/storage/bind-mounts/
|
|
354
389
|
[docker-hub-markdownlint-cli2]: https://hub.docker.com/r/davidanson/markdownlint-cli2
|
|
355
390
|
[front-matter]: https://jekyllrb.com/docs/frontmatter/
|
|
@@ -374,16 +409,20 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
|
|
|
374
409
|
[markdownlint-cli2]: https://github.com/DavidAnson/markdownlint-cli2
|
|
375
410
|
[markdownlint-cli2-blog]: https://dlaa.me/blog/post/markdownlintcli2
|
|
376
411
|
[markdownlint-cli2-formatter]: https://www.npmjs.com/search?q=keywords:markdownlint-cli2-formatter
|
|
377
|
-
[markdownlint-cli2-
|
|
412
|
+
[markdownlint-cli2-cjs]: test/markdownlint-cli2-cjs/.markdownlint-cli2.cjs
|
|
378
413
|
[markdownlint-cli2-jsonc]: test/markdownlint-cli2-jsonc-example/.markdownlint-cli2.jsonc
|
|
414
|
+
[markdownlint-cli2-mjs]: test/markdownlint-cli2-mjs/.markdownlint-cli2.mjs
|
|
379
415
|
[markdownlint-cli2-yaml]: test/markdownlint-cli2-yaml-example/.markdownlint-cli2.yaml
|
|
380
|
-
[markdownlint-
|
|
416
|
+
[markdownlint-cjs]: test/markdownlint-cjs/.markdownlint.cjs
|
|
381
417
|
[markdownlint-jsonc]: https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.jsonc
|
|
418
|
+
[markdownlint-mjs]: test/markdownlint-mjs/.markdownlint.mjs
|
|
382
419
|
[markdownlint-rule]: https://www.npmjs.com/search?q=keywords:markdownlint-rule
|
|
383
420
|
[markdownlint-yaml]: https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml
|
|
384
421
|
[nodejs]: https://nodejs.org/
|
|
385
422
|
[nodejs-docker]: https://github.com/nodejs/docker-node
|
|
386
423
|
[nodejs-docker-non-root]: https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#non-root-user
|
|
424
|
+
[nodejs-import-expression]: https://nodejs.org/api/esm.html#import-expressions
|
|
425
|
+
[nodejs-import-meta-resolve]: https://nodejs.org/api/esm.html#importmetaresolvespecifier-parent
|
|
387
426
|
[nodejs-require]: https://nodejs.org/api/modules.html#modules_require_id
|
|
388
427
|
[npm-image]: https://img.shields.io/npm/v/markdownlint-cli2.svg
|
|
389
428
|
[npm-url]: https://www.npmjs.com/package/markdownlint-cli2
|
package/markdownlint-cli2-fix.js
CHANGED
package/markdownlint-cli2.js
CHANGED
|
@@ -10,19 +10,19 @@ const dynamicRequire = (typeof __non_webpack_require__ === "undefined") ? requir
|
|
|
10
10
|
// Capture native require implementation for dynamic loading of modules
|
|
11
11
|
|
|
12
12
|
// Requires
|
|
13
|
-
const path = require("path");
|
|
14
|
-
const
|
|
13
|
+
const path = require("node:path");
|
|
14
|
+
const { pathToFileURL } = require("node:url");
|
|
15
15
|
const markdownlintLibrary = require("markdownlint");
|
|
16
16
|
const { markdownlint, "readConfig": markdownlintReadConfig } =
|
|
17
17
|
markdownlintLibrary.promises;
|
|
18
|
-
const markdownlintRuleHelpers = require("markdownlint
|
|
18
|
+
const markdownlintRuleHelpers = require("markdownlint/helpers");
|
|
19
19
|
const appendToArray = require("./append-to-array");
|
|
20
20
|
const mergeOptions = require("./merge-options");
|
|
21
21
|
const resolveAndRequire = require("./resolve-and-require");
|
|
22
22
|
|
|
23
23
|
// Variables
|
|
24
24
|
const packageName = "markdownlint-cli2";
|
|
25
|
-
const packageVersion = "0.
|
|
25
|
+
const packageVersion = "0.5.1";
|
|
26
26
|
const libraryName = "markdownlint";
|
|
27
27
|
const libraryVersion = markdownlintLibrary.getVersion();
|
|
28
28
|
const dotOnlySubstitute = "*.{md,markdown}";
|
|
@@ -31,10 +31,16 @@ const utf8 = "utf8";
|
|
|
31
31
|
// No-op function
|
|
32
32
|
const noop = () => null;
|
|
33
33
|
|
|
34
|
-
//
|
|
35
|
-
const
|
|
34
|
+
// Gets a synchronous function to parse JSONC text
|
|
35
|
+
const getJsoncParse = async () => {
|
|
36
|
+
const { "default": stripJsonComments } =
|
|
37
|
+
// eslint-disable-next-line max-len
|
|
38
|
+
// eslint-disable-next-line no-inline-comments, node/no-unsupported-features/es-syntax
|
|
39
|
+
await import(/* webpackMode: "eager" */ "strip-json-comments");
|
|
40
|
+
return (text) => JSON.parse(stripJsonComments(text));
|
|
41
|
+
};
|
|
36
42
|
|
|
37
|
-
//
|
|
43
|
+
// Synchronous function to parse YAML text
|
|
38
44
|
const yamlParse = (text) => require("yaml").parse(text);
|
|
39
45
|
|
|
40
46
|
// Negate a glob
|
|
@@ -48,54 +54,143 @@ const readConfig = (fs, dir, name, otherwise) => {
|
|
|
48
54
|
const file = path.posix.join(dir, name);
|
|
49
55
|
return () => fs.promises.access(file).
|
|
50
56
|
then(
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
() => getJsoncParse().then(
|
|
58
|
+
(jsoncParse) => markdownlintReadConfig(
|
|
59
|
+
file,
|
|
60
|
+
[ jsoncParse, yamlParse ],
|
|
61
|
+
fs
|
|
62
|
+
)
|
|
63
|
+
),
|
|
53
64
|
otherwise
|
|
54
65
|
);
|
|
55
66
|
};
|
|
56
67
|
|
|
57
|
-
//
|
|
58
|
-
const
|
|
68
|
+
// Import or resolve/require a module ID with a custom directory in the path
|
|
69
|
+
const importOrRequireResolve = async (dir, id) => {
|
|
59
70
|
if (typeof id === "string") {
|
|
60
|
-
|
|
71
|
+
const expandId =
|
|
72
|
+
markdownlintRuleHelpers.expandTildePath(id, require("node:os"));
|
|
73
|
+
const errors = [];
|
|
74
|
+
try {
|
|
75
|
+
return resolveAndRequire(dynamicRequire, expandId, dir);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
errors.push(error);
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const fileUrlString =
|
|
81
|
+
pathToFileURL(path.resolve(dir, expandId)).toString();
|
|
82
|
+
// eslint-disable-next-line max-len
|
|
83
|
+
// eslint-disable-next-line no-inline-comments, node/no-unsupported-features/es-syntax
|
|
84
|
+
const module = await import(/* webpackIgnore: true */ fileUrlString);
|
|
85
|
+
return module.default;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
errors.push(error);
|
|
88
|
+
}
|
|
89
|
+
// Use AggregateError once available in Node 15+
|
|
90
|
+
throw new Error(errors.map((error) => error.message).join(" / "));
|
|
61
91
|
}
|
|
62
92
|
return id;
|
|
63
93
|
};
|
|
64
94
|
|
|
65
|
-
//
|
|
66
|
-
const
|
|
67
|
-
noRequire ? [] : ids.map((id) =>
|
|
95
|
+
// Import or require an array of modules by ID
|
|
96
|
+
const importOrRequireIds = (dir, ids, noRequire) => (
|
|
97
|
+
Promise.all(noRequire ? [] : ids.map((id) => importOrRequireResolve(dir, id)))
|
|
68
98
|
);
|
|
69
99
|
|
|
70
|
-
//
|
|
71
|
-
const
|
|
100
|
+
// Import or require an array of modules by ID (preserving parameters)
|
|
101
|
+
const importOrRequireIdsAndParams = async (dir, idsAndParams, noRequire) => {
|
|
72
102
|
if (noRequire) {
|
|
73
103
|
return [];
|
|
74
104
|
}
|
|
75
105
|
const ids = idsAndParams.map((entry) => entry[0]);
|
|
76
|
-
const modules =
|
|
106
|
+
const modules = await importOrRequireIds(dir, ids);
|
|
77
107
|
const modulesAndParams = idsAndParams.
|
|
78
108
|
map((entry, i) => [ modules[i], ...entry.slice(1) ]);
|
|
79
109
|
return modulesAndParams;
|
|
80
110
|
};
|
|
81
111
|
|
|
82
|
-
//
|
|
83
|
-
const
|
|
112
|
+
// Import or require a JavaScript file and return the exported object
|
|
113
|
+
const importOrRequireConfig = (fs, dir, name, noRequire, otherwise) => (
|
|
84
114
|
() => (noRequire
|
|
85
115
|
// eslint-disable-next-line prefer-promise-reject-errors
|
|
86
116
|
? Promise.reject()
|
|
87
117
|
: fs.promises.access(path.posix.join(dir, name))
|
|
88
118
|
).
|
|
89
119
|
then(
|
|
90
|
-
() =>
|
|
91
|
-
|
|
120
|
+
() => importOrRequireResolve(dir, `./${name}`),
|
|
121
|
+
otherwise
|
|
92
122
|
)
|
|
93
123
|
);
|
|
94
124
|
|
|
95
|
-
//
|
|
125
|
+
// Read an options or config file in any format and return the object
|
|
126
|
+
const readOptionsOrConfig = async (configPath, fs, noRequire) => {
|
|
127
|
+
const basename = path.basename(configPath);
|
|
128
|
+
const dirname = path.dirname(configPath);
|
|
129
|
+
let options = null;
|
|
130
|
+
let config = null;
|
|
131
|
+
if (basename.endsWith(".markdownlint-cli2.jsonc")) {
|
|
132
|
+
const jsoncParse = await getJsoncParse();
|
|
133
|
+
options = jsoncParse(await fs.promises.readFile(configPath, utf8));
|
|
134
|
+
} else if (basename.endsWith(".markdownlint-cli2.yaml")) {
|
|
135
|
+
options = yamlParse(await fs.promises.readFile(configPath, utf8));
|
|
136
|
+
} else if (
|
|
137
|
+
basename.endsWith(".markdownlint-cli2.cjs") ||
|
|
138
|
+
basename.endsWith(".markdownlint-cli2.mjs")
|
|
139
|
+
) {
|
|
140
|
+
options = await (
|
|
141
|
+
importOrRequireConfig(fs, dirname, basename, noRequire, noop)()
|
|
142
|
+
);
|
|
143
|
+
} else if (
|
|
144
|
+
basename.endsWith(".markdownlint.jsonc") ||
|
|
145
|
+
basename.endsWith(".markdownlint.json") ||
|
|
146
|
+
basename.endsWith(".markdownlint.yaml") ||
|
|
147
|
+
basename.endsWith(".markdownlint.yml")
|
|
148
|
+
) {
|
|
149
|
+
const jsoncParse = await getJsoncParse();
|
|
150
|
+
config =
|
|
151
|
+
await markdownlintReadConfig(configPath, [ jsoncParse, yamlParse ], fs);
|
|
152
|
+
} else if (
|
|
153
|
+
basename.endsWith(".markdownlint.cjs") ||
|
|
154
|
+
basename.endsWith(".markdownlint.mjs")
|
|
155
|
+
) {
|
|
156
|
+
config = await (
|
|
157
|
+
importOrRequireConfig(fs, dirname, basename, noRequire, noop)()
|
|
158
|
+
);
|
|
159
|
+
} else {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Configuration file "${configPath}" is unrecognized; ` +
|
|
162
|
+
"its name should be (or end with) one of the supported types " +
|
|
163
|
+
"(e.g., \".markdownlint.json\" or \"example.markdownlint-cli2.jsonc\")."
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
return options || { config };
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Filter a list of files to ignore by glob
|
|
170
|
+
const removeIgnoredFiles = (dir, files, ignores) => {
|
|
171
|
+
const micromatch = require("micromatch");
|
|
172
|
+
return micromatch(
|
|
173
|
+
files.map((file) => path.posix.relative(dir, file)),
|
|
174
|
+
ignores
|
|
175
|
+
).map((file) => path.posix.join(dir, file));
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Process/normalize command-line arguments and return glob patterns
|
|
96
179
|
const processArgv = (argv) => {
|
|
97
180
|
const globPatterns = (argv || []).map(
|
|
98
|
-
(glob) =>
|
|
181
|
+
(glob) => {
|
|
182
|
+
if (glob.startsWith(":")) {
|
|
183
|
+
return glob;
|
|
184
|
+
}
|
|
185
|
+
// Escape RegExp special characters recognized by fast-glob
|
|
186
|
+
// https://github.com/mrmlnc/fast-glob#advanced-syntax
|
|
187
|
+
const specialCharacters = /\\(?![$()*+?[\]^])/gu;
|
|
188
|
+
if (glob.startsWith("\\:")) {
|
|
189
|
+
return `\\:${glob.slice(2).replace(specialCharacters, "/")}`;
|
|
190
|
+
}
|
|
191
|
+
return (glob.startsWith("#") ? `!${glob.slice(1)}` : glob).
|
|
192
|
+
replace(specialCharacters, "/");
|
|
193
|
+
}
|
|
99
194
|
);
|
|
100
195
|
if ((globPatterns.length === 1) && (globPatterns[0] === ".")) {
|
|
101
196
|
// Substitute a more reasonable pattern
|
|
@@ -106,31 +201,33 @@ const processArgv = (argv) => {
|
|
|
106
201
|
|
|
107
202
|
// Show help if missing arguments
|
|
108
203
|
const showHelp = (logMessage) => {
|
|
109
|
-
const { name, homepage } = require("./package.json");
|
|
110
204
|
/* eslint-disable max-len */
|
|
111
|
-
logMessage(
|
|
205
|
+
logMessage(`https://github.com/DavidAnson/markdownlint-cli2
|
|
112
206
|
|
|
113
|
-
Syntax:
|
|
207
|
+
Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN]
|
|
208
|
+
markdownlint-cli2-fix glob0 [glob1] [...] [globN]
|
|
209
|
+
markdownlint-cli2-config config-file glob0 [glob1] [...] [globN]
|
|
114
210
|
|
|
115
211
|
Glob expressions (from the globby library):
|
|
116
212
|
- * matches any number of characters, but not /
|
|
117
213
|
- ? matches a single character, but not /
|
|
118
|
-
- ** matches any number of characters, including /
|
|
214
|
+
- ** matches any number of characters, including /
|
|
119
215
|
- {} allows for a comma-separated list of "or" expressions
|
|
120
216
|
- ! or # at the beginning of a pattern negate the match
|
|
217
|
+
- : at the beginning identifies a literal file path
|
|
121
218
|
|
|
122
219
|
Dot-only glob:
|
|
123
|
-
- The command "
|
|
124
|
-
- Instead, it is mapped to "
|
|
125
|
-
- To lint every file in the current directory tree, the command "
|
|
220
|
+
- The command "markdownlint-cli2 ." would lint every file in the current directory tree which is probably not intended
|
|
221
|
+
- Instead, it is mapped to "markdownlint-cli2 ${dotOnlySubstitute}" which lints all Markdown files in the current directory
|
|
222
|
+
- To lint every file in the current directory tree, the command "markdownlint-cli2 **" can be used instead
|
|
126
223
|
|
|
127
224
|
Configuration via:
|
|
128
225
|
- .markdownlint-cli2.jsonc
|
|
129
226
|
- .markdownlint-cli2.yaml
|
|
130
|
-
- .markdownlint-cli2.
|
|
227
|
+
- .markdownlint-cli2.cjs or .markdownlint-cli2.mjs
|
|
131
228
|
- .markdownlint.jsonc or .markdownlint.json
|
|
132
229
|
- .markdownlint.yaml or .markdownlint.yml
|
|
133
|
-
- .markdownlint.
|
|
230
|
+
- .markdownlint.cjs or .markdownlint.mjs
|
|
134
231
|
|
|
135
232
|
Cross-platform compatibility:
|
|
136
233
|
- UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
|
|
@@ -139,19 +236,20 @@ Cross-platform compatibility:
|
|
|
139
236
|
- Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
|
|
140
237
|
- The path separator is forward slash (/) on all platforms; backslash (\\) is automatically converted
|
|
141
238
|
|
|
142
|
-
|
|
143
|
-
$
|
|
239
|
+
The most compatible syntax for cross-platform support:
|
|
240
|
+
$ markdownlint-cli2 "**/*.md" "#node_modules"`
|
|
144
241
|
);
|
|
145
242
|
/* eslint-enable max-len */
|
|
146
243
|
};
|
|
147
244
|
|
|
148
245
|
// Get (creating if necessary) and process a directory's info object
|
|
149
246
|
const getAndProcessDirInfo =
|
|
150
|
-
(fs, tasks, dirToDirInfo, dir, noRequire, func) => {
|
|
247
|
+
(fs, tasks, dirToDirInfo, dir, relativeDir, noRequire, func) => {
|
|
151
248
|
let dirInfo = dirToDirInfo[dir];
|
|
152
249
|
if (!dirInfo) {
|
|
153
250
|
dirInfo = {
|
|
154
251
|
dir,
|
|
252
|
+
relativeDir,
|
|
155
253
|
"parent": null,
|
|
156
254
|
"files": [],
|
|
157
255
|
"markdownlintConfig": null,
|
|
@@ -169,17 +267,27 @@ const getAndProcessDirInfo =
|
|
|
169
267
|
then(
|
|
170
268
|
() => fs.promises.
|
|
171
269
|
readFile(markdownlintCli2Jsonc, utf8).
|
|
172
|
-
then(
|
|
270
|
+
then(
|
|
271
|
+
(content) => getJsoncParse().
|
|
272
|
+
then((jsoncParse) => jsoncParse(content))
|
|
273
|
+
),
|
|
173
274
|
() => fs.promises.access(markdownlintCli2Yaml).
|
|
174
275
|
then(
|
|
175
276
|
() => fs.promises.
|
|
176
277
|
readFile(markdownlintCli2Yaml, utf8).
|
|
177
278
|
then(yamlParse),
|
|
178
|
-
|
|
279
|
+
importOrRequireConfig(
|
|
179
280
|
fs,
|
|
180
281
|
dir,
|
|
181
|
-
".markdownlint-cli2.
|
|
182
|
-
noRequire
|
|
282
|
+
".markdownlint-cli2.cjs",
|
|
283
|
+
noRequire,
|
|
284
|
+
importOrRequireConfig(
|
|
285
|
+
fs,
|
|
286
|
+
dir,
|
|
287
|
+
".markdownlint-cli2.mjs",
|
|
288
|
+
noRequire,
|
|
289
|
+
noop
|
|
290
|
+
)
|
|
183
291
|
)
|
|
184
292
|
)
|
|
185
293
|
).
|
|
@@ -206,11 +314,18 @@ const getAndProcessDirInfo =
|
|
|
206
314
|
fs,
|
|
207
315
|
dir,
|
|
208
316
|
".markdownlint.yml",
|
|
209
|
-
|
|
317
|
+
importOrRequireConfig(
|
|
210
318
|
fs,
|
|
211
319
|
dir,
|
|
212
|
-
".markdownlint.
|
|
213
|
-
noRequire
|
|
320
|
+
".markdownlint.cjs",
|
|
321
|
+
noRequire,
|
|
322
|
+
importOrRequireConfig(
|
|
323
|
+
fs,
|
|
324
|
+
dir,
|
|
325
|
+
".markdownlint.mjs",
|
|
326
|
+
noRequire,
|
|
327
|
+
noop
|
|
328
|
+
)
|
|
214
329
|
)
|
|
215
330
|
)
|
|
216
331
|
)
|
|
@@ -233,20 +348,28 @@ const getAndProcessDirInfo =
|
|
|
233
348
|
const getBaseOptions = async (
|
|
234
349
|
fs,
|
|
235
350
|
baseDir,
|
|
351
|
+
relativeDir,
|
|
236
352
|
globPatterns,
|
|
237
|
-
|
|
353
|
+
options,
|
|
238
354
|
fixDefault,
|
|
239
355
|
noGlobs,
|
|
240
356
|
noRequire
|
|
241
357
|
) => {
|
|
242
358
|
const tasks = [];
|
|
243
359
|
const dirToDirInfo = {};
|
|
244
|
-
getAndProcessDirInfo(
|
|
360
|
+
getAndProcessDirInfo(
|
|
361
|
+
fs,
|
|
362
|
+
tasks,
|
|
363
|
+
dirToDirInfo,
|
|
364
|
+
baseDir,
|
|
365
|
+
relativeDir,
|
|
366
|
+
noRequire
|
|
367
|
+
);
|
|
245
368
|
await Promise.all(tasks);
|
|
246
369
|
// eslint-disable-next-line no-multi-assign
|
|
247
370
|
const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions =
|
|
248
371
|
mergeOptions(
|
|
249
|
-
mergeOptions(
|
|
372
|
+
mergeOptions(options, { "fix": fixDefault }),
|
|
250
373
|
dirToDirInfo[baseDir].markdownlintOptions
|
|
251
374
|
);
|
|
252
375
|
|
|
@@ -270,24 +393,51 @@ const getBaseOptions = async (
|
|
|
270
393
|
|
|
271
394
|
// Enumerate files from globs and build directory infos
|
|
272
395
|
const enumerateFiles =
|
|
273
|
-
|
|
396
|
+
// eslint-disable-next-line max-len
|
|
397
|
+
async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
|
|
274
398
|
const tasks = [];
|
|
275
399
|
const globbyOptions = {
|
|
276
400
|
"absolute": true,
|
|
277
401
|
"cwd": baseDir,
|
|
402
|
+
"dot": true,
|
|
278
403
|
"expandDirectories": false,
|
|
279
404
|
fs
|
|
280
405
|
};
|
|
281
406
|
if (noErrors) {
|
|
282
407
|
globbyOptions.suppressErrors = true;
|
|
283
408
|
}
|
|
409
|
+
// Special-case literal files
|
|
410
|
+
const literalFiles = [];
|
|
411
|
+
const filteredGlobPatterns = globPatterns.filter(
|
|
412
|
+
(globPattern) => {
|
|
413
|
+
if (globPattern.startsWith(":")) {
|
|
414
|
+
literalFiles.push(
|
|
415
|
+
posixPath(path.resolve(baseDirSystem, globPattern.slice(1)))
|
|
416
|
+
);
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
).map((globPattern) => globPattern.replace(/^\\:/u, ":"));
|
|
422
|
+
const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions;
|
|
423
|
+
const globsForIgnore =
|
|
424
|
+
(baseMarkdownlintOptions.globs || []).
|
|
425
|
+
filter((glob) => glob.startsWith("!"));
|
|
426
|
+
const filteredLiteralFiles =
|
|
427
|
+
((literalFiles.length > 0) && (globsForIgnore.length > 0))
|
|
428
|
+
? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore)
|
|
429
|
+
: literalFiles;
|
|
284
430
|
// Manually expand directories to avoid globby call to dir-glob.sync
|
|
285
431
|
const expandedDirectories = await Promise.all(
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
432
|
+
filteredGlobPatterns.map((globPattern) => {
|
|
433
|
+
const barePattern =
|
|
434
|
+
globPattern.startsWith("!")
|
|
435
|
+
? globPattern.slice(1)
|
|
436
|
+
: globPattern;
|
|
437
|
+
const globPath =
|
|
438
|
+
(path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern))
|
|
439
|
+
? barePattern
|
|
440
|
+
: path.posix.join(baseDir, barePattern);
|
|
291
441
|
return fs.promises.stat(globPath).
|
|
292
442
|
then((stats) => (stats.isDirectory()
|
|
293
443
|
? path.posix.join(globPattern, "**")
|
|
@@ -296,7 +446,13 @@ async (fs, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
|
|
|
296
446
|
})
|
|
297
447
|
);
|
|
298
448
|
// Process glob patterns
|
|
299
|
-
|
|
449
|
+
// eslint-disable-next-line max-len
|
|
450
|
+
// eslint-disable-next-line no-inline-comments, node/no-unsupported-features/es-syntax
|
|
451
|
+
const { globby } = await import(/* webpackMode: "eager" */ "globby");
|
|
452
|
+
const files = [
|
|
453
|
+
...await globby(expandedDirectories, globbyOptions),
|
|
454
|
+
...filteredLiteralFiles
|
|
455
|
+
];
|
|
300
456
|
for (const file of files) {
|
|
301
457
|
const dir = path.posix.dirname(file);
|
|
302
458
|
getAndProcessDirInfo(
|
|
@@ -304,6 +460,7 @@ async (fs, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
|
|
|
304
460
|
tasks,
|
|
305
461
|
dirToDirInfo,
|
|
306
462
|
dir,
|
|
463
|
+
null,
|
|
307
464
|
noRequire,
|
|
308
465
|
(dirInfo) => {
|
|
309
466
|
dirInfo.files.push(file);
|
|
@@ -341,6 +498,7 @@ const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => {
|
|
|
341
498
|
tasks,
|
|
342
499
|
dirToDirInfo,
|
|
343
500
|
dir,
|
|
501
|
+
null,
|
|
344
502
|
noRequire,
|
|
345
503
|
// eslint-disable-next-line no-loop-func
|
|
346
504
|
(dirInfo) => {
|
|
@@ -360,9 +518,10 @@ const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => {
|
|
|
360
518
|
// Create directory info objects by enumerating file globs
|
|
361
519
|
const createDirInfos =
|
|
362
520
|
// eslint-disable-next-line max-len
|
|
363
|
-
async (fs, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => {
|
|
521
|
+
async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => {
|
|
364
522
|
await enumerateFiles(
|
|
365
523
|
fs,
|
|
524
|
+
baseDirSystem,
|
|
366
525
|
baseDir,
|
|
367
526
|
globPatterns,
|
|
368
527
|
dirToDirInfo,
|
|
@@ -381,11 +540,13 @@ async (fs, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noReq
|
|
|
381
540
|
dirs.sort((a, b) => b.length - a.length);
|
|
382
541
|
const dirInfos = [];
|
|
383
542
|
const noConfigDirInfo =
|
|
543
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
384
544
|
(dirInfo) => (
|
|
385
545
|
dirInfo.parent &&
|
|
386
546
|
!dirInfo.markdownlintConfig &&
|
|
387
547
|
!dirInfo.markdownlintOptions
|
|
388
548
|
);
|
|
549
|
+
const tasks = [];
|
|
389
550
|
for (const dir of dirs) {
|
|
390
551
|
const dirInfo = dirToDirInfo[dir];
|
|
391
552
|
if (noConfigDirInfo(dirInfo)) {
|
|
@@ -394,28 +555,34 @@ async (fs, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noReq
|
|
|
394
555
|
}
|
|
395
556
|
dirToDirInfo[dir] = null;
|
|
396
557
|
} else {
|
|
397
|
-
const { markdownlintOptions } = dirInfo;
|
|
558
|
+
const { markdownlintOptions, relativeDir } = dirInfo;
|
|
398
559
|
if (markdownlintOptions && markdownlintOptions.customRules) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
dir,
|
|
560
|
+
tasks.push(
|
|
561
|
+
importOrRequireIds(
|
|
562
|
+
relativeDir || dir,
|
|
402
563
|
markdownlintOptions.customRules,
|
|
403
564
|
noRequire
|
|
404
|
-
)
|
|
405
|
-
|
|
406
|
-
|
|
565
|
+
).then((customRules) => {
|
|
566
|
+
// Expand nested arrays (for packages that export multiple rules)
|
|
567
|
+
markdownlintOptions.customRules = customRules.flat();
|
|
568
|
+
})
|
|
569
|
+
);
|
|
407
570
|
}
|
|
408
571
|
if (markdownlintOptions && markdownlintOptions.markdownItPlugins) {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
dir,
|
|
572
|
+
tasks.push(
|
|
573
|
+
importOrRequireIdsAndParams(
|
|
574
|
+
relativeDir || dir,
|
|
412
575
|
markdownlintOptions.markdownItPlugins,
|
|
413
576
|
noRequire
|
|
414
|
-
)
|
|
577
|
+
).then((markdownItPlugins) => {
|
|
578
|
+
markdownlintOptions.markdownItPlugins = markdownItPlugins;
|
|
579
|
+
})
|
|
580
|
+
);
|
|
415
581
|
}
|
|
416
582
|
dirInfos.push(dirInfo);
|
|
417
583
|
}
|
|
418
584
|
}
|
|
585
|
+
await Promise.all(tasks);
|
|
419
586
|
for (const dirInfo of dirInfos) {
|
|
420
587
|
while (dirInfo.parent && !dirToDirInfo[dirInfo.parent.dir]) {
|
|
421
588
|
dirInfo.parent = dirInfo.parent.parent;
|
|
@@ -481,7 +648,8 @@ async (fs, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noReq
|
|
|
481
648
|
};
|
|
482
649
|
|
|
483
650
|
// Lint files in groups by shared configuration
|
|
484
|
-
const lintFiles = (fs, dirInfos, fileContents) => {
|
|
651
|
+
const lintFiles = async (fs, dirInfos, fileContents) => {
|
|
652
|
+
const jsoncParse = await getJsoncParse();
|
|
485
653
|
const tasks = [];
|
|
486
654
|
// For each dirInfo
|
|
487
655
|
for (const dirInfo of dirInfos) {
|
|
@@ -494,11 +662,7 @@ const lintFiles = (fs, dirInfos, fileContents) => {
|
|
|
494
662
|
) {
|
|
495
663
|
// eslint-disable-next-line unicorn/no-array-callback-reference
|
|
496
664
|
const ignores = markdownlintOptions.ignores.map(negateGlob);
|
|
497
|
-
|
|
498
|
-
filesAfterIgnores = micromatch(
|
|
499
|
-
files.map((file) => path.posix.relative(dir, file)),
|
|
500
|
-
ignores
|
|
501
|
-
).map((file) => path.posix.join(dir, file));
|
|
665
|
+
filesAfterIgnores = removeIgnoredFiles(dir, files, ignores);
|
|
502
666
|
}
|
|
503
667
|
const filteredFiles = filesAfterIgnores.filter(
|
|
504
668
|
(file) => fileContents[file] === undefined
|
|
@@ -514,6 +678,7 @@ const lintFiles = (fs, dirInfos, fileContents) => {
|
|
|
514
678
|
"files": filteredFiles,
|
|
515
679
|
"strings": filteredStrings,
|
|
516
680
|
"config": markdownlintConfig || markdownlintOptions.config,
|
|
681
|
+
"configParsers": [ jsoncParse ],
|
|
517
682
|
"customRules": markdownlintOptions.customRules,
|
|
518
683
|
"frontMatter": markdownlintOptions.frontMatter
|
|
519
684
|
? new RegExp(markdownlintOptions.frontMatter, "u")
|
|
@@ -595,26 +760,33 @@ const createSummary = (baseDir, taskResults) => {
|
|
|
595
760
|
};
|
|
596
761
|
|
|
597
762
|
// Output summary via formatters
|
|
598
|
-
const outputSummary =
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
763
|
+
const outputSummary = async (
|
|
764
|
+
baseDir,
|
|
765
|
+
relativeDir,
|
|
766
|
+
summary,
|
|
767
|
+
outputFormatters,
|
|
768
|
+
logMessage,
|
|
769
|
+
logError
|
|
770
|
+
) => {
|
|
771
|
+
const errorsPresent = (summary.length > 0);
|
|
772
|
+
if (errorsPresent || outputFormatters) {
|
|
773
|
+
const formatterOptions = {
|
|
774
|
+
"directory": baseDir,
|
|
775
|
+
"results": summary,
|
|
776
|
+
logMessage,
|
|
777
|
+
logError
|
|
778
|
+
};
|
|
779
|
+
const dir = relativeDir || baseDir;
|
|
780
|
+
const formattersAndParams = outputFormatters
|
|
781
|
+
? await importOrRequireIdsAndParams(dir, outputFormatters)
|
|
782
|
+
: [ [ require("markdownlint-cli2-formatter-default") ] ];
|
|
783
|
+
await Promise.all(formattersAndParams.map((formatterAndParams) => {
|
|
784
|
+
const [ formatter, ...formatterParams ] = formatterAndParams;
|
|
785
|
+
return formatter(formatterOptions, ...formatterParams);
|
|
786
|
+
}));
|
|
787
|
+
}
|
|
788
|
+
return errorsPresent;
|
|
789
|
+
};
|
|
618
790
|
|
|
619
791
|
// Main function
|
|
620
792
|
const main = async (params) => {
|
|
@@ -629,27 +801,39 @@ const main = async (params) => {
|
|
|
629
801
|
nonFileContents,
|
|
630
802
|
noErrors,
|
|
631
803
|
noGlobs,
|
|
632
|
-
noRequire
|
|
804
|
+
noRequire,
|
|
805
|
+
name
|
|
633
806
|
} = params;
|
|
634
807
|
const logMessage = params.logMessage || noop;
|
|
635
808
|
const logError = params.logError || noop;
|
|
636
|
-
const fs = params.fs || require("fs");
|
|
809
|
+
const fs = params.fs || require("node:fs");
|
|
637
810
|
const baseDirSystem =
|
|
638
811
|
(directory && path.resolve(directory)) ||
|
|
639
812
|
process.cwd();
|
|
640
813
|
const baseDir = posixPath(baseDirSystem);
|
|
641
814
|
// Output banner
|
|
642
815
|
logMessage(
|
|
643
|
-
|
|
816
|
+
// eslint-disable-next-line max-len
|
|
817
|
+
`${name || packageName} v${packageVersion} (${libraryName} v${libraryVersion})`
|
|
644
818
|
);
|
|
819
|
+
// Read argv configuration file (if relevant and present)
|
|
820
|
+
let optionsArgv = null;
|
|
821
|
+
let relativeDir = null;
|
|
822
|
+
const [ configPath ] = (argv || []);
|
|
823
|
+
if ((name === "markdownlint-cli2-config") && configPath) {
|
|
824
|
+
optionsArgv =
|
|
825
|
+
await readOptionsOrConfig(configPath, fs, noRequire);
|
|
826
|
+
relativeDir = path.dirname(configPath);
|
|
827
|
+
}
|
|
645
828
|
// Process arguments and get base options
|
|
646
|
-
const globPatterns = processArgv(argv);
|
|
829
|
+
const globPatterns = processArgv(optionsArgv ? argv.slice(1) : argv);
|
|
647
830
|
const { baseMarkdownlintOptions, dirToDirInfo } =
|
|
648
831
|
await getBaseOptions(
|
|
649
832
|
fs,
|
|
650
833
|
baseDir,
|
|
834
|
+
relativeDir,
|
|
651
835
|
globPatterns,
|
|
652
|
-
optionsDefault,
|
|
836
|
+
optionsArgv || optionsDefault,
|
|
653
837
|
fixDefault,
|
|
654
838
|
noGlobs,
|
|
655
839
|
noRequire
|
|
@@ -681,6 +865,7 @@ const main = async (params) => {
|
|
|
681
865
|
const dirInfos =
|
|
682
866
|
await createDirInfos(
|
|
683
867
|
fs,
|
|
868
|
+
baseDirSystem,
|
|
684
869
|
baseDir,
|
|
685
870
|
globPatterns,
|
|
686
871
|
dirToDirInfo,
|
|
@@ -707,7 +892,7 @@ const main = async (params) => {
|
|
|
707
892
|
(optionsOverride && optionsOverride.outputFormatters) ||
|
|
708
893
|
baseMarkdownlintOptions.outputFormatters;
|
|
709
894
|
const errorsPresent = await outputSummary(
|
|
710
|
-
baseDir, summary, outputFormatters, logMessage, logError
|
|
895
|
+
baseDir, relativeDir, summary, outputFormatters, logMessage, logError
|
|
711
896
|
);
|
|
712
897
|
// Return result
|
|
713
898
|
return errorsPresent ? 1 : 0;
|
package/package.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdownlint-cli2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "A fast, flexible, configuration-based command-line interface for linting Markdown/CommonMark files with the `markdownlint` library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "David Anson",
|
|
7
7
|
"url": "https://dlaa.me/"
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"
|
|
10
|
+
"type": "commonjs",
|
|
11
|
+
"main": "./markdownlint-cli2.js",
|
|
12
|
+
"exports": "./markdownlint-cli2.js",
|
|
11
13
|
"bin": {
|
|
12
14
|
"markdownlint-cli2": "markdownlint-cli2.js",
|
|
15
|
+
"markdownlint-cli2-config": "markdownlint-cli2-config.js",
|
|
13
16
|
"markdownlint-cli2-fix": "markdownlint-cli2-fix.js"
|
|
14
17
|
},
|
|
15
18
|
"homepage": "https://github.com/DavidAnson/markdownlint-cli2",
|
|
@@ -19,55 +22,61 @@
|
|
|
19
22
|
},
|
|
20
23
|
"bugs": "https://github.com/DavidAnson/markdownlint-cli2/issues",
|
|
21
24
|
"scripts": {
|
|
22
|
-
"build-docker-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker build -t davidanson/markdownlint-cli2
|
|
25
|
+
"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 .",
|
|
23
26
|
"ci": "npm-run-all --continue-on-error --parallel test-cover lint",
|
|
27
|
+
"docker-npm-install": "docker run --rm --tty --name npm-install --volume $PWD:/home/workdir --workdir /home/workdir --user node node:16 npm install",
|
|
28
|
+
"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",
|
|
24
29
|
"lint": "eslint --max-warnings 0 .",
|
|
25
30
|
"lint-dockerfile": "docker run --rm -i hadolint/hadolint:latest-alpine < docker/Dockerfile",
|
|
26
31
|
"lint-watch": "git ls-files | entr npm run lint",
|
|
27
|
-
"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
|
|
28
|
-
"test": "ava 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",
|
|
29
|
-
"test-docker-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2
|
|
30
|
-
"test-docker-hub-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker image rm davidanson/markdownlint-cli2
|
|
32
|
+
"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 .",
|
|
33
|
+
"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",
|
|
34
|
+
"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\"",
|
|
35
|
+
"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\"",
|
|
31
36
|
"test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test",
|
|
32
|
-
"test-watch": "git ls-files | entr npm run test"
|
|
37
|
+
"test-watch": "git ls-files | entr npm run test",
|
|
38
|
+
"update-snapshots": "ava --update-snapshots test/markdownlint-cli2-test-exec.js test/markdownlint-cli2-test-fs.js test/markdownlint-cli2-test-main.js",
|
|
39
|
+
"upgrade": "npx --yes npm-check-updates --upgrade",
|
|
40
|
+
"webworker": "cd webworker && webpack --mode none",
|
|
41
|
+
"webworker-install": "npm run docker-npm-install -- --no-save path-browserify process setimmediate stream-browserify url util webpack-cli"
|
|
33
42
|
},
|
|
34
43
|
"engines": {
|
|
35
|
-
"node": ">=
|
|
44
|
+
"node": ">=14"
|
|
36
45
|
},
|
|
37
46
|
"files": [
|
|
38
47
|
"append-to-array.js",
|
|
39
48
|
"markdownlint-cli2.js",
|
|
49
|
+
"markdownlint-cli2-config.js",
|
|
40
50
|
"markdownlint-cli2-fix.js",
|
|
41
51
|
"merge-options.js",
|
|
42
52
|
"resolve-and-require.js"
|
|
43
53
|
],
|
|
44
54
|
"dependencies": {
|
|
45
|
-
"globby": "
|
|
46
|
-
"markdownlint": "
|
|
47
|
-
"markdownlint-cli2-formatter-default": "
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"yaml": "~1.10.2"
|
|
55
|
+
"globby": "13.1.2",
|
|
56
|
+
"markdownlint": "0.26.2",
|
|
57
|
+
"markdownlint-cli2-formatter-default": "0.0.3",
|
|
58
|
+
"micromatch": "4.0.5",
|
|
59
|
+
"strip-json-comments": "5.0.0",
|
|
60
|
+
"yaml": "2.1.1"
|
|
52
61
|
},
|
|
53
62
|
"devDependencies": {
|
|
54
|
-
"@iktakahiro/markdown-it-katex": "
|
|
55
|
-
"ava": "
|
|
56
|
-
"c8": "
|
|
57
|
-
"cpy": "
|
|
58
|
-
"del": "
|
|
59
|
-
"eslint": "
|
|
60
|
-
"eslint-plugin-node": "
|
|
61
|
-
"eslint-plugin-unicorn": "
|
|
62
|
-
"execa": "
|
|
63
|
-
"markdown-it-emoji": "
|
|
64
|
-
"markdown-it-for-inline": "
|
|
65
|
-
"markdownlint-cli2-formatter-json": "
|
|
66
|
-
"markdownlint-cli2-formatter-junit": "
|
|
67
|
-
"markdownlint-cli2-formatter-pretty": "
|
|
68
|
-
"markdownlint-cli2-formatter-summarize": "
|
|
69
|
-
"markdownlint-rule-titlecase": "
|
|
70
|
-
"npm-run-all": "
|
|
63
|
+
"@iktakahiro/markdown-it-katex": "4.0.1",
|
|
64
|
+
"ava": "4.3.1",
|
|
65
|
+
"c8": "7.12.0",
|
|
66
|
+
"cpy": "9.0.1",
|
|
67
|
+
"del": "7.0.0",
|
|
68
|
+
"eslint": "8.21.0",
|
|
69
|
+
"eslint-plugin-node": "11.1.0",
|
|
70
|
+
"eslint-plugin-unicorn": "43.0.2",
|
|
71
|
+
"execa": "6.1.0",
|
|
72
|
+
"markdown-it-emoji": "2.0.2",
|
|
73
|
+
"markdown-it-for-inline": "0.1.1",
|
|
74
|
+
"markdownlint-cli2-formatter-json": "0.0.6",
|
|
75
|
+
"markdownlint-cli2-formatter-junit": "0.0.5",
|
|
76
|
+
"markdownlint-cli2-formatter-pretty": "0.0.3",
|
|
77
|
+
"markdownlint-cli2-formatter-summarize": "0.0.5",
|
|
78
|
+
"markdownlint-rule-titlecase": "0.1.0",
|
|
79
|
+
"npm-run-all": "4.1.5"
|
|
71
80
|
},
|
|
72
81
|
"keywords": [
|
|
73
82
|
"markdown",
|
package/resolve-and-require.js
CHANGED
|
@@ -4,10 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Wrapper for calling Node's require.resolve/require with an additional path.
|
|
7
|
-
*
|
|
8
|
-
* @param {
|
|
9
|
-
* @param {
|
|
10
|
-
* @param {*} dir Directory to include when resolving paths.
|
|
7
|
+
* @param {Object} req Node's require implementation (or equivalent).
|
|
8
|
+
* @param {String} id Package identifier to require.
|
|
9
|
+
* @param {String} dir Directory to include when resolving paths.
|
|
11
10
|
* @returns {Object} Exported module content.
|
|
12
11
|
*/
|
|
13
12
|
const resolveAndRequire = (req, id, dir) => {
|