markdownlint-cli2 0.12.1 → 0.13.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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.0
4
+
5
+ - Add `noBanner` and `gitignore` configuration options
6
+ - Reduce install size by switching to `js-yaml` package
7
+ - Add more detail to some error messages
8
+ - Export JSONC/YAML parsers for reuse
9
+ - Update dependencies (including `markdownlint`)
10
+
3
11
  ## 0.12.1
4
12
 
5
13
  - Update JSONC parsing to handle trailing commas
package/README.md CHANGED
@@ -147,7 +147,7 @@ A container image [`davidanson/markdownlint-cli2`][docker-hub-markdownlint-cli2]
147
147
  can also be used (e.g., as part of a CI pipeline):
148
148
 
149
149
  ```bash
150
- docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.12.1 "**/*.md" "#node_modules"
150
+ docker run -v $PWD:/workdir davidanson/markdownlint-cli2:v0.13.0 "**/*.md" "#node_modules"
151
151
  ```
152
152
 
153
153
  Notes:
@@ -164,7 +164,7 @@ Notes:
164
164
  - A custom working directory can be specified with Docker's `-w` flag:
165
165
 
166
166
  ```bash
167
- docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.12.1 "**/*.md" "#node_modules"
167
+ docker run -w /myfolder -v $PWD:/myfolder davidanson/markdownlint-cli2:v0.13.0 "**/*.md" "#node_modules"
168
168
  ```
169
169
 
170
170
  For convenience, the container image
@@ -256,6 +256,10 @@ of the rules within.
256
256
  - The `String` is passed as the `pattern` parameter to the
257
257
  [`RegExp` constructor][regexp-constructor]
258
258
  - For example: `(^---\s*$[^]*?^---\s*$)(\r\n|\r|\n|$)`
259
+ - `gitignore`: `Boolean` value to ignore files referenced by `.gitignore` when
260
+ linting
261
+ - This top-level setting is valid **only** in the directory from which
262
+ `markdownlint-cli2` is run
259
263
  - `globs`: `Array` of `String`s defining glob expressions to append to the
260
264
  command-line arguments
261
265
  - This setting can be used instead of (or in addition to) passing globs on
@@ -285,6 +289,10 @@ of the rules within.
285
289
  - Search [`markdown-it-plugins` on npm][markdown-it-plugins]
286
290
  - `modulePaths`: `Array` of `String`s providing additional paths to use when
287
291
  resolving module references (e.g., alternate locations for `node_modules`)
292
+ - `noBanner`: `Boolean` value to disable the display of the banner message and
293
+ version numbers on `stdout`
294
+ - This top-level setting is valid **only** in the directory from which
295
+ `markdownlint-cli2` is run
288
296
  - `noInlineConfig`: `Boolean` value to disable the support of
289
297
  [HTML comments][html-comment] within Markdown content
290
298
  - For example: `<!-- markdownlint-disable some-rule -->`
@@ -396,7 +404,7 @@ reference to the `repos` list in that project's `.pre-commit-config.yaml` like:
396
404
 
397
405
  ```yaml
398
406
  - repo: https://github.com/DavidAnson/markdownlint-cli2
399
- rev: v0.12.1
407
+ rev: v0.13.0
400
408
  hooks:
401
409
  - id: markdownlint-cli2
402
410
  ```
@@ -6,9 +6,9 @@ const sliceSize = 1000;
6
6
 
7
7
  /**
8
8
  * Efficiently appends the source array to the destination array.
9
- * @param {Object[]} destination Destination Array.
10
- * @param {Object[]} source Source Array.
11
- * @returns void
9
+ * @param {object[]} destination Destination Array.
10
+ * @param {object[]} source Source Array.
11
+ * @returns {void}
12
12
  */
13
13
  const appendToArray = (destination, source) => {
14
14
  // NOTE: destination.push(...source) throws "RangeError: Maximum call stack
@@ -26,35 +26,37 @@ const resolveAndRequire = require("./resolve-and-require");
26
26
 
27
27
  // Variables
28
28
  const packageName = "markdownlint-cli2";
29
- const packageVersion = "0.12.1";
29
+ const packageVersion = "0.13.0";
30
30
  const libraryName = "markdownlint";
31
31
  const libraryVersion = markdownlintLibrary.getVersion();
32
+ const bannerMessage = `${packageName} v${packageVersion} (${libraryName} v${libraryVersion})`;
32
33
  const dotOnlySubstitute = "*.{md,markdown}";
33
34
  const utf8 = "utf8";
34
35
 
35
36
  // No-op function
36
37
  const noop = () => null;
37
38
 
38
- // Synchronous function to parse JSONC text
39
- const jsoncParse = (text) => {
40
- const { parse, printParseErrorCode } = require("jsonc-parser");
41
- const errors = [];
42
- const result = parse(text, errors, { "allowTrailingComma": true });
43
- if (errors.length > 0) {
44
- const aggregate = errors.map(
45
- (err) => `${printParseErrorCode(err.error)} (offset ${err.offset}, length ${err.length})`
46
- ).join(", ");
47
- throw new Error(`Unable to parse JSON(C) content, ${aggregate}`);
48
- }
49
- return result;
50
- };
39
+ // Gets a JSONC parser
40
+ const getJsoncParse = () => require("./parsers/jsonc-parse.js");
41
+
42
+ // Gets a YAML parser
43
+ const getYamlParse = () => require("./parsers/yaml-parse.js");
51
44
 
52
- // Synchronous function to parse YAML text
53
- const yamlParse = (text) => require("yaml").parse(text);
45
+ // Gets an ordered array of parsers
46
+ const getParsers = () => require("./parsers/parsers.js");
54
47
 
55
- // Negate a glob
48
+ // Negates a glob
56
49
  const negateGlob = (glob) => `!${glob}`;
57
50
 
51
+ // Throws a meaningful exception for an unusable configuration file
52
+ const throwForConfigurationFile = (file, error) => {
53
+ throw new Error(
54
+ `Unable to use configuration file '${file}'; ${error?.message}`,
55
+ // @ts-ignore
56
+ { "cause": error }
57
+ );
58
+ };
59
+
58
60
  // Return a posix path (even on Windows)
59
61
  const posixPath = (p) => p.split(pathDefault.sep).join(pathPosix.sep);
60
62
 
@@ -69,13 +71,13 @@ const resolveModulePaths = (dir, modulePaths) => (
69
71
  );
70
72
 
71
73
  // Read a JSON(C) or YAML file and return the object
72
- const readConfig = (fs, dir, name, otherwise) => {
74
+ const readConfig = (fs, dir, name, otherwise) => () => {
73
75
  const file = pathPosix.join(dir, name);
74
- return () => fs.promises.access(file).
76
+ return fs.promises.access(file).
75
77
  then(
76
78
  () => markdownlintReadConfig(
77
79
  file,
78
- [ jsoncParse, yamlParse ],
80
+ getParsers(),
79
81
  fs
80
82
  ),
81
83
  otherwise
@@ -83,11 +85,12 @@ const readConfig = (fs, dir, name, otherwise) => {
83
85
  };
84
86
 
85
87
  // Import or resolve/require a module ID with a custom directory in the path
86
- const importOrRequireResolve = async (dirs, id, noRequire) => {
88
+ const importOrRequireResolve = async (dirOrDirs, id, noRequire) => {
87
89
  if (typeof id === "string") {
88
90
  if (noRequire) {
89
91
  return null;
90
92
  }
93
+ const dirs = Array.isArray(dirOrDirs) ? dirOrDirs : [ dirOrDirs ];
91
94
  const expandId = expandTildePath(id);
92
95
  const errors = [];
93
96
  try {
@@ -96,10 +99,12 @@ const importOrRequireResolve = async (dirs, id, noRequire) => {
96
99
  errors.push(error);
97
100
  }
98
101
  try {
99
- const fileUrlString =
100
- pathToFileURL(pathDefault.resolve(dirs[0], expandId)).toString();
102
+ const isURL = !pathDefault.isAbsolute(expandId) && URL.canParse(expandId);
103
+ const urlString = (
104
+ isURL ? new URL(expandId) : pathToFileURL(pathDefault.resolve(dirs[0], expandId))
105
+ ).toString();
101
106
  // eslint-disable-next-line no-inline-comments
102
- const module = await import(/* webpackIgnore: true */ fileUrlString);
107
+ const module = await import(/* webpackIgnore: true */ urlString);
103
108
  return module.default;
104
109
  } catch (error) {
105
110
  errors.push(error);
@@ -133,11 +138,11 @@ const importOrRequireIdsAndParams = (dirs, idsAndParams, noRequire) => (
133
138
  );
134
139
 
135
140
  // Import or require a JavaScript file and return the exported object
136
- const importOrRequireConfig = (fs, dir, name, noRequire, otherwise) => {
137
- const id = pathPosix.join(dir, name);
138
- return () => fs.promises.access(id).
141
+ const importOrRequireConfig = (fs, dir, name, noRequire, otherwise) => () => {
142
+ const file = pathPosix.join(dir, name);
143
+ return fs.promises.access(file).
139
144
  then(
140
- () => (noRequire ? {} : importOrRequireResolve([ dir ], id)),
145
+ () => importOrRequireResolve(dir, name, noRequire),
141
146
  otherwise
142
147
  );
143
148
  };
@@ -148,7 +153,7 @@ const getExtendedConfig = (config, configPath, fs) => {
148
153
  return markdownlintExtendConfig(
149
154
  config,
150
155
  configPath,
151
- [ jsoncParse, yamlParse ],
156
+ getParsers(),
152
157
  fs
153
158
  );
154
159
  }
@@ -162,47 +167,43 @@ const readOptionsOrConfig = async (configPath, fs, noRequire) => {
162
167
  const dirname = pathPosix.dirname(configPath);
163
168
  let options = null;
164
169
  let config = null;
165
- if (basename.endsWith(".markdownlint-cli2.jsonc")) {
166
- options = jsoncParse(await fs.promises.readFile(configPath, utf8));
167
- } else if (basename.endsWith(".markdownlint-cli2.yaml")) {
168
- options = yamlParse(await fs.promises.readFile(configPath, utf8));
169
- } else if (
170
- basename.endsWith(".markdownlint-cli2.cjs") ||
171
- basename.endsWith(".markdownlint-cli2.mjs")
172
- ) {
173
- options = await (
174
- importOrRequireConfig(fs, dirname, basename, noRequire, noop)()
175
- );
176
- } else if (
177
- basename.endsWith(".markdownlint.jsonc") ||
178
- basename.endsWith(".markdownlint.json") ||
179
- basename.endsWith(".markdownlint.yaml") ||
180
- basename.endsWith(".markdownlint.yml")
181
- ) {
182
- config =
183
- await markdownlintReadConfig(configPath, [ jsoncParse, yamlParse ], fs);
184
- } else if (
185
- basename.endsWith(".markdownlint.cjs") ||
186
- basename.endsWith(".markdownlint.mjs")
187
- ) {
188
- config = await (
189
- importOrRequireConfig(fs, dirname, basename, noRequire, noop)()
190
- );
191
- } else {
192
- throw new Error(
193
- `Configuration file "${configPath}" is unrecognized; ` +
194
- "its name should be (or end with) one of the supported types " +
195
- "(e.g., \".markdownlint.json\" or \"example.markdownlint-cli2.jsonc\")."
196
- );
170
+ try {
171
+ if (basename.endsWith(".markdownlint-cli2.jsonc")) {
172
+ options = getJsoncParse()(await fs.promises.readFile(configPath, utf8));
173
+ } else if (basename.endsWith(".markdownlint-cli2.yaml")) {
174
+ options = getYamlParse()(await fs.promises.readFile(configPath, utf8));
175
+ } else if (
176
+ basename.endsWith(".markdownlint-cli2.cjs") ||
177
+ basename.endsWith(".markdownlint-cli2.mjs")
178
+ ) {
179
+ options = await importOrRequireResolve(dirname, basename, noRequire);
180
+ } else if (
181
+ basename.endsWith(".markdownlint.jsonc") ||
182
+ basename.endsWith(".markdownlint.json") ||
183
+ basename.endsWith(".markdownlint.yaml") ||
184
+ basename.endsWith(".markdownlint.yml")
185
+ ) {
186
+ config = await markdownlintReadConfig(configPath, getParsers(), fs);
187
+ } else if (
188
+ basename.endsWith(".markdownlint.cjs") ||
189
+ basename.endsWith(".markdownlint.mjs")
190
+ ) {
191
+ config = await importOrRequireResolve(dirname, basename, noRequire);
192
+ } else {
193
+ throw new Error(
194
+ "File name should be (or end with) one of the supported types " +
195
+ "(e.g., '.markdownlint.json' or 'example.markdownlint-cli2.jsonc')."
196
+ );
197
+ }
198
+ } catch (error) {
199
+ throwForConfigurationFile(configPath, error);
197
200
  }
198
-
199
201
  if (options) {
200
202
  if (options.config) {
201
203
  options.config = await getExtendedConfig(options.config, configPath, fs);
202
204
  }
203
205
  return options;
204
206
  }
205
-
206
207
  config = await getExtendedConfig(config, configPath, fs);
207
208
  return { config };
208
209
  };
@@ -241,7 +242,10 @@ const processArgv = (argv) => {
241
242
  };
242
243
 
243
244
  // Show help if missing arguments
244
- const showHelp = (logMessage) => {
245
+ const showHelp = (logMessage, showBanner) => {
246
+ if (showBanner) {
247
+ logMessage(bannerMessage);
248
+ }
245
249
  logMessage(`https://github.com/DavidAnson/markdownlint-cli2
246
250
 
247
251
  Syntax: markdownlint-cli2 glob0 [glob1] [...] [globN] [--config file] [--fix] [--help]
@@ -297,6 +301,7 @@ const getAndProcessDirInfo = (
297
301
  noRequire,
298
302
  allowPackageJson
299
303
  ) => {
304
+ // Create dirInfo
300
305
  let dirInfo = dirToDirInfo[dir];
301
306
  if (!dirInfo) {
302
307
  dirInfo = {
@@ -310,46 +315,41 @@ const getAndProcessDirInfo = (
310
315
  dirToDirInfo[dir] = dirInfo;
311
316
 
312
317
  // Load markdownlint-cli2 object(s)
313
- const markdownlintCli2Jsonc =
314
- pathPosix.join(dir, ".markdownlint-cli2.jsonc");
315
- const markdownlintCli2Yaml =
316
- pathPosix.join(dir, ".markdownlint-cli2.yaml");
318
+ const markdownlintCli2Jsonc = pathPosix.join(dir, ".markdownlint-cli2.jsonc");
319
+ const markdownlintCli2Yaml = pathPosix.join(dir, ".markdownlint-cli2.yaml");
320
+ const markdownlintCli2Cjs = pathPosix.join(dir, ".markdownlint-cli2.cjs");
321
+ const markdownlintCli2Mjs = pathPosix.join(dir, ".markdownlint-cli2.mjs");
317
322
  const packageJson = pathPosix.join(dir, "package.json");
323
+ let file = "[UNKNOWN]";
324
+ // eslint-disable-next-line no-return-assign
325
+ const captureFile = (f) => file = f;
318
326
  tasks.push(
319
- fs.promises.access(markdownlintCli2Jsonc).
327
+ fs.promises.access(captureFile(markdownlintCli2Jsonc)).
320
328
  then(
321
- () => fs.promises.
322
- readFile(markdownlintCli2Jsonc, utf8).
323
- then(jsoncParse),
324
- () => fs.promises.access(markdownlintCli2Yaml).
329
+ () => fs.promises.readFile(file, utf8).then(getJsoncParse()),
330
+ () => fs.promises.access(captureFile(markdownlintCli2Yaml)).
325
331
  then(
326
- () => fs.promises.
327
- readFile(markdownlintCli2Yaml, utf8).
328
- then(yamlParse),
329
- importOrRequireConfig(
330
- fs,
331
- dir,
332
- ".markdownlint-cli2.cjs",
333
- noRequire,
334
- importOrRequireConfig(
335
- fs,
336
- dir,
337
- ".markdownlint-cli2.mjs",
338
- noRequire,
339
- () => (allowPackageJson
340
- ? fs.promises.access(packageJson)
341
- // eslint-disable-next-line prefer-promise-reject-errors
342
- : Promise.reject()
343
- ).
332
+ () => fs.promises.readFile(file, utf8).then(getYamlParse()),
333
+ () => fs.promises.access(captureFile(markdownlintCli2Cjs)).
334
+ then(
335
+ () => importOrRequireResolve(dir, file, noRequire),
336
+ () => fs.promises.access(captureFile(markdownlintCli2Mjs)).
344
337
  then(
345
- () => fs.promises.
346
- readFile(packageJson, utf8).
347
- then(jsoncParse).
348
- then((obj) => obj[packageName]),
349
- noop
338
+ () => importOrRequireResolve(dir, file, noRequire),
339
+ () => (allowPackageJson
340
+ ? fs.promises.access(captureFile(packageJson))
341
+ // eslint-disable-next-line prefer-promise-reject-errors
342
+ : Promise.reject()
343
+ ).
344
+ then(
345
+ () => fs.promises.
346
+ readFile(file, utf8).
347
+ then(getJsoncParse()).
348
+ then((obj) => obj[packageName]),
349
+ noop
350
+ )
350
351
  )
351
352
  )
352
- )
353
353
  )
354
354
  ).
355
355
  then((options) => {
@@ -358,7 +358,7 @@ const getAndProcessDirInfo = (
358
358
  options.config &&
359
359
  getExtendedConfig(
360
360
  options.config,
361
- // Just needs to identify a file in the right directory
361
+ // Just need to identify a file in the right directory
362
362
  markdownlintCli2Jsonc,
363
363
  fs
364
364
  ).
@@ -366,6 +366,9 @@ const getAndProcessDirInfo = (
366
366
  options.config = config;
367
367
  });
368
368
  })
369
+ .catch((error) => {
370
+ throwForConfigurationFile(file, error);
371
+ })
369
372
  );
370
373
 
371
374
  // Load markdownlint object(s)
@@ -410,6 +413,8 @@ const getAndProcessDirInfo = (
410
413
  })
411
414
  );
412
415
  }
416
+
417
+ // Return dirInfo
413
418
  return dirInfo;
414
419
  };
415
420
 
@@ -471,14 +476,17 @@ const enumerateFiles = async (
471
476
  baseDir,
472
477
  globPatterns,
473
478
  dirToDirInfo,
479
+ gitignore,
474
480
  noRequire
475
481
  ) => {
476
482
  const tasks = [];
483
+ /** @type {import("globby").Options} */
477
484
  const globbyOptions = {
478
485
  "absolute": true,
479
486
  "cwd": baseDir,
480
487
  "dot": true,
481
488
  "expandDirectories": false,
489
+ gitignore,
482
490
  "suppressErrors": true,
483
491
  fs
484
492
  };
@@ -603,6 +611,7 @@ const createDirInfos = async (
603
611
  globPatterns,
604
612
  dirToDirInfo,
605
613
  optionsOverride,
614
+ gitignore,
606
615
  noRequire
607
616
  ) => {
608
617
  await enumerateFiles(
@@ -611,6 +620,7 @@ const createDirInfos = async (
611
620
  baseDir,
612
621
  globPatterns,
613
622
  dirToDirInfo,
623
+ gitignore,
614
624
  noRequire
615
625
  );
616
626
  await enumerateParents(
@@ -767,7 +777,7 @@ const lintFiles = (fs, dirInfos, fileContents) => {
767
777
  "files": filteredFiles,
768
778
  "strings": filteredStrings,
769
779
  "config": markdownlintConfig || markdownlintOptions.config,
770
- "configParsers": [ jsoncParse, yamlParse ],
780
+ "configParsers": getParsers(),
771
781
  "customRules": markdownlintOptions.customRules,
772
782
  "frontMatter": markdownlintOptions.frontMatter
773
783
  ? new RegExp(markdownlintOptions.frontMatter, "u")
@@ -902,10 +912,6 @@ const main = async (params) => {
902
912
  (directory && pathDefault.resolve(directory)) ||
903
913
  process.cwd();
904
914
  const baseDir = posixPath(baseDirSystem);
905
- // Output banner
906
- logMessage(
907
- `${packageName} v${packageVersion} (${libraryName} v${libraryVersion})`
908
- );
909
915
  // Merge and process args/argv
910
916
  let fixDefault = false;
911
917
  // eslint-disable-next-line unicorn/no-useless-undefined
@@ -932,22 +938,24 @@ const main = async (params) => {
932
938
  return true;
933
939
  });
934
940
  if (shouldShowHelp) {
935
- return showHelp(logMessage);
941
+ return showHelp(logMessage, true);
936
942
  }
937
943
  // Read argv configuration file (if relevant and present)
938
944
  let optionsArgv = null;
939
945
  let relativeDir = null;
940
- if (configPath) {
941
- const resolvedConfigPath =
942
- posixPath(pathDefault.resolve(baseDirSystem, configPath));
943
- optionsArgv =
944
- await readOptionsOrConfig(resolvedConfigPath, fs, noRequire);
945
- relativeDir = pathPosix.dirname(resolvedConfigPath);
946
- }
947
- // Process arguments and get base options
948
- const globPatterns = processArgv(argvFiltered);
949
- const { baseMarkdownlintOptions, dirToDirInfo } =
950
- await getBaseOptions(
946
+ let globPatterns = null;
947
+ let baseOptions = null;
948
+ try {
949
+ if (configPath) {
950
+ const resolvedConfigPath =
951
+ posixPath(pathDefault.resolve(baseDirSystem, configPath));
952
+ optionsArgv =
953
+ await readOptionsOrConfig(resolvedConfigPath, fs, noRequire);
954
+ relativeDir = pathPosix.dirname(resolvedConfigPath);
955
+ }
956
+ // Process arguments and get base options
957
+ globPatterns = processArgv(argvFiltered);
958
+ baseOptions = await getBaseOptions(
951
959
  fs,
952
960
  baseDir,
953
961
  relativeDir,
@@ -957,13 +965,19 @@ const main = async (params) => {
957
965
  noGlobs,
958
966
  noRequire
959
967
  );
968
+ } finally {
969
+ if (!baseOptions?.baseMarkdownlintOptions.noBanner) {
970
+ logMessage(bannerMessage);
971
+ }
972
+ }
960
973
  if (
961
974
  ((globPatterns.length === 0) && !nonFileContents) ||
962
975
  (configPath === null)
963
976
  ) {
964
- return showHelp(logMessage);
977
+ return showHelp(logMessage, false);
965
978
  }
966
979
  // Include any file overrides or non-file content
980
+ const { baseMarkdownlintOptions, dirToDirInfo } = baseOptions;
967
981
  const resolvedFileContents = {};
968
982
  for (const file in fileContents) {
969
983
  const resolvedFile = posixPath(pathDefault.resolve(baseDirSystem, file));
@@ -991,6 +1005,8 @@ const main = async (params) => {
991
1005
  globPatterns,
992
1006
  dirToDirInfo,
993
1007
  optionsOverride,
1008
+ // https://github.com/sindresorhus/globby/issues/265
1009
+ !params.fs && Boolean(baseMarkdownlintOptions.gitignore),
994
1010
  noRequire
995
1011
  );
996
1012
  // Output linting status
package/merge-options.js CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  /**
6
6
  * Merges two options objects by combining config and replacing properties.
7
- * @param {Object} first First options object.
8
- * @param {Object} second Second options object.
9
- * @returns {Object} Merged options object.
7
+ * @param {object} first First options object.
8
+ * @param {object} second Second options object.
9
+ * @returns {object} Merged options object.
10
10
  */
11
11
  const mergeOptions = (first, second) => {
12
12
  const merged = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdownlint-cli2",
3
- "version": "0.12.1",
3
+ "version": "0.13.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",
@@ -12,7 +12,10 @@
12
12
  "exports": {
13
13
  ".": "./markdownlint-cli2.js",
14
14
  "./markdownlint": "./export-markdownlint.js",
15
- "./markdownlint/helpers": "./export-markdownlint-helpers.js"
15
+ "./markdownlint/helpers": "./export-markdownlint-helpers.js",
16
+ "./parsers": "./parsers/parsers.js",
17
+ "./parsers/jsonc": "./parsers/jsonc-parse.js",
18
+ "./parsers/yaml": "./parsers/yaml-parse.js"
16
19
  },
17
20
  "bin": {
18
21
  "markdownlint-cli2": "markdownlint-cli2.js"
@@ -32,7 +35,7 @@
32
35
  "lint-dockerfile": "docker run --rm -i hadolint/hadolint:latest-alpine < docker/Dockerfile",
33
36
  "lint-watch": "git ls-files | entr npm run lint",
34
37
  "schema": "cpy ./node_modules/markdownlint/schema/markdownlint-config-schema.json ./schema --flat",
35
- "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",
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-exports.js test/markdownlint-cli2-test-fs.js test/markdownlint-cli2-test-main.js test/merge-options-test.js test/resolve-and-require-test.js",
36
39
  "test-cover": "c8 --100 npm test",
37
40
  "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\"",
38
41
  "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\"",
@@ -55,6 +58,9 @@
55
58
  "LICENSE",
56
59
  "markdownlint-cli2.js",
57
60
  "merge-options.js",
61
+ "parsers/parsers.js",
62
+ "parsers/jsonc-parse.js",
63
+ "parsers/yaml-parse.js",
58
64
  "README.md",
59
65
  "resolve-and-require.js",
60
66
  "schema/markdownlint-cli2-config-schema.json",
@@ -62,30 +68,31 @@
62
68
  "schema/ValidatingConfiguration.md"
63
69
  ],
64
70
  "dependencies": {
65
- "globby": "14.0.0",
66
- "jsonc-parser": "3.2.0",
67
- "markdownlint": "0.33.0",
71
+ "globby": "14.0.1",
72
+ "js-yaml": "4.1.0",
73
+ "jsonc-parser": "3.2.1",
74
+ "markdownlint": "0.34.0",
68
75
  "markdownlint-cli2-formatter-default": "0.0.4",
69
- "micromatch": "4.0.5",
70
- "yaml": "2.3.4"
76
+ "micromatch": "4.0.5"
71
77
  },
72
78
  "devDependencies": {
73
79
  "@iktakahiro/markdown-it-katex": "4.0.1",
74
80
  "ajv": "8.12.0",
75
- "ava": "6.0.1",
81
+ "ava": "6.1.2",
76
82
  "c8": "9.1.0",
77
- "cpy": "11.0.0",
83
+ "cpy": "11.0.1",
78
84
  "cpy-cli": "5.0.0",
79
85
  "del": "7.1.0",
80
- "eslint": "8.56.0",
86
+ "eslint": "8.57.0",
87
+ "eslint-plugin-jsdoc": "48.2.2",
81
88
  "eslint-plugin-n": "16.6.2",
82
- "eslint-plugin-unicorn": "50.0.1",
89
+ "eslint-plugin-unicorn": "51.0.1",
83
90
  "execa": "8.0.1",
84
91
  "markdown-it-emoji": "3.0.0",
85
92
  "markdown-it-for-inline": "2.0.1",
86
93
  "markdownlint-cli2-formatter-codequality": "0.0.4",
87
94
  "markdownlint-cli2-formatter-json": "0.0.7",
88
- "markdownlint-cli2-formatter-junit": "0.0.8",
95
+ "markdownlint-cli2-formatter-junit": "0.0.9",
89
96
  "markdownlint-cli2-formatter-pretty": "0.0.5",
90
97
  "markdownlint-cli2-formatter-sarif": "0.0.1",
91
98
  "markdownlint-cli2-formatter-summarize": "0.0.6",
@@ -0,0 +1,24 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ const { parse, printParseErrorCode } = require("jsonc-parser");
6
+
7
+ /**
8
+ * Parses a JSONC string, returning the corresponding object.
9
+ * @param {string} text String to parse as JSONC.
10
+ * @returns {object} Corresponding object.
11
+ */
12
+ const jsoncParse = (text) => {
13
+ const errors = [];
14
+ const result = parse(text, errors, { "allowTrailingComma": true });
15
+ if (errors.length > 0) {
16
+ const aggregate = errors.map(
17
+ (error) => `${printParseErrorCode(error.error)} (offset ${error.offset}, length ${error.length})`
18
+ ).join(", ");
19
+ throw new Error(`Unable to parse JSONC content, ${aggregate}`);
20
+ }
21
+ return result;
22
+ };
23
+
24
+ module.exports = jsoncParse;
@@ -0,0 +1,16 @@
1
+ // @ts-check
2
+
3
+ "use strict";
4
+
5
+ const jsoncParse = require("./jsonc-parse");
6
+ const yamlParse = require("./yaml-parse");
7
+
8
+ /**
9
+ * Array of parser objects ordered by priority.
10
+ */
11
+ const parsers = [
12
+ jsoncParse,
13
+ yamlParse
14
+ ];
15
+
16
+ module.exports = parsers;