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.
Files changed (60) hide show
  1. package/ARCHITECTURE.ja.md +419 -0
  2. package/ARCHITECTURE.md +419 -0
  3. package/CHANGELOG.md +22 -3
  4. package/SKILL.md +110 -0
  5. package/docs/maintenance.ja.md +207 -0
  6. package/docs/maintenance.md +207 -0
  7. package/lib/api/index.d.ts +8 -0
  8. package/lib/api/index.js +8 -0
  9. package/lib/api/lint.d.ts +7 -0
  10. package/lib/api/lint.js +7 -0
  11. package/lib/api/ml-engine.d.ts +48 -0
  12. package/lib/api/ml-engine.js +43 -0
  13. package/lib/api/types.d.ts +6 -0
  14. package/lib/api/v1.d.ts +8 -3
  15. package/lib/api/v1.js +8 -3
  16. package/lib/cli/bootstrap.d.ts +12 -0
  17. package/lib/cli/bootstrap.js +8 -0
  18. package/lib/cli/command.d.ts +12 -0
  19. package/lib/cli/command.js +12 -0
  20. package/lib/cli/index.d.ts +7 -0
  21. package/lib/cli/index.js +7 -0
  22. package/lib/cli/init/create-config.d.ts +16 -0
  23. package/lib/cli/init/create-config.js +20 -0
  24. package/lib/cli/init/get-default-rules.d.ts +9 -0
  25. package/lib/cli/init/get-default-rules.js +9 -0
  26. package/lib/cli/init/index.d.ts +14 -0
  27. package/lib/cli/init/index.js +14 -0
  28. package/lib/cli/init/select-modules.d.ts +10 -0
  29. package/lib/cli/init/select-modules.js +10 -0
  30. package/lib/cli/init/types.d.ts +19 -0
  31. package/lib/cli/output.d.ts +11 -0
  32. package/lib/cli/output.js +11 -0
  33. package/lib/cli/search/index.d.ts +17 -0
  34. package/lib/cli/search/index.js +17 -0
  35. package/lib/debug.d.ts +9 -0
  36. package/lib/debug.js +9 -0
  37. package/lib/get-json-module.d.ts +10 -0
  38. package/lib/get-json-module.js +10 -0
  39. package/lib/global-settings.d.ts +15 -0
  40. package/lib/global-settings.js +12 -0
  41. package/lib/i18n.d.ts +9 -0
  42. package/lib/i18n.js +9 -0
  43. package/lib/index.d.ts +14 -1
  44. package/lib/index.js +13 -1
  45. package/lib/reporter/github-reporter.d.ts +9 -0
  46. package/lib/reporter/github-reporter.js +9 -0
  47. package/lib/reporter/index.d.ts +9 -0
  48. package/lib/reporter/index.js +9 -0
  49. package/lib/reporter/simple-reporter.d.ts +11 -0
  50. package/lib/reporter/simple-reporter.js +11 -0
  51. package/lib/reporter/standard-reporter.d.ts +12 -0
  52. package/lib/reporter/standard-reporter.js +12 -0
  53. package/lib/testing-tool/index.d.ts +44 -0
  54. package/lib/testing-tool/index.js +32 -0
  55. package/lib/types.d.ts +3 -0
  56. package/lib/v1.d.ts +3 -1
  57. package/lib/v1.js +3 -1
  58. package/lib/version.d.ts +3 -0
  59. package/lib/version.js +3 -0
  60. package/package.json +17 -17
@@ -0,0 +1,419 @@
1
+ # markuplint
2
+
3
+ ## Overview
4
+
5
+ `markuplint` is the main integration package for the markuplint linting ecosystem. It provides a CLI tool, a programmatic API, and testing utilities. The core `MLEngine` class orchestrates the entire linting pipeline: file resolution, configuration loading, parser selection, rule execution, and result output. It integrates `@markuplint/file-resolver`, `@markuplint/ml-core`, `@markuplint/rules`, and other packages into a unified interface for end users, editor extensions, and CI/CD environments.
6
+
7
+ ## Directory Structure
8
+
9
+ ```
10
+ bin/
11
+ └── markuplint.mjs -- CLI executable entry point
12
+ src/
13
+ ├── index.ts -- Package exports (MLEngine, testing tools, types, i18n)
14
+ ├── types.ts -- MLResultInfo type definition
15
+ ├── version.ts -- Package version string (from package.json)
16
+ ├── i18n.ts -- Locale detection and message loading
17
+ ├── debug.ts -- Debug logging (namespace: markuplint-cli)
18
+ ├── global-settings.ts -- Global settings management (locale)
19
+ ├── get-json-module.ts -- Dynamic JSON module loader (safe require wrapper)
20
+ ├── v1.ts -- Deprecated v1 API re-exports
21
+ ├── api/
22
+ │ ├── index.ts -- API exports (MLEngine, lint)
23
+ │ ├── types.ts -- APIOptions, MLEngineEventMap
24
+ │ ├── ml-engine.ts -- MLEngine class (core orchestrator)
25
+ │ ├── ml-engine.spec.ts -- MLEngine tests
26
+ │ ├── lint.ts -- Standalone lint() function
27
+ │ └── v1.ts -- Deprecated v1 lint function
28
+ ├── cli/
29
+ │ ├── index.ts -- CLI entry (arg parsing, command dispatch)
30
+ │ ├── bootstrap.ts -- meow CLI definition (flags, help text)
31
+ │ ├── command.ts -- Lint command implementation
32
+ │ ├── output.ts -- Reporter dispatch (format -> reporter)
33
+ │ ├── index.spec.ts -- CLI integration tests
34
+ │ ├── init/ -- --init subcommand (interactive wizard)
35
+ │ │ ├── index.ts -- Initialization flow orchestration
36
+ │ │ ├── types.ts -- Langs, Category, RuleSettingMode types
37
+ │ │ ├── create-config.ts -- Config generation from user selections
38
+ │ │ ├── get-default-rules.ts -- Built-in rule metadata extraction
39
+ │ │ ├── select-modules.ts -- npm module list from language selections
40
+ │ │ └── *.spec.ts -- Init wizard tests
41
+ │ └── search/ -- --search subcommand (CSS selector search)
42
+ │ └── index.ts -- Element search using temporary rule
43
+ ├── reporter/
44
+ │ ├── index.ts -- Reporter exports
45
+ │ ├── standard-reporter.ts -- Detailed multi-line format with source context
46
+ │ ├── simple-reporter.ts -- Compact one-line-per-violation format
47
+ │ ├── github-reporter.ts -- GitHub Actions annotation format (::error, ::warning)
48
+ │ └── github-reporter.spec.ts
49
+ └── testing-tool/
50
+ └── index.ts -- mlTest(), mlRuleTest(), mlTestFile()
51
+ ```
52
+
53
+ ## Architecture Diagram
54
+
55
+ ```mermaid
56
+ flowchart TD
57
+ subgraph cli ["CLI Layer"]
58
+ bin["bin/markuplint.mjs"]
59
+ bootstrap["bootstrap.ts\n(meow flags)"]
60
+ cliIndex["cli/index.ts\n(dispatch)"]
61
+ cmd["command.ts\n(lint command)"]
62
+ initWiz["init/ (wizard)"]
63
+ searchCmd["search/ (CSS selector)"]
64
+ end
65
+
66
+ subgraph api ["API Layer"]
67
+ MLEngine["MLEngine\n(core orchestrator)"]
68
+ lintFn["lint()\n(multi-file)"]
69
+ end
70
+
71
+ subgraph reporters ["Reporter Layer"]
72
+ standard["standardReporter"]
73
+ simple["simpleReporter"]
74
+ github["githubReporter"]
75
+ json["JSON output"]
76
+ end
77
+
78
+ subgraph testing ["Testing Layer"]
79
+ mlTest["mlTest()"]
80
+ mlRuleTest["mlRuleTest()"]
81
+ mlTestFile["mlTestFile()"]
82
+ end
83
+
84
+ subgraph deps ["Dependencies"]
85
+ fileResolver["@markuplint/file-resolver\n(files, config, parser)"]
86
+ mlCore["@markuplint/ml-core\n(MLCore, rules, verify)"]
87
+ rules["@markuplint/rules\n(built-in rules)"]
88
+ mlConfig["@markuplint/ml-config\n(Config types, merge)"]
89
+ end
90
+
91
+ bin --> cliIndex
92
+ cliIndex --> bootstrap
93
+ cliIndex -->|"--init"| initWiz
94
+ cliIndex -->|"--search"| searchCmd
95
+ cliIndex -->|"files"| cmd
96
+ cmd --> MLEngine
97
+ cmd -->|"output()"| reporters
98
+ searchCmd --> cmd
99
+
100
+ lintFn --> MLEngine
101
+ mlTest --> lintFn
102
+ mlRuleTest --> mlTest
103
+ mlTestFile --> lintFn
104
+
105
+ MLEngine --> fileResolver
106
+ MLEngine --> mlCore
107
+ MLEngine --> rules
108
+ MLEngine --> mlConfig
109
+ ```
110
+
111
+ ## MLEngine Class
112
+
113
+ The central class that orchestrates the linting pipeline. Extends `Emitter<MLEngineEventMap>` from `strict-event-emitter` for type-safe event emission.
114
+
115
+ ### Static Methods
116
+
117
+ | Method | Description |
118
+ | -------------------------------- | -------------------------------------------------------------------------- |
119
+ | `fromCode(sourceCode, options?)` | Creates an MLEngine from inline source code. Resolves an MLFile internally |
120
+ | `toMLFile(target)` | Converts a `Target` (file path or inline source) to an `MLFile` instance |
121
+
122
+ ### Instance Methods
123
+
124
+ | Method | Description |
125
+ | ---------------------- | --------------------------------------------------------------------------------------------------- |
126
+ | `exec()` | Runs linting: calls `setup()`, then `core.verify(fix)`. Returns `MLResultInfo` or `null` if skipped |
127
+ | `setCode(code)` | Updates the source code and re-parses without re-resolving configuration |
128
+ | `watchMode(enable)` | Enables/disables file watching via chokidar. On change: re-resolve config, update core, re-lint |
129
+ | `close()` | Removes all event listeners and stops the file watcher |
130
+ | `resolveConfig(cache)` | Resolves configuration (public for `--show-config` support) |
131
+
132
+ ### Pipeline: setup -> provide -> exec
133
+
134
+ ```mermaid
135
+ flowchart TD
136
+ Exec["exec()"] --> Setup["setup()"]
137
+ Setup --> CoreExists{"core exists?"}
138
+ CoreExists -->|Yes| ReturnCore["Return existing core"]
139
+ CoreExists -->|No| Provide["provide()"]
140
+
141
+ Provide --> ResolveConfig["resolveConfig()\n ConfigProvider.search() + merge"]
142
+ ResolveConfig --> FileExists{"file exists?"}
143
+ FileExists -->|No| ReturnNull1["Return null"]
144
+ FileExists -->|Yes| ExcludeCheck{"excluded?"}
145
+ ExcludeCheck -->|Yes| ReturnNull2["Return null"]
146
+ ExcludeCheck -->|No| ResolveParser["resolveParser()\n parser module selection"]
147
+ ResolveParser --> ExtCheck{"extension matched?\n(unless --ignore-ext)"}
148
+ ExtCheck -->|No| ReturnNull3["Return null"]
149
+ ExtCheck -->|Yes| ResolvePretenders["resolvePretenders()"]
150
+ ResolvePretenders --> ResolveRuleset["resolveRuleset()\n convertRuleset()"]
151
+ ResolveRuleset --> ResolveSchemas["resolveSchemas()"]
152
+ ResolveSchemas --> ResolveRules["resolveRules()\n plugins + custom rules"]
153
+ ResolveRules --> LoadI18n["i18n()\n locale loading"]
154
+ LoadI18n --> ReturnFabric["Return MLFabric"]
155
+
156
+ ReturnFabric --> CreateCore["createCore(fabric)\n new MLCore(...)"]
157
+ CreateCore --> ReturnCore
158
+
159
+ ReturnCore --> Verify["core.verify(fix)"]
160
+ Verify --> EmitLint["emit 'lint' event"]
161
+ EmitLint --> ReturnResult["Return MLResultInfo"]
162
+ ```
163
+
164
+ ### Configuration Resolution Priority
165
+
166
+ The `resolveConfig()` method resolves configuration from multiple sources with the following priority (highest to lowest):
167
+
168
+ ```
169
+ 1. options.config -- Inline config object passed via API
170
+ 2. options.configFile -- Explicit config file path (--config flag)
171
+ 3. ConfigProvider.search()-- Auto-discovery from file location (unless --no-search-config)
172
+ 4. options.defaultConfig -- Fallback config
173
+ 5. markuplint:recommended -- Default when no config is found at all
174
+ ```
175
+
176
+ These are combined via `ConfigProvider.resolve()` which merges all layers using `@markuplint/ml-config`'s `mergeConfig()`.
177
+
178
+ ### Event System
179
+
180
+ | Event | Payload | Emitted When |
181
+ | --------------- | -------------------------------------------------- | --------------------------- |
182
+ | `log` | phase, message | At each processing stage |
183
+ | `config` | filePath, configSet | After config resolution |
184
+ | `exclude` | filePath, setting | When a file is excluded |
185
+ | `parser` | filePath, parserName | After parser resolution |
186
+ | `ruleset` | filePath, ruleset | After ruleset conversion |
187
+ | `schemas` | filePath, schemas | After schema resolution |
188
+ | `rules` | filePath, rules | After rule resolution |
189
+ | `i18n` | filePath, locale | After locale loading |
190
+ | `code` | filePath, sourceCode | After source code retrieval |
191
+ | `lint` | filePath, sourceCode, violations, fixedCode, debug | After lint completion |
192
+ | `lint-error` | filePath, sourceCode, error | On lint error |
193
+ | `config-errors` | filePath, errors | On config resolution errors |
194
+
195
+ ### Watch Mode
196
+
197
+ When enabled, the engine uses `chokidar.FSWatcher` to monitor configuration files (not the target file itself, which is managed by editors/language servers):
198
+
199
+ 1. `resolveConfig()` adds `configSet.files` to the watcher
200
+ 2. On file change: `onChange()` fires
201
+ 3. `provide(false)` re-resolves config without cache
202
+ 4. `core.update(fabric)` updates the core with new settings
203
+ 5. `exec()` re-lints the file
204
+
205
+ ## CLI Architecture
206
+
207
+ ### Entry Point Flow
208
+
209
+ ```
210
+ bin/markuplint.mjs
211
+ -> import cli/index.ts
212
+ |-- -v -> cli.showVersion() (exit 0)
213
+ |-- -h -> cli.showHelp(0) (exit 0)
214
+ |-- --verbose -> verbosely()
215
+ |-- --init -> initialize() (exit 0/1)
216
+ |-- --create-rule -> error message (exit 1, use @markuplint/create-rule)
217
+ |-- files + --search -> search() (exit 0)
218
+ |-- files -> command() (exit 0/1)
219
+ |-- stdin (pipe) -> command([{sourceCode}]) (exit 0/1)
220
+ `-- (no args) -> cli.showHelp(1) (exit 1)
221
+ ```
222
+
223
+ ### command() Processing Flow
224
+
225
+ 1. `resolveFiles()` expands file globs into `MLFile` list
226
+ 2. Create `ViolationCollector` with `maxCount` limit
227
+ 3. For each file:
228
+ - Create `MLEngine` with options
229
+ - If `--show-config`: output computed config as JSON and return
230
+ - `engine.exec()` to lint
231
+ - If `--progressive-output` and not JSON: output immediately
232
+ - Otherwise: accumulate results in memory
233
+ - Collect violations into `ViolationCollector`
234
+ - If `--fix`: overwrite file with fixed code
235
+ 4. Output results (JSON format: `collector.toArray()`, others: per-file via `output()`)
236
+ 5. Check `--max-warnings` threshold
237
+ 6. Return `hasError` (used as exit code)
238
+
239
+ ### CLI Options
240
+
241
+ | Flag | Type | Default | Description |
242
+ | -------------------------- | ------- | ------------ | -------------------------------------------------------- |
243
+ | `--config`, `-c` | string | -- | Configuration file path |
244
+ | `--fix` | boolean | `false` | Auto-fix violations |
245
+ | `--format`, `-f` | string | `"Standard"` | Output format: Standard, Simple, GitHub, JSON |
246
+ | `--no-search-config` | boolean | `false` | Disable automatic config file discovery |
247
+ | `--ignore-ext` | boolean | `false` | Lint files regardless of extension |
248
+ | `--no-import-preset-rules` | boolean | `false` | Do not load built-in rules |
249
+ | `--locale` | string | OS locale | Locale for violation messages |
250
+ | `--no-color` | boolean | `false` | Strip ANSI escape codes from output |
251
+ | `--problem-only`, `-p` | boolean | `false` | Only show files with violations |
252
+ | `--allow-warnings` | boolean | `false` | Exit 0 even with warnings |
253
+ | `--allow-empty-input` | boolean | `true` | Do not error on empty file list |
254
+ | `--show-config` | string | -- | Output computed config (`""` or `"details"`) |
255
+ | `--verbose` | boolean | `false` | Enable debug output |
256
+ | `--include-node-modules` | boolean | `false` | Include files in node_modules |
257
+ | `--severity-parse-error` | string | `"error"` | Severity for parse errors: error, warning, off |
258
+ | `--max-count` | number | `0` | Limit total violations shown (0 = no limit) |
259
+ | `--max-warnings` | number | `-1` | Warning count threshold for nonzero exit (-1 = no limit) |
260
+ | `--progressive-output` | boolean | `false` | Output results as each file is processed |
261
+ | `--init` | boolean | `false` | Run interactive setup wizard |
262
+ | `--search` | string | -- | Search for elements by CSS selector |
263
+
264
+ ## Reporter System
265
+
266
+ | Format | Reporter | Output Target | Characteristics |
267
+ | -------- | ------------------ | ------------------------------------- | -------------------------------------------------------------- |
268
+ | Standard | `standardReporter` | stderr (violations) / stdout (passed) | Multi-line: source context, line numbers, highlighted regions |
269
+ | Simple | `simpleReporter` | stderr / stdout | Compact: one line per violation with severity icon |
270
+ | GitHub | `githubReporter` | stderr / stdout | GitHub Actions: `::error`, `::warning`, `::notice` annotations |
271
+ | JSON | (in command.ts) | stdout | Structured JSON via `ViolationCollector.toArray()` |
272
+
273
+ The `output()` function in `cli/output.ts` dispatches to the appropriate reporter based on `--format`. Violations are written to stderr (setting `process.exitCode = 1`), clean results to stdout. When `--no-color` is set, ANSI codes are stripped via `strip-ansi`.
274
+
275
+ ## Testing Tool
276
+
277
+ | Function | Purpose |
278
+ | ------------------------------------------------------ | ------------------------------------------------- |
279
+ | `mlTest(sourceCode, config, rules?, locale?, fix?)` | Lint inline source code with a full configuration |
280
+ | `mlRuleTest(rule, sourceCode, config?, fix?, locale?)` | Unit test a single rule implementation |
281
+ | `mlTestFile(target, config?, rules?, locale?, fix?)` | Lint a file target for integration testing |
282
+
283
+ ### mlRuleTest Internals
284
+
285
+ `mlRuleTest()` creates a temporary `MLRule` named `<current-rule>` and translates the simplified test config format into a full markuplint `Config`:
286
+
287
+ - `config.rule` maps to `rules: { '<current-rule>': value }`
288
+ - `config.nodeRule` maps to `nodeRules` with rule settings under `<current-rule>`
289
+ - `config.childNodeRule` maps to `childNodeRules` similarly
290
+ - After linting, `ruleId` is removed from violations to make test assertions rule-name-independent
291
+
292
+ ## Initialization Wizard (--init)
293
+
294
+ Interactive flow:
295
+
296
+ 1. Multi-select template engines (JSX, Vue, Svelte, Pug, PHP, etc.)
297
+ 2. Confirm npm dependency installation
298
+ 3. Choose: customize rules per category or use recommended preset
299
+ 4. If customizing: confirm each category (validation, a11y, naming-convention, maintainability, style)
300
+ 5. Generate `.markuplintrc` with parser/spec mappings and selected rules
301
+ 6. Auto-install npm packages if confirmed
302
+
303
+ The `createConfig()` function builds the config by:
304
+
305
+ - Mapping each language to its parser module and file extension pattern
306
+ - Adding spec packages for Vue (`@markuplint/vue-spec`), React (`@markuplint/react-spec`), Svelte (`@markuplint/svelte-spec`), and Alpine
307
+ - Populating rules from selected categories or the `markuplint:recommended` preset
308
+
309
+ ## Search Subcommand (--search)
310
+
311
+ Searches for elements matching a CSS selector across files:
312
+
313
+ 1. Creates a temporary `MLRule` named `__CLI_SEARCH__`
314
+ 2. The rule's `verify()` uses `document.querySelectorAll(selectors)` to find matches
315
+ 3. Collects `{file, line, col}` locations from matched nodes
316
+ 4. Outputs results in `file:line:col` format to stdout
317
+
318
+ This reuses the full lint pipeline via `command()` with `importPresetRules: false` and `problemOnly: true`.
319
+
320
+ ## Key Source Files
321
+
322
+ | File | Purpose |
323
+ | ----------------------------------- | ----------------------------------------------------------------------- |
324
+ | `src/api/ml-engine.ts` | `MLEngine` class: pipeline orchestration, config resolution, watch mode |
325
+ | `src/api/lint.ts` | `lint()`: multi-file linting convenience function |
326
+ | `src/api/types.ts` | `APIOptions`, `MLEngineEventMap` type definitions |
327
+ | `src/cli/index.ts` | CLI entry point: argument parsing and command dispatch |
328
+ | `src/cli/bootstrap.ts` | `meow` CLI definition with all flags and help text |
329
+ | `src/cli/command.ts` | `command()`: file iteration, violation collection, output |
330
+ | `src/cli/output.ts` | `output()`: reporter selection and result formatting |
331
+ | `src/reporter/standard-reporter.ts` | Detailed reporter with source context |
332
+ | `src/reporter/simple-reporter.ts` | Compact single-line reporter |
333
+ | `src/reporter/github-reporter.ts` | GitHub Actions annotation reporter |
334
+ | `src/testing-tool/index.ts` | `mlTest()`, `mlRuleTest()`, `mlTestFile()` |
335
+ | `src/cli/init/index.ts` | Interactive initialization wizard orchestration |
336
+ | `src/cli/init/create-config.ts` | Config generation from wizard selections |
337
+ | `src/cli/search/index.ts` | CSS selector search subcommand |
338
+ | `src/types.ts` | `MLResultInfo` type definition |
339
+ | `src/i18n.ts` | Locale detection and message set loading |
340
+ | `src/debug.ts` | Debug logger (namespace: `markuplint-cli`) and `verbosely()` |
341
+ | `src/global-settings.ts` | Global settings (locale) management |
342
+
343
+ ## External Dependencies
344
+
345
+ | Dependency | Purpose |
346
+ | --------------------------- | -------------------------------------------------------------- |
347
+ | `@markuplint/file-resolver` | File resolution, config loading, parser/schema/rule resolution |
348
+ | `@markuplint/ml-config` | `Config` types, `mergeConfig()` |
349
+ | `@markuplint/ml-core` | `MLCore`, `MLRule`, `ViolationCollector`, `convertRuleset()` |
350
+ | `@markuplint/rules` | Built-in lint rules |
351
+ | `@markuplint/html-parser` | Default HTML parser |
352
+ | `@markuplint/html-spec` | HTML specification definitions |
353
+ | `@markuplint/i18n` | Locale set types and translated messages |
354
+ | `@markuplint/cli-utils` | CLI output utilities, interactive prompts, module installer |
355
+ | `@markuplint/shared` | Shared utility functions |
356
+ | `chokidar` | File system watching (watch mode) |
357
+ | `debug` | Debug logging with namespaces |
358
+ | `meow` | CLI argument parser |
359
+ | `os-locale` | OS locale detection |
360
+ | `strict-event-emitter` | Type-safe event emitter base class |
361
+ | `strip-ansi` | ANSI escape code removal (--no-color) |
362
+
363
+ ## Integration Points
364
+
365
+ ```mermaid
366
+ flowchart LR
367
+ subgraph upstream ["Upstream"]
368
+ fileResolver["@markuplint/file-resolver\n(file resolution,\nconfig loading,\nparser/schema resolution)"]
369
+ mlConfig["@markuplint/ml-config\n(Config types, merge)"]
370
+ mlCore["@markuplint/ml-core\n(MLCore, verify,\nViolationCollector)"]
371
+ builtinRules["@markuplint/rules\n(built-in rules)"]
372
+ end
373
+
374
+ subgraph pkg ["markuplint"]
375
+ engine["MLEngine\n(orchestrator)"]
376
+ cli["CLI\n(meow, command, output)"]
377
+ reporters["Reporters\n(standard, simple, github)"]
378
+ testTools["Testing Tools\n(mlTest, mlRuleTest,\nmlTestFile)"]
379
+ end
380
+
381
+ subgraph downstream ["Downstream"]
382
+ users["Users (CLI)"]
383
+ editors["Editor Extensions (API)"]
384
+ ci["CI/CD\n(GitHub Actions format)"]
385
+ ruleTests["Rule Authors\n(testing utilities)"]
386
+ end
387
+
388
+ fileResolver --> engine
389
+ mlConfig --> engine
390
+ mlCore --> engine
391
+ builtinRules --> engine
392
+
393
+ cli --> engine
394
+ engine --> reporters
395
+ testTools --> engine
396
+
397
+ cli --> users
398
+ engine --> editors
399
+ reporters --> ci
400
+ testTools --> ruleTests
401
+ ```
402
+
403
+ ### Upstream
404
+
405
+ - **`@markuplint/file-resolver`** -- Resolves file targets, discovers and loads config files, resolves parser/schema modules
406
+ - **`@markuplint/ml-config`** -- Provides `Config` types and `mergeConfig()` for combining config layers
407
+ - **`@markuplint/ml-core`** -- Provides `MLCore` for document parsing and rule verification, `ViolationCollector` for result aggregation
408
+ - **`@markuplint/rules`** -- Provides the built-in rule set loaded by default
409
+
410
+ ### Downstream
411
+
412
+ - **Users** -- Invoke via CLI (`npx markuplint`)
413
+ - **Editor Extensions** -- Use `MLEngine` API programmatically for real-time linting
414
+ - **CI/CD** -- Use GitHub Actions reporter format for inline annotations
415
+ - **Rule Authors** -- Use `mlRuleTest()` to unit test custom rule implementations
416
+
417
+ ## Documentation Map
418
+
419
+ - [Maintenance Guide](docs/maintenance.md) -- Commands, recipes, and troubleshooting
package/CHANGELOG.md CHANGED
@@ -3,16 +3,35 @@
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
- # [4.14.0](https://github.com/markuplint/markuplint/compare/markuplint@4.13.1...markuplint@4.14.0) (2025-11-05)
6
+ # [4.18.0](https://github.com/markuplint/markuplint/compare/v4.14.1...v4.18.0) (2026-04-22)
7
+
8
+ ### Bug Fixes
7
9
 
10
+ - **deps:** adapt code to breaking changes from upgrade ([ced7fab](https://github.com/markuplint/markuplint/commit/ced7fab5b50ea3effd844e17b1f676fce790b53c))
8
11
 
9
- ### Features
12
+ ### Reverts
13
+
14
+ - pin meow and os-locale for Node 18 support ([ed61c88](https://github.com/markuplint/markuplint/commit/ed61c8829aca912b81fd6efb518b4518199db2ca))
15
+
16
+ ## [4.14.2](https://github.com/markuplint/markuplint/compare/markuplint@4.14.1...markuplint@4.14.2) (2026-04-21)
17
+
18
+ ### Bug Fixes
19
+
20
+ - **deps:** adapt code to breaking changes from upgrade ([ced7fab](https://github.com/markuplint/markuplint/commit/ced7fab5b50ea3effd844e17b1f676fce790b53c))
10
21
 
11
- * **markuplint:** add progressive output option for CLI ([9cbfa69](https://github.com/markuplint/markuplint/commit/9cbfa69d1acbcb123b7b83a91cdbaf9a97f6c3d7))
22
+ ### Reverts
12
23
 
24
+ - pin meow and os-locale for Node 18 support ([ed61c88](https://github.com/markuplint/markuplint/commit/ed61c8829aca912b81fd6efb518b4518199db2ca))
13
25
 
26
+ ## [4.14.1](https://github.com/markuplint/markuplint/compare/markuplint@4.14.0...markuplint@4.14.1) (2026-02-10)
27
+
28
+ **Note:** Version bump only for package markuplint
14
29
 
30
+ # [4.14.0](https://github.com/markuplint/markuplint/compare/markuplint@4.13.1...markuplint@4.14.0) (2025-11-05)
31
+
32
+ ### Features
15
33
 
34
+ - **markuplint:** add progressive output option for CLI ([9cbfa69](https://github.com/markuplint/markuplint/commit/9cbfa69d1acbcb123b7b83a91cdbaf9a97f6c3d7))
16
35
 
17
36
  ## [4.13.1](https://github.com/markuplint/markuplint/compare/markuplint@4.13.0...markuplint@4.13.1) (2025-08-24)
18
37
 
package/SKILL.md ADDED
@@ -0,0 +1,110 @@
1
+ ---
2
+ description: Maintenance tasks for markuplint
3
+ globs:
4
+ - packages/markuplint/src/**/*.ts
5
+ alwaysApply: false
6
+ ---
7
+
8
+ # markuplint-maintenance
9
+
10
+ Perform maintenance tasks for `markuplint`: add CLI options, add reporters,
11
+ and modify configuration resolution logic.
12
+
13
+ ## Input
14
+
15
+ `$ARGUMENTS` specifies the task. Supported tasks:
16
+
17
+ | Task | Description |
18
+ | -------------------------- | ----------------------------------------------------------- |
19
+ | `add-cli-option` | Add a new CLI flag and wire it through the command pipeline |
20
+ | `add-reporter` | Add a new output formatter for lint results |
21
+ | `modify-config-resolution` | Change how MLEngine resolves and merges configuration |
22
+
23
+ If omitted, defaults to `add-cli-option`.
24
+
25
+ ## Reference
26
+
27
+ Before executing any task, read `docs/maintenance.md` (or `docs/maintenance.ja.md`)
28
+ for the full guide. The recipes there are the source of truth for procedures.
29
+
30
+ Also read:
31
+
32
+ - `ARCHITECTURE.md` -- Package overview, MLEngine pipeline, CLI architecture, reporter system
33
+ - `src/api/ml-engine.ts` -- MLEngine class (core orchestrator, config resolution, watch mode)
34
+ - `src/api/types.ts` -- APIOptions, MLEngineEventMap type definitions
35
+ - `src/cli/bootstrap.ts` -- meow CLI flag definitions and help text
36
+ - `src/cli/command.ts` -- Lint command implementation
37
+ - `src/cli/output.ts` -- Reporter dispatch logic
38
+
39
+ ## Task: add-cli-option
40
+
41
+ Add a new CLI flag and wire it through the command pipeline. Follow recipe #1 in `docs/maintenance.md`.
42
+
43
+ ### Step 1: Define the flag
44
+
45
+ 1. Read `src/cli/bootstrap.ts`
46
+ 2. Add the new flag to the `meow` flags object with type, default, and optional shortFlag
47
+ 3. Update the `help` text to document the new flag
48
+ 4. Note: `CLIOptions` type updates automatically (derived from `typeof cli.flags`)
49
+
50
+ ### Step 2: Wire through command
51
+
52
+ 1. Read `src/cli/command.ts`
53
+ 2. Extract the flag value from `options` and implement the processing logic
54
+ 3. If the flag affects the API layer, also update `src/api/types.ts` (`APIOptions`)
55
+
56
+ ### Step 3: Verify
57
+
58
+ 1. Add tests in `src/cli/index.spec.ts`
59
+ 2. Build: `yarn build --scope markuplint`
60
+ 3. Test: `yarn test --scope markuplint`
61
+
62
+ ## Task: add-reporter
63
+
64
+ Add a new output formatter for lint results. Follow recipe #2 in `docs/maintenance.md`.
65
+
66
+ ### Step 1: Create the reporter
67
+
68
+ 1. Read existing reporters in `src/reporter/` for the pattern
69
+ 2. Create a new file `src/reporter/<name>-reporter.ts`
70
+ 3. Export a function that takes `MLResultInfo` (and optionally `CLIOptions`) and returns `string[]`
71
+
72
+ ### Step 2: Register the reporter
73
+
74
+ 1. Read `src/reporter/index.ts` and add an export for the new reporter
75
+ 2. Read `src/cli/output.ts` and add a case in the `switch` statement for the new format name
76
+
77
+ ### Step 3: Verify
78
+
79
+ 1. Add tests in `src/reporter/<name>-reporter.spec.ts`
80
+ 2. Build: `yarn build --scope markuplint`
81
+ 3. Test: `yarn test --scope markuplint`
82
+
83
+ ## Task: modify-config-resolution
84
+
85
+ Change how MLEngine resolves and merges configuration. Follow recipe #3 in `docs/maintenance.md`.
86
+
87
+ ### Step 1: Understand the current flow
88
+
89
+ 1. Read `src/api/ml-engine.ts` and locate `resolveConfig()`
90
+ 2. Current priority: options.config -> configFile -> search -> defaultConfig -> recommended
91
+ 3. Understand `ConfigProvider` methods: `search()`, `set()`, `resolve()` (from `@markuplint/file-resolver`)
92
+
93
+ ### Step 2: Modify the logic
94
+
95
+ 1. Make changes to `resolveConfig()` in `src/api/ml-engine.ts`
96
+ 2. If changing the API surface, update `src/api/types.ts`
97
+
98
+ ### Step 3: Verify
99
+
100
+ 1. Add tests in `src/api/ml-engine.spec.ts`
101
+ 2. Build: `yarn build --scope markuplint`
102
+ 3. Test: `yarn test --scope markuplint`
103
+
104
+ ## Rules
105
+
106
+ 1. **CLI flag types are inferred** -- `CLIOptions` is derived from `typeof cli.flags`; do not manually define flag types.
107
+ 2. **Reporters return `string[]`** -- each element is one output line; the caller handles joining and writing.
108
+ 3. **Violations go to stderr, passed results to stdout** -- follow this convention in `output()`.
109
+ 4. **Test with MLEngine.fromCode()** -- use `MLEngine.fromCode(sourceCode, options)` for API-level tests.
110
+ 5. **Add JSDoc comments** to all new public types and functions.