markuplint 4.14.0 → 4.18.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 +22 -3
- 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 +43 -0
- 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 +12 -0
- package/lib/cli/bootstrap.js +8 -0
- 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 +20 -0
- 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 +9 -0
- package/lib/i18n.js +9 -0
- package/lib/index.d.ts +14 -1
- package/lib/index.js +13 -1
- package/lib/reporter/github-reporter.d.ts +9 -0
- package/lib/reporter/github-reporter.js +9 -0
- 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 +11 -0
- package/lib/reporter/standard-reporter.d.ts +12 -0
- package/lib/reporter/standard-reporter.js +12 -0
- 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 +3 -0
- package/package.json +17 -17
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# メンテナンスガイド
|
|
2
|
+
|
|
3
|
+
## コマンド
|
|
4
|
+
|
|
5
|
+
| コマンド | 説明 |
|
|
6
|
+
| ------------------------------- | ---------------------- |
|
|
7
|
+
| `yarn build --scope markuplint` | このパッケージをビルド |
|
|
8
|
+
| `yarn dev --scope markuplint` | ウォッチモードでビルド |
|
|
9
|
+
| `yarn clean --scope markuplint` | ビルド成果物を削除 |
|
|
10
|
+
| `yarn test --scope markuplint` | テストを実行 |
|
|
11
|
+
|
|
12
|
+
## テスト
|
|
13
|
+
|
|
14
|
+
テストファイルは `*.spec.ts` の命名規則に従い、`src/` ディレクトリに配置されています:
|
|
15
|
+
|
|
16
|
+
| テストファイル | カバレッジ |
|
|
17
|
+
| ---------------------------------- | --------------------------------------------------------------------- |
|
|
18
|
+
| `api/ml-engine.spec.ts` | MLEngine ライフサイクル(イベント、watch モード、設定解決、fromCode) |
|
|
19
|
+
| `cli/index.spec.ts` | CLI 統合テスト(stdout 出力、fix モード、JSON 形式、フラグ) |
|
|
20
|
+
| `index.spec.ts` | パッケージ統合テスト(HTML ファイル linting エンドツーエンド) |
|
|
21
|
+
| `reporter/github-reporter.spec.ts` | GitHub Actions アノテーション出力形式 |
|
|
22
|
+
| `cli/init/*.spec.ts` | 初期化ウィザード(設定生成、モジュール選択) |
|
|
23
|
+
| `i18n.spec.ts` | ロケール読み込みとフォールバック動作 |
|
|
24
|
+
|
|
25
|
+
MLEngine テストの主なパターン:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { MLEngine } from './api/index.js';
|
|
29
|
+
|
|
30
|
+
const engine = await MLEngine.fromCode(sourceCode, {
|
|
31
|
+
config: { rules: { 'rule-name': true } },
|
|
32
|
+
locale: 'en',
|
|
33
|
+
});
|
|
34
|
+
const result = await engine.exec();
|
|
35
|
+
expect(result?.violations).toStrictEqual([
|
|
36
|
+
// 期待される違反
|
|
37
|
+
]);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
テストユーティリティを使用したテスト:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { mlRuleTest } from './testing-tool/index.js';
|
|
44
|
+
|
|
45
|
+
const { violations } = await mlRuleTest(ruleSeed, '<div></div>', { rule: true });
|
|
46
|
+
expect(violations).toStrictEqual([
|
|
47
|
+
// ruleId を含まない期待される違反
|
|
48
|
+
]);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## レシピ
|
|
52
|
+
|
|
53
|
+
### 1. 新しい CLI フラグの追加
|
|
54
|
+
|
|
55
|
+
1. `src/cli/bootstrap.ts` を読み、`meow()` 内の `flags` オブジェクトを確認
|
|
56
|
+
2. 新しいフラグ定義を追加:
|
|
57
|
+
```ts
|
|
58
|
+
newFlag: {
|
|
59
|
+
type: 'boolean', // または 'string', 'number'
|
|
60
|
+
default: false,
|
|
61
|
+
shortFlag: 'n', // オプション
|
|
62
|
+
},
|
|
63
|
+
```
|
|
64
|
+
3. ファイル上部の `help` 文字列を更新し、新しいフラグをドキュメント化
|
|
65
|
+
4. 注意: `CLIOptions` 型は自動更新される(`typeof cli.flags` から推論)
|
|
66
|
+
5. `src/cli/command.ts` を読み、`options` からフラグ値を取得:
|
|
67
|
+
```ts
|
|
68
|
+
const newFlag = options.newFlag;
|
|
69
|
+
```
|
|
70
|
+
6. `command()` 内にフラグの動作を実装、または `MLEngine` オプションに渡す
|
|
71
|
+
7. フラグが API レイヤーに影響する場合、`src/api/types.ts` の `APIOptions` に対応プロパティを追加
|
|
72
|
+
8. `src/cli/index.spec.ts` にテストを追加
|
|
73
|
+
9. ビルド: `yarn build --scope markuplint`
|
|
74
|
+
10. テスト: `yarn test --scope markuplint`
|
|
75
|
+
|
|
76
|
+
### 2. 新しいレポーターの追加
|
|
77
|
+
|
|
78
|
+
1. `src/reporter/` の既存レポーターを読みパターンを理解:
|
|
79
|
+
- 関数は `MLResultInfo`(およびオプションで `CLIOptions`)を受け取る
|
|
80
|
+
- `string[]` を返す(1要素 = 1出力行)
|
|
81
|
+
2. `src/reporter/<name>-reporter.ts` を作成:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import type { MLResultInfo } from '../types.js';
|
|
85
|
+
|
|
86
|
+
export function <name>Reporter(results: MLResultInfo) {
|
|
87
|
+
const out: string[] = [];
|
|
88
|
+
for (const violation of results.violations) {
|
|
89
|
+
out.push(/* 違反をフォーマット */);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
3. `src/reporter/index.ts` からエクスポート:
|
|
96
|
+
```ts
|
|
97
|
+
export * from './<name>-reporter.js';
|
|
98
|
+
```
|
|
99
|
+
4. `src/cli/output.ts` を読み、`switch` 文にケースを追加:
|
|
100
|
+
```ts
|
|
101
|
+
case '<name>': {
|
|
102
|
+
out = <name>Reporter(results);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
5. `src/reporter/<name>-reporter.spec.ts` にテストを追加
|
|
107
|
+
6. ビルド: `yarn build --scope markuplint`
|
|
108
|
+
7. テスト: `yarn test --scope markuplint`
|
|
109
|
+
|
|
110
|
+
### 3. 設定解決ロジックの変更
|
|
111
|
+
|
|
112
|
+
1. `src/api/ml-engine.ts` を読み、`resolveConfig()` を確認
|
|
113
|
+
2. 現在の優先順位を理解:
|
|
114
|
+
- `options.config`(インライン設定オブジェクト)
|
|
115
|
+
- `options.configFile`(明示的ファイルパス)
|
|
116
|
+
- `ConfigProvider.search()`(自動探索、`--no-search-config` でなければ)
|
|
117
|
+
- `options.defaultConfig`(フォールバック)
|
|
118
|
+
- `markuplint:recommended`(他に設定がない場合のデフォルト)
|
|
119
|
+
3. `@markuplint/file-resolver` の `ConfigProvider` を理解:
|
|
120
|
+
- `set(config)` で設定を登録しキーを返す
|
|
121
|
+
- `search(file)` でターゲットに最も近い設定ファイルを検索
|
|
122
|
+
- `resolve(file, keys, cache)` で全設定レイヤーをマージ
|
|
123
|
+
4. イベント発行(`this.emit('config', ...)`)を保持しつつ `resolveConfig()` を変更
|
|
124
|
+
5. 新しい API オプションを追加する場合、`src/api/types.ts` の `APIOptions` を更新
|
|
125
|
+
6. `src/api/ml-engine.spec.ts` にテストを追加
|
|
126
|
+
7. ビルド: `yarn build --scope markuplint`
|
|
127
|
+
8. テスト: `yarn test --scope markuplint`
|
|
128
|
+
|
|
129
|
+
### 4. MLEngine イベントの追加
|
|
130
|
+
|
|
131
|
+
1. `src/api/types.ts` を読み、`MLEngineEventMap` を確認
|
|
132
|
+
2. 新しいイベント型定義を追加:
|
|
133
|
+
```ts
|
|
134
|
+
'new-event': [filePath: string, data: SomeType, message?: string];
|
|
135
|
+
```
|
|
136
|
+
3. `src/api/ml-engine.ts` を読み、パイプラインの適切な箇所に `this.emit('new-event', ...)` を追加
|
|
137
|
+
4. `src/api/ml-engine.spec.ts` に `engine.on('new-event', ...)` を使ったテストを追加
|
|
138
|
+
5. ビルド: `yarn build --scope markuplint`
|
|
139
|
+
6. テスト: `yarn test --scope markuplint`
|
|
140
|
+
|
|
141
|
+
## 上流パッケージ影響チェックリスト
|
|
142
|
+
|
|
143
|
+
上流パッケージの変更がこのパッケージに影響する可能性があります:
|
|
144
|
+
|
|
145
|
+
| パッケージ | markuplint への影響 |
|
|
146
|
+
| --------------------------- | ------------------------------------------------------------------------------ |
|
|
147
|
+
| `@markuplint/file-resolver` | ConfigProvider API の変更、ファイル解決の変更、パーサー/スキーマリゾルバの変更 |
|
|
148
|
+
| `@markuplint/ml-config` | Config 型の変更、mergeConfig の動作変更 |
|
|
149
|
+
| `@markuplint/ml-core` | MLCore API の変更、MLRule インターフェースの変更、ViolationCollector の変更 |
|
|
150
|
+
| `@markuplint/rules` | ルールの追加/削除がビルトインルールセットに影響 |
|
|
151
|
+
| `@markuplint/cli-utils` | CLI 出力ユーティリティの変更、インストーラ API の変更 |
|
|
152
|
+
| `@markuplint/i18n` | LocaleSet 型の変更、ロケールファイル形式の変更 |
|
|
153
|
+
|
|
154
|
+
上流パッケージが更新された場合:
|
|
155
|
+
|
|
156
|
+
```shell
|
|
157
|
+
yarn test --scope markuplint
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## トラブルシューティング
|
|
161
|
+
|
|
162
|
+
### ファイルが linting されない
|
|
163
|
+
|
|
164
|
+
**症状:** 対象ファイルが存在するが lint 結果が返らない。
|
|
165
|
+
|
|
166
|
+
**原因:** 拡張子の不一致、または `excludeFiles` でファイルが除外されている。
|
|
167
|
+
|
|
168
|
+
**解決策:**
|
|
169
|
+
|
|
170
|
+
1. `--ignore-ext` で拡張子チェックを無効化
|
|
171
|
+
2. 設定の `excludeFiles` を確認
|
|
172
|
+
3. `--verbose` でどのファイルがスキップされているか、その理由を確認
|
|
173
|
+
|
|
174
|
+
### 設定が適用されない
|
|
175
|
+
|
|
176
|
+
**症状:** ルールが有効にならない、設定ファイルが認識されない。
|
|
177
|
+
|
|
178
|
+
**原因:** `--no-search-config` が設定されている、または設定ファイルが探索パスにない。
|
|
179
|
+
|
|
180
|
+
**解決策:**
|
|
181
|
+
|
|
182
|
+
1. `--config` で設定ファイルパスを明示的に指定
|
|
183
|
+
2. `--show-config` で計算済み設定を確認
|
|
184
|
+
3. 設定ファイルが対象ファイルの親ディレクトリにあることを確認
|
|
185
|
+
|
|
186
|
+
### Watch モードで設定変更後に再 lint されない
|
|
187
|
+
|
|
188
|
+
**症状:** 設定ファイルを変更しても再 linting が行われない。
|
|
189
|
+
|
|
190
|
+
**原因:** 設定ファイルが `configSet.files`(ウォッチャーが追跡するファイルセット)に含まれていない。
|
|
191
|
+
|
|
192
|
+
**解決策:**
|
|
193
|
+
|
|
194
|
+
1. `--verbose` でウォッチャーが追跡しているファイルを確認
|
|
195
|
+
2. `ConfigProvider.search()` の結果に設定ファイルが含まれていることを確認
|
|
196
|
+
3. chokidar がファイルを正しく監視しているか確認(プラットフォーム固有の問題)
|
|
197
|
+
|
|
198
|
+
### mlTest() で違反が検出されない
|
|
199
|
+
|
|
200
|
+
**症状:** `mlTest()` が空の violations 配列を返す。
|
|
201
|
+
|
|
202
|
+
**原因:** 第3引数にカスタム `rules` を渡すと、`importPresetRules` がデフォルトで `false` になる。
|
|
203
|
+
|
|
204
|
+
**解決策:**
|
|
205
|
+
|
|
206
|
+
1. `rules` パラメータを省略してすべてのビルトインルールを使用
|
|
207
|
+
2. または必要なルールを明示的に渡し、ルール設定でそれらが有効になっていることを確認
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Maintenance Guide
|
|
2
|
+
|
|
3
|
+
## Commands
|
|
4
|
+
|
|
5
|
+
| Command | Description |
|
|
6
|
+
| ------------------------------- | ---------------------- |
|
|
7
|
+
| `yarn build --scope markuplint` | Build this package |
|
|
8
|
+
| `yarn dev --scope markuplint` | Watch mode build |
|
|
9
|
+
| `yarn clean --scope markuplint` | Remove build artifacts |
|
|
10
|
+
| `yarn test --scope markuplint` | Run tests |
|
|
11
|
+
|
|
12
|
+
## Testing
|
|
13
|
+
|
|
14
|
+
Test files follow the `*.spec.ts` naming convention and are located in the `src/` directory:
|
|
15
|
+
|
|
16
|
+
| Test File | Coverage |
|
|
17
|
+
| ---------------------------------- | -------------------------------------------------------------------- |
|
|
18
|
+
| `api/ml-engine.spec.ts` | MLEngine lifecycle (events, watch mode, config resolution, fromCode) |
|
|
19
|
+
| `cli/index.spec.ts` | CLI integration (stdout output, fix mode, JSON format, flags) |
|
|
20
|
+
| `index.spec.ts` | Package integration (HTML file linting end-to-end) |
|
|
21
|
+
| `reporter/github-reporter.spec.ts` | GitHub Actions annotation output format |
|
|
22
|
+
| `cli/init/*.spec.ts` | Initialization wizard (config generation, module selection) |
|
|
23
|
+
| `i18n.spec.ts` | Locale loading and fallback behavior |
|
|
24
|
+
|
|
25
|
+
The primary testing pattern for MLEngine tests:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { MLEngine } from './api/index.js';
|
|
29
|
+
|
|
30
|
+
const engine = await MLEngine.fromCode(sourceCode, {
|
|
31
|
+
config: { rules: { 'rule-name': true } },
|
|
32
|
+
locale: 'en',
|
|
33
|
+
});
|
|
34
|
+
const result = await engine.exec();
|
|
35
|
+
expect(result?.violations).toStrictEqual([
|
|
36
|
+
// expected violations
|
|
37
|
+
]);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For testing with the testing utilities:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { mlRuleTest } from './testing-tool/index.js';
|
|
44
|
+
|
|
45
|
+
const { violations } = await mlRuleTest(ruleSeed, '<div></div>', { rule: true });
|
|
46
|
+
expect(violations).toStrictEqual([
|
|
47
|
+
// expected violations without ruleId
|
|
48
|
+
]);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Recipes
|
|
52
|
+
|
|
53
|
+
### 1. Adding a New CLI Flag
|
|
54
|
+
|
|
55
|
+
1. Read `src/cli/bootstrap.ts` and locate the `flags` object inside `meow()`
|
|
56
|
+
2. Add the new flag definition:
|
|
57
|
+
```ts
|
|
58
|
+
newFlag: {
|
|
59
|
+
type: 'boolean', // or 'string', 'number'
|
|
60
|
+
default: false,
|
|
61
|
+
shortFlag: 'n', // optional
|
|
62
|
+
},
|
|
63
|
+
```
|
|
64
|
+
3. Update the `help` string at the top of the file to document the new flag
|
|
65
|
+
4. Note: `CLIOptions` type updates automatically (it is `typeof cli.flags`)
|
|
66
|
+
5. Read `src/cli/command.ts` and extract the flag value from `options`:
|
|
67
|
+
```ts
|
|
68
|
+
const newFlag = options.newFlag;
|
|
69
|
+
```
|
|
70
|
+
6. Implement the flag's behavior in `command()` or pass it to `MLEngine` options
|
|
71
|
+
7. If the flag affects the API layer, add a corresponding property to `APIOptions` in `src/api/types.ts`
|
|
72
|
+
8. Add tests in `src/cli/index.spec.ts`
|
|
73
|
+
9. Build: `yarn build --scope markuplint`
|
|
74
|
+
10. Test: `yarn test --scope markuplint`
|
|
75
|
+
|
|
76
|
+
### 2. Adding a New Reporter
|
|
77
|
+
|
|
78
|
+
1. Read existing reporters in `src/reporter/` to understand the pattern:
|
|
79
|
+
- Function takes `MLResultInfo` (and optionally `CLIOptions`)
|
|
80
|
+
- Returns `string[]` (one element per output line)
|
|
81
|
+
2. Create `src/reporter/<name>-reporter.ts`:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import type { MLResultInfo } from '../types.js';
|
|
85
|
+
|
|
86
|
+
export function <name>Reporter(results: MLResultInfo) {
|
|
87
|
+
const out: string[] = [];
|
|
88
|
+
for (const violation of results.violations) {
|
|
89
|
+
out.push(/* format violation */);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
3. Export from `src/reporter/index.ts`:
|
|
96
|
+
```ts
|
|
97
|
+
export * from './<name>-reporter.js';
|
|
98
|
+
```
|
|
99
|
+
4. Read `src/cli/output.ts` and add a case to the `switch` statement:
|
|
100
|
+
```ts
|
|
101
|
+
case '<name>': {
|
|
102
|
+
out = <name>Reporter(results);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
5. Add tests in `src/reporter/<name>-reporter.spec.ts`
|
|
107
|
+
6. Build: `yarn build --scope markuplint`
|
|
108
|
+
7. Test: `yarn test --scope markuplint`
|
|
109
|
+
|
|
110
|
+
### 3. Modifying Configuration Resolution Logic
|
|
111
|
+
|
|
112
|
+
1. Read `src/api/ml-engine.ts` and locate `resolveConfig()`
|
|
113
|
+
2. Understand the current priority:
|
|
114
|
+
- `options.config` (inline config object)
|
|
115
|
+
- `options.configFile` (explicit file path)
|
|
116
|
+
- `ConfigProvider.search()` (auto-discovery, unless `--no-search-config`)
|
|
117
|
+
- `options.defaultConfig` (fallback)
|
|
118
|
+
- `markuplint:recommended` (default when nothing else is configured)
|
|
119
|
+
3. Understand `ConfigProvider` from `@markuplint/file-resolver`:
|
|
120
|
+
- `set(config)` registers a config and returns a key
|
|
121
|
+
- `search(file)` finds the nearest config file for a target
|
|
122
|
+
- `resolve(file, keys, cache)` merges all config layers
|
|
123
|
+
4. Make changes to `resolveConfig()`, preserving the event emissions (`this.emit('config', ...)`)
|
|
124
|
+
5. If adding new API options, update `APIOptions` in `src/api/types.ts`
|
|
125
|
+
6. Add tests in `src/api/ml-engine.spec.ts`
|
|
126
|
+
7. Build: `yarn build --scope markuplint`
|
|
127
|
+
8. Test: `yarn test --scope markuplint`
|
|
128
|
+
|
|
129
|
+
### 4. Adding an MLEngine Event
|
|
130
|
+
|
|
131
|
+
1. Read `src/api/types.ts` and locate `MLEngineEventMap`
|
|
132
|
+
2. Add the new event type definition:
|
|
133
|
+
```ts
|
|
134
|
+
'new-event': [filePath: string, data: SomeType, message?: string];
|
|
135
|
+
```
|
|
136
|
+
3. Read `src/api/ml-engine.ts` and add `this.emit('new-event', ...)` at the appropriate point in the pipeline
|
|
137
|
+
4. Add tests in `src/api/ml-engine.spec.ts` using `engine.on('new-event', ...)`
|
|
138
|
+
5. Build: `yarn build --scope markuplint`
|
|
139
|
+
6. Test: `yarn test --scope markuplint`
|
|
140
|
+
|
|
141
|
+
## Upstream Impact Checklist
|
|
142
|
+
|
|
143
|
+
Changes to upstream packages can affect this package:
|
|
144
|
+
|
|
145
|
+
| Package | Impact on markuplint |
|
|
146
|
+
| --------------------------- | ----------------------------------------------------------------------------------- |
|
|
147
|
+
| `@markuplint/file-resolver` | ConfigProvider API changes, file resolution changes, parser/schema resolver changes |
|
|
148
|
+
| `@markuplint/ml-config` | Config type changes, mergeConfig behavior changes |
|
|
149
|
+
| `@markuplint/ml-core` | MLCore API changes, MLRule interface changes, ViolationCollector changes |
|
|
150
|
+
| `@markuplint/rules` | Rule additions/removals affect the built-in rule set |
|
|
151
|
+
| `@markuplint/cli-utils` | CLI output utility changes, installer API changes |
|
|
152
|
+
| `@markuplint/i18n` | LocaleSet type changes, locale file format changes |
|
|
153
|
+
|
|
154
|
+
When upstream packages are updated, run:
|
|
155
|
+
|
|
156
|
+
```shell
|
|
157
|
+
yarn test --scope markuplint
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Troubleshooting
|
|
161
|
+
|
|
162
|
+
### Files are not being linted
|
|
163
|
+
|
|
164
|
+
**Symptom:** A target file exists but no lint results are returned.
|
|
165
|
+
|
|
166
|
+
**Cause:** Extension mismatch or the file is excluded by `excludeFiles`.
|
|
167
|
+
|
|
168
|
+
**Solution:**
|
|
169
|
+
|
|
170
|
+
1. Use `--ignore-ext` to disable extension checking
|
|
171
|
+
2. Check the `excludeFiles` setting in the configuration
|
|
172
|
+
3. Use `--verbose` to see which files are being skipped and why
|
|
173
|
+
|
|
174
|
+
### Configuration is not applied
|
|
175
|
+
|
|
176
|
+
**Symptom:** Rules are not active, the config file is not recognized.
|
|
177
|
+
|
|
178
|
+
**Cause:** `--no-search-config` is set, or the config file is not in the search path.
|
|
179
|
+
|
|
180
|
+
**Solution:**
|
|
181
|
+
|
|
182
|
+
1. Use `--config` to explicitly specify the config file path
|
|
183
|
+
2. Use `--show-config` to inspect the computed configuration
|
|
184
|
+
3. Check that the config file is in a parent directory of the target file
|
|
185
|
+
|
|
186
|
+
### Watch mode does not re-lint on config changes
|
|
187
|
+
|
|
188
|
+
**Symptom:** Config file is modified but re-linting does not happen.
|
|
189
|
+
|
|
190
|
+
**Cause:** The config file is not in `configSet.files` (the set of files tracked by the watcher).
|
|
191
|
+
|
|
192
|
+
**Solution:**
|
|
193
|
+
|
|
194
|
+
1. Use `--verbose` to see which files the watcher is tracking
|
|
195
|
+
2. Verify that `ConfigProvider.search()` includes the config file in its result
|
|
196
|
+
3. Check that chokidar is correctly watching the file (platform-specific issues)
|
|
197
|
+
|
|
198
|
+
### mlTest() does not detect violations
|
|
199
|
+
|
|
200
|
+
**Symptom:** `mlTest()` returns an empty violations array.
|
|
201
|
+
|
|
202
|
+
**Cause:** When custom `rules` are passed as the third argument, `importPresetRules` defaults to `false`.
|
|
203
|
+
|
|
204
|
+
**Solution:**
|
|
205
|
+
|
|
206
|
+
1. Omit the `rules` parameter to use all built-in rules
|
|
207
|
+
2. Or explicitly pass the rules you need and ensure the rule configuration enables them
|
package/lib/api/index.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module api
|
|
3
|
+
*
|
|
4
|
+
* Public API entry point for markuplint.
|
|
5
|
+
* Re-exports the lint engine and the standalone lint function used for programmatic access.
|
|
6
|
+
*/
|
|
7
|
+
/** The primary linting engine that manages file resolution, configuration, and rule execution. */
|
|
1
8
|
export { MLEngine, FromCodeOptions } from './ml-engine.js';
|
|
9
|
+
/** Standalone function to lint one or more files or source code strings. */
|
|
2
10
|
export { lint } from './lint.js';
|
package/lib/api/index.js
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module api
|
|
3
|
+
*
|
|
4
|
+
* Public API entry point for markuplint.
|
|
5
|
+
* Re-exports the lint engine and the standalone lint function used for programmatic access.
|
|
6
|
+
*/
|
|
7
|
+
/** The primary linting engine that manages file resolution, configuration, and rule execution. */
|
|
1
8
|
export { MLEngine } from './ml-engine.js';
|
|
9
|
+
/** Standalone function to lint one or more files or source code strings. */
|
|
2
10
|
export { lint } from './lint.js';
|
package/lib/api/lint.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import type { APIOptions } from './types.js';
|
|
2
2
|
import type { MLResultInfo } from '../types.js';
|
|
3
3
|
import type { Target } from '@markuplint/file-resolver';
|
|
4
|
+
/**
|
|
5
|
+
* Lints multiple targets (files or inline sources) and returns results for each.
|
|
6
|
+
*
|
|
7
|
+
* @param targetList - An array of file paths/globs or inline source code targets
|
|
8
|
+
* @param options - API options for configuration, locale, rules, and behavior
|
|
9
|
+
* @returns An array of lint results, one per processed file
|
|
10
|
+
*/
|
|
4
11
|
export declare function lint(targetList: readonly Readonly<Target>[], options?: APIOptions): Promise<MLResultInfo[]>;
|
package/lib/api/lint.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { resolveFiles } from '@markuplint/file-resolver';
|
|
2
2
|
import { MLEngine } from './ml-engine.js';
|
|
3
|
+
/**
|
|
4
|
+
* Lints multiple targets (files or inline sources) and returns results for each.
|
|
5
|
+
*
|
|
6
|
+
* @param targetList - An array of file paths/globs or inline source code targets
|
|
7
|
+
* @param options - API options for configuration, locale, rules, and behavior
|
|
8
|
+
* @returns An array of lint results, one per processed file
|
|
9
|
+
*/
|
|
3
10
|
export async function lint(targetList, options) {
|
|
4
11
|
const res = [];
|
|
5
12
|
const files = await resolveFiles(targetList);
|
package/lib/api/ml-engine.d.ts
CHANGED
|
@@ -8,19 +8,67 @@ type MLEngineOptions = {
|
|
|
8
8
|
readonly debug?: boolean;
|
|
9
9
|
readonly watch?: boolean;
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Options for creating an {@link MLEngine} from inline source code.
|
|
13
|
+
*/
|
|
11
14
|
export type FromCodeOptions = APIOptions & MLEngineOptions & {
|
|
15
|
+
/** Optional filename for the inline source code */
|
|
12
16
|
readonly name?: string;
|
|
17
|
+
/** Optional working directory for config resolution */
|
|
13
18
|
readonly dirname?: string;
|
|
14
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* The main markuplint engine that orchestrates file resolution, configuration loading,
|
|
22
|
+
* parsing, and linting. Supports both single-file and watch-mode operation.
|
|
23
|
+
*
|
|
24
|
+
* Emits events at each stage of the linting pipeline for monitoring and debugging.
|
|
25
|
+
*/
|
|
15
26
|
export declare class MLEngine extends Emitter<MLEngineEventMap> {
|
|
16
27
|
#private;
|
|
28
|
+
/**
|
|
29
|
+
* Creates an MLEngine instance from inline source code.
|
|
30
|
+
*
|
|
31
|
+
* @param sourceCode - The markup source code to lint
|
|
32
|
+
* @param options - Options for configuration, naming, and behavior
|
|
33
|
+
* @returns A new MLEngine instance ready to lint the provided code
|
|
34
|
+
*/
|
|
17
35
|
static fromCode(sourceCode: string, options?: FromCodeOptions): Promise<MLEngine>;
|
|
36
|
+
/**
|
|
37
|
+
* Converts a target (file path or inline source) into an MLFile instance.
|
|
38
|
+
*
|
|
39
|
+
* @param target - A file path string or inline source code target
|
|
40
|
+
* @returns The resolved MLFile, or `undefined` if resolution failed
|
|
41
|
+
*/
|
|
18
42
|
static toMLFile(target: Target): Promise<MLFile | undefined>;
|
|
19
43
|
constructor(file: Readonly<MLFile>, options?: APIOptions & MLEngineOptions);
|
|
44
|
+
/**
|
|
45
|
+
* The parsed document, or `null` if not yet set up or if parsing failed.
|
|
46
|
+
*/
|
|
20
47
|
get document(): Document<RuleConfigValue, PlainData> | null;
|
|
48
|
+
/**
|
|
49
|
+
* Closes the engine, removing all event listeners and stopping the file watcher.
|
|
50
|
+
*/
|
|
21
51
|
close(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Executes linting on the target file and returns the results.
|
|
54
|
+
*
|
|
55
|
+
* Sets up the engine on first call, then verifies the document against all rules.
|
|
56
|
+
*
|
|
57
|
+
* @returns The lint result including violations and fixed code, or `null` if setup was skipped
|
|
58
|
+
*/
|
|
22
59
|
exec(): Promise<MLResultInfo | null>;
|
|
60
|
+
/**
|
|
61
|
+
* Updates the source code and re-parses the document without re-resolving configuration.
|
|
62
|
+
*
|
|
63
|
+
* @param code - The new markup source code
|
|
64
|
+
*/
|
|
23
65
|
setCode(code: string): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Enables or disables watch mode. When enabled, the engine watches config files
|
|
68
|
+
* for changes and re-lints automatically.
|
|
69
|
+
*
|
|
70
|
+
* @param enable - Whether to enable watch mode
|
|
71
|
+
*/
|
|
24
72
|
watchMode(enable: boolean): void;
|
|
25
73
|
private createCore;
|
|
26
74
|
private i18n;
|
package/lib/api/ml-engine.js
CHANGED
|
@@ -20,7 +20,20 @@ import { i18n } from '../i18n.js';
|
|
|
20
20
|
const log = coreLog.extend('ml-engine');
|
|
21
21
|
const fileLog = log.extend('file');
|
|
22
22
|
const configLog = log.extend('config');
|
|
23
|
+
/**
|
|
24
|
+
* The main markuplint engine that orchestrates file resolution, configuration loading,
|
|
25
|
+
* parsing, and linting. Supports both single-file and watch-mode operation.
|
|
26
|
+
*
|
|
27
|
+
* Emits events at each stage of the linting pipeline for monitoring and debugging.
|
|
28
|
+
*/
|
|
23
29
|
export class MLEngine extends Emitter {
|
|
30
|
+
/**
|
|
31
|
+
* Creates an MLEngine instance from inline source code.
|
|
32
|
+
*
|
|
33
|
+
* @param sourceCode - The markup source code to lint
|
|
34
|
+
* @param options - Options for configuration, naming, and behavior
|
|
35
|
+
* @returns A new MLEngine instance ready to lint the provided code
|
|
36
|
+
*/
|
|
24
37
|
static async fromCode(sourceCode, options) {
|
|
25
38
|
if (options?.debug) {
|
|
26
39
|
verbosely();
|
|
@@ -38,6 +51,12 @@ export class MLEngine extends Emitter {
|
|
|
38
51
|
const engine = new MLEngine(file, options);
|
|
39
52
|
return engine;
|
|
40
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Converts a target (file path or inline source) into an MLFile instance.
|
|
56
|
+
*
|
|
57
|
+
* @param target - A file path string or inline source code target
|
|
58
|
+
* @returns The resolved MLFile, or `undefined` if resolution failed
|
|
59
|
+
*/
|
|
41
60
|
static async toMLFile(target) {
|
|
42
61
|
const files = await resolveFiles([target]);
|
|
43
62
|
return files[0];
|
|
@@ -58,16 +77,29 @@ export class MLEngine extends Emitter {
|
|
|
58
77
|
this.watchMode(!!__classPrivateFieldGet(this, _MLEngine_options, "f")?.watch);
|
|
59
78
|
log('[MLEngine] Initialized: %s', __classPrivateFieldGet(this, _MLEngine_file, "f").path);
|
|
60
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* The parsed document, or `null` if not yet set up or if parsing failed.
|
|
82
|
+
*/
|
|
61
83
|
get document() {
|
|
62
84
|
if (__classPrivateFieldGet(this, _MLEngine_core, "f")?.document instanceof Error) {
|
|
63
85
|
return null;
|
|
64
86
|
}
|
|
65
87
|
return __classPrivateFieldGet(this, _MLEngine_core, "f")?.document ?? null;
|
|
66
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Closes the engine, removing all event listeners and stopping the file watcher.
|
|
91
|
+
*/
|
|
67
92
|
async close() {
|
|
68
93
|
this.removeAllListeners();
|
|
69
94
|
await __classPrivateFieldGet(this, _MLEngine_watcher, "f").close();
|
|
70
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Executes linting on the target file and returns the results.
|
|
98
|
+
*
|
|
99
|
+
* Sets up the engine on first call, then verifies the document against all rules.
|
|
100
|
+
*
|
|
101
|
+
* @returns The lint result including violations and fixed code, or `null` if setup was skipped
|
|
102
|
+
*/
|
|
71
103
|
async exec() {
|
|
72
104
|
log('exec: start');
|
|
73
105
|
const core = await this.setup();
|
|
@@ -115,6 +147,11 @@ export class MLEngine extends Emitter {
|
|
|
115
147
|
status: 'processed',
|
|
116
148
|
};
|
|
117
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Updates the source code and re-parses the document without re-resolving configuration.
|
|
152
|
+
*
|
|
153
|
+
* @param code - The new markup source code
|
|
154
|
+
*/
|
|
118
155
|
async setCode(code) {
|
|
119
156
|
const core = await this.setup();
|
|
120
157
|
if (!core) {
|
|
@@ -123,6 +160,12 @@ export class MLEngine extends Emitter {
|
|
|
123
160
|
__classPrivateFieldGet(this, _MLEngine_file, "f").setCode(code);
|
|
124
161
|
core.setCode(code);
|
|
125
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Enables or disables watch mode. When enabled, the engine watches config files
|
|
165
|
+
* for changes and re-lints automatically.
|
|
166
|
+
*
|
|
167
|
+
* @param enable - Whether to enable watch mode
|
|
168
|
+
*/
|
|
126
169
|
watchMode(enable) {
|
|
127
170
|
__classPrivateFieldSet(this, _MLEngine_options, {
|
|
128
171
|
...__classPrivateFieldGet(this, _MLEngine_options, "f"),
|
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);
|