markuplint 4.12.0 → 4.13.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/CHANGELOG.md +25 -0
- package/README.md +3 -0
- package/lib/api/ml-engine.js +2 -0
- package/lib/cli/bootstrap.d.ts +9 -1
- package/lib/cli/bootstrap.js +10 -0
- package/lib/cli/command.js +62 -10
- package/lib/cli/index.js +2 -2
- package/lib/reporter/simple-reporter.js +2 -1
- package/lib/reporter/standard-reporter.js +3 -1
- package/lib/types.d.ts +1 -0
- package/package.json +17 -21
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,31 @@
|
|
|
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
|
+
## [4.13.1](https://github.com/markuplint/markuplint/compare/markuplint@4.13.0...markuplint@4.13.1) (2025-08-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package markuplint
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# [4.13.0](https://github.com/markuplint/markuplint/compare/markuplint@4.12.0...markuplint@4.13.0) (2025-08-13)
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
- ensure that each `clean` command correctly removes build files ([110b78e](https://github.com/markuplint/markuplint/commit/110b78e85379d29a84ca68325127344a87a570b6))
|
|
19
|
+
- **markuplint:** remove duplicate test for cross-platform compatibility ([d7af614](https://github.com/markuplint/markuplint/commit/d7af6142892a1b4ba4ae196e53df4480817044ff))
|
|
20
|
+
|
|
21
|
+
### Features
|
|
22
|
+
|
|
23
|
+
- **markuplint:** add --max-violations CLI option ([3ec868d](https://github.com/markuplint/markuplint/commit/3ec868d5e666993a6220a352081100947c31f999))
|
|
24
|
+
- **markuplint:** add --max-warnings option for incremental adoption ([b14513d](https://github.com/markuplint/markuplint/commit/b14513d952b3c47330aba2ce8c4b31714bbc1625)), closes [#2523](https://github.com/markuplint/markuplint/issues/2523)
|
|
25
|
+
- **markuplint:** add maxViolations support to API layer ([cb6d577](https://github.com/markuplint/markuplint/commit/cb6d577483a38e32a378d89a13e950c0eb311b09))
|
|
26
|
+
- **markuplint:** add skip status display to reporters ([5c1f189](https://github.com/markuplint/markuplint/commit/5c1f1897c76b42fc97fce4ce2edd75dd31470abd))
|
|
27
|
+
- **markuplint:** add status field to MLResultInfo and simplify verification ([56deb99](https://github.com/markuplint/markuplint/commit/56deb999a330bb7d91333dc464a034cbc6010479))
|
|
28
|
+
- **markuplint:** add truncation info message to standard reporter ([9c9a21d](https://github.com/markuplint/markuplint/commit/9c9a21dcc01b391a68d23cc315254b69039d9afc))
|
|
29
|
+
- **markuplint:** implement max-count option with skip status tracking ([20ca12d](https://github.com/markuplint/markuplint/commit/20ca12d391bcf8f09eae4c8786ba688ef7192506))
|
|
30
|
+
|
|
6
31
|
# [4.12.0](https://github.com/markuplint/markuplint/compare/markuplint@4.11.8...markuplint@4.12.0) (2025-04-13)
|
|
7
32
|
|
|
8
33
|
### Features
|
package/README.md
CHANGED
|
@@ -87,6 +87,8 @@ Options
|
|
|
87
87
|
--verbose Output with detailed information.
|
|
88
88
|
--include-node-modules Include files in node_modules directory. Default: false.
|
|
89
89
|
--severity-parse-error Specifies the severity level of parse errors. Supports "error", "warning", and "off". Default: "error".
|
|
90
|
+
--max-count Limit the number of violations shown. Default: 0 (no limit).
|
|
91
|
+
--max-warnings Number of warnings to trigger nonzero exit code. Default: -1 (no limit).
|
|
90
92
|
|
|
91
93
|
--init Initialize settings interactively.
|
|
92
94
|
--search Search lines of codes that include the target element by selectors.
|
|
@@ -96,6 +98,7 @@ Options
|
|
|
96
98
|
|
|
97
99
|
Examples
|
|
98
100
|
$ markuplint verifyee.html --config path/to/.markuplintrc
|
|
101
|
+
$ markuplint "**/*.html" --max-count=10
|
|
99
102
|
$ cat verifyee.html | markuplint
|
|
100
103
|
```
|
|
101
104
|
|
package/lib/api/ml-engine.js
CHANGED
|
@@ -101,6 +101,7 @@ export class MLEngine extends Emitter {
|
|
|
101
101
|
filePath: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
|
|
102
102
|
sourceCode,
|
|
103
103
|
fixedCode,
|
|
104
|
+
status: 'processed',
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
107
|
const debugMap = 'debugMap' in core.document ? core.document.debugMap() : null;
|
|
@@ -111,6 +112,7 @@ export class MLEngine extends Emitter {
|
|
|
111
112
|
filePath: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
|
|
112
113
|
sourceCode,
|
|
113
114
|
fixedCode,
|
|
115
|
+
status: 'processed',
|
|
114
116
|
};
|
|
115
117
|
}
|
|
116
118
|
async setCode(code) {
|
package/lib/cli/bootstrap.d.ts
CHANGED
|
@@ -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--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--allow-warnings Return status code 0 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 Specifies the severity level of parse errors. Supports \"error\", \"warning\", and \"off\". Default: \"error\".\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\n\nOptions\n\t--config, -c FILE_PATH A configuration file path.\n\t--fix, Fix HTML.\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--allow-warnings Return status code 0 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 Specifies the severity level of parse errors. Supports \"error\", \"warning\", and \"off\". Default: \"error\".\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\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";
|
|
3
3
|
export declare const cli: import("meow").Result<{
|
|
4
4
|
config: {
|
|
5
5
|
type: "string";
|
|
@@ -71,5 +71,13 @@ export declare const cli: import("meow").Result<{
|
|
|
71
71
|
type: "string";
|
|
72
72
|
default: string;
|
|
73
73
|
};
|
|
74
|
+
maxCount: {
|
|
75
|
+
type: "number";
|
|
76
|
+
default: number;
|
|
77
|
+
};
|
|
78
|
+
maxWarnings: {
|
|
79
|
+
type: "number";
|
|
80
|
+
default: number;
|
|
81
|
+
};
|
|
74
82
|
}>;
|
|
75
83
|
export type CLIOptions = ReadonlyDeep<typeof cli.flags>;
|
package/lib/cli/bootstrap.js
CHANGED
|
@@ -20,6 +20,8 @@ Options
|
|
|
20
20
|
--verbose Output with detailed information.
|
|
21
21
|
--include-node-modules Include files in node_modules directory. Default: false.
|
|
22
22
|
--severity-parse-error Specifies the severity level of parse errors. Supports "error", "warning", and "off". Default: "error".
|
|
23
|
+
--max-count Limit the number of violations shown. Default: 0 (no limit).
|
|
24
|
+
--max-warnings Number of warnings to trigger nonzero exit code. Default: -1 (no limit).
|
|
23
25
|
|
|
24
26
|
--init Initialize settings interactively.
|
|
25
27
|
--search Search lines of codes that include the target element by selectors.
|
|
@@ -105,5 +107,13 @@ export const cli = meow(help, {
|
|
|
105
107
|
type: 'string',
|
|
106
108
|
default: 'error',
|
|
107
109
|
},
|
|
110
|
+
maxCount: {
|
|
111
|
+
type: 'number',
|
|
112
|
+
default: 0,
|
|
113
|
+
},
|
|
114
|
+
maxWarnings: {
|
|
115
|
+
type: 'number',
|
|
116
|
+
default: -1,
|
|
117
|
+
},
|
|
108
118
|
},
|
|
109
119
|
});
|
package/lib/cli/command.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { resolveFiles } from '@markuplint/file-resolver';
|
|
4
|
+
import { ViolationCollector } from '@markuplint/ml-core';
|
|
4
5
|
import { MLEngine } from '../api/index.js';
|
|
5
6
|
import { log } from '../debug.js';
|
|
6
7
|
import { output } from './output.js';
|
|
@@ -27,7 +28,11 @@ export async function command(files, options, apiOptions) {
|
|
|
27
28
|
}
|
|
28
29
|
const format = options.format?.toLowerCase().trim();
|
|
29
30
|
let hasError = false;
|
|
30
|
-
|
|
31
|
+
let totalWarningCount = 0;
|
|
32
|
+
const collector = new ViolationCollector(options.maxCount);
|
|
33
|
+
const processedFiles = [];
|
|
34
|
+
const skippedFiles = [];
|
|
35
|
+
const filesContent = new Map();
|
|
31
36
|
const severityParseError = options.severityParseError.toLowerCase();
|
|
32
37
|
const severity = {
|
|
33
38
|
parseError: ['error', 'warning', 'off'].includes(severityParseError)
|
|
@@ -35,6 +40,12 @@ export async function command(files, options, apiOptions) {
|
|
|
35
40
|
: true,
|
|
36
41
|
};
|
|
37
42
|
for (const file of fileList) {
|
|
43
|
+
// Check if collector is already locked (max-count reached)
|
|
44
|
+
if (collector.isLocked()) {
|
|
45
|
+
log('Skipping file due to max-count limit: %s', file.path);
|
|
46
|
+
skippedFiles.push(file.path);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
38
49
|
const engine = new MLEngine(file, {
|
|
39
50
|
configFile,
|
|
40
51
|
fix,
|
|
@@ -72,8 +83,18 @@ export async function command(files, options, apiOptions) {
|
|
|
72
83
|
if (!result) {
|
|
73
84
|
continue;
|
|
74
85
|
}
|
|
86
|
+
// Track processed file
|
|
87
|
+
processedFiles.push(result.filePath);
|
|
88
|
+
filesContent.set(result.filePath, {
|
|
89
|
+
sourceCode: result.sourceCode,
|
|
90
|
+
fixedCode: result.fixedCode,
|
|
91
|
+
});
|
|
92
|
+
// Add violations to collector
|
|
93
|
+
collector.pushWithFile(result.filePath, ...result.violations);
|
|
75
94
|
const errorCount = result.violations.filter(v => v.severity === 'error').length;
|
|
76
95
|
const warningCount = result.violations.filter(v => v.severity === 'warning').length;
|
|
96
|
+
// Track total warning count across all files
|
|
97
|
+
totalWarningCount += warningCount;
|
|
77
98
|
if (!hasError && (errorCount > 0 || (warningCount > 0 && !options.allowWarnings))) {
|
|
78
99
|
hasError = true;
|
|
79
100
|
}
|
|
@@ -81,19 +102,50 @@ export async function command(files, options, apiOptions) {
|
|
|
81
102
|
log('Overwrite file: %s', result.filePath);
|
|
82
103
|
await fs.writeFile(result.filePath, result.fixedCode, { encoding: 'utf8' });
|
|
83
104
|
}
|
|
84
|
-
if (format === 'json') {
|
|
85
|
-
jsonOutput.push(...result.violations.map(v => ({
|
|
86
|
-
...v,
|
|
87
|
-
filePath: result.filePath,
|
|
88
|
-
})));
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
log('Output reports');
|
|
92
|
-
output(result, options);
|
|
93
105
|
}
|
|
106
|
+
// Output results
|
|
94
107
|
if (format === 'json') {
|
|
108
|
+
const jsonOutput = collector.toArray();
|
|
95
109
|
process.stdout.write(JSON.stringify(jsonOutput, null, 2) + '\n');
|
|
96
110
|
return false;
|
|
97
111
|
}
|
|
112
|
+
// For standard/simple/github output, group violations by file
|
|
113
|
+
const violationsByFile = collector.groupByFile();
|
|
114
|
+
// Output per file - include processed files without violations
|
|
115
|
+
for (const filePath of processedFiles) {
|
|
116
|
+
const violations = violationsByFile.get(filePath) || [];
|
|
117
|
+
const content = filesContent.get(filePath) || { sourceCode: '', fixedCode: '' };
|
|
118
|
+
if (violations.length === 0 && !options.problemOnly) {
|
|
119
|
+
log('Output reports');
|
|
120
|
+
output({
|
|
121
|
+
violations,
|
|
122
|
+
filePath,
|
|
123
|
+
sourceCode: content.sourceCode,
|
|
124
|
+
fixedCode: content.fixedCode,
|
|
125
|
+
status: 'processed',
|
|
126
|
+
}, options);
|
|
127
|
+
}
|
|
128
|
+
else if (violations.length > 0) {
|
|
129
|
+
log('Output reports');
|
|
130
|
+
output({
|
|
131
|
+
violations,
|
|
132
|
+
filePath,
|
|
133
|
+
sourceCode: content.sourceCode,
|
|
134
|
+
fixedCode: content.fixedCode,
|
|
135
|
+
status: 'processed',
|
|
136
|
+
}, options);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Output skipped files
|
|
140
|
+
if (!options.problemOnly) {
|
|
141
|
+
for (const filePath of skippedFiles) {
|
|
142
|
+
log('Output skipped file report');
|
|
143
|
+
output({ violations: [], filePath, sourceCode: '', fixedCode: '', status: 'skipped' }, options);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Check if max-warnings limit is exceeded (ESLint compatible)
|
|
147
|
+
if (!hasError && options.maxWarnings >= 0 && totalWarningCount > options.maxWarnings) {
|
|
148
|
+
hasError = true;
|
|
149
|
+
}
|
|
98
150
|
return hasError;
|
|
99
151
|
}
|
package/lib/cli/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { text } from 'node:stream/consumers';
|
|
2
2
|
import { verbosely } from '../debug.js';
|
|
3
3
|
import { cli } from './bootstrap.js';
|
|
4
4
|
import { command } from './command.js';
|
|
@@ -40,7 +40,7 @@ if (files.length > 0) {
|
|
|
40
40
|
process.exit(hasError ? 1 : 0);
|
|
41
41
|
}
|
|
42
42
|
if (usePipe()) {
|
|
43
|
-
const stdin = await
|
|
43
|
+
const stdin = await text(process.stdin).catch(error => {
|
|
44
44
|
// eslint-disable-next-line no-console
|
|
45
45
|
console.warn(error);
|
|
46
46
|
process.exit(1);
|
|
@@ -24,7 +24,8 @@ export function simpleReporter(results, options) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
else if (!options.problemOnly) {
|
|
27
|
-
|
|
27
|
+
const icon = results.status === 'skipped' ? font.yellow('⚠') : font.green('✓');
|
|
28
|
+
out.push(`<${commandName}> ${font.underline(results.filePath)}: ${icon}`);
|
|
28
29
|
}
|
|
29
30
|
return out;
|
|
30
31
|
}
|
|
@@ -52,7 +52,9 @@ export function standardReporter(results, options) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
else if (!options.problemOnly) {
|
|
55
|
-
|
|
55
|
+
const message = results.status === 'skipped' ? 'skipped' : 'passed';
|
|
56
|
+
const color = results.status === 'skipped' ? font.yellow : font.green;
|
|
57
|
+
out.push(`<${commandName}> ${color(message)} ${font.underline(results.filePath)}`);
|
|
56
58
|
}
|
|
57
59
|
return out;
|
|
58
60
|
}
|
package/lib/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markuplint",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.13.1",
|
|
4
4
|
"description": "An HTML linter for all markup developers",
|
|
5
5
|
"author": "Yusuke Hirao",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"private": false,
|
|
8
7
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
9
8
|
"type": "module",
|
|
10
9
|
"exports": {
|
|
@@ -17,35 +16,32 @@
|
|
|
17
16
|
"typedoc": {
|
|
18
17
|
"entryPoint": "./src/index.ts"
|
|
19
18
|
},
|
|
20
|
-
"bin":
|
|
21
|
-
"markuplint": "./bin/markuplint.mjs"
|
|
22
|
-
},
|
|
19
|
+
"bin": "./bin/markuplint.mjs",
|
|
23
20
|
"scripts": {
|
|
24
21
|
"build": "tsc --project tsconfig.build.json",
|
|
25
22
|
"dev": "tsc --watch --project tsconfig.build.json",
|
|
26
|
-
"clean": "tsc --build --clean"
|
|
23
|
+
"clean": "tsc --build --clean tsconfig.build.json"
|
|
27
24
|
},
|
|
28
25
|
"dependencies": {
|
|
29
|
-
"@markuplint/cli-utils": "4.4.
|
|
30
|
-
"@markuplint/file-resolver": "4.9.
|
|
31
|
-
"@markuplint/html-parser": "4.6.
|
|
32
|
-
"@markuplint/html-spec": "4.
|
|
33
|
-
"@markuplint/i18n": "4.
|
|
34
|
-
"@markuplint/ml-ast": "4.4.
|
|
35
|
-
"@markuplint/ml-config": "4.8.
|
|
36
|
-
"@markuplint/ml-core": "4.
|
|
37
|
-
"@markuplint/ml-spec": "4.
|
|
38
|
-
"@markuplint/rules": "4.
|
|
39
|
-
"@markuplint/shared": "4.4.
|
|
26
|
+
"@markuplint/cli-utils": "4.4.12",
|
|
27
|
+
"@markuplint/file-resolver": "4.9.16",
|
|
28
|
+
"@markuplint/html-parser": "4.6.21",
|
|
29
|
+
"@markuplint/html-spec": "4.16.0",
|
|
30
|
+
"@markuplint/i18n": "4.7.0",
|
|
31
|
+
"@markuplint/ml-ast": "4.4.10",
|
|
32
|
+
"@markuplint/ml-config": "4.8.13",
|
|
33
|
+
"@markuplint/ml-core": "4.13.1",
|
|
34
|
+
"@markuplint/ml-spec": "4.10.0",
|
|
35
|
+
"@markuplint/rules": "4.11.1",
|
|
36
|
+
"@markuplint/shared": "4.4.12",
|
|
40
37
|
"@types/debug": "4.1.12",
|
|
41
38
|
"chokidar": "4.0.3",
|
|
42
|
-
"debug": "4.4.
|
|
43
|
-
"get-stdin": "9.0.0",
|
|
39
|
+
"debug": "4.4.1",
|
|
44
40
|
"meow": "13.2.0",
|
|
45
41
|
"os-locale": "6.0.2",
|
|
46
42
|
"strict-event-emitter": "0.5.1",
|
|
47
43
|
"strip-ansi": "7.1.0",
|
|
48
|
-
"type-fest": "4.
|
|
44
|
+
"type-fest": "4.41.0"
|
|
49
45
|
},
|
|
50
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "ae97eb2d31ecedf4f0800fbbf18588aad4ebca04"
|
|
51
47
|
}
|