@markuplint/ml-core 5.4.0 → 5.6.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 (45) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/lib/ml-core.js +3 -0
  3. package/lib/ml-dom/helper/accname.d.ts +35 -0
  4. package/lib/ml-dom/helper/accname.js +69 -17
  5. package/lib/ml-dom/helper/debug.js +1 -1
  6. package/lib/ml-dom/helper/literal-values.d.ts +102 -0
  7. package/lib/ml-dom/helper/literal-values.js +193 -0
  8. package/lib/ml-dom/helper/pretended-attrs.d.ts +16 -0
  9. package/lib/ml-dom/helper/pretended-attrs.js +21 -0
  10. package/lib/ml-dom/helper/slot-assignment.d.ts +48 -0
  11. package/lib/ml-dom/helper/slot-assignment.js +292 -0
  12. package/lib/ml-dom/helper/tree-scope.d.ts +130 -0
  13. package/lib/ml-dom/helper/tree-scope.js +341 -0
  14. package/lib/ml-dom/helper/walkers.d.ts +15 -0
  15. package/lib/ml-dom/helper/walkers.js +34 -0
  16. package/lib/ml-dom/index.d.ts +4 -0
  17. package/lib/ml-dom/index.js +2 -0
  18. package/lib/ml-dom/node/attr.d.ts +77 -10
  19. package/lib/ml-dom/node/attr.js +209 -20
  20. package/lib/ml-dom/node/block.d.ts +15 -6
  21. package/lib/ml-dom/node/block.js +17 -8
  22. package/lib/ml-dom/node/document-fragment.d.ts +18 -6
  23. package/lib/ml-dom/node/document-fragment.js +19 -7
  24. package/lib/ml-dom/node/document.d.ts +36 -7
  25. package/lib/ml-dom/node/document.js +60 -17
  26. package/lib/ml-dom/node/dom-token-list.js +28 -3
  27. package/lib/ml-dom/node/element.d.ts +148 -24
  28. package/lib/ml-dom/node/element.js +258 -48
  29. package/lib/ml-dom/node/named-node-map.js +2 -1
  30. package/lib/ml-dom/node/node-list.js +2 -3
  31. package/lib/ml-dom/node/node.d.ts +55 -10
  32. package/lib/ml-dom/node/node.js +98 -13
  33. package/lib/ml-dom/node/parent-node.d.ts +39 -8
  34. package/lib/ml-dom/node/parent-node.js +79 -12
  35. package/lib/ml-dom/node/shadow-root.d.ts +162 -0
  36. package/lib/ml-dom/node/shadow-root.js +219 -0
  37. package/lib/ml-dom/node/text.d.ts +12 -3
  38. package/lib/ml-dom/node/text.js +14 -3
  39. package/lib/ml-rule/ml-rule.js +4 -1
  40. package/lib/test/index.js +3 -0
  41. package/lib/utils/index.d.ts +2 -0
  42. package/lib/utils/index.js +1 -0
  43. package/lib/utils/search-node-at-location.d.ts +39 -0
  44. package/lib/utils/search-node-at-location.js +53 -0
  45. package/package.json +12 -15
@@ -1,12 +1,13 @@
1
1
  import { exchangeValueOnRule, mergeRule } from '@markuplint/ml-config';
2
- import { schemaToSpec, getComputedRole, mayBeFocusable, getComputedAriaProps, isExposed, getSpecByTagName, ARIA_RECOMMENDED_VERSION, } from '@markuplint/ml-spec';
2
+ import { schemaToSpec, getComputedRole, mayBeFocusable, getComputedAriaProps, isExposed, isShadowRoot, getSpecByTagName, ARIA_RECOMMENDED_VERSION, } from '@markuplint/ml-spec';
3
3
  import { ConfigParserError, isComponentName } from '@markuplint/parser-utils';
4
4
  import { InvalidSelectorError } from '@markuplint/selector';
5
5
  import { log as coreLog } from '../../debug.js';
6
+ import { searchNodeAtLocation } from '../../utils/search-node-at-location.js';
6
7
  import { createNode } from '../helper/create-node.js';
7
8
  import { nodeListToDebugMaps } from '../helper/debug.js';
8
9
  import { sequentialWalker, syncWalk } from '../helper/walkers.js';
9
- import { nodeListToHTMLCollection } from './node-list.js';
10
+ import { nodeListToHTMLCollection, toHTMLCollection } from './node-list.js';
10
11
  import { MLParentNode } from './parent-node.js';
11
12
  import { RuleMapper } from './rule-mapper.js';
12
13
  import { UnexpectedCallError } from '@markuplint/shared';
@@ -36,6 +37,23 @@ export class MLDocument extends MLParentNode {
36
37
  * @default false
37
38
  */
38
39
  booleanish;
40
+ /**
41
+ * The language of the code that an attribute value is written in when it is written as code
42
+ * (`MLParser#attrExpressionLanguage`). Absent when the parser does not say; then no attribute
43
+ * value of the document is read as a literal (a pretender's attribute is, whatever it says).
44
+ */
45
+ attrExpressionLanguage;
46
+ /**
47
+ * How the framework of the parser renders a literal in an attribute value, where it differs from
48
+ * the default (`MLParser#literalValues`). What the spec says (`MLMLSpec#literalValues`) wins over
49
+ * this.
50
+ */
51
+ literalValues;
52
+ /**
53
+ * What the `slot` element is in the language of the document (`MLParser#slotElement`): the HTML
54
+ * element, or the placeholder of a framework's component, whose slot assignment is not computed.
55
+ */
56
+ slotElement;
39
57
  /**
40
58
  * The rule currently being evaluated during a lint pass.
41
59
  * Set by the linting engine before rule evaluation begins and used by nodes
@@ -145,6 +163,9 @@ export class MLDocument extends MLParentNode {
145
163
  this.isFragment = ast.isFragment;
146
164
  this.specs = schemaToSpec(schemas);
147
165
  this.booleanish = options?.booleanish ?? false;
166
+ this.attrExpressionLanguage = options?.attrExpressionLanguage;
167
+ this.literalValues = options?.literalValues;
168
+ this.slotElement = options?.slotElement ?? 'html';
148
169
  this.endTag = options?.endTag ?? 'omittable';
149
170
  this.#filename = options?.filename;
150
171
  this.tagNameCaseSensitive = options?.tagNameCaseSensitive ?? false;
@@ -165,8 +186,10 @@ export class MLDocument extends MLParentNode {
165
186
  return createNode(astNode, this);
166
187
  })
167
188
  .filter((n) => !!n));
168
- this.#pretending(options?.pretenders);
189
+ // A selector of the configuration is matched here, by a pretender and by a rule, so an
190
+ // invalid one is the fault of the configuration in both.
169
191
  try {
192
+ this.#pretending(options?.pretenders);
170
193
  this.#ruleMapping(ruleset);
171
194
  }
172
195
  catch (error) {
@@ -2119,7 +2142,16 @@ export class MLDocument extends MLParentNode {
2119
2142
  const focusable = mayBeFocusable(node, node.ownerMLDocument.specs);
2120
2143
  const nameRequired = role.role?.accessibleNameRequired ?? false;
2121
2144
  const nameProhibited = role.role?.accessibleNameProhibited ?? false;
2122
- const hasSlot = !!node.querySelector('slot');
2145
+ // A slot whose assignment is known is read by `getAccessibleName` above. The slot of a shadow root is in
2146
+ // a tree of its own, so every tree is searched, except the content of an ordinary `template` element,
2147
+ // which is not rendered where it is written.
2148
+ const hasSlot = node.deepQuerySelectorAll('slot').some(slot => {
2149
+ if (slot.getAssignedNodes() !== null) {
2150
+ return false;
2151
+ }
2152
+ const root = slot.getRootNode();
2153
+ return isShadowRoot(root) || !root.is(root.DOCUMENT_FRAGMENT_NODE);
2154
+ });
2123
2155
  aria.role = role.role?.name;
2124
2156
  aria.nameRequired = nameRequired;
2125
2157
  aria.nameProhibited = nameProhibited;
@@ -2154,19 +2186,29 @@ export class MLDocument extends MLParentNode {
2154
2186
  throw new UnexpectedCallError('Not supported "getAnimations" method');
2155
2187
  }
2156
2188
  /**
2189
+ * The first element of the tree of the document whose id is `elementId`, with the character
2190
+ * references in the markup resolved: not in the content of an HTML `template` element, which is a
2191
+ * tree of its own.
2192
+ *
2157
2193
  * @implements DOM API: `Document`
2194
+ * @see https://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid
2158
2195
  */
2159
2196
  getElementById(elementId) {
2160
- return this.querySelector(`#${elementId}`);
2197
+ return this._getElementById(elementId);
2161
2198
  }
2162
2199
  /**
2163
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
2164
- *
2165
- * @unsupported
2166
2200
  * @implements DOM API: `Document`
2201
+ * @see https://dom.spec.whatwg.org/#concept-getelementsbyclassname
2167
2202
  */
2168
2203
  getElementsByClassName(classNames) {
2169
- return nodeListToHTMLCollection(this.querySelectorAll(classNames));
2204
+ const names = classNames.split(/[\t\n\f\r ]+/).filter(Boolean);
2205
+ return toHTMLCollection(names.length === 0
2206
+ ? []
2207
+ : this._descendantsToArray(node => {
2208
+ if (node.is(node.ELEMENT_NODE) && names.every(name => node.classList.contains(name))) {
2209
+ return node;
2210
+ }
2211
+ }));
2170
2212
  }
2171
2213
  /**
2172
2214
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
@@ -2178,10 +2220,12 @@ export class MLDocument extends MLParentNode {
2178
2220
  throw new UnexpectedCallError('Not supported "getElementsByName" method');
2179
2221
  }
2180
2222
  /**
2181
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
2223
+ * The elements of the tree of the document that a type selector of that name matches, so that a
2224
+ * name is compared as a selector compares it in the language of the document (the case, and a
2225
+ * component that a pretender stands for), not as the DOM compares a tag name.
2182
2226
  *
2183
- * @unsupported
2184
2227
  * @implements DOM API: `Document`
2228
+ * @see https://dom.spec.whatwg.org/#concept-getelementsbytagname
2185
2229
  */
2186
2230
  getElementsByTagName(qualifiedName) {
2187
2231
  return nodeListToHTMLCollection(this.querySelectorAll(qualifiedName));
@@ -2312,18 +2356,17 @@ export class MLDocument extends MLParentNode {
2312
2356
  /**
2313
2357
  * Searches for a node at the given source location (line and column).
2314
2358
  *
2359
+ * The node is the innermost one whose source range, from its start, included,
2360
+ * to its end, excluded, holds the position; a position in an end tag is its
2361
+ * element. The rule is `searchNodeAtLocation`'s.
2362
+ *
2315
2363
  * @implements `@markuplint/ml-core` API: `MLDocument`
2316
2364
  * @param line - The 1-based line number to search at
2317
2365
  * @param col - The 1-based column number to search at
2318
2366
  * @returns The node at the given location, or null if not found
2319
2367
  */
2320
2368
  searchNodeByLocation(line, col) {
2321
- for (const node of this.nodeList) {
2322
- if (node.startLine <= line && line <= node.endLine && node.startCol <= col && col <= node.endCol) {
2323
- return node;
2324
- }
2325
- }
2326
- return null;
2369
+ return searchNodeAtLocation(this.nodeList, line, col);
2327
2370
  }
2328
2371
  /**
2329
2372
  * Sets the currently active rule for this document. Called by the linting engine
@@ -114,14 +114,39 @@ export class MLDomTokenList extends Array {
114
114
  if (startOffset === -1) {
115
115
  continue;
116
116
  }
117
+ // The value is what code results in (`{"a b"}`), not the text of the source: an offset in it is the offset in
118
+ // the source only for a string of the same characters in quotes, where the quote is one character before the
119
+ // value. For an escape, a wrapper or another notation, the token is reported at the start of the value.
120
+ const base = ownerAttr.valueNode;
121
+ let shift = 0;
122
+ if (ownerAttr.isExpressionValue && ownerAttr.valueNode) {
123
+ const raw = ownerAttr.valueNode.raw;
124
+ const quote = raw[0];
125
+ const isPlainString = raw.length >= 2 &&
126
+ (quote === '"' || quote === "'" || quote === '`') &&
127
+ raw.endsWith(quote) &&
128
+ raw.slice(1, -1) === this.#origin;
129
+ if (!isPlainString) {
130
+ return {
131
+ raw: token,
132
+ startOffset: ownerAttr.valueNode.startOffset,
133
+ startLine: ownerAttr.valueNode.startLine,
134
+ startCol: ownerAttr.valueNode.startCol,
135
+ rule: ownerAttr.rule,
136
+ _searchedIndex: startOffset,
137
+ };
138
+ }
139
+ shift = 1;
140
+ }
117
141
  const position = getPosition(this.#origin, startOffset);
118
142
  const startLine = position.line;
119
143
  const startCol = position.column;
120
144
  return {
121
145
  raw: token,
122
- startOffset: (ownerAttr.valueNode?.startOffset ?? 0) + startOffset,
123
- startLine: (ownerAttr.valueNode?.startLine ?? 0) + (startLine - 1),
124
- startCol: (ownerAttr.valueNode?.startCol ?? 0) + (startCol - 1),
146
+ startOffset: (base?.startOffset ?? 0) + shift + startOffset,
147
+ startLine: (base?.startLine ?? 0) + (startLine - 1),
148
+ // What starts the value (the quote) is before a token on the first line only: the column on a later line is the column in the line
149
+ startCol: startLine > 1 ? startCol : (base?.startCol ?? 0) + shift + (startCol - 1),
125
150
  rule: ownerAttr.rule,
126
151
  _searchedIndex: startOffset,
127
152
  };
@@ -1,3 +1,5 @@
1
+ import type { DeclarativeShadowRootAttachment } from '../helper/tree-scope.js';
2
+ import type { MLChildNode } from './child-node.js';
1
3
  import type { MLDocument } from './document.js';
2
4
  import type { MLNamedNodeMap } from './named-node-map.js';
3
5
  import type { MLNode } from './node.js';
@@ -8,9 +10,11 @@ import type { PlainData, Pretender, RegexSelector, RuleConfigValue, RuleInfo } f
8
10
  import type { AccnameSource, AccnameVisit, ARIAVersion } from '@markuplint/ml-spec';
9
11
  import type { SelectorMatches } from '@markuplint/selector';
10
12
  import { MLAttr } from './attr.js';
13
+ import { MLDocumentFragment } from './document-fragment.js';
11
14
  import { MLDomTokenList } from './dom-token-list.js';
12
15
  import { MLElementCloseTag } from './element-close-tag.js';
13
16
  import { MLParentNode } from './parent-node.js';
17
+ import { MLShadowRoot } from './shadow-root.js';
14
18
  /**
15
19
  * Represents a DOM Element node wrapper in the markuplint DOM tree.
16
20
  * Provides access to element attributes, tag names, namespace, ARIA properties,
@@ -601,9 +605,10 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
601
605
  */
602
606
  get ariaValueText(): string | null;
603
607
  /**
604
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
608
+ * The slot of an open declarative shadow root that this element is assigned to, or `null` when no
609
+ * slot takes it, the root is closed (the DOM does not expose it), or the assignment is not known
610
+ * (see {@link MLElement.getFlatTreeSlot}).
605
611
  *
606
- * @unsupported
607
612
  * @implements DOM API: `Element`
608
613
  * @see https://dom.spec.whatwg.org/#dom-slotable-assignedslot
609
614
  */
@@ -664,7 +669,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
664
669
  *
665
670
  * @unsupported
666
671
  * @implements DOM API: `Element`
667
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-clientheight-1
672
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-clientheight
668
673
  */
669
674
  get clientHeight(): number;
670
675
  /**
@@ -672,7 +677,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
672
677
  *
673
678
  * @unsupported
674
679
  * @implements DOM API: `Element`
675
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-clientleft-1
680
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-clientleft
676
681
  */
677
682
  get clientLeft(): number;
678
683
  /**
@@ -680,7 +685,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
680
685
  *
681
686
  * @unsupported
682
687
  * @implements DOM API: `Element`
683
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-clienttop-1
688
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-clienttop
684
689
  */
685
690
  get clientTop(): number;
686
691
  /**
@@ -688,7 +693,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
688
693
  *
689
694
  * @unsupported
690
695
  * @implements DOM API: `Element`
691
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-clientwidth-1
696
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-clientwidth
692
697
  */
693
698
  get clientWidth(): number;
694
699
  /**
@@ -770,7 +775,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
770
775
  * @deprecated
771
776
  * @unsupported
772
777
  * @implements DOM API: `Element`
773
- * @see https://html.spec.whatwg.org/multipage/interaction.html#dom-inert
778
+ * @see https://html.spec.whatwg.org/multipage/dom.html#dom-inert
774
779
  */
775
780
  get inert(): boolean;
776
781
  /**
@@ -778,7 +783,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
778
783
  *
779
784
  * @unsupported
780
785
  * @implements DOM API: `Element`
781
- * @see https://w3c.github.io/DOM-Parsing/#dom-innerhtml-innerhtml
786
+ * @see https://w3c.github.io/DOM-Parsing/#dom-innerhtml
782
787
  */
783
788
  get innerHTML(): string;
784
789
  /**
@@ -1756,7 +1761,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1756
1761
  *
1757
1762
  * @unsupported
1758
1763
  * @implements DOM API: `Element`
1759
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-scrollheight-1
1764
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-scrollheight
1760
1765
  */
1761
1766
  get scrollHeight(): number;
1762
1767
  /**
@@ -1764,7 +1769,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1764
1769
  *
1765
1770
  * @unsupported
1766
1771
  * @implements DOM API: `Element`
1767
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-scrollleft-1
1772
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-scrollleft
1768
1773
  */
1769
1774
  get scrollLeft(): number;
1770
1775
  /**
@@ -1772,7 +1777,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1772
1777
  *
1773
1778
  * @unsupported
1774
1779
  * @implements DOM API: `Element`
1775
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-scrolltop-1
1780
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-scrolltop
1776
1781
  */
1777
1782
  get scrollTop(): number;
1778
1783
  /**
@@ -1780,17 +1785,73 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1780
1785
  *
1781
1786
  * @unsupported
1782
1787
  * @implements DOM API: `Element`
1783
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-scrollwidth-1
1788
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-scrollwidth
1784
1789
  */
1785
1790
  get scrollWidth(): number;
1786
1791
  /**
1787
- * **IT THROWS AN ERROR WHEN CALLING THIS.**
1792
+ * The shadow root that a `template` element with `shadowrootmode="open"` declares on this element:
1793
+ * `null` for a `closed` one, which the DOM does not expose, and when there is none. See
1794
+ * {@link MLElement.declarativeShadowRoot} for one of either mode.
1788
1795
  *
1789
- * @unsupported
1790
1796
  * @implements DOM API: `Element`
1791
1797
  * @see https://dom.spec.whatwg.org/#ref-for-dom-element-shadowroot%E2%91%A0
1792
1798
  */
1793
- get shadowRoot(): ShadowRoot | null;
1799
+ get shadowRoot(): MLShadowRoot<T, O> | null;
1800
+ /**
1801
+ * Whether this element is an HTML `template` element, which holds its children in {@link MLElement.content},
1802
+ * a tree of its own. A `template` of a framework that puts the children in the element itself
1803
+ * (`templateContent: 'in-place'` in the spec: React, Vue), a fragment, and a `template` with a
1804
+ * directive of a template engine are not.
1805
+ *
1806
+ * The getters about trees (this one, {@link MLElement.declarativeShadowRootAttachment},
1807
+ * {@link MLElement.content}, `getRootNode()` and the id lookups) keep what they first return: they
1808
+ * depend on the pretenders, the spec and the whole syntax tree, which are all in place once the
1809
+ * document is built, and the document does not change after that.
1810
+ *
1811
+ * @implements `@markuplint/ml-core` API: `MLElement`
1812
+ * @see https://html.spec.whatwg.org/multipage/scripting.html#the-template-element
1813
+ */
1814
+ get isHTMLTemplateElement(): boolean;
1815
+ /**
1816
+ * Whether this element is in no tree: an HTML `template` element that a declarative shadow root is
1817
+ * attached to, or that may have one (see {@link DeclarativeShadowRootAttachment}). The parser inserts
1818
+ * such an element into no tree, so it has no parent in a tree, is its own root, and is found by no
1819
+ * query of a tree. Unknown is treated as in no tree, as markuplint does not count what it cannot tell.
1820
+ *
1821
+ * @implements `@markuplint/ml-core` API: `MLElement`
1822
+ */
1823
+ get isInNoTree(): boolean;
1824
+ /**
1825
+ * The mode that the `shadowrootmode` attribute of an HTML `template` element asks for. `null` when the
1826
+ * element is not one, the attribute is missing or invalid, or its value is dynamic.
1827
+ *
1828
+ * @implements `@markuplint/ml-core` API: `MLElement`
1829
+ */
1830
+ get declarativeShadowRootMode(): 'open' | 'closed' | null;
1831
+ /**
1832
+ * Whether the HTML parser attaches a declarative shadow root to the parent of this `template`
1833
+ * element (see {@link DeclarativeShadowRootAttachment}).
1834
+ *
1835
+ * @implements `@markuplint/ml-core` API: `MLElement`
1836
+ */
1837
+ get declarativeShadowRootAttachment(): DeclarativeShadowRootAttachment;
1838
+ /**
1839
+ * The content of an HTML `template` element: a document fragment that is a tree of its own, holding
1840
+ * the same nodes as the children of the element. When a declarative shadow root is attached to the
1841
+ * parent of the `template`, it is the shadow root. `null` for an element that is not an HTML
1842
+ * `template` element.
1843
+ *
1844
+ * @implements DOM API: `HTMLTemplateElement`
1845
+ * @see https://html.spec.whatwg.org/multipage/scripting.html#dom-template-content
1846
+ */
1847
+ get content(): MLDocumentFragment<T, O> | null;
1848
+ /**
1849
+ * The shadow root that a `template` element declares on this element, whatever its mode.
1850
+ *
1851
+ * @implements `@markuplint/ml-core` API: `MLElement`
1852
+ * @returns The shadow root, or `null` when none is attached to this element
1853
+ */
1854
+ get declarativeShadowRoot(): MLShadowRoot<T, O> | null;
1794
1855
  /**
1795
1856
  * @implements DOM API: `Element`
1796
1857
  * @see https://dom.spec.whatwg.org/#ref-for-dom-element-slot%E2%91%A0
@@ -1879,9 +1940,35 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
1879
1940
  */
1880
1941
  animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation;
1881
1942
  /**
1943
+ * The nodes this `slot` places, in tree order, or with `flatten` what it renders in the flat tree. It
1944
+ * is empty when the assignment is not known; use {@link MLElement.getAssignedNodes} to tell the two apart.
1945
+ *
1946
+ * @implements DOM API: `HTMLSlotElement`
1882
1947
  * @see https://html.spec.whatwg.org/multipage/scripting.html#dom-slot-assignednodes
1883
1948
  */
1884
- assignedNodes(): never[];
1949
+ assignedNodes(options?: AssignedNodesOptions): MLChildNode<T, O>[];
1950
+ /**
1951
+ * The nodes this `slot` places, by the named slot assignment of the declarative shadow root it is in.
1952
+ * A slot that takes none has `[]`, and renders its own children. `null` when the assignment is not
1953
+ * known; what makes it so is in the module comment of `helper/slot-assignment.ts`.
1954
+ *
1955
+ * @implements `@markuplint/ml-core` API: `MLElement`
1956
+ * @see https://dom.spec.whatwg.org/#find-slotables
1957
+ */
1958
+ getAssignedNodes(): readonly MLChildNode<T, O>[] | null;
1959
+ /**
1960
+ * The slot that places this element in the flat tree: the slot of the shadow root of its parent that
1961
+ * takes it. `null` when its parent is a shadow host and no slot takes it, so that it is not rendered;
1962
+ * `undefined` when its parent is not a shadow host, or the assignment is not known
1963
+ * (see {@link MLElement.getAssignedNodes}).
1964
+ *
1965
+ * `getComposedParentElement` of `@markuplint/ml-spec` reads it as the parent that the accessibility
1966
+ * tree has for the element.
1967
+ *
1968
+ * @implements `@markuplint/ml-core` API: `MLElement`
1969
+ * @see https://dom.spec.whatwg.org/#find-a-slot
1970
+ */
1971
+ getFlatTreeSlot(): MLElement<T, O> | null | undefined;
1885
1972
  /**
1886
1973
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
1887
1974
  *
@@ -2064,7 +2151,8 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2064
2151
  getAttributePretended(attrName: string): string | null;
2065
2152
  /**
2066
2153
  * Returns all attribute tokens matching the given name, including duplicates.
2067
- * Unlike `getAttribute`, this returns the full `MLAttr` token objects.
2154
+ * Unlike `getAttribute`, this returns the full `MLAttr` token objects. An attribute that the
2155
+ * framework does not output (`MLAttr#isAbsent`) is not one of them, as it is not for `getAttribute`.
2068
2156
  *
2069
2157
  * @implements `@markuplint/ml-core` API: `MLElement`
2070
2158
  * @param attrName - The attribute name to look up (see {@link MLAttr.isNamedBy} for how its case is compared)
@@ -2074,6 +2162,9 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2074
2162
  /**
2075
2163
  * Returns all attribute tokens for this element, respecting the pretender context.
2076
2164
  * If the element is pretending to be another, returns the pretender's attributes.
2165
+ * It lists every attribute that is written, those that the framework does not output
2166
+ * (`MLAttr#isAbsent`) too, as a name that is misspelled is so whatever its value is; what is asked
2167
+ * of the DOM by name (`getAttributeToken`, `getAttribute`) does not find them.
2077
2168
  *
2078
2169
  * @implements `@markuplint/ml-core` API: `MLElement`
2079
2170
  * @returns A frozen array of all attribute tokens
@@ -2084,7 +2175,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2084
2175
  *
2085
2176
  * @unsupported
2086
2177
  * @implements DOM API: `Element`
2087
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-getboundingclientrect-1
2178
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-getboundingclientrect
2088
2179
  */
2089
2180
  getBoundingClientRect(): DOMRect;
2090
2181
  /**
@@ -2100,7 +2191,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2100
2191
  *
2101
2192
  * @unsupported
2102
2193
  * @implements DOM API: `Element`
2103
- * @see https://www.w3.org/TR/cssom-view-1/#ref-for-dom-element-getclientrects-1
2194
+ * @see https://www.w3.org/TR/cssom-view-1/#dom-element-getclientrects
2104
2195
  */
2105
2196
  getClientRects(): DOMRectList;
2106
2197
  /**
@@ -2166,10 +2257,25 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2166
2257
  * @returns True if any attribute is dynamic or lacks a name node (spread)
2167
2258
  */
2168
2259
  hasMutableAttributes(): boolean;
2260
+ /**
2261
+ * Checks whether this element is a component whose rendered output is not known: the
2262
+ * parser sees it as a component (`elementType` is `'authored'`) and no pretender stands
2263
+ * for an element of HTML, which includes a pretender whose own target is a component
2264
+ * (the chain of `pretenders.auto` stopped at `Tabs.Root`).
2265
+ *
2266
+ * A web component is not one: it is the element that it is written as. The criterion of
2267
+ * `isTreatedAsCustom` in `@markuplint/rules` (`permitted-contents`) includes it, because
2268
+ * a content model accepts a custom element wherever it accepts flow content; change them
2269
+ * together.
2270
+ *
2271
+ * @implements `@markuplint/ml-core` API: `MLElement`
2272
+ * @returns True if what this element renders is not known
2273
+ */
2274
+ isUnresolvedComponent(): boolean;
2169
2275
  /**
2170
2276
  * Checks whether this element has children that are potentially mutable,
2171
2277
  * such as preprocessor-specific blocks, slot elements, or (optionally) elements
2172
- * with dynamic attributes.
2278
+ * with dynamic attributes and components that no pretender resolved.
2173
2279
  *
2174
2280
  * Blocks that carry a `blockBehavior` are not treated as mutable because
2175
2281
  * their branches are deterministically enumerable via
@@ -2177,11 +2283,29 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2177
2283
  * like `{value}`) can produce arbitrary content, so the children are
2178
2284
  * considered mutable.
2179
2285
  *
2286
+ * A component that no pretender resolved renders something that is not known, however its
2287
+ * attributes are written (`size={size}`, `size={16}` and `size="16"` tell the same): a rule that
2288
+ * asks about what the descendants are or have (the accessible name, the owned elements) cannot decide
2289
+ * on it, so it is mutable when `attr` is true ({@link MLElement.isUnresolvedComponent}). A component
2290
+ * that a pretender resolved is the element that it renders, which the rules read themselves.
2291
+ *
2292
+ * A rule that asks which children an element has (the required children, the elements that
2293
+ * satisfy a query) does not pass `attr`: an attribute that cannot be known does not decide whether
2294
+ * a child exists. It looks for the unresolved components among the children itself.
2295
+ *
2296
+ * Every `slot` is mutable by default, as a `slot` that is not in a declarative shadow root renders what
2297
+ * is given to it, and a rule that reads the children as they are written (`require-datetime`) cannot
2298
+ * know it. A rule that reads what a slot of a shadow root renders by `MLElement#getAssignedNodes` says
2299
+ * which slots are with `isMutableSlot`.
2300
+ *
2301
+ *
2180
2302
  * @implements `@markuplint/ml-core` API: `MLElement`
2181
- * @param attr - When true, also considers children with mutable attributes as mutable
2303
+ * @param attr - When true, also considers children with mutable attributes, and components that no
2304
+ * pretender resolved, as mutable
2305
+ * @param isMutableSlot - Whether a `slot` among the descendants may render what is not known
2182
2306
  * @returns True if this element has potentially mutable children
2183
2307
  */
2184
- hasMutableChildren(attr?: boolean): boolean;
2308
+ hasMutableChildren(attr?: boolean, isMutableSlot?: (slot: MLElement<T, O>) => boolean): boolean;
2185
2309
  /**
2186
2310
  * **IT THROWS AN ERROR WHEN CALLING THIS.**
2187
2311
  *
@@ -2211,7 +2335,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2211
2335
  *
2212
2336
  * @unsupported
2213
2337
  * @implements DOM API: `Element`
2214
- * @see https://w3c.github.io/DOM-Parsing/#widl-Element-insertAdjacentHTML-void-DOMString-position-DOMString-text
2338
+ * @see https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml
2215
2339
  */
2216
2340
  insertAdjacentHTML(position: InsertPosition, text: string): void;
2217
2341
  /**
@@ -2323,7 +2447,7 @@ export declare class MLElement<T extends RuleConfigValue, O extends PlainData =
2323
2447
  *
2324
2448
  * @unsupported
2325
2449
  * @implements DOM API: `Element`
2326
- * @see https://w3c.github.io/pointerlock/#dom-element-requestpointerlock
2450
+ * @see https://www.w3.org/TR/pointerlock-2/#dom-element-requestpointerlock
2327
2451
  */
2328
2452
  requestPointerLock(options?: any): Promise<void>;
2329
2453
  /**