markuplint 4.14.1 → 5.0.0-alpha.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 +35 -0
- package/README.md +2 -2
- package/lib/api/ml-engine.js +75 -86
- package/lib/cli/bootstrap.d.ts +2 -2
- package/lib/cli/bootstrap.js +2 -3
- package/lib/cli/init/create-config.js +1 -1
- package/lib/i18n.d.ts +1 -1
- package/lib/i18n.js +3 -10
- package/lib/index.d.ts +0 -4
- package/lib/index.js +0 -4
- package/lib/reporter/github-reporter.js +1 -1
- package/lib/reporter/simple-reporter.js +1 -1
- package/lib/reporter/standard-reporter.js +1 -1
- package/lib/version.js +1 -4
- package/package.json +19 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,41 @@
|
|
|
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.0.0-alpha.1](https://github.com/markuplint/markuplint/compare/v5.0.0-alpha.0...v5.0.0-alpha.1) (2026-02-22)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package markuplint
|
|
9
|
+
|
|
10
|
+
# [5.0.0-alpha.0](https://github.com/markuplint/markuplint/compare/v4.14.1...v5.0.0-alpha.0) (2026-02-20)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **markuplint:** remove async from i18n since os-locale v8 is sync ([3d1f4a6](https://github.com/markuplint/markuplint/commit/3d1f4a68afd2c2a2eac286710d9874dec492c326))
|
|
15
|
+
- **markuplint:** set LANG=en in allow warnings test for CI compatibility ([5d4ea00](https://github.com/markuplint/markuplint/commit/5d4ea003e8153e481b9501b18253757a4b891267))
|
|
16
|
+
- **markuplint:** update os-locale from v6 to v8 ([f10d128](https://github.com/markuplint/markuplint/commit/f10d1280b9dec56ff34fe0d27065f69a61d9231d))
|
|
17
|
+
|
|
18
|
+
- feat!: stop loading default config when --config is specified (#1862) ([1b8aa71](https://github.com/markuplint/markuplint/commit/1b8aa710bad65fa626e55a0ebae80d591b915e31)), closes [#1862](https://github.com/markuplint/markuplint/issues/1862)
|
|
19
|
+
- feat!: remove deprecated v1 API ([f8999ae](https://github.com/markuplint/markuplint/commit/f8999aecc8e05c3ba2022a93698c87b01bbd573b))
|
|
20
|
+
- feat(markuplint)!: wire ruleCommonSettings and set allowWarnings default to true ([79524a4](https://github.com/markuplint/markuplint/commit/79524a407f1bf5015c700d11599c4caca0d3a33d))
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
- delete htmx-parser, simplify alpine-parser, add migration guide and tests ([f8dbb09](https://github.com/markuplint/markuplint/commit/f8dbb090707d8cfbf3d859a9b868b2087064f89b))
|
|
25
|
+
- **markuplint:** display virtual rule names in reporters ([39a0473](https://github.com/markuplint/markuplint/commit/39a04737926d254d72082a1091b931c72b68cbc6))
|
|
26
|
+
- **rules:** add redundant-accessible-name rule for detecting overridden accessible name sources ([63b89d4](https://github.com/markuplint/markuplint/commit/63b89d47bf5056f823d5b27cda4fda2b96419bb3))
|
|
27
|
+
|
|
28
|
+
### BREAKING CHANGES
|
|
29
|
+
|
|
30
|
+
- `--config` no longer merges with auto-discovered config files.
|
|
31
|
+
|
|
32
|
+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
33
|
+
|
|
34
|
+
- The `exec` export (v1 API) has been removed.
|
|
35
|
+
|
|
36
|
+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
37
|
+
|
|
38
|
+
- --allow-warnings now defaults to true. Use --no-allow-warnings
|
|
39
|
+
to restore the previous behavior of returning exit code 1 when warnings exist.
|
|
40
|
+
|
|
6
41
|
## [4.14.1](https://github.com/markuplint/markuplint/compare/markuplint@4.14.0...markuplint@4.14.1) (2026-02-10)
|
|
7
42
|
|
|
8
43
|
**Note:** Version bump only for package markuplint
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
$ npx markuplint target.html
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
Supported for _Node.js_ `
|
|
28
|
+
Supported for _Node.js_ `v22.0.0` or later.
|
|
29
29
|
|
|
30
30
|
## Usage
|
|
31
31
|
|
|
@@ -81,7 +81,7 @@ Options
|
|
|
81
81
|
--locale Locale of the message of violation. Default is an OS setting.
|
|
82
82
|
--no-color, Output no color.
|
|
83
83
|
--problem-only, -p Output only problems, without passeds.
|
|
84
|
-
--allow-warnings
|
|
84
|
+
--no-allow-warnings Return status code 1 even if there are warnings.
|
|
85
85
|
--allow-empty-input Return status code 1 even if there are no input files.
|
|
86
86
|
--show-config Output computed configuration of the target file. Supports "details" and empty. Default: empty.
|
|
87
87
|
--verbose Output with detailed information.
|
package/lib/api/ml-engine.js
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
7
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
|
-
};
|
|
12
|
-
var _MLEngine_configProvider, _MLEngine_core, _MLEngine_file, _MLEngine_options, _MLEngine_watcher;
|
|
13
1
|
import { ConfigProvider, resolveFiles, resolveParser, resolvePretenders, resolveRules, resolveSpecs, } from '@markuplint/file-resolver';
|
|
14
2
|
import { mergeConfig } from '@markuplint/ml-config';
|
|
15
3
|
import { MLCore, convertRuleset } from '@markuplint/ml-core';
|
|
@@ -61,37 +49,37 @@ export class MLEngine extends Emitter {
|
|
|
61
49
|
const files = await resolveFiles([target]);
|
|
62
50
|
return files[0];
|
|
63
51
|
}
|
|
52
|
+
#configProvider;
|
|
53
|
+
#core = null;
|
|
54
|
+
#file;
|
|
55
|
+
#options;
|
|
56
|
+
#watcher = new FSWatcher();
|
|
64
57
|
constructor(file, options) {
|
|
65
58
|
super();
|
|
66
|
-
|
|
67
|
-
_MLEngine_core.set(this, null);
|
|
68
|
-
_MLEngine_file.set(this, void 0);
|
|
69
|
-
_MLEngine_options.set(this, void 0);
|
|
70
|
-
_MLEngine_watcher.set(this, new FSWatcher());
|
|
71
|
-
if (__classPrivateFieldGet(this, _MLEngine_options, "f")?.debug) {
|
|
59
|
+
if (this.#options?.debug) {
|
|
72
60
|
verbosely();
|
|
73
61
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.watchMode(!!
|
|
78
|
-
log('[MLEngine] Initialized: %s',
|
|
62
|
+
this.#file = file;
|
|
63
|
+
this.#options = options;
|
|
64
|
+
this.#configProvider = new ConfigProvider();
|
|
65
|
+
this.watchMode(!!this.#options?.watch);
|
|
66
|
+
log('[MLEngine] Initialized: %s', this.#file.path);
|
|
79
67
|
}
|
|
80
68
|
/**
|
|
81
69
|
* The parsed document, or `null` if not yet set up or if parsing failed.
|
|
82
70
|
*/
|
|
83
71
|
get document() {
|
|
84
|
-
if (
|
|
72
|
+
if (this.#core?.document instanceof Error) {
|
|
85
73
|
return null;
|
|
86
74
|
}
|
|
87
|
-
return
|
|
75
|
+
return this.#core?.document ?? null;
|
|
88
76
|
}
|
|
89
77
|
/**
|
|
90
78
|
* Closes the engine, removing all event listeners and stopping the file watcher.
|
|
91
79
|
*/
|
|
92
80
|
async close() {
|
|
93
81
|
this.removeAllListeners();
|
|
94
|
-
await
|
|
82
|
+
await this.#watcher.close();
|
|
95
83
|
}
|
|
96
84
|
/**
|
|
97
85
|
* Executes linting on the target file and returns the results.
|
|
@@ -107,16 +95,16 @@ export class MLEngine extends Emitter {
|
|
|
107
95
|
log('exec: cancel (unsetuped yet)');
|
|
108
96
|
return null;
|
|
109
97
|
}
|
|
110
|
-
const violations = await core.verify(
|
|
98
|
+
const violations = await core.verify(this.#options?.fix).catch(error => {
|
|
111
99
|
if (error instanceof Error) {
|
|
112
100
|
return error;
|
|
113
101
|
}
|
|
114
102
|
throw error;
|
|
115
103
|
});
|
|
116
|
-
const sourceCode = await
|
|
104
|
+
const sourceCode = await this.#file.getCode();
|
|
117
105
|
const fixedCode = core.document.toString(true);
|
|
118
106
|
if (violations instanceof Error) {
|
|
119
|
-
this.emit('lint-error',
|
|
107
|
+
this.emit('lint-error', this.#file.path, sourceCode, violations);
|
|
120
108
|
const errMessage = violations.stack ?? violations.message;
|
|
121
109
|
log('exec: error %O', errMessage);
|
|
122
110
|
return {
|
|
@@ -130,18 +118,18 @@ export class MLEngine extends Emitter {
|
|
|
130
118
|
raw: '',
|
|
131
119
|
},
|
|
132
120
|
],
|
|
133
|
-
filePath:
|
|
121
|
+
filePath: this.#file.path,
|
|
134
122
|
sourceCode,
|
|
135
123
|
fixedCode,
|
|
136
124
|
status: 'processed',
|
|
137
125
|
};
|
|
138
126
|
}
|
|
139
127
|
const debugMap = 'debugMap' in core.document ? core.document.debugMap() : null;
|
|
140
|
-
this.emit('lint',
|
|
128
|
+
this.emit('lint', this.#file.path, sourceCode, violations, fixedCode, debugMap);
|
|
141
129
|
log('exec: end');
|
|
142
130
|
return {
|
|
143
131
|
violations,
|
|
144
|
-
filePath:
|
|
132
|
+
filePath: this.#file.path,
|
|
145
133
|
sourceCode,
|
|
146
134
|
fixedCode,
|
|
147
135
|
status: 'processed',
|
|
@@ -157,7 +145,7 @@ export class MLEngine extends Emitter {
|
|
|
157
145
|
if (!core) {
|
|
158
146
|
return;
|
|
159
147
|
}
|
|
160
|
-
|
|
148
|
+
this.#file.setCode(code);
|
|
161
149
|
core.setCode(code);
|
|
162
150
|
}
|
|
163
151
|
/**
|
|
@@ -167,40 +155,40 @@ export class MLEngine extends Emitter {
|
|
|
167
155
|
* @param enable - Whether to enable watch mode
|
|
168
156
|
*/
|
|
169
157
|
watchMode(enable) {
|
|
170
|
-
|
|
171
|
-
...
|
|
158
|
+
this.#options = {
|
|
159
|
+
...this.#options,
|
|
172
160
|
watch: enable,
|
|
173
|
-
}
|
|
161
|
+
};
|
|
174
162
|
if (enable) {
|
|
175
|
-
|
|
163
|
+
this.#watcher.on('change', this.onChange.bind(this));
|
|
176
164
|
}
|
|
177
165
|
else {
|
|
178
|
-
|
|
166
|
+
this.#watcher.removeAllListeners();
|
|
179
167
|
}
|
|
180
168
|
}
|
|
181
169
|
async createCore(fabric) {
|
|
182
170
|
fileLog('Get source code');
|
|
183
|
-
const sourceCode = await
|
|
184
|
-
fileLog('Source code path: %s',
|
|
171
|
+
const sourceCode = await this.#file.getCode();
|
|
172
|
+
fileLog('Source code path: %s', this.#file.path);
|
|
185
173
|
// cspell: disable-next-line
|
|
186
174
|
fileLog('Source code size: %dbyte', sourceCode.length);
|
|
187
|
-
this.emit('code',
|
|
175
|
+
this.emit('code', this.#file.path, sourceCode);
|
|
188
176
|
const core = new MLCore({
|
|
189
177
|
sourceCode,
|
|
190
|
-
filename:
|
|
191
|
-
debug:
|
|
178
|
+
filename: this.#file.path,
|
|
179
|
+
debug: this.#options?.debug,
|
|
192
180
|
...fabric,
|
|
193
181
|
});
|
|
194
|
-
|
|
182
|
+
this.#core = core;
|
|
195
183
|
return core;
|
|
196
184
|
}
|
|
197
|
-
|
|
198
|
-
const i18nSettings =
|
|
199
|
-
this.emit('i18n',
|
|
185
|
+
i18n() {
|
|
186
|
+
const i18nSettings = i18n(this.#options?.locale);
|
|
187
|
+
this.emit('i18n', this.#file.path, i18nSettings);
|
|
200
188
|
return i18nSettings;
|
|
201
189
|
}
|
|
202
190
|
async onChange(filePath) {
|
|
203
|
-
if (!
|
|
191
|
+
if (!this.#options?.watch) {
|
|
204
192
|
return;
|
|
205
193
|
}
|
|
206
194
|
this.emit('log', 'watch:onChange', filePath);
|
|
@@ -209,10 +197,10 @@ export class MLEngine extends Emitter {
|
|
|
209
197
|
return;
|
|
210
198
|
}
|
|
211
199
|
if (fabric.configErrors) {
|
|
212
|
-
this.emit('config-errors',
|
|
200
|
+
this.emit('config-errors', this.#file.path, fabric.configErrors);
|
|
213
201
|
}
|
|
214
|
-
this.emit('log', 'update:core',
|
|
215
|
-
|
|
202
|
+
this.emit('log', 'update:core', this.#file.path);
|
|
203
|
+
this.#core?.update(fabric);
|
|
216
204
|
await this.exec();
|
|
217
205
|
}
|
|
218
206
|
async provide(cache = true) {
|
|
@@ -237,27 +225,27 @@ export class MLEngine extends Emitter {
|
|
|
237
225
|
fileLog('Resolved Config: %O', configSet.config);
|
|
238
226
|
fileLog('Resolved Plugins: %O', configSet.plugins);
|
|
239
227
|
fileLog('Resolve Errors: %O', configSet.errs);
|
|
240
|
-
if (!(await
|
|
241
|
-
this.emit('log', 'file-no-exists', `The file doesn't exist or it is not a file: ${
|
|
242
|
-
fileLog("The file doesn't exist or it is not a file: %s",
|
|
228
|
+
if (!(await this.#file.isFile())) {
|
|
229
|
+
this.emit('log', 'file-no-exists', `The file doesn't exist or it is not a file: ${this.#file.path}`);
|
|
230
|
+
fileLog("The file doesn't exist or it is not a file: %s", this.#file.path);
|
|
243
231
|
return null;
|
|
244
232
|
}
|
|
245
233
|
// Exclude
|
|
246
234
|
const excludeFiles = configSet.config.excludeFiles ?? [];
|
|
247
|
-
if (
|
|
248
|
-
fileLog('Excludes the file: %s',
|
|
235
|
+
if (this.#file.ignored(excludeFiles)) {
|
|
236
|
+
fileLog('Excludes the file: %s', this.#file.path);
|
|
249
237
|
return null;
|
|
250
238
|
}
|
|
251
239
|
const { parser, parserOptions, matched } = await this.resolveParser(configSet);
|
|
252
|
-
const checkingExt = !
|
|
240
|
+
const checkingExt = !this.#options?.ignoreExt;
|
|
253
241
|
if (checkingExt && !matched) {
|
|
254
|
-
this.emit('log', 'ext-unmatched', `Avoided linting because a file is unmatched by the extension: ${
|
|
255
|
-
fileLog('Avoided linting because a file is unmatched by the extension: %s',
|
|
242
|
+
this.emit('log', 'ext-unmatched', `Avoided linting because a file is unmatched by the extension: ${this.#file.path}`);
|
|
243
|
+
fileLog('Avoided linting because a file is unmatched by the extension: %s', this.#file.path);
|
|
256
244
|
return null;
|
|
257
245
|
}
|
|
258
246
|
const severity = {
|
|
259
247
|
...configSet.config.severity,
|
|
260
|
-
...
|
|
248
|
+
...this.#options?.severity,
|
|
261
249
|
};
|
|
262
250
|
const pretenders = await this.resolvePretenders(configSet);
|
|
263
251
|
fileLog('Resolved pretenders: %O', pretenders);
|
|
@@ -278,7 +266,8 @@ export class MLEngine extends Emitter {
|
|
|
278
266
|
}
|
|
279
267
|
const rules = await this.resolveRules(configSet.plugins, ruleset);
|
|
280
268
|
fileLog('Resolved rules: %O', rules);
|
|
281
|
-
const locale =
|
|
269
|
+
const locale = i18n(this.#options?.locale);
|
|
270
|
+
const ruleCommonSettings = configSet.config.ruleCommonSettings ?? {};
|
|
282
271
|
if (fileLog.enabled) {
|
|
283
272
|
fileLog('Loaded %d rules: %O', rules.length, rules.map(r => r.name));
|
|
284
273
|
}
|
|
@@ -291,46 +280,47 @@ export class MLEngine extends Emitter {
|
|
|
291
280
|
schemas,
|
|
292
281
|
rules,
|
|
293
282
|
locale,
|
|
283
|
+
ruleCommonSettings,
|
|
294
284
|
configErrors: configSet.errs,
|
|
295
285
|
};
|
|
296
286
|
}
|
|
297
287
|
async resolveConfig(cache) {
|
|
298
|
-
this.emit('log', 'resolveConfig', JSON.stringify(
|
|
299
|
-
configLog('configProvider: %s',
|
|
300
|
-
const defaultConfigKey =
|
|
288
|
+
this.emit('log', 'resolveConfig', JSON.stringify(this.#configProvider, null, 2));
|
|
289
|
+
configLog('configProvider: %s', this.#configProvider);
|
|
290
|
+
const defaultConfigKey = this.#options?.defaultConfig && this.#configProvider.set(mergeConfig(this.#options?.defaultConfig));
|
|
301
291
|
configLog('defaultConfigKey: %s', defaultConfigKey ?? 'N/A');
|
|
302
292
|
this.emit('log', 'defaultConfigKey', defaultConfigKey ?? 'N/A');
|
|
303
|
-
const targetConfig = await
|
|
293
|
+
const targetConfig = await this.#configProvider.search(this.#file);
|
|
304
294
|
this.emit('log', 'targetConfig', targetConfig ?? 'N/A');
|
|
305
|
-
const configFilePathsFromTarget =
|
|
295
|
+
const configFilePathsFromTarget = this.#options?.noSearchConfig || this.#options?.configFile
|
|
306
296
|
? (defaultConfigKey ?? null)
|
|
307
297
|
: (targetConfig ?? defaultConfigKey);
|
|
308
298
|
configLog('configFilePathsFromTarget: %s', configFilePathsFromTarget ?? 'N/A');
|
|
309
299
|
this.emit('log', 'configFilePathsFromTarget', configFilePathsFromTarget ?? 'N/A');
|
|
310
|
-
const configKey =
|
|
300
|
+
const configKey = this.#options?.config && this.#configProvider.set(mergeConfig(this.#options.config));
|
|
311
301
|
configLog('option.config: %s', configKey ?? 'N/A');
|
|
312
302
|
this.emit('log', 'option.config', configFilePathsFromTarget ?? 'N/A');
|
|
313
303
|
let defaultRecommended = null;
|
|
314
|
-
if (!defaultConfigKey && !configFilePathsFromTarget && !configKey) {
|
|
304
|
+
if (!defaultConfigKey && !configFilePathsFromTarget && !configKey && !this.#options?.configFile) {
|
|
315
305
|
// No configured
|
|
316
306
|
// Default: set recommended
|
|
317
|
-
defaultRecommended =
|
|
307
|
+
defaultRecommended = this.#configProvider.set({ extends: ['markuplint:recommended'] });
|
|
318
308
|
}
|
|
319
309
|
configLog('defaultRecommended: %s', defaultRecommended ?? 'N/A');
|
|
320
310
|
this.emit('log', 'defaultRecommended', defaultRecommended ?? 'N/A');
|
|
321
|
-
const configSet = await
|
|
322
|
-
this.emit('config',
|
|
323
|
-
if (
|
|
311
|
+
const configSet = await this.#configProvider.resolve(this.#file, [configFilePathsFromTarget, this.#options?.configFile, configKey, defaultRecommended], cache);
|
|
312
|
+
this.emit('config', this.#file.path, configSet);
|
|
313
|
+
if (this.#options?.watch) {
|
|
324
314
|
// It doesn't watch the main HTML file because it may is watched and managed by a language server or text editor or more.
|
|
325
|
-
|
|
315
|
+
this.#watcher.add([...configSet.files]);
|
|
326
316
|
}
|
|
327
317
|
return configSet;
|
|
328
318
|
}
|
|
329
319
|
async resolveParser(
|
|
330
320
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
331
321
|
configSet) {
|
|
332
|
-
const parser = await resolveParser(
|
|
333
|
-
this.emit('parser',
|
|
322
|
+
const parser = await resolveParser(this.#file, configSet.config.parser, configSet.config.parserOptions);
|
|
323
|
+
this.emit('parser', this.#file.path, parser.parserModName);
|
|
334
324
|
fileLog('Fetched Parser module: %s', parser.parserModName);
|
|
335
325
|
return parser;
|
|
336
326
|
}
|
|
@@ -342,39 +332,38 @@ export class MLEngine extends Emitter {
|
|
|
342
332
|
return pretenders;
|
|
343
333
|
}
|
|
344
334
|
async resolveRules(plugins, ruleset) {
|
|
345
|
-
const rules = await resolveRules(plugins, ruleset,
|
|
346
|
-
if (
|
|
347
|
-
rules.push(...
|
|
335
|
+
const rules = await resolveRules(plugins, ruleset, this.#options?.importPresetRules ?? true, this.#options?.autoLoad ?? true);
|
|
336
|
+
if (this.#options?.rules) {
|
|
337
|
+
rules.push(...this.#options.rules);
|
|
348
338
|
}
|
|
349
|
-
this.emit('rules',
|
|
339
|
+
this.emit('rules', this.#file.path, rules);
|
|
350
340
|
return rules;
|
|
351
341
|
}
|
|
352
342
|
resolveRuleset(
|
|
353
343
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
354
344
|
configSet) {
|
|
355
345
|
const ruleset = convertRuleset(configSet.config);
|
|
356
|
-
this.emit('ruleset',
|
|
346
|
+
this.emit('ruleset', this.#file.path, ruleset);
|
|
357
347
|
return ruleset;
|
|
358
348
|
}
|
|
359
349
|
async resolveSchemas(
|
|
360
350
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
361
351
|
configSet) {
|
|
362
|
-
const { schemas } = await resolveSpecs(
|
|
363
|
-
this.emit('schemas',
|
|
352
|
+
const { schemas } = await resolveSpecs(this.#file.path, configSet.config.specs);
|
|
353
|
+
this.emit('schemas', this.#file.path, schemas);
|
|
364
354
|
return schemas;
|
|
365
355
|
}
|
|
366
356
|
async setup() {
|
|
367
|
-
if (
|
|
368
|
-
return
|
|
357
|
+
if (this.#core) {
|
|
358
|
+
return this.#core;
|
|
369
359
|
}
|
|
370
360
|
const fabric = await this.provide();
|
|
371
361
|
if (!fabric) {
|
|
372
362
|
return null;
|
|
373
363
|
}
|
|
374
364
|
if (fabric.configErrors) {
|
|
375
|
-
this.emit('config-errors',
|
|
365
|
+
this.emit('config-errors', this.#file.path, fabric.configErrors);
|
|
376
366
|
}
|
|
377
367
|
return this.createCore(fabric);
|
|
378
368
|
}
|
|
379
369
|
}
|
|
380
|
-
_MLEngine_configProvider = new WeakMap(), _MLEngine_core = new WeakMap(), _MLEngine_file = new WeakMap(), _MLEngine_options = new WeakMap(), _MLEngine_watcher = new WeakMap();
|
package/lib/cli/bootstrap.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { ReadonlyDeep } from 'type-fest';
|
|
|
3
3
|
* Help text displayed when the CLI is invoked with `--help` or without arguments.
|
|
4
4
|
* Documents all available options, flags, and usage examples.
|
|
5
5
|
*/
|
|
6
|
-
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
|
|
6
|
+
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--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 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\t--progressive-output Output results immediately after processing each file. Default: false.\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";
|
|
7
7
|
/**
|
|
8
8
|
* The parsed CLI instance created by `meow`, providing access to
|
|
9
9
|
* positional arguments (`cli.input`) and parsed flags (`cli.flags`).
|
|
@@ -47,7 +47,7 @@ export declare const cli: import("meow").Result<{
|
|
|
47
47
|
};
|
|
48
48
|
allowWarnings: {
|
|
49
49
|
type: "boolean";
|
|
50
|
-
default:
|
|
50
|
+
default: true;
|
|
51
51
|
};
|
|
52
52
|
allowEmptyInput: {
|
|
53
53
|
type: "boolean";
|
package/lib/cli/bootstrap.js
CHANGED
|
@@ -18,7 +18,7 @@ Options
|
|
|
18
18
|
--locale Locale of the message of violation. Default is an OS setting.
|
|
19
19
|
--no-color, Output no color.
|
|
20
20
|
--problem-only, -p Output only problems, without passeds.
|
|
21
|
-
--allow-warnings
|
|
21
|
+
--no-allow-warnings Return status code 1 even if there are warnings.
|
|
22
22
|
--allow-empty-input Return status code 1 even if there are no input files.
|
|
23
23
|
--show-config Output computed configuration of the target file. Supports "details" and empty. Default: empty.
|
|
24
24
|
--verbose Output with detailed information.
|
|
@@ -83,8 +83,7 @@ export const cli = meow(help, {
|
|
|
83
83
|
},
|
|
84
84
|
allowWarnings: {
|
|
85
85
|
type: 'boolean',
|
|
86
|
-
|
|
87
|
-
default: false,
|
|
86
|
+
default: true,
|
|
88
87
|
},
|
|
89
88
|
allowEmptyInput: {
|
|
90
89
|
type: 'boolean',
|
package/lib/i18n.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ import type { LocaleSet } from '@markuplint/i18n';
|
|
|
8
8
|
* @param locale - An optional BCP 47 locale string (e.g., `"ja"`, `"en-US"`).
|
|
9
9
|
* @returns The loaded locale set containing translated messages and the resolved locale code.
|
|
10
10
|
*/
|
|
11
|
-
export declare function i18n(locale?: string):
|
|
11
|
+
export declare function i18n(locale?: string): LocaleSet;
|
package/lib/i18n.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import osLocale from 'os-locale';
|
|
2
2
|
import { getJsonModule } from './get-json-module.js';
|
|
3
|
-
let cachedLocale = null;
|
|
4
|
-
async function getLocale() {
|
|
5
|
-
if (!cachedLocale) {
|
|
6
|
-
cachedLocale = await osLocale({ spawn: true });
|
|
7
|
-
}
|
|
8
|
-
return cachedLocale;
|
|
9
|
-
}
|
|
10
3
|
/**
|
|
11
4
|
* Loads the locale-specific message set for use in violation messages.
|
|
12
5
|
*
|
|
@@ -16,8 +9,8 @@ async function getLocale() {
|
|
|
16
9
|
* @param locale - An optional BCP 47 locale string (e.g., `"ja"`, `"en-US"`).
|
|
17
10
|
* @returns The loaded locale set containing translated messages and the resolved locale code.
|
|
18
11
|
*/
|
|
19
|
-
export
|
|
20
|
-
locale = locale ?? (
|
|
12
|
+
export function i18n(locale) {
|
|
13
|
+
locale = locale ?? osLocale() ?? 'en';
|
|
21
14
|
const langCode = locale.split('-')[0] ?? locale;
|
|
22
15
|
const loadLocaleSet = getJsonModule(`@markuplint/i18n/locales/${langCode}.json`);
|
|
23
16
|
const localeSet = loadLocaleSet ?? getJsonModule('@markuplint/i18n/locales/en.json');
|
package/lib/index.d.ts
CHANGED
|
@@ -17,7 +17,3 @@ export * from './testing-tool/index.js';
|
|
|
17
17
|
export * from './types.js';
|
|
18
18
|
/** The current markuplint package version string. */
|
|
19
19
|
export { version } from './version.js';
|
|
20
|
-
/**
|
|
21
|
-
* @deprecated Use the current API exports instead.
|
|
22
|
-
*/
|
|
23
|
-
export * from './v1.js';
|
package/lib/index.js
CHANGED
|
@@ -15,7 +15,3 @@ export * from './testing-tool/index.js';
|
|
|
15
15
|
export * from './types.js';
|
|
16
16
|
/** The current markuplint package version string. */
|
|
17
17
|
export { version } from './version.js';
|
|
18
|
-
/**
|
|
19
|
-
* @deprecated Use the current API exports instead.
|
|
20
|
-
*/
|
|
21
|
-
export * from './v1.js';
|
|
@@ -13,7 +13,7 @@ export function githubReporter(results) {
|
|
|
13
13
|
for (const violation of results.violations) {
|
|
14
14
|
const command = severityToCommand(violation.severity);
|
|
15
15
|
const meg = messageToString(violation.message, violation.reason);
|
|
16
|
-
out.push(`::${command} file=${results.filePath},line=${violation.line},col=${violation.col}::${meg} (${violation.ruleId})`);
|
|
16
|
+
out.push(`::${command} file=${results.filePath},line=${violation.line},col=${violation.col}::${meg} (${violation.name ?? violation.ruleId})`);
|
|
17
17
|
}
|
|
18
18
|
return out;
|
|
19
19
|
}
|
|
@@ -31,7 +31,7 @@ export function simpleReporter(results, options) {
|
|
|
31
31
|
for (const violation of results.violations) {
|
|
32
32
|
const s = violation.severity === 'error' ? loggerError('✖') : loggerWarning('⚠️');
|
|
33
33
|
const meg = messageToString(violation.message, violation.reason);
|
|
34
|
-
out.push(` ${font.cyan(`${pad(violation.line, sizes.line, true)}:${pad(violation.col, sizes.col)}`)} ${s} ${pad(meg, sizes.meg)} ${xterm(8)(violation.ruleId)} `);
|
|
34
|
+
out.push(` ${font.cyan(`${pad(violation.line, sizes.line, true)}:${pad(violation.col, sizes.col)}`)} ${s} ${pad(meg, sizes.meg)} ${xterm(8)(violation.name ?? violation.ruleId)} `);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
else if (!options.problemOnly) {
|
|
@@ -34,7 +34,7 @@ export function standardReporter(results, options) {
|
|
|
34
34
|
const meg = messageToString(violation.message, violation.reason);
|
|
35
35
|
const startLine = violation.line - 1;
|
|
36
36
|
// Main message
|
|
37
|
-
out.push(`<${commandName}> ${logger(`${violation.severity}: ${meg} (${violation.ruleId}) ${font.underline(`${results.filePath}:${violation.line}:${violation.col}`)}`)}`);
|
|
37
|
+
out.push(`<${commandName}> ${logger(`${violation.severity}: ${meg} (${violation.name ?? violation.ruleId}) ${font.underline(`${results.filePath}:${violation.line}:${violation.col}`)}`)}`);
|
|
38
38
|
// Previous line
|
|
39
39
|
if (startLine > 0) {
|
|
40
40
|
const prev = lines[startLine - 1] ?? '';
|
package/lib/version.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
const require = createRequire(import.meta.url);
|
|
3
|
-
// TODO: Use import attribute in Node.js v22 and v20.10 or later
|
|
4
|
-
const pkg = require('../package.json');
|
|
1
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
5
2
|
/**
|
|
6
3
|
* The current version string of the markuplint package, read from `package.json`.
|
|
7
4
|
*/
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markuplint",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-alpha.1",
|
|
4
4
|
"description": "An HTML linter for all markup developers",
|
|
5
5
|
"author": "Yusuke Hirao",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22"
|
|
9
|
+
},
|
|
7
10
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
8
11
|
"type": "module",
|
|
9
12
|
"exports": {
|
|
@@ -23,25 +26,25 @@
|
|
|
23
26
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@markuplint/cli-utils": "
|
|
27
|
-
"@markuplint/file-resolver": "
|
|
28
|
-
"@markuplint/html-parser": "
|
|
29
|
-
"@markuplint/html-spec": "
|
|
30
|
-
"@markuplint/i18n": "
|
|
31
|
-
"@markuplint/ml-ast": "
|
|
32
|
-
"@markuplint/ml-config": "
|
|
33
|
-
"@markuplint/ml-core": "
|
|
34
|
-
"@markuplint/ml-spec": "
|
|
35
|
-
"@markuplint/rules": "
|
|
36
|
-
"@markuplint/shared": "
|
|
29
|
+
"@markuplint/cli-utils": "5.0.0-alpha.1",
|
|
30
|
+
"@markuplint/file-resolver": "5.0.0-alpha.1",
|
|
31
|
+
"@markuplint/html-parser": "5.0.0-alpha.1",
|
|
32
|
+
"@markuplint/html-spec": "5.0.0-alpha.1",
|
|
33
|
+
"@markuplint/i18n": "5.0.0-alpha.1",
|
|
34
|
+
"@markuplint/ml-ast": "5.0.0-alpha.1",
|
|
35
|
+
"@markuplint/ml-config": "5.0.0-alpha.1",
|
|
36
|
+
"@markuplint/ml-core": "5.0.0-alpha.1",
|
|
37
|
+
"@markuplint/ml-spec": "5.0.0-alpha.1",
|
|
38
|
+
"@markuplint/rules": "5.0.0-alpha.1",
|
|
39
|
+
"@markuplint/shared": "5.0.0-alpha.1",
|
|
37
40
|
"@types/debug": "4.1.12",
|
|
38
41
|
"chokidar": "5.0.0",
|
|
39
42
|
"debug": "4.4.3",
|
|
40
|
-
"meow": "
|
|
41
|
-
"os-locale": "
|
|
43
|
+
"meow": "14.1.0",
|
|
44
|
+
"os-locale": "8.0.0",
|
|
42
45
|
"strict-event-emitter": "0.5.1",
|
|
43
46
|
"strip-ansi": "7.1.2",
|
|
44
|
-
"type-fest": "4.
|
|
47
|
+
"type-fest": "5.4.4"
|
|
45
48
|
},
|
|
46
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "78a295e73a097a1ce09c777c06fa21ab68136387"
|
|
47
50
|
}
|