markuplint 5.4.0 → 5.6.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
@@ -3,6 +3,30 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [5.6.0](https://github.com/markuplint/markuplint/compare/v5.5.0...v5.6.0) (2026-11-12)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **markuplint:** keep the scope of the suppressions ([4f2409d](https://github.com/markuplint/markuplint/commit/4f2409d1d9c98cefbbe91f7c0f084f5855fafeb5)), closes [#4592](https://github.com/markuplint/markuplint/issues/4592)
11
+
12
+
13
+ # [5.5.0](https://github.com/markuplint/markuplint/compare/v5.4.0...v5.5.0) (2026-11-10)
14
+
15
+ ### Bug Fixes
16
+
17
+ * **markuplint:** exit with the lint verdict under --format json ([3c02102](https://github.com/markuplint/markuplint/commit/3c02102e939565e628447b7c25490e4346db0f20)), closes [#4551](https://github.com/markuplint/markuplint/issues/4551)
18
+ * **markuplint:** keep the whole report on a pipe by not calling process.exit() ([6d98027](https://github.com/markuplint/markuplint/commit/6d98027684cdcd0a3f30d45bebac81813a5a9fc7)), closes [#4554](https://github.com/markuplint/markuplint/issues/4554)
19
+ * **markuplint:** reject the options that act on a file when the source is stdin ([f980686](https://github.com/markuplint/markuplint/commit/f9806863a1e12c3a4d78ef30b739a65ce0318ee6)), closes [#4560](https://github.com/markuplint/markuplint/issues/4560)
20
+ * **markuplint:** report a failure to resolve pretenders as a config-error of the file ([6178627](https://github.com/markuplint/markuplint/commit/61786271a4be989a91e8757c455dbeec9ffe4e9e))
21
+ * **markuplint:** search every tree with --search ([a2e8955](https://github.com/markuplint/markuplint/commit/a2e89552b430e3473c6e7c00c273d05de9b9cdec))
22
+ * **markuplint:** stop --max-count from changing the exit decision ([8dd1b8a](https://github.com/markuplint/markuplint/commit/8dd1b8a86e86c3b0e1410fc22d708baa0282e853)), closes [#4556](https://github.com/markuplint/markuplint/issues/4556)
23
+ * **markuplint:** take configFile as a value of extends is ([789a487](https://github.com/markuplint/markuplint/commit/789a487d3efd257e9e13969674aed9f002b7ee93))
24
+
25
+ ### Features
26
+
27
+ * **markuplint:** describe the parse errors of framework parsers in the parseError option ([095b21a](https://github.com/markuplint/markuplint/commit/095b21af53ec0cc03a7e87a9dd9a26669978b74d))
28
+
29
+
6
30
  # [5.4.0](https://github.com/markuplint/markuplint/compare/v5.3.0...v5.4.0) (2026-10-29)
7
31
 
8
32
  ### Bug Fixes
package/README.md CHANGED
@@ -69,11 +69,13 @@ $ npx markuplint --help
69
69
 
70
70
  Usage
71
71
  $ markuplint <HTML file paths (glob format)>
72
- $ <stdout> | markuplint
72
+ $ <stdout> | markuplint Read the source from the standard input when the output is a terminal. Not with --search, --fix or the suppressions options.
73
+ $ <stdout> | markuplint - Read the source from the standard input. Not with file paths, --search, --fix or the suppressions options.
73
74
 
74
75
  Options
75
76
  --config, -c FILE_PATH A configuration file path.
76
77
  --fix, Fix HTML.
78
+ --fix-dry-run Show what --fix would change without writing files.
77
79
  --format, -f FORMAT Output format. Support "JSON", "Simple", "GitHub" and "Standard". Default: "Standard".
78
80
  --no-search-config No search a configure file automatically.
79
81
  --ignore-ext Evaluate files that are received even though the type of extension.
@@ -86,11 +88,11 @@ Options
86
88
  --show-config Output computed configuration of the target file. Supports "details" and empty. Default: empty.
87
89
  --verbose Output with detailed information.
88
90
  --include-node-modules Include files in node_modules directory. Default: false.
89
- --severity-parse-error Specifies the severity level of parse errors. Supports "error", "warning", and "off". Default: "error".
90
- --severity-deprecation Specifies the severity level of deprecated rule name notices. Supports "error", "warning", and "off". Default: "warning".
91
- --max-count Limit the number of violations shown. Default: 0 (no limit).
91
+ --severity-parse-error Severity for the built-in parse-error channel. Supports "error", "warning", and "off". Unset by default: fatal ParserErrors emit at "error" and non-fatal parse5 and framework parser events are off (opt-in per code via config).
92
+ --severity-deprecation Severity for the built-in rule-deprecation channel (deprecated rule names). Supports "error", "warning", and "off". Default: "warning".
93
+ --max-count Limit the number of violations shown, not the exit code. Default: 0 (no limit).
92
94
  --max-warnings Number of warnings to trigger nonzero exit code. Default: -1 (no limit).
93
- --progressive-output Output results immediately after processing each file. Default: false.
95
+ --no-progressive-output Wait until every file is processed before outputting results. Default: false (output progressively).
94
96
 
95
97
  --suppress [Experimental] Generate/update suppressions file for all current errors.
96
98
  --suppress-rule RULE_ID [Experimental] Suppress only the specified rule.
@@ -105,8 +107,8 @@ Options
105
107
 
106
108
  Examples
107
109
  $ markuplint verifyee.html --config path/to/.markuplintrc
108
- $ markuplint "**/*.html" --max-count=10
109
110
  $ cat verifyee.html | markuplint
111
+ $ cat verifyee.html | markuplint - --format JSON | jq
110
112
  ```
111
113
 
112
114
  ### Bulk Suppressions (Experimental)
@@ -134,6 +136,7 @@ $ markuplint --prune-suppressions "src/**/*.html"
134
136
  - Only `error`-severity violations are suppressed; `warning` and `info` always pass through.
135
137
  - If the number of violations for a file+rule pair **exceeds** the suppressed count, **all** violations for that pair are reported.
136
138
  - `--suppress` always exits with code 0 (success).
139
+ - Running `--suppress` again keeps the entries it does not record, scope included, and gives the ones it records the newly computed scope.
137
140
  - When a DOM tree is available, each suppression entry includes a **scope selector** (computed via LCA) to narrow suppression to a specific subtree. Entries without `scope` apply to the entire file.
138
141
 
139
142
  ```json
@@ -509,10 +509,18 @@ export class MLEngine extends Emitter {
509
509
  * of `@markuplint/shared`'s `errors/index.ts`): any non-fatal error thrown by
510
510
  * the resolution, or a `ConfigLoadError` collected into the config set's
511
511
  * `errs`, fails the file. Tier 1 errors — markuplint's own bugs
512
- * (`isFatalError()`) — are not caught here. The other `errs` (a rule or a
513
- * plugin that is not found, an invalid selector, a circular `extends`)
514
- * leave the rest of the config usable, so they stay `config-error` warnings
515
- * that `MLCore.verify()` reports.
512
+ * (`isFatalError()`) — are not caught here.
513
+ *
514
+ * The pretenders that the config asks for are resolved here as well, and
515
+ * fail the file in the same way. `@markuplint/pretenders` is an optional
516
+ * peer, so a config that needs it fails with how to install it when it is
517
+ * missing; any other non-fatal failure of the resolution, a component that
518
+ * cannot be read for one, is reported as a `config-error` too, instead of
519
+ * rejecting {@link exec} and ending a run that has other files to lint.
520
+ *
521
+ * The other `errs` (a rule or a plugin that is not found, an invalid
522
+ * selector, a circular `extends`) leave the rest of the config usable, so
523
+ * they stay `config-error` warnings that `MLCore.verify()` reports.
516
524
  */
517
525
  async #provide(cache = true) {
518
526
  this.#configFailure = null;
@@ -556,7 +564,19 @@ export class MLEngine extends Emitter {
556
564
  ...configSet.config.severity,
557
565
  ...this.#options?.severity,
558
566
  };
559
- const pretenders = await this.#resolvePretenders(configSet, cache);
567
+ let pretenders;
568
+ try {
569
+ pretenders = await this.#resolvePretenders(configSet, cache);
570
+ }
571
+ catch (error) {
572
+ // What the configuration asks of pretenders cannot be resolved: `@markuplint/pretenders`, an optional
573
+ // peer, is not installed, or a component it reads is unreadable. As with the config itself, that fails
574
+ // this file, not the run.
575
+ if (isFatalError(error) || !(error instanceof Error)) {
576
+ throw error;
577
+ }
578
+ return this.#failConfig(error);
579
+ }
560
580
  fileLog('Resolved pretenders: %O', pretenders);
561
581
  const ruleset = this.#resolveRuleset(configSet);
562
582
  fileLog('Resolved ruleset: %O', ruleset);
@@ -6,6 +6,11 @@ import type { AnyMLRule, FixSummary, MLSchema, Ruleset } from '@markuplint/ml-co
6
6
  * Options for the markuplint API, controlling configuration, locale, rules, and behavior.
7
7
  */
8
8
  export type APIOptions = {
9
+ /**
10
+ * The configuration file to use; the search for one is skipped. Resolved as a value of
11
+ * `extends` is: a module name is loaded as such, and a relative path is based on the working
12
+ * directory, as a relative path in `config` and `defaultConfig` is.
13
+ */
9
14
  readonly configFile?: string;
10
15
  readonly config?: Config;
11
16
  readonly defaultConfig?: Config;
@@ -1,5 +1,5 @@
1
1
  import type { ReadonlyDeep } from 'type-fest';
2
- export declare const help = "\nUsage\n\t$ markuplint <HTML file paths (glob format)>\n\t$ <stdout> | markuplint\n\nOptions\n\t--config, -c FILE_PATH A configuration file path.\n\t--fix, Fix HTML.\n\t--fix-dry-run Show what --fix would change without writing files.\n\t--format, -f FORMAT Output format. Support \"JSON\", \"Simple\", \"GitHub\" and \"Standard\". Default: \"Standard\".\n\t--no-search-config No search a configure file automatically.\n\t--ignore-ext Evaluate files that are received even though the type of extension.\n\t--no-import-preset-rules No import preset rules.\n\t--locale Locale of the message of violation. Default is an OS setting.\n\t--no-color, Output no color.\n\t--problem-only, -p Output only problems, without passeds.\n\t--no-allow-warnings Return status code 1 even if there are warnings.\n\t--allow-empty-input Return status code 1 even if there are no input files.\n\t--show-config Output computed configuration of the target file. Supports \"details\" and empty. Default: empty.\n\t--verbose Output with detailed information.\n\t--include-node-modules Include files in node_modules directory. Default: false.\n\t--severity-parse-error Severity for the built-in parse-error channel. Supports \"error\", \"warning\", and \"off\". Unset by default: fatal ParserErrors emit at \"error\" and non-fatal parse5 events are off (opt-in per code via config).\n\t--severity-deprecation Severity for the built-in rule-deprecation channel (deprecated rule names). Supports \"error\", \"warning\", and \"off\". Default: \"warning\".\n\t--max-count Limit the number of violations shown. Default: 0 (no limit).\n\t--max-warnings Number of warnings to trigger nonzero exit code. Default: -1 (no limit).\n\t--no-progressive-output Wait until every file is processed before outputting results. Default: false (output progressively).\n\n\t--suppress [Experimental] Generate/update suppressions file for all current errors.\n\t--suppress-rule RULE_ID [Experimental] Suppress only the specified rule.\n\t--prune-suppressions [Experimental] Remove stale entries from the suppressions file.\n\t--suppressions-location PATH [Experimental] Custom path for the suppressions file. Default: \"markuplint-suppressions.json\".\n\n\t--init Initialize settings interactively.\n\t--search Search lines of codes that include the target element by selectors.\n\n\t--help, -h Show help.\n\t--version, -v Show version.\n\nExamples\n\t$ markuplint verifyee.html --config path/to/.markuplintrc\n\t$ cat verifyee.html | markuplint\n";
2
+ export declare const help = "\nUsage\n\t$ markuplint <HTML file paths (glob format)>\n\t$ <stdout> | markuplint Read the source from the standard input when the output is a terminal. Not with --search, --fix or the suppressions options.\n\t$ <stdout> | markuplint - Read the source from the standard input. Not with file paths, --search, --fix or the suppressions options.\n\nOptions\n\t--config, -c FILE_PATH A configuration file path.\n\t--fix, Fix HTML.\n\t--fix-dry-run Show what --fix would change without writing files.\n\t--format, -f FORMAT Output format. Support \"JSON\", \"Simple\", \"GitHub\" and \"Standard\". Default: \"Standard\".\n\t--no-search-config No search a configure file automatically.\n\t--ignore-ext Evaluate files that are received even though the type of extension.\n\t--no-import-preset-rules No import preset rules.\n\t--locale Locale of the message of violation. Default is an OS setting.\n\t--no-color, Output no color.\n\t--problem-only, -p Output only problems, without passeds.\n\t--no-allow-warnings Return status code 1 even if there are warnings.\n\t--allow-empty-input Return status code 1 even if there are no input files.\n\t--show-config Output computed configuration of the target file. Supports \"details\" and empty. Default: empty.\n\t--verbose Output with detailed information.\n\t--include-node-modules Include files in node_modules directory. Default: false.\n\t--severity-parse-error Severity for the built-in parse-error channel. Supports \"error\", \"warning\", and \"off\". Unset by default: fatal ParserErrors emit at \"error\" and non-fatal parse5 and framework parser events are off (opt-in per code via config).\n\t--severity-deprecation Severity for the built-in rule-deprecation channel (deprecated rule names). Supports \"error\", \"warning\", and \"off\". Default: \"warning\".\n\t--max-count Limit the number of violations shown, not the exit code. Default: 0 (no limit).\n\t--max-warnings Number of warnings to trigger nonzero exit code. Default: -1 (no limit).\n\t--no-progressive-output Wait until every file is processed before outputting results. Default: false (output progressively).\n\n\t--suppress [Experimental] Generate/update suppressions file for all current errors.\n\t--suppress-rule RULE_ID [Experimental] Suppress only the specified rule.\n\t--prune-suppressions [Experimental] Remove stale entries from the suppressions file.\n\t--suppressions-location PATH [Experimental] Custom path for the suppressions file. Default: \"markuplint-suppressions.json\".\n\n\t--init Initialize settings interactively.\n\t--search Search lines of codes that include the target element by selectors.\n\n\t--help, -h Show help.\n\t--version, -v Show version.\n\nExamples\n\t$ markuplint verifyee.html --config path/to/.markuplintrc\n\t$ cat verifyee.html | markuplint\n\t$ cat verifyee.html | markuplint - --format JSON | jq\n";
3
3
  export declare const cli: import("meow").Result<{
4
4
  config: {
5
5
  type: "string";
@@ -2,7 +2,8 @@ import meow from 'meow';
2
2
  export const help = `
3
3
  Usage
4
4
  $ markuplint <HTML file paths (glob format)>
5
- $ <stdout> | markuplint
5
+ $ <stdout> | markuplint Read the source from the standard input when the output is a terminal. Not with --search, --fix or the suppressions options.
6
+ $ <stdout> | markuplint - Read the source from the standard input. Not with file paths, --search, --fix or the suppressions options.
6
7
 
7
8
  Options
8
9
  --config, -c FILE_PATH A configuration file path.
@@ -20,9 +21,9 @@ Options
20
21
  --show-config Output computed configuration of the target file. Supports "details" and empty. Default: empty.
21
22
  --verbose Output with detailed information.
22
23
  --include-node-modules Include files in node_modules directory. Default: false.
23
- --severity-parse-error Severity for the built-in parse-error channel. Supports "error", "warning", and "off". Unset by default: fatal ParserErrors emit at "error" and non-fatal parse5 events are off (opt-in per code via config).
24
+ --severity-parse-error Severity for the built-in parse-error channel. Supports "error", "warning", and "off". Unset by default: fatal ParserErrors emit at "error" and non-fatal parse5 and framework parser events are off (opt-in per code via config).
24
25
  --severity-deprecation Severity for the built-in rule-deprecation channel (deprecated rule names). Supports "error", "warning", and "off". Default: "warning".
25
- --max-count Limit the number of violations shown. Default: 0 (no limit).
26
+ --max-count Limit the number of violations shown, not the exit code. Default: 0 (no limit).
26
27
  --max-warnings Number of warnings to trigger nonzero exit code. Default: -1 (no limit).
27
28
  --no-progressive-output Wait until every file is processed before outputting results. Default: false (output progressively).
28
29
 
@@ -40,9 +41,13 @@ Options
40
41
  Examples
41
42
  $ markuplint verifyee.html --config path/to/.markuplintrc
42
43
  $ cat verifyee.html | markuplint
44
+ $ cat verifyee.html | markuplint - --format JSON | jq
43
45
  `;
44
46
  export const cli = meow(help, {
45
47
  importMeta: import.meta,
48
+ // `index.ts` prints them: meow ends the process with `process.exit()`, which drops a pending write.
49
+ autoHelp: false,
50
+ autoVersion: false,
46
51
  flags: {
47
52
  config: {
48
53
  type: 'string',
@@ -1,4 +1,22 @@
1
1
  import type { CLIOptions } from './bootstrap.js';
2
2
  import type { APIOptions } from '../api/types.js';
3
3
  import type { Target } from '@markuplint/file-resolver';
4
+ /**
5
+ * Runs the CLI over the given targets and writes the report in the format
6
+ * `--format` selects.
7
+ *
8
+ * @param files Files or source code to lint.
9
+ * @param options The parsed CLI flags.
10
+ * @param apiOptions Options passed through to every `MLEngine`.
11
+ * @returns `true` when the process must exit with `1`: an error, a warning
12
+ * with `--no-allow-warnings`, more warnings than `--max-warnings`, or a
13
+ * usage error such as no target files. The decision does not depend on
14
+ * `--format`: CI reads the exit code whatever format the report is in. Nor
15
+ * does it depend on `--max-count`, which only decides what the report shows:
16
+ * a violation the limit hides, and every violation of a file after the
17
+ * limit, still counts. (`--fix`, `--suppress` and `--prune-suppressions`
18
+ * ignore the limit altogether; see `maxCount` below.)
19
+ * `--show-config`, `--suppress` and `--prune-suppressions` do not lint for
20
+ * a verdict, so they return `false` whatever violations exist.
21
+ */
4
22
  export declare function command(files: readonly Readonly<Target>[], options: CLIOptions, apiOptions?: APIOptions): Promise<boolean>;