markuplint 4.14.0 → 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.
Files changed (61) hide show
  1. package/ARCHITECTURE.ja.md +419 -0
  2. package/ARCHITECTURE.md +419 -0
  3. package/CHANGELOG.md +32 -2
  4. package/README.md +2 -2
  5. package/SKILL.md +110 -0
  6. package/docs/maintenance.ja.md +207 -0
  7. package/docs/maintenance.md +207 -0
  8. package/lib/api/index.d.ts +8 -0
  9. package/lib/api/index.js +8 -0
  10. package/lib/api/lint.d.ts +7 -0
  11. package/lib/api/lint.js +7 -0
  12. package/lib/api/ml-engine.d.ts +48 -0
  13. package/lib/api/ml-engine.js +118 -86
  14. package/lib/api/types.d.ts +6 -0
  15. package/lib/api/v1.d.ts +8 -3
  16. package/lib/api/v1.js +8 -3
  17. package/lib/cli/bootstrap.d.ts +14 -2
  18. package/lib/cli/bootstrap.js +10 -3
  19. package/lib/cli/command.d.ts +12 -0
  20. package/lib/cli/command.js +12 -0
  21. package/lib/cli/index.d.ts +7 -0
  22. package/lib/cli/index.js +7 -0
  23. package/lib/cli/init/create-config.d.ts +16 -0
  24. package/lib/cli/init/create-config.js +21 -1
  25. package/lib/cli/init/get-default-rules.d.ts +9 -0
  26. package/lib/cli/init/get-default-rules.js +9 -0
  27. package/lib/cli/init/index.d.ts +14 -0
  28. package/lib/cli/init/index.js +14 -0
  29. package/lib/cli/init/select-modules.d.ts +10 -0
  30. package/lib/cli/init/select-modules.js +10 -0
  31. package/lib/cli/init/types.d.ts +19 -0
  32. package/lib/cli/output.d.ts +11 -0
  33. package/lib/cli/output.js +11 -0
  34. package/lib/cli/search/index.d.ts +17 -0
  35. package/lib/cli/search/index.js +17 -0
  36. package/lib/debug.d.ts +9 -0
  37. package/lib/debug.js +9 -0
  38. package/lib/get-json-module.d.ts +10 -0
  39. package/lib/get-json-module.js +10 -0
  40. package/lib/global-settings.d.ts +15 -0
  41. package/lib/global-settings.js +12 -0
  42. package/lib/i18n.d.ts +10 -1
  43. package/lib/i18n.js +12 -10
  44. package/lib/index.d.ts +13 -4
  45. package/lib/index.js +12 -4
  46. package/lib/reporter/github-reporter.d.ts +9 -0
  47. package/lib/reporter/github-reporter.js +10 -1
  48. package/lib/reporter/index.d.ts +9 -0
  49. package/lib/reporter/index.js +9 -0
  50. package/lib/reporter/simple-reporter.d.ts +11 -0
  51. package/lib/reporter/simple-reporter.js +12 -1
  52. package/lib/reporter/standard-reporter.d.ts +12 -0
  53. package/lib/reporter/standard-reporter.js +13 -1
  54. package/lib/testing-tool/index.d.ts +44 -0
  55. package/lib/testing-tool/index.js +32 -0
  56. package/lib/types.d.ts +3 -0
  57. package/lib/v1.d.ts +3 -1
  58. package/lib/v1.js +3 -1
  59. package/lib/version.d.ts +3 -0
  60. package/lib/version.js +4 -4
  61. package/package.json +20 -17
@@ -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';
@@ -20,7 +8,20 @@ import { i18n } from '../i18n.js';
20
8
  const log = coreLog.extend('ml-engine');
21
9
  const fileLog = log.extend('file');
22
10
  const configLog = log.extend('config');
11
+ /**
12
+ * The main markuplint engine that orchestrates file resolution, configuration loading,
13
+ * parsing, and linting. Supports both single-file and watch-mode operation.
14
+ *
15
+ * Emits events at each stage of the linting pipeline for monitoring and debugging.
16
+ */
23
17
  export class MLEngine extends Emitter {
18
+ /**
19
+ * Creates an MLEngine instance from inline source code.
20
+ *
21
+ * @param sourceCode - The markup source code to lint
22
+ * @param options - Options for configuration, naming, and behavior
23
+ * @returns A new MLEngine instance ready to lint the provided code
24
+ */
24
25
  static async fromCode(sourceCode, options) {
25
26
  if (options?.debug) {
26
27
  verbosely();
@@ -38,36 +39,55 @@ export class MLEngine extends Emitter {
38
39
  const engine = new MLEngine(file, options);
39
40
  return engine;
40
41
  }
42
+ /**
43
+ * Converts a target (file path or inline source) into an MLFile instance.
44
+ *
45
+ * @param target - A file path string or inline source code target
46
+ * @returns The resolved MLFile, or `undefined` if resolution failed
47
+ */
41
48
  static async toMLFile(target) {
42
49
  const files = await resolveFiles([target]);
43
50
  return files[0];
44
51
  }
52
+ #configProvider;
53
+ #core = null;
54
+ #file;
55
+ #options;
56
+ #watcher = new FSWatcher();
45
57
  constructor(file, options) {
46
58
  super();
47
- _MLEngine_configProvider.set(this, void 0);
48
- _MLEngine_core.set(this, null);
49
- _MLEngine_file.set(this, void 0);
50
- _MLEngine_options.set(this, void 0);
51
- _MLEngine_watcher.set(this, new FSWatcher());
52
- if (__classPrivateFieldGet(this, _MLEngine_options, "f")?.debug) {
59
+ if (this.#options?.debug) {
53
60
  verbosely();
54
61
  }
55
- __classPrivateFieldSet(this, _MLEngine_file, file, "f");
56
- __classPrivateFieldSet(this, _MLEngine_options, options, "f");
57
- __classPrivateFieldSet(this, _MLEngine_configProvider, new ConfigProvider(), "f");
58
- this.watchMode(!!__classPrivateFieldGet(this, _MLEngine_options, "f")?.watch);
59
- 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);
60
67
  }
68
+ /**
69
+ * The parsed document, or `null` if not yet set up or if parsing failed.
70
+ */
61
71
  get document() {
62
- if (__classPrivateFieldGet(this, _MLEngine_core, "f")?.document instanceof Error) {
72
+ if (this.#core?.document instanceof Error) {
63
73
  return null;
64
74
  }
65
- return __classPrivateFieldGet(this, _MLEngine_core, "f")?.document ?? null;
75
+ return this.#core?.document ?? null;
66
76
  }
77
+ /**
78
+ * Closes the engine, removing all event listeners and stopping the file watcher.
79
+ */
67
80
  async close() {
68
81
  this.removeAllListeners();
69
- await __classPrivateFieldGet(this, _MLEngine_watcher, "f").close();
82
+ await this.#watcher.close();
70
83
  }
84
+ /**
85
+ * Executes linting on the target file and returns the results.
86
+ *
87
+ * Sets up the engine on first call, then verifies the document against all rules.
88
+ *
89
+ * @returns The lint result including violations and fixed code, or `null` if setup was skipped
90
+ */
71
91
  async exec() {
72
92
  log('exec: start');
73
93
  const core = await this.setup();
@@ -75,16 +95,16 @@ export class MLEngine extends Emitter {
75
95
  log('exec: cancel (unsetuped yet)');
76
96
  return null;
77
97
  }
78
- const violations = await core.verify(__classPrivateFieldGet(this, _MLEngine_options, "f")?.fix).catch(error => {
98
+ const violations = await core.verify(this.#options?.fix).catch(error => {
79
99
  if (error instanceof Error) {
80
100
  return error;
81
101
  }
82
102
  throw error;
83
103
  });
84
- const sourceCode = await __classPrivateFieldGet(this, _MLEngine_file, "f").getCode();
104
+ const sourceCode = await this.#file.getCode();
85
105
  const fixedCode = core.document.toString(true);
86
106
  if (violations instanceof Error) {
87
- this.emit('lint-error', __classPrivateFieldGet(this, _MLEngine_file, "f").path, sourceCode, violations);
107
+ this.emit('lint-error', this.#file.path, sourceCode, violations);
88
108
  const errMessage = violations.stack ?? violations.message;
89
109
  log('exec: error %O', errMessage);
90
110
  return {
@@ -98,66 +118,77 @@ export class MLEngine extends Emitter {
98
118
  raw: '',
99
119
  },
100
120
  ],
101
- filePath: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
121
+ filePath: this.#file.path,
102
122
  sourceCode,
103
123
  fixedCode,
104
124
  status: 'processed',
105
125
  };
106
126
  }
107
127
  const debugMap = 'debugMap' in core.document ? core.document.debugMap() : null;
108
- this.emit('lint', __classPrivateFieldGet(this, _MLEngine_file, "f").path, sourceCode, violations, fixedCode, debugMap);
128
+ this.emit('lint', this.#file.path, sourceCode, violations, fixedCode, debugMap);
109
129
  log('exec: end');
110
130
  return {
111
131
  violations,
112
- filePath: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
132
+ filePath: this.#file.path,
113
133
  sourceCode,
114
134
  fixedCode,
115
135
  status: 'processed',
116
136
  };
117
137
  }
138
+ /**
139
+ * Updates the source code and re-parses the document without re-resolving configuration.
140
+ *
141
+ * @param code - The new markup source code
142
+ */
118
143
  async setCode(code) {
119
144
  const core = await this.setup();
120
145
  if (!core) {
121
146
  return;
122
147
  }
123
- __classPrivateFieldGet(this, _MLEngine_file, "f").setCode(code);
148
+ this.#file.setCode(code);
124
149
  core.setCode(code);
125
150
  }
151
+ /**
152
+ * Enables or disables watch mode. When enabled, the engine watches config files
153
+ * for changes and re-lints automatically.
154
+ *
155
+ * @param enable - Whether to enable watch mode
156
+ */
126
157
  watchMode(enable) {
127
- __classPrivateFieldSet(this, _MLEngine_options, {
128
- ...__classPrivateFieldGet(this, _MLEngine_options, "f"),
158
+ this.#options = {
159
+ ...this.#options,
129
160
  watch: enable,
130
- }, "f");
161
+ };
131
162
  if (enable) {
132
- __classPrivateFieldGet(this, _MLEngine_watcher, "f").on('change', this.onChange.bind(this));
163
+ this.#watcher.on('change', this.onChange.bind(this));
133
164
  }
134
165
  else {
135
- __classPrivateFieldGet(this, _MLEngine_watcher, "f").removeAllListeners();
166
+ this.#watcher.removeAllListeners();
136
167
  }
137
168
  }
138
169
  async createCore(fabric) {
139
170
  fileLog('Get source code');
140
- const sourceCode = await __classPrivateFieldGet(this, _MLEngine_file, "f").getCode();
141
- 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);
142
173
  // cspell: disable-next-line
143
174
  fileLog('Source code size: %dbyte', sourceCode.length);
144
- this.emit('code', __classPrivateFieldGet(this, _MLEngine_file, "f").path, sourceCode);
175
+ this.emit('code', this.#file.path, sourceCode);
145
176
  const core = new MLCore({
146
177
  sourceCode,
147
- filename: __classPrivateFieldGet(this, _MLEngine_file, "f").path,
148
- debug: __classPrivateFieldGet(this, _MLEngine_options, "f")?.debug,
178
+ filename: this.#file.path,
179
+ debug: this.#options?.debug,
149
180
  ...fabric,
150
181
  });
151
- __classPrivateFieldSet(this, _MLEngine_core, core, "f");
182
+ this.#core = core;
152
183
  return core;
153
184
  }
154
- async i18n() {
155
- const i18nSettings = await i18n(__classPrivateFieldGet(this, _MLEngine_options, "f")?.locale);
156
- 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);
157
188
  return i18nSettings;
158
189
  }
159
190
  async onChange(filePath) {
160
- if (!__classPrivateFieldGet(this, _MLEngine_options, "f")?.watch) {
191
+ if (!this.#options?.watch) {
161
192
  return;
162
193
  }
163
194
  this.emit('log', 'watch:onChange', filePath);
@@ -166,10 +197,10 @@ export class MLEngine extends Emitter {
166
197
  return;
167
198
  }
168
199
  if (fabric.configErrors) {
169
- this.emit('config-errors', __classPrivateFieldGet(this, _MLEngine_file, "f").path, fabric.configErrors);
200
+ this.emit('config-errors', this.#file.path, fabric.configErrors);
170
201
  }
171
- this.emit('log', 'update:core', __classPrivateFieldGet(this, _MLEngine_file, "f").path);
172
- __classPrivateFieldGet(this, _MLEngine_core, "f")?.update(fabric);
202
+ this.emit('log', 'update:core', this.#file.path);
203
+ this.#core?.update(fabric);
173
204
  await this.exec();
174
205
  }
175
206
  async provide(cache = true) {
@@ -194,27 +225,27 @@ export class MLEngine extends Emitter {
194
225
  fileLog('Resolved Config: %O', configSet.config);
195
226
  fileLog('Resolved Plugins: %O', configSet.plugins);
196
227
  fileLog('Resolve Errors: %O', configSet.errs);
197
- if (!(await __classPrivateFieldGet(this, _MLEngine_file, "f").isFile())) {
198
- this.emit('log', 'file-no-exists', `The file doesn't exist or it is not a file: ${__classPrivateFieldGet(this, _MLEngine_file, "f").path}`);
199
- 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);
200
231
  return null;
201
232
  }
202
233
  // Exclude
203
234
  const excludeFiles = configSet.config.excludeFiles ?? [];
204
- if (__classPrivateFieldGet(this, _MLEngine_file, "f").ignored(excludeFiles)) {
205
- 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);
206
237
  return null;
207
238
  }
208
239
  const { parser, parserOptions, matched } = await this.resolveParser(configSet);
209
- const checkingExt = !__classPrivateFieldGet(this, _MLEngine_options, "f")?.ignoreExt;
240
+ const checkingExt = !this.#options?.ignoreExt;
210
241
  if (checkingExt && !matched) {
211
- this.emit('log', 'ext-unmatched', `Avoided linting because a file is unmatched by the extension: ${__classPrivateFieldGet(this, _MLEngine_file, "f").path}`);
212
- 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);
213
244
  return null;
214
245
  }
215
246
  const severity = {
216
247
  ...configSet.config.severity,
217
- ...__classPrivateFieldGet(this, _MLEngine_options, "f")?.severity,
248
+ ...this.#options?.severity,
218
249
  };
219
250
  const pretenders = await this.resolvePretenders(configSet);
220
251
  fileLog('Resolved pretenders: %O', pretenders);
@@ -235,7 +266,8 @@ export class MLEngine extends Emitter {
235
266
  }
236
267
  const rules = await this.resolveRules(configSet.plugins, ruleset);
237
268
  fileLog('Resolved rules: %O', rules);
238
- const locale = await i18n(__classPrivateFieldGet(this, _MLEngine_options, "f")?.locale);
269
+ const locale = i18n(this.#options?.locale);
270
+ const ruleCommonSettings = configSet.config.ruleCommonSettings ?? {};
239
271
  if (fileLog.enabled) {
240
272
  fileLog('Loaded %d rules: %O', rules.length, rules.map(r => r.name));
241
273
  }
@@ -248,46 +280,47 @@ export class MLEngine extends Emitter {
248
280
  schemas,
249
281
  rules,
250
282
  locale,
283
+ ruleCommonSettings,
251
284
  configErrors: configSet.errs,
252
285
  };
253
286
  }
254
287
  async resolveConfig(cache) {
255
- this.emit('log', 'resolveConfig', JSON.stringify(__classPrivateFieldGet(this, _MLEngine_configProvider, "f"), null, 2));
256
- configLog('configProvider: %s', __classPrivateFieldGet(this, _MLEngine_configProvider, "f"));
257
- 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));
258
291
  configLog('defaultConfigKey: %s', defaultConfigKey ?? 'N/A');
259
292
  this.emit('log', 'defaultConfigKey', defaultConfigKey ?? 'N/A');
260
- const targetConfig = await __classPrivateFieldGet(this, _MLEngine_configProvider, "f").search(__classPrivateFieldGet(this, _MLEngine_file, "f"));
293
+ const targetConfig = await this.#configProvider.search(this.#file);
261
294
  this.emit('log', 'targetConfig', targetConfig ?? 'N/A');
262
- const configFilePathsFromTarget = __classPrivateFieldGet(this, _MLEngine_options, "f")?.noSearchConfig
295
+ const configFilePathsFromTarget = this.#options?.noSearchConfig || this.#options?.configFile
263
296
  ? (defaultConfigKey ?? null)
264
297
  : (targetConfig ?? defaultConfigKey);
265
298
  configLog('configFilePathsFromTarget: %s', configFilePathsFromTarget ?? 'N/A');
266
299
  this.emit('log', 'configFilePathsFromTarget', configFilePathsFromTarget ?? 'N/A');
267
- 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));
268
301
  configLog('option.config: %s', configKey ?? 'N/A');
269
302
  this.emit('log', 'option.config', configFilePathsFromTarget ?? 'N/A');
270
303
  let defaultRecommended = null;
271
- if (!defaultConfigKey && !configFilePathsFromTarget && !configKey) {
304
+ if (!defaultConfigKey && !configFilePathsFromTarget && !configKey && !this.#options?.configFile) {
272
305
  // No configured
273
306
  // Default: set recommended
274
- defaultRecommended = __classPrivateFieldGet(this, _MLEngine_configProvider, "f").set({ extends: ['markuplint:recommended'] });
307
+ defaultRecommended = this.#configProvider.set({ extends: ['markuplint:recommended'] });
275
308
  }
276
309
  configLog('defaultRecommended: %s', defaultRecommended ?? 'N/A');
277
310
  this.emit('log', 'defaultRecommended', defaultRecommended ?? 'N/A');
278
- const configSet = await __classPrivateFieldGet(this, _MLEngine_configProvider, "f").resolve(__classPrivateFieldGet(this, _MLEngine_file, "f"), [configFilePathsFromTarget, __classPrivateFieldGet(this, _MLEngine_options, "f")?.configFile, configKey, defaultRecommended], cache);
279
- this.emit('config', __classPrivateFieldGet(this, _MLEngine_file, "f").path, configSet);
280
- 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) {
281
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.
282
- __classPrivateFieldGet(this, _MLEngine_watcher, "f").add([...configSet.files]);
315
+ this.#watcher.add([...configSet.files]);
283
316
  }
284
317
  return configSet;
285
318
  }
286
319
  async resolveParser(
287
320
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
288
321
  configSet) {
289
- const parser = await resolveParser(__classPrivateFieldGet(this, _MLEngine_file, "f"), configSet.config.parser, configSet.config.parserOptions);
290
- 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);
291
324
  fileLog('Fetched Parser module: %s', parser.parserModName);
292
325
  return parser;
293
326
  }
@@ -299,39 +332,38 @@ export class MLEngine extends Emitter {
299
332
  return pretenders;
300
333
  }
301
334
  async resolveRules(plugins, ruleset) {
302
- const rules = await resolveRules(plugins, ruleset, __classPrivateFieldGet(this, _MLEngine_options, "f")?.importPresetRules ?? true, __classPrivateFieldGet(this, _MLEngine_options, "f")?.autoLoad ?? true);
303
- if (__classPrivateFieldGet(this, _MLEngine_options, "f")?.rules) {
304
- 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);
305
338
  }
306
- this.emit('rules', __classPrivateFieldGet(this, _MLEngine_file, "f").path, rules);
339
+ this.emit('rules', this.#file.path, rules);
307
340
  return rules;
308
341
  }
309
342
  resolveRuleset(
310
343
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
311
344
  configSet) {
312
345
  const ruleset = convertRuleset(configSet.config);
313
- this.emit('ruleset', __classPrivateFieldGet(this, _MLEngine_file, "f").path, ruleset);
346
+ this.emit('ruleset', this.#file.path, ruleset);
314
347
  return ruleset;
315
348
  }
316
349
  async resolveSchemas(
317
350
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
318
351
  configSet) {
319
- const { schemas } = await resolveSpecs(__classPrivateFieldGet(this, _MLEngine_file, "f").path, configSet.config.specs);
320
- 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);
321
354
  return schemas;
322
355
  }
323
356
  async setup() {
324
- if (__classPrivateFieldGet(this, _MLEngine_core, "f")) {
325
- return __classPrivateFieldGet(this, _MLEngine_core, "f");
357
+ if (this.#core) {
358
+ return this.#core;
326
359
  }
327
360
  const fabric = await this.provide();
328
361
  if (!fabric) {
329
362
  return null;
330
363
  }
331
364
  if (fabric.configErrors) {
332
- this.emit('config-errors', __classPrivateFieldGet(this, _MLEngine_file, "f").path, fabric.configErrors);
365
+ this.emit('config-errors', this.#file.path, fabric.configErrors);
333
366
  }
334
367
  return this.createCore(fabric);
335
368
  }
336
369
  }
337
- _MLEngine_configProvider = new WeakMap(), _MLEngine_core = new WeakMap(), _MLEngine_file = new WeakMap(), _MLEngine_options = new WeakMap(), _MLEngine_watcher = new WeakMap();
@@ -2,6 +2,9 @@ import type { ConfigSet } from '@markuplint/file-resolver';
2
2
  import type { LocaleSet } from '@markuplint/i18n';
3
3
  import type { Config, SeverityOptions, Violation } from '@markuplint/ml-config';
4
4
  import type { AnyMLRule, MLSchema, Ruleset } from '@markuplint/ml-core';
5
+ /**
6
+ * Options for the markuplint API, controlling configuration, locale, rules, and behavior.
7
+ */
5
8
  export type APIOptions = {
6
9
  readonly configFile?: string;
7
10
  readonly config?: Config;
@@ -18,6 +21,9 @@ export type APIOptions = {
18
21
  */
19
22
  readonly autoLoad?: boolean;
20
23
  };
24
+ /**
25
+ * Event map for the {@link MLEngine}, defining all emitted events and their payload types.
26
+ */
21
27
  export type MLEngineEventMap = {
22
28
  log: [phase: string, message: string];
23
29
  config: [filePath: string, config: ConfigSet, message?: string];
package/lib/api/v1.d.ts CHANGED
@@ -2,9 +2,14 @@ import type { MLResultInfo } from '../types.js';
2
2
  import type { Config, PlainData, RuleConfigValue } from '@markuplint/ml-config';
3
3
  import type { MLRule } from '@markuplint/ml-core';
4
4
  /**
5
- * @deprecated
6
- * @param options
7
- * @returns
5
+ * Legacy v1 lint function provided for backward compatibility.
6
+ *
7
+ * Translates the v1 option shape into the current `lint` function's parameters
8
+ * and delegates execution to it.
9
+ *
10
+ * @deprecated Use the `lint` function or `MLEngine` class from the current API instead.
11
+ * @param options - The v1-style lint options including file paths, source codes, config, and rules.
12
+ * @returns An array of lint result information objects, one per evaluated file.
8
13
  */
9
14
  export declare function lint_v1(options: {
10
15
  /**
package/lib/api/v1.js CHANGED
@@ -1,9 +1,14 @@
1
1
  import { toNoEmptyStringArrayFromStringOrArray } from '@markuplint/shared';
2
2
  import { lint } from './lint.js';
3
3
  /**
4
- * @deprecated
5
- * @param options
6
- * @returns
4
+ * Legacy v1 lint function provided for backward compatibility.
5
+ *
6
+ * Translates the v1 option shape into the current `lint` function's parameters
7
+ * and delegates execution to it.
8
+ *
9
+ * @deprecated Use the `lint` function or `MLEngine` class from the current API instead.
10
+ * @param options - The v1-style lint options including file paths, source codes, config, and rules.
11
+ * @returns An array of lint result information objects, one per evaluated file.
7
12
  */
8
13
  export async function lint_v1(options) {
9
14
  const filePathList = toNoEmptyStringArrayFromStringOrArray(options.files);
@@ -1,5 +1,13 @@
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\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";
2
+ /**
3
+ * Help text displayed when the CLI is invoked with `--help` or without arguments.
4
+ * Documents all available options, flags, and usage examples.
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--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
+ /**
8
+ * The parsed CLI instance created by `meow`, providing access to
9
+ * positional arguments (`cli.input`) and parsed flags (`cli.flags`).
10
+ */
3
11
  export declare const cli: import("meow").Result<{
4
12
  config: {
5
13
  type: "string";
@@ -39,7 +47,7 @@ export declare const cli: import("meow").Result<{
39
47
  };
40
48
  allowWarnings: {
41
49
  type: "boolean";
42
- default: false;
50
+ default: true;
43
51
  };
44
52
  allowEmptyInput: {
45
53
  type: "boolean";
@@ -84,4 +92,8 @@ export declare const cli: import("meow").Result<{
84
92
  default: false;
85
93
  };
86
94
  }>;
95
+ /**
96
+ * Deeply read-only type representing the parsed CLI flags.
97
+ * Derived from the `meow` flag definitions in {@link cli}.
98
+ */
87
99
  export type CLIOptions = ReadonlyDeep<typeof cli.flags>;
@@ -1,4 +1,8 @@
1
1
  import meow from 'meow';
2
+ /**
3
+ * Help text displayed when the CLI is invoked with `--help` or without arguments.
4
+ * Documents all available options, flags, and usage examples.
5
+ */
2
6
  export const help = `
3
7
  Usage
4
8
  $ markuplint <HTML file paths (glob format)>
@@ -14,7 +18,7 @@ Options
14
18
  --locale Locale of the message of violation. Default is an OS setting.
15
19
  --no-color, Output no color.
16
20
  --problem-only, -p Output only problems, without passeds.
17
- --allow-warnings Return status code 0 even if there are warnings.
21
+ --no-allow-warnings Return status code 1 even if there are warnings.
18
22
  --allow-empty-input Return status code 1 even if there are no input files.
19
23
  --show-config Output computed configuration of the target file. Supports "details" and empty. Default: empty.
20
24
  --verbose Output with detailed information.
@@ -34,6 +38,10 @@ Examples
34
38
  $ markuplint verifyee.html --config path/to/.markuplintrc
35
39
  $ cat verifyee.html | markuplint
36
40
  `;
41
+ /**
42
+ * The parsed CLI instance created by `meow`, providing access to
43
+ * positional arguments (`cli.input`) and parsed flags (`cli.flags`).
44
+ */
37
45
  export const cli = meow(help, {
38
46
  importMeta: import.meta,
39
47
  flags: {
@@ -75,8 +83,7 @@ export const cli = meow(help, {
75
83
  },
76
84
  allowWarnings: {
77
85
  type: 'boolean',
78
- // TODO: It will be changed to `true` in the next major version.
79
- default: false,
86
+ default: true,
80
87
  },
81
88
  allowEmptyInput: {
82
89
  type: 'boolean',
@@ -1,4 +1,16 @@
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
+ * Executes the markuplint linting command against the given files.
6
+ *
7
+ * Resolves file targets, creates an {@link MLEngine} for each file, collects
8
+ * violations, and outputs results in the requested format. When the `--fix`
9
+ * flag is set, overwrites files with their auto-fixed content.
10
+ *
11
+ * @param files - The list of file targets (paths or inline source code) to lint.
12
+ * @param options - CLI options controlling output format, fix mode, locale, and other behaviors.
13
+ * @param apiOptions - Optional overrides for the underlying API (e.g., custom rules or config).
14
+ * @returns `true` if any errors were found (or warnings exceeded the limit), `false` otherwise.
15
+ */
4
16
  export declare function command(files: readonly Readonly<Target>[], options: CLIOptions, apiOptions?: APIOptions): Promise<boolean>;
@@ -5,6 +5,18 @@ import { ViolationCollector } from '@markuplint/ml-core';
5
5
  import { MLEngine } from '../api/index.js';
6
6
  import { log } from '../debug.js';
7
7
  import { output } from './output.js';
8
+ /**
9
+ * Executes the markuplint linting command against the given files.
10
+ *
11
+ * Resolves file targets, creates an {@link MLEngine} for each file, collects
12
+ * violations, and outputs results in the requested format. When the `--fix`
13
+ * flag is set, overwrites files with their auto-fixed content.
14
+ *
15
+ * @param files - The list of file targets (paths or inline source code) to lint.
16
+ * @param options - CLI options controlling output format, fix mode, locale, and other behaviors.
17
+ * @param apiOptions - Optional overrides for the underlying API (e.g., custom rules or config).
18
+ * @returns `true` if any errors were found (or warnings exceeded the limit), `false` otherwise.
19
+ */
8
20
  export async function command(files, options, apiOptions) {
9
21
  const fix = options.fix;
10
22
  const configFile = options.config &&
@@ -1 +1,8 @@
1
+ /**
2
+ * @module cli
3
+ *
4
+ * CLI entry point for markuplint.
5
+ * Parses command-line arguments, dispatches to the appropriate handler
6
+ * (lint, init, search, or help), and manages the process exit code.
7
+ */
1
8
  export {};
package/lib/cli/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ /**
2
+ * @module cli
3
+ *
4
+ * CLI entry point for markuplint.
5
+ * Parses command-line arguments, dispatches to the appropriate handler
6
+ * (lint, init, search, or help), and manages the process exit code.
7
+ */
1
8
  import { text } from 'node:stream/consumers';
2
9
  import { verbosely } from '../debug.js';
3
10
  import { cli } from './bootstrap.js';
@@ -1,4 +1,20 @@
1
1
  import type { DefaultRules, Langs, RuleSettingMode } from './types.js';
2
2
  import type { Config } from '@markuplint/ml-config';
3
+ /**
4
+ * Human-readable display names for each supported template language/framework,
5
+ * shown in the interactive init wizard prompts.
6
+ */
3
7
  export declare const langs: Record<Langs, string>;
8
+ /**
9
+ * Builds a markuplint configuration object based on the user's init wizard selections.
10
+ *
11
+ * Configures parsers and spec modules for the selected template languages,
12
+ * and populates rules based on the chosen rule-setting mode (custom categories,
13
+ * recommended preset, or all defaults).
14
+ *
15
+ * @param langs - The template languages/frameworks selected by the user.
16
+ * @param mode - The rule selection mode: an array of categories, `'recommended'`, or `'none'`.
17
+ * @param defaultRules - The full set of available default rules with their categories and values.
18
+ * @returns A complete markuplint `Config` object ready to be serialized to a file.
19
+ */
4
20
  export declare function createConfig(langs: readonly Langs[], mode: RuleSettingMode, defaultRules: DefaultRules): Config;