markdownlint-cli2 0.6.0 → 0.7.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2022 David Anson
3
+ Copyright (c) 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
@@ -37,7 +37,7 @@ As a [GitHub Action][github-action] via
37
37
 
38
38
  ```yaml
39
39
  - name: markdownlint-cli2-action
40
- uses: DavidAnson/markdownlint-cli2-action
40
+ uses: DavidAnson/markdownlint-cli2-action@v9
41
41
  ```
42
42
 
43
43
  ## Overview
@@ -145,7 +145,7 @@ A container image [`davidanson/markdownlint-cli2`][docker-hub-markdownlint-cli2]
145
145
  can also be used (e.g., as part of a CI pipeline):
146
146
 
147
147
  ```bash
148
- docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.6.0 "**/*.md" "#node_modules"
148
+ docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.7.1 "**/*.md" "#node_modules"
149
149
  ```
150
150
 
151
151
  Notes:
@@ -162,16 +162,25 @@ Notes:
162
162
  - A custom working directory can be specified with Docker's `-w` flag:
163
163
 
164
164
  ```bash
165
- docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.6.0 "**/*.md" "#node_modules"
165
+ docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.7.1 "**/*.md" "#node_modules"
166
166
  ```
167
167
 
168
168
  To invoke the `markdownlint-cli2-config` or `markdownlint-cli2-fix` commands
169
169
  instead, use Docker's `--entrypoint` flag:
170
170
 
171
171
  ```bash
172
- docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:v0.6.0 "**/*.md" "#node_modules"
172
+ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/markdownlint-cli2:v0.7.1 "**/*.md" "#node_modules"
173
173
  ```
174
174
 
175
+ For convenience, the container image
176
+ [`davidanson/markdownlint-cli2-rules`][docker-hub-markdownlint-cli2-rules]
177
+ includes the latest versions of custom rules published to npm with the tag
178
+ [`markdownlint-rule`][markdownlint-rule]. These rules are installed globally
179
+ onto the base image `davidanson/markdownlint-cli2`.
180
+
181
+ **Note**: This container image exists for convenience and is not an endorsement
182
+ of the rules within.
183
+
175
184
  ### Exit Codes
176
185
 
177
186
  - `0`: Linting was successful and there were no errors
@@ -193,11 +202,20 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
193
202
  - See the [Configuration][markdownlint-configuration] section of the
194
203
  `markdownlint` documentation for information about the inline comment syntax
195
204
  for enabling and disabling rules with HTML comments.
196
- - In general, glob expressions match files under the current directory and the
197
- configuration for that directory applies to the entire tree.
205
+ - In general, glob expressions should match files under the current directory;
206
+ the configuration for that directory will apply to the entire tree.
198
207
  - When glob expressions match files *not* under the current directory,
199
208
  configuration for the current directory is applied to the closest common
200
209
  parent directory.
210
+ - There are two kinds of configuration file (both detailed below):
211
+ - Configuration files like `.markdownlint-cli2.*` allow complete control of
212
+ `markdownlint-cli2` behavior and are also used by `vscode-markdownlint`.
213
+ - Configuration files like `.markdownlint.*` allow control over only the
214
+ `markdownlint` `config` object and tend to be supported more broadly (such
215
+ as by `markdownlint-cli`).
216
+ - The VS Code extension `vscode-markdownlint` includes a schema definition for
217
+ the `JSON(C)` configuration files described below. This adds auto-complete and
218
+ can make it easier to define proper structure.
201
219
 
202
220
  ### `.markdownlint-cli2.jsonc`
203
221
 
@@ -208,6 +226,8 @@ docker run -v $PWD:/workdir --entrypoint="markdownlint-cli2-fix" davidanson/mark
208
226
  rules for this part of the directory tree
209
227
  - If a `.markdownlint.{jsonc,json,yaml,yml,js}` file (see below) is present
210
228
  in the same directory, it overrides the value of this property
229
+ - If the `config` object contains an `extends` property, it will be resolved
230
+ the same as `.markdownlint.{jsonc,json,yaml,yml,js}` (see below)
211
231
  - `customRules`: `Array` of `String`s (or `Array`s of `String`s) of module
212
232
  names/paths of [custom rules][markdownlint-custom-rules] to load and use
213
233
  when linting
@@ -358,7 +378,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
358
378
 
359
379
  ```yaml
360
380
  - repo: https://github.com/DavidAnson/markdownlint-cli2
361
- rev: v0.6.0
381
+ rev: v0.7.1
362
382
  hooks:
363
383
  - id: markdownlint-cli2
364
384
  ```
@@ -368,32 +388,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
368
388
 
369
389
  ## History
370
390
 
371
- - 0.0.2 - Initial release
372
- - 0.0.3 - Feature parity with `markdownlint-cli`
373
- - 0.0.4 - Support output formatters and `markdown-it` plugins
374
- - 0.0.5 - Improve support for ignoring files
375
- - 0.0.6 - Improve handling of very large directory trees
376
- - 0.0.7 - Support `.markdownlint-cli2.js` and `.markdownlint.js`
377
- - 0.0.8 - Support `.markdownlint-cli2.yaml`, add progress
378
- - 0.0.9 - Improve configuration file handling
379
- - 0.0.10 - Improve performance and configuration
380
- - 0.0.11 - Improve performance of `fix`, update banner
381
- - 0.0.12 - Update dependencies (including `markdownlint`)
382
- - 0.0.13 - Add `markdownlint-cli2-fix` command
383
- - 0.0.14 - Update dependencies (including `markdownlint`)
384
- - 0.0.15 - Improve extensibility
385
- - 0.1.0 - Simplify use of `require`, increment minor version
386
- - 0.1.1 - Restore previous use of `require`
387
- - 0.1.2 - Update use of `require` to be more flexible
388
- - 0.1.3 - Support rule collections
389
- - 0.2.0 - Improve handling of Windows paths using backslash
390
- - 0.3.0 - Add Docker container, update dependencies
391
- - 0.3.1 - Extensibility tweaks
392
- - 0.3.2 - Extensibility/Windows/consistency improvements
393
- - 0.4.0 - New rules, async custom rules, explicit config, CJS (breaking)
394
- - 0.5.0 - New rules, support modules (MJS) everywhere, include dotfiles
395
- - 0.5.1 - Update dependencies
396
- - 0.6.0 - Update dependencies (including `markdownlint`)
391
+ See [CHANGELOG.md](CHANGELOG.md).
397
392
 
398
393
  <!-- markdownlint-disable line-length -->
399
394
 
@@ -403,6 +398,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
403
398
  [docker]: https://www.docker.com
404
399
  [docker-bind-mounts]: https://docs.docker.com/storage/bind-mounts/
405
400
  [docker-hub-markdownlint-cli2]: https://hub.docker.com/r/davidanson/markdownlint-cli2
401
+ [docker-hub-markdownlint-cli2-rules]: https://hub.docker.com/r/davidanson/markdownlint-cli2-rules
406
402
  [front-matter]: https://jekyllrb.com/docs/frontmatter/
407
403
  [github-action]: https://docs.github.com/actions
408
404
  [globby]: https://www.npmjs.com/package/globby
@@ -0,0 +1,5 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ module.exports = require("markdownlint/helpers");
@@ -0,0 +1,5 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ module.exports = require("markdownlint");
@@ -13,8 +13,11 @@ const dynamicRequire = (typeof __non_webpack_require__ === "undefined") ? requir
13
13
  const path = require("node:path");
14
14
  const { pathToFileURL } = require("node:url");
15
15
  const markdownlintLibrary = require("markdownlint");
16
- const { markdownlint, "readConfig": markdownlintReadConfig } =
17
- markdownlintLibrary.promises;
16
+ const {
17
+ markdownlint,
18
+ "extendConfig": markdownlintExtendConfig,
19
+ "readConfig": markdownlintReadConfig
20
+ } = markdownlintLibrary.promises;
18
21
  const markdownlintRuleHelpers = require("markdownlint/helpers");
19
22
  const appendToArray = require("./append-to-array");
20
23
  const mergeOptions = require("./merge-options");
@@ -22,7 +25,7 @@ const resolveAndRequire = require("./resolve-and-require");
22
25
 
23
26
  // Variables
24
27
  const packageName = "markdownlint-cli2";
25
- const packageVersion = "0.6.0";
28
+ const packageVersion = "0.7.1";
26
29
  const libraryName = "markdownlint";
27
30
  const libraryVersion = markdownlintLibrary.getVersion();
28
31
  const dotOnlySubstitute = "*.{md,markdown}";
@@ -242,105 +245,121 @@ $ markdownlint-cli2 "**/*.md" "#node_modules"`
242
245
 
243
246
  // Get (creating if necessary) and process a directory's info object
244
247
  const getAndProcessDirInfo =
245
- (fs, tasks, dirToDirInfo, dir, relativeDir, noRequire, func) => {
246
- let dirInfo = dirToDirInfo[dir];
247
- if (!dirInfo) {
248
- dirInfo = {
249
- dir,
250
- relativeDir,
251
- "parent": null,
252
- "files": [],
253
- "markdownlintConfig": null,
254
- "markdownlintOptions": null
255
- };
256
- dirToDirInfo[dir] = dirInfo;
257
-
258
- // Load markdownlint-cli2 object(s)
259
- const markdownlintCli2Jsonc =
260
- path.posix.join(dir, ".markdownlint-cli2.jsonc");
261
- const markdownlintCli2Yaml =
262
- path.posix.join(dir, ".markdownlint-cli2.yaml");
263
- tasks.push(
264
- fs.promises.access(markdownlintCli2Jsonc).
265
- then(
266
- () => fs.promises.
267
- readFile(markdownlintCli2Jsonc, utf8).
268
- then(
269
- (content) => getJsoncParse().
270
- then((jsoncParse) => jsoncParse(content))
271
- ),
272
- () => fs.promises.access(markdownlintCli2Yaml).
273
- then(
274
- () => fs.promises.
275
- readFile(markdownlintCli2Yaml, utf8).
276
- then(yamlParse),
277
- importOrRequireConfig(
278
- fs,
279
- dir,
280
- ".markdownlint-cli2.cjs",
281
- noRequire,
248
+ (fs, tasks, dirToDirInfo, dir, relativeDir, noRequire, func) => {
249
+ let dirInfo = dirToDirInfo[dir];
250
+ if (!dirInfo) {
251
+ dirInfo = {
252
+ dir,
253
+ relativeDir,
254
+ "parent": null,
255
+ "files": [],
256
+ "markdownlintConfig": null,
257
+ "markdownlintOptions": null
258
+ };
259
+ dirToDirInfo[dir] = dirInfo;
260
+
261
+ // Load markdownlint-cli2 object(s)
262
+ const markdownlintCli2Jsonc =
263
+ path.posix.join(dir, ".markdownlint-cli2.jsonc");
264
+ const markdownlintCli2Yaml =
265
+ path.posix.join(dir, ".markdownlint-cli2.yaml");
266
+ tasks.push(
267
+ fs.promises.access(markdownlintCli2Jsonc).
268
+ then(
269
+ () => fs.promises.
270
+ readFile(markdownlintCli2Jsonc, utf8).
271
+ then(
272
+ (content) => getJsoncParse().
273
+ then((jsoncParse) => jsoncParse(content))
274
+ ),
275
+ () => fs.promises.access(markdownlintCli2Yaml).
276
+ then(
277
+ () => fs.promises.
278
+ readFile(markdownlintCli2Yaml, utf8).
279
+ then(yamlParse),
282
280
  importOrRequireConfig(
283
281
  fs,
284
282
  dir,
285
- ".markdownlint-cli2.mjs",
283
+ ".markdownlint-cli2.cjs",
286
284
  noRequire,
287
- noop
285
+ importOrRequireConfig(
286
+ fs,
287
+ dir,
288
+ ".markdownlint-cli2.mjs",
289
+ noRequire,
290
+ noop
291
+ )
288
292
  )
289
293
  )
290
- )
291
- ).
292
- then((options) => {
293
- dirInfo.markdownlintOptions = options;
294
- })
295
- );
294
+ ).
295
+ then((options) => {
296
+ dirInfo.markdownlintOptions = options;
297
+ return options &&
298
+ options.config &&
299
+ options.config.extends &&
300
+ getJsoncParse().
301
+ then(
302
+ (jsoncParse) => markdownlintExtendConfig(
303
+ options.config,
304
+ // Just needs to identify a file in the right directory
305
+ markdownlintCli2Jsonc,
306
+ [ jsoncParse, yamlParse ],
307
+ fs
308
+ )
309
+ ).
310
+ then((config) => {
311
+ options.config = config;
312
+ });
313
+ })
314
+ );
296
315
 
297
- // Load markdownlint object(s)
298
- const readConfigs =
299
- readConfig(
300
- fs,
301
- dir,
302
- ".markdownlint.jsonc",
316
+ // Load markdownlint object(s)
317
+ const readConfigs =
303
318
  readConfig(
304
319
  fs,
305
320
  dir,
306
- ".markdownlint.json",
321
+ ".markdownlint.jsonc",
307
322
  readConfig(
308
323
  fs,
309
324
  dir,
310
- ".markdownlint.yaml",
325
+ ".markdownlint.json",
311
326
  readConfig(
312
327
  fs,
313
328
  dir,
314
- ".markdownlint.yml",
315
- importOrRequireConfig(
329
+ ".markdownlint.yaml",
330
+ readConfig(
316
331
  fs,
317
332
  dir,
318
- ".markdownlint.cjs",
319
- noRequire,
333
+ ".markdownlint.yml",
320
334
  importOrRequireConfig(
321
335
  fs,
322
336
  dir,
323
- ".markdownlint.mjs",
337
+ ".markdownlint.cjs",
324
338
  noRequire,
325
- noop
339
+ importOrRequireConfig(
340
+ fs,
341
+ dir,
342
+ ".markdownlint.mjs",
343
+ noRequire,
344
+ noop
345
+ )
326
346
  )
327
347
  )
328
348
  )
329
349
  )
330
- )
350
+ );
351
+ tasks.push(
352
+ readConfigs().
353
+ then((config) => {
354
+ dirInfo.markdownlintConfig = config;
355
+ })
331
356
  );
332
- tasks.push(
333
- readConfigs().
334
- then((config) => {
335
- dirInfo.markdownlintConfig = config;
336
- })
337
- );
338
- }
339
- if (func) {
340
- func(dirInfo);
341
- }
342
- return dirInfo;
343
- };
357
+ }
358
+ if (func) {
359
+ func(dirInfo);
360
+ }
361
+ return dirInfo;
362
+ };
344
363
 
345
364
  // Get base markdownlint-cli2 options object
346
365
  const getBaseOptions = async (
@@ -367,7 +386,10 @@ const getBaseOptions = async (
367
386
  // eslint-disable-next-line no-multi-assign
368
387
  const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions =
369
388
  mergeOptions(
370
- mergeOptions(options, { "fix": fixDefault }),
389
+ mergeOptions(
390
+ { "fix": fixDefault },
391
+ options
392
+ ),
371
393
  dirToDirInfo[baseDir].markdownlintOptions
372
394
  );
373
395
 
@@ -391,81 +413,81 @@ const getBaseOptions = async (
391
413
 
392
414
  // Enumerate files from globs and build directory infos
393
415
  const enumerateFiles =
394
- // eslint-disable-next-line max-len
395
- async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
396
- const tasks = [];
397
- const globbyOptions = {
398
- "absolute": true,
399
- "cwd": baseDir,
400
- "dot": true,
401
- "expandDirectories": false,
402
- fs
403
- };
404
- if (noErrors) {
405
- globbyOptions.suppressErrors = true;
406
- }
407
- // Special-case literal files
408
- const literalFiles = [];
409
- const filteredGlobPatterns = globPatterns.filter(
410
- (globPattern) => {
411
- if (globPattern.startsWith(":")) {
412
- literalFiles.push(
413
- posixPath(path.resolve(baseDirSystem, globPattern.slice(1)))
414
- );
415
- return false;
416
- }
417
- return true;
416
+ // eslint-disable-next-line max-len
417
+ async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, noErrors, noRequire) => {
418
+ const tasks = [];
419
+ const globbyOptions = {
420
+ "absolute": true,
421
+ "cwd": baseDir,
422
+ "dot": true,
423
+ "expandDirectories": false,
424
+ fs
425
+ };
426
+ if (noErrors) {
427
+ globbyOptions.suppressErrors = true;
418
428
  }
419
- ).map((globPattern) => globPattern.replace(/^\\:/u, ":"));
420
- const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions;
421
- const globsForIgnore =
422
- (baseMarkdownlintOptions.globs || []).
423
- filter((glob) => glob.startsWith("!"));
424
- const filteredLiteralFiles =
425
- ((literalFiles.length > 0) && (globsForIgnore.length > 0))
426
- ? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore)
427
- : literalFiles;
428
- // Manually expand directories to avoid globby call to dir-glob.sync
429
- const expandedDirectories = await Promise.all(
430
- filteredGlobPatterns.map((globPattern) => {
431
- const barePattern =
432
- globPattern.startsWith("!")
433
- ? globPattern.slice(1)
434
- : globPattern;
435
- const globPath =
436
- (path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern))
437
- ? barePattern
438
- : path.posix.join(baseDir, barePattern);
439
- return fs.promises.stat(globPath).
440
- then((stats) => (stats.isDirectory()
441
- ? path.posix.join(globPattern, "**")
442
- : globPattern)).
443
- catch(() => globPattern);
444
- })
445
- );
446
- // Process glob patterns
447
- // eslint-disable-next-line no-inline-comments
448
- const { globby } = await import(/* webpackMode: "eager" */ "globby");
449
- const files = [
450
- ...await globby(expandedDirectories, globbyOptions),
451
- ...filteredLiteralFiles
452
- ];
453
- for (const file of files) {
454
- const dir = path.posix.dirname(file);
455
- getAndProcessDirInfo(
456
- fs,
457
- tasks,
458
- dirToDirInfo,
459
- dir,
460
- null,
461
- noRequire,
462
- (dirInfo) => {
463
- dirInfo.files.push(file);
429
+ // Special-case literal files
430
+ const literalFiles = [];
431
+ const filteredGlobPatterns = globPatterns.filter(
432
+ (globPattern) => {
433
+ if (globPattern.startsWith(":")) {
434
+ literalFiles.push(
435
+ posixPath(path.resolve(baseDirSystem, globPattern.slice(1)))
436
+ );
437
+ return false;
438
+ }
439
+ return true;
464
440
  }
441
+ ).map((globPattern) => globPattern.replace(/^\\:/u, ":"));
442
+ const baseMarkdownlintOptions = dirToDirInfo[baseDir].markdownlintOptions;
443
+ const globsForIgnore =
444
+ (baseMarkdownlintOptions.globs || []).
445
+ filter((glob) => glob.startsWith("!"));
446
+ const filteredLiteralFiles =
447
+ ((literalFiles.length > 0) && (globsForIgnore.length > 0))
448
+ ? removeIgnoredFiles(baseDir, literalFiles, globsForIgnore)
449
+ : literalFiles;
450
+ // Manually expand directories to avoid globby call to dir-glob.sync
451
+ const expandedDirectories = await Promise.all(
452
+ filteredGlobPatterns.map((globPattern) => {
453
+ const barePattern =
454
+ globPattern.startsWith("!")
455
+ ? globPattern.slice(1)
456
+ : globPattern;
457
+ const globPath =
458
+ (path.posix.isAbsolute(barePattern) || path.isAbsolute(barePattern))
459
+ ? barePattern
460
+ : path.posix.join(baseDir, barePattern);
461
+ return fs.promises.stat(globPath).
462
+ then((stats) => (stats.isDirectory()
463
+ ? path.posix.join(globPattern, "**")
464
+ : globPattern)).
465
+ catch(() => globPattern);
466
+ })
465
467
  );
466
- }
467
- await Promise.all(tasks);
468
- };
468
+ // Process glob patterns
469
+ // eslint-disable-next-line no-inline-comments
470
+ const { globby } = await import(/* webpackMode: "eager" */ "globby");
471
+ const files = [
472
+ ...await globby(expandedDirectories, globbyOptions),
473
+ ...filteredLiteralFiles
474
+ ];
475
+ for (const file of files) {
476
+ const dir = path.posix.dirname(file);
477
+ getAndProcessDirInfo(
478
+ fs,
479
+ tasks,
480
+ dirToDirInfo,
481
+ dir,
482
+ null,
483
+ noRequire,
484
+ (dirInfo) => {
485
+ dirInfo.files.push(file);
486
+ }
487
+ );
488
+ }
489
+ await Promise.all(tasks);
490
+ };
469
491
 
470
492
  // Enumerate (possibly missing) parent directories and update directory infos
471
493
  const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => {
@@ -514,135 +536,135 @@ const enumerateParents = async (fs, baseDir, dirToDirInfo, noRequire) => {
514
536
 
515
537
  // Create directory info objects by enumerating file globs
516
538
  const createDirInfos =
517
- // eslint-disable-next-line max-len
518
- async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => {
519
- await enumerateFiles(
520
- fs,
521
- baseDirSystem,
522
- baseDir,
523
- globPatterns,
524
- dirToDirInfo,
525
- noErrors,
526
- noRequire
527
- );
528
- await enumerateParents(
529
- fs,
530
- baseDir,
531
- dirToDirInfo,
532
- noRequire
533
- );
534
-
535
- // Merge file lists with identical configuration
536
- const dirs = Object.keys(dirToDirInfo);
537
- dirs.sort((a, b) => b.length - a.length);
538
- const dirInfos = [];
539
- const noConfigDirInfo =
540
- // eslint-disable-next-line unicorn/consistent-function-scoping
541
- (dirInfo) => (
542
- dirInfo.parent &&
543
- !dirInfo.markdownlintConfig &&
544
- !dirInfo.markdownlintOptions
539
+ // eslint-disable-next-line max-len
540
+ async (fs, baseDirSystem, baseDir, globPatterns, dirToDirInfo, optionsOverride, noErrors, noRequire) => {
541
+ await enumerateFiles(
542
+ fs,
543
+ baseDirSystem,
544
+ baseDir,
545
+ globPatterns,
546
+ dirToDirInfo,
547
+ noErrors,
548
+ noRequire
545
549
  );
546
- const tasks = [];
547
- for (const dir of dirs) {
548
- const dirInfo = dirToDirInfo[dir];
549
- if (noConfigDirInfo(dirInfo)) {
550
- if (dirInfo.parent) {
551
- appendToArray(dirInfo.parent.files, dirInfo.files);
552
- }
553
- dirToDirInfo[dir] = null;
554
- } else {
555
- const { markdownlintOptions, relativeDir } = dirInfo;
556
- if (markdownlintOptions && markdownlintOptions.customRules) {
557
- tasks.push(
558
- importOrRequireIds(
559
- relativeDir || dir,
560
- markdownlintOptions.customRules,
561
- noRequire
562
- ).then((customRules) => {
563
- // Expand nested arrays (for packages that export multiple rules)
564
- markdownlintOptions.customRules = customRules.flat();
565
- })
566
- );
567
- }
568
- if (markdownlintOptions && markdownlintOptions.markdownItPlugins) {
569
- tasks.push(
570
- importOrRequireIdsAndParams(
571
- relativeDir || dir,
572
- markdownlintOptions.markdownItPlugins,
573
- noRequire
574
- ).then((markdownItPlugins) => {
575
- markdownlintOptions.markdownItPlugins = markdownItPlugins;
576
- })
577
- );
550
+ await enumerateParents(
551
+ fs,
552
+ baseDir,
553
+ dirToDirInfo,
554
+ noRequire
555
+ );
556
+
557
+ // Merge file lists with identical configuration
558
+ const dirs = Object.keys(dirToDirInfo);
559
+ dirs.sort((a, b) => b.length - a.length);
560
+ const dirInfos = [];
561
+ const noConfigDirInfo =
562
+ // eslint-disable-next-line unicorn/consistent-function-scoping
563
+ (dirInfo) => (
564
+ dirInfo.parent &&
565
+ !dirInfo.markdownlintConfig &&
566
+ !dirInfo.markdownlintOptions
567
+ );
568
+ const tasks = [];
569
+ for (const dir of dirs) {
570
+ const dirInfo = dirToDirInfo[dir];
571
+ if (noConfigDirInfo(dirInfo)) {
572
+ if (dirInfo.parent) {
573
+ appendToArray(dirInfo.parent.files, dirInfo.files);
574
+ }
575
+ dirToDirInfo[dir] = null;
576
+ } else {
577
+ const { markdownlintOptions, relativeDir } = dirInfo;
578
+ if (markdownlintOptions && markdownlintOptions.customRules) {
579
+ tasks.push(
580
+ importOrRequireIds(
581
+ relativeDir || dir,
582
+ markdownlintOptions.customRules,
583
+ noRequire
584
+ ).then((customRules) => {
585
+ // Expand nested arrays (for packages that export multiple rules)
586
+ markdownlintOptions.customRules = customRules.flat();
587
+ })
588
+ );
589
+ }
590
+ if (markdownlintOptions && markdownlintOptions.markdownItPlugins) {
591
+ tasks.push(
592
+ importOrRequireIdsAndParams(
593
+ relativeDir || dir,
594
+ markdownlintOptions.markdownItPlugins,
595
+ noRequire
596
+ ).then((markdownItPlugins) => {
597
+ markdownlintOptions.markdownItPlugins = markdownItPlugins;
598
+ })
599
+ );
600
+ }
601
+ dirInfos.push(dirInfo);
578
602
  }
579
- dirInfos.push(dirInfo);
580
603
  }
581
- }
582
- await Promise.all(tasks);
583
- for (const dirInfo of dirInfos) {
584
- while (dirInfo.parent && !dirToDirInfo[dirInfo.parent.dir]) {
585
- dirInfo.parent = dirInfo.parent.parent;
604
+ await Promise.all(tasks);
605
+ for (const dirInfo of dirInfos) {
606
+ while (dirInfo.parent && !dirToDirInfo[dirInfo.parent.dir]) {
607
+ dirInfo.parent = dirInfo.parent.parent;
608
+ }
586
609
  }
587
- }
588
610
 
589
- // Verify dirInfos is simplified
590
- // if (
591
- // dirInfos.filter(
592
- // (di) => di.parent && !dirInfos.includes(di.parent)
593
- // ).length > 0
594
- // ) {
595
- // throw new Error("Extra parent");
596
- // }
597
- // if (
598
- // dirInfos.filter(
599
- // (di) => !di.parent && (di.dir !== baseDir)
600
- // ).length > 0
601
- // ) {
602
- // throw new Error("Missing parent");
603
- // }
604
- // if (
605
- // dirInfos.filter(
606
- // (di) => di.parent &&
607
- // !((di.markdownlintConfig ? 1 : 0) ^ (di.markdownlintOptions ? 1 : 0))
608
- // ).length > 0
609
- // ) {
610
- // throw new Error("Missing object");
611
- // }
612
- // if (dirInfos.filter((di) => di.dir === "/").length > 0) {
613
- // throw new Error("Includes root");
614
- // }
615
-
616
- // Merge configuration by inheritance
617
- for (const dirInfo of dirInfos) {
618
- let markdownlintOptions = dirInfo.markdownlintOptions || {};
619
- let { markdownlintConfig } = dirInfo;
620
- let parent = dirInfo;
621
- // eslint-disable-next-line prefer-destructuring
622
- while ((parent = parent.parent)) {
623
- if (parent.markdownlintOptions) {
624
- markdownlintOptions = mergeOptions(
625
- parent.markdownlintOptions,
626
- markdownlintOptions
627
- );
628
- }
629
- if (
630
- !markdownlintConfig &&
631
- parent.markdownlintConfig &&
632
- !markdownlintOptions.config
633
- ) {
634
- // eslint-disable-next-line prefer-destructuring
635
- markdownlintConfig = parent.markdownlintConfig;
611
+ // Verify dirInfos is simplified
612
+ // if (
613
+ // dirInfos.filter(
614
+ // (di) => di.parent && !dirInfos.includes(di.parent)
615
+ // ).length > 0
616
+ // ) {
617
+ // throw new Error("Extra parent");
618
+ // }
619
+ // if (
620
+ // dirInfos.filter(
621
+ // (di) => !di.parent && (di.dir !== baseDir)
622
+ // ).length > 0
623
+ // ) {
624
+ // throw new Error("Missing parent");
625
+ // }
626
+ // if (
627
+ // dirInfos.filter(
628
+ // (di) => di.parent &&
629
+ // !((di.markdownlintConfig ? 1 : 0) ^ (di.markdownlintOptions ? 1 : 0))
630
+ // ).length > 0
631
+ // ) {
632
+ // throw new Error("Missing object");
633
+ // }
634
+ // if (dirInfos.filter((di) => di.dir === "/").length > 0) {
635
+ // throw new Error("Includes root");
636
+ // }
637
+
638
+ // Merge configuration by inheritance
639
+ for (const dirInfo of dirInfos) {
640
+ let markdownlintOptions = dirInfo.markdownlintOptions || {};
641
+ let { markdownlintConfig } = dirInfo;
642
+ let parent = dirInfo;
643
+ // eslint-disable-next-line prefer-destructuring
644
+ while ((parent = parent.parent)) {
645
+ if (parent.markdownlintOptions) {
646
+ markdownlintOptions = mergeOptions(
647
+ parent.markdownlintOptions,
648
+ markdownlintOptions
649
+ );
650
+ }
651
+ if (
652
+ !markdownlintConfig &&
653
+ parent.markdownlintConfig &&
654
+ !markdownlintOptions.config
655
+ ) {
656
+ // eslint-disable-next-line prefer-destructuring
657
+ markdownlintConfig = parent.markdownlintConfig;
658
+ }
636
659
  }
660
+ dirInfo.markdownlintOptions = mergeOptions(
661
+ markdownlintOptions,
662
+ optionsOverride
663
+ );
664
+ dirInfo.markdownlintConfig = markdownlintConfig;
637
665
  }
638
- dirInfo.markdownlintOptions = mergeOptions(
639
- markdownlintOptions,
640
- optionsOverride
641
- );
642
- dirInfo.markdownlintConfig = markdownlintConfig;
643
- }
644
- return dirInfos;
645
- };
666
+ return dirInfos;
667
+ };
646
668
 
647
669
  // Lint files in groups by shared configuration
648
670
  const lintFiles = async (fs, dirInfos, fileContents) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdownlint-cli2",
3
- "version": "0.6.0",
3
+ "version": "0.7.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",
@@ -9,7 +9,11 @@
9
9
  "license": "MIT",
10
10
  "type": "commonjs",
11
11
  "main": "./markdownlint-cli2.js",
12
- "exports": "./markdownlint-cli2.js",
12
+ "exports": {
13
+ ".": "./markdownlint-cli2.js",
14
+ "./markdownlint": "./export-markdownlint.js",
15
+ "./markdownlint/helpers": "./export-markdownlint-helpers.js"
16
+ },
13
17
  "bin": {
14
18
  "markdownlint-cli2": "markdownlint-cli2.js",
15
19
  "markdownlint-cli2-config": "markdownlint-cli2-config.js",
@@ -23,6 +27,7 @@
23
27
  "bugs": "https://github.com/DavidAnson/markdownlint-cli2/issues",
24
28
  "scripts": {
25
29
  "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 .",
30
+ "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 .",
26
31
  "ci": "npm-run-all --continue-on-error --parallel test-cover lint",
27
32
  "docker-npm-install": "docker run --rm --tty --name npm-install --volume $PWD:/home/workdir --workdir /home/workdir --user node node:16 npm install",
28
33
  "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 @@
32
37
  "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
38
  "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
39
  "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\"",
40
+ "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\"",
35
41
  "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\"",
42
+ "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\"",
36
43
  "test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test",
37
44
  "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",
45
+ "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",
39
46
  "upgrade": "npx --yes npm-check-updates --upgrade",
40
47
  "webworker": "cd webworker && webpack --mode none",
41
48
  "webworker-install": "npm run docker-npm-install -- --no-save path-browserify process setimmediate stream-browserify url util webpack-cli"
@@ -45,6 +52,8 @@
45
52
  },
46
53
  "files": [
47
54
  "append-to-array.js",
55
+ "export-markdownlint.js",
56
+ "export-markdownlint-helpers.js",
48
57
  "markdownlint-cli2.js",
49
58
  "markdownlint-cli2-config.js",
50
59
  "markdownlint-cli2-fix.js",
@@ -52,30 +61,30 @@
52
61
  "resolve-and-require.js"
53
62
  ],
54
63
  "dependencies": {
55
- "globby": "13.1.3",
56
- "markdownlint": "0.27.0",
57
- "markdownlint-cli2-formatter-default": "0.0.3",
64
+ "globby": "13.1.4",
65
+ "markdownlint": "0.28.2",
66
+ "markdownlint-cli2-formatter-default": "0.0.4",
58
67
  "micromatch": "4.0.5",
59
68
  "strip-json-comments": "5.0.0",
60
- "yaml": "2.2.1"
69
+ "yaml": "2.2.2"
61
70
  },
62
71
  "devDependencies": {
63
72
  "@iktakahiro/markdown-it-katex": "4.0.1",
64
- "ava": "5.1.0",
65
- "c8": "7.12.0",
73
+ "ava": "5.2.0",
74
+ "c8": "7.13.0",
66
75
  "cpy": "9.0.1",
67
76
  "del": "7.0.0",
68
- "eslint": "8.30.0",
69
- "eslint-plugin-n": "15.6.0",
70
- "eslint-plugin-unicorn": "45.0.2",
71
- "execa": "6.1.0",
77
+ "eslint": "8.39.0",
78
+ "eslint-plugin-n": "15.7.0",
79
+ "eslint-plugin-unicorn": "46.0.0",
80
+ "execa": "7.1.1",
72
81
  "markdown-it-emoji": "2.0.2",
73
82
  "markdown-it-for-inline": "0.1.1",
74
- "markdownlint-cli2-formatter-codequality": "0.0.1",
75
- "markdownlint-cli2-formatter-json": "0.0.6",
76
- "markdownlint-cli2-formatter-junit": "0.0.5",
77
- "markdownlint-cli2-formatter-pretty": "0.0.3",
78
- "markdownlint-cli2-formatter-summarize": "0.0.5",
83
+ "markdownlint-cli2-formatter-codequality": "0.0.4",
84
+ "markdownlint-cli2-formatter-json": "0.0.7",
85
+ "markdownlint-cli2-formatter-junit": "0.0.6",
86
+ "markdownlint-cli2-formatter-pretty": "0.0.4",
87
+ "markdownlint-cli2-formatter-summarize": "0.0.6",
79
88
  "markdownlint-rule-titlecase": "0.1.0",
80
89
  "npm-run-all": "4.1.5"
81
90
  },