@getodk/xforms-engine 0.14.0 → 0.15.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 (87) hide show
  1. package/dist/client/AttributeNode.d.ts +53 -0
  2. package/dist/client/index.d.ts +1 -0
  3. package/dist/client/node-types.d.ts +1 -1
  4. package/dist/client/validation.d.ts +7 -1
  5. package/dist/index.js +436 -164
  6. package/dist/index.js.map +1 -1
  7. package/dist/instance/Attribute.d.ts +58 -0
  8. package/dist/instance/Group.d.ts +4 -0
  9. package/dist/instance/PrimaryInstance.d.ts +4 -0
  10. package/dist/instance/Root.d.ts +4 -0
  11. package/dist/instance/UploadControl.d.ts +4 -0
  12. package/dist/instance/abstract/InstanceNode.d.ts +7 -4
  13. package/dist/instance/abstract/ValueNode.d.ts +1 -0
  14. package/dist/instance/attachments/buildAttributes.d.ts +3 -0
  15. package/dist/instance/hierarchy.d.ts +2 -1
  16. package/dist/instance/internal-api/AttributeContext.d.ts +29 -0
  17. package/dist/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.d.ts +16 -0
  18. package/dist/instance/internal-api/serialization/ClientReactiveSerializableParentNode.d.ts +2 -0
  19. package/dist/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.d.ts +2 -2
  20. package/dist/instance/repeat/BaseRepeatRange.d.ts +5 -0
  21. package/dist/instance/repeat/RepeatInstance.d.ts +4 -2
  22. package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +2 -2
  23. package/dist/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.d.ts +3 -0
  24. package/dist/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.d.ts +0 -3
  25. package/dist/lib/names/NamespaceDeclarationMap.d.ts +1 -1
  26. package/dist/lib/reactivity/createAttributeState.d.ts +16 -0
  27. package/dist/lib/reactivity/createAttributeValueState.d.ts +15 -0
  28. package/dist/lib/xml-serialization.d.ts +5 -9
  29. package/dist/parse/XFormDOM.d.ts +1 -1
  30. package/dist/parse/model/AttributeDefinition.d.ts +22 -0
  31. package/dist/parse/model/{RootAttributeMap.d.ts → AttributeDefinitionMap.d.ts} +4 -10
  32. package/dist/parse/model/GroupDefinition.d.ts +4 -1
  33. package/dist/parse/model/LeafNodeDefinition.d.ts +1 -0
  34. package/dist/parse/model/NodeDefinition.d.ts +8 -3
  35. package/dist/parse/model/RepeatDefinition.d.ts +4 -1
  36. package/dist/parse/model/RootDefinition.d.ts +2 -2
  37. package/dist/solid.js +436 -164
  38. package/dist/solid.js.map +1 -1
  39. package/package.json +5 -5
  40. package/src/client/AttributeNode.ts +62 -0
  41. package/src/client/index.ts +1 -0
  42. package/src/client/node-types.ts +1 -0
  43. package/src/client/validation.ts +9 -1
  44. package/src/instance/Attribute.ts +164 -0
  45. package/src/instance/Group.ts +16 -0
  46. package/src/instance/InputControl.ts +1 -0
  47. package/src/instance/ModelValue.ts +1 -0
  48. package/src/instance/Note.ts +1 -0
  49. package/src/instance/PrimaryInstance.ts +17 -0
  50. package/src/instance/RangeControl.ts +1 -0
  51. package/src/instance/RankControl.ts +1 -0
  52. package/src/instance/Root.ts +16 -0
  53. package/src/instance/SelectControl.ts +1 -0
  54. package/src/instance/TriggerControl.ts +1 -0
  55. package/src/instance/UploadControl.ts +14 -0
  56. package/src/instance/abstract/DescendantNode.ts +5 -1
  57. package/src/instance/abstract/InstanceNode.ts +6 -3
  58. package/src/instance/abstract/ValueNode.ts +1 -0
  59. package/src/instance/attachments/buildAttributes.ts +8 -0
  60. package/src/instance/hierarchy.ts +3 -1
  61. package/src/instance/internal-api/AttributeContext.ts +34 -0
  62. package/src/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.ts +19 -0
  63. package/src/instance/internal-api/serialization/ClientReactiveSerializableParentNode.ts +2 -0
  64. package/src/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.ts +2 -3
  65. package/src/instance/repeat/BaseRepeatRange.ts +14 -0
  66. package/src/instance/repeat/RepeatInstance.ts +14 -5
  67. package/src/integration/xpath/adapter/XFormsXPathNode.ts +3 -1
  68. package/src/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.ts +16 -0
  69. package/src/lib/client-reactivity/instance-state/createParentNodeInstanceState.ts +5 -5
  70. package/src/lib/client-reactivity/instance-state/createRootInstanceState.ts +6 -9
  71. package/src/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.ts +5 -15
  72. package/src/lib/names/NamespaceDeclarationMap.ts +1 -1
  73. package/src/lib/reactivity/createAttributeState.ts +51 -0
  74. package/src/lib/reactivity/createAttributeValueState.ts +189 -0
  75. package/src/lib/xml-serialization.ts +30 -34
  76. package/src/parse/model/AttributeDefinition.ts +58 -0
  77. package/src/parse/model/{RootAttributeMap.ts → AttributeDefinitionMap.ts} +7 -13
  78. package/src/parse/model/GroupDefinition.ts +6 -0
  79. package/src/parse/model/LeafNodeDefinition.ts +1 -0
  80. package/src/parse/model/NodeDefinition.ts +11 -3
  81. package/src/parse/model/RepeatDefinition.ts +8 -1
  82. package/src/parse/model/RootDefinition.ts +5 -5
  83. package/src/parse/model/nodeDefinitionMap.ts +1 -1
  84. package/dist/error/TemplatedNodeAttributeSerializationError.d.ts +0 -22
  85. package/dist/parse/model/RootAttributeDefinition.d.ts +0 -21
  86. package/src/error/TemplatedNodeAttributeSerializationError.ts +0 -24
  87. package/src/parse/model/RootAttributeDefinition.ts +0 -44
@@ -1,3 +1,5 @@
1
+ import type { GeneralChildNode } from '../client/hierarchy.ts';
2
+ import type { Attribute } from '../instance/Attribute.ts';
1
3
  import type { NamespaceDeclarationMap } from './names/NamespaceDeclarationMap.ts';
2
4
  import type { QualifiedName } from './names/QualifiedName.ts';
3
5
 
@@ -78,15 +80,6 @@ export const escapeXMLText = <Text extends string>(
78
80
  : (out as EscapedXMLText);
79
81
  };
80
82
 
81
- interface SerializableElementAttribute {
82
- serializeAttributeXML(): string;
83
- }
84
-
85
- interface ElementXMLSerializationOptions {
86
- readonly namespaceDeclarations?: NamespaceDeclarationMap;
87
- readonly attributes?: readonly SerializableElementAttribute[];
88
- }
89
-
90
83
  const serializeElementNamespaceDeclarationXML = (
91
84
  namespaceDeclarations?: NamespaceDeclarationMap
92
85
  ): string => {
@@ -103,24 +96,11 @@ const serializeElementNamespaceDeclarationXML = (
103
96
  .join('');
104
97
  };
105
98
 
106
- const serializeElementAttributeXML = (
107
- attributes?: readonly SerializableElementAttribute[]
108
- ): string => {
109
- if (attributes == null) {
110
- return '';
111
- }
112
-
113
- return attributes
114
- .map((attribute) => {
115
- return attribute.serializeAttributeXML();
116
- })
117
- .join('');
118
- };
119
-
120
99
  const serializeElementXML = (
121
100
  qualifiedName: QualifiedName,
122
101
  children: string,
123
- options: ElementXMLSerializationOptions = {}
102
+ attributes: string,
103
+ namespaceDeclarations?: NamespaceDeclarationMap
124
104
  ): string => {
125
105
  // See JSDoc for the `getPrefixedName` method. If we find we do actually need
126
106
  // custom element (subtree) prefix resolution, we'd uncomment the argument
@@ -133,11 +113,9 @@ const serializeElementXML = (
133
113
  const nodeName = qualifiedName.getPrefixedName(
134
114
  // options.namespaceDeclarations
135
115
  );
136
- const namespaceDeclarations = serializeElementNamespaceDeclarationXML(
137
- options.namespaceDeclarations
138
- );
139
- const attributes = serializeElementAttributeXML(options.attributes);
140
- const prefix = `<${nodeName}${namespaceDeclarations}${attributes}`;
116
+ const serializedNamespaceDeclarations =
117
+ serializeElementNamespaceDeclarationXML(namespaceDeclarations);
118
+ const prefix = `<${nodeName}${serializedNamespaceDeclarations}${attributes}`;
141
119
 
142
120
  if (children === '') {
143
121
  return `${prefix}/>`;
@@ -146,18 +124,36 @@ const serializeElementXML = (
146
124
  return `${prefix}>${children}</${nodeName}>`;
147
125
  };
148
126
 
127
+ export const serializeAttributeXML = (
128
+ qualifiedName: QualifiedName,
129
+ xmlValue: EscapedXMLText
130
+ ): string => {
131
+ const nodeName = qualifiedName.getPrefixedName();
132
+ return ` ${nodeName}="${xmlValue.normalize()}"`;
133
+ };
134
+
149
135
  export const serializeParentElementXML = (
150
136
  qualifiedName: QualifiedName,
151
- serializedChildren: readonly string[],
152
- options?: ElementXMLSerializationOptions
137
+ children: readonly GeneralChildNode[],
138
+ attributes: readonly Attribute[],
139
+ namespaceDeclarations?: NamespaceDeclarationMap
153
140
  ): string => {
154
- return serializeElementXML(qualifiedName, serializedChildren.join(''), options);
141
+ const serializedChildren = children.map((child) => child.instanceState.instanceXML).join('');
142
+ const serializedAttributes = attributes
143
+ .map((attribute) => attribute.instanceState.instanceXML)
144
+ .join('');
145
+ return serializeElementXML(
146
+ qualifiedName,
147
+ serializedChildren,
148
+ serializedAttributes,
149
+ namespaceDeclarations
150
+ );
155
151
  };
156
152
 
157
153
  export const serializeLeafElementXML = (
158
154
  qualifiedName: QualifiedName,
159
155
  xmlValue: EscapedXMLText,
160
- options?: ElementXMLSerializationOptions
156
+ namespaceDeclarations?: NamespaceDeclarationMap
161
157
  ): string => {
162
- return serializeElementXML(qualifiedName, xmlValue.normalize(), options);
158
+ return serializeElementXML(qualifiedName, xmlValue.normalize(), '', namespaceDeclarations);
163
159
  };
@@ -0,0 +1,58 @@
1
+ import { XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
+ import type { StaticAttribute } from '../../integration/xpath/static-dom/StaticAttribute.ts';
3
+ import {
4
+ NamespaceDeclarationMap,
5
+ type NamedNodeDefinition,
6
+ } from '../../lib/names/NamespaceDeclarationMap.ts';
7
+ import { QualifiedName } from '../../lib/names/QualifiedName.ts';
8
+ import { escapeXMLText, serializeAttributeXML } from '../../lib/xml-serialization.ts';
9
+ import type { BindDefinition } from './BindDefinition.ts';
10
+ import { NodeDefinition } from './NodeDefinition.ts';
11
+ import type { RootDefinition } from './RootDefinition.ts';
12
+
13
+ export class AttributeDefinition
14
+ extends NodeDefinition<'attribute'>
15
+ implements NamedNodeDefinition
16
+ {
17
+ private readonly serializedXML: string;
18
+
19
+ readonly value: string;
20
+ readonly type = 'attribute';
21
+ readonly namespaceDeclarations: NamespaceDeclarationMap;
22
+ readonly bodyElement = null;
23
+ readonly root: RootDefinition;
24
+ readonly isTranslated: boolean = false;
25
+ readonly parent = null;
26
+ readonly children = null;
27
+ readonly attributes = null;
28
+
29
+ readonly qualifiedName: QualifiedName;
30
+
31
+ constructor(
32
+ root: RootDefinition,
33
+ bind: BindDefinition,
34
+ readonly template: StaticAttribute
35
+ ) {
36
+ super(bind);
37
+
38
+ const { value } = template;
39
+
40
+ this.root = root;
41
+
42
+ this.value = value;
43
+ this.qualifiedName = template.qualifiedName;
44
+ this.namespaceDeclarations = new NamespaceDeclarationMap(this);
45
+
46
+ // We serialize namespace declarations separately
47
+ if (this.qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI) {
48
+ this.serializedXML = '';
49
+ } else {
50
+ const xmlValue = escapeXMLText(this.value, true);
51
+ this.serializedXML = serializeAttributeXML(this.qualifiedName, xmlValue);
52
+ }
53
+ }
54
+
55
+ serializeAttributeXML(): string {
56
+ return this.serializedXML;
57
+ }
58
+ }
@@ -2,8 +2,8 @@ import { XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
2
  import type { StaticAttribute } from '../../integration/xpath/static-dom/StaticAttribute.ts';
3
3
  import type { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
4
4
  import type { QualifiedName } from '../../lib/names/QualifiedName.ts';
5
- import { RootAttributeDefinition } from './RootAttributeDefinition.ts';
6
- import type { RootDefinition } from './RootDefinition.ts';
5
+ import { AttributeDefinition } from './AttributeDefinition.ts';
6
+ import type { ModelDefinition } from './ModelDefinition.ts';
7
7
 
8
8
  /**
9
9
  * @todo We should probably just distinguish these as separate `StaticNode`
@@ -14,12 +14,6 @@ const isNonNamespaceAttribute = (attribute: StaticAttribute) => {
14
14
  };
15
15
 
16
16
  /**
17
- * @todo This can be trivially expanded to a narrowly general case when we
18
- * prioritize work to
19
- * {@link https://github.com/getodk/web-forms/issues/285 | support attributes}
20
- * (as modeled form nodes on par with elements). It's been deferred here to
21
- * avoid expanding scope of an already fairly large yak shave.
22
- *
23
17
  * @todo There's a **much more expansive** general case just waiting for a good
24
18
  * opportuntity to prioritize it. E.g. a `NamedNodeMap<T>`, where T is any
25
19
  * generalized concept of a named node. This expansive generalization would have
@@ -29,17 +23,17 @@ const isNonNamespaceAttribute = (attribute: StaticAttribute) => {
29
23
  *
30
24
  * @see {@link QualifiedName} for more detail.
31
25
  */
32
- export class RootAttributeMap extends Map<QualifiedName, RootAttributeDefinition> {
33
- static from(root: RootDefinition, instanceNode: StaticElement) {
26
+ export class AttributeDefinitionMap extends Map<QualifiedName, AttributeDefinition> {
27
+ static from(model: ModelDefinition, instanceNode: StaticElement) {
34
28
  const nonNamespaceAttributes = instanceNode.attributes.filter(isNonNamespaceAttribute);
35
29
  const definitions = nonNamespaceAttributes.map((attribute) => {
36
- return new RootAttributeDefinition(root, attribute);
30
+ const bind = model.binds.getOrCreateBindDefinition(attribute.nodeset);
31
+ return new AttributeDefinition(model.root, bind, attribute);
37
32
  });
38
-
39
33
  return new this(definitions);
40
34
  }
41
35
 
42
- private constructor(definitions: readonly RootAttributeDefinition[]) {
36
+ private constructor(definitions: readonly AttributeDefinition[]) {
43
37
  super(
44
38
  definitions.map((attribute) => {
45
39
  return [attribute.qualifiedName, attribute];
@@ -3,8 +3,10 @@ import { NamespaceDeclarationMap } from '../../lib/names/NamespaceDeclarationMap
3
3
  import { QualifiedName } from '../../lib/names/QualifiedName.ts';
4
4
  import type { AnyBodyElementDefinition } from '../body/BodyDefinition.ts';
5
5
  import type { GroupElementDefinition } from '../body/GroupElementDefinition.ts';
6
+ import { AttributeDefinitionMap } from './AttributeDefinitionMap.ts';
6
7
  import type { BindDefinition } from './BindDefinition.ts';
7
8
  import { DescendentNodeDefinition } from './DescendentNodeDefinition.ts';
9
+ import type { ModelDefinition } from './ModelDefinition.ts';
8
10
  import type { ChildNodeDefinition, ParentNodeDefinition } from './NodeDefinition.ts';
9
11
 
10
12
  export class GroupDefinition extends DescendentNodeDefinition<
@@ -16,8 +18,10 @@ export class GroupDefinition extends DescendentNodeDefinition<
16
18
  readonly namespaceDeclarations: NamespaceDeclarationMap;
17
19
  readonly qualifiedName: QualifiedName;
18
20
  readonly children: readonly ChildNodeDefinition[];
21
+ readonly attributes: AttributeDefinitionMap;
19
22
 
20
23
  constructor(
24
+ model: ModelDefinition,
21
25
  parent: ParentNodeDefinition,
22
26
  bind: BindDefinition,
23
27
  bodyElement: AnyBodyElementDefinition | null,
@@ -37,6 +41,8 @@ export class GroupDefinition extends DescendentNodeDefinition<
37
41
  this.qualifiedName = template.qualifiedName;
38
42
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
39
43
  this.children = root.buildSubtree(this, template);
44
+
45
+ this.attributes = AttributeDefinitionMap.from(model, template);
40
46
  }
41
47
 
42
48
  toJSON() {
@@ -20,6 +20,7 @@ export class LeafNodeDefinition<V extends ValueType = ValueType>
20
20
  readonly namespaceDeclarations: NamespaceDeclarationMap;
21
21
  readonly qualifiedName: QualifiedName;
22
22
  readonly children = null;
23
+ readonly attributes = null;
23
24
 
24
25
  constructor(
25
26
  parent: ParentNodeDefinition,
@@ -1,3 +1,4 @@
1
+ import type { StaticAttribute } from '../../integration/xpath/static-dom/StaticAttribute.ts';
1
2
  import type { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
2
3
  import type {
3
4
  NamedSubtreeDefinition,
@@ -6,6 +7,8 @@ import type {
6
7
  import type { QualifiedName } from '../../lib/names/QualifiedName.ts';
7
8
  import type { AnyBodyElementDefinition } from '../body/BodyDefinition.ts';
8
9
  import type { RepeatElementDefinition } from '../body/RepeatElementDefinition.ts';
10
+ import type { AttributeDefinition } from './AttributeDefinition.ts';
11
+ import type { AttributeDefinitionMap } from './AttributeDefinitionMap.ts';
9
12
  import type { BindDefinition } from './BindDefinition.ts';
10
13
  import type { GroupDefinition } from './GroupDefinition.ts';
11
14
  import type { LeafNodeDefinition } from './LeafNodeDefinition.ts';
@@ -45,13 +48,16 @@ export type GroupNodeType = 'group';
45
48
  */
46
49
  export type LeafNodeType = 'leaf-node';
47
50
 
51
+ export type AttributeNodeType = 'attribute';
52
+
48
53
  // prettier-ignore
49
54
  export type NodeDefinitionType =
50
55
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
51
56
  | RootNodeType
52
57
  | RepeatType
53
58
  | GroupNodeType
54
- | LeafNodeType;
59
+ | LeafNodeType
60
+ | AttributeNodeType;
55
61
 
56
62
  // prettier-ignore
57
63
  export type ParentNodeDefinition =
@@ -76,8 +82,9 @@ export abstract class NodeDefinition<Type extends NodeDefinitionType>
76
82
  abstract readonly isTranslated: boolean;
77
83
  abstract readonly root: RootDefinition;
78
84
  abstract readonly parent: ParentNodeDefinition | null;
79
- abstract readonly template: StaticElement;
85
+ abstract readonly template: StaticAttribute | StaticElement;
80
86
  abstract readonly children: readonly ChildNodeDefinition[] | null;
87
+ abstract readonly attributes: AttributeDefinitionMap | null;
81
88
 
82
89
  readonly nodeset: string;
83
90
 
@@ -92,4 +99,5 @@ export type AnyNodeDefinition =
92
99
  | RootDefinition
93
100
  | AnyRepeatDefinition
94
101
  | GroupDefinition
95
- | LeafNodeDefinition;
102
+ | LeafNodeDefinition
103
+ | AttributeDefinition;
@@ -19,9 +19,11 @@ import type { NamespaceURL } from '../../lib/names/NamespaceURL.ts';
19
19
  import type { QualifiedName, QualifiedNameSource } from '../../lib/names/QualifiedName.ts';
20
20
  import type { RepeatElementDefinition } from '../body/RepeatElementDefinition.ts';
21
21
  import { RepeatCountControlExpression } from '../expression/RepeatCountControlExpression.ts';
22
+ import { AttributeDefinitionMap } from './AttributeDefinitionMap.ts';
22
23
  import type { BindDefinition } from './BindDefinition.ts';
23
24
  import { DescendentNodeDefinition } from './DescendentNodeDefinition.ts';
24
25
  import type { GroupDefinition } from './GroupDefinition.ts';
26
+ import type { ModelDefinition } from './ModelDefinition.ts';
25
27
  import type { ChildNodeDefinition, ParentNodeDefinition } from './NodeDefinition.ts';
26
28
  import type { RootDefinition } from './RootDefinition.ts';
27
29
 
@@ -313,18 +315,20 @@ export interface UncontrolledRepeatDefinition extends RepeatDefinition {
313
315
  */
314
316
  export class RepeatDefinition extends DescendentNodeDefinition<'repeat', RepeatElementDefinition> {
315
317
  static from(
318
+ model: ModelDefinition,
316
319
  parent: ParentNodeDefinition,
317
320
  bind: BindDefinition,
318
321
  bodyElement: RepeatElementDefinition,
319
322
  instanceNodes: RepeatInstanceNodes
320
323
  ): AnyRepeatDefinition;
321
324
  static from(
325
+ model: ModelDefinition,
322
326
  parent: ParentNodeDefinition,
323
327
  bind: BindDefinition,
324
328
  bodyElement: RepeatElementDefinition,
325
329
  instanceNodes: RepeatInstanceNodes
326
330
  ): RepeatDefinition {
327
- return new this(parent, bind, bodyElement, instanceNodes);
331
+ return new this(model, parent, bind, bodyElement, instanceNodes);
328
332
  }
329
333
 
330
334
  readonly type = 'repeat';
@@ -333,8 +337,10 @@ export class RepeatDefinition extends DescendentNodeDefinition<'repeat', RepeatE
333
337
  readonly template: StaticElement;
334
338
  readonly namespaceDeclarations: NamespaceDeclarationMap;
335
339
  readonly qualifiedName: QualifiedName;
340
+ readonly attributes: AttributeDefinitionMap;
336
341
 
337
342
  private constructor(
343
+ model: ModelDefinition,
338
344
  parent: ParentNodeDefinition,
339
345
  bind: BindDefinition,
340
346
  bodyElement: RepeatElementDefinition,
@@ -353,6 +359,7 @@ export class RepeatDefinition extends DescendentNodeDefinition<'repeat', RepeatE
353
359
  this.children = root.buildSubtree(self, template);
354
360
 
355
361
  const initialCount = this.omitTemplate(instanceNodes).length;
362
+ this.attributes = AttributeDefinitionMap.from(model, template);
356
363
 
357
364
  this.count = RepeatCountControlExpression.from(bodyElement, initialCount);
358
365
  }
@@ -3,6 +3,7 @@ import { NamespaceDeclarationMap } from '../../lib/names/NamespaceDeclarationMap
3
3
  import { QualifiedName } from '../../lib/names/QualifiedName.ts';
4
4
  import type { BodyClassList } from '../body/BodyDefinition.ts';
5
5
  import type { XFormDefinition } from '../XFormDefinition.ts';
6
+ import { AttributeDefinitionMap } from './AttributeDefinitionMap.ts';
6
7
  import { GroupDefinition } from './GroupDefinition.ts';
7
8
  import { LeafNodeDefinition } from './LeafNodeDefinition.ts';
8
9
  import type { ModelDefinition } from './ModelDefinition.ts';
@@ -11,7 +12,6 @@ import { NodeDefinition } from './NodeDefinition.ts';
11
12
  import { NoteNodeDefinition } from './NoteNodeDefinition.ts';
12
13
  import { RangeNodeDefinition } from './RangeNodeDefinition.ts';
13
14
  import { RepeatDefinition } from './RepeatDefinition.ts';
14
- import { RootAttributeMap } from './RootAttributeMap.ts';
15
15
  import type { SubmissionDefinition } from './SubmissionDefinition.ts';
16
16
 
17
17
  export class RootDefinition extends NodeDefinition<'root'> {
@@ -22,7 +22,7 @@ export class RootDefinition extends NodeDefinition<'root'> {
22
22
  readonly parent = null;
23
23
  readonly template: StaticElement;
24
24
  readonly namespaceDeclarations: NamespaceDeclarationMap;
25
- readonly attributes: RootAttributeMap;
25
+ readonly attributes: AttributeDefinitionMap;
26
26
  readonly children: readonly ChildNodeDefinition[];
27
27
 
28
28
  readonly isTranslated = false;
@@ -51,7 +51,7 @@ export class RootDefinition extends NodeDefinition<'root'> {
51
51
 
52
52
  this.qualifiedName = qualifiedName;
53
53
  this.template = template;
54
- this.attributes = RootAttributeMap.from(this, template);
54
+ this.attributes = AttributeDefinitionMap.from(model, template);
55
55
  this.namespaceDeclarations = new NamespaceDeclarationMap(this);
56
56
  this.children = this.buildSubtree(this, template);
57
57
  }
@@ -87,7 +87,7 @@ export class RootDefinition extends NodeDefinition<'root'> {
87
87
  const [firstChild, ...restChildren] = children;
88
88
 
89
89
  if (bodyElement?.type === 'repeat') {
90
- return RepeatDefinition.from(parent, bind, bodyElement, children);
90
+ return RepeatDefinition.from(model, parent, bind, bodyElement, children);
91
91
  }
92
92
 
93
93
  if (restChildren.length) {
@@ -107,7 +107,7 @@ export class RootDefinition extends NodeDefinition<'root'> {
107
107
  );
108
108
  }
109
109
 
110
- return new GroupDefinition(parent, bind, bodyElement, element);
110
+ return new GroupDefinition(model, parent, bind, bodyElement, element);
111
111
  });
112
112
  }
113
113
 
@@ -16,7 +16,7 @@ const collectDefinitions = (
16
16
 
17
17
  result.set(nodeset, definition);
18
18
 
19
- if (definition.type === 'leaf-node') {
19
+ if (definition.type === 'leaf-node' || definition.type === 'attribute') {
20
20
  return result;
21
21
  }
22
22
 
@@ -1,22 +0,0 @@
1
- /**
2
- * This error class is intended as a common point of reference for all of the
3
- * related interfaces and implementation where we've deferred two concerns:
4
- *
5
- * 1. Support for attributes on instance nodes (which may be bound in a form's
6
- * model and/or may be expected to preserve model-defined defaults)
7
- * 2. Present lack of logic to treat a `jr:template` attribute as a special
8
- * case: whereas in the general case we would expect to pass through a
9
- * form/model-defined attribute, we expect to specifically **omit**
10
- * `jr:template` from repeat instances derived from any of form's
11
- * explicitly-defined repeat templates
12
- *
13
- * Addressing #1 is (now) a prerequisite to addressing #2, and it is also a
14
- * prerequisite for #2's unaddressed status to _become meaningfully observable
15
- * and problematic_.
16
- *
17
- * By introducing this error at a point where a change in #1's status is likely
18
- * to be implicated, we're also likely to be reminded to address #2 in tandem.
19
- */
20
- export declare class TemplatedNodeAttributeSerializationError extends Error {
21
- constructor();
22
- }
@@ -1,21 +0,0 @@
1
- import { NamedNodeDefinition } from '../../lib/names/NamespaceDeclarationMap.ts';
2
- import { QualifiedName } from '../../lib/names/QualifiedName.ts';
3
- import { RootDefinition } from './RootDefinition.ts';
4
- interface RootAttributeSource {
5
- readonly qualifiedName: QualifiedName;
6
- readonly value: string;
7
- }
8
- /**
9
- * @todo This class is named and typed to emphasize its intentionally narrow
10
- * usage and purpose. It **intentionally** avoids addressing the much broader
11
- * set of concerns around modeling attributes in primary instance/submissions.
12
- */
13
- export declare class RootAttributeDefinition implements NamedNodeDefinition {
14
- private readonly serializedXML;
15
- readonly parent: RootDefinition;
16
- readonly qualifiedName: QualifiedName;
17
- readonly value: string;
18
- constructor(root: RootDefinition, source: RootAttributeSource);
19
- serializeAttributeXML(): string;
20
- }
21
- export {};
@@ -1,24 +0,0 @@
1
- /**
2
- * This error class is intended as a common point of reference for all of the
3
- * related interfaces and implementation where we've deferred two concerns:
4
- *
5
- * 1. Support for attributes on instance nodes (which may be bound in a form's
6
- * model and/or may be expected to preserve model-defined defaults)
7
- * 2. Present lack of logic to treat a `jr:template` attribute as a special
8
- * case: whereas in the general case we would expect to pass through a
9
- * form/model-defined attribute, we expect to specifically **omit**
10
- * `jr:template` from repeat instances derived from any of form's
11
- * explicitly-defined repeat templates
12
- *
13
- * Addressing #1 is (now) a prerequisite to addressing #2, and it is also a
14
- * prerequisite for #2's unaddressed status to _become meaningfully observable
15
- * and problematic_.
16
- *
17
- * By introducing this error at a point where a change in #1's status is likely
18
- * to be implicated, we're also likely to be reminded to address #2 in tandem.
19
- */
20
- export class TemplatedNodeAttributeSerializationError extends Error {
21
- constructor() {
22
- super('Template attribute omission not implemented');
23
- }
24
- }
@@ -1,44 +0,0 @@
1
- import { XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
- import type { NamedNodeDefinition } from '../../lib/names/NamespaceDeclarationMap.ts';
3
- import { QualifiedName } from '../../lib/names/QualifiedName.ts';
4
- import { escapeXMLText } from '../../lib/xml-serialization.ts';
5
- import type { RootDefinition } from './RootDefinition.ts';
6
-
7
- interface RootAttributeSource {
8
- readonly qualifiedName: QualifiedName;
9
- readonly value: string;
10
- }
11
-
12
- /**
13
- * @todo This class is named and typed to emphasize its intentionally narrow
14
- * usage and purpose. It **intentionally** avoids addressing the much broader
15
- * set of concerns around modeling attributes in primary instance/submissions.
16
- */
17
- export class RootAttributeDefinition implements NamedNodeDefinition {
18
- private readonly serializedXML: string;
19
-
20
- readonly parent: RootDefinition;
21
- readonly qualifiedName: QualifiedName;
22
- readonly value: string;
23
-
24
- constructor(root: RootDefinition, source: RootAttributeSource) {
25
- const { qualifiedName, value } = source;
26
-
27
- this.parent = root;
28
- this.qualifiedName = qualifiedName;
29
- this.value = value;
30
-
31
- // We serialize namespace declarations separately
32
- if (qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI) {
33
- this.serializedXML = '';
34
- } else {
35
- const nodeName = qualifiedName.getPrefixedName();
36
-
37
- this.serializedXML = ` ${nodeName}="${escapeXMLText(value, true)}"`;
38
- }
39
- }
40
-
41
- serializeAttributeXML(): string {
42
- return this.serializedXML;
43
- }
44
- }