@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.
- package/dist/client/AttributeNode.d.ts +53 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/node-types.d.ts +1 -1
- package/dist/client/validation.d.ts +7 -1
- package/dist/index.js +436 -164
- package/dist/index.js.map +1 -1
- package/dist/instance/Attribute.d.ts +58 -0
- package/dist/instance/Group.d.ts +4 -0
- package/dist/instance/PrimaryInstance.d.ts +4 -0
- package/dist/instance/Root.d.ts +4 -0
- package/dist/instance/UploadControl.d.ts +4 -0
- package/dist/instance/abstract/InstanceNode.d.ts +7 -4
- package/dist/instance/abstract/ValueNode.d.ts +1 -0
- package/dist/instance/attachments/buildAttributes.d.ts +3 -0
- package/dist/instance/hierarchy.d.ts +2 -1
- package/dist/instance/internal-api/AttributeContext.d.ts +29 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.d.ts +16 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableParentNode.d.ts +2 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.d.ts +2 -2
- package/dist/instance/repeat/BaseRepeatRange.d.ts +5 -0
- package/dist/instance/repeat/RepeatInstance.d.ts +4 -2
- package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +2 -2
- package/dist/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.d.ts +3 -0
- package/dist/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.d.ts +0 -3
- package/dist/lib/names/NamespaceDeclarationMap.d.ts +1 -1
- package/dist/lib/reactivity/createAttributeState.d.ts +16 -0
- package/dist/lib/reactivity/createAttributeValueState.d.ts +15 -0
- package/dist/lib/xml-serialization.d.ts +5 -9
- package/dist/parse/XFormDOM.d.ts +1 -1
- package/dist/parse/model/AttributeDefinition.d.ts +22 -0
- package/dist/parse/model/{RootAttributeMap.d.ts → AttributeDefinitionMap.d.ts} +4 -10
- package/dist/parse/model/GroupDefinition.d.ts +4 -1
- package/dist/parse/model/LeafNodeDefinition.d.ts +1 -0
- package/dist/parse/model/NodeDefinition.d.ts +8 -3
- package/dist/parse/model/RepeatDefinition.d.ts +4 -1
- package/dist/parse/model/RootDefinition.d.ts +2 -2
- package/dist/solid.js +436 -164
- package/dist/solid.js.map +1 -1
- package/package.json +5 -5
- package/src/client/AttributeNode.ts +62 -0
- package/src/client/index.ts +1 -0
- package/src/client/node-types.ts +1 -0
- package/src/client/validation.ts +9 -1
- package/src/instance/Attribute.ts +164 -0
- package/src/instance/Group.ts +16 -0
- package/src/instance/InputControl.ts +1 -0
- package/src/instance/ModelValue.ts +1 -0
- package/src/instance/Note.ts +1 -0
- package/src/instance/PrimaryInstance.ts +17 -0
- package/src/instance/RangeControl.ts +1 -0
- package/src/instance/RankControl.ts +1 -0
- package/src/instance/Root.ts +16 -0
- package/src/instance/SelectControl.ts +1 -0
- package/src/instance/TriggerControl.ts +1 -0
- package/src/instance/UploadControl.ts +14 -0
- package/src/instance/abstract/DescendantNode.ts +5 -1
- package/src/instance/abstract/InstanceNode.ts +6 -3
- package/src/instance/abstract/ValueNode.ts +1 -0
- package/src/instance/attachments/buildAttributes.ts +8 -0
- package/src/instance/hierarchy.ts +3 -1
- package/src/instance/internal-api/AttributeContext.ts +34 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.ts +19 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableParentNode.ts +2 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.ts +2 -3
- package/src/instance/repeat/BaseRepeatRange.ts +14 -0
- package/src/instance/repeat/RepeatInstance.ts +14 -5
- package/src/integration/xpath/adapter/XFormsXPathNode.ts +3 -1
- package/src/lib/client-reactivity/instance-state/createAttributeNodeInstanceState.ts +16 -0
- package/src/lib/client-reactivity/instance-state/createParentNodeInstanceState.ts +5 -5
- package/src/lib/client-reactivity/instance-state/createRootInstanceState.ts +6 -9
- package/src/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.ts +5 -15
- package/src/lib/names/NamespaceDeclarationMap.ts +1 -1
- package/src/lib/reactivity/createAttributeState.ts +51 -0
- package/src/lib/reactivity/createAttributeValueState.ts +189 -0
- package/src/lib/xml-serialization.ts +30 -34
- package/src/parse/model/AttributeDefinition.ts +58 -0
- package/src/parse/model/{RootAttributeMap.ts → AttributeDefinitionMap.ts} +7 -13
- package/src/parse/model/GroupDefinition.ts +6 -0
- package/src/parse/model/LeafNodeDefinition.ts +1 -0
- package/src/parse/model/NodeDefinition.ts +11 -3
- package/src/parse/model/RepeatDefinition.ts +8 -1
- package/src/parse/model/RootDefinition.ts +5 -5
- package/src/parse/model/nodeDefinitionMap.ts +1 -1
- package/dist/error/TemplatedNodeAttributeSerializationError.d.ts +0 -22
- package/dist/parse/model/RootAttributeDefinition.d.ts +0 -21
- package/src/error/TemplatedNodeAttributeSerializationError.ts +0 -24
- 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
|
-
|
|
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
|
|
137
|
-
|
|
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
|
-
|
|
152
|
-
|
|
137
|
+
children: readonly GeneralChildNode[],
|
|
138
|
+
attributes: readonly Attribute[],
|
|
139
|
+
namespaceDeclarations?: NamespaceDeclarationMap
|
|
153
140
|
): string => {
|
|
154
|
-
|
|
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
|
-
|
|
156
|
+
namespaceDeclarations?: NamespaceDeclarationMap
|
|
161
157
|
): string => {
|
|
162
|
-
return serializeElementXML(qualifiedName, xmlValue.normalize(),
|
|
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 {
|
|
6
|
-
import type {
|
|
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
|
|
33
|
-
static from(
|
|
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
|
-
|
|
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
|
|
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:
|
|
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 =
|
|
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
|
|
|
@@ -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
|
-
}
|