markdownlint-cli2 0.1.0 → 0.2.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/README.md CHANGED
@@ -68,11 +68,11 @@ Configuration via:
68
68
  - .markdownlint.js
69
69
 
70
70
  Cross-platform compatibility:
71
- - UNIX and Windows shells expand globs according to different rules, so quoting glob arguments is recommended
72
- - Shells that expand globs do not support negated patterns (!node_modules), so quoting negated globs is required
73
- - Some Windows shells do not handle single-quoted (') arguments correctly, so double-quotes (") are recommended
74
- - Some UNIX shells handle exclamation (!) in double-quotes specially, so hashtag (#) is recommended for negated globs
75
- - Some shells use backslash (\) to escape special characters, so forward slash (/) is the recommended path separator
71
+ - UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
72
+ - Some Windows shells don't handle single-quoted (') arguments well; double-quote (") is recommended
73
+ - Shells that expand globs do not support negated patterns (!node_modules); quoting is required here
74
+ - Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
75
+ - The path separator is forward slash (/) on all platforms; backslash (\) is automatically converted
76
76
 
77
77
  Therefore, the most compatible glob syntax for cross-platform support:
78
78
  $ markdownlint-cli2 "**/*.md" "#node_modules"
@@ -136,8 +136,9 @@ in both cases), these two commands behave identically.
136
136
  rules for this part of the directory tree
137
137
  - If a `.markdownlint.{jsonc,json,yaml,yml,js}` file (see below) is present
138
138
  in the same directory, it overrides the value of this property
139
- - `customRules`: `Array` of `String`s of module names/paths of
140
- [custom rules][markdownlint-custom-rules] to load and use when linting
139
+ - `customRules`: `Array` of `String`s (or `Array`s of `String`s) of module
140
+ names/paths of [custom rules][markdownlint-custom-rules] to load and use
141
+ when linting
141
142
  - Each `String` is passed as the `id` parameter to Node's
142
143
  [require function][nodejs-require]
143
144
  - Relative paths are resolved based on the location of the `JSONC` file
@@ -265,7 +266,7 @@ in both cases), these two commands behave identically.
265
266
 
266
267
  ### `vscode-markdownlint`
267
268
 
268
- - `.markdownlintrc` and `.markdownlintignore` are not supported.
269
+ - `.markdownlintignore` is not supported.
269
270
 
270
271
  ## pre-commit
271
272
 
@@ -274,7 +275,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
274
275
 
275
276
  ```yaml
276
277
  - repo: https://github.com/DavidAnson/markdownlint-cli2
277
- rev: v0.1.0
278
+ rev: v0.2.0
278
279
  hooks:
279
280
  - id: markdownlint-cli2
280
281
  ```
@@ -299,6 +300,10 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
299
300
  - 0.0.14 - Update dependencies (including `markdownlint`)
300
301
  - 0.0.15 - Improve extensibility
301
302
  - 0.1.0 - Simplify use of `require`, increment minor version
303
+ - 0.1.1 - Restore previous use of `require`
304
+ - 0.1.2 - Update use of `require` to be more flexible
305
+ - 0.1.3 - Support rule collections
306
+ - 0.2.0 - Improve handling of Windows paths using backslash
302
307
 
303
308
  <!-- markdownlint-disable line-length -->
304
309
 
@@ -19,10 +19,11 @@ const { markdownlint, "readConfig": markdownlintReadConfig } =
19
19
  const markdownlintRuleHelpers = require("markdownlint-rule-helpers");
20
20
  const appendToArray = require("./append-to-array");
21
21
  const mergeOptions = require("./merge-options");
22
+ const resolveAndRequire = require("./resolve-and-require");
22
23
 
23
24
  // Variables
24
25
  const packageName = "markdownlint-cli2";
25
- const packageVersion = "0.1.0";
26
+ const packageVersion = "0.2.0";
26
27
  const libraryName = "markdownlint";
27
28
  const libraryVersion = markdownlintLibrary.getVersion();
28
29
  const dotOnlySubstitute = "*.{md,markdown}";
@@ -45,7 +46,7 @@ const posixPath = (p) => p.split(path.sep).join(path.posix.sep);
45
46
 
46
47
  // Read a JSON(C) or YAML file and return the object
47
48
  const readConfig = (dir, name, otherwise) => {
48
- const file = path.join(dir, name);
49
+ const file = path.posix.join(dir, name);
49
50
  return () => fs.access(file).
50
51
  then(
51
52
  // @ts-ignore
@@ -57,9 +58,7 @@ const readConfig = (dir, name, otherwise) => {
57
58
  // Require a module ID with the specified directory in the path
58
59
  const requireResolve = (dir, id) => {
59
60
  if (typeof id === "string") {
60
- const paths = [ dir ];
61
- const resolved = dynamicRequire.resolve(id, { paths });
62
- return dynamicRequire(resolved);
61
+ return resolveAndRequire(dynamicRequire, id, dir);
63
62
  }
64
63
  return id;
65
64
  };
@@ -83,7 +82,7 @@ const requireIdsAndParams = (dir, idsAndParams, noRequire) => {
83
82
 
84
83
  // Require a JS file and return the exported object
85
84
  const requireConfig = (dir, name, noRequire) => {
86
- const file = path.join(dir, name);
85
+ const file = path.posix.join(dir, name);
87
86
  // eslint-disable-next-line prefer-promise-reject-errors
88
87
  return () => (noRequire ? Promise.reject() : fs.access(file)).
89
88
  then(
@@ -94,7 +93,9 @@ const requireConfig = (dir, name, noRequire) => {
94
93
 
95
94
  // Process command-line arguments and return glob patterns
96
95
  const processArgv = (argv) => {
97
- const globPatterns = argv.map((glob) => glob.replace(/^#/u, "!"));
96
+ const globPatterns = argv.map(
97
+ (glob) => glob.replace(/^#/u, "!").replace(/\\(?![$()*+?[\]^])/gu, "/")
98
+ );
98
99
  if ((globPatterns.length === 1) && (globPatterns[0] === ".")) {
99
100
  // Substitute a more reasonable pattern
100
101
  globPatterns[0] = dotOnlySubstitute;
@@ -131,11 +132,11 @@ Configuration via:
131
132
  - .markdownlint.js
132
133
 
133
134
  Cross-platform compatibility:
134
- - UNIX and Windows shells expand globs according to different rules, so quoting glob arguments is recommended
135
- - Shells that expand globs do not support negated patterns (!node_modules), so quoting negated globs is required
136
- - Some Windows shells do not handle single-quoted (') arguments correctly, so double-quotes (") are recommended
137
- - Some UNIX shells handle exclamation (!) in double-quotes specially, so hashtag (#) is recommended for negated globs
138
- - Some shells use backslash (\\) to escape special characters, so forward slash (/) is the recommended path separator
135
+ - UNIX and Windows shells expand globs according to different rules; quoting arguments is recommended
136
+ - Some Windows shells don't handle single-quoted (') arguments well; double-quote (") is recommended
137
+ - Shells that expand globs do not support negated patterns (!node_modules); quoting is required here
138
+ - Some UNIX shells parse exclamation (!) in double-quotes; hashtag (#) is recommended in these cases
139
+ - The path separator is forward slash (/) on all platforms; backslash (\\) is automatically converted
139
140
 
140
141
  Therefore, the most compatible glob syntax for cross-platform support:
141
142
  $ ${name} "**/*.md" "#node_modules"`
@@ -157,8 +158,10 @@ const getAndProcessDirInfo = (tasks, dirToDirInfo, dir, noRequire, func) => {
157
158
  dirToDirInfo[dir] = dirInfo;
158
159
 
159
160
  // Load markdownlint-cli2 object(s)
160
- const markdownlintCli2Jsonc = path.join(dir, ".markdownlint-cli2.jsonc");
161
- const markdownlintCli2Yaml = path.join(dir, ".markdownlint-cli2.yaml");
161
+ const markdownlintCli2Jsonc =
162
+ path.posix.join(dir, ".markdownlint-cli2.jsonc");
163
+ const markdownlintCli2Yaml =
164
+ path.posix.join(dir, ".markdownlint-cli2.yaml");
162
165
  tasks.push(
163
166
  fs.access(markdownlintCli2Jsonc).
164
167
  then(
@@ -234,6 +237,7 @@ async (baseDir, globPatterns, optionsDefault, fixDefault, noRequire) => {
234
237
 
235
238
  // Pass base ignore globs as globby patterns (best performance)
236
239
  const ignorePatterns =
240
+ // eslint-disable-next-line unicorn/no-array-callback-reference
237
241
  (baseMarkdownlintOptions.ignores || []).map(negateGlob);
238
242
  appendToArray(globPatterns, ignorePatterns);
239
243
  delete baseMarkdownlintOptions.ignores;
@@ -254,7 +258,7 @@ async (baseDir, globPatterns, dirToDirInfo, noRequire) => {
254
258
  };
255
259
  for await (const file of globby.stream(globPatterns, globbyOptions)) {
256
260
  // @ts-ignore
257
- const dir = path.dirname(file);
261
+ const dir = path.posix.dirname(file);
258
262
  getAndProcessDirInfo(tasks, dirToDirInfo, dir, noRequire, (dirInfo) => {
259
263
  dirInfo.files.push(file);
260
264
  });
@@ -271,7 +275,7 @@ const enumerateParents = async (baseDir, dirToDirInfo, noRequire) => {
271
275
  let baseDirParent = baseDir;
272
276
  do {
273
277
  baseDirParents[baseDirParent] = true;
274
- baseDirParent = path.dirname(baseDirParent);
278
+ baseDirParent = path.posix.dirname(baseDirParent);
275
279
  } while (!baseDirParents[baseDirParent]);
276
280
 
277
281
  // Visit parents of each dirInfo
@@ -280,7 +284,7 @@ const enumerateParents = async (baseDir, dirToDirInfo, noRequire) => {
280
284
  let lastDir = dir;
281
285
  while (
282
286
  !baseDirParents[dir] &&
283
- (dir = path.dirname(dir)) &&
287
+ (dir = path.posix.dirname(dir)) &&
284
288
  (dir !== lastDir)
285
289
  ) {
286
290
  lastDir = dir;
@@ -325,12 +329,14 @@ async (baseDir, globPatterns, dirToDirInfo, optionsOverride, noRequire) => {
325
329
  } else {
326
330
  const { markdownlintOptions } = dirInfo;
327
331
  if (markdownlintOptions && markdownlintOptions.customRules) {
328
- markdownlintOptions.customRules =
332
+ const customRules =
329
333
  requireIds(
330
334
  dir,
331
335
  markdownlintOptions.customRules,
332
336
  noRequire
333
337
  );
338
+ // Expand nested arrays (for packages that export multiple rules)
339
+ markdownlintOptions.customRules = customRules.flat();
334
340
  }
335
341
  if (markdownlintOptions && markdownlintOptions.markdownItPlugins) {
336
342
  markdownlintOptions.markdownItPlugins =
@@ -424,12 +430,13 @@ const lintFiles = (dirInfos, fileContents) => {
424
430
  (file) => fileContents[file] === undefined
425
431
  );
426
432
  if (markdownlintOptions.ignores) {
433
+ // eslint-disable-next-line unicorn/no-array-callback-reference
427
434
  const ignores = markdownlintOptions.ignores.map(negateGlob);
428
435
  const micromatch = require("micromatch");
429
436
  filteredFiles = micromatch(
430
- files.map((file) => path.relative(dir, file)),
437
+ files.map((file) => path.posix.relative(dir, file)),
431
438
  ignores
432
- ).map((file) => path.join(dir, file));
439
+ ).map((file) => path.posix.join(dir, file));
433
440
  }
434
441
  // Create markdownlint options object
435
442
  const options = {
@@ -493,10 +500,9 @@ const createSummary = (baseDir, taskResults) => {
493
500
  for (const fileName in results) {
494
501
  const errorInfos = results[fileName];
495
502
  for (const errorInfo of errorInfos) {
496
- const fileNameRelativePosix =
497
- posixPath(path.relative(baseDir, fileName));
503
+ const fileNameRelative = path.posix.relative(baseDir, fileName);
498
504
  summary.push({
499
- "fileName": fileNameRelativePosix,
505
+ "fileName": fileNameRelative,
500
506
  ...errorInfo,
501
507
  counter
502
508
  });
@@ -553,10 +559,10 @@ const main = async (params) => {
553
559
  } = params;
554
560
  const logMessage = params.logMessage || noop;
555
561
  const logError = params.logError || noop;
556
- const baseDir = posixPath(
562
+ const baseDirSystem =
557
563
  (directory && path.resolve(directory)) ||
558
- process.cwd()
559
- );
564
+ process.cwd();
565
+ const baseDir = posixPath(baseDirSystem);
560
566
  // Output banner
561
567
  logMessage(
562
568
  `${packageName} v${packageVersion} (${libraryName} v${libraryVersion})`
@@ -578,7 +584,8 @@ const main = async (params) => {
578
584
  // Include any file overrides or non-file content
579
585
  const resolvedFileContents = {};
580
586
  for (const file in fileContents) {
581
- resolvedFileContents[posixPath(path.resolve(baseDir, file))] =
587
+ const resolvedFile = posixPath(path.resolve(baseDirSystem, file));
588
+ resolvedFileContents[resolvedFile] =
582
589
  fileContents[file];
583
590
  }
584
591
  for (const nonFile in nonFileContents) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdownlint-cli2",
3
- "version": "0.1.0",
3
+ "version": "0.2.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",
@@ -22,38 +22,39 @@
22
22
  "ci": "npm-run-all --continue-on-error --parallel test-cover lint",
23
23
  "lint": "eslint --max-warnings 0 .",
24
24
  "lint-watch": "git ls-files | entr npm run lint",
25
- "test": "ava test/append-to-array-test.js test/markdownlint-cli2-test.js test/markdownlint-cli2-test-exec.js test/markdownlint-cli2-test-main.js test/merge-options-test.js",
25
+ "test": "ava test/append-to-array-test.js test/markdownlint-cli2-test.js test/markdownlint-cli2-test-exec.js test/markdownlint-cli2-test-main.js test/merge-options-test.js test/resolve-and-require-test.js",
26
26
  "test-cover": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 npm test",
27
27
  "test-watch": "git ls-files | entr npm run test"
28
28
  },
29
29
  "engines": {
30
- "node": ">=10.17.0"
30
+ "node": ">=12"
31
31
  },
32
32
  "files": [
33
33
  "append-to-array.js",
34
34
  "markdownlint-cli2.js",
35
35
  "markdownlint-cli2-fix.js",
36
- "merge-options.js"
36
+ "merge-options.js",
37
+ "resolve-and-require.js"
37
38
  ],
38
39
  "dependencies": {
39
- "globby": "~11.0.3",
40
+ "globby": "~11.0.4",
40
41
  "markdownlint": "~0.23.1",
41
42
  "markdownlint-cli2-formatter-default": "^0.0.2",
42
43
  "markdownlint-rule-helpers": "~0.14.0",
43
- "micromatch": "~4.0.2",
44
+ "micromatch": "~4.0.4",
44
45
  "strip-json-comments": "~3.1.1",
45
46
  "yaml": "~1.10.2"
46
47
  },
47
48
  "devDependencies": {
48
49
  "@iktakahiro/markdown-it-katex": "~4.0.1",
49
50
  "ava": "~3.15.0",
50
- "c8": "~7.7.0",
51
+ "c8": "~7.7.3",
51
52
  "cpy": "~8.1.2",
52
53
  "del": "~6.0.0",
53
- "eslint": "~7.23.0",
54
+ "eslint": "~7.31.0",
54
55
  "eslint-plugin-node": "~11.1.0",
55
- "eslint-plugin-unicorn": "~29.0.0",
56
- "execa": "~5.0.0",
56
+ "eslint-plugin-unicorn": "~34.0.1",
57
+ "execa": "~5.1.1",
57
58
  "markdown-it-emoji": "~2.0.0",
58
59
  "markdown-it-for-inline": "~0.1.1",
59
60
  "markdownlint-cli2-formatter-json": "^0.0.4",
@@ -0,0 +1,20 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ /**
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.
11
+ * @returns {Object} Exported module content.
12
+ */
13
+ const resolveAndRequire = (req, id, dir) => {
14
+ const resolvePaths = req.resolve.paths ? req.resolve.paths("") : [];
15
+ const paths = [ dir, ...resolvePaths ];
16
+ const resolved = req.resolve(id, { paths });
17
+ return req(resolved);
18
+ };
19
+
20
+ module.exports = resolveAndRequire;