@markuplint/rules 4.11.2 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -3
- package/SKILL.md +76 -0
- package/lib/attr-check.d.ts +41 -5
- package/lib/attr-check.js +29 -5
- package/lib/attr-duplication/index.d.ts +7 -0
- package/lib/attr-duplication/index.js +7 -0
- package/lib/attr-duplication/meta.d.ts +1 -0
- package/lib/attr-duplication/meta.js +1 -0
- package/lib/attr-value-quotes/index.d.ts +10 -0
- package/lib/attr-value-quotes/index.js +10 -0
- package/lib/attr-value-quotes/meta.d.ts +1 -0
- package/lib/attr-value-quotes/meta.js +1 -0
- package/lib/case-sensitive-attr-name/index.d.ts +9 -0
- package/lib/case-sensitive-attr-name/index.js +8 -0
- package/lib/case-sensitive-attr-name/meta.d.ts +1 -0
- package/lib/case-sensitive-attr-name/meta.js +1 -0
- package/lib/case-sensitive-tag-name/index.d.ts +9 -0
- package/lib/case-sensitive-tag-name/index.js +8 -0
- package/lib/case-sensitive-tag-name/meta.d.ts +1 -0
- package/lib/case-sensitive-tag-name/meta.js +1 -0
- package/lib/character-reference/index.d.ts +8 -0
- package/lib/character-reference/index.js +16 -0
- package/lib/character-reference/meta.d.ts +1 -0
- package/lib/character-reference/meta.js +1 -0
- package/lib/class-naming/index.d.ts +9 -0
- package/lib/class-naming/index.js +8 -0
- package/lib/class-naming/meta.d.ts +1 -0
- package/lib/class-naming/meta.js +1 -0
- package/lib/create-message.d.ts +27 -0
- package/lib/create-message.js +56 -1
- package/lib/debug.d.ts +9 -0
- package/lib/debug.js +5 -0
- package/lib/deprecated-attr/index.d.ts +6 -0
- package/lib/deprecated-attr/index.js +6 -0
- package/lib/deprecated-attr/meta.d.ts +1 -0
- package/lib/deprecated-attr/meta.js +1 -0
- package/lib/deprecated-element/index.d.ts +8 -0
- package/lib/deprecated-element/index.js +8 -0
- package/lib/deprecated-element/meta.d.ts +1 -0
- package/lib/deprecated-element/meta.js +1 -0
- package/lib/disallowed-element/index.d.ts +7 -0
- package/lib/disallowed-element/index.js +7 -0
- package/lib/disallowed-element/meta.d.ts +1 -0
- package/lib/disallowed-element/meta.js +1 -0
- package/lib/doctype/index.d.ts +10 -0
- package/lib/doctype/index.js +8 -0
- package/lib/doctype/meta.d.ts +1 -0
- package/lib/doctype/meta.js +1 -0
- package/lib/end-tag/index.d.ts +7 -0
- package/lib/end-tag/index.js +7 -0
- package/lib/end-tag/meta.d.ts +1 -0
- package/lib/end-tag/meta.js +1 -0
- package/lib/heading-levels/index.d.ts +6 -0
- package/lib/heading-levels/index.js +6 -0
- package/lib/heading-levels/meta.d.ts +1 -0
- package/lib/heading-levels/meta.js +1 -0
- package/lib/helpers.d.ts +104 -0
- package/lib/helpers.js +105 -2
- package/lib/id-duplication/index.d.ts +7 -0
- package/lib/id-duplication/index.js +7 -0
- package/lib/id-duplication/meta.d.ts +1 -0
- package/lib/id-duplication/meta.js +1 -0
- package/lib/index.d.ts +13 -0
- package/lib/index.js +12 -0
- package/lib/ineffective-attr/index.d.ts +7 -0
- package/lib/ineffective-attr/index.js +7 -0
- package/lib/ineffective-attr/meta.d.ts +1 -0
- package/lib/ineffective-attr/meta.js +1 -0
- package/lib/invalid-attr/index.d.ts +24 -0
- package/lib/invalid-attr/index.js +17 -0
- package/lib/invalid-attr/meta.d.ts +1 -0
- package/lib/invalid-attr/meta.js +1 -0
- package/lib/label-has-control/index.d.ts +7 -0
- package/lib/label-has-control/index.js +11 -0
- package/lib/label-has-control/meta.d.ts +1 -0
- package/lib/label-has-control/meta.js +1 -0
- package/lib/landmark-roles/index.d.ts +14 -0
- package/lib/landmark-roles/index.js +21 -0
- package/lib/landmark-roles/meta.d.ts +1 -0
- package/lib/landmark-roles/meta.js +1 -0
- package/lib/neighbor-popovers/index.d.ts +8 -0
- package/lib/neighbor-popovers/index.js +26 -2
- package/lib/neighbor-popovers/meta.d.ts +1 -0
- package/lib/neighbor-popovers/meta.js +1 -0
- package/lib/no-ambiguous-navigable-target-names/index.d.ts +8 -0
- package/lib/no-ambiguous-navigable-target-names/index.js +8 -0
- package/lib/no-ambiguous-navigable-target-names/meta.d.ts +1 -0
- package/lib/no-ambiguous-navigable-target-names/meta.js +1 -0
- package/lib/no-boolean-attr-value/index.d.ts +7 -0
- package/lib/no-boolean-attr-value/index.js +7 -0
- package/lib/no-boolean-attr-value/meta.d.ts +1 -0
- package/lib/no-boolean-attr-value/meta.js +1 -0
- package/lib/no-consecutive-br/index.d.ts +8 -0
- package/lib/no-consecutive-br/index.js +8 -0
- package/lib/no-consecutive-br/meta.d.ts +1 -0
- package/lib/no-consecutive-br/meta.js +1 -0
- package/lib/no-default-value/index.d.ts +7 -0
- package/lib/no-default-value/index.js +7 -0
- package/lib/no-default-value/meta.d.ts +1 -0
- package/lib/no-default-value/meta.js +1 -0
- package/lib/no-duplicate-dt/index.d.ts +6 -0
- package/lib/no-duplicate-dt/index.js +6 -0
- package/lib/no-duplicate-dt/meta.d.ts +1 -0
- package/lib/no-duplicate-dt/meta.js +1 -0
- package/lib/no-empty-palpable-content/index.d.ts +13 -0
- package/lib/no-empty-palpable-content/index.js +12 -0
- package/lib/no-empty-palpable-content/meta.d.ts +1 -0
- package/lib/no-empty-palpable-content/meta.js +1 -0
- package/lib/no-hard-code-id/index.d.ts +8 -0
- package/lib/no-hard-code-id/index.js +8 -0
- package/lib/no-hard-code-id/meta.d.ts +1 -0
- package/lib/no-hard-code-id/meta.js +1 -0
- package/lib/no-orphaned-end-tag/index.d.ts +7 -0
- package/lib/no-orphaned-end-tag/index.js +7 -0
- package/lib/no-orphaned-end-tag/meta.d.ts +1 -0
- package/lib/no-orphaned-end-tag/meta.js +1 -0
- package/lib/no-refer-to-non-existent-id/index.d.ts +8 -0
- package/lib/no-refer-to-non-existent-id/index.js +9 -0
- package/lib/no-refer-to-non-existent-id/meta.d.ts +1 -0
- package/lib/no-refer-to-non-existent-id/meta.js +1 -0
- package/lib/no-use-event-handler-attr/index.d.ts +10 -0
- package/lib/no-use-event-handler-attr/index.js +8 -0
- package/lib/no-use-event-handler-attr/meta.d.ts +1 -0
- package/lib/no-use-event-handler-attr/meta.js +1 -0
- package/lib/permitted-contents/choice.d.ts +17 -0
- package/lib/permitted-contents/choice.js +30 -0
- package/lib/permitted-contents/complex-branch.d.ts +11 -7
- package/lib/permitted-contents/complex-branch.js +11 -7
- package/lib/permitted-contents/content-model.d.ts +11 -0
- package/lib/permitted-contents/content-model.js +32 -0
- package/lib/permitted-contents/count-pattern.d.ts +13 -7
- package/lib/permitted-contents/count-pattern.js +23 -7
- package/lib/permitted-contents/debug.browser.d.ts +12 -0
- package/lib/permitted-contents/debug.browser.js +12 -0
- package/lib/permitted-contents/debug.d.ts +12 -0
- package/lib/permitted-contents/debug.js +12 -0
- package/lib/permitted-contents/index.d.ts +12 -0
- package/lib/permitted-contents/index.js +21 -0
- package/lib/permitted-contents/matches-selector.d.ts +19 -0
- package/lib/permitted-contents/matches-selector.js +33 -0
- package/lib/permitted-contents/meta.d.ts +1 -0
- package/lib/permitted-contents/meta.js +1 -0
- package/lib/permitted-contents/order.d.ts +14 -7
- package/lib/permitted-contents/order.js +14 -7
- package/lib/permitted-contents/recursive-branch.d.ts +17 -0
- package/lib/permitted-contents/recursive-branch.js +17 -0
- package/lib/permitted-contents/represent-transparent-nodes.d.ts +29 -0
- package/lib/permitted-contents/represent-transparent-nodes.js +24 -0
- package/lib/permitted-contents/start.d.ts +12 -6
- package/lib/permitted-contents/start.js +12 -6
- package/lib/permitted-contents/transparent.d.ts +12 -0
- package/lib/permitted-contents/transparent.js +12 -0
- package/lib/permitted-contents/types.d.ts +67 -0
- package/lib/permitted-contents/utils.d.ts +161 -1
- package/lib/permitted-contents/utils.js +194 -0
- package/lib/placeholder-label-option/index.d.ts +7 -0
- package/lib/placeholder-label-option/index.js +19 -15
- package/lib/placeholder-label-option/meta.d.ts +1 -0
- package/lib/placeholder-label-option/meta.js +1 -0
- package/lib/require-accessible-name/index.d.ts +11 -0
- package/lib/require-accessible-name/index.js +7 -0
- package/lib/require-accessible-name/meta.d.ts +1 -0
- package/lib/require-accessible-name/meta.js +1 -0
- package/lib/require-datetime/index.d.ts +12 -0
- package/lib/require-datetime/index.js +8 -0
- package/lib/require-datetime/meta.d.ts +1 -0
- package/lib/require-datetime/meta.js +1 -0
- package/lib/require-datetime/types.d.ts +7 -0
- package/lib/require-datetime/utils.d.ts +18 -5
- package/lib/require-datetime/utils.js +53 -9
- package/lib/required-attr/index.d.ts +13 -0
- package/lib/required-attr/index.js +7 -0
- package/lib/required-attr/meta.d.ts +1 -0
- package/lib/required-attr/meta.js +1 -0
- package/lib/required-element/index.d.ts +14 -0
- package/lib/required-element/index.js +14 -2
- package/lib/required-element/meta.d.ts +1 -0
- package/lib/required-element/meta.js +1 -0
- package/lib/required-h1/index.d.ts +12 -0
- package/lib/required-h1/index.js +7 -0
- package/lib/required-h1/meta.d.ts +1 -0
- package/lib/required-h1/meta.js +1 -0
- package/lib/table-row-column-alignment/find-children.d.ts +10 -0
- package/lib/table-row-column-alignment/find-children.js +11 -0
- package/lib/table-row-column-alignment/grid.d.ts +60 -0
- package/lib/table-row-column-alignment/grid.js +85 -0
- package/lib/table-row-column-alignment/index.d.ts +8 -0
- package/lib/table-row-column-alignment/index.js +8 -0
- package/lib/table-row-column-alignment/meta.d.ts +1 -0
- package/lib/table-row-column-alignment/meta.js +1 -0
- package/lib/table-row-column-alignment/types.d.ts +10 -0
- package/lib/use-list/index.d.ts +16 -0
- package/lib/use-list/index.js +20 -0
- package/lib/use-list/meta.d.ts +1 -0
- package/lib/use-list/meta.js +1 -0
- package/lib/wai-aria/checkings/abstract-role.d.ts +9 -0
- package/lib/wai-aria/checkings/abstract-role.js +9 -0
- package/lib/wai-aria/checkings/default-value.d.ts +11 -0
- package/lib/wai-aria/checkings/default-value.js +11 -0
- package/lib/wai-aria/checkings/deprecated-props.d.ts +11 -0
- package/lib/wai-aria/checkings/deprecated-props.js +11 -0
- package/lib/wai-aria/checkings/deprecated-role.d.ts +10 -0
- package/lib/wai-aria/checkings/deprecated-role.js +10 -0
- package/lib/wai-aria/checkings/disallowed-prop.d.ts +14 -0
- package/lib/wai-aria/checkings/disallowed-prop.js +14 -0
- package/lib/wai-aria/checkings/implicit-props.d.ts +13 -0
- package/lib/wai-aria/checkings/implicit-props.js +13 -0
- package/lib/wai-aria/checkings/implicit-role.d.ts +9 -0
- package/lib/wai-aria/checkings/implicit-role.js +9 -0
- package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +9 -0
- package/lib/wai-aria/checkings/interaction-in-hidden.js +15 -4
- package/lib/wai-aria/checkings/no-global-prop.d.ts +10 -0
- package/lib/wai-aria/checkings/no-global-prop.js +10 -0
- package/lib/wai-aria/checkings/non-existent-role.d.ts +10 -0
- package/lib/wai-aria/checkings/non-existent-role.js +10 -0
- package/lib/wai-aria/checkings/permitted-roles.d.ts +10 -0
- package/lib/wai-aria/checkings/permitted-roles.js +10 -0
- package/lib/wai-aria/checkings/presentational-children.d.ts +7 -1
- package/lib/wai-aria/checkings/presentational-children.js +14 -1
- package/lib/wai-aria/checkings/required-owned-elements.d.ts +9 -1
- package/lib/wai-aria/checkings/required-owned-elements.js +16 -1
- package/lib/wai-aria/checkings/required-prop.d.ts +13 -0
- package/lib/wai-aria/checkings/required-prop.js +13 -0
- package/lib/wai-aria/checkings/value.d.ts +23 -0
- package/lib/wai-aria/checkings/value.js +32 -0
- package/lib/wai-aria/index.d.ts +10 -0
- package/lib/wai-aria/index.js +10 -0
- package/lib/wai-aria/meta.d.ts +1 -0
- package/lib/wai-aria/meta.js +1 -0
- package/lib/wai-aria/types.d.ts +17 -0
- package/package.json +9 -9
|
@@ -2,4 +2,21 @@ import type { SelectorResult } from './matches-selector.js';
|
|
|
2
2
|
import type { ChildNode, Options, Specs } from './types.js';
|
|
3
3
|
import type { PermittedContentPattern, Model } from '@markuplint/ml-spec';
|
|
4
4
|
import type { ReadonlyDeep } from 'type-fest';
|
|
5
|
+
/**
|
|
6
|
+
* Evaluates a model or nested pattern array against child nodes at the leaf level
|
|
7
|
+
* of the content model tree. If the input is a nested pattern array (not a terminal model),
|
|
8
|
+
* it recurses back into `order` for sequential evaluation. If it is a terminal model
|
|
9
|
+
* (a single selector string or an array of selector strings representing alternatives),
|
|
10
|
+
* it tests the first unmatched child node against each selector via `matchesSelector`.
|
|
11
|
+
*
|
|
12
|
+
* For array-of-selectors models, the selectors act as alternatives (logical OR): the first
|
|
13
|
+
* selector to match the child node produces the result.
|
|
14
|
+
*
|
|
15
|
+
* @param model - Either a terminal model (selector string or array of selector strings) or a nested pattern array.
|
|
16
|
+
* @param childNodes - The child nodes to validate against the model.
|
|
17
|
+
* @param specs - The resolved spec data for content model lookups.
|
|
18
|
+
* @param options - Validation behavior options.
|
|
19
|
+
* @param depth - The current recursion depth, used for debug logging and nested evaluation.
|
|
20
|
+
* @returns A selector result indicating whether the first unmatched child node matches the model.
|
|
21
|
+
*/
|
|
5
22
|
export declare function recursiveBranch(model: ReadonlyDeep<Model | PermittedContentPattern[]>, childNodes: readonly ChildNode[], specs: Specs, options: Options, depth: number): SelectorResult;
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import { matchesSelector } from './matches-selector.js';
|
|
2
2
|
import { order } from './order.js';
|
|
3
3
|
import { Collection, isModel } from './utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Evaluates a model or nested pattern array against child nodes at the leaf level
|
|
6
|
+
* of the content model tree. If the input is a nested pattern array (not a terminal model),
|
|
7
|
+
* it recurses back into `order` for sequential evaluation. If it is a terminal model
|
|
8
|
+
* (a single selector string or an array of selector strings representing alternatives),
|
|
9
|
+
* it tests the first unmatched child node against each selector via `matchesSelector`.
|
|
10
|
+
*
|
|
11
|
+
* For array-of-selectors models, the selectors act as alternatives (logical OR): the first
|
|
12
|
+
* selector to match the child node produces the result.
|
|
13
|
+
*
|
|
14
|
+
* @param model - Either a terminal model (selector string or array of selector strings) or a nested pattern array.
|
|
15
|
+
* @param childNodes - The child nodes to validate against the model.
|
|
16
|
+
* @param specs - The resolved spec data for content model lookups.
|
|
17
|
+
* @param options - Validation behavior options.
|
|
18
|
+
* @param depth - The current recursion depth, used for debug logging and nested evaluation.
|
|
19
|
+
* @returns A selector result indicating whether the first unmatched child node matches the model.
|
|
20
|
+
*/
|
|
4
21
|
export function recursiveBranch(model,
|
|
5
22
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
6
23
|
childNodes, specs, options, depth) {
|
|
@@ -1,8 +1,37 @@
|
|
|
1
1
|
import type { ChildNode, Options, Result, Specs } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A map tracking child nodes that are currently being evaluated through
|
|
4
|
+
* a transparent content model. Used to prevent infinite recursion and
|
|
5
|
+
* to enable special handling in error messages and debug output.
|
|
6
|
+
*/
|
|
2
7
|
export declare const transparentMode: Map<ChildNode, true>;
|
|
8
|
+
/**
|
|
9
|
+
* Represents a possible resolution of transparent content model nodes,
|
|
10
|
+
* containing the flattened list of child nodes to validate and any
|
|
11
|
+
* errors detected during transparent model resolution.
|
|
12
|
+
*/
|
|
3
13
|
type TransparentNode = {
|
|
4
14
|
nodes: ChildNode[];
|
|
5
15
|
errors: Result[];
|
|
6
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Resolves transparent content model elements by replacing them with their
|
|
19
|
+
* children for validation purposes. In HTML, elements like `<a>`, `<ins>`, and `<del>`
|
|
20
|
+
* have transparent content models, meaning their children must be valid in the
|
|
21
|
+
* parent's content model as if the transparent element were not present.
|
|
22
|
+
*
|
|
23
|
+
* This function:
|
|
24
|
+
* 1. Identifies child elements with transparent content models.
|
|
25
|
+
* 2. Filters out children that match non-transparent parts of the element's content model.
|
|
26
|
+
* 3. Replaces the transparent element with its remaining (unmatched) children.
|
|
27
|
+
* 4. Validates that each remaining child satisfies the transparent model's condition selector.
|
|
28
|
+
* 5. Recursively resolves parent-level transparent nodes to propagate errors up the tree.
|
|
29
|
+
* 6. Uses `branchesToPatterns` to handle branching when multiple resolutions are possible.
|
|
30
|
+
*
|
|
31
|
+
* @param childNodes - The child nodes of the element being validated, some of which may be transparent.
|
|
32
|
+
* @param specs - The resolved spec data for content model lookups.
|
|
33
|
+
* @param options - Validation behavior options.
|
|
34
|
+
* @returns An array of possible transparent node resolutions, each with flattened nodes and accumulated errors.
|
|
35
|
+
*/
|
|
7
36
|
export declare function representTransparentNodes(childNodes: readonly ChildNode[], specs: Specs, options: Options): TransparentNode[];
|
|
8
37
|
export {};
|
|
@@ -2,7 +2,31 @@ import { getContentModel } from '@markuplint/ml-spec';
|
|
|
2
2
|
import { branchesToPatterns } from '@markuplint/shared';
|
|
3
3
|
import { order } from './order.js';
|
|
4
4
|
import { Collection, isTransparent, matches } from './utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* A map tracking child nodes that are currently being evaluated through
|
|
7
|
+
* a transparent content model. Used to prevent infinite recursion and
|
|
8
|
+
* to enable special handling in error messages and debug output.
|
|
9
|
+
*/
|
|
5
10
|
export const transparentMode = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* Resolves transparent content model elements by replacing them with their
|
|
13
|
+
* children for validation purposes. In HTML, elements like `<a>`, `<ins>`, and `<del>`
|
|
14
|
+
* have transparent content models, meaning their children must be valid in the
|
|
15
|
+
* parent's content model as if the transparent element were not present.
|
|
16
|
+
*
|
|
17
|
+
* This function:
|
|
18
|
+
* 1. Identifies child elements with transparent content models.
|
|
19
|
+
* 2. Filters out children that match non-transparent parts of the element's content model.
|
|
20
|
+
* 3. Replaces the transparent element with its remaining (unmatched) children.
|
|
21
|
+
* 4. Validates that each remaining child satisfies the transparent model's condition selector.
|
|
22
|
+
* 5. Recursively resolves parent-level transparent nodes to propagate errors up the tree.
|
|
23
|
+
* 6. Uses `branchesToPatterns` to handle branching when multiple resolutions are possible.
|
|
24
|
+
*
|
|
25
|
+
* @param childNodes - The child nodes of the element being validated, some of which may be transparent.
|
|
26
|
+
* @param specs - The resolved spec data for content model lookups.
|
|
27
|
+
* @param options - Validation behavior options.
|
|
28
|
+
* @returns An array of possible transparent node resolutions, each with flattened nodes and accumulated errors.
|
|
29
|
+
*/
|
|
6
30
|
export function representTransparentNodes(
|
|
7
31
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
8
32
|
childNodes, specs, options) {
|
|
@@ -2,12 +2,18 @@ import type { ContentModelResult, Element, Options, Specs } from './types.js';
|
|
|
2
2
|
import type { ContentModel } from '@markuplint/ml-spec';
|
|
3
3
|
import type { ReadonlyDeep } from 'type-fest';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Entry point for validating an element's child nodes against a content model definition.
|
|
6
|
+
* Handles the three forms of content model: `false` (no content allowed), `true` (any content
|
|
7
|
+
* allowed), or an ordered pattern array. For pattern arrays, transparent content model nodes
|
|
8
|
+
* are first resolved, then each resulting pattern of child nodes is validated via `order`.
|
|
6
9
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* @param
|
|
11
|
-
* @
|
|
10
|
+
* When `options.evaluateConditionalChildNodes` is enabled, all conditional branches
|
|
11
|
+
* (e.g., from template directives) are evaluated independently.
|
|
12
|
+
*
|
|
13
|
+
* @param contents - The content model definition: `false` for empty, `true` for any, or an array of patterns.
|
|
14
|
+
* @param el - The parent element whose children are being validated.
|
|
15
|
+
* @param specs - The resolved spec data for content model lookups.
|
|
16
|
+
* @param options - Validation behavior options.
|
|
17
|
+
* @returns An array of content model results describing any violations found.
|
|
12
18
|
*/
|
|
13
19
|
export declare function start(contents: ReadonlyDeep<ContentModel['contents']>, el: Element, specs: Specs, options: Options): ContentModelResult[];
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { order } from './order.js';
|
|
2
2
|
import { representTransparentNodes } from './represent-transparent-nodes.js';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Entry point for validating an element's child nodes against a content model definition.
|
|
5
|
+
* Handles the three forms of content model: `false` (no content allowed), `true` (any content
|
|
6
|
+
* allowed), or an ordered pattern array. For pattern arrays, transparent content model nodes
|
|
7
|
+
* are first resolved, then each resulting pattern of child nodes is validated via `order`.
|
|
5
8
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @param
|
|
10
|
-
* @
|
|
9
|
+
* When `options.evaluateConditionalChildNodes` is enabled, all conditional branches
|
|
10
|
+
* (e.g., from template directives) are evaluated independently.
|
|
11
|
+
*
|
|
12
|
+
* @param contents - The content model definition: `false` for empty, `true` for any, or an array of patterns.
|
|
13
|
+
* @param el - The parent element whose children are being validated.
|
|
14
|
+
* @param specs - The resolved spec data for content model lookups.
|
|
15
|
+
* @param options - Validation behavior options.
|
|
16
|
+
* @returns An array of content model results describing any violations found.
|
|
11
17
|
*/
|
|
12
18
|
export function start(contents,
|
|
13
19
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
@@ -1,2 +1,14 @@
|
|
|
1
1
|
import type { ChildNode, Result } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Handles the transparent content model pattern by passing all child nodes
|
|
4
|
+
* through as matched. In HTML, a transparent element inherits the content model
|
|
5
|
+
* of its parent, so its children are validated against the parent's model instead.
|
|
6
|
+
*
|
|
7
|
+
* If the element is a component root (has no grandparent element), all children
|
|
8
|
+
* are treated as matched. Otherwise, validation is deferred to the parent's
|
|
9
|
+
* content model processing.
|
|
10
|
+
*
|
|
11
|
+
* @param childNodes - The child nodes to evaluate under the transparent model.
|
|
12
|
+
* @returns A result indicating all children are matched (validation deferred to parent).
|
|
13
|
+
*/
|
|
2
14
|
export declare function transparent(childNodes: readonly ChildNode[]): Result;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { cmLog } from './debug.js';
|
|
2
2
|
const transparentLog = cmLog.extend('transparent');
|
|
3
|
+
/**
|
|
4
|
+
* Handles the transparent content model pattern by passing all child nodes
|
|
5
|
+
* through as matched. In HTML, a transparent element inherits the content model
|
|
6
|
+
* of its parent, so its children are validated against the parent's model instead.
|
|
7
|
+
*
|
|
8
|
+
* If the element is a component root (has no grandparent element), all children
|
|
9
|
+
* are treated as matched. Otherwise, validation is deferred to the parent's
|
|
10
|
+
* content model processing.
|
|
11
|
+
*
|
|
12
|
+
* @param childNodes - The child nodes to evaluate under the transparent model.
|
|
13
|
+
* @returns A result indicating all children are matched (validation deferred to parent).
|
|
14
|
+
*/
|
|
3
15
|
export function transparent(
|
|
4
16
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
5
17
|
childNodes) {
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import type { Element as _Element, ChildNode as _ChildNode } from '@markuplint/ml-core';
|
|
2
2
|
import type { ContentModel, MLMLSpec } from '@markuplint/ml-spec';
|
|
3
3
|
import type { ReadonlyDeep } from 'type-fest';
|
|
4
|
+
/**
|
|
5
|
+
* An element node parameterized with the permitted-contents rule's TagRule and Options.
|
|
6
|
+
*/
|
|
4
7
|
export type Element = _Element<TagRule[], Options>;
|
|
8
|
+
/**
|
|
9
|
+
* A child node parameterized with the permitted-contents rule's TagRule and Options.
|
|
10
|
+
*/
|
|
5
11
|
export type ChildNode = _ChildNode<TagRule[], Options>;
|
|
12
|
+
/**
|
|
13
|
+
* A subset of the full ML spec containing only the fields needed
|
|
14
|
+
* for content model validation: citation references, global definitions,
|
|
15
|
+
* and per-element content model specifications.
|
|
16
|
+
*/
|
|
6
17
|
export type Specs = {
|
|
7
18
|
readonly cites: MLMLSpec['cites'];
|
|
8
19
|
readonly def: MLMLSpec['def'];
|
|
@@ -13,12 +24,24 @@ export type Specs = {
|
|
|
13
24
|
};
|
|
14
25
|
}[];
|
|
15
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* The final result of content model validation for a single child node,
|
|
29
|
+
* indicating whether the node is permitted, missing, or unexpected
|
|
30
|
+
* within its parent element's content model.
|
|
31
|
+
*/
|
|
16
32
|
export type ContentModelResult = {
|
|
17
33
|
type: MatchedReason | UnmatchedReason;
|
|
18
34
|
scope: ChildNode;
|
|
19
35
|
query: Result['query'];
|
|
20
36
|
hint: Result['hint'];
|
|
21
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* An intermediate result produced during content model pattern matching.
|
|
40
|
+
* Tracks which child nodes were matched, which were unmatched, and
|
|
41
|
+
* provides diagnostic hints about the nature of a mismatch.
|
|
42
|
+
*
|
|
43
|
+
* @template T - Additional result type strings beyond the standard matched/unmatched reasons.
|
|
44
|
+
*/
|
|
22
45
|
export type Result<T extends string = MatchedReason> = {
|
|
23
46
|
type: MatchedReason | UnmatchedReason | T;
|
|
24
47
|
matched: ChildNode[];
|
|
@@ -27,6 +50,11 @@ export type Result<T extends string = MatchedReason> = {
|
|
|
27
50
|
query: string;
|
|
28
51
|
hint: Hints;
|
|
29
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Diagnostic hints attached to a content model result, providing additional
|
|
55
|
+
* context for error reporting such as maximum allowed count, the offending
|
|
56
|
+
* node, or information about transparent model violations.
|
|
57
|
+
*/
|
|
30
58
|
export type Hints = {
|
|
31
59
|
max?: number;
|
|
32
60
|
not?: ChildNode;
|
|
@@ -36,21 +64,60 @@ export type Hints = {
|
|
|
36
64
|
need?: string;
|
|
37
65
|
};
|
|
38
66
|
};
|
|
67
|
+
/**
|
|
68
|
+
* Reasons indicating that a content model pattern successfully matched.
|
|
69
|
+
* `MATCHED` means one or more nodes matched; `MATCHED_ZERO` means the pattern
|
|
70
|
+
* matched vacuously (zero nodes consumed, but the pattern allows it).
|
|
71
|
+
*/
|
|
39
72
|
export type MatchedReason = 'MATCHED' | 'MATCHED_ZERO';
|
|
73
|
+
/**
|
|
74
|
+
* Reasons indicating that a content model pattern did not match.
|
|
75
|
+
* Includes cases where content is disallowed entirely, an unexpected node
|
|
76
|
+
* was found, a transparent model forbids the node, or a required node is missing.
|
|
77
|
+
*/
|
|
40
78
|
export type UnmatchedReason = 'NOTHING' | 'UNEXPECTED_EXTRA_NODE' | 'TRANSPARENT_MODEL_DISALLOWS' | MissingNodeReason;
|
|
79
|
+
/**
|
|
80
|
+
* Specific reasons for a missing node: either a required element is absent,
|
|
81
|
+
* or one-or-more occurrences are expected but none were found.
|
|
82
|
+
*/
|
|
41
83
|
export type MissingNodeReason = 'MISSING_NODE_REQUIRED' | 'MISSING_NODE_ONE_OR_MORE';
|
|
84
|
+
/**
|
|
85
|
+
* A regular-expression-like repeat sign used to describe the quantifier
|
|
86
|
+
* of a content model pattern (e.g., `?` for optional, `+` for one-or-more,
|
|
87
|
+
* `*` for zero-or-more, or `{min,max}` for a specific range).
|
|
88
|
+
*/
|
|
42
89
|
export type RepeatSign = '' | '?' | '+' | '*' | `{${number},${number}}`;
|
|
90
|
+
/**
|
|
91
|
+
* Describes a transparent content model element along with any additional
|
|
92
|
+
* CSS selector condition that must be satisfied for the transparency to apply.
|
|
93
|
+
*/
|
|
43
94
|
export type TransparentModel = {
|
|
44
95
|
el: Element;
|
|
45
96
|
additionalCondition: string;
|
|
46
97
|
};
|
|
98
|
+
/**
|
|
99
|
+
* A user-defined tag rule that associates an element tag name with
|
|
100
|
+
* its permitted content model definition, used to override or extend
|
|
101
|
+
* the built-in HTML spec content models.
|
|
102
|
+
*/
|
|
47
103
|
export type TagRule = {
|
|
48
104
|
readonly tag: string;
|
|
49
105
|
} & ReadonlyDeep<ContentModel>;
|
|
106
|
+
/**
|
|
107
|
+
* Options for the permitted-contents rule that control validation behavior.
|
|
108
|
+
*/
|
|
50
109
|
export type Options = {
|
|
110
|
+
/**
|
|
111
|
+
* When true, skips reporting missing-node errors on elements that
|
|
112
|
+
* have mutable children (e.g., elements whose children may be
|
|
113
|
+
* dynamically injected by a framework or template engine).
|
|
114
|
+
*/
|
|
51
115
|
readonly ignoreHasMutableChildren: boolean;
|
|
52
116
|
/**
|
|
53
117
|
* @experimental
|
|
118
|
+
* When true, evaluates conditional child node branches (e.g., from
|
|
119
|
+
* template directives like `v-if`) to validate each possible branch
|
|
120
|
+
* against the content model.
|
|
54
121
|
*/
|
|
55
122
|
readonly evaluateConditionalChildNodes: boolean;
|
|
56
123
|
};
|
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import type { ChildNode, Hints, MissingNodeReason, RepeatSign, Specs } from './types.js';
|
|
2
2
|
import type { PermittedContentPattern, PermittedContentChoice, PermittedContentOneOrMore, PermittedContentOptional, PermittedContentRequire, PermittedContentTransparent, PermittedContentZeroOrMore, Model } from '@markuplint/ml-spec';
|
|
3
3
|
import type { ReadonlyDeep } from 'type-fest';
|
|
4
|
+
/**
|
|
5
|
+
* Determines whether a given value is a terminal model (a selector string or an array
|
|
6
|
+
* of selector strings) rather than a nested array of content model patterns.
|
|
7
|
+
* Distinguishes between `Model` (leaf-level selectors) and `PermittedContentPattern[]`
|
|
8
|
+
* (structural pattern arrays that require further recursive evaluation).
|
|
9
|
+
*
|
|
10
|
+
* @param model - The value to check, either a terminal model or a nested pattern array.
|
|
11
|
+
* @returns True if the value is a terminal model (string or string array), false if it is a pattern array.
|
|
12
|
+
*/
|
|
4
13
|
export declare function isModel(model: ReadonlyDeep<Model | PermittedContentPattern[]>): model is ReadonlyDeep<Model>;
|
|
14
|
+
/**
|
|
15
|
+
* Tests whether a child node matches a CSS selector string using the markuplint
|
|
16
|
+
* selector engine. Returns whether the node matched and, if not, the deepest
|
|
17
|
+
* unmatched descendant node for diagnostic purposes.
|
|
18
|
+
*
|
|
19
|
+
* @param selector - The CSS selector string to test against.
|
|
20
|
+
* @param node - The child node to test.
|
|
21
|
+
* @param specs - The spec data passed to the selector engine for attribute resolution.
|
|
22
|
+
* @returns An object with `matched: true` if the node matches, or `matched: false` with an optional `not` node.
|
|
23
|
+
*/
|
|
5
24
|
export declare function matches(selector: string, node: ChildNode, specs: Specs): {
|
|
6
25
|
matched: boolean;
|
|
7
26
|
not?: undefined;
|
|
@@ -9,19 +28,78 @@ export declare function matches(selector: string, node: ChildNode, specs: Specs)
|
|
|
9
28
|
matched: boolean;
|
|
10
29
|
not: ChildNode | undefined;
|
|
11
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Type guard that checks whether a content model pattern is a "require" pattern,
|
|
33
|
+
* indicating one or more required occurrences of a specific element or model.
|
|
34
|
+
*
|
|
35
|
+
* @param content - The content model pattern to check.
|
|
36
|
+
* @returns True if the pattern has a `require` property.
|
|
37
|
+
*/
|
|
12
38
|
export declare function isRequire(content: ReadonlyDeep<PermittedContentPattern>): content is ReadonlyDeep<PermittedContentRequire>;
|
|
39
|
+
/**
|
|
40
|
+
* Type guard that checks whether a content model pattern is an "optional" pattern,
|
|
41
|
+
* indicating zero or one occurrences of a specific element or model.
|
|
42
|
+
*
|
|
43
|
+
* @param content - The content model pattern to check.
|
|
44
|
+
* @returns True if the pattern has an `optional` property.
|
|
45
|
+
*/
|
|
13
46
|
export declare function isOptional(content: ReadonlyDeep<PermittedContentPattern>): content is ReadonlyDeep<PermittedContentOptional>;
|
|
47
|
+
/**
|
|
48
|
+
* Type guard that checks whether a content model pattern is a "oneOrMore" pattern,
|
|
49
|
+
* indicating one or more occurrences of a specific element or model.
|
|
50
|
+
*
|
|
51
|
+
* @param content - The content model pattern to check.
|
|
52
|
+
* @returns True if the pattern has a `oneOrMore` property.
|
|
53
|
+
*/
|
|
14
54
|
export declare function isOneOrMore(content: ReadonlyDeep<PermittedContentPattern>): content is ReadonlyDeep<PermittedContentOneOrMore>;
|
|
55
|
+
/**
|
|
56
|
+
* Type guard that checks whether a content model pattern is a "zeroOrMore" pattern,
|
|
57
|
+
* indicating zero or more occurrences of a specific element or model.
|
|
58
|
+
*
|
|
59
|
+
* @param content - The content model pattern to check.
|
|
60
|
+
* @returns True if the pattern has a `zeroOrMore` property.
|
|
61
|
+
*/
|
|
15
62
|
export declare function isZeroOrMore(content: ReadonlyDeep<PermittedContentPattern>): content is ReadonlyDeep<PermittedContentZeroOrMore>;
|
|
63
|
+
/**
|
|
64
|
+
* Type guard that checks whether a content model pattern is a "choice" pattern,
|
|
65
|
+
* representing an alternation between multiple possible content model branches.
|
|
66
|
+
*
|
|
67
|
+
* @param content - The content model pattern to check.
|
|
68
|
+
* @returns True if the pattern has a `choice` property.
|
|
69
|
+
*/
|
|
16
70
|
export declare function isChoice(content: ReadonlyDeep<PermittedContentPattern>): content is ReadonlyDeep<PermittedContentChoice>;
|
|
71
|
+
/**
|
|
72
|
+
* Type guard that checks whether a content model pattern is a "transparent" pattern,
|
|
73
|
+
* indicating the element inherits its parent's content model.
|
|
74
|
+
*
|
|
75
|
+
* @param content - The content model pattern to check.
|
|
76
|
+
* @returns True if the pattern has a `transparent` property.
|
|
77
|
+
*/
|
|
17
78
|
export declare function isTransparent(content: ReadonlyDeep<PermittedContentPattern>): content is ReadonlyDeep<PermittedContentTransparent>;
|
|
79
|
+
/**
|
|
80
|
+
* Normalizes a quantified content model pattern (require, optional, oneOrMore, or zeroOrMore)
|
|
81
|
+
* into a uniform representation with the inner model, minimum count, maximum count,
|
|
82
|
+
* a regex-like repeat sign for debug display, and the appropriate missing-node error type.
|
|
83
|
+
*
|
|
84
|
+
* @param pattern - A quantified content model pattern to normalize.
|
|
85
|
+
* @returns An object with `model`, `min`, `max`, `repeat` sign, and optional `missingType`.
|
|
86
|
+
*/
|
|
18
87
|
export declare function normalizeModel(pattern: ReadonlyDeep<PermittedContentRequire> | ReadonlyDeep<PermittedContentOptional> | ReadonlyDeep<PermittedContentOneOrMore> | ReadonlyDeep<PermittedContentZeroOrMore>): {
|
|
19
|
-
model: ReadonlyDeep<PermittedContentPattern[]
|
|
88
|
+
model: ReadonlyDeep<Model | PermittedContentPattern[]>;
|
|
20
89
|
min: number;
|
|
21
90
|
max: number;
|
|
22
91
|
repeat: RepeatSign;
|
|
23
92
|
missingType: MissingNodeReason | undefined;
|
|
24
93
|
};
|
|
94
|
+
/**
|
|
95
|
+
* Merges two Hints objects, combining their properties and selecting the
|
|
96
|
+
* `missing` hint with the higher `barelyMatchedElements` count (i.e., the
|
|
97
|
+
* one closest to a successful match) for the most useful error diagnostics.
|
|
98
|
+
*
|
|
99
|
+
* @param a - The first hints object.
|
|
100
|
+
* @param b - The second hints object.
|
|
101
|
+
* @returns A merged hints object with undefined properties removed.
|
|
102
|
+
*/
|
|
25
103
|
export declare function mergeHints(a: Readonly<Hints>, b: Readonly<Hints>): Partial<{
|
|
26
104
|
missing: Partial<{
|
|
27
105
|
barelyMatchedElements?: number;
|
|
@@ -31,20 +109,102 @@ export declare function mergeHints(a: Readonly<Hints>, b: Readonly<Hints>): Part
|
|
|
31
109
|
not?: ChildNode;
|
|
32
110
|
transparent?: import("./types.js").Element;
|
|
33
111
|
}>;
|
|
112
|
+
/**
|
|
113
|
+
* Creates a shallow copy of an object with all `undefined` values removed.
|
|
114
|
+
* Used to produce clean hint objects for result reporting without
|
|
115
|
+
* extraneous undefined properties.
|
|
116
|
+
*
|
|
117
|
+
* @template T - The object type.
|
|
118
|
+
* @param object - The source object to clean.
|
|
119
|
+
* @returns A new object containing only the defined properties of the input.
|
|
120
|
+
*/
|
|
34
121
|
export declare function cleanObject<T extends object>(object: T): Partial<T>;
|
|
122
|
+
/**
|
|
123
|
+
* Tracks matched and unmatched child nodes during content model validation.
|
|
124
|
+
* Provides operations for adding matched nodes, backtracking to a locked state,
|
|
125
|
+
* capping matches at a maximum count, and generating colored debug output.
|
|
126
|
+
*
|
|
127
|
+
* The collection maintains an ordered set of original nodes and partitions them
|
|
128
|
+
* into matched and unmatched sets as the validation algorithm progresses.
|
|
129
|
+
*/
|
|
35
130
|
export declare class Collection {
|
|
36
131
|
#private;
|
|
132
|
+
/**
|
|
133
|
+
* Creates a new Collection from the given child nodes.
|
|
134
|
+
*
|
|
135
|
+
* @param origin - The initial list of child nodes to track.
|
|
136
|
+
*/
|
|
37
137
|
constructor(origin: readonly ChildNode[]);
|
|
138
|
+
/**
|
|
139
|
+
* Returns a copy of the currently matched nodes in insertion order.
|
|
140
|
+
*/
|
|
38
141
|
get matched(): ChildNode[];
|
|
142
|
+
/**
|
|
143
|
+
* Returns the number of currently matched nodes.
|
|
144
|
+
*/
|
|
39
145
|
get matchedCount(): number;
|
|
146
|
+
/**
|
|
147
|
+
* Returns a copy of all original nodes in their original order.
|
|
148
|
+
*/
|
|
40
149
|
get nodes(): ChildNode[];
|
|
150
|
+
/**
|
|
151
|
+
* Returns the nodes that have not yet been matched, preserving original order.
|
|
152
|
+
*/
|
|
41
153
|
get unmatched(): ChildNode[];
|
|
154
|
+
/**
|
|
155
|
+
* Adds nodes to the matched set. All nodes must belong to the original
|
|
156
|
+
* collection; external nodes will cause a ReferenceError.
|
|
157
|
+
*
|
|
158
|
+
* @param nodes - The child nodes to mark as matched.
|
|
159
|
+
* @returns True if the matched set grew (new nodes were added), false otherwise.
|
|
160
|
+
*/
|
|
42
161
|
addMatched(nodes: ChildNode[]): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Reverts the matched set to the last locked state, discarding
|
|
164
|
+
* any matches added since the last `lock()` call. Used for backtracking
|
|
165
|
+
* when a pattern match attempt fails after a zero-match.
|
|
166
|
+
*/
|
|
43
167
|
back(): void;
|
|
168
|
+
/**
|
|
169
|
+
* Saves the current matched set as a checkpoint that `back()` can
|
|
170
|
+
* revert to. Called after a successful backtrack recovery to preserve
|
|
171
|
+
* the known-good state.
|
|
172
|
+
*/
|
|
44
173
|
lock(): void;
|
|
174
|
+
/**
|
|
175
|
+
* Trims the matched set to at most `max` entries by removing
|
|
176
|
+
* the most recently added nodes beyond the limit. Used when the
|
|
177
|
+
* maximum occurrence count for a pattern is exceeded.
|
|
178
|
+
*
|
|
179
|
+
* @param max - The maximum number of matched nodes to retain.
|
|
180
|
+
*/
|
|
45
181
|
max(max: number): void;
|
|
182
|
+
/**
|
|
183
|
+
* Returns a colored string representation of all nodes for debug logging.
|
|
184
|
+
* Matched nodes are shown in green, locked nodes in bold green, unmatched
|
|
185
|
+
* extra nodes in red (when highlighted), and transparent-mode nodes in
|
|
186
|
+
* blue/cyan/magenta variants.
|
|
187
|
+
*
|
|
188
|
+
* @param highlightExtraNodes - When true, unmatched nodes are highlighted in red/magenta.
|
|
189
|
+
* @returns A formatted string like `[ <div>, <span>, <p> ]` with ANSI colors.
|
|
190
|
+
*/
|
|
46
191
|
toString(highlightExtraNodes?: boolean): string;
|
|
47
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Error class representing an unsupported content model feature.
|
|
195
|
+
* Thrown when the validation engine encounters a pattern type or
|
|
196
|
+
* configuration that is not yet implemented.
|
|
197
|
+
*/
|
|
48
198
|
export declare class UnsupportedError extends Error {
|
|
49
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Formats a content model (terminal model or pattern array) and its repeat sign
|
|
202
|
+
* into a regex-like string for debug logging output. Terminal selectors are
|
|
203
|
+
* rendered as `<selector>`, arrays of selectors as `(<s1>|<s2>)`, and
|
|
204
|
+
* nested patterns are recursively formatted.
|
|
205
|
+
*
|
|
206
|
+
* @param model - The model or pattern array to format.
|
|
207
|
+
* @param repeat - The quantifier sign to append (e.g., `+`, `*`, `?`, or `{m,n}`).
|
|
208
|
+
* @returns A human-readable regex-like string representation of the model.
|
|
209
|
+
*/
|
|
50
210
|
export declare function modelLog(model: ReadonlyDeep<Model | PermittedContentPattern[]>, repeat: RepeatSign): string;
|