@getodk/xforms-engine 0.13.0 → 0.14.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 (71) hide show
  1. package/dist/client/BaseItem.d.ts +6 -0
  2. package/dist/client/GroupNode.d.ts +4 -4
  3. package/dist/client/MarkdownNode.d.ts +33 -0
  4. package/dist/client/RankNode.d.ts +2 -4
  5. package/dist/client/SelectNode.d.ts +2 -5
  6. package/dist/client/TextRange.d.ts +2 -2
  7. package/dist/client/hierarchy.d.ts +1 -2
  8. package/dist/client/index.d.ts +1 -1
  9. package/dist/client/node-types.d.ts +1 -1
  10. package/dist/index.js +10411 -327
  11. package/dist/index.js.map +1 -1
  12. package/dist/instance/hierarchy.d.ts +5 -6
  13. package/dist/instance/markdown/MarkdownNode.d.ts +75 -0
  14. package/dist/instance/text/TextChunk.d.ts +0 -1
  15. package/dist/instance/text/TextRange.d.ts +2 -1
  16. package/dist/instance/text/markdownFormat.d.ts +3 -0
  17. package/dist/lib/reactivity/createItemCollection.d.ts +5 -7
  18. package/dist/parse/body/BodyDefinition.d.ts +2 -8
  19. package/dist/parse/body/GroupElementDefinition.d.ts +22 -0
  20. package/dist/parse/body/control/ItemsetDefinition.d.ts +3 -0
  21. package/dist/parse/expression/ItemPropertyExpression.d.ts +6 -0
  22. package/dist/parse/model/{SubtreeDefinition.d.ts → GroupDefinition.d.ts} +4 -3
  23. package/dist/parse/model/NodeDefinition.d.ts +7 -8
  24. package/dist/parse/model/RepeatDefinition.d.ts +1 -1
  25. package/dist/parse/model/RootDefinition.d.ts +1 -1
  26. package/dist/parse/text/LabelDefinition.d.ts +4 -5
  27. package/dist/solid.js +10411 -327
  28. package/dist/solid.js.map +1 -1
  29. package/package.json +3 -2
  30. package/src/client/BaseItem.ts +7 -0
  31. package/src/client/GroupNode.ts +4 -10
  32. package/src/client/MarkdownNode.ts +53 -0
  33. package/src/client/RankNode.ts +2 -5
  34. package/src/client/SelectNode.ts +2 -6
  35. package/src/client/TextRange.ts +2 -2
  36. package/src/client/hierarchy.ts +0 -2
  37. package/src/client/index.ts +1 -1
  38. package/src/client/node-types.ts +0 -1
  39. package/src/instance/Group.ts +1 -1
  40. package/src/instance/children/buildChildren.ts +1 -17
  41. package/src/instance/children/normalizeChildInitOptions.ts +44 -59
  42. package/src/instance/hierarchy.ts +0 -6
  43. package/src/instance/markdown/MarkdownNode.ts +115 -0
  44. package/src/instance/text/TextChunk.ts +0 -5
  45. package/src/instance/text/TextRange.ts +5 -3
  46. package/src/instance/text/markdownFormat.ts +214 -0
  47. package/src/integration/xpath/adapter/names.ts +0 -1
  48. package/src/lib/reactivity/createItemCollection.ts +25 -9
  49. package/src/parse/body/BodyDefinition.ts +7 -34
  50. package/src/parse/body/GroupElementDefinition.ts +47 -0
  51. package/src/parse/body/control/ItemsetDefinition.ts +7 -0
  52. package/src/parse/expression/ItemPropertyExpression.ts +12 -0
  53. package/src/parse/model/{SubtreeDefinition.ts → GroupDefinition.ts} +6 -8
  54. package/src/parse/model/NodeDefinition.ts +8 -9
  55. package/src/parse/model/RepeatDefinition.ts +2 -2
  56. package/src/parse/model/RootDefinition.ts +2 -2
  57. package/src/parse/text/LabelDefinition.ts +4 -9
  58. package/dist/client/SubtreeNode.d.ts +0 -56
  59. package/dist/instance/Subtree.d.ts +0 -38
  60. package/dist/instance/text/FormattedTextStub.d.ts +0 -1
  61. package/dist/parse/body/group/BaseGroupDefinition.d.ts +0 -40
  62. package/dist/parse/body/group/LogicalGroupDefinition.d.ts +0 -6
  63. package/dist/parse/body/group/PresentationGroupDefinition.d.ts +0 -11
  64. package/dist/parse/body/group/StructuralGroupDefinition.d.ts +0 -6
  65. package/src/client/SubtreeNode.ts +0 -61
  66. package/src/instance/Subtree.ts +0 -102
  67. package/src/instance/text/FormattedTextStub.ts +0 -8
  68. package/src/parse/body/group/BaseGroupDefinition.ts +0 -89
  69. package/src/parse/body/group/LogicalGroupDefinition.ts +0 -11
  70. package/src/parse/body/group/PresentationGroupDefinition.ts +0 -28
  71. package/src/parse/body/group/StructuralGroupDefinition.ts +0 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getodk/xforms-engine",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "XForms engine for ODK Web Forms",
6
6
  "type": "module",
@@ -55,6 +55,7 @@
55
55
  },
56
56
  "dependencies": {
57
57
  "bin-packer": "1.7.0",
58
+ "mdast-util-from-markdown": "^2.0.2",
58
59
  "papaparse": "^5.5.3",
59
60
  "solid-js": "^1.9.7",
60
61
  "temporal-polyfill": "^0.3.0"
@@ -62,7 +63,7 @@
62
63
  "devDependencies": {
63
64
  "@babel/core": "^7.28.0",
64
65
  "@getodk/tree-sitter-xpath": "0.2.0",
65
- "@getodk/xpath": "0.8.0",
66
+ "@getodk/xpath": "0.8.1",
66
67
  "@playwright/test": "^1.53.2",
67
68
  "@types/papaparse": "^5.3.16",
68
69
  "@vitest/browser": "^3.2.4",
@@ -0,0 +1,7 @@
1
+ import type { TextRange } from './TextRange.ts';
2
+
3
+ export interface BaseItem {
4
+ get label(): TextRange<'item-label'>;
5
+ get value(): string;
6
+ properties: Array<[string, string]>;
7
+ }
@@ -1,5 +1,5 @@
1
- import type { AnyGroupElementDefinition } from '../parse/body/BodyDefinition.ts';
2
- import type { SubtreeDefinition } from '../parse/model/SubtreeDefinition.ts';
1
+ import type { GroupElementDefinition } from '../parse/body/GroupElementDefinition.ts';
2
+ import type { GroupDefinition as GroupNodeDefinition } from '../parse/model/GroupDefinition.ts';
3
3
  import type { BaseNode, BaseNodeState } from './BaseNode.ts';
4
4
  import type { NodeAppearances } from './NodeAppearances.ts';
5
5
  import type { RootNode } from './RootNode.ts';
@@ -13,10 +13,8 @@ export interface GroupNodeState extends BaseNodeState {
13
13
  get value(): null;
14
14
  }
15
15
 
16
- // TODO: as with `SubtreeNode`'s `SubtreeDefinition`, there is a naming
17
- // inconsistency emerging here.
18
- export interface GroupDefinition extends SubtreeDefinition {
19
- readonly bodyElement: AnyGroupElementDefinition;
16
+ export interface GroupDefinition extends GroupNodeDefinition {
17
+ readonly bodyElement: GroupElementDefinition;
20
18
  }
21
19
 
22
20
  export type GroupNodeAppearances = NodeAppearances<GroupDefinition>;
@@ -24,10 +22,6 @@ export type GroupNodeAppearances = NodeAppearances<GroupDefinition>;
24
22
  /**
25
23
  * A node corresponding to an XForms `<group>`.
26
24
  */
27
- // TODO: test (fix?) case where a `<group>` is implicitly connected to a
28
- // subtree, but doesn't reference it directly. See
29
- // https://github.com/getodk/web-forms/blob/6cfff8b4c5a2cf6a23a71ef6d4308343bccd2436/packages/odk-web-forms/src/lib/xform/model/ModelDefinition.test.ts#L480-L540
30
- // for context.
31
25
  export interface GroupNode extends BaseNode {
32
26
  readonly nodeType: 'group';
33
27
  readonly appearances: GroupNodeAppearances;
@@ -0,0 +1,53 @@
1
+ export type Heading = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
2
+
3
+ export type ElementName =
4
+ | Heading
5
+ | 'a'
6
+ | 'div'
7
+ | 'em'
8
+ | 'li'
9
+ | 'ol'
10
+ | 'p'
11
+ | 'span'
12
+ | 'strong'
13
+ | 'u'
14
+ | 'ul';
15
+
16
+ export type MarkdownNode = ChildMarkdownNode | HtmlMarkdownNode | ParentMarkdownNode;
17
+
18
+ export interface ParentMarkdownNode {
19
+ readonly role: 'parent';
20
+ readonly elementName: string;
21
+ readonly children: MarkdownNode[];
22
+ }
23
+
24
+ export interface ChildMarkdownNode {
25
+ readonly role: 'child';
26
+ readonly value: string;
27
+ }
28
+
29
+ export interface HtmlMarkdownNode {
30
+ readonly role: 'html';
31
+ readonly unsafeHtml: string;
32
+ }
33
+
34
+ export interface AnchorMarkdownNode extends ParentMarkdownNode {
35
+ readonly elementName: 'a';
36
+ readonly url: string;
37
+ }
38
+
39
+ export interface StyledMarkdownNode extends ParentMarkdownNode {
40
+ readonly elementName: 'div' | 'p' | 'span';
41
+ readonly properties: MarkdownProperty | undefined;
42
+ }
43
+
44
+ export interface MarkdownProperty {
45
+ readonly style: StyleProperty;
46
+ }
47
+
48
+ export interface StyleProperty {
49
+ readonly color: string | undefined;
50
+ readonly 'font-family': string | undefined;
51
+ readonly 'text-align': 'center' | 'left' | 'right' | undefined;
52
+ readonly 'font-size': string | undefined;
53
+ }
@@ -1,6 +1,7 @@
1
1
  import type { RankControlDefinition } from '../parse/body/control/RankControlDefinition.ts';
2
2
  import type { LeafNodeDefinition } from '../parse/model/LeafNodeDefinition.ts';
3
3
  import type { BaseValueNode, BaseValueNodeState } from './BaseValueNode.ts';
4
+ import type { BaseItem } from './BaseItem.ts';
4
5
  import type { RootNode } from './RootNode.ts';
5
6
  import type { TextRange } from './TextRange.ts';
6
7
  import type { GeneralParentNode } from './hierarchy.ts';
@@ -8,11 +9,7 @@ import type { LeafNodeValidationState } from './validation.ts';
8
9
  import type { UnknownAppearanceDefinition } from '../parse/body/appearance/unknownAppearanceParser.ts';
9
10
  import type { ValueType } from './ValueType.ts';
10
11
 
11
- export interface RankItem {
12
- get label(): TextRange<'item-label'>;
13
- get value(): string;
14
- }
15
-
12
+ export type RankItem = BaseItem;
16
13
  export type RankValueOptions = readonly RankItem[];
17
14
 
18
15
  export interface RankNodeState extends BaseValueNodeState<readonly string[]> {
@@ -4,18 +4,14 @@ import type {
4
4
  } from '../parse/body/control/SelectControlDefinition.ts';
5
5
  import type { LeafNodeDefinition } from '../parse/model/LeafNodeDefinition.ts';
6
6
  import type { BaseValueNode, BaseValueNodeState } from './BaseValueNode.ts';
7
+ import type { BaseItem } from './BaseItem.ts';
7
8
  import type { NodeAppearances } from './NodeAppearances.ts';
8
9
  import type { RootNode } from './RootNode.ts';
9
- import type { TextRange } from './TextRange.ts';
10
10
  import type { ValueType } from './ValueType.ts';
11
11
  import type { GeneralParentNode } from './hierarchy.ts';
12
12
  import type { LeafNodeValidationState } from './validation.ts';
13
13
 
14
- export interface SelectItem {
15
- get label(): TextRange<'item-label'>;
16
- get value(): string;
17
- }
18
-
14
+ export type SelectItem = BaseItem;
19
15
  export type SelectValueOptions = readonly SelectItem[];
20
16
 
21
17
  export interface SelectNodeState extends BaseValueNodeState<readonly string[]> {
@@ -1,5 +1,6 @@
1
1
  import { JRResourceURL } from '@getodk/common/jr-resources/JRResourceURL.ts';
2
2
  import type { ActiveLanguage } from './FormLanguage.ts';
3
+ import type { MarkdownNode } from './MarkdownNode.ts';
3
4
 
4
5
  /**
5
6
  * **COMMENTARY**
@@ -73,7 +74,6 @@ export interface TextChunk {
73
74
  get language(): ActiveLanguage;
74
75
 
75
76
  get asString(): string;
76
- get formatted(): unknown;
77
77
  }
78
78
 
79
79
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
@@ -146,7 +146,7 @@ export interface TextRange<Role extends TextRole, Origin extends TextOrigin = Te
146
146
  [Symbol.iterator](): Iterable<TextChunk>;
147
147
 
148
148
  get asString(): string;
149
- get formatted(): unknown;
149
+ get formatted(): MarkdownNode[];
150
150
 
151
151
  get imageSource(): JRResourceURL | undefined;
152
152
  get audioSource(): JRResourceURL | undefined;
@@ -10,7 +10,6 @@ import type { RepeatRangeControlledNode } from './repeat/RepeatRangeControlledNo
10
10
  import type { RepeatRangeUncontrolledNode } from './repeat/RepeatRangeUncontrolledNode.ts';
11
11
  import type { RootNode } from './RootNode.ts';
12
12
  import type { SelectNode } from './SelectNode.ts';
13
- import type { SubtreeNode } from './SubtreeNode.ts';
14
13
  import type { TriggerNode } from './TriggerNode.ts';
15
14
  import type { UploadNode } from './UploadNode.ts';
16
15
 
@@ -40,7 +39,6 @@ export type RepeatRangeNode =
40
39
  */
41
40
  export type GeneralParentNode =
42
41
  | RootNode // eslint-disable-line @typescript-eslint/sort-type-constituents
43
- | SubtreeNode
44
42
  | GroupNode
45
43
  | RepeatInstanceNode;
46
44
 
@@ -24,6 +24,7 @@ export type {
24
24
  } from './hierarchy.ts';
25
25
  export type * from './identity.ts';
26
26
  export type * from './InputNode.ts';
27
+ export type * from './MarkdownNode.ts';
27
28
  export type * from './ModelValueNode.ts';
28
29
  export type * from './NoteNode.ts';
29
30
  export type * from './OpaqueReactiveObjectFactory.ts';
@@ -41,7 +42,6 @@ export type * from './serialization/InstancePayload.ts';
41
42
  export type * from './serialization/InstancePayloadOptions.ts';
42
43
  export type * from './serialization/InstanceState.ts';
43
44
  export type * from './submission/SubmissionMeta.ts';
44
- export type * from './SubtreeNode.ts';
45
45
  export type * from './TextRange.ts';
46
46
  export type * from './TriggerNode.ts';
47
47
  export type * from './UploadNode.ts';
@@ -22,5 +22,4 @@ export type InstanceNodeType =
22
22
  | RepeatRangeNodeType
23
23
  | 'repeat-instance'
24
24
  | 'group'
25
- | 'subtree'
26
25
  | LeafNodeType;
@@ -65,7 +65,7 @@ export class Group
65
65
  ) {
66
66
  super(parent, instanceNode, definition);
67
67
 
68
- this.appearances = definition.bodyElement.appearances;
68
+ this.appearances = definition.bodyElement?.appearances ?? null;
69
69
 
70
70
  const childrenState = createChildrenState<Group, GeneralChildNode>(this);
71
71
 
@@ -4,7 +4,6 @@ import type { InputDefinition } from '../../client/InputNode.ts';
4
4
  import type { ModelValueDefinition } from '../../client/ModelValueNode.ts';
5
5
  import type { RankDefinition } from '../../client/RankNode.ts';
6
6
  import type { SelectDefinition } from '../../client/SelectNode.ts';
7
- import type { SubtreeDefinition } from '../../client/SubtreeNode.ts';
8
7
  import type { TriggerNodeDefinition } from '../../client/TriggerNode.ts';
9
8
  import type { UploadDefinition } from '../../client/UploadNode.ts';
10
9
  import { ErrorProductionDesignPendingError } from '../../error/ErrorProductionDesignPendingError.ts';
@@ -15,7 +14,6 @@ import type {
15
14
  RangeLeafNodeDefinition,
16
15
  } from '../../parse/model/RangeNodeDefinition.ts';
17
16
  import { RangeNodeDefinition } from '../../parse/model/RangeNodeDefinition.ts';
18
- import type { SubtreeDefinition as ModelSubtreeDefinition } from '../../parse/model/SubtreeDefinition.ts';
19
17
  import { Group } from '../Group.ts';
20
18
  import type { GeneralChildNode, GeneralParentNode } from '../hierarchy.ts';
21
19
  import { InputControl } from '../InputControl.ts';
@@ -26,17 +24,10 @@ import { RankControl } from '../RankControl.ts';
26
24
  import { RepeatRangeControlled } from '../repeat/RepeatRangeControlled.ts';
27
25
  import { RepeatRangeUncontrolled } from '../repeat/RepeatRangeUncontrolled.ts';
28
26
  import { SelectControl } from '../SelectControl.ts';
29
- import { Subtree } from '../Subtree.ts';
30
27
  import { TriggerControl } from '../TriggerControl.ts';
31
28
  import { UploadControl } from '../UploadControl.ts';
32
29
  import { childrenInitOptions } from './childrenInitOptions.ts';
33
30
 
34
- const isSubtreeDefinition = (
35
- definition: ModelSubtreeDefinition
36
- ): definition is SubtreeDefinition => {
37
- return definition.bodyElement == null;
38
- };
39
-
40
31
  // prettier-ignore
41
32
  type ControlNodeDefinition =
42
33
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
@@ -131,14 +122,7 @@ export const buildChildren = (parent: GeneralParentNode): GeneralChildNode[] =>
131
122
  const [instanceNode = null] = instanceNodes;
132
123
 
133
124
  switch (definition.type) {
134
- case 'subtree': {
135
- if (isSubtreeDefinition(definition)) {
136
- return new Subtree(parent, instanceNode, definition);
137
- }
138
-
139
- // TODO: it'd be good to be able to do without this type assertion. The
140
- // only distinction between the types is whether `bodyElement` is
141
- // `null`, but for some reason that's insufficient to narrow the union.
125
+ case 'group': {
142
126
  return new Group(parent, instanceNode, definition as GroupDefinition);
143
127
  }
144
128
 
@@ -3,21 +3,19 @@ import {
3
3
  XFORMS_NAMESPACE_URI,
4
4
  } from '@getodk/common/constants/xmlns.ts';
5
5
  import type { GroupDefinition } from '../../client/GroupNode.ts';
6
- import type { SubtreeDefinition } from '../../client/SubtreeNode.ts';
7
6
  import { ErrorProductionDesignPendingError } from '../../error/ErrorProductionDesignPendingError.ts';
8
7
  import { StaticDocument } from '../../integration/xpath/static-dom/StaticDocument.ts';
9
8
  import type { StaticLeafElement } from '../../integration/xpath/static-dom/StaticElement.ts';
10
9
  import { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
11
10
  import type { NamespaceURL } from '../../lib/names/NamespaceURL.ts';
12
11
  import type { QualifiedName } from '../../lib/names/QualifiedName.ts';
12
+ import type { GroupDefinition as ModelGroupDefinition } from '../../parse/model/GroupDefinition.ts';
13
13
  import { LeafNodeDefinition } from '../../parse/model/LeafNodeDefinition.ts';
14
- import type { SubtreeDefinition as ModelSubtreeDefinition } from '../../parse/model/SubtreeDefinition.ts';
15
14
  import type { XFormDOM } from '../../parse/XFormDOM.ts';
16
15
  import type { Group } from '../Group.ts';
17
16
  import type { GeneralParentNode } from '../hierarchy.ts';
18
17
  import type { PrimaryInstance } from '../PrimaryInstance.ts';
19
18
  import type { Root } from '../Root.ts';
20
- import type { Subtree } from '../Subtree.ts';
21
19
  import type { ChildrenInitOptions } from './childrenInitOptions.ts';
22
20
  import type { DescendantNodeInitOptions } from './DescendantNodeInitOptions.ts';
23
21
 
@@ -65,21 +63,12 @@ interface BaseMetaDefinition {
65
63
  readonly qualifiedName: MetaName;
66
64
  }
67
65
 
68
- const isBaseMetaDefinition = <T extends ModelSubtreeDefinition>(
66
+ const isBaseMetaDefinition = <T extends ModelGroupDefinition>(
69
67
  definition: T
70
68
  ): definition is BaseMetaDefinition & T => {
71
69
  return isMetaName(definition.qualifiedName);
72
70
  };
73
71
 
74
- interface MetaSubtreeDefinition extends SubtreeDefinition {
75
- readonly qualifiedName: MetaName;
76
- }
77
-
78
- interface MetaSubtree extends Subtree {
79
- readonly parent: Root;
80
- readonly definition: MetaSubtreeDefinition;
81
- }
82
-
83
72
  interface MetaGroupDefinition extends GroupDefinition {
84
73
  readonly qualifiedName: MetaName;
85
74
  }
@@ -89,17 +78,15 @@ interface MetaGroup extends Group {
89
78
  readonly definition: MetaGroupDefinition;
90
79
  }
91
80
 
92
- type MetaSubroot = MetaGroup | MetaSubtree;
93
-
94
- interface MetaSubrootInitOptions extends ChildrenInitOptions {
95
- readonly parent: MetaGroup | MetaSubtree;
81
+ interface MetaGroupInitOptions extends ChildrenInitOptions {
82
+ readonly parent: MetaGroup;
96
83
  }
97
84
 
98
- const isMetaSubroot = (options: ChildrenInitOptions): options is MetaSubrootInitOptions => {
85
+ const isMetaGroup = (options: ChildrenInitOptions): options is MetaGroupInitOptions => {
99
86
  const { nodeType } = options.parent;
100
87
 
101
88
  return (
102
- (nodeType === 'subtree' || nodeType === 'group') &&
89
+ nodeType === 'group' &&
103
90
  isDirectRootDescendant(options.parent) &&
104
91
  isBaseMetaDefinition(options.parent.definition)
105
92
  );
@@ -119,16 +106,16 @@ interface EditModeInstanceDescendant {
119
106
  readonly rootDocument: EditModeInstance;
120
107
  }
121
108
 
122
- type EditModeMetaSubroot = EditModeInstanceDescendant & MetaSubroot;
109
+ type EditModeMetaGroup = EditModeInstanceDescendant & MetaGroup;
123
110
 
124
- interface EditModeMetaSubrootInitOptions extends MetaSubrootInitOptions {
125
- readonly parent: EditModeMetaSubroot;
111
+ interface EditModeMetaGroupInitOptions extends MetaGroupInitOptions {
112
+ readonly parent: EditModeMetaGroup;
126
113
  }
127
114
 
128
- const isEditModeMetaSubroot = (
129
- subroot: MetaSubrootInitOptions
130
- ): subroot is EditModeMetaSubrootInitOptions => {
131
- return isEditModeInstance(subroot.parent.rootDocument);
115
+ const isEditModeMetaGroup = (
116
+ group: MetaGroupInitOptions
117
+ ): group is EditModeMetaGroupInitOptions => {
118
+ return isEditModeInstance(group.parent.rootDocument);
132
119
  };
133
120
 
134
121
  interface LeafNodeInitOptions extends DescendantNodeInitOptions {
@@ -147,13 +134,13 @@ const isLeafNodeInitOptions = (
147
134
  type MetaLeafChildEntry = readonly [index: number, child: LeafNodeInitOptions];
148
135
 
149
136
  const findMetaLeafChild = (
150
- subroot: MetaSubrootInitOptions,
137
+ group: MetaGroupInitOptions,
151
138
  localName: string
152
139
  ): MetaLeafChildEntry | null => {
153
- const metaName = subroot.parent.definition.qualifiedName satisfies MetaName;
140
+ const metaName = group.parent.definition.qualifiedName satisfies MetaName;
154
141
  const namespaceURI = metaName.namespaceURI.href satisfies MetaNamespaceURIValue;
155
142
 
156
- const result = Array.from(subroot.children.entries()).find(
143
+ const result = Array.from(group.children.entries()).find(
157
144
  (entry): entry is [number, LeafNodeInitOptions] => {
158
145
  const [, child] = entry;
159
146
 
@@ -173,8 +160,8 @@ const findMetaLeafChild = (
173
160
  return result ?? null;
174
161
  };
175
162
 
176
- const getInstanceIDValue = (subroot: MetaSubrootInitOptions): string | null => {
177
- const [, child = null] = findMetaLeafChild(subroot, INSTANCE_ID_LOCAL_NAME) ?? [];
163
+ const getInstanceIDValue = (group: MetaGroupInitOptions): string | null => {
164
+ const [, child = null] = findMetaLeafChild(group, INSTANCE_ID_LOCAL_NAME) ?? [];
178
165
 
179
166
  if (child == null) {
180
167
  return null;
@@ -200,11 +187,11 @@ const assertStaticLeafElement: AssertStaticLeafElement = (element) => {
200
187
  * on {@link populateDeprecatedID}.
201
188
  */
202
189
  const buildMetaValueElement = (
203
- subroot: MetaSubrootInitOptions,
190
+ group: MetaGroupInitOptions,
204
191
  localName: string,
205
192
  value: string
206
193
  ): StaticLeafElement => {
207
- const { qualifiedName, nodeset } = subroot.parent.definition;
194
+ const { qualifiedName, nodeset } = group.parent.definition;
208
195
  const { namespaceURI, prefix } = qualifiedName;
209
196
  const { root } = new StaticDocument({
210
197
  documentRoot: {
@@ -224,21 +211,21 @@ const buildMetaValueElement = (
224
211
  };
225
212
 
226
213
  const buildDeprecatedIDDefinition = (
227
- subroot: EditModeMetaSubrootInitOptions,
214
+ group: EditModeMetaGroupInitOptions,
228
215
  instanceNode: StaticLeafElement
229
216
  ): LeafNodeDefinition => {
230
217
  const nodeset = instanceNode.nodeset;
231
- const bind = subroot.model.binds.getOrCreateBindDefinition(nodeset);
218
+ const bind = group.model.binds.getOrCreateBindDefinition(nodeset);
232
219
 
233
- return new LeafNodeDefinition(subroot.parent.definition, bind, null, instanceNode);
220
+ return new LeafNodeDefinition(group.parent.definition, bind, null, instanceNode);
234
221
  };
235
222
 
236
223
  const buildDeprecatedID = (
237
- subroot: EditModeMetaSubrootInitOptions,
224
+ group: EditModeMetaGroupInitOptions,
238
225
  value: string
239
226
  ): LeafNodeInitOptions => {
240
- const instanceNode = buildMetaValueElement(subroot, DEPRECATED_ID_LOCAL_NAME, value);
241
- const definition = buildDeprecatedIDDefinition(subroot, instanceNode);
227
+ const instanceNode = buildMetaValueElement(group, DEPRECATED_ID_LOCAL_NAME, value);
228
+ const definition = buildDeprecatedIDDefinition(group, instanceNode);
242
229
 
243
230
  return {
244
231
  childNodeset: instanceNode.nodeset,
@@ -248,11 +235,11 @@ const buildDeprecatedID = (
248
235
  };
249
236
 
250
237
  const updateDeprecatedID = (
251
- subroot: EditModeMetaSubrootInitOptions,
238
+ group: EditModeMetaGroupInitOptions,
252
239
  child: LeafNodeInitOptions,
253
240
  value: string
254
241
  ): LeafNodeInitOptions => {
255
- const instanceNode = buildMetaValueElement(subroot, DEPRECATED_ID_LOCAL_NAME, value);
242
+ const instanceNode = buildMetaValueElement(group, DEPRECATED_ID_LOCAL_NAME, value);
256
243
 
257
244
  return {
258
245
  childNodeset: child.childNodeset,
@@ -288,44 +275,42 @@ const replaceOrConcat = <T>(values: readonly T[], index: number | null, value: T
288
275
  * hacky normalization for `instanceID`.
289
276
  */
290
277
  const populateDeprecatedID = (
291
- subroot: EditModeMetaSubrootInitOptions
292
- ): EditModeMetaSubrootInitOptions => {
293
- const value = getInstanceIDValue(subroot);
278
+ group: EditModeMetaGroupInitOptions
279
+ ): EditModeMetaGroupInitOptions => {
280
+ const value = getInstanceIDValue(group);
294
281
 
295
282
  if (value == null) {
296
- return subroot;
283
+ return group;
297
284
  }
298
285
 
299
- const [index, currentDeprecatedID] = findMetaLeafChild(subroot, DEPRECATED_ID_LOCAL_NAME) ?? [
300
- null,
301
- ];
286
+ const [index, currentDeprecatedID] = findMetaLeafChild(group, DEPRECATED_ID_LOCAL_NAME) ?? [null];
302
287
 
303
288
  let deprecatedID: LeafNodeInitOptions;
304
289
 
305
290
  if (currentDeprecatedID == null) {
306
- deprecatedID = buildDeprecatedID(subroot, value);
291
+ deprecatedID = buildDeprecatedID(group, value);
307
292
  } else {
308
- deprecatedID = updateDeprecatedID(subroot, currentDeprecatedID, value);
293
+ deprecatedID = updateDeprecatedID(group, currentDeprecatedID, value);
309
294
  }
310
295
 
311
296
  return {
312
- model: subroot.model,
313
- parent: subroot.parent,
314
- children: replaceOrConcat(subroot.children, index, deprecatedID),
297
+ model: group.model,
298
+ parent: group.parent,
299
+ children: replaceOrConcat(group.children, index, deprecatedID),
315
300
  };
316
301
  };
317
302
 
318
- const normalizeMetaSubroot = (subroot: MetaSubrootInitOptions): MetaSubrootInitOptions => {
319
- if (isEditModeMetaSubroot(subroot)) {
320
- return populateDeprecatedID(subroot);
303
+ const normalizeMetaGroup = (group: MetaGroupInitOptions): MetaGroupInitOptions => {
304
+ if (isEditModeMetaGroup(group)) {
305
+ return populateDeprecatedID(group);
321
306
  }
322
307
 
323
- return subroot;
308
+ return group;
324
309
  };
325
310
 
326
311
  export const normalizeChildInitOptions = (options: ChildrenInitOptions): ChildrenInitOptions => {
327
- if (isMetaSubroot(options)) {
328
- return normalizeMetaSubroot(options);
312
+ if (isMetaGroup(options)) {
313
+ return normalizeMetaGroup(options);
329
314
  }
330
315
 
331
316
  return options;
@@ -10,7 +10,6 @@ import type { RepeatRangeControlled } from './repeat/RepeatRangeControlled.ts';
10
10
  import type { RepeatRangeUncontrolled } from './repeat/RepeatRangeUncontrolled.ts';
11
11
  import type { Root } from './Root.ts';
12
12
  import type { SelectControl } from './SelectControl.ts';
13
- import type { Subtree } from './Subtree.ts';
14
13
  import type { TriggerControl } from './TriggerControl.ts';
15
14
  import type { UploadControl } from './UploadControl.ts';
16
15
 
@@ -22,7 +21,6 @@ export type AnyNode =
22
21
  | PrimaryInstance
23
22
  | Root
24
23
  | Group
25
- | Subtree
26
24
  | RepeatRange
27
25
  | RepeatInstance
28
26
  | AnyNote
@@ -40,7 +38,6 @@ export type AnyParentNode =
40
38
  | PrimaryInstance
41
39
  | Root
42
40
  | Group
43
- | Subtree
44
41
  | RepeatRange
45
42
  | RepeatInstance;
46
43
 
@@ -49,7 +46,6 @@ export type GeneralParentNode =
49
46
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
50
47
  | Root
51
48
  | Group
52
- | Subtree
53
49
  | RepeatInstance;
54
50
 
55
51
  // prettier-ignore
@@ -57,7 +53,6 @@ export type AnyChildNode =
57
53
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
58
54
  | Root
59
55
  | Group
60
- | Subtree
61
56
  | RepeatRange
62
57
  | RepeatInstance
63
58
  | AnyModelValue
@@ -73,7 +68,6 @@ export type AnyChildNode =
73
68
  export type GeneralChildNode =
74
69
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
75
70
  | Group
76
- | Subtree
77
71
  | RepeatRange
78
72
  | AnyModelValue
79
73
  | AnyNote