@getodk/xforms-engine 0.1.1 → 0.3.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 (228) hide show
  1. package/dist/body/BodyDefinition.d.ts +24 -7
  2. package/dist/body/BodyElementDefinition.d.ts +4 -3
  3. package/dist/body/RepeatElementDefinition.d.ts +19 -0
  4. package/dist/body/appearance/inputAppearanceParser.d.ts +4 -0
  5. package/dist/body/appearance/selectAppearanceParser.d.ts +4 -0
  6. package/dist/body/appearance/structureElementAppearanceParser.d.ts +4 -0
  7. package/dist/body/control/ControlDefinition.d.ts +4 -2
  8. package/dist/body/control/InputDefinition.d.ts +5 -0
  9. package/dist/body/control/select/ItemDefinition.d.ts +2 -2
  10. package/dist/body/control/select/ItemsetDefinition.d.ts +5 -4
  11. package/dist/body/control/select/SelectDefinition.d.ts +11 -1
  12. package/dist/body/group/BaseGroupDefinition.d.ts +4 -9
  13. package/dist/body/group/PresentationGroupDefinition.d.ts +1 -1
  14. package/dist/client/BaseNode.d.ts +74 -3
  15. package/dist/client/GroupNode.d.ts +7 -2
  16. package/dist/client/ModelValueNode.d.ts +37 -0
  17. package/dist/client/NodeAppearances.d.ts +15 -0
  18. package/dist/client/NoteNode.d.ts +53 -0
  19. package/dist/client/RootNode.d.ts +21 -0
  20. package/dist/client/SelectNode.d.ts +8 -3
  21. package/dist/client/StringNode.d.ts +8 -3
  22. package/dist/client/SubtreeNode.d.ts +3 -0
  23. package/dist/client/TextRange.d.ts +85 -2
  24. package/dist/client/constants.d.ts +9 -0
  25. package/dist/client/hierarchy.d.ts +14 -9
  26. package/dist/client/node-types.d.ts +2 -1
  27. package/dist/client/{RepeatRangeNode.d.ts → repeat/BaseRepeatRangeNode.d.ts} +19 -15
  28. package/dist/client/{RepeatInstanceNode.d.ts → repeat/RepeatInstanceNode.d.ts} +11 -7
  29. package/dist/client/repeat/RepeatRangeControlledNode.d.ts +19 -0
  30. package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +20 -0
  31. package/dist/client/validation.d.ts +163 -0
  32. package/dist/expression/DependentExpression.d.ts +12 -8
  33. package/dist/index.d.ts +9 -4
  34. package/dist/index.js +3173 -960
  35. package/dist/index.js.map +1 -1
  36. package/dist/instance/Group.d.ts +6 -4
  37. package/dist/instance/ModelValue.d.ts +40 -0
  38. package/dist/instance/Note.d.ts +42 -0
  39. package/dist/instance/Root.d.ts +10 -23
  40. package/dist/instance/SelectField.d.ts +12 -6
  41. package/dist/instance/StringField.d.ts +13 -7
  42. package/dist/instance/Subtree.d.ts +3 -1
  43. package/dist/instance/abstract/DescendantNode.d.ts +16 -9
  44. package/dist/instance/abstract/InstanceNode.d.ts +28 -29
  45. package/dist/instance/hierarchy.d.ts +10 -5
  46. package/dist/instance/internal-api/EvaluationContext.d.ts +5 -4
  47. package/dist/instance/internal-api/ValidationContext.d.ts +21 -0
  48. package/dist/instance/internal-api/ValueContext.d.ts +2 -2
  49. package/dist/instance/repeat/BaseRepeatRange.d.ts +160 -0
  50. package/dist/instance/{RepeatInstance.d.ts → repeat/RepeatInstance.d.ts} +38 -13
  51. package/dist/instance/repeat/RepeatRangeControlled.d.ts +16 -0
  52. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +35 -0
  53. package/dist/instance/text/TextRange.d.ts +4 -4
  54. package/dist/lib/TokenListParser.d.ts +84 -0
  55. package/dist/lib/dom/query.d.ts +5 -0
  56. package/dist/lib/reactivity/createComputedExpression.d.ts +6 -1
  57. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +5 -0
  58. package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +2 -1
  59. package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +1 -1
  60. package/dist/lib/reactivity/node-state/createSpecifiedState.d.ts +1 -1
  61. package/dist/lib/reactivity/text/createFieldHint.d.ts +3 -3
  62. package/dist/lib/reactivity/text/createNodeLabel.d.ts +2 -2
  63. package/dist/lib/reactivity/text/createNoteText.d.ts +25 -0
  64. package/dist/lib/reactivity/text/createTextRange.d.ts +5 -7
  65. package/dist/lib/reactivity/validation/createAggregatedViolations.d.ts +9 -0
  66. package/dist/lib/reactivity/validation/createValidation.d.ts +18 -0
  67. package/dist/model/BindDefinition.d.ts +4 -2
  68. package/dist/model/BindElement.d.ts +1 -0
  69. package/dist/model/DescendentNodeDefinition.d.ts +1 -2
  70. package/dist/model/{ValueNodeDefinition.d.ts → LeafNodeDefinition.d.ts} +3 -4
  71. package/dist/model/NodeDefinition.d.ts +16 -16
  72. package/dist/model/RepeatInstanceDefinition.d.ts +5 -6
  73. package/dist/model/RepeatRangeDefinition.d.ts +30 -0
  74. package/dist/model/RepeatTemplateDefinition.d.ts +6 -7
  75. package/dist/model/RootDefinition.d.ts +3 -1
  76. package/dist/model/SubtreeDefinition.d.ts +2 -2
  77. package/dist/parse/NoteNodeDefinition.d.ts +31 -0
  78. package/dist/parse/expression/RepeatCountControlExpression.d.ts +19 -0
  79. package/dist/parse/text/HintDefinition.d.ts +9 -0
  80. package/dist/parse/text/ItemLabelDefinition.d.ts +9 -0
  81. package/dist/parse/text/ItemsetLabelDefinition.d.ts +13 -0
  82. package/dist/parse/text/LabelDefinition.d.ts +15 -0
  83. package/dist/parse/text/MessageDefinition.d.ts +15 -0
  84. package/dist/parse/text/OutputChunkDefinition.d.ts +8 -0
  85. package/dist/parse/text/ReferenceChunkDefinition.d.ts +8 -0
  86. package/dist/parse/text/StaticTextChunkDefinition.d.ts +10 -0
  87. package/dist/parse/text/TranslationChunkDefinition.d.ts +9 -0
  88. package/dist/parse/text/abstract/TextChunkDefinition.d.ts +18 -0
  89. package/dist/parse/text/abstract/TextElementDefinition.d.ts +23 -0
  90. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +35 -0
  91. package/dist/parse/xpath/dependency-analysis.d.ts +40 -0
  92. package/dist/parse/xpath/path-resolution.d.ts +70 -0
  93. package/dist/parse/xpath/predicate-analysis.d.ts +30 -0
  94. package/dist/parse/xpath/reference-parsing.d.ts +18 -0
  95. package/dist/parse/xpath/semantic-analysis.d.ts +98 -0
  96. package/dist/parse/xpath/syntax-traversal.d.ts +69 -0
  97. package/dist/solid.js +3174 -961
  98. package/dist/solid.js.map +1 -1
  99. package/package.json +14 -15
  100. package/src/XFormDOM.ts +81 -8
  101. package/src/body/BodyDefinition.ts +38 -23
  102. package/src/body/BodyElementDefinition.ts +4 -3
  103. package/src/body/RepeatElementDefinition.ts +58 -0
  104. package/src/body/appearance/inputAppearanceParser.ts +39 -0
  105. package/src/body/appearance/selectAppearanceParser.ts +38 -0
  106. package/src/body/appearance/structureElementAppearanceParser.ts +7 -0
  107. package/src/body/control/ControlDefinition.ts +8 -3
  108. package/src/body/control/InputDefinition.ts +13 -0
  109. package/src/body/control/select/ItemDefinition.ts +3 -3
  110. package/src/body/control/select/ItemsetDefinition.ts +29 -12
  111. package/src/body/control/select/ItemsetNodesetExpression.ts +1 -1
  112. package/src/body/control/select/SelectDefinition.ts +14 -5
  113. package/src/body/group/BaseGroupDefinition.ts +14 -51
  114. package/src/body/group/PresentationGroupDefinition.ts +1 -1
  115. package/src/client/BaseNode.ts +82 -8
  116. package/src/client/GroupNode.ts +8 -2
  117. package/src/client/ModelValueNode.ts +40 -0
  118. package/src/client/NodeAppearances.ts +22 -0
  119. package/src/client/NoteNode.ts +74 -0
  120. package/src/client/README.md +1 -0
  121. package/src/client/RootNode.ts +24 -0
  122. package/src/client/SelectNode.ts +9 -3
  123. package/src/client/StringNode.ts +9 -3
  124. package/src/client/SubtreeNode.ts +3 -0
  125. package/src/client/TextRange.ts +99 -2
  126. package/src/client/constants.ts +10 -0
  127. package/src/client/hierarchy.ts +30 -14
  128. package/src/client/node-types.ts +8 -1
  129. package/src/client/{RepeatRangeNode.ts → repeat/BaseRepeatRangeNode.ts} +20 -17
  130. package/src/client/{RepeatInstanceNode.ts → repeat/RepeatInstanceNode.ts} +13 -7
  131. package/src/client/repeat/RepeatRangeControlledNode.ts +20 -0
  132. package/src/client/repeat/RepeatRangeUncontrolledNode.ts +21 -0
  133. package/src/client/validation.ts +199 -0
  134. package/src/expression/DependentExpression.ts +45 -27
  135. package/src/index.ts +15 -8
  136. package/src/instance/Group.ts +24 -13
  137. package/src/instance/ModelValue.ts +104 -0
  138. package/src/instance/Note.ts +142 -0
  139. package/src/instance/Root.ts +29 -67
  140. package/src/instance/SelectField.ts +35 -13
  141. package/src/instance/StringField.ts +40 -13
  142. package/src/instance/Subtree.ts +19 -10
  143. package/src/instance/abstract/DescendantNode.ts +50 -49
  144. package/src/instance/abstract/InstanceNode.ts +89 -92
  145. package/src/instance/children.ts +47 -10
  146. package/src/instance/hierarchy.ts +21 -2
  147. package/src/instance/index.ts +1 -1
  148. package/src/instance/internal-api/EvaluationContext.ts +5 -6
  149. package/src/instance/internal-api/ValidationContext.ts +23 -0
  150. package/src/instance/internal-api/ValueContext.ts +2 -2
  151. package/src/instance/repeat/BaseRepeatRange.ts +347 -0
  152. package/src/instance/{RepeatInstance.ts → repeat/RepeatInstance.ts} +85 -36
  153. package/src/instance/repeat/RepeatRangeControlled.ts +82 -0
  154. package/src/instance/repeat/RepeatRangeUncontrolled.ts +67 -0
  155. package/src/instance/text/TextRange.ts +10 -4
  156. package/src/lib/TokenListParser.ts +156 -0
  157. package/src/lib/dom/query.ts +13 -0
  158. package/src/lib/reactivity/createChildrenState.ts +51 -6
  159. package/src/lib/reactivity/createComputedExpression.ts +23 -25
  160. package/src/lib/reactivity/createNoteReadonlyThunk.ts +33 -0
  161. package/src/lib/reactivity/createSelectItems.ts +25 -20
  162. package/src/lib/reactivity/createValueState.ts +6 -6
  163. package/src/lib/reactivity/materializeCurrentStateChildren.ts +3 -1
  164. package/src/lib/reactivity/node-state/createSharedNodeState.ts +1 -1
  165. package/src/lib/reactivity/text/createFieldHint.ts +9 -7
  166. package/src/lib/reactivity/text/createNodeLabel.ts +7 -5
  167. package/src/lib/reactivity/text/createNoteText.ts +72 -0
  168. package/src/lib/reactivity/text/createTextRange.ts +17 -90
  169. package/src/lib/reactivity/validation/createAggregatedViolations.ts +70 -0
  170. package/src/lib/reactivity/validation/createValidation.ts +196 -0
  171. package/src/model/BindComputation.ts +0 -4
  172. package/src/model/BindDefinition.ts +8 -6
  173. package/src/model/BindElement.ts +1 -0
  174. package/src/model/DescendentNodeDefinition.ts +1 -2
  175. package/src/model/{ValueNodeDefinition.ts → LeafNodeDefinition.ts} +5 -6
  176. package/src/model/ModelBindMap.ts +4 -0
  177. package/src/model/ModelDefinition.ts +1 -1
  178. package/src/model/NodeDefinition.ts +21 -21
  179. package/src/model/RepeatInstanceDefinition.ts +8 -13
  180. package/src/model/RepeatRangeDefinition.ts +94 -0
  181. package/src/model/RepeatTemplateDefinition.ts +10 -15
  182. package/src/model/RootDefinition.ts +12 -14
  183. package/src/model/SubtreeDefinition.ts +3 -3
  184. package/src/parse/NoteNodeDefinition.ts +70 -0
  185. package/src/parse/TODO.md +3 -0
  186. package/src/parse/expression/RepeatCountControlExpression.ts +44 -0
  187. package/src/parse/text/HintDefinition.ts +25 -0
  188. package/src/parse/text/ItemLabelDefinition.ts +25 -0
  189. package/src/parse/text/ItemsetLabelDefinition.ts +44 -0
  190. package/src/parse/text/LabelDefinition.ts +61 -0
  191. package/src/parse/text/MessageDefinition.ts +49 -0
  192. package/src/parse/text/OutputChunkDefinition.ts +25 -0
  193. package/src/parse/text/ReferenceChunkDefinition.ts +14 -0
  194. package/src/parse/text/StaticTextChunkDefinition.ts +19 -0
  195. package/src/parse/text/TranslationChunkDefinition.ts +38 -0
  196. package/src/parse/text/abstract/TextChunkDefinition.ts +38 -0
  197. package/src/parse/text/abstract/TextElementDefinition.ts +71 -0
  198. package/src/parse/text/abstract/TextRangeDefinition.ts +70 -0
  199. package/src/parse/xpath/dependency-analysis.ts +105 -0
  200. package/src/parse/xpath/path-resolution.ts +475 -0
  201. package/src/parse/xpath/predicate-analysis.ts +61 -0
  202. package/src/parse/xpath/reference-parsing.ts +90 -0
  203. package/src/parse/xpath/semantic-analysis.ts +466 -0
  204. package/src/parse/xpath/syntax-traversal.ts +129 -0
  205. package/dist/body/RepeatDefinition.d.ts +0 -16
  206. package/dist/body/group/RepeatGroupDefinition.d.ts +0 -13
  207. package/dist/body/text/HintDefinition.d.ts +0 -11
  208. package/dist/body/text/LabelDefinition.d.ts +0 -20
  209. package/dist/body/text/TextElementDefinition.d.ts +0 -33
  210. package/dist/body/text/TextElementOutputPart.d.ts +0 -13
  211. package/dist/body/text/TextElementPart.d.ts +0 -13
  212. package/dist/body/text/TextElementReferencePart.d.ts +0 -7
  213. package/dist/body/text/TextElementStaticPart.d.ts +0 -7
  214. package/dist/instance/RepeatRange.d.ts +0 -80
  215. package/dist/lib/xpath/analysis.d.ts +0 -23
  216. package/dist/model/RepeatSequenceDefinition.d.ts +0 -20
  217. package/src/body/RepeatDefinition.ts +0 -54
  218. package/src/body/group/RepeatGroupDefinition.ts +0 -91
  219. package/src/body/text/HintDefinition.ts +0 -26
  220. package/src/body/text/LabelDefinition.ts +0 -54
  221. package/src/body/text/TextElementDefinition.ts +0 -97
  222. package/src/body/text/TextElementOutputPart.ts +0 -27
  223. package/src/body/text/TextElementPart.ts +0 -31
  224. package/src/body/text/TextElementReferencePart.ts +0 -21
  225. package/src/body/text/TextElementStaticPart.ts +0 -26
  226. package/src/instance/RepeatRange.ts +0 -214
  227. package/src/lib/xpath/analysis.ts +0 -241
  228. package/src/model/RepeatSequenceDefinition.ts +0 -53
@@ -1,13 +0,0 @@
1
- import { AnyTextElementDefinition } from './TextElementDefinition.ts';
2
- import { TextElementPart } from './TextElementPart.ts';
3
-
4
- interface OutputElement extends Element {
5
- readonly localName: 'output';
6
- getAttribute(name: 'value'): string;
7
- getAttribute(name: string): string | null;
8
- }
9
- export declare class TextElementOutputPart extends TextElementPart<'output'> {
10
- static from(context: AnyTextElementDefinition, element: Element): TextElementOutputPart | null;
11
- protected constructor(context: AnyTextElementDefinition, element: OutputElement);
12
- }
13
- export {};
@@ -1,13 +0,0 @@
1
- import { DependentExpression } from '../../expression/DependentExpression.ts';
2
- import { AnyTextElementDefinition } from './TextElementDefinition.ts';
3
- import { TextElementOutputPart } from './TextElementOutputPart.ts';
4
- import { TextElementReferencePart } from './TextElementReferencePart.ts';
5
- import { TextElementStaticPart } from './TextElementStaticPart.ts';
6
-
7
- export type TextElementPartType = 'output' | 'reference' | 'static';
8
- export declare abstract class TextElementPart<Type extends TextElementPartType> extends DependentExpression<'string'> {
9
- readonly type: Type;
10
- readonly stringValue?: string;
11
- constructor(type: Type, context: AnyTextElementDefinition, expression: string);
12
- }
13
- export type AnyTextElementPart = TextElementOutputPart | TextElementReferencePart | TextElementStaticPart;
@@ -1,7 +0,0 @@
1
- import { AnyTextElementDefinition, TextElement } from './TextElementDefinition.ts';
2
- import { TextElementPart } from './TextElementPart.ts';
3
-
4
- export declare class TextElementReferencePart extends TextElementPart<'reference'> {
5
- static from(context: AnyTextElementDefinition, element: TextElement): TextElementReferencePart | null;
6
- protected constructor(context: AnyTextElementDefinition, expression: string);
7
- }
@@ -1,7 +0,0 @@
1
- import { AnyTextElementDefinition } from './TextElementDefinition.ts';
2
- import { TextElementPart } from './TextElementPart.ts';
3
-
4
- export declare class TextElementStaticPart extends TextElementPart<'static'> {
5
- readonly stringValue: string;
6
- constructor(context: AnyTextElementDefinition, node: Text);
7
- }
@@ -1,80 +0,0 @@
1
- import { Accessor } from 'solid-js';
2
- import { RepeatRangeNode } from '../client/RepeatRangeNode.ts';
3
- import { MaterializedChildren } from '../lib/reactivity/materializeCurrentStateChildren.ts';
4
- import { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
5
- import { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
6
- import { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
7
- import { RepeatSequenceDefinition } from '../model/RepeatSequenceDefinition.ts';
8
- import { RepeatDefinition, RepeatInstance } from './RepeatInstance.ts';
9
- import { Root } from './Root.ts';
10
- import { DescendantNodeSharedStateSpec, DescendantNode } from './abstract/DescendantNode.ts';
11
- import { GeneralParentNode } from './hierarchy.ts';
12
- import { NodeID } from './identity.ts';
13
- import { EvaluationContext } from './internal-api/EvaluationContext.ts';
14
- import { SubscribableDependency } from './internal-api/SubscribableDependency.ts';
15
- import { TextRange } from './text/TextRange.ts';
16
-
17
- interface RepeatRangeStateSpec extends DescendantNodeSharedStateSpec {
18
- readonly hint: null;
19
- readonly label: Accessor<TextRange<'label'> | null>;
20
- readonly children: Accessor<readonly NodeID[]>;
21
- readonly valueOptions: null;
22
- readonly value: null;
23
- }
24
- export declare class RepeatRange extends DescendantNode<RepeatSequenceDefinition, RepeatRangeStateSpec, RepeatInstance> implements RepeatRangeNode, EvaluationContext, SubscribableDependency {
25
- /**
26
- * A repeat range doesn't have a corresponding primary instance element of its
27
- * own, and its instances are appended to the range's parent element. During
28
- * creation of the initial primary instance state and DOM trees, we _could_
29
- * reliably append all of the range's instances in order as the definition
30
- * tree is recursed. But that would fail to handle some instance addition
31
- * cases afterwards.
32
- *
33
- * Most notably, we need to know where in the primary instance tree to append
34
- * instances created for a range which is currently empty. As a lucky
35
- * coincidence, this need coincides with the ability to add instances at any
36
- * arbitrary index within the range. In each case, we can reference a primary
37
- * instance DOM node which will become the new instance's preceding sibling.
38
- * Where the range is empty, we use this {@link Comment} node (itself created
39
- * and appended during range initialization) in lieu of a nonexistent
40
- * preceding instance's {@link contextNode}.
41
- *
42
- * @todo We likely want to remove these during submission serialization.
43
- * @todo Can we use a
44
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/Range | DOM Range}
45
- * instead?
46
- */
47
- private readonly anchorNode;
48
- private readonly childrenState;
49
- protected readonly state: SharedNodeState<RepeatRangeStateSpec>;
50
- protected engineState: EngineState<RepeatRangeStateSpec>;
51
- readonly nodeType = "repeat-range";
52
- readonly currentState: MaterializedChildren<CurrentState<RepeatRangeStateSpec>, RepeatInstance>;
53
- constructor(parent: GeneralParentNode, definition: RepeatSequenceDefinition);
54
- private getLastIndex;
55
- protected initializeContextNode(parentContextNode: Element): Element;
56
- protected computeReference(parent: GeneralParentNode): string;
57
- getInstanceIndex(instance: RepeatInstance): number;
58
- addInstances(afterIndex?: number, count?: number, definition?: RepeatDefinition): Root;
59
- /**
60
- * Removes the {@link RepeatInstance}s corresponding to the specified range of
61
- * indexes, and then removes those repeat instances from the repeat range's
62
- * own children state in that order:
63
- *
64
- * 1. Identify the set of {@link RepeatInstance}s to be removed.
65
- *
66
- * 2. For each {@link RepeatInstance} pending removal, perform that node's
67
- * removal logic. @see {@link RepeatInstance.remove} for more detail.
68
- *
69
- * 3. Finalize update to the repeat range's own {@link childrenState},
70
- * omitting those {@link RepeatInstance}s which were removed.
71
- *
72
- * This ordering ensures a consistent representation of state is established
73
- * prior to any downstream reactive updates, and ensures that removed nodes'
74
- * reactivity is cleaned up.
75
- */
76
- removeInstances(startIndex: number, count?: number): Root;
77
- subscribe(): void;
78
- getChildren(): readonly RepeatInstance[];
79
- }
80
- export {};
@@ -1,23 +0,0 @@
1
- import { AnySyntaxNode } from '@getodk/xpath/static/grammar/SyntaxNode.js';
2
-
3
- export type SingleChildNode = Extract<AnySyntaxNode, {
4
- readonly children: readonly [AnySyntaxNode];
5
- }>;
6
- export declare const isItextFunctionCalled: (expression: string) => boolean;
7
- interface GetNodesetDependenciesOptions {
8
- readonly contextReference?: string | null;
9
- /**
10
- * @default false
11
- */
12
- readonly ignoreContextReference?: boolean;
13
- /**
14
- * Ignores location path sub-expressions whose full text is `null`. While this
15
- * is technically a valid relative name test step, it seems that real forms in
16
- * the wild use it as if XPath had an actual `null` token/value.
17
- *
18
- * @default true
19
- */
20
- readonly ignoreNullExpressions?: boolean;
21
- }
22
- export declare const getNodesetDependencies: (expression: string, options?: GetNodesetDependenciesOptions) => Set<string>;
23
- export {};
@@ -1,20 +0,0 @@
1
- import { RepeatGroupDefinition } from '../body/group/RepeatGroupDefinition.ts';
2
- import { BindDefinition } from './BindDefinition.ts';
3
- import { DescendentNodeDefinition } from './DescendentNodeDefinition.ts';
4
- import { NodeDefinition, ParentNodeDefinition } from './NodeDefinition.ts';
5
- import { RepeatInstanceDefinition } from './RepeatInstanceDefinition.ts';
6
- import { RepeatTemplateDefinition } from './RepeatTemplateDefinition.ts';
7
-
8
- export declare class RepeatSequenceDefinition extends DescendentNodeDefinition<'repeat-sequence', RepeatGroupDefinition> implements NodeDefinition<'repeat-sequence'> {
9
- static createTemplateElement(instanceElement: Element): Element;
10
- static createInstanceElement(templateElement: Element): Element;
11
- readonly type = "repeat-sequence";
12
- readonly template: RepeatTemplateDefinition;
13
- readonly children: null;
14
- readonly instances: RepeatInstanceDefinition[];
15
- readonly node: null;
16
- readonly nodeName: string;
17
- readonly defaultValue: null;
18
- constructor(parent: ParentNodeDefinition, bind: BindDefinition, bodyElement: RepeatGroupDefinition, modelNodes: readonly [Element, ...Element[]]);
19
- toJSON(): Omit<this, "toJSON" | "parent" | "bind" | "root" | "bodyElement">;
20
- }
@@ -1,54 +0,0 @@
1
- import { JAVAROSA_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
- import type { XFormDefinition } from '../XFormDefinition.ts';
3
- import type { BodyElementDefinitionArray } from './BodyDefinition.ts';
4
- import { BodyElementDefinition } from './BodyElementDefinition.ts';
5
- import type { RepeatGroupDefinition } from './group/RepeatGroupDefinition.ts';
6
-
7
- export class RepeatDefinition extends BodyElementDefinition<'repeat'> {
8
- override readonly category = 'structure';
9
- readonly type = 'repeat';
10
- override readonly reference: string;
11
-
12
- // TODO: this will fall into the growing category of non-`BindExpression`
13
- // cases which have roughly the same design story.
14
- readonly countExpression: string | null;
15
-
16
- readonly isFixedCount: boolean;
17
-
18
- readonly children: BodyElementDefinitionArray;
19
-
20
- constructor(
21
- form: XFormDefinition,
22
- readonly groupDefinition: RepeatGroupDefinition,
23
- element: Element
24
- ) {
25
- super(form, groupDefinition, element);
26
-
27
- const reference = element.getAttribute('nodeset');
28
-
29
- if (reference == null) {
30
- throw new Error('Invalid repeat: missing `nodeset` reference');
31
- }
32
-
33
- this.reference = reference;
34
- this.countExpression = element.getAttributeNS(JAVAROSA_NAMESPACE_URI, 'count');
35
- this.children = groupDefinition.getChildren(element);
36
-
37
- // Spec says this can be either `true()` or `false()`. That said, it
38
- // could also presumably be `true ( )` or whatever.
39
- const noAddRemove =
40
- element
41
- .getAttributeNS(JAVAROSA_NAMESPACE_URI, 'noAddRemove')
42
- ?.trim()
43
- .replaceAll(/\s+/g, '') ?? 'false()';
44
-
45
- // TODO: **probably** safe to disregard anything else?
46
- this.isFixedCount = noAddRemove === 'true()';
47
- }
48
-
49
- override toJSON() {
50
- const { form, groupDefinition, parent, ...rest } = this;
51
-
52
- return rest;
53
- }
54
- }
@@ -1,91 +0,0 @@
1
- import { getRepeatElement } from '../../lib/dom/query.ts';
2
- import type { XFormDefinition } from '../../XFormDefinition.ts';
3
- import type { BodyElementDefinitionArray, BodyElementParentContext } from '../BodyDefinition.ts';
4
- import { RepeatDefinition } from '../RepeatDefinition.ts';
5
- import { BaseGroupDefinition } from './BaseGroupDefinition.ts';
6
-
7
- /**
8
- * TODO: The `RepeatGroupDefinition`/`RepeatDefinition` types are currently
9
- * expected to always pair, mirroring the corresponding XForm structure, e.g.
10
- *
11
- * ```xml
12
- * <group ref="/root/rep"> <!-- RepeatGroupDefinition -->
13
- * <repeat nodeset="/root/rep" /> <!-- RepeatDefinition -->
14
- * </group>
15
- * ```
16
- *
17
- * This structure has already been a source of one bug (where a recursive walk
18
- * through a `BodyDefinition`'s descendants failed to reach the children of
19
- * `RepeatDefinition`s). It seems likely this will continue to be a footgun.
20
- * After some discussion with @lognaturel, I concluded that the pairing isn't
21
- * strictly necessary, as this should be considered invalid:
22
- *
23
- * ```xml
24
- * <group ref="/root/rep">
25
- * <repeat nodeset="/root/rep" />
26
- * <input ref="/root/rep/not-a-repeat-child" />
27
- * </group>
28
- * ```
29
- *
30
- * It **may** make sense to collapse these types in the future, but I've held
31
- * off, following another discussion with @lognaturel. There's some potential
32
- * for group/repeat labeling ambiguity.
33
- *
34
- * - The current design accommodates sharing a repeat-containing group's label
35
- * across multiple repeat instances, but
36
- * - The
37
- * {@link https://github.com/getodk/xforms-spec/blob/791753a09fabd3d64d8cb95776dc0cef71fa4446/_sections/60-repeats.md?plain=1#L46 | ODK XForms spec suggests}
38
- * a repeat's first group might be a better candidate
39
- *
40
- * Example of such a structure:
41
- *
42
- * ```xml
43
- * <group ref="/root/foo">
44
- * <label>Foo (outer label)</label>
45
- * <repeat nodeset="/root/foo">
46
- * <group>
47
- * <label>Foo (inner label)</label>
48
- * <!-- ... -->
49
- * </group>
50
- * </repeat>
51
- * </group>
52
- * ```
53
- */
54
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
55
- // @ts-ignore - All this so I could attach a JSDoc comment to something other
56
- // than the actual class...
57
- // eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars
58
- interface IgnoreMeIAmJustHereForTheJSDoc {}
59
-
60
- export class RepeatGroupDefinition extends BaseGroupDefinition<'repeat-group'> {
61
- static override isCompatible(localName: string, element: Element): boolean {
62
- return this.getGroupType(localName, element) === 'repeat-group';
63
- }
64
-
65
- readonly type = 'repeat-group';
66
-
67
- readonly repeat: RepeatDefinition;
68
-
69
- get repeatChildren(): BodyElementDefinitionArray {
70
- return this.repeat.children;
71
- }
72
-
73
- constructor(form: XFormDefinition, parent: BodyElementParentContext, element: Element) {
74
- // TODO: this has already been queried at least twice before reaching this
75
- // point!
76
- const repeat = getRepeatElement(element);
77
-
78
- // TODO: and as such, this should not happen
79
- if (repeat == null) {
80
- throw new Error('Invalid repeat-group');
81
- }
82
-
83
- super(form, parent, element);
84
-
85
- const repeatDefinition = new RepeatDefinition(form, this, repeat);
86
-
87
- this.repeat = repeatDefinition;
88
- }
89
- }
90
-
91
- export type RepeatGroupDefinitionClass = typeof RepeatGroupDefinition;
@@ -1,26 +0,0 @@
1
- import { getHintElement } from '../../lib/dom/query.ts';
2
- import type { XFormDefinition } from '../../XFormDefinition.ts';
3
- import type { AnyControlDefinition } from '../control/ControlDefinition.ts';
4
- import type { TextElement } from './TextElementDefinition.ts';
5
- import { TextElementDefinition } from './TextElementDefinition.ts';
6
-
7
- export interface HintElement extends TextElement {
8
- readonly localName: 'hint';
9
- }
10
-
11
- export class HintDefinition extends TextElementDefinition<'hint'> {
12
- static forElement(
13
- form: XFormDefinition,
14
- definition: AnyControlDefinition
15
- ): HintDefinition | null {
16
- const hintElement = getHintElement(definition.element);
17
-
18
- if (hintElement == null) {
19
- return null;
20
- }
21
-
22
- return new this(form, definition, hintElement);
23
- }
24
-
25
- readonly type = 'hint';
26
- }
@@ -1,54 +0,0 @@
1
- import { getLabelElement } from '../../lib/dom/query.ts';
2
- import type { XFormDefinition } from '../../XFormDefinition.ts';
3
- import type { AnyControlDefinition } from '../control/ControlDefinition.ts';
4
- import type { ItemDefinition } from '../control/select/ItemDefinition.ts';
5
- import type { ItemsetDefinition } from '../control/select/ItemsetDefinition.ts';
6
- import type { BaseGroupDefinition } from '../group/BaseGroupDefinition.ts';
7
- import type { TextElement, TextElementOwner } from './TextElementDefinition.ts';
8
- import { TextElementDefinition } from './TextElementDefinition.ts';
9
-
10
- export interface LabelElement extends TextElement {
11
- readonly localName: 'label';
12
- }
13
-
14
- type StaticLabelContext = Exclude<TextElementOwner, ItemsetDefinition>;
15
-
16
- export class LabelDefinition extends TextElementDefinition<'label'> {
17
- protected static staticDefinition(
18
- form: XFormDefinition,
19
- definition: StaticLabelContext
20
- ): LabelDefinition | null {
21
- const labelElement = getLabelElement(definition.element);
22
-
23
- if (labelElement == null) {
24
- return null;
25
- }
26
-
27
- return new this(form, definition, labelElement);
28
- }
29
-
30
- static forControl(form: XFormDefinition, control: AnyControlDefinition): LabelDefinition | null {
31
- return this.staticDefinition(form, control);
32
- }
33
-
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- static forGroup(form: XFormDefinition, group: BaseGroupDefinition<any>): LabelDefinition | null {
36
- return this.staticDefinition(form, group);
37
- }
38
-
39
- static forItem(form: XFormDefinition, item: ItemDefinition): LabelDefinition | null {
40
- return this.staticDefinition(form, item);
41
- }
42
-
43
- static forItemset(form: XFormDefinition, itemset: ItemsetDefinition): LabelDefinition | null {
44
- const labelElement = getLabelElement(itemset.element);
45
-
46
- if (labelElement == null) {
47
- return null;
48
- }
49
-
50
- return new this(form, itemset, labelElement);
51
- }
52
-
53
- readonly type = 'label';
54
- }
@@ -1,97 +0,0 @@
1
- import { isCommentNode, isElementNode, isTextNode } from '@getodk/common/lib/dom/predicates.ts';
2
- import type { XFormDefinition } from '../../XFormDefinition.ts';
3
- import { type AnyDependentExpression } from '../../expression/DependentExpression.ts';
4
- import type { AnyGroupElementDefinition } from '../BodyDefinition.ts';
5
- import { BodyElementDefinition } from '../BodyElementDefinition.ts';
6
- import type { InputDefinition } from '../control/InputDefinition.ts';
7
- import type { ItemDefinition } from '../control/select/ItemDefinition.ts';
8
- import type { ItemsetDefinition } from '../control/select/ItemsetDefinition.ts';
9
- import type { AnySelectDefinition } from '../control/select/SelectDefinition.ts';
10
- import { TextElementOutputPart } from './TextElementOutputPart.ts';
11
- import { TextElementReferencePart } from './TextElementReferencePart.ts';
12
- import { TextElementStaticPart } from './TextElementStaticPart.ts';
13
-
14
- export type TextElementType = 'hint' | 'label';
15
-
16
- export interface TextElement extends Element {
17
- readonly localName: TextElementType;
18
- }
19
-
20
- export type TextElementOwner =
21
- | AnyGroupElementDefinition
22
- | AnySelectDefinition
23
- | InputDefinition
24
- | ItemDefinition
25
- | ItemsetDefinition;
26
-
27
- export type TextElementChild = TextElementOutputPart | TextElementStaticPart;
28
-
29
- export abstract class TextElementDefinition<
30
- Type extends TextElementType,
31
- > extends BodyElementDefinition<Type> {
32
- readonly category = 'support';
33
- abstract override readonly type: Type;
34
-
35
- override readonly reference: string | null;
36
- override readonly parentReference: string | null;
37
-
38
- readonly referenceExpression: TextElementReferencePart | null;
39
- readonly children: readonly TextElementChild[];
40
-
41
- override get isTranslated(): boolean {
42
- return this.owner.isTranslated;
43
- }
44
-
45
- override set isTranslated(value: true) {
46
- this.owner.isTranslated = value;
47
- }
48
-
49
- protected constructor(
50
- form: XFormDefinition,
51
- readonly owner: TextElementOwner,
52
- element: TextElement
53
- ) {
54
- super(form, owner, element);
55
-
56
- this.reference = owner.reference;
57
- this.parentReference = owner.parentReference;
58
- this.referenceExpression = TextElementReferencePart.from(this, element);
59
-
60
- const children = Array.from(element.childNodes).flatMap((node) => {
61
- if (isTextNode(node)) {
62
- return new TextElementStaticPart(this, node);
63
- }
64
-
65
- if (isElementNode(node)) {
66
- const output = TextElementOutputPart.from(this, node);
67
-
68
- if (output != null) {
69
- return output;
70
- }
71
- }
72
-
73
- if (isCommentNode(node)) {
74
- return [];
75
- }
76
-
77
- // eslint-disable-next-line no-console
78
- console.error('Unexpected text element child', node);
79
-
80
- throw new Error(`Unexpected <${element.nodeName}> child element`);
81
- });
82
-
83
- this.children = children;
84
- }
85
-
86
- override registerDependentExpression(expression: AnyDependentExpression): void {
87
- this.owner.registerDependentExpression(expression);
88
- }
89
-
90
- override toJSON(): object {
91
- const { form, owner, parent, ...rest } = this;
92
-
93
- return rest;
94
- }
95
- }
96
-
97
- export type AnyTextElementDefinition = TextElementDefinition<TextElementType>;
@@ -1,27 +0,0 @@
1
- import type { AnyTextElementDefinition } from './TextElementDefinition.ts';
2
- import { TextElementPart } from './TextElementPart.ts';
3
-
4
- interface OutputElement extends Element {
5
- readonly localName: 'output';
6
-
7
- getAttribute(name: 'value'): string;
8
- getAttribute(name: string): string | null;
9
- }
10
-
11
- const isOutputElement = (element: Element): element is OutputElement => {
12
- return element.localName === 'output' && element.hasAttribute('value');
13
- };
14
-
15
- export class TextElementOutputPart extends TextElementPart<'output'> {
16
- static from(context: AnyTextElementDefinition, element: Element): TextElementOutputPart | null {
17
- if (isOutputElement(element)) {
18
- return new this(context, element);
19
- }
20
-
21
- return null;
22
- }
23
-
24
- protected constructor(context: AnyTextElementDefinition, element: OutputElement) {
25
- super('output', context, element.getAttribute('value'));
26
- }
27
- }
@@ -1,31 +0,0 @@
1
- import { DependentExpression } from '../../expression/DependentExpression.ts';
2
- import type { AnyTextElementDefinition } from './TextElementDefinition.ts';
3
- import type { TextElementOutputPart } from './TextElementOutputPart.ts';
4
- import type { TextElementReferencePart } from './TextElementReferencePart.ts';
5
- import type { TextElementStaticPart } from './TextElementStaticPart.ts';
6
-
7
- export type TextElementPartType = 'output' | 'reference' | 'static';
8
-
9
- export abstract class TextElementPart<
10
- Type extends TextElementPartType,
11
- > extends DependentExpression<'string'> {
12
- readonly stringValue?: string;
13
-
14
- constructor(
15
- readonly type: Type,
16
- context: AnyTextElementDefinition,
17
- expression: string
18
- ) {
19
- super(context, 'string', expression, {
20
- semanticDependencies: {
21
- translations: type !== 'static',
22
- },
23
- ignoreContextReference: true,
24
- });
25
- }
26
- }
27
-
28
- export type AnyTextElementPart =
29
- | TextElementOutputPart
30
- | TextElementReferencePart
31
- | TextElementStaticPart;
@@ -1,21 +0,0 @@
1
- import type { AnyTextElementDefinition, TextElement } from './TextElementDefinition.ts';
2
- import { TextElementPart } from './TextElementPart.ts';
3
-
4
- export class TextElementReferencePart extends TextElementPart<'reference'> {
5
- static from(
6
- context: AnyTextElementDefinition,
7
- element: TextElement
8
- ): TextElementReferencePart | null {
9
- const expression = element.getAttribute('ref');
10
-
11
- if (expression == null) {
12
- return null;
13
- }
14
-
15
- return new this(context, expression);
16
- }
17
-
18
- protected constructor(context: AnyTextElementDefinition, expression: string) {
19
- super('reference', context, expression);
20
- }
21
- }
@@ -1,26 +0,0 @@
1
- import type { AnyTextElementDefinition } from './TextElementDefinition.ts';
2
- import { TextElementPart } from './TextElementPart.ts';
3
-
4
- const toStaticXPathExpression = (staticTextValue: string): string => {
5
- const quote = staticTextValue.includes('"') ? "'" : '"';
6
-
7
- if (staticTextValue.includes(quote)) {
8
- // throw new Error('todo concat()');
9
- return 'todo(concat())';
10
- }
11
-
12
- return `${quote}${staticTextValue}${quote}`;
13
- };
14
-
15
- export class TextElementStaticPart extends TextElementPart<'static'> {
16
- override readonly stringValue: string;
17
-
18
- constructor(context: AnyTextElementDefinition, node: Text) {
19
- const stringValue = node.data;
20
- const expression = toStaticXPathExpression(stringValue);
21
-
22
- super('static', context, expression);
23
-
24
- this.stringValue = stringValue;
25
- }
26
- }