markdownlint-cli2 0.3.2 → 0.4.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2021 David Anson
3
+ Copyright (c) 2020-2022 David Anson
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -51,13 +51,16 @@ markdownlint-cli2 vX.Y.Z (markdownlint vX.Y.Z)
51
51
  https://github.com/DavidAnson/markdownlint-cli2
52
52
 
53
53
  Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN]
54
+ markdownlint-cli2-fix glob0 [glob1] [...] [globN]
55
+ markdownlint-cli2-config config-file glob0 [glob1] [...] [globN]
54
56
 
55
57
  Glob expressions (from the globby library):
56
58
  - * matches any number of characters, but not /
57
59
  - ? matches a single character, but not /
58
- - ** matches any number of characters, including / (when it's the only thing in a path part)
60
+ - ** matches any number of characters, including /
59
61
  - {} allows for a comma-separated list of "or" expressions
60
62
  - ! or # at the beginning of a pattern negate the match
63
+ - : at the beginning identifies a literal file path
61
64
 
62
65
  Dot-only glob:
63
66
  - The command "markdownlint-cli2 ." would lint every file in the current directory tree which is probably not intended
@@ -67,10 +70,10 @@ Dot-only glob:
67
70
  Configuration via:
68
71
  - .markdownlint-cli2.jsonc
69
72
  - .markdownlint-cli2.yaml
70
- - .markdownlint-cli2.js
73
+ - .markdownlint-cli2.cjs
71
74
  - .markdownlint.jsonc or .markdownlint.json
72
75
  - .markdownlint.yaml or .markdownlint.yml
73
- - .markdownlint.js
76
+ - .markdownlint.cjs
74
77
 
75
78
  Cross-platform compatibility:
76
79
  - UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
@@ -79,31 +82,41 @@ Cross-platform compatibility:
79
82
  - Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
80
83
  - The path separator is forward slash (/) on all platforms; backslash (\) is automatically converted
81
84
 
82
- Therefore, the most compatible glob syntax for cross-platform support:
85
+ The most compatible syntax for cross-platform support:
83
86
  $ markdownlint-cli2 "**/*.md" "#node_modules"
84
87
  ```
85
88
 
86
89
  For scenarios where it is preferable to specify glob expressions in a
87
90
  configuration file, the `globs` property of `.markdownlint-cli2.jsonc` or
88
- `.markdownlint-cli2.yaml` or `.markdownlint-cli2.js` may be used instead of (or
91
+ `.markdownlint-cli2.yaml` or `.markdownlint-cli2.cjs` may be used instead of (or
89
92
  in addition to) passing `glob0 ... globN` on the command-line.
90
93
 
91
- As shown above, the default command-line for `markdownlint-cli2` looks something
94
+ As shown above, a typical command-line for `markdownlint-cli2` looks something
92
95
  like:
93
96
 
94
97
  ```bash
95
98
  markdownlint-cli2 "**/*.md" "#node_modules"
96
99
  ```
97
100
 
98
- However, because sharing configuration between "normal" and "fix" modes is so
101
+ Because sharing the same configuration between "normal" and "fix" modes is
99
102
  common, the following command defaults the `fix` property (see below) to `true`:
100
103
 
101
104
  ```bash
102
105
  markdownlint-cli2-fix "**/*.md" "#node_modules"
103
106
  ```
104
107
 
105
- Other than the default behavior of the `fix` property (which can be overridden
106
- in both cases), these two commands behave identically.
108
+ Other than the default behavior of the `fix` property (which can be overridden),
109
+ these two commands behave identically.
110
+
111
+ In cases where it is not convenient to store a configuration file in the root
112
+ of a project, the `markdownlint-cli2-config` command can be used. This command
113
+ accepts a path to any supported configuration file as its first argument:
114
+
115
+ ```bash
116
+ markdownlint-cli2-config "config/.markdownlint-cli2.jsonc" "**/*.md" "#node_modules"
117
+ ```
118
+
119
+ Otherwise, this command behaves identically to `markdownlint-cli2`.
107
120
 
108
121
  ### Container Image
109
122
 
@@ -111,7 +124,7 @@ A container image [`davidanson/markdownlint-cli2`][docker-hub-markdownlint-cli2]
111
124
  can also be used (e.g., as part of a CI pipeline):
112
125
 
113
126
  ```bash
114
- docker run -v $PWD:/workdir davidanson/markdownlint-cli2:0.3.2 "**/*.md" "#node_modules"
127
+ docker run -v $PWD:/workdir davidanson/markdownlint-cli2:0.4.0 "**/*.md" "#node_modules"
115
128
  ```
116
129
 
117
130
  Notes:
@@ -123,19 +136,19 @@ Notes:
123
136
  runs with restricted permissions. If it is necessary to run as `root`, pass
124
137
  the `-u root` option when invoking `docker`.
125
138
  - By default, `markdownlint-cli2` will execute within the `/workdir` directory
126
- _inside the container_. So, as shown above, [bind mount][docker-bind-mounts]
139
+ *inside the container*. So, as shown above, [bind mount][docker-bind-mounts]
127
140
  the project's directory there.
128
141
  - A custom working directory can be specified with Docker's `-w` flag:
129
142
 
130
143
  ```bash
131
- docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:0.3.2 "**/*.md" "#node_modules"
144
+ docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:0.4.0 "**/*.md" "#node_modules"
132
145
  ```
133
146
 
134
- To invoke the `markdownlint-cli2-fix` command instead, specify it via Docker's
135
- `--entrypoint` flag:
147
+ To invoke the `markdownlint-cli2-config` or `markdownlint-cli2-fix` commands
148
+ instead, use Docker's `--entrypoint` flag:
136
149
 
137
150
  ```bash
138
- docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:0.3.2 "**/*.md" "#node_modules"
151
+ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:0.4.0 "**/*.md" "#node_modules"
139
152
  ```
140
153
 
141
154
  ### Exit Codes
@@ -245,7 +258,7 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
245
258
  - For example: [`.markdownlint-cli2.yaml`][markdownlint-cli2-yaml] with all
246
259
  properties set
247
260
 
248
- ### `.markdownlint-cli2.js`
261
+ ### `.markdownlint-cli2.cjs`
249
262
 
250
263
  - The format of this file is a [CommonJS module][commonjs-module] that exports
251
264
  the object described above for `.markdownlint-cli2.jsonc`.
@@ -255,7 +268,7 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
255
268
  - Other details are the same as for `.markdownlint-cli2.jsonc` described above.
256
269
  - If a `.markdownlint-cli2.jsonc` or `.markdownlint-cli2.yaml` file is present
257
270
  in the same directory, it takes precedence.
258
- - For example: [`.markdownlint-cli2.js`][markdownlint-cli2-js]
271
+ - For example: [`.markdownlint-cli2.cjs`][markdownlint-cli2-cjs]
259
272
 
260
273
  ### `.markdownlint.jsonc` or `.markdownlint.json`
261
274
 
@@ -282,14 +295,14 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
282
295
  precedence.
283
296
  - For example: [`.markdownlint.yaml`][markdownlint-yaml]
284
297
 
285
- ### `.markdownlint.js`
298
+ ### `.markdownlint.cjs`
286
299
 
287
300
  - The format of this file is a [CommonJS module][commonjs-module] that exports
288
301
  the [`markdownlint` `config` object][markdownlint-config].
289
302
  - Other details are the same as for `jsonc`/`json` files described above.
290
303
  - If a `jsonc`, `json`, `yaml`, or `yml` file is present in the same directory,
291
304
  it takes precedence.
292
- - For example: [`.markdownlint.js`][markdownlint-js]
305
+ - For example: [`.markdownlint.cjs`][markdownlint-cjs]
293
306
 
294
307
  ## Compatibility
295
308
 
@@ -313,7 +326,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
313
326
 
314
327
  ```yaml
315
328
  - repo: https://github.com/DavidAnson/markdownlint-cli2
316
- rev: v0.3.2
329
+ rev: v0.4.0
317
330
  hooks:
318
331
  - id: markdownlint-cli2
319
332
  ```
@@ -345,6 +358,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
345
358
  - 0.3.0 - Add Docker container, update dependencies
346
359
  - 0.3.1 - Extensibility tweaks
347
360
  - 0.3.2 - Extensibility/Windows/consistency improvements
361
+ - 0.4.0 - New rules, async custom rules, explicit config, CJS (breaking)
348
362
 
349
363
  <!-- markdownlint-disable line-length -->
350
364
 
@@ -374,10 +388,10 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
374
388
  [markdownlint-cli2]: https://github.com/DavidAnson/markdownlint-cli2
375
389
  [markdownlint-cli2-blog]: https://dlaa.me/blog/post/markdownlintcli2
376
390
  [markdownlint-cli2-formatter]: https://www.npmjs.com/search?q=keywords:markdownlint-cli2-formatter
377
- [markdownlint-cli2-js]: test/markdownlint-cli2-js/.markdownlint-cli2.js
391
+ [markdownlint-cli2-cjs]: test/markdownlint-cli2-cjs/.markdownlint-cli2.cjs
378
392
  [markdownlint-cli2-jsonc]: test/markdownlint-cli2-jsonc-example/.markdownlint-cli2.jsonc
379
393
  [markdownlint-cli2-yaml]: test/markdownlint-cli2-yaml-example/.markdownlint-cli2.yaml
380
- [markdownlint-js]: test/markdownlint-js/.markdownlint.js
394
+ [markdownlint-cjs]: test/markdownlint-cjs/.markdownlint.cjs
381
395
  [markdownlint-jsonc]: https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.jsonc
382
396
  [markdownlint-rule]: https://www.npmjs.com/search?q=keywords:markdownlint-rule
383
397
  [markdownlint-yaml]: https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ // @ts-check
4
+
5
+ "use strict";
6
+
7
+ const { run } = require("./markdownlint-cli2");
8
+
9
+ run({
10
+ "name": "markdownlint-cli2-config"
11
+ });
@@ -7,5 +7,6 @@
7
7
  const { run } = require("./markdownlint-cli2");
8
8
 
9
9
  run({
10
- "fixDefault": true
10
+ "fixDefault": true,
11
+ "name": "markdownlint-cli2-fix"
11
12
  });
@@ -11,7 +11,6 @@ const dynamicRequire = (typeof __non_webpack_require__ === "undefined") ? requir
11
11
 
12
12
  // Requires
13
13
  const path = require("path");
14
- const globby = require("globby");
15
14
  const markdownlintLibrary = require("markdownlint");
16
15
  const { markdownlint, "readConfig": markdownlintReadConfig } =
17
16
  markdownlintLibrary.promises;
@@ -22,7 +21,7 @@ const resolveAndRequire = require("./resolve-and-require");
22
21
 
23
22
  // Variables
24
23
  const packageName = "markdownlint-cli2";
25
- const packageVersion = "0.3.2";
24
+ const packageVersion = "0.4.0";
26
25
  const libraryName = "markdownlint";
27
26
  const libraryVersion = markdownlintLibrary.getVersion();
28
27
  const dotOnlySubstitute = "*.{md,markdown}";
@@ -31,10 +30,16 @@ const utf8 = "utf8";
31
30
  // No-op function
32
31
  const noop = () => null;
33
32
 
34
- // Parse JSONC text
35
- const jsoncParse = (text) => JSON.parse(require("strip-json-comments")(text));
33
+ // Gets a synchronous function to parse JSONC text
34
+ const getJsoncParse = async () => {
35
+ const { "default": stripJsonComments } =
36
+ // eslint-disable-next-line max-len
37
+ // eslint-disable-next-line no-inline-comments, node/no-unsupported-features/es-syntax
38
+ await import(/* webpackMode: "eager" */ "strip-json-comments");
39
+ return (text) => JSON.parse(stripJsonComments(text));
40
+ };
36
41
 
37
- // Parse YAML text
42
+ // Synchronous function to parse YAML text
38
43
  const yamlParse = (text) => require("yaml").parse(text);
39
44
 
40
45
  // Negate a glob
@@ -48,8 +53,13 @@ const readConfig = (fs, dir, name, otherwise) => {
48
53
  const file = path.posix.join(dir, name);
49
54
  return () => fs.promises.access(file).
50
55
  then(
51
- // @ts-ignore
52
- () => markdownlintReadConfig(file, [ jsoncParse, yamlParse ], fs),
56
+ () => getJsoncParse().then(
57
+ (jsoncParse) => markdownlintReadConfig(
58
+ file,
59
+ [ jsoncParse, yamlParse ],
60
+ fs
61
+ )
62
+ ),
53
63
  otherwise
54
64
  );
55
65
  };
@@ -92,10 +102,59 @@ const requireConfig = (fs, dir, name, noRequire) => (
92
102
  )
93
103
  );
94
104
 
95
- // Process command-line arguments and return glob patterns
105
+ // Read an options or config file in any format and return the object
106
+ const readOptionsOrConfig = async (configPath, fs, noRequire) => {
107
+ const basename = path.basename(configPath);
108
+ const dirname = path.dirname(configPath);
109
+ let options = null;
110
+ let config = null;
111
+ if (basename.endsWith(".markdownlint-cli2.jsonc")) {
112
+ const jsoncParse = await getJsoncParse();
113
+ options = jsoncParse(await fs.promises.readFile(configPath, utf8));
114
+ } else if (basename.endsWith(".markdownlint-cli2.yaml")) {
115
+ options = yamlParse(await fs.promises.readFile(configPath, utf8));
116
+ } else if (basename.endsWith(".markdownlint-cli2.cjs")) {
117
+ options = await (requireConfig(fs, dirname, basename, noRequire)());
118
+ } else if (
119
+ basename.endsWith(".markdownlint.jsonc") ||
120
+ basename.endsWith(".markdownlint.json") ||
121
+ basename.endsWith(".markdownlint.yaml") ||
122
+ basename.endsWith(".markdownlint.yml")
123
+ ) {
124
+ const jsoncParse = await getJsoncParse();
125
+ config =
126
+ await markdownlintReadConfig(configPath, [ jsoncParse, yamlParse ], fs);
127
+ } else if (basename.endsWith(".markdownlint.cjs")) {
128
+ config = await (requireConfig(fs, dirname, basename, noRequire)());
129
+ }
130
+ return options || { config };
131
+ };
132
+
133
+ // Filter a list of files to ignore by glob
134
+ const removeIgnoredFiles = (dir, files, ignores) => {
135
+ const micromatch = require("micromatch");
136
+ return micromatch(
137
+ files.map((file) => path.posix.relative(dir, file)),
138
+ ignores
139
+ ).map((file) => path.posix.join(dir, file));
140
+ };
141
+
142
+ // Process/normalize command-line arguments and return glob patterns
96
143
  const processArgv = (argv) => {
97
144
  const globPatterns = (argv || []).map(
98
- (glob) => glob.replace(/^#/u, "!").replace(/\\(?![$()*+?[\]^])/gu, "/")
145
+ (glob) => {
146
+ if (glob.startsWith(":")) {
147
+ return glob;
148
+ }
149
+ // Escape RegExp special characters recognized by fast-glob
150
+ // https://github.com/mrmlnc/fast-glob#advanced-syntax
151
+ const specialCharacters = /\\(?![$()*+?[\]^])/gu;
152
+ if (glob.startsWith("\\:")) {
153
+ return `\\:${glob.slice(2).replace(specialCharacters, "/")}`;
154
+ }
155
+ return (glob.startsWith("#") ? `!${glob.slice(1)}` : glob).
156
+ replace(specialCharacters, "/");
157
+ }
99
158
  );
100
159
  if ((globPatterns.length === 1) && (globPatterns[0] === ".")) {
101
160
  // Substitute a more reasonable pattern
@@ -106,31 +165,33 @@ const processArgv = (argv) => {
106
165
 
107
166
  // Show help if missing arguments
108
167
  const showHelp = (logMessage) => {
109
- const { name, homepage } = require("./package.json");
110
168
  /* eslint-disable max-len */
111
- logMessage(`${homepage}
169
+ logMessage(`https://github.com/DavidAnson/markdownlint-cli2
112
170
 
113
- Syntax: ${name} glob0 [glob1] [...] [globN]
171
+ Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN]
172
+ markdownlint-cli2-fix glob0 [glob1] [...] [globN]
173
+ markdownlint-cli2-config config-file glob0 [glob1] [...] [globN]
114
174
 
115
175
  Glob expressions (from the globby library):
116
176
  - * matches any number of characters, but not /
117
177
  - ? matches a single character, but not /
118
- - ** matches any number of characters, including / (when it's the only thing in a path part)
178
+ - ** matches any number of characters, including /
119
179
  - {} allows for a comma-separated list of "or" expressions
120
180
  - ! or # at the beginning of a pattern negate the match
181
+ - : at the beginning identifies a literal file path
121
182
 
122
183
  Dot-only glob:
123
- - The command "${name} ." would lint every file in the current directory tree which is probably not intended
124
- - Instead, it is mapped to "${name} ${dotOnlySubstitute}" which lints all Markdown files in the current directory
125
- - To lint every file in the current directory tree, the command "${name} **" can be used instead
184
+ - The command "markdownlint-cli2 ." would lint every file in the current directory tree which is probably not intended
185
+ - Instead, it is mapped to "markdownlint-cli2 ${dotOnlySubstitute}" which lints all Markdown files in the current directory
186
+ - To lint every file in the current directory tree, the command "markdownlint-cli2 **" can be used instead
126
187
 
127
188
  Configuration via:
128
189
  - .markdownlint-cli2.jsonc
129
190
  - .markdownlint-cli2.yaml
130
- - .markdownlint-cli2.js
191
+ - .markdownlint-cli2.cjs
131
192
  - .markdownlint.jsonc or .markdownlint.json
132
193
  - .markdownlint.yaml or .markdownlint.yml
133
- - .markdownlint.js
194
+ - .markdownlint.cjs
134
195
 
135
196
  Cross-platform compatibility:
136
197
  - UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
@@ -139,8 +200,8 @@ Cross-platform compatibility:
139
200
  - Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
140
201
  - The path separator is forward slash (/) on all platforms; backslash (\\) is automatically converted
141
202
 
142
- Therefore, the most compatible glob syntax for cross-platform support:
143
- $ ${name} "**/*.md" "#node_modules"`
203
+ The most compatible syntax for cross-platform support:
204
+ $ markdownlint-cli2 "**/*.md" "#node_modules"`
144
205
  );
145
206
  /* eslint-enable max-len */
146
207
  };
@@ -169,7 +230,10 @@ const getAndProcessDirInfo =
169
230
  then(
170
231
  () => fs.promises.
171
232
  readFile(markdownlintCli2Jsonc, utf8).
172
- then(jsoncParse),
233
+ then(
234
+ (content) => getJsoncParse().
235
+ then((jsoncParse) => jsoncParse(content))
236
+ ),
173
237
  () => fs.promises.access(markdownlintCli2Yaml).
174
238
  then(
175
239
  () => fs.promises.
@@ -178,7 +242,7 @@ const getAndProcessDirInfo =
178
242
  requireConfig(
179
243
  fs,
180
244
  dir,
181
- ".markdownlint-cli2.js",
245
+ ".markdownlint-cli2.cjs",
182
246
  noRequire
183
247
  )
184
248
  )
@@ -209,7 +273,7 @@ const getAndProcessDirInfo =
209
273
  requireConfig(
210
274
  fs,
211
275
  dir,
212
- ".markdownlint.js",
276
+ ".markdownlint.cjs",
213
277
  noRequire
214
278
  )
215
279
  )
@@ -270,7 +334,8 @@ const getBaseOptions = async (
270
334
 
271
335
  // Enumerate files from globs and build directory infos
272
336
  const enumerateFiles =
273
- async (fs, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
337
+ // eslint-disable-next-line max-len
338
+ async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
274
339
  const tasks = [];
275
340
  const globbyOptions = {
276
341
  "absolute": true,
@@ -281,13 +346,38 @@ async (fs, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
281
346
  if (noErrors) {
282
347
  globbyOptions.suppressErrors = true;
283
348
  }
349
+ // Special-case literal files
350
+ const literalFiles = [];
351
+ const filteredGlobPatterns = globPatterns.filter(
352
+ (globPattern) => {
353
+ if (globPattern.startsWith(":")) {
354
+ literalFiles.push(
355
+ posixPath(path.resolve(baseDirSystem, globPattern.slice(1)))
356
+ );
357
+ return false;
358
+ }
359
+ return true;
360
+ }
361
+ ).map((globPattern) => globPattern.replace(/^\\:/u, ":"));
362
+ const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions;
363
+ const globsForIgnore =
364
+ (baseMarkdownlintOptions.globs || []).
365
+ filter((glob) => glob.startsWith("!"));
366
+ const filteredLiteralFiles =
367
+ ((literalFiles.length > 0) && (globsForIgnore.length > 0))
368
+ ? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore)
369
+ : literalFiles;
284
370
  // Manually expand directories to avoid globby call to dir-glob.sync
285
371
  const expandedDirectories = await Promise.all(
286
- globPatterns.map((globPattern) => {
287
- const globPath = path.posix.join(
288
- baseDir,
289
- globPattern[0] === "!" ? globPattern.slice(1) : globPattern
290
- );
372
+ filteredGlobPatterns.map((globPattern) => {
373
+ const barePattern =
374
+ globPattern.startsWith("!")
375
+ ? globPattern.slice(1)
376
+ : globPattern;
377
+ const globPath =
378
+ (path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern))
379
+ ? barePattern
380
+ : path.posix.join(baseDir, barePattern);
291
381
  return fs.promises.stat(globPath).
292
382
  then((stats) => (stats.isDirectory()
293
383
  ? path.posix.join(globPattern, "**")
@@ -296,7 +386,13 @@ async (fs, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
296
386
  })
297
387
  );
298
388
  // Process glob patterns
299
- const files = await globby(expandedDirectories, globbyOptions);
389
+ // eslint-disable-next-line max-len
390
+ // eslint-disable-next-line no-inline-comments, node/no-unsupported-features/es-syntax
391
+ const { globby } = await import(/* webpackMode: "eager" */ "globby");
392
+ const files = [
393
+ ...await globby(expandedDirectories, globbyOptions),
394
+ ...filteredLiteralFiles
395
+ ];
300
396
  for (const file of files) {
301
397
  const dir = path.posix.dirname(file);
302
398
  getAndProcessDirInfo(
@@ -360,9 +456,10 @@ const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => {
360
456
  // Create directory info objects by enumerating file globs
361
457
  const createDirInfos =
362
458
  // eslint-disable-next-line max-len
363
- async (fs, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => {
459
+ async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => {
364
460
  await enumerateFiles(
365
461
  fs,
462
+ baseDirSystem,
366
463
  baseDir,
367
464
  globPatterns,
368
465
  dirToDirInfo,
@@ -494,11 +591,7 @@ const lintFiles = (fs, dirInfos, fileContents) => {
494
591
  ) {
495
592
  // eslint-disable-next-line unicorn/no-array-callback-reference
496
593
  const ignores = markdownlintOptions.ignores.map(negateGlob);
497
- const micromatch = require("micromatch");
498
- filesAfterIgnores = micromatch(
499
- files.map((file) => path.posix.relative(dir, file)),
500
- ignores
501
- ).map((file) => path.posix.join(dir, file));
594
+ filesAfterIgnores = removeIgnoredFiles(dir, files, ignores);
502
595
  }
503
596
  const filteredFiles = filesAfterIgnores.filter(
504
597
  (file) => fileContents[file] === undefined
@@ -629,7 +722,8 @@ const main = async (params) => {
629
722
  nonFileContents,
630
723
  noErrors,
631
724
  noGlobs,
632
- noRequire
725
+ noRequire,
726
+ name
633
727
  } = params;
634
728
  const logMessage = params.logMessage || noop;
635
729
  const logError = params.logError || noop;
@@ -640,16 +734,24 @@ const main = async (params) => {
640
734
  const baseDir = posixPath(baseDirSystem);
641
735
  // Output banner
642
736
  logMessage(
643
- `${packageName} v${packageVersion} (${libraryName} v${libraryVersion})`
737
+ // eslint-disable-next-line max-len
738
+ `${name || packageName} v${packageVersion} (${libraryName} v${libraryVersion})`
644
739
  );
740
+ // Read argv configuration file (if relevant and present)
741
+ let optionsArgv = null;
742
+ const [ configPath ] = (argv || []);
743
+ if ((name === "markdownlint-cli2-config") && configPath) {
744
+ optionsArgv =
745
+ await readOptionsOrConfig(configPath, fs, noRequire);
746
+ }
645
747
  // Process arguments and get base options
646
- const globPatterns = processArgv(argv);
748
+ const globPatterns = processArgv(optionsArgv ? argv.slice(1) : argv);
647
749
  const { baseMarkdownlintOptions, dirToDirInfo } =
648
750
  await getBaseOptions(
649
751
  fs,
650
752
  baseDir,
651
753
  globPatterns,
652
- optionsDefault,
754
+ optionsArgv || optionsDefault,
653
755
  fixDefault,
654
756
  noGlobs,
655
757
  noRequire
@@ -681,6 +783,7 @@ const main = async (params) => {
681
783
  const dirInfos =
682
784
  await createDirInfos(
683
785
  fs,
786
+ baseDirSystem,
684
787
  baseDir,
685
788
  globPatterns,
686
789
  dirToDirInfo,
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "markdownlint-cli2",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
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
+ "type": "commonjs",
10
11
  "main": "markdownlint-cli2.js",
11
12
  "bin": {
12
13
  "markdownlint-cli2": "markdownlint-cli2.js",
14
+ "markdownlint-cli2-config": "markdownlint-cli2-config.js",
13
15
  "markdownlint-cli2-fix": "markdownlint-cli2-fix.js"
14
16
  },
15
17
  "homepage": "https://github.com/DavidAnson/markdownlint-cli2",
@@ -21,15 +23,19 @@
21
23
  "scripts": {
22
24
  "build-docker-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker build -t davidanson/markdownlint-cli2:$VERSION -f docker/Dockerfile .",
23
25
  "ci": "npm-run-all --continue-on-error --parallel test-cover lint",
26
+ "docker-npm-install": "docker run --rm --tty --name npm-install --volume $PWD:/home/workdir --workdir /home/workdir --user node node:16 npm install",
27
+ "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
28
  "lint": "eslint --max-warnings 0 .",
25
29
  "lint-dockerfile": "docker run --rm -i hadolint/hadolint:latest-alpine < docker/Dockerfile",
26
30
  "lint-watch": "git ls-files | entr npm run lint",
27
31
  "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:$VERSION -t davidanson/markdownlint-cli2:latest -f docker/Dockerfile --push .",
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",
32
+ "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",
29
33
  "test-docker-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2:$VERSION \"*.md\"",
30
34
  "test-docker-hub-image": "VERSION=$(node -e \"process.stdout.write(require('./package.json').version)\") && docker image rm davidanson/markdownlint-cli2:$VERSION davidanson/markdownlint-cli2:latest || true && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2:$VERSION \"*.md\" && docker run --rm -v $PWD:/workdir davidanson/markdownlint-cli2:latest \"*.md\"",
31
35
  "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"
36
+ "test-watch": "git ls-files | entr npm run test",
37
+ "update-snapshots": "ava --update-snapshots test/markdownlint-cli2-test-exec.js test/markdownlint-cli2-test-fs.js test/markdownlint-cli2-test-main.js",
38
+ "upgrade": "npx --yes npm-check-updates --upgrade"
33
39
  },
34
40
  "engines": {
35
41
  "node": ">=12"
@@ -37,37 +43,39 @@
37
43
  "files": [
38
44
  "append-to-array.js",
39
45
  "markdownlint-cli2.js",
46
+ "markdownlint-cli2-config.js",
40
47
  "markdownlint-cli2-fix.js",
41
48
  "merge-options.js",
42
49
  "resolve-and-require.js"
43
50
  ],
44
51
  "dependencies": {
45
- "globby": "~11.0.4",
46
- "markdownlint": "~0.24.0",
47
- "markdownlint-cli2-formatter-default": "^0.0.2",
48
- "markdownlint-rule-helpers": "~0.15.0",
49
- "micromatch": "~4.0.4",
50
- "strip-json-comments": "~3.1.1",
51
- "yaml": "~1.10.2"
52
+ "globby": "12.1.0",
53
+ "markdownlint": "0.25.1",
54
+ "markdownlint-cli2-formatter-default": "0.0.3",
55
+ "markdownlint-rule-helpers": "0.16.0",
56
+ "micromatch": "4.0.4",
57
+ "strip-json-comments": "4.0.0",
58
+ "yaml": "1.10.2"
52
59
  },
53
60
  "devDependencies": {
54
- "@iktakahiro/markdown-it-katex": "~4.0.1",
55
- "ava": "~3.15.0",
56
- "c8": "~7.8.0",
57
- "cpy": "~8.1.2",
58
- "del": "~6.0.0",
59
- "eslint": "~7.32.0",
60
- "eslint-plugin-node": "~11.1.0",
61
- "eslint-plugin-unicorn": "~35.0.0",
62
- "execa": "~5.1.1",
63
- "markdown-it-emoji": "~2.0.0",
64
- "markdown-it-for-inline": "~0.1.1",
65
- "markdownlint-cli2-formatter-json": "^0.0.4",
66
- "markdownlint-cli2-formatter-junit": "^0.0.3",
67
- "markdownlint-cli2-formatter-pretty": "^0.0.2",
68
- "markdownlint-cli2-formatter-summarize": "^0.0.3",
69
- "markdownlint-rule-titlecase": "~0.1.0",
70
- "npm-run-all": "~4.1.5"
61
+ "@iktakahiro/markdown-it-katex": "4.0.1",
62
+ "ava": "4.0.1",
63
+ "c8": "7.11.0",
64
+ "cpy": "8.1.2",
65
+ "del": "6.0.0",
66
+ "eslint": "8.6.0",
67
+ "eslint-plugin-node": "11.1.0",
68
+ "eslint-plugin-unicorn": "40.0.0",
69
+ "execa": "6.0.0",
70
+ "markdown-it-emoji": "2.0.0",
71
+ "markdown-it-for-inline": "0.1.1",
72
+ "markdownlint-cli2-formatter-json": "0.0.5",
73
+ "markdownlint-cli2-formatter-junit": "0.0.4",
74
+ "markdownlint-cli2-formatter-pretty": "0.0.3",
75
+ "markdownlint-cli2-formatter-summarize": "0.0.5",
76
+ "markdownlint-rule-github-internal-links": "0.1.0",
77
+ "markdownlint-rule-titlecase": "0.1.0",
78
+ "npm-run-all": "4.1.5"
71
79
  },
72
80
  "keywords": [
73
81
  "markdown",
@@ -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 {Object} req Node's require function (or equivalent).
9
- * @param {*} id Package identifier to require.
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) => {