@markuplint/ml-ast 5.0.0-rc.2 → 5.0.0-rc.5
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 +15 -0
- package/README.md +0 -6
- package/lib/index.d.ts +16 -0
- package/lib/index.js +16 -0
- package/lib/types.d.ts +145 -8
- package/package.json +3 -3
- package/ARCHITECTURE.ja.md +0 -309
- package/ARCHITECTURE.md +0 -309
- package/SKILL.md +0 -123
- package/docs/maintenance.ja.md +0 -213
- package/docs/maintenance.md +0 -214
- package/docs/node-reference.ja.md +0 -487
- package/docs/node-reference.md +0 -487
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
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.0.0-rc.5](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.4...v5.0.0-rc.5) (2026-08-28)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **ml-ast:** add documentMode to ParserOptions ([530493e](https://github.com/markuplint/markuplint/commit/530493e7f99eb27dd2f420666474e233db450c26)), closes [#3844](https://github.com/markuplint/markuplint/issues/3844)
|
|
11
|
+
- **ml-ast:** add MLASTParseError + MLASTParseErrorCode types and parseErrors field ([be34fbd](https://github.com/markuplint/markuplint/commit/be34fbd36ba7fb36b0a07cd6e865c8d81d8752ae)), closes [#3844](https://github.com/markuplint/markuplint/issues/3844)
|
|
12
|
+
|
|
13
|
+
# [5.0.0-rc.4](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.3...v5.0.0-rc.4) (2026-04-19)
|
|
14
|
+
|
|
15
|
+
**Note:** Version bump only for package @markuplint/ml-ast
|
|
16
|
+
|
|
17
|
+
# [5.0.0-rc.3](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.2...v5.0.0-rc.3) (2026-04-19)
|
|
18
|
+
|
|
19
|
+
**Note:** Version bump only for package @markuplint/ml-ast
|
|
20
|
+
|
|
6
21
|
# [5.0.0-rc.2](https://github.com/markuplint/markuplint/compare/v5.0.0-rc.1...v5.0.0-rc.2) (2026-04-15)
|
|
7
22
|
|
|
8
23
|
**Note:** Version bump only for package @markuplint/ml-ast
|
package/README.md
CHANGED
|
@@ -16,9 +16,3 @@ $ yarn add @markuplint/ml-ast
|
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
</details>
|
|
19
|
-
|
|
20
|
-
## Documentation
|
|
21
|
-
|
|
22
|
-
- [Architecture](ARCHITECTURE.md) -- Package overview, type hierarchy diagrams, and integration points
|
|
23
|
-
- [Node Reference](docs/node-reference.md) -- Detailed documentation of each AST node type
|
|
24
|
-
- [Maintenance Guide](docs/maintenance.md) -- Commands, recipes, and troubleshooting
|
package/lib/index.d.ts
CHANGED
|
@@ -1 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The language-independent AST contract of markuplint: every parser package
|
|
3
|
+
* must produce these types and `@markuplint/ml-core` consumes them, so the
|
|
4
|
+
* core and rules can operate on a unified AST regardless of the source
|
|
5
|
+
* language.
|
|
6
|
+
*
|
|
7
|
+
* This package intentionally contains zero runtime code and zero
|
|
8
|
+
* dependencies — keep it type-only so parsers and downstream consumers can
|
|
9
|
+
* share the contract without runtime coupling.
|
|
10
|
+
*
|
|
11
|
+
* Backward-compatibility convention: when adding a field to an existing node
|
|
12
|
+
* interface, prefer an optional field so existing parser implementations do
|
|
13
|
+
* not break.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
1
17
|
export * from './types.js';
|
package/lib/index.js
CHANGED
|
@@ -1 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The language-independent AST contract of markuplint: every parser package
|
|
3
|
+
* must produce these types and `@markuplint/ml-core` consumes them, so the
|
|
4
|
+
* core and rules can operate on a unified AST regardless of the source
|
|
5
|
+
* language.
|
|
6
|
+
*
|
|
7
|
+
* This package intentionally contains zero runtime code and zero
|
|
8
|
+
* dependencies — keep it type-only so parsers and downstream consumers can
|
|
9
|
+
* share the contract without runtime coupling.
|
|
10
|
+
*
|
|
11
|
+
* Backward-compatibility convention: when adding a field to an existing node
|
|
12
|
+
* interface, prefer an optional field so existing parser implementations do
|
|
13
|
+
* not break.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
1
17
|
export * from './types.js';
|
package/lib/types.d.ts
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
* - `'invalid'` – A node that could not be parsed correctly
|
|
12
12
|
* - `'attr'` – A regular HTML attribute
|
|
13
13
|
* - `'spread'` – A spread attribute (e.g. `{...props}` in JSX)
|
|
14
|
+
*
|
|
15
|
+
* Adding a value here requires a corresponding `case` in `ml-core`'s
|
|
16
|
+
* `createNode()` (`packages/@markuplint/ml-core/src/ml-dom/helper/create-node.ts`);
|
|
17
|
+
* an unhandled value throws `TypeError: Invalid AST node types` at runtime.
|
|
14
18
|
*/
|
|
15
19
|
export type MLASTNodeType = 'doctype' | 'starttag' | 'endtag' | 'comment' | 'text' | 'omittedtag' | 'psblock' | 'invalid' | 'attr' | 'spread';
|
|
16
20
|
/**
|
|
@@ -54,7 +58,14 @@ export type MLASTAttr = MLASTHTMLAttr | MLASTSpreadAttr;
|
|
|
54
58
|
* in `@markuplint/parser-utils`.
|
|
55
59
|
*/
|
|
56
60
|
export interface MLASTToken {
|
|
57
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* Unique identifier for this token instance.
|
|
63
|
+
*
|
|
64
|
+
* Cross-references between nodes (`parentNodeUuid`, `pairNodeUuid`) use
|
|
65
|
+
* UUID strings rather than object references so the AST stays free of
|
|
66
|
+
* circular references and can be serialized as JSON; consumers resolve a
|
|
67
|
+
* UUID against `MLASTDocument.nodeList`.
|
|
68
|
+
*/
|
|
58
69
|
readonly uuid: string;
|
|
59
70
|
/** The original raw source text of this token */
|
|
60
71
|
readonly raw: string;
|
|
@@ -109,7 +120,7 @@ export interface MLASTElement extends MLASTAbstractNode {
|
|
|
109
120
|
readonly namespace: NamespaceURI;
|
|
110
121
|
/** Whether the element is native HTML, a Web Component, or an authored component */
|
|
111
122
|
readonly elementType: ElementType;
|
|
112
|
-
/** Whether this element acts as a fragment (no actual DOM node) */
|
|
123
|
+
/** Whether this element acts as a fragment (no actual DOM node, e.g. a JSX fragment `<>` or a Vue `<template>` wrapper) */
|
|
113
124
|
readonly isFragment: boolean;
|
|
114
125
|
/** Attributes on this element */
|
|
115
126
|
readonly attributes: readonly MLASTAttr[];
|
|
@@ -130,12 +141,17 @@ export interface MLASTElement extends MLASTAbstractNode {
|
|
|
130
141
|
readonly tagOpenChar: string;
|
|
131
142
|
/** The characters that close this tag (usually `">"`) */
|
|
132
143
|
readonly tagCloseChar: string;
|
|
133
|
-
/** Whether this element is a ghost node (omitted tag inferred by the parser) */
|
|
144
|
+
/** Whether this element is a ghost node (omitted tag inferred by the parser, e.g. an implicit `<tbody>`); ghost nodes have an empty `raw` */
|
|
134
145
|
readonly isGhost: boolean;
|
|
135
146
|
}
|
|
136
147
|
/**
|
|
137
148
|
* A closing element tag (e.g. `</div>`).
|
|
138
149
|
* Always paired with an {@link MLASTElement} via `pairNodeUuid`.
|
|
150
|
+
*
|
|
151
|
+
* Close tags are not part of DOM tree traversal in `ml-core`: `createNode()`
|
|
152
|
+
* skips `'endtag'` entries in the node list, and the paired `MLElement`
|
|
153
|
+
* instead resolves `pairNodeUuid` to create its `MLElementCloseTag`, which
|
|
154
|
+
* exists only as a satellite of that element.
|
|
139
155
|
*/
|
|
140
156
|
export interface MLASTElementCloseTag extends MLASTAbstractNode {
|
|
141
157
|
readonly type: 'endtag';
|
|
@@ -157,6 +173,11 @@ export interface MLASTElementCloseTag extends MLASTAbstractNode {
|
|
|
157
173
|
* A preprocessor-specific block node, representing control-flow constructs
|
|
158
174
|
* from template engines and frameworks (e.g. `{#if}`, `{#each}` in Svelte,
|
|
159
175
|
* `v-if` blocks in Vue, `<% if %>` in EJS/ERB).
|
|
176
|
+
*
|
|
177
|
+
* In `ml-core` this maps to `MLBlock` — a markuplint-specific extension with
|
|
178
|
+
* the custom `nodeType` `101` (no DOM Standard equivalent) — which acts as a
|
|
179
|
+
* transparent container: its children are treated as belonging to the parent
|
|
180
|
+
* node for tree traversal purposes.
|
|
160
181
|
*/
|
|
161
182
|
export interface MLASTPreprocessorSpecificBlock extends MLASTAbstractNode {
|
|
162
183
|
readonly type: 'psblock';
|
|
@@ -168,7 +189,7 @@ export interface MLASTPreprocessorSpecificBlock extends MLASTAbstractNode {
|
|
|
168
189
|
readonly isFragment: boolean;
|
|
169
190
|
/** Direct child nodes within this block */
|
|
170
191
|
readonly childNodes: readonly MLASTChildNode[];
|
|
171
|
-
/** Block behavior associated with this block,
|
|
192
|
+
/** Block behavior associated with this block, or `null` when the block has no control-flow semantic (e.g. a pure expression output like `<%= expr %>` in EJS) */
|
|
172
193
|
readonly blockBehavior: MLASTBlockBehavior | null;
|
|
173
194
|
/** Whether this block is bogus (unparsable or malformed) */
|
|
174
195
|
readonly isBogus: boolean;
|
|
@@ -177,6 +198,10 @@ export interface MLASTPreprocessorSpecificBlock extends MLASTAbstractNode {
|
|
|
177
198
|
* Describes the behavior of a preprocessor block or element,
|
|
178
199
|
* capturing both the kind of control-flow construct and the
|
|
179
200
|
* source expression that drives it.
|
|
201
|
+
*
|
|
202
|
+
* `ml-core` uses the `type` to enumerate conditional branches
|
|
203
|
+
* (`conditionalChildNodes()`) so content-model rules such as
|
|
204
|
+
* `permitted-contents` can analyze each branch separately.
|
|
180
205
|
*/
|
|
181
206
|
export interface MLASTBlockBehavior {
|
|
182
207
|
/** The kind of block behavior (e.g. `'if'`, `'each'`, `'await'`) */
|
|
@@ -196,7 +221,12 @@ export interface MLASTComment extends MLASTAbstractNode {
|
|
|
196
221
|
readonly nodeName: '#comment';
|
|
197
222
|
/** Nesting depth in the document tree */
|
|
198
223
|
readonly depth: number;
|
|
199
|
-
/**
|
|
224
|
+
/**
|
|
225
|
+
* Whether the comment is bogus (malformed per the HTML parsing spec,
|
|
226
|
+
* e.g. `<!...>` or a processing instruction such as `<?xml ... ?>`).
|
|
227
|
+
* The parser still captures these as comment nodes but flags them so
|
|
228
|
+
* lint rules can report them.
|
|
229
|
+
*/
|
|
200
230
|
readonly isBogus: boolean;
|
|
201
231
|
}
|
|
202
232
|
/**
|
|
@@ -211,6 +241,12 @@ export interface MLASTText extends MLASTAbstractNode {
|
|
|
211
241
|
/**
|
|
212
242
|
* A node representing markup that could not be parsed correctly.
|
|
213
243
|
* Always marked as bogus.
|
|
244
|
+
*
|
|
245
|
+
* This is a recovery node: the parser captures unparsable content instead of
|
|
246
|
+
* failing the whole parse. It is never preserved as-is in the DOM —
|
|
247
|
+
* `ml-core` converts it to an `MLElement` named `x-invalid` (when `kind` is
|
|
248
|
+
* `'starttag'`) or to an `MLText` (otherwise), so lint rules can still
|
|
249
|
+
* operate on the content based on the parser's best guess.
|
|
214
250
|
*/
|
|
215
251
|
export interface MLASTInvalid extends MLASTAbstractNode {
|
|
216
252
|
readonly type: 'invalid';
|
|
@@ -225,6 +261,12 @@ export interface MLASTInvalid extends MLASTAbstractNode {
|
|
|
225
261
|
/**
|
|
226
262
|
* A regular HTML attribute node, decomposed into its constituent tokens
|
|
227
263
|
* (name, equal sign, quotes, value, and surrounding whitespace).
|
|
264
|
+
*
|
|
265
|
+
* The decomposition exists so lint rules can validate whitespace around the
|
|
266
|
+
* equal sign, quoting style, and attribute naming conventions with precise
|
|
267
|
+
* source locations. For boolean attributes without a value (e.g.
|
|
268
|
+
* `disabled`), the `equal`, `startQuote`, `value`, and `endQuote` tokens
|
|
269
|
+
* still exist but have empty `raw` strings.
|
|
228
270
|
*/
|
|
229
271
|
export interface MLASTHTMLAttr extends MLASTToken {
|
|
230
272
|
readonly type: 'attr';
|
|
@@ -250,7 +292,7 @@ export interface MLASTHTMLAttr extends MLASTToken {
|
|
|
250
292
|
readonly isDynamicValue?: true;
|
|
251
293
|
/** Whether the attribute is a framework directive (e.g. `v-if`, `@click`) */
|
|
252
294
|
readonly isDirective?: true;
|
|
253
|
-
/** The resolved attribute name when the actual name is a framework-specific directive */
|
|
295
|
+
/** The resolved attribute name when the actual name is a framework-specific directive (e.g. Vue's `:class` resolves to `class`, `@click` to `onclick`) */
|
|
254
296
|
readonly potentialName?: string;
|
|
255
297
|
/** The resolved attribute value when the actual value is dynamic */
|
|
256
298
|
readonly potentialValue?: string;
|
|
@@ -258,16 +300,66 @@ export interface MLASTHTMLAttr extends MLASTToken {
|
|
|
258
300
|
readonly valueType?: 'string' | 'number' | 'boolean' | 'code';
|
|
259
301
|
/** A candidate attribute name for auto-correction */
|
|
260
302
|
readonly candidate?: string;
|
|
261
|
-
/** Whether this attribute is allowed to appear multiple times on the same element */
|
|
303
|
+
/** Whether this attribute is allowed to appear multiple times on the same element (e.g. `class` in template engines that merge values) */
|
|
262
304
|
readonly isDuplicatable: boolean;
|
|
263
305
|
}
|
|
264
306
|
/**
|
|
265
307
|
* A spread attribute node (e.g. `{...props}` in JSX).
|
|
308
|
+
*
|
|
309
|
+
* Minimal by design: a spread cannot be statically decomposed into
|
|
310
|
+
* name/value tokens, so only the positional token information is kept.
|
|
266
311
|
*/
|
|
267
312
|
export interface MLASTSpreadAttr extends MLASTToken {
|
|
268
313
|
readonly type: 'spread';
|
|
269
314
|
readonly nodeName: '#spread';
|
|
270
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Stable identifier for a non-fatal parser conformance error. The full set
|
|
318
|
+
* mirrors parse5's `ERR` enum (HTML LS tokenizer / tree-construction parse
|
|
319
|
+
* errors) — each value is a kebab-case string that appears verbatim in the
|
|
320
|
+
* `code` field of `MLASTParseError` and as the key in
|
|
321
|
+
* `severity.parseError`'s `Record` form.
|
|
322
|
+
*
|
|
323
|
+
* Source of truth: `parse5/dist/common/error-codes.d.ts`. When parse5
|
|
324
|
+
* adds a new code, append it here and update the migration guide.
|
|
325
|
+
*
|
|
326
|
+
* @see https://html.spec.whatwg.org/multipage/parsing.html#parse-errors
|
|
327
|
+
*/
|
|
328
|
+
export type MLASTParseErrorCode = 'control-character-in-input-stream' | 'noncharacter-in-input-stream' | 'surrogate-in-input-stream' | 'non-void-html-element-start-tag-with-trailing-solidus' | 'end-tag-with-attributes' | 'end-tag-with-trailing-solidus' | 'unexpected-solidus-in-tag' | 'unexpected-null-character' | 'unexpected-question-mark-instead-of-tag-name' | 'invalid-first-character-of-tag-name' | 'unexpected-equals-sign-before-attribute-name' | 'missing-end-tag-name' | 'unexpected-character-in-attribute-name' | 'unknown-named-character-reference' | 'missing-semicolon-after-character-reference' | 'absence-of-digits-in-numeric-character-reference' | 'null-character-reference' | 'surrogate-character-reference' | 'character-reference-outside-unicode-range' | 'control-character-reference' | 'noncharacter-character-reference' | 'unexpected-character-in-unquoted-attribute-value' | 'missing-attribute-value' | 'missing-whitespace-between-attributes' | 'duplicate-attribute' | 'unexpected-character-after-doctype-system-identifier' | 'missing-whitespace-after-doctype-public-keyword' | 'missing-whitespace-between-doctype-public-and-system-identifiers' | 'missing-whitespace-after-doctype-system-keyword' | 'missing-quote-before-doctype-public-identifier' | 'missing-quote-before-doctype-system-identifier' | 'missing-doctype-public-identifier' | 'missing-doctype-system-identifier' | 'abrupt-doctype-public-identifier' | 'abrupt-doctype-system-identifier' | 'missing-whitespace-before-doctype-name' | 'missing-doctype-name' | 'invalid-character-sequence-after-doctype-name' | 'non-conforming-doctype' | 'missing-doctype' | 'misplaced-doctype' | 'eof-in-doctype' | 'incorrectly-opened-comment' | 'incorrectly-closed-comment' | 'nested-comment' | 'abrupt-closing-of-empty-comment' | 'eof-in-comment' | 'cdata-in-html-content' | 'eof-in-cdata' | 'eof-in-script-html-comment-like-text' | 'eof-before-tag-name' | 'eof-in-tag' | 'eof-in-element-that-can-contain-only-text' | 'end-tag-without-matching-open-element' | 'closing-of-element-with-open-child-elements' | 'disallowed-content-in-noscript-in-head' | 'open-elements-left-after-eof' | 'abandoned-head-element-child' | 'misplaced-start-tag-for-head-element' | 'nested-noscript-in-head';
|
|
329
|
+
/**
|
|
330
|
+
* Non-fatal parser-level conformance error emitted by the underlying parser
|
|
331
|
+
* during tokenisation (e.g., parse5's `onParseError` events). Unlike
|
|
332
|
+
* `unknownParseError` these do not abort the parse — the document is still
|
|
333
|
+
* usable — but they correspond to HTML LS tokenizer / tree-construction
|
|
334
|
+
* conformance errors that the `parse-error` rule surfaces as lint
|
|
335
|
+
* violations.
|
|
336
|
+
*
|
|
337
|
+
* @see https://html.spec.whatwg.org/multipage/parsing.html#parse-errors
|
|
338
|
+
*/
|
|
339
|
+
export interface MLASTParseError {
|
|
340
|
+
/**
|
|
341
|
+
* Stable kebab-case identifier from the underlying parser. The current
|
|
342
|
+
* full enumeration mirrors parse5's `ERR` enum and is captured by
|
|
343
|
+
* {@link MLASTParseErrorCode}; framework parsers that surface a code
|
|
344
|
+
* outside that set should still use a kebab-case identifier so user
|
|
345
|
+
* configuration (`severity.parseError`) can target it.
|
|
346
|
+
*/
|
|
347
|
+
readonly code: MLASTParseErrorCode;
|
|
348
|
+
/** Zero-based offset into the source where the error starts. */
|
|
349
|
+
readonly startOffset: number;
|
|
350
|
+
/** 1-based line where the error starts. */
|
|
351
|
+
readonly startLine: number;
|
|
352
|
+
/** 1-based column where the error starts. */
|
|
353
|
+
readonly startCol: number;
|
|
354
|
+
/** Zero-based offset into the source where the error ends. */
|
|
355
|
+
readonly endOffset: number;
|
|
356
|
+
/** 1-based line where the error ends. */
|
|
357
|
+
readonly endLine: number;
|
|
358
|
+
/** 1-based column where the error ends. */
|
|
359
|
+
readonly endCol: number;
|
|
360
|
+
/** The slice of the source between `startOffset` and `endOffset`. */
|
|
361
|
+
readonly raw: string;
|
|
362
|
+
}
|
|
271
363
|
/**
|
|
272
364
|
* The root document node returned by a parser.
|
|
273
365
|
* Contains the full node list and metadata about the parse result.
|
|
@@ -275,12 +367,34 @@ export interface MLASTSpreadAttr extends MLASTToken {
|
|
|
275
367
|
export interface MLASTDocument {
|
|
276
368
|
/** The full original source code */
|
|
277
369
|
readonly raw: string;
|
|
278
|
-
/**
|
|
370
|
+
/**
|
|
371
|
+
* Depth-first flattened list of all AST nodes in document order (the
|
|
372
|
+
* order they appear in the source) — nodes also appear in their parent's
|
|
373
|
+
* `childNodes`. UUID cross-references (`parentNodeUuid`, `pairNodeUuid`)
|
|
374
|
+
* are resolved against this list, so every node referenced by UUID must
|
|
375
|
+
* be present in it.
|
|
376
|
+
*/
|
|
279
377
|
readonly nodeList: readonly MLASTNodeTreeItem[];
|
|
280
378
|
/** Whether the document is a fragment (no root element required) */
|
|
281
379
|
readonly isFragment: boolean;
|
|
282
380
|
/** A description of any unknown parse error that occurred, if any */
|
|
283
381
|
readonly unknownParseError?: string;
|
|
382
|
+
/**
|
|
383
|
+
* Non-fatal parser-level conformance errors collected during tokenisation.
|
|
384
|
+
* Populated by parsers that support it (e.g., `@markuplint/html-parser`
|
|
385
|
+
* via parse5's `onParseError`); omitted otherwise. Consumed by
|
|
386
|
+
* `@markuplint/ml-core`'s verify pipeline, which surfaces each entry as a
|
|
387
|
+
* `ruleId: 'parse-error'` violation (sharing the channel with fatal
|
|
388
|
+
* `ParserError`s; controlled by `severity.parseError`).
|
|
389
|
+
*
|
|
390
|
+
* **Order contract**: entries must appear in the order the parser emitted
|
|
391
|
+
* them, and `ml-core` pushes them onto the violations list **before** any
|
|
392
|
+
* rule iteration runs — so they always precede rule-level violations in
|
|
393
|
+
* test fixtures and reporter output. Custom parsers populating this field
|
|
394
|
+
* must preserve emit order; downstream consumers (including 80+ rule spec
|
|
395
|
+
* files) rely on it.
|
|
396
|
+
*/
|
|
397
|
+
readonly parseErrors?: readonly MLASTParseError[];
|
|
284
398
|
}
|
|
285
399
|
/**
|
|
286
400
|
* Interface for a markuplint-compatible parser.
|
|
@@ -333,6 +447,29 @@ export type ParserOptions = {
|
|
|
333
447
|
readonly ignoreFrontMatter?: boolean;
|
|
334
448
|
/** How to distinguish authored (component) element names from native HTML elements */
|
|
335
449
|
readonly authoredElementName?: ParserAuthoredElementNameDistinguishing;
|
|
450
|
+
/**
|
|
451
|
+
* Override how the underlying HTML parser decides between full-document
|
|
452
|
+
* and fragment parsing.
|
|
453
|
+
*
|
|
454
|
+
* - `'auto'` (default) — inspect the source: input starting with
|
|
455
|
+
* `<!doctype html>` or `<html>` is treated as a full document;
|
|
456
|
+
* anything else as a fragment. Backwards-compatible behaviour.
|
|
457
|
+
* - `'document'` — force full-document parsing. Use for sources that
|
|
458
|
+
* are complete HTML pages without an explicit doctype, so that
|
|
459
|
+
* document-level parse5 errors (`missing-doctype`, `misplaced-doctype`,
|
|
460
|
+
* etc.) surface via the `parse-error` channel.
|
|
461
|
+
* - `'fragment'` — force fragment parsing. Use for SSR / template
|
|
462
|
+
* partials whose source intentionally starts with `<head>`, `<meta>`,
|
|
463
|
+
* `<title>`, … as legitimate inserted chunks (parse5 should not emit
|
|
464
|
+
* `missing-doctype` for those).
|
|
465
|
+
*
|
|
466
|
+
* Template-engine parsers that internally re-invoke the HTML parser for
|
|
467
|
+
* embedded HTML chunks (Markdown HTML blocks, Pug raw HTML output, …)
|
|
468
|
+
* pass `'fragment'` to that internal call by default; users can still
|
|
469
|
+
* override that via `parserOptions` when their template legitimately
|
|
470
|
+
* carries a full document.
|
|
471
|
+
*/
|
|
472
|
+
readonly documentMode?: 'auto' | 'document' | 'fragment';
|
|
336
473
|
};
|
|
337
474
|
/**
|
|
338
475
|
* Configuration for distinguishing authored (component) elements from native HTML elements.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/ml-ast",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.5",
|
|
4
4
|
"description": "The markuplint AST types.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"engines": {
|
|
13
|
-
"node": ">=
|
|
13
|
+
"node": ">=24"
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
@@ -30,5 +30,5 @@
|
|
|
30
30
|
"dev": "tsc --watch --project tsconfig.build.json",
|
|
31
31
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "8d87463af2ff3f1b83fb28da20f1819362cf3555"
|
|
34
34
|
}
|
package/ARCHITECTURE.ja.md
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
# @markuplint/ml-ast
|
|
2
|
-
|
|
3
|
-
## 概要
|
|
4
|
-
|
|
5
|
-
`@markuplint/ml-ast` は、markuplint の言語非依存な抽象構文木(AST)中間表現を定義する純粋な型定義パッケージです。**ランタイムコードはゼロ**、**依存関係もゼロ**で、すべてのパーサーが生成し、すべての下流パッケージが消費する TypeScript 型定義のみを含みます。
|
|
6
|
-
|
|
7
|
-
すべてのマークアップ言語パーサー(HTML、JSX、Vue、Svelte、Astro、Pug など)はソースコードをここで定義された型にパースし、markuplint のコアとルールがソース言語に関係なく統一された AST 上で動作できるようにします。
|
|
8
|
-
|
|
9
|
-
## ディレクトリ構成
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
src/
|
|
13
|
-
├── index.ts — types.ts からすべての型を再エクスポート
|
|
14
|
-
└── types.ts — すべての型定義(約470行)
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## アーキテクチャ図
|
|
18
|
-
|
|
19
|
-
```mermaid
|
|
20
|
-
flowchart TD
|
|
21
|
-
subgraph parsers ["パーサー(上流)"]
|
|
22
|
-
html["@markuplint/html-parser"]
|
|
23
|
-
jsx["@markuplint/jsx-parser"]
|
|
24
|
-
vue["@markuplint/vue-parser"]
|
|
25
|
-
svelte["@markuplint/svelte-parser"]
|
|
26
|
-
astro["@markuplint/astro-parser"]
|
|
27
|
-
pug["@markuplint/pug-parser"]
|
|
28
|
-
parserUtils["@markuplint/parser-utils"]
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
subgraph ast ["@markuplint/ml-ast"]
|
|
32
|
-
types["型定義\n(MLASTDocument, MLASTElement,\nMLASTComment, MLASTText, ...)"]
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
subgraph downstream ["下流"]
|
|
36
|
-
mlCore["@markuplint/ml-core\n(AST → DOM マッピング)"]
|
|
37
|
-
mlConfig["@markuplint/ml-config"]
|
|
38
|
-
mlSpec["@markuplint/ml-spec"]
|
|
39
|
-
rules["@markuplint/rules"]
|
|
40
|
-
fileResolver["@markuplint/file-resolver"]
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
parsers -->|"生成"| types
|
|
44
|
-
types -->|"消費"| downstream
|
|
45
|
-
mlCore -->|"DOM ノードを作成"| types
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## 型継承図
|
|
49
|
-
|
|
50
|
-
```mermaid
|
|
51
|
-
classDiagram
|
|
52
|
-
class MLASTToken {
|
|
53
|
-
<<interface>>
|
|
54
|
-
+uuid: string
|
|
55
|
-
+raw: string
|
|
56
|
-
+offset: number
|
|
57
|
-
+line: number
|
|
58
|
-
+col: number
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
class MLASTAbstractNode {
|
|
62
|
-
<<interface>>
|
|
63
|
-
+type: MLASTNodeType
|
|
64
|
-
+nodeName: string
|
|
65
|
-
+parentNodeUuid: string | null
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
class MLASTDoctype {
|
|
69
|
-
<<interface>>
|
|
70
|
-
+type: "doctype"
|
|
71
|
-
+depth: number
|
|
72
|
-
+name: string
|
|
73
|
-
+publicId: string
|
|
74
|
-
+systemId: string
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
class MLASTElement {
|
|
78
|
-
<<interface>>
|
|
79
|
-
+type: "starttag"
|
|
80
|
-
+depth: number
|
|
81
|
-
+namespace: string
|
|
82
|
-
+elementType: ElementType
|
|
83
|
-
+attributes: MLASTAttr[]
|
|
84
|
-
+childNodes: MLASTChildNode[]
|
|
85
|
-
+blockBehavior: MLASTBlockBehavior | null
|
|
86
|
-
+pairNodeUuid: string | null
|
|
87
|
-
+isGhost: boolean
|
|
88
|
-
+isFragment: boolean
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
class MLASTElementCloseTag {
|
|
92
|
-
<<interface>>
|
|
93
|
-
+type: "endtag"
|
|
94
|
-
+depth: number
|
|
95
|
-
+pairNodeUuid: string | null
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
class MLASTComment {
|
|
99
|
-
<<interface>>
|
|
100
|
-
+type: "comment"
|
|
101
|
-
+depth: number
|
|
102
|
-
+isBogus: boolean
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
class MLASTText {
|
|
106
|
-
<<interface>>
|
|
107
|
-
+type: "text"
|
|
108
|
-
+depth: number
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
class MLASTPreprocessorSpecificBlock {
|
|
112
|
-
<<interface>>
|
|
113
|
-
+type: "psblock"
|
|
114
|
-
+blockBehavior: MLASTBlockBehavior | null
|
|
115
|
-
+depth: number
|
|
116
|
-
+childNodes: MLASTChildNode[]
|
|
117
|
-
+isBogus: boolean
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
class MLASTInvalid {
|
|
121
|
-
<<interface>>
|
|
122
|
-
+type: "invalid"
|
|
123
|
-
+depth: number
|
|
124
|
-
+kind: MLASTChildNode type
|
|
125
|
-
+isBogus: true
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
class MLASTHTMLAttr {
|
|
129
|
-
<<interface>>
|
|
130
|
-
+type: "attr"
|
|
131
|
-
+name: MLASTToken
|
|
132
|
-
+value: MLASTToken
|
|
133
|
-
+isDynamicValue: boolean
|
|
134
|
-
+isDirective: boolean
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
class MLASTSpreadAttr {
|
|
138
|
-
<<interface>>
|
|
139
|
-
+type: "spread"
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
MLASTToken <|-- MLASTAbstractNode
|
|
143
|
-
MLASTAbstractNode <|-- MLASTDoctype
|
|
144
|
-
MLASTAbstractNode <|-- MLASTElement
|
|
145
|
-
MLASTAbstractNode <|-- MLASTElementCloseTag
|
|
146
|
-
MLASTAbstractNode <|-- MLASTComment
|
|
147
|
-
MLASTAbstractNode <|-- MLASTText
|
|
148
|
-
MLASTAbstractNode <|-- MLASTPreprocessorSpecificBlock
|
|
149
|
-
MLASTAbstractNode <|-- MLASTInvalid
|
|
150
|
-
MLASTToken <|-- MLASTHTMLAttr
|
|
151
|
-
MLASTToken <|-- MLASTSpreadAttr
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
## 共用体型
|
|
155
|
-
|
|
156
|
-
```mermaid
|
|
157
|
-
flowchart TD
|
|
158
|
-
subgraph MLASTNode ["MLASTNode(全ノード型)"]
|
|
159
|
-
subgraph MLASTNodeTreeItem ["MLASTNodeTreeItem"]
|
|
160
|
-
MLASTDoctype["MLASTDoctype"]
|
|
161
|
-
subgraph MLASTChildNode ["MLASTChildNode"]
|
|
162
|
-
subgraph MLASTTag ["MLASTTag"]
|
|
163
|
-
MLASTElement["MLASTElement"]
|
|
164
|
-
MLASTElementCloseTag["MLASTElementCloseTag"]
|
|
165
|
-
end
|
|
166
|
-
MLASTText["MLASTText"]
|
|
167
|
-
MLASTComment["MLASTComment"]
|
|
168
|
-
MLASTPreprocessorSpecificBlock["MLASTPreprocessorSpecificBlock"]
|
|
169
|
-
MLASTInvalid["MLASTInvalid"]
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
subgraph MLASTAttr ["MLASTAttr"]
|
|
173
|
-
MLASTHTMLAttr["MLASTHTMLAttr"]
|
|
174
|
-
MLASTSpreadAttr["MLASTSpreadAttr"]
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
style MLASTElement fill:#e1f5fe
|
|
179
|
-
style MLASTPreprocessorSpecificBlock fill:#e1f5fe
|
|
180
|
-
|
|
181
|
-
note1["MLASTParentNode = MLASTElement | MLASTPreprocessorSpecificBlock\n(青でハイライト)"]
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## ノード型一覧
|
|
185
|
-
|
|
186
|
-
| 型 | `type` 値 | 代表例 | 説明 |
|
|
187
|
-
| -------------------------------- | ------------ | ---------------------- | ---------------------------------------- |
|
|
188
|
-
| `MLASTDoctype` | `'doctype'` | `<!DOCTYPE html>` | DOCTYPE 宣言 |
|
|
189
|
-
| `MLASTElement` | `'starttag'` | `<div class="foo">` | 開始タグ。属性・子ノード・名前空間を保持 |
|
|
190
|
-
| `MLASTElementCloseTag` | `'endtag'` | `</div>` | 閉じタグ。開始タグとペア |
|
|
191
|
-
| `MLASTComment` | `'comment'` | `<!-- ... -->` | HTML コメント。bogus フラグ付き |
|
|
192
|
-
| `MLASTText` | `'text'` | テキスト内容 | 要素間の文字データ |
|
|
193
|
-
| `MLASTPreprocessorSpecificBlock` | `'psblock'` | `{#if}`, `<% %>` | テンプレートエンジン構文 |
|
|
194
|
-
| `MLASTInvalid` | `'invalid'` | パース不能マークアップ | 不正ノード。意図された種別のヒント付き |
|
|
195
|
-
| `MLASTHTMLAttr` | `'attr'` | `class="foo"` | 完全分解された HTML 属性 |
|
|
196
|
-
| `MLASTSpreadAttr` | `'spread'` | `{...props}` | JSX スプレッド属性 |
|
|
197
|
-
|
|
198
|
-
各型の詳細は[ノードリファレンス](docs/node-reference.ja.md)を参照してください。
|
|
199
|
-
|
|
200
|
-
## AST から MLDOM へのマッピング
|
|
201
|
-
|
|
202
|
-
各 AST ノードは、最終的に `@markuplint/ml-core` によって **MLDOM** ノードに変換されます。MLDOM は [DOM Standard](https://dom.spec.whatwg.org/) に準拠しており、各クラスは対応する DOM インターフェース(`Node`、`Element`、`DocumentType`、`Comment`、`Text` など)を実装しているため、リントルールは標準 DOM API を使って検査できます。
|
|
203
|
-
|
|
204
|
-
| AST 型(`ml-ast`) | MLDOM クラス(`ml-core`) | DOM インターフェース | `nodeType` |
|
|
205
|
-
| ------------------------------------ | -------------------------- | ------------------------ | ---------- |
|
|
206
|
-
| `MLASTDoctype` | `MLDocumentType` | `DocumentType` | `10` |
|
|
207
|
-
| `MLASTElement` | `MLElement` | `Element`, `HTMLElement` | `1` |
|
|
208
|
-
| `MLASTComment` | `MLComment` | `Comment` | `8` |
|
|
209
|
-
| `MLASTText` | `MLText` | `Text` | `3` |
|
|
210
|
-
| `MLASTPreprocessorSpecificBlock` | `MLBlock` | _(markuplint 独自)_ | `101` |
|
|
211
|
-
| `MLASTInvalid`(`kind: 'starttag'`) | `MLElement`(`x-invalid`) | `Element`, `HTMLElement` | `1` |
|
|
212
|
-
| `MLASTInvalid`(その他) | `MLText` | `Text` | `3` |
|
|
213
|
-
| `MLASTHTMLAttr` / `MLASTSpreadAttr` | `MLAttr` | `Attr` | `2` |
|
|
214
|
-
|
|
215
|
-
**特殊なノード:**
|
|
216
|
-
|
|
217
|
-
- **`MLBlock`**(`nodeType: 101`)は DOM Standard に相当するものがない markuplint 独自の拡張です。透過的なコンテナとして機能し、子ノードはツリー走査時に親に属するものとして扱われます。
|
|
218
|
-
- **`MLElementCloseTag`** は `createNode()` で生成されません。代わりに `MLElement` が `pairNodeUuid` を解決して閉じタグの AST ノードを検索し、`MLElementCloseTag` を生成します。ペアとなる要素の付属物としてのみ存在し、DOM ツリー走査の対象ではありません。
|
|
219
|
-
- **`MLASTInvalid`** はリカバリノードです。MLDOM にそのまま保持されることはなく、`kind` フィールドに応じて `MLElement`(タグ名 `x-invalid`)または `MLText` に変換されます。
|
|
220
|
-
|
|
221
|
-
詳細は[ノードリファレンス -- AST から MLDOM へのマッピング](docs/node-reference.ja.md#ast-から-mldom-へのマッピング)を参照してください。
|
|
222
|
-
|
|
223
|
-
## 属性分解モデル
|
|
224
|
-
|
|
225
|
-
`MLASTHTMLAttr` は各属性を完全な位置情報を持つ個別のトークンに分解します:
|
|
226
|
-
|
|
227
|
-
```
|
|
228
|
-
·class="container"
|
|
229
|
-
↑ ↑↑ ↑
|
|
230
|
-
│ ││ └─ endQuote
|
|
231
|
-
│ │└─ value
|
|
232
|
-
│ └─ startQuote
|
|
233
|
-
│ equal
|
|
234
|
-
└─ spacesBeforeName
|
|
235
|
-
name
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
これにより、リントルールは `=` 前後のホワイトスペース、引用符スタイル、属性命名規則を正確なソース位置で検証できます。完全なフィールドドキュメントは[ノードリファレンス](docs/node-reference.ja.md#mlasthtmlattr)を参照してください。
|
|
239
|
-
|
|
240
|
-
## パーサーインターフェース
|
|
241
|
-
|
|
242
|
-
| 型 | 説明 |
|
|
243
|
-
| ---------------- | -------------------------------------------------------- |
|
|
244
|
-
| `MLParser` | markuplint 互換パーサーのインターフェース |
|
|
245
|
-
| `MLParserModule` | パーサーインスタンスをエクスポートするモジュールラッパー |
|
|
246
|
-
|
|
247
|
-
`MLParser` は `MLASTDocument` を返す `parse(sourceCode, options?)` メソッドを必要とします。オプションフィールドには `endTag`(終了タグ処理戦略)、`booleanish`(ブール属性検出)、`tagNameCaseSensitive`(XHTML/JSX 用)があります。
|
|
248
|
-
|
|
249
|
-
## 設定型
|
|
250
|
-
|
|
251
|
-
| 型 | 説明 |
|
|
252
|
-
| ----------------------------------------- | ---------------------------------------------------------------------- |
|
|
253
|
-
| `MLASTNodeType` | ノード種別の判別共用体タグ |
|
|
254
|
-
| `ElementType` | 要素分類:`'html' \| 'web-component' \| 'authored'` |
|
|
255
|
-
| `EndTagType` | 終了タグ戦略:`'xml' \| 'omittable' \| 'never'` |
|
|
256
|
-
| `Namespace` | 短い名前空間識別子:`'html' \| 'svg' \| 'mml' \| 'xlink'` |
|
|
257
|
-
| `NamespaceURI` | HTML、SVG、MathML、XLink の完全な名前空間 URI |
|
|
258
|
-
| `ParserOptions` | パーサーに渡すオプション(`ignoreFrontMatter`、`authoredElementName`) |
|
|
259
|
-
| `ParserAuthoredElementNameDistinguishing` | 著者定義要素を区別するための設定 |
|
|
260
|
-
| `Walker<Node>` | AST ノードを走査するコールバック |
|
|
261
|
-
|
|
262
|
-
## 外部依存関係
|
|
263
|
-
|
|
264
|
-
なし。このパッケージはランタイム依存関係がゼロです。TypeScript の型定義のみをエクスポートします。
|
|
265
|
-
|
|
266
|
-
## 統合ポイント
|
|
267
|
-
|
|
268
|
-
```mermaid
|
|
269
|
-
flowchart TD
|
|
270
|
-
subgraph upstream ["上流(パーサー)"]
|
|
271
|
-
htmlParser["@markuplint/html-parser"]
|
|
272
|
-
parserUtils["@markuplint/parser-utils"]
|
|
273
|
-
jsxParser["@markuplint/jsx-parser"]
|
|
274
|
-
astroParser["@markuplint/astro-parser"]
|
|
275
|
-
vueParser["@markuplint/vue-parser"]
|
|
276
|
-
svelteParser["@markuplint/svelte-parser"]
|
|
277
|
-
pugParser["@markuplint/pug-parser"]
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
subgraph pkg ["@markuplint/ml-ast"]
|
|
281
|
-
astTypes["型定義"]
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
subgraph downstream ["下流"]
|
|
285
|
-
mlCore["@markuplint/ml-core"]
|
|
286
|
-
mlConfig["@markuplint/ml-config"]
|
|
287
|
-
mlSpec["@markuplint/ml-spec"]
|
|
288
|
-
fileResolver["@markuplint/file-resolver"]
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
upstream -->|"MLParser を実装\nMLASTDocument を生成"| astTypes
|
|
292
|
-
astTypes -->|"MLASTNode 型\nMLParser インターフェース"| downstream
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### 上流
|
|
296
|
-
|
|
297
|
-
すべてのパーサーは `MLParser` インターフェースを実装し、このパッケージで定義された AST ノード型を含む `MLASTDocument` インスタンスを生成します。
|
|
298
|
-
|
|
299
|
-
### 下流
|
|
300
|
-
|
|
301
|
-
- **`@markuplint/ml-core`** は AST ノードを消費し、`createNode()` を通じて DOM ノードにマッピングします。`MLASTElement` が `MLElement` に、`MLASTText` が `MLText` になるなど、主要な統合ポイントです。
|
|
302
|
-
- **`@markuplint/ml-config`** は設定スキーマ定義で AST 型を参照します。
|
|
303
|
-
- **`@markuplint/ml-spec`** は名前空間と要素型の定義を使用します。
|
|
304
|
-
- **`@markuplint/file-resolver`** はパーサー関連の型を参照します。
|
|
305
|
-
|
|
306
|
-
## ドキュメントマップ
|
|
307
|
-
|
|
308
|
-
- [ノードリファレンス](docs/node-reference.ja.md) -- 各 AST ノード型の詳細ドキュメント
|
|
309
|
-
- [メンテナンスガイド](docs/maintenance.ja.md) -- コマンド、レシピ、トラブルシューティング
|