markuplint 4.14.1 → 5.0.0-alpha.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,37 @@
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.0](https://github.com/markuplint/markuplint/compare/v4.14.1...v5.0.0-alpha.0) (2026-02-20)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **markuplint:** remove async from i18n since os-locale v8 is sync ([3d1f4a6](https://github.com/markuplint/markuplint/commit/3d1f4a68afd2c2a2eac286710d9874dec492c326))
11
+ - **markuplint:** set LANG=en in allow warnings test for CI compatibility ([5d4ea00](https://github.com/markuplint/markuplint/commit/5d4ea003e8153e481b9501b18253757a4b891267))
12
+ - **markuplint:** update os-locale from v6 to v8 ([f10d128](https://github.com/markuplint/markuplint/commit/f10d1280b9dec56ff34fe0d27065f69a61d9231d))
13
+
14
+ - 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)
15
+ - feat!: remove deprecated v1 API ([f8999ae](https://github.com/markuplint/markuplint/commit/f8999aecc8e05c3ba2022a93698c87b01bbd573b))
16
+ - feat(markuplint)!: wire ruleCommonSettings and set allowWarnings default to true ([79524a4](https://github.com/markuplint/markuplint/commit/79524a407f1bf5015c700d11599c4caca0d3a33d))
17
+
18
+ ### Features
19
+
20
+ - delete htmx-parser, simplify alpine-parser, add migration guide and tests ([f8dbb09](https://github.com/markuplint/markuplint/commit/f8dbb090707d8cfbf3d859a9b868b2087064f89b))
21
+ - **markuplint:** display virtual rule names in reporters ([39a0473](https://github.com/markuplint/markuplint/commit/39a04737926d254d72082a1091b931c72b68cbc6))
22
+ - **rules:** add redundant-accessible-name rule for detecting overridden accessible name sources ([63b89d4](https://github.com/markuplint/markuplint/commit/63b89d47bf5056f823d5b27cda4fda2b96419bb3))
23
+
24
+ ### BREAKING CHANGES
25
+
26
+ - `--config` no longer merges with auto-discovered config files.
27
+
28
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
29
+
30
+ - The `exec` export (v1 API) has been removed.
31
+
32
+ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
33
+
34
+ - --allow-warnings now defaults to true. Use --no-allow-warnings
35
+ to restore the previous behavior of returning exit code 1 when warnings exist.
36
+
6
37
  ## [4.14.1](https://github.com/markuplint/markuplint/compare/markuplint@4.14.0...markuplint@4.14.1) (2026-02-10)
7
38
 
8
39
  **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_ `v18.18.0` or later.
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 Return status code 0 even if there are 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.
@@ -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
- _MLEngine_configProvider.set(this, void 0);
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
- __classPrivateFieldSet(this, _MLEngine_file, file, "f");
75
- __classPrivateFieldSet(this, _MLEngine_options, options, "f");
76
- __classPrivateFieldSet(this, _MLEngine_configProvider, new ConfigProvider(), "f");
77
- this.watchMode(!!__classPrivateFieldGet(this, _MLEngine_options, "f")?.watch);
78
- log('[MLEngine] Initialized: %s', __classPrivateFieldGet(this, _MLEngine_file, "f").path);
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 (__classPrivateFieldGet(this, _MLEngine_core, "f")?.document instanceof Error) {
72
+ if (this.#core?.document instanceof Error) {
85
73
  return null;
86
74
  }
87
- return __classPrivateFieldGet(this, _MLEngine_core, "f")?.document ?? null;
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 __classPrivateFieldGet(this, _MLEngine_watcher, "f").close();
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(__classPrivateFieldGet(this, _MLEngine_options, "f")?.fix).catch(error => {
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 __classPrivateFieldGet(this, _MLEngine_file, "f").getCode();
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', __classPrivateFieldGet(this, _MLEngine_file, "f").path, sourceCode, violations);
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: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
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', __classPrivateFieldGet(this, _MLEngine_file, "f").path, sourceCode, violations, fixedCode, debugMap);
128
+ this.emit('lint', this.#file.path, sourceCode, violations, fixedCode, debugMap);
141
129
  log('exec: end');
142
130
  return {
143
131
  violations,
144
- filePath: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
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
- __classPrivateFieldGet(this, _MLEngine_file, "f").setCode(code);
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
- __classPrivateFieldSet(this, _MLEngine_options, {
171
- ...__classPrivateFieldGet(this, _MLEngine_options, "f"),
158
+ this.#options = {
159
+ ...this.#options,
172
160
  watch: enable,
173
- }, "f");
161
+ };
174
162
  if (enable) {
175
- __classPrivateFieldGet(this, _MLEngine_watcher, "f").on('change', this.onChange.bind(this));
163
+ this.#watcher.on('change', this.onChange.bind(this));
176
164
  }
177
165
  else {
178
- __classPrivateFieldGet(this, _MLEngine_watcher, "f").removeAllListeners();
166
+ this.#watcher.removeAllListeners();
179
167
  }
180
168
  }
181
169
  async createCore(fabric) {
182
170
  fileLog('Get source code');
183
- const sourceCode = await __classPrivateFieldGet(this, _MLEngine_file, "f").getCode();
184
- fileLog('Source code path: %s', __classPrivateFieldGet(this, _MLEngine_file, "f").path);
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', __classPrivateFieldGet(this, _MLEngine_file, "f").path, sourceCode);
175
+ this.emit('code', this.#file.path, sourceCode);
188
176
  const core = new MLCore({
189
177
  sourceCode,
190
- filename: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
191
- debug: __classPrivateFieldGet(this, _MLEngine_options, "f")?.debug,
178
+ filename: this.#file.path,
179
+ debug: this.#options?.debug,
192
180
  ...fabric,
193
181
  });
194
- __classPrivateFieldSet(this, _MLEngine_core, core, "f");
182
+ this.#core = core;
195
183
  return core;
196
184
  }
197
- async i18n() {
198
- const i18nSettings = await i18n(__classPrivateFieldGet(this, _MLEngine_options, "f")?.locale);
199
- this.emit('i18n', __classPrivateFieldGet(this, _MLEngine_file, "f").path, i18nSettings);
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 (!__classPrivateFieldGet(this, _MLEngine_options, "f")?.watch) {
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', __classPrivateFieldGet(this, _MLEngine_file, "f").path, fabric.configErrors);
200
+ this.emit('config-errors', this.#file.path, fabric.configErrors);
213
201
  }
214
- this.emit('log', 'update:core', __classPrivateFieldGet(this, _MLEngine_file, "f").path);
215
- __classPrivateFieldGet(this, _MLEngine_core, "f")?.update(fabric);
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 __classPrivateFieldGet(this, _MLEngine_file, "f").isFile())) {
241
- this.emit('log', 'file-no-exists', `The file doesn't exist or it is not a file: ${__classPrivateFieldGet(this, _MLEngine_file, "f").path}`);
242
- fileLog("The file doesn't exist or it is not a file: %s", __classPrivateFieldGet(this, _MLEngine_file, "f").path);
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 (__classPrivateFieldGet(this, _MLEngine_file, "f").ignored(excludeFiles)) {
248
- fileLog('Excludes the file: %s', __classPrivateFieldGet(this, _MLEngine_file, "f").path);
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 = !__classPrivateFieldGet(this, _MLEngine_options, "f")?.ignoreExt;
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: ${__classPrivateFieldGet(this, _MLEngine_file, "f").path}`);
255
- fileLog('Avoided linting because a file is unmatched by the extension: %s', __classPrivateFieldGet(this, _MLEngine_file, "f").path);
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
- ...__classPrivateFieldGet(this, _MLEngine_options, "f")?.severity,
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 = await i18n(__classPrivateFieldGet(this, _MLEngine_options, "f")?.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(__classPrivateFieldGet(this, _MLEngine_configProvider, "f"), null, 2));
299
- configLog('configProvider: %s', __classPrivateFieldGet(this, _MLEngine_configProvider, "f"));
300
- const defaultConfigKey = __classPrivateFieldGet(this, _MLEngine_options, "f")?.defaultConfig && __classPrivateFieldGet(this, _MLEngine_configProvider, "f").set(mergeConfig(__classPrivateFieldGet(this, _MLEngine_options, "f")?.defaultConfig));
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 __classPrivateFieldGet(this, _MLEngine_configProvider, "f").search(__classPrivateFieldGet(this, _MLEngine_file, "f"));
293
+ const targetConfig = await this.#configProvider.search(this.#file);
304
294
  this.emit('log', 'targetConfig', targetConfig ?? 'N/A');
305
- const configFilePathsFromTarget = __classPrivateFieldGet(this, _MLEngine_options, "f")?.noSearchConfig
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 = __classPrivateFieldGet(this, _MLEngine_options, "f")?.config && __classPrivateFieldGet(this, _MLEngine_configProvider, "f").set(mergeConfig(__classPrivateFieldGet(this, _MLEngine_options, "f").config));
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 = __classPrivateFieldGet(this, _MLEngine_configProvider, "f").set({ extends: ['markuplint:recommended'] });
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 __classPrivateFieldGet(this, _MLEngine_configProvider, "f").resolve(__classPrivateFieldGet(this, _MLEngine_file, "f"), [configFilePathsFromTarget, __classPrivateFieldGet(this, _MLEngine_options, "f")?.configFile, configKey, defaultRecommended], cache);
322
- this.emit('config', __classPrivateFieldGet(this, _MLEngine_file, "f").path, configSet);
323
- if (__classPrivateFieldGet(this, _MLEngine_options, "f")?.watch) {
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
- __classPrivateFieldGet(this, _MLEngine_watcher, "f").add([...configSet.files]);
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(__classPrivateFieldGet(this, _MLEngine_file, "f"), configSet.config.parser, configSet.config.parserOptions);
333
- this.emit('parser', __classPrivateFieldGet(this, _MLEngine_file, "f").path, parser.parserModName);
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, __classPrivateFieldGet(this, _MLEngine_options, "f")?.importPresetRules ?? true, __classPrivateFieldGet(this, _MLEngine_options, "f")?.autoLoad ?? true);
346
- if (__classPrivateFieldGet(this, _MLEngine_options, "f")?.rules) {
347
- rules.push(...__classPrivateFieldGet(this, _MLEngine_options, "f").rules);
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', __classPrivateFieldGet(this, _MLEngine_file, "f").path, 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', __classPrivateFieldGet(this, _MLEngine_file, "f").path, 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(__classPrivateFieldGet(this, _MLEngine_file, "f").path, configSet.config.specs);
363
- this.emit('schemas', __classPrivateFieldGet(this, _MLEngine_file, "f").path, 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 (__classPrivateFieldGet(this, _MLEngine_core, "f")) {
368
- return __classPrivateFieldGet(this, _MLEngine_core, "f");
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', __classPrivateFieldGet(this, _MLEngine_file, "f").path, fabric.configErrors);
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();
@@ -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 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\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";
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: false;
50
+ default: true;
51
51
  };
52
52
  allowEmptyInput: {
53
53
  type: "boolean";
@@ -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 Return status code 0 even if there are 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
- // TODO: It will be changed to `true` in the next major version.
87
- default: false,
86
+ default: true,
88
87
  },
89
88
  allowEmptyInput: {
90
89
  type: 'boolean',
@@ -99,7 +99,7 @@ export function createConfig(langs, mode, defaultRules) {
99
99
  ...config,
100
100
  specs: {
101
101
  ...config.specs,
102
- '\\.html': '@markuplint/alpine-parser/spec',
102
+ '\\.html': '@markuplint/alpine-spec',
103
103
  },
104
104
  };
105
105
  }
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): Promise<LocaleSet>;
11
+ export declare function i18n(locale?: string): LocaleSet;
package/lib/i18n.js CHANGED
@@ -1,12 +1,5 @@
1
- import { osLocale } from 'os-locale';
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 async function i18n(locale) {
20
- locale = locale ?? (await getLocale()) ?? 'en';
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 { createRequire } from 'node:module';
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": "4.14.1",
3
+ "version": "5.0.0-alpha.0",
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": "4.4.14",
27
- "@markuplint/file-resolver": "4.9.18",
28
- "@markuplint/html-parser": "4.6.23",
29
- "@markuplint/html-spec": "4.17.0",
30
- "@markuplint/i18n": "4.7.1",
31
- "@markuplint/ml-ast": "4.4.11",
32
- "@markuplint/ml-config": "4.8.15",
33
- "@markuplint/ml-core": "4.13.3",
34
- "@markuplint/ml-spec": "4.10.2",
35
- "@markuplint/rules": "4.12.0",
36
- "@markuplint/shared": "4.4.13",
29
+ "@markuplint/cli-utils": "5.0.0-alpha.0",
30
+ "@markuplint/file-resolver": "5.0.0-alpha.0",
31
+ "@markuplint/html-parser": "5.0.0-alpha.0",
32
+ "@markuplint/html-spec": "5.0.0-alpha.0",
33
+ "@markuplint/i18n": "5.0.0-alpha.0",
34
+ "@markuplint/ml-ast": "5.0.0-alpha.0",
35
+ "@markuplint/ml-config": "5.0.0-alpha.0",
36
+ "@markuplint/ml-core": "5.0.0-alpha.0",
37
+ "@markuplint/ml-spec": "5.0.0-alpha.0",
38
+ "@markuplint/rules": "5.0.0-alpha.0",
39
+ "@markuplint/shared": "5.0.0-alpha.0",
37
40
  "@types/debug": "4.1.12",
38
41
  "chokidar": "5.0.0",
39
42
  "debug": "4.4.3",
40
- "meow": "13.2.0",
41
- "os-locale": "6.0.2",
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.41.0"
47
+ "type-fest": "5.4.4"
45
48
  },
46
- "gitHead": "193ee7c1262bbed95424e38efdf1a8e56ff049f4"
49
+ "gitHead": "13dcfc84ec83d87360c720e253383b60767e1b56"
47
50
  }