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.
- package/ARCHITECTURE.ja.md +419 -0
- package/ARCHITECTURE.md +419 -0
- package/CHANGELOG.md +32 -2
- package/README.md +2 -2
- package/SKILL.md +110 -0
- package/docs/maintenance.ja.md +207 -0
- package/docs/maintenance.md +207 -0
- package/lib/api/index.d.ts +8 -0
- package/lib/api/index.js +8 -0
- package/lib/api/lint.d.ts +7 -0
- package/lib/api/lint.js +7 -0
- package/lib/api/ml-engine.d.ts +48 -0
- package/lib/api/ml-engine.js +118 -86
- package/lib/api/types.d.ts +6 -0
- package/lib/api/v1.d.ts +8 -3
- package/lib/api/v1.js +8 -3
- package/lib/cli/bootstrap.d.ts +14 -2
- package/lib/cli/bootstrap.js +10 -3
- package/lib/cli/command.d.ts +12 -0
- package/lib/cli/command.js +12 -0
- package/lib/cli/index.d.ts +7 -0
- package/lib/cli/index.js +7 -0
- package/lib/cli/init/create-config.d.ts +16 -0
- package/lib/cli/init/create-config.js +21 -1
- package/lib/cli/init/get-default-rules.d.ts +9 -0
- package/lib/cli/init/get-default-rules.js +9 -0
- package/lib/cli/init/index.d.ts +14 -0
- package/lib/cli/init/index.js +14 -0
- package/lib/cli/init/select-modules.d.ts +10 -0
- package/lib/cli/init/select-modules.js +10 -0
- package/lib/cli/init/types.d.ts +19 -0
- package/lib/cli/output.d.ts +11 -0
- package/lib/cli/output.js +11 -0
- package/lib/cli/search/index.d.ts +17 -0
- package/lib/cli/search/index.js +17 -0
- package/lib/debug.d.ts +9 -0
- package/lib/debug.js +9 -0
- package/lib/get-json-module.d.ts +10 -0
- package/lib/get-json-module.js +10 -0
- package/lib/global-settings.d.ts +15 -0
- package/lib/global-settings.js +12 -0
- package/lib/i18n.d.ts +10 -1
- package/lib/i18n.js +12 -10
- package/lib/index.d.ts +13 -4
- package/lib/index.js +12 -4
- package/lib/reporter/github-reporter.d.ts +9 -0
- package/lib/reporter/github-reporter.js +10 -1
- package/lib/reporter/index.d.ts +9 -0
- package/lib/reporter/index.js +9 -0
- package/lib/reporter/simple-reporter.d.ts +11 -0
- package/lib/reporter/simple-reporter.js +12 -1
- package/lib/reporter/standard-reporter.d.ts +12 -0
- package/lib/reporter/standard-reporter.js +13 -1
- package/lib/testing-tool/index.d.ts +44 -0
- package/lib/testing-tool/index.js +32 -0
- package/lib/types.d.ts +3 -0
- package/lib/v1.d.ts +3 -1
- package/lib/v1.js +3 -1
- package/lib/version.d.ts +3 -0
- package/lib/version.js +4 -4
- package/package.json +20 -17
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';
|
|
@@ -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
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this.watchMode(!!
|
|
59
|
-
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);
|
|
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 (
|
|
72
|
+
if (this.#core?.document instanceof Error) {
|
|
63
73
|
return null;
|
|
64
74
|
}
|
|
65
|
-
return
|
|
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
|
|
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(
|
|
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
|
|
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',
|
|
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:
|
|
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',
|
|
128
|
+
this.emit('lint', this.#file.path, sourceCode, violations, fixedCode, debugMap);
|
|
109
129
|
log('exec: end');
|
|
110
130
|
return {
|
|
111
131
|
violations,
|
|
112
|
-
filePath:
|
|
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
|
-
|
|
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
|
-
|
|
128
|
-
...
|
|
158
|
+
this.#options = {
|
|
159
|
+
...this.#options,
|
|
129
160
|
watch: enable,
|
|
130
|
-
}
|
|
161
|
+
};
|
|
131
162
|
if (enable) {
|
|
132
|
-
|
|
163
|
+
this.#watcher.on('change', this.onChange.bind(this));
|
|
133
164
|
}
|
|
134
165
|
else {
|
|
135
|
-
|
|
166
|
+
this.#watcher.removeAllListeners();
|
|
136
167
|
}
|
|
137
168
|
}
|
|
138
169
|
async createCore(fabric) {
|
|
139
170
|
fileLog('Get source code');
|
|
140
|
-
const sourceCode = await
|
|
141
|
-
fileLog('Source code path: %s',
|
|
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',
|
|
175
|
+
this.emit('code', this.#file.path, sourceCode);
|
|
145
176
|
const core = new MLCore({
|
|
146
177
|
sourceCode,
|
|
147
|
-
filename:
|
|
148
|
-
debug:
|
|
178
|
+
filename: this.#file.path,
|
|
179
|
+
debug: this.#options?.debug,
|
|
149
180
|
...fabric,
|
|
150
181
|
});
|
|
151
|
-
|
|
182
|
+
this.#core = core;
|
|
152
183
|
return core;
|
|
153
184
|
}
|
|
154
|
-
|
|
155
|
-
const i18nSettings =
|
|
156
|
-
this.emit('i18n',
|
|
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 (!
|
|
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',
|
|
200
|
+
this.emit('config-errors', this.#file.path, fabric.configErrors);
|
|
170
201
|
}
|
|
171
|
-
this.emit('log', 'update:core',
|
|
172
|
-
|
|
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
|
|
198
|
-
this.emit('log', 'file-no-exists', `The file doesn't exist or it is not a file: ${
|
|
199
|
-
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);
|
|
200
231
|
return null;
|
|
201
232
|
}
|
|
202
233
|
// Exclude
|
|
203
234
|
const excludeFiles = configSet.config.excludeFiles ?? [];
|
|
204
|
-
if (
|
|
205
|
-
fileLog('Excludes the file: %s',
|
|
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 = !
|
|
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: ${
|
|
212
|
-
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);
|
|
213
244
|
return null;
|
|
214
245
|
}
|
|
215
246
|
const severity = {
|
|
216
247
|
...configSet.config.severity,
|
|
217
|
-
...
|
|
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 =
|
|
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(
|
|
256
|
-
configLog('configProvider: %s',
|
|
257
|
-
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));
|
|
258
291
|
configLog('defaultConfigKey: %s', defaultConfigKey ?? 'N/A');
|
|
259
292
|
this.emit('log', 'defaultConfigKey', defaultConfigKey ?? 'N/A');
|
|
260
|
-
const targetConfig = await
|
|
293
|
+
const targetConfig = await this.#configProvider.search(this.#file);
|
|
261
294
|
this.emit('log', 'targetConfig', targetConfig ?? 'N/A');
|
|
262
|
-
const configFilePathsFromTarget =
|
|
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 =
|
|
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 =
|
|
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
|
|
279
|
-
this.emit('config',
|
|
280
|
-
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) {
|
|
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
|
-
|
|
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(
|
|
290
|
-
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);
|
|
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,
|
|
303
|
-
if (
|
|
304
|
-
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);
|
|
305
338
|
}
|
|
306
|
-
this.emit('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',
|
|
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(
|
|
320
|
-
this.emit('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 (
|
|
325
|
-
return
|
|
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',
|
|
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();
|
package/lib/api/types.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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);
|
package/lib/cli/bootstrap.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { ReadonlyDeep } from 'type-fest';
|
|
2
|
-
|
|
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:
|
|
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>;
|
package/lib/cli/bootstrap.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
79
|
-
default: false,
|
|
86
|
+
default: true,
|
|
80
87
|
},
|
|
81
88
|
allowEmptyInput: {
|
|
82
89
|
type: 'boolean',
|
package/lib/cli/command.d.ts
CHANGED
|
@@ -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>;
|
package/lib/cli/command.js
CHANGED
|
@@ -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 &&
|
package/lib/cli/index.d.ts
CHANGED
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;
|