markuplint 5.3.0 → 5.4.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 +8 -0
- package/lib/api/ml-engine.js +47 -8
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
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.4.0](https://github.com/markuplint/markuplint/compare/v5.3.0...v5.4.0) (2026-10-29)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **markuplint:** skip the config search when it is disabled ([e2e8da9](https://github.com/markuplint/markuplint/commit/e2e8da9a81fb113b726fc30877b16cfab4d53736)), closes [#4409](https://github.com/markuplint/markuplint/issues/4409)
|
|
11
|
+
* **markuplint:** watch a config file the search found broken ([1a51145](https://github.com/markuplint/markuplint/commit/1a51145b3eb34c18c0475205466b608787352b66)), closes [#4413](https://github.com/markuplint/markuplint/issues/4413)
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
# [5.3.0](https://github.com/markuplint/markuplint/compare/v5.2.0...v5.3.0) (2026-10-21)
|
|
7
15
|
|
|
8
16
|
### Bug Fixes
|
package/lib/api/ml-engine.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigProvider, createPretenderResolver, disambiguatePretendersForFile, invalidatePretenderResolutionCaches, resolveFiles, resolveParser, resolveRules, resolveSpecs, } from '@markuplint/file-resolver';
|
|
1
|
+
import { ConfigProvider, configLoadErrorFiles, createPretenderResolver, disambiguatePretendersForFile, invalidatePretenderResolutionCaches, resolveFiles, resolveParser, resolveRules, resolveSpecs, } from '@markuplint/file-resolver';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { applyRuleAliasesToConfig, mergeConfig } from '@markuplint/ml-config';
|
|
4
4
|
import { CONFIG_ERROR_RULE_ID, MLCore, convertRuleset } from '@markuplint/ml-core';
|
|
@@ -620,7 +620,7 @@ export class MLEngine extends Emitter {
|
|
|
620
620
|
// in the middle of this one's `set()`/`search()` calls, which would
|
|
621
621
|
// wipe the keys just registered below before `resolve()` gets to use
|
|
622
622
|
// them. See #4015.
|
|
623
|
-
const resolvedConfigSet = await this.#
|
|
623
|
+
const resolvedConfigSet = await this.#runResolution(async () => {
|
|
624
624
|
if (!cache) {
|
|
625
625
|
// Must run before any `set()` call below — `ConfigProvider#resolve()`
|
|
626
626
|
// no longer clears its own store on `cache: false`, so invalidating
|
|
@@ -632,17 +632,24 @@ export class MLEngine extends Emitter {
|
|
|
632
632
|
this.#configProvider.set(mergeConfig(this.#options.defaultConfig), undefined, this.#options.defaultConfig);
|
|
633
633
|
configLog('defaultConfigKey: %s', defaultConfigKey ?? 'N/A');
|
|
634
634
|
this.emit('log', 'defaultConfigKey', defaultConfigKey ?? 'N/A');
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
635
|
+
// Skipped, not run and discarded: the search reads and parses every
|
|
636
|
+
// config file it reaches, so a malformed one would still surface as a
|
|
637
|
+
// `config-error` in a run that asked not to search. See #4409.
|
|
638
|
+
let targetConfig = null;
|
|
639
|
+
if (this.#options?.noSearchConfig || this.#options?.configFile) {
|
|
640
|
+
this.emit('log', 'targetConfig', 'skipped (search is disabled)');
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
targetConfig = await this.#configProvider.search(this.#file);
|
|
644
|
+
this.emit('log', 'targetConfig', targetConfig ?? 'N/A');
|
|
645
|
+
}
|
|
646
|
+
const configFilePathsFromTarget = targetConfig ?? defaultConfigKey ?? null;
|
|
640
647
|
configLog('configFilePathsFromTarget: %s', configFilePathsFromTarget ?? 'N/A');
|
|
641
648
|
this.emit('log', 'configFilePathsFromTarget', configFilePathsFromTarget ?? 'N/A');
|
|
642
649
|
const configKey = this.#options?.config &&
|
|
643
650
|
this.#configProvider.set(mergeConfig(this.#options.config), undefined, this.#options.config);
|
|
644
651
|
configLog('option.config: %s', configKey ?? 'N/A');
|
|
645
|
-
this.emit('log', 'option.config',
|
|
652
|
+
this.emit('log', 'option.config', configKey ?? 'N/A');
|
|
646
653
|
let defaultRecommended = null;
|
|
647
654
|
if (!defaultConfigKey && !configFilePathsFromTarget && !configKey && !this.#options?.configFile) {
|
|
648
655
|
// No configured
|
|
@@ -675,6 +682,38 @@ export class MLEngine extends Emitter {
|
|
|
675
682
|
await this.#syncWatch();
|
|
676
683
|
return configSet;
|
|
677
684
|
}
|
|
685
|
+
/**
|
|
686
|
+
* Runs `resolve` exclusively on the provider (see {@link resolveConfig}).
|
|
687
|
+
* When it throws a `ConfigLoadError` (a config file that the search found
|
|
688
|
+
* cannot be loaded, or a preset that is not found), the files whose change
|
|
689
|
+
* can fix it ({@link configLoadErrorFiles}: the file it names, and a
|
|
690
|
+
* `$import` target that does not exist yet) are added to the watched files
|
|
691
|
+
* before the error goes on: there is no config set to take
|
|
692
|
+
* {@link ConfigSet.files} from, and the files of the previous resolution
|
|
693
|
+
* alone would miss the fix of a file that was broken from the start. They
|
|
694
|
+
* stay watched, as the error names only the first thing that failed, not
|
|
695
|
+
* every file the config depends on. A directory that the search cannot
|
|
696
|
+
* examine is not among them, as the shared watcher takes file paths (see
|
|
697
|
+
* its module JSDoc in `shared-watcher.ts`).
|
|
698
|
+
*
|
|
699
|
+
* @param resolve - The resolution, which runs inside `runExclusive`
|
|
700
|
+
* @returns The config set that `resolve` returns
|
|
701
|
+
*/
|
|
702
|
+
async #runResolution(resolve) {
|
|
703
|
+
try {
|
|
704
|
+
return await this.#configProvider.runExclusive(resolve);
|
|
705
|
+
}
|
|
706
|
+
catch (error) {
|
|
707
|
+
if (isFatalError(error)) {
|
|
708
|
+
throw error;
|
|
709
|
+
}
|
|
710
|
+
if (error instanceof ConfigLoadError) {
|
|
711
|
+
this.#configFiles = new Set([...this.#configFiles, ...configLoadErrorFiles(error)]);
|
|
712
|
+
await this.#syncWatch();
|
|
713
|
+
}
|
|
714
|
+
throw error;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
678
717
|
async #resolveParser(
|
|
679
718
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
680
719
|
configSet) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markuplint",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"description": "An HTML linter for all markup developers",
|
|
5
5
|
"author": "Yusuke Hirao",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@markuplint/cli-utils": "5.3.0",
|
|
38
|
-
"@markuplint/file-resolver": "5.
|
|
39
|
-
"@markuplint/html-parser": "5.
|
|
40
|
-
"@markuplint/html-spec": "5.
|
|
38
|
+
"@markuplint/file-resolver": "5.4.0",
|
|
39
|
+
"@markuplint/html-parser": "5.4.0",
|
|
40
|
+
"@markuplint/html-spec": "5.4.0",
|
|
41
41
|
"@markuplint/i18n": "5.3.0",
|
|
42
42
|
"@markuplint/ml-ast": "5.3.0",
|
|
43
|
-
"@markuplint/ml-config": "5.
|
|
44
|
-
"@markuplint/ml-core": "5.
|
|
45
|
-
"@markuplint/ml-spec": "5.
|
|
46
|
-
"@markuplint/rules": "5.
|
|
47
|
-
"@markuplint/shared": "5.
|
|
43
|
+
"@markuplint/ml-config": "5.4.0",
|
|
44
|
+
"@markuplint/ml-core": "5.4.0",
|
|
45
|
+
"@markuplint/ml-spec": "5.4.0",
|
|
46
|
+
"@markuplint/rules": "5.4.0",
|
|
47
|
+
"@markuplint/shared": "5.4.0",
|
|
48
48
|
"@types/debug": "^4.1.13",
|
|
49
49
|
"chokidar": "^5.0.0",
|
|
50
50
|
"debug": "^4.4.3",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"strip-ansi": "^7.2.0",
|
|
55
55
|
"type-fest": "^5.10.0"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "647f6fb5d5743f060678599c97e9c84b58970747"
|
|
58
58
|
}
|