@getodk/xforms-engine 0.6.0 → 0.7.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 (296) hide show
  1. package/dist/client/BaseNode.d.ts +4 -4
  2. package/dist/client/BaseValueNode.d.ts +7 -3
  3. package/dist/client/RootNode.d.ts +20 -16
  4. package/dist/client/constants.d.ts +11 -12
  5. package/dist/client/form/CreateFormInstance.d.ts +14 -0
  6. package/dist/client/form/EditFormInstance.d.ts +62 -0
  7. package/dist/client/form/FormInstance.d.ts +104 -0
  8. package/dist/client/form/FormInstanceConfig.d.ts +17 -0
  9. package/dist/client/form/FormResource.d.ts +1 -0
  10. package/dist/client/form/LoadForm.d.ts +79 -0
  11. package/dist/client/form/LoadFormResult.d.ts +67 -0
  12. package/dist/client/form/RestoreFormInstance.d.ts +8 -0
  13. package/dist/client/index.d.ts +37 -11
  14. package/dist/client/node-types.d.ts +2 -2
  15. package/dist/client/repeat/BaseRepeatRangeNode.d.ts +3 -4
  16. package/dist/client/repeat/RepeatInstanceNode.d.ts +4 -5
  17. package/dist/client/repeat/RepeatRangeControlledNode.d.ts +2 -2
  18. package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +2 -2
  19. package/dist/client/resources.d.ts +1 -1
  20. package/dist/client/serialization/InstanceData.d.ts +12 -0
  21. package/dist/client/serialization/InstanceFile.d.ts +6 -0
  22. package/dist/client/serialization/InstancePayload.d.ts +93 -0
  23. package/dist/client/serialization/InstancePayloadOptions.d.ts +23 -0
  24. package/dist/client/serialization/InstanceState.d.ts +12 -0
  25. package/dist/client/submission/{SubmissionDefinition.d.ts → SubmissionMeta.d.ts} +1 -1
  26. package/dist/entrypoints/FormInstance.d.ts +20 -0
  27. package/dist/entrypoints/FormResult/BaseFormResult.d.ts +22 -0
  28. package/dist/entrypoints/FormResult/BaseInstantiableFormResult.d.ts +25 -0
  29. package/dist/entrypoints/FormResult/FormFailureResult.d.ts +17 -0
  30. package/dist/entrypoints/FormResult/FormSuccessResult.d.ts +15 -0
  31. package/dist/entrypoints/FormResult/FormWarningResult.d.ts +15 -0
  32. package/dist/entrypoints/createInstance.d.ts +9 -0
  33. package/dist/entrypoints/editInstance.d.ts +9 -0
  34. package/dist/entrypoints/index.d.ts +4 -0
  35. package/dist/entrypoints/loadForm.d.ts +4 -0
  36. package/dist/entrypoints/restoreInstance.d.ts +9 -0
  37. package/dist/error/LoadFormFailureError.d.ts +9 -0
  38. package/dist/error/MalformedInstanceDataError.d.ts +3 -0
  39. package/dist/error/TemplatedNodeAttributeSerializationError.d.ts +22 -0
  40. package/dist/index.d.ts +2 -33
  41. package/dist/index.js +1915 -1419
  42. package/dist/index.js.map +1 -1
  43. package/dist/instance/Group.d.ts +6 -5
  44. package/dist/instance/InputControl.d.ts +5 -4
  45. package/dist/instance/ModelValue.d.ts +5 -4
  46. package/dist/instance/Note.d.ts +4 -3
  47. package/dist/instance/PrimaryInstance.d.ts +35 -8
  48. package/dist/instance/RangeControl.d.ts +5 -4
  49. package/dist/instance/RankControl.d.ts +6 -5
  50. package/dist/instance/Root.d.ts +7 -9
  51. package/dist/instance/SelectControl.d.ts +4 -3
  52. package/dist/instance/Subtree.d.ts +6 -5
  53. package/dist/instance/TriggerControl.d.ts +4 -3
  54. package/dist/instance/abstract/DescendantNode.d.ts +10 -1
  55. package/dist/instance/abstract/InstanceNode.d.ts +7 -4
  56. package/dist/instance/abstract/ValueNode.d.ts +7 -5
  57. package/dist/instance/children/DescendantNodeInitOptions.d.ts +32 -0
  58. package/dist/instance/{children.d.ts → children/buildChildren.d.ts} +1 -1
  59. package/dist/instance/children/childrenInitOptions.d.ts +9 -0
  60. package/dist/instance/children/normalizeChildInitOptions.d.ts +2 -0
  61. package/dist/instance/input/InitialInstanceState.d.ts +13 -0
  62. package/dist/instance/input/InstanceAttachmentMap.d.ts +19 -0
  63. package/dist/instance/internal-api/InstanceConfig.d.ts +2 -9
  64. package/dist/instance/internal-api/InstanceValueContext.d.ts +8 -1
  65. package/dist/instance/internal-api/serialization/ClientReactiveSerializableInstance.d.ts +14 -0
  66. package/dist/instance/internal-api/serialization/ClientReactiveSerializableLeafNode.d.ts +32 -0
  67. package/dist/instance/internal-api/serialization/ClientReactiveSerializableParentNode.d.ts +18 -0
  68. package/dist/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.d.ts +13 -0
  69. package/dist/instance/internal-api/serialization/ClientReactiveSerializableValueNode.d.ts +21 -0
  70. package/dist/instance/repeat/BaseRepeatRange.d.ts +10 -8
  71. package/dist/instance/repeat/RepeatInstance.d.ts +10 -7
  72. package/dist/instance/repeat/RepeatRangeControlled.d.ts +27 -3
  73. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +4 -3
  74. package/dist/instance/resource.d.ts +5 -1
  75. package/dist/instance/unsupported/UploadControl.d.ts +32 -4
  76. package/dist/integration/xpath/EngineXPathEvaluator.d.ts +2 -2
  77. package/dist/integration/xpath/adapter/kind.d.ts +4 -10
  78. package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +4 -5
  79. package/dist/integration/xpath/static-dom/StaticDocument.d.ts +13 -10
  80. package/dist/integration/xpath/static-dom/StaticElement.d.ts +21 -22
  81. package/dist/integration/xpath/static-dom/StaticNode.d.ts +1 -1
  82. package/dist/integration/xpath/static-dom/StaticParentNode.d.ts +13 -0
  83. package/dist/integration/xpath/static-dom/staticNodeName.d.ts +3 -0
  84. package/dist/lib/client-reactivity/instance-state/createNodeRangeInstanceState.d.ts +4 -0
  85. package/dist/lib/client-reactivity/instance-state/createParentNodeInstanceState.d.ts +4 -0
  86. package/dist/lib/client-reactivity/instance-state/createPrimaryInstanceState.d.ts +3 -0
  87. package/dist/lib/client-reactivity/instance-state/createRootInstanceState.d.ts +3 -0
  88. package/dist/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.d.ts +6 -0
  89. package/dist/lib/client-reactivity/instance-state/createValueNodeInstanceState.d.ts +3 -0
  90. package/dist/lib/client-reactivity/instance-state/prepareInstancePayload.d.ts +8 -0
  91. package/dist/lib/codecs/TempUnsupportedControlCodec.d.ts +7 -0
  92. package/dist/lib/names/UnprefixedXFormsName.d.ts +4 -0
  93. package/dist/lib/reactivity/createInstanceValueState.d.ts +2 -27
  94. package/dist/parse/XFormDOM.d.ts +1 -1
  95. package/dist/parse/model/BindDefinition.d.ts +1 -1
  96. package/dist/parse/model/ItextTranslationsDefinition.d.ts +18 -0
  97. package/dist/parse/model/LeafNodeDefinition.d.ts +4 -5
  98. package/dist/parse/model/ModelBindMap.d.ts +1 -1
  99. package/dist/parse/model/ModelDefinition.d.ts +9 -2
  100. package/dist/parse/model/NodeDefinition.d.ts +18 -30
  101. package/dist/parse/model/NoteNodeDefinition.d.ts +3 -2
  102. package/dist/parse/model/RangeNodeDefinition.d.ts +2 -1
  103. package/dist/parse/model/RepeatDefinition.d.ts +62 -0
  104. package/dist/parse/model/RootAttributeDefinition.d.ts +1 -4
  105. package/dist/parse/model/RootAttributeMap.d.ts +2 -1
  106. package/dist/parse/model/RootDefinition.d.ts +7 -8
  107. package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +15 -2
  108. package/dist/parse/model/SecondaryInstance/assertSecondaryInstanceDefinition.d.ts +5 -0
  109. package/dist/parse/model/SecondaryInstance/defineSecondaryInstance.d.ts +5 -0
  110. package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +1 -7
  111. package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +1 -1
  112. package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +1 -1
  113. package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +1 -1
  114. package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +1 -1
  115. package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +1 -1
  116. package/dist/parse/model/{FormSubmissionDefinition.d.ts → SubmissionDefinition.d.ts} +2 -2
  117. package/dist/parse/model/SubtreeDefinition.d.ts +4 -5
  118. package/dist/parse/model/nodeDefinitionMap.d.ts +5 -0
  119. package/dist/parse/shared/parseInstanceXML.d.ts +21 -0
  120. package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +4 -21
  121. package/dist/solid.js +1709 -1213
  122. package/dist/solid.js.map +1 -1
  123. package/package.json +1 -1
  124. package/src/client/BaseNode.ts +4 -4
  125. package/src/client/BaseValueNode.ts +7 -3
  126. package/src/client/RootNode.ts +27 -19
  127. package/src/client/constants.ts +12 -14
  128. package/src/client/form/CreateFormInstance.ts +19 -0
  129. package/src/client/form/EditFormInstance.ts +93 -0
  130. package/src/client/form/FormInstance.ts +114 -0
  131. package/src/client/form/FormInstanceConfig.ts +18 -0
  132. package/src/client/form/FormResource.ts +1 -0
  133. package/src/client/form/LoadForm.ts +92 -0
  134. package/src/client/form/LoadFormResult.ts +103 -0
  135. package/src/client/form/RestoreFormInstance.ts +14 -0
  136. package/src/client/index.ts +47 -29
  137. package/src/client/node-types.ts +2 -4
  138. package/src/client/repeat/BaseRepeatRangeNode.ts +3 -4
  139. package/src/client/repeat/RepeatInstanceNode.ts +4 -8
  140. package/src/client/repeat/RepeatRangeControlledNode.ts +2 -2
  141. package/src/client/repeat/RepeatRangeUncontrolledNode.ts +2 -2
  142. package/src/client/resources.ts +2 -2
  143. package/src/client/serialization/InstanceData.ts +16 -0
  144. package/src/client/serialization/InstanceFile.ts +9 -0
  145. package/src/client/serialization/InstancePayload.ts +126 -0
  146. package/src/client/serialization/InstancePayloadOptions.ts +28 -0
  147. package/src/client/serialization/InstanceState.ts +14 -0
  148. package/src/client/submission/{SubmissionDefinition.ts → SubmissionMeta.ts} +1 -1
  149. package/src/entrypoints/FormInstance.ts +55 -0
  150. package/src/entrypoints/FormResult/BaseFormResult.ts +40 -0
  151. package/src/entrypoints/FormResult/BaseInstantiableFormResult.ts +109 -0
  152. package/src/entrypoints/FormResult/FormFailureResult.ts +44 -0
  153. package/src/entrypoints/FormResult/FormSuccessResult.ts +25 -0
  154. package/src/entrypoints/FormResult/FormWarningResult.ts +25 -0
  155. package/src/entrypoints/createInstance.ts +23 -0
  156. package/src/entrypoints/editInstance.ts +24 -0
  157. package/src/entrypoints/index.ts +4 -0
  158. package/src/entrypoints/loadForm.ts +154 -0
  159. package/src/entrypoints/restoreInstance.ts +27 -0
  160. package/src/error/LoadFormFailureError.ts +114 -0
  161. package/src/error/MalformedInstanceDataError.ts +3 -0
  162. package/src/error/TemplatedNodeAttributeSerializationError.ts +24 -0
  163. package/src/index.ts +2 -46
  164. package/src/instance/Group.ts +16 -15
  165. package/src/instance/InputControl.ts +17 -11
  166. package/src/instance/ModelValue.ts +17 -11
  167. package/src/instance/Note.ts +10 -9
  168. package/src/instance/PrimaryInstance.ts +69 -31
  169. package/src/instance/RangeControl.ts +17 -11
  170. package/src/instance/RankControl.ts +28 -19
  171. package/src/instance/Root.ts +20 -31
  172. package/src/instance/SelectControl.ts +21 -12
  173. package/src/instance/Subtree.ts +16 -15
  174. package/src/instance/TriggerControl.ts +21 -12
  175. package/src/instance/abstract/DescendantNode.ts +12 -2
  176. package/src/instance/abstract/InstanceNode.ts +9 -5
  177. package/src/instance/abstract/ValueNode.ts +11 -13
  178. package/src/instance/children/DescendantNodeInitOptions.ts +35 -0
  179. package/src/instance/{children.ts → children/buildChildren.ts} +55 -48
  180. package/src/instance/children/childrenInitOptions.ts +117 -0
  181. package/src/instance/children/normalizeChildInitOptions.ts +332 -0
  182. package/src/instance/input/InitialInstanceState.ts +108 -0
  183. package/src/instance/input/InstanceAttachmentMap.ts +142 -0
  184. package/src/instance/internal-api/InstanceConfig.ts +3 -10
  185. package/src/instance/internal-api/InstanceValueContext.ts +9 -1
  186. package/src/instance/internal-api/serialization/ClientReactiveSerializableInstance.ts +20 -0
  187. package/src/instance/internal-api/serialization/ClientReactiveSerializableLeafNode.ts +43 -0
  188. package/src/instance/internal-api/serialization/ClientReactiveSerializableParentNode.ts +26 -0
  189. package/src/instance/internal-api/serialization/ClientReactiveSerializableTemplatedNode.ts +24 -0
  190. package/src/instance/internal-api/serialization/ClientReactiveSerializableValueNode.ts +28 -0
  191. package/src/instance/repeat/BaseRepeatRange.ts +19 -24
  192. package/src/instance/repeat/RepeatInstance.ts +26 -19
  193. package/src/instance/repeat/RepeatRangeControlled.ts +90 -17
  194. package/src/instance/repeat/RepeatRangeUncontrolled.ts +10 -9
  195. package/src/instance/resource.ts +14 -1
  196. package/src/instance/unsupported/UploadControl.ts +116 -5
  197. package/src/integration/xpath/EngineXPathEvaluator.ts +2 -2
  198. package/src/integration/xpath/adapter/kind.ts +1 -28
  199. package/src/integration/xpath/adapter/traversal.ts +2 -2
  200. package/src/integration/xpath/static-dom/StaticAttribute.ts +6 -5
  201. package/src/integration/xpath/static-dom/StaticDocument.ts +17 -16
  202. package/src/integration/xpath/static-dom/StaticElement.ts +196 -50
  203. package/src/integration/xpath/static-dom/StaticNode.ts +1 -1
  204. package/src/integration/xpath/static-dom/StaticParentNode.ts +22 -0
  205. package/src/integration/xpath/static-dom/staticNodeName.ts +20 -0
  206. package/src/lib/client-reactivity/instance-state/createNodeRangeInstanceState.ts +17 -0
  207. package/src/lib/client-reactivity/instance-state/createParentNodeInstanceState.ts +22 -0
  208. package/src/lib/client-reactivity/instance-state/createPrimaryInstanceState.ts +12 -0
  209. package/src/lib/client-reactivity/{submission/createRootSubmissionState.ts → instance-state/createRootInstanceState.ts} +4 -4
  210. package/src/lib/client-reactivity/instance-state/createTemplatedNodeInstanceState.ts +31 -0
  211. package/src/lib/client-reactivity/instance-state/createValueNodeInstanceState.ts +21 -0
  212. package/src/lib/client-reactivity/instance-state/prepareInstancePayload.ts +173 -0
  213. package/src/lib/codecs/TempUnsupportedControlCodec.ts +32 -0
  214. package/src/lib/names/UnprefixedXFormsName.ts +12 -0
  215. package/src/lib/reactivity/createInstanceValueState.ts +27 -51
  216. package/src/parse/model/ItextTranslationsDefinition.ts +79 -0
  217. package/src/parse/model/LeafNodeDefinition.ts +3 -5
  218. package/src/parse/model/ModelDefinition.ts +36 -3
  219. package/src/parse/model/NodeDefinition.ts +19 -45
  220. package/src/parse/model/NoteNodeDefinition.ts +4 -3
  221. package/src/parse/model/RangeNodeDefinition.ts +3 -2
  222. package/src/parse/model/RepeatDefinition.ts +382 -0
  223. package/src/parse/model/RootAttributeDefinition.ts +6 -7
  224. package/src/parse/model/RootAttributeMap.ts +15 -10
  225. package/src/parse/model/RootDefinition.ts +17 -19
  226. package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +23 -2
  227. package/src/parse/model/SecondaryInstance/assertSecondaryInstanceDefinition.ts +14 -0
  228. package/src/parse/model/SecondaryInstance/defineSecondaryInstance.ts +32 -0
  229. package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +3 -24
  230. package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +33 -86
  231. package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +64 -137
  232. package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +9 -7
  233. package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +1 -1
  234. package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +7 -7
  235. package/src/parse/model/{FormSubmissionDefinition.ts → SubmissionDefinition.ts} +2 -2
  236. package/src/parse/model/SubtreeDefinition.ts +4 -5
  237. package/src/parse/model/nodeDefinitionMap.ts +34 -0
  238. package/src/parse/shared/parseInstanceXML.ts +79 -0
  239. package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +45 -130
  240. package/dist/client/EngineConfig.d.ts +0 -79
  241. package/dist/client/submission/SubmissionData.d.ts +0 -7
  242. package/dist/client/submission/SubmissionInstanceFile.d.ts +0 -6
  243. package/dist/client/submission/SubmissionOptions.d.ts +0 -23
  244. package/dist/client/submission/SubmissionResult.d.ts +0 -91
  245. package/dist/client/submission/SubmissionState.d.ts +0 -12
  246. package/dist/instance/abstract/UnsupportedControl.d.ts +0 -54
  247. package/dist/instance/index.d.ts +0 -8
  248. package/dist/instance/internal-api/ValueContext.d.ts +0 -23
  249. package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +0 -14
  250. package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +0 -32
  251. package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +0 -19
  252. package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +0 -18
  253. package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +0 -3
  254. package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +0 -3
  255. package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +0 -4
  256. package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +0 -4
  257. package/dist/lib/client-reactivity/submission/createRootSubmissionState.d.ts +0 -3
  258. package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +0 -3
  259. package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +0 -8
  260. package/dist/lib/reactivity/createValueState.d.ts +0 -40
  261. package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +0 -4
  262. package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +0 -9
  263. package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +0 -8
  264. package/dist/parse/model/RepeatInstanceDefinition.d.ts +0 -17
  265. package/dist/parse/model/RepeatRangeDefinition.d.ts +0 -32
  266. package/dist/parse/model/RepeatTemplateDefinition.d.ts +0 -31
  267. package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +0 -4
  268. package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +0 -7
  269. package/src/client/EngineConfig.ts +0 -84
  270. package/src/client/submission/SubmissionData.ts +0 -12
  271. package/src/client/submission/SubmissionInstanceFile.ts +0 -9
  272. package/src/client/submission/SubmissionOptions.ts +0 -28
  273. package/src/client/submission/SubmissionResult.ts +0 -124
  274. package/src/client/submission/SubmissionState.ts +0 -14
  275. package/src/instance/abstract/UnsupportedControl.ts +0 -175
  276. package/src/instance/index.ts +0 -55
  277. package/src/instance/internal-api/ValueContext.ts +0 -28
  278. package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +0 -20
  279. package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +0 -43
  280. package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +0 -26
  281. package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +0 -24
  282. package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +0 -12
  283. package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +0 -20
  284. package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +0 -17
  285. package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +0 -22
  286. package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +0 -21
  287. package/src/lib/client-reactivity/submission/prepareSubmission.ts +0 -172
  288. package/src/lib/reactivity/createValueState.ts +0 -200
  289. package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +0 -4
  290. package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +0 -42
  291. package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +0 -31
  292. package/src/parse/model/RepeatInstanceDefinition.ts +0 -38
  293. package/src/parse/model/RepeatRangeDefinition.ts +0 -98
  294. package/src/parse/model/RepeatTemplateDefinition.ts +0 -149
  295. package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +0 -4
  296. package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +0 -12
@@ -1,21 +1,54 @@
1
+ import { ErrorProductionDesignPendingError } from '../../error/ErrorProductionDesignPendingError.ts';
2
+ import type { StaticDocument } from '../../integration/xpath/static-dom/StaticDocument.ts';
3
+ import { parseStaticDocumentFromDOMSubtree } from '../shared/parseStaticDocumentFromDOMSubtree.ts';
1
4
  import type { XFormDefinition } from '../XFormDefinition.ts';
2
- import { FormSubmissionDefinition } from './FormSubmissionDefinition.ts';
3
- import { ItextTranslationsDefinition } from './ItextTranslation/ItextTranslationsDefinition.ts';
5
+ import { ItextTranslationsDefinition } from './ItextTranslationsDefinition.ts';
4
6
  import { ModelBindMap } from './ModelBindMap.ts';
7
+ import type { AnyNodeDefinition } from './NodeDefinition.ts';
8
+ import type { NodeDefinitionMap } from './nodeDefinitionMap.ts';
9
+ import { nodeDefinitionMap } from './nodeDefinitionMap.ts';
5
10
  import { RootDefinition } from './RootDefinition.ts';
11
+ import { SubmissionDefinition } from './SubmissionDefinition.ts';
6
12
 
7
13
  export class ModelDefinition {
8
14
  readonly binds: ModelBindMap;
9
15
  readonly root: RootDefinition;
16
+ readonly nodes: NodeDefinitionMap;
17
+ readonly instance: StaticDocument;
10
18
  readonly itextTranslations: ItextTranslationsDefinition;
11
19
 
12
20
  constructor(readonly form: XFormDefinition) {
13
- const submission = new FormSubmissionDefinition(form.xformDOM);
21
+ const submission = new SubmissionDefinition(form.xformDOM);
22
+
14
23
  this.binds = ModelBindMap.fromModel(this);
24
+ this.instance = parseStaticDocumentFromDOMSubtree(form.xformDOM.primaryInstanceRoot, {
25
+ nodesetPrefix: '/',
26
+ });
15
27
  this.root = new RootDefinition(form, this, submission, form.body.classes);
28
+ this.nodes = nodeDefinitionMap(this.root);
16
29
  this.itextTranslations = ItextTranslationsDefinition.from(form.xformDOM);
17
30
  }
18
31
 
32
+ getNodeDefinition(nodeset: string): AnyNodeDefinition {
33
+ const definition = this.nodes.get(nodeset);
34
+
35
+ if (definition == null) {
36
+ throw new ErrorProductionDesignPendingError(`No definition for nodeset: ${nodeset}`);
37
+ }
38
+
39
+ return definition;
40
+ }
41
+
42
+ getRootDefinition(instance: StaticDocument): RootDefinition {
43
+ const definition = this.getNodeDefinition(instance.root.nodeset);
44
+
45
+ if (definition !== this.root) {
46
+ throw new ErrorProductionDesignPendingError();
47
+ }
48
+
49
+ return definition;
50
+ }
51
+
19
52
  toJSON() {
20
53
  const { form, ...rest } = this;
21
54
 
@@ -1,3 +1,4 @@
1
+ import type { StaticElement } from '../../integration/xpath/static-dom/StaticElement.ts';
1
2
  import type {
2
3
  NamedSubtreeDefinition,
3
4
  NamespaceDeclarationMap,
@@ -7,14 +8,12 @@ import type { AnyBodyElementDefinition } from '../body/BodyDefinition.ts';
7
8
  import type { RepeatElementDefinition } from '../body/RepeatElementDefinition.ts';
8
9
  import type { BindDefinition } from './BindDefinition.ts';
9
10
  import type { LeafNodeDefinition } from './LeafNodeDefinition.ts';
10
- import type { RepeatInstanceDefinition } from './RepeatInstanceDefinition.ts';
11
- import type { AnyRepeatRangeDefinition } from './RepeatRangeDefinition.ts';
12
- import type { RepeatTemplateDefinition } from './RepeatTemplateDefinition.ts';
11
+ import type { AnyRepeatDefinition } from './RepeatDefinition.ts';
13
12
  import type { RootDefinition } from './RootDefinition.ts';
14
13
  import type { SubtreeDefinition } from './SubtreeDefinition.ts';
15
14
 
16
15
  /**
17
- * Corresponds to the model/entry DOM root node, i.e.:
16
+ * Corresponds to a model instance root node, i.e.:
18
17
  *
19
18
  * - the element matching `/*` in primary instance expressions, a.k.a.
20
19
  * - `/h:html/h:head/xf:model/xf:instance[1]/*`
@@ -22,34 +21,25 @@ import type { SubtreeDefinition } from './SubtreeDefinition.ts';
22
21
  export type RootNodeType = 'root';
23
22
 
24
23
  /**
25
- * Corresponds to a range/sequence of model/entry DOM subtrees which in turn
26
- * corresponds to a <repeat> in the form body definition.
27
- */
28
- export type RepeatRangeType = 'repeat-range';
29
-
30
- /**
31
- * Corresponds to a template definition for a repeat range, which either has
32
- * an explicit `jr:template=""` attribute in the form definition or is inferred
33
- * as a template from the form's first element matched by a <repeat nodeset>.
34
- */
35
- export type RepeatTemplateType = 'repeat-template';
36
-
37
- /**
38
- * Corresponds to a single instance of a model/entry DOM subtree which
39
- * in turn corresponds to a <repeat> in the form body definition, and a
40
- * 'repeat-range' definition.
24
+ * Corresponds to the combined concepts defining a "repeat".
25
+ *
26
+ * @see {@link RepeatDefinition} for details on these concepts and how they are used to produce a "repeat definition", as such.
27
+ *
28
+ * , including or
29
+ * referencing all of the following:
30
+ *
41
31
  */
42
- export type RepeatInstanceType = 'repeat-instance';
32
+ export type RepeatType = 'repeat';
43
33
 
44
34
  /**
45
- * Corresponds to a model/entry DOM subtree which **does not** correspond to a
35
+ * Corresponds to a model instance subtree which **does not** correspond to a
46
36
  * <repeat> in the form definition. This will typically correspond to a <group>,
47
37
  * but this is not strictly necessary per spec (hence the distinct name).
48
38
  */
49
39
  export type SubtreeNodeType = 'subtree';
50
40
 
51
41
  /**
52
- * Corresponds to a model/entry DOM leaf node, i.e. one of:
42
+ * Corresponds to a model instance leaf node, i.e. one of:
53
43
  *
54
44
  * - An element with no child elements
55
45
  * - Any attribute corresponding to a bind's `nodeset` expression
@@ -60,9 +50,7 @@ export type LeafNodeType = 'leaf-node';
60
50
  export type NodeDefinitionType =
61
51
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
62
52
  | RootNodeType
63
- | RepeatRangeType
64
- | RepeatTemplateType
65
- | RepeatInstanceType
53
+ | RepeatType
66
54
  | SubtreeNodeType
67
55
  | LeafNodeType;
68
56
 
@@ -70,24 +58,15 @@ export type NodeDefinitionType =
70
58
  export type ParentNodeDefinition =
71
59
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
72
60
  | RootDefinition
73
- | RepeatTemplateDefinition
74
- | RepeatInstanceDefinition
61
+ | AnyRepeatDefinition
75
62
  | SubtreeDefinition;
76
63
 
77
64
  // prettier-ignore
78
65
  export type ChildNodeDefinition =
79
- | AnyRepeatRangeDefinition
66
+ | AnyRepeatDefinition
80
67
  | LeafNodeDefinition
81
68
  | SubtreeDefinition;
82
69
 
83
- // prettier-ignore
84
- export type ChildNodeInstanceDefinition =
85
- // eslint-disable-next-line @typescript-eslint/sort-type-constituents
86
- | RepeatTemplateDefinition
87
- | RepeatInstanceDefinition
88
- | SubtreeDefinition
89
- | LeafNodeDefinition;
90
-
91
70
  export abstract class NodeDefinition<Type extends NodeDefinitionType>
92
71
  implements NamedSubtreeDefinition
93
72
  {
@@ -98,12 +77,8 @@ export abstract class NodeDefinition<Type extends NodeDefinitionType>
98
77
  abstract readonly isTranslated: boolean;
99
78
  abstract readonly root: RootDefinition;
100
79
  abstract readonly parent: ParentNodeDefinition | null;
80
+ abstract readonly template: StaticElement;
101
81
  abstract readonly children: readonly ChildNodeDefinition[] | null;
102
- abstract readonly instances: readonly RepeatInstanceDefinition[] | null;
103
- abstract readonly defaultValue: string | null;
104
-
105
- /** @todo leaf-node may be Attr */
106
- abstract readonly node: Element | null;
107
82
 
108
83
  readonly nodeset: string;
109
84
 
@@ -112,11 +87,10 @@ export abstract class NodeDefinition<Type extends NodeDefinitionType>
112
87
  }
113
88
  }
114
89
 
90
+ // prettier-ignore
115
91
  export type AnyNodeDefinition =
116
92
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
117
93
  | RootDefinition
118
- | AnyRepeatRangeDefinition
119
- | RepeatTemplateDefinition
120
- | RepeatInstanceDefinition
94
+ | AnyRepeatDefinition
121
95
  | SubtreeDefinition
122
96
  | LeafNodeDefinition;
@@ -1,5 +1,6 @@
1
1
  import type { NoteNode } from '../../client/NoteNode.ts';
2
2
  import type { ValueType } from '../../client/ValueType.ts';
3
+ import type { StaticLeafElement } from '../../integration/xpath/static-dom/StaticElement.ts';
3
4
  import type { AnyBodyElementDefinition } from '../body/BodyDefinition.ts';
4
5
  import type { InputControlDefinition } from '../body/control/InputControlDefinition.ts';
5
6
  import { BindComputationExpression } from '../expression/BindComputationExpression.ts';
@@ -43,7 +44,7 @@ export class NoteNodeDefinition<V extends ValueType = ValueType> extends LeafNod
43
44
  parent: ParentNodeDefinition,
44
45
  bind: BindDefinition<V>,
45
46
  bodyElement: AnyBodyElementDefinition | null,
46
- node: Element
47
+ node: StaticLeafElement
47
48
  ): NoteNodeDefinition<V> | null {
48
49
  if (!isNoteBindDefinition(bind) || bodyElement?.type !== 'input') {
49
50
  return null;
@@ -64,8 +65,8 @@ export class NoteNodeDefinition<V extends ValueType = ValueType> extends LeafNod
64
65
  override readonly bind: NoteBindDefinition<V>,
65
66
  override readonly bodyElement: InputControlDefinition,
66
67
  readonly noteTextDefinition: NoteTextDefinition,
67
- node: Element
68
+ template: StaticLeafElement
68
69
  ) {
69
- super(parent, bind, bodyElement, node);
70
+ super(parent, bind, bodyElement, template);
70
71
  }
71
72
  }
@@ -1,5 +1,6 @@
1
1
  import type { ValueType } from '../../client/ValueType.ts';
2
2
  import { ErrorProductionDesignPendingError } from '../../error/ErrorProductionDesignPendingError.ts';
3
+ import type { StaticLeafElement } from '../../integration/xpath/static-dom/StaticElement.ts';
3
4
  import type { RuntimeValue, SharedValueCodec } from '../../lib/codecs/getSharedValueCodec.ts';
4
5
  import { getSharedValueCodec } from '../../lib/codecs/getSharedValueCodec.ts';
5
6
  import type {
@@ -91,7 +92,7 @@ export class RangeNodeDefinition<V extends RangeValueType = RangeValueType>
91
92
  parent: ParentNodeDefinition,
92
93
  bind: BindDefinition<V>,
93
94
  bodyElement: RangeControlDefinition,
94
- node: Element
95
+ node: StaticLeafElement
95
96
  ): RangeNodeDefinition<Extract<V, RangeValueType>> {
96
97
  assertRangeBindDefinition(bind);
97
98
 
@@ -104,7 +105,7 @@ export class RangeNodeDefinition<V extends RangeValueType = RangeValueType>
104
105
  parent: ParentNodeDefinition,
105
106
  override readonly bind: BindDefinition<V>,
106
107
  override readonly bodyElement: RangeControlDefinition,
107
- node: Element
108
+ node: StaticLeafElement
108
109
  ) {
109
110
  super(parent, bind, bodyElement, node);
110
111
 
@@ -0,0 +1,382 @@
1
+ import { JAVAROSA_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
+ import type { XFORMS_KNOWN_ATTRIBUTE } from '@getodk/xpath';
3
+ import type { RepeatRange } from '../../instance/hierarchy.ts';
4
+ import type { PrimaryInstance } from '../../instance/PrimaryInstance.ts';
5
+ import type { RepeatInstance } from '../../instance/repeat/RepeatInstance.ts';
6
+ import type {
7
+ StaticAttribute,
8
+ StaticAttributeOptions,
9
+ } from '../../integration/xpath/static-dom/StaticAttribute.ts';
10
+ import { StaticDocument } from '../../integration/xpath/static-dom/StaticDocument.ts';
11
+ import type {
12
+ StaticElement,
13
+ StaticElementOptions,
14
+ } from '../../integration/xpath/static-dom/StaticElement.ts';
15
+ import type { StaticNode } from '../../integration/xpath/static-dom/StaticNode.ts';
16
+ import type { StaticText } from '../../integration/xpath/static-dom/StaticText.ts';
17
+ import { NamespaceDeclarationMap } from '../../lib/names/NamespaceDeclarationMap.ts';
18
+ import type { NamespaceURL } from '../../lib/names/NamespaceURL.ts';
19
+ import type { QualifiedName, QualifiedNameSource } from '../../lib/names/QualifiedName.ts';
20
+ import type { RepeatElementDefinition } from '../body/RepeatElementDefinition.ts';
21
+ import { RepeatCountControlExpression } from '../expression/RepeatCountControlExpression.ts';
22
+ import type { BindDefinition } from './BindDefinition.ts';
23
+ import { DescendentNodeDefinition } from './DescendentNodeDefinition.ts';
24
+ import type { ChildNodeDefinition, ParentNodeDefinition } from './NodeDefinition.ts';
25
+ import type { RootDefinition } from './RootDefinition.ts';
26
+ import type { SubtreeDefinition } from './SubtreeDefinition.ts';
27
+
28
+ interface JavaRosaNamespaceURI extends NamespaceURL {
29
+ readonly href: JAVAROSA_NAMESPACE_URI;
30
+ }
31
+
32
+ interface JRTemplateAttributeName extends QualifiedName {
33
+ readonly namespaceURI: JavaRosaNamespaceURI;
34
+ readonly localName: 'template';
35
+ }
36
+
37
+ const isJRTemplateAttributeName = (name: QualifiedNameSource) => {
38
+ if (name.localName !== 'template') {
39
+ return false;
40
+ }
41
+
42
+ const namespaceURI = (name.namespaceURI as NamespaceURL)?.href ?? name.namespaceURI;
43
+
44
+ return namespaceURI === JAVAROSA_NAMESPACE_URI;
45
+ };
46
+
47
+ interface JRTemplateAttribute extends StaticAttribute {
48
+ readonly qualifiedName: JRTemplateAttributeName;
49
+ }
50
+
51
+ const isJRTemplateAttribute = (attribute: StaticAttribute): attribute is JRTemplateAttribute => {
52
+ return isJRTemplateAttributeName(attribute.qualifiedName);
53
+ };
54
+
55
+ interface ExplicitRepeatTemplateElement extends StaticElement {
56
+ readonly [XFORMS_KNOWN_ATTRIBUTE]: 'template';
57
+
58
+ getAttributeValue(localName: 'template'): string;
59
+ getAttributeValue(localName: string): string | null;
60
+ }
61
+
62
+ /**
63
+ * Determines whether a model instance node is an **explicit** repeat template,
64
+ * as defined by the presence of a `jr:template` attribute on that node.
65
+ *
66
+ * @see {@link https://getodk.github.io/xforms-spec/#default-values-in-repeats}
67
+ */
68
+ const isExplicitRepeatTemplateElement = (
69
+ sourceElement: StaticElement
70
+ ): sourceElement is ExplicitRepeatTemplateElement => {
71
+ return sourceElement.attributes.some(isJRTemplateAttribute);
72
+ };
73
+
74
+ const cloneStaticAttributeOptions = (attribute: StaticAttribute): StaticAttributeOptions => {
75
+ return {
76
+ name: attribute.qualifiedName,
77
+ value: attribute.value,
78
+ };
79
+ };
80
+
81
+ interface ClonedSubtreeStructure extends StaticElementOptions {
82
+ readonly attributes: readonly StaticAttributeOptions[];
83
+ readonly children: readonly StaticElementOptions[];
84
+ }
85
+
86
+ const cloneStaticSubtreeStructure = (sourceElement: StaticElement): ClonedSubtreeStructure => {
87
+ const name = sourceElement.qualifiedName;
88
+ const attributes = sourceElement.attributes.map(cloneStaticAttributeOptions);
89
+ const children = sourceElement.childElements.map(cloneStaticSubtreeStructure);
90
+
91
+ return {
92
+ name,
93
+ attributes,
94
+ children,
95
+ };
96
+ };
97
+
98
+ /**
99
+ * Clones the **structure** of a {@link StaticElement}, omitting
100
+ * {@link StaticText | text values} of the element itself, and any of its
101
+ * descendants.
102
+ *
103
+ * @todo This function's behavior is **plausibly** general purpose. The function
104
+ * itself, its argument, its local bindings are all named to reflect that fact.
105
+ *
106
+ * However, the **use case** for the function is quite specific: when a form
107
+ * defines a `<repeat>` that isn't associated with an explicit `jr:template`, we
108
+ * fabricate a template by cloning its structure with all text values removed
109
+ * (described in more detail for {@link parseRepeatTemplateElement}).
110
+ *
111
+ * As generalized as this the function is, it's not at all clear how or why we'd
112
+ * use it for other purposes. Even the top-of-mind (at time of writing) use case
113
+ * which might semantically line up with it (i.e. potentially as a basis to
114
+ * reconcile edit instance state into a form definition, as sort of a three-way
115
+ * merge) would effectively be pure overhead. For now, we have something
116
+ * library-ish living here private in this module unless/until we find another
117
+ * good reason to use it elsewhere!
118
+ *
119
+ * If we do find another plausible use case for this behavior, it's pretty
120
+ * likely we'd want to implement it as a part of the {@link StaticElement} (or
121
+ * somewhere else up the class hierarchy to {@link StaticNode}), to encapsulate
122
+ * as much as possible about how it's done. We've been pretty aggressive about
123
+ * changing the internals and signatures of {@link StaticNode}s and the
124
+ * static-dom abstraction. It'd be nice if ongoing changes were a lot more
125
+ * isolated, with far less impact on the growing set of use cases actually
126
+ * consuming the abstraction.
127
+ */
128
+ const cloneStaticElementStructure = (sourceElement: StaticElement): StaticElement => {
129
+ const { root: clone } = new StaticDocument({
130
+ documentRoot: cloneStaticSubtreeStructure(sourceElement),
131
+ nodesetPrefix: sourceElement.parent.nodeset,
132
+ });
133
+
134
+ return clone;
135
+ };
136
+
137
+ export type RepeatInstanceNodes = readonly [StaticElement, ...StaticElement[]];
138
+
139
+ /**
140
+ * Produces a consistent "repeat template" interface for each
141
+ * {@link RepeatDefinition}, which is used to produce new repeat instances in
142
+ * {@link PrimaryInstance | runtime form instance state}. How a "repeat
143
+ * template" is parsed is as follows:
144
+ *
145
+ * - If the form definition includes an **explicit template** (as described by
146
+ * {@link isExplicitRepeatTemplateElement}) as the
147
+ * {@link firstRepeatInstanceNode | first} node referenced by a `<repeat
148
+ * nodeset>`, that node is returned as it was already parsed.
149
+ *
150
+ * - If the {@link firstRepeatInstanceNode | first} repeat instance node is
151
+ * **NOT** an explicit template, a template is **implicitly created** from its
152
+ * blank structure, as a
153
+ * {@link cloneStaticElementStructure | clone of its structure}.
154
+ *
155
+ * The latter behavior may sound surprising if unfamiliar, but it is well
156
+ * understood. It is also known to be consistent with Collect (JavaRosa), as
157
+ * demonstrated by affected tests in `@getodk/scenario` which fail when this
158
+ * behavior is changed.
159
+ *
160
+ * - - -
161
+ *
162
+ * Note: this is a vastly simplified evolution of what was previously
163
+ * implemented in
164
+ * {@link https://github.com/getodk/web-forms/blob/99295eb1d6ec78cd6a758385793e97859b6a74cc/packages/xforms-engine/src/parse/model/RepeatTemplateDefinition.ts#L81 | `RepeatTemplateDefinition.parseModelNodes`}
165
+ * (permalink to implementation at time of writing/refactor).
166
+ *
167
+ * That previous implementation was based on a flawed mental model of how a
168
+ * parsed form model relates to the form's instance structure. The following
169
+ * describes the previous flawed mental model, and the reasoning behind revising
170
+ * the mental model established here.
171
+ *
172
+ * - - -
173
+ *
174
+ * **Flawed mental model**
175
+ *
176
+ * Repeat model definitions were composed of a combination of:
177
+ *
178
+ * 1. `RepeatRangeDefinition`: this effectively had a 1:1 correspondence to the
179
+ * `<repeat>` _body element_ referencing the `nodeset` of 1+ instance nodes
180
+ * (as defined in the form's model).
181
+ *
182
+ * 2. `RepeatTemplateDefinition`: this had a 0-1:1 correspondence between an
183
+ * instance node (as defined in the form's model) defining a `jr:template`
184
+ * attribute, if one exists; if none exists, one was synthesized at parse
185
+ * time.
186
+ *
187
+ * 3. `RepeatInstanceDefinition`: these had an N:N correspondence to _every
188
+ * non-template instance node_ (as defined in the form's model).
189
+ *
190
+ * For each instance of a form:
191
+ *
192
+ * - `RepeatRangeControlled` or `RepeatRangeUncontrolled` (engine-internal
193
+ * implementation of the `RepeatRangeControlledNode` and
194
+ * `RepeatRangeUncontrolledNode` client interfaces, respectively) also
195
+ * corresponded 1:1 with a `RepeatRangeDefinition`.
196
+ *
197
+ * - `RepeatInstance` (engine-internal implementation of the
198
+ * `RepeatInstanceNode`) had an N:N relationship with _either_:
199
+ * - `RepeatInstanceDefinition`, if one was defined for that repeat instance's
200
+ * the positional index
201
+ * - `RepeatTemplateDefinition`, otherwise
202
+ *
203
+ * **Revised mental model**
204
+ *
205
+ * 1. `RepeatDefinition`: merges the responsibilities of the former
206
+ * `RepeatRangeDefinition` and `RepeatTemplateDefinition`.
207
+ *
208
+ * 2. Repeat instance nodes (as defined in the form's model) are refereced
209
+ * _during the construction of instance state_ (`PrimaryInstance`):
210
+ *
211
+ * - if an instance node exists at the positional index of the
212
+ * `RepeatInstance` to be created, that node is used to populate the
213
+ * `RepeatInstance`'s initial state
214
+ *
215
+ * - if no instance node exists at that positional index, the template
216
+ * returned by {@link RepeatTemplateDefinition.parseRepeatTemplateElement}
217
+ * is referenced for the `RepeatInstance`'s initial state instead
218
+ *
219
+ * Aside from simplifying the parsing responsibilities associated with repeats,
220
+ * this also creates a roughly 1:1 relationship between the different
221
+ * representations of what we call an "instance node".
222
+ *
223
+ * @todo The above "revised mental model" for repeat definitions pretty much
224
+ * reflects the same principles which will be applied for non-form instance
225
+ * state, i.e. for (a) restoring previously serialized instance state and/or (b)
226
+ * editing previously submitted instance state. It will make sense to reflect
227
+ * that once that aspect of implementation is complete!
228
+ *
229
+ * - - -
230
+ *
231
+ * At time of writing, I believe that detailing the differences between these
232
+ * mental models will provide useful context, in the long term, for reasoning
233
+ * about the relationship between "node definition" and "instance node" (as
234
+ * defined in a form or a serialized and/or submitted instance; also the
235
+ * engine's active, stateful representations of those same nodes).
236
+ *
237
+ * Namely, the revised relationship is _1 (node definition) : N (instance
238
+ * node)_, associated by each instance node's nodeset.
239
+ */
240
+ const parseRepeatTemplateElement = (firstRepeatInstanceNode: StaticElement) => {
241
+ if (isExplicitRepeatTemplateElement(firstRepeatInstanceNode)) {
242
+ return firstRepeatInstanceNode;
243
+ }
244
+
245
+ return cloneStaticElementStructure(firstRepeatInstanceNode);
246
+
247
+ // TODO: We previously **intended** to check for duplicate explicit repeat
248
+ // templates (i.e. defined with a `jr:template` attribute). This was
249
+ // **partially** handled by defining a (temporary/local) mapping from the
250
+ // repeat's `BindDefinition` to an already-parsed explicit template element
251
+ // (if any). Identifying duplicates **should** have been handled by
252
+ // determining that an entry for the same binding already existed. **BUT NO
253
+ // ENTRY WAS NEVER WRITTEN!** This comment is now intended to recognize:
254
+ //
255
+ // 1. ... that the intended behavior was never implemented correctly in the
256
+ // first place, and we are not making any changes to that intended aspect
257
+ // of engine behavior/semantics by eliminating the flawed implementation
258
+ // now.
259
+ //
260
+ // 2. ... that whether this behavior should have even been implemented was
261
+ // also an open question! The previous text of this
262
+ // comment's conceptual successor is preserved below, either for clarity in review or for logner-term posterity.
263
+ //
264
+ // - - -
265
+ //
266
+ // Previous text of this comment:
267
+ //
268
+ // > TODO: this is under the assumption that for any depth > 1, if a
269
+ // > template has already been defined for the given form definition, any
270
+ // > subsequent nodes matching the repeat's nodeset are implicitly default
271
+ // > instances. Is this right?
272
+ };
273
+
274
+ export interface ControlledRepeatDefinition extends RepeatDefinition {
275
+ readonly count: RepeatCountControlExpression;
276
+ }
277
+
278
+ export interface UncontrolledRepeatDefinition extends RepeatDefinition {
279
+ readonly count: null;
280
+ }
281
+
282
+ /**
283
+ * Represents a definition of the combined concepts colloquially called a
284
+ * "repeat", as defined by a form, where those concepts include:
285
+ *
286
+ * - A {@link RepeatElementDefinition}—corresponding to a `<repeat>` {@link https://getodk.github.io/xforms-spec/#body-elements | body element}—which is associated with the nodeset referencing the "repeat template" and
287
+ * all "repeat instances" (see below points describing both concepts in more detail). The presence of such a body element determines whether to produce a repeat definition (rather than e.g. a {@link SubtreeDefinition}).
288
+ *
289
+ * - A "repeat template", defined by a form either
290
+ * explicitly,
291
+ * or derived from the structure of the first form-defined "repeat instance"
292
+ * (as described in the next point).
293
+ *
294
+ * - A sequence of one or more model instance nodes, each representing a "repeat instance"
295
+ * defined by the form. These nodes contribute to the definition in the following ways:
296
+ *
297
+ * - If an explicit "repeat template" is not defined for
298
+ * the "repeat", one is derived from the **structure** (but not the values!)
299
+ * of the first such model instance node.
300
+ *
301
+ * - If the "repeat" is {@link ControlledRepeatDefinition | controlled} (i.e. by either a `jr:count` or `jr:noAddRemove` {@link https://getodk.github.io/xforms-spec/#body-attributes | attribute} on the associated {@link RepeatElementDefinition}
302
+ *
303
+ * (For construction of this
304
+ * definition, all other referenced instance nodes are **consumed** in the
305
+ * process of building the repeat definition's subtree of a
306
+ * {@link RootDefinition}, ensuring that one repeat definition is produced for
307
+ * all applicable nodes; they are later referenced for construction of a
308
+ * form's {@link PrimaryInstance | instance state}.)
309
+ *
310
+ * Combined, these concepts produce the details required to instantiate the
311
+ * {@link RepeatRange} and {@link RepeatInstance} instance state nodes
312
+ * associated with a defined repeat.
313
+ */
314
+ export class RepeatDefinition extends DescendentNodeDefinition<'repeat', RepeatElementDefinition> {
315
+ static from(
316
+ parent: ParentNodeDefinition,
317
+ bind: BindDefinition,
318
+ bodyElement: RepeatElementDefinition,
319
+ instanceNodes: RepeatInstanceNodes
320
+ ): AnyRepeatDefinition;
321
+ static from(
322
+ parent: ParentNodeDefinition,
323
+ bind: BindDefinition,
324
+ bodyElement: RepeatElementDefinition,
325
+ instanceNodes: RepeatInstanceNodes
326
+ ): RepeatDefinition {
327
+ return new this(parent, bind, bodyElement, instanceNodes);
328
+ }
329
+
330
+ readonly type = 'repeat';
331
+ readonly children: readonly ChildNodeDefinition[];
332
+ readonly count: RepeatCountControlExpression | null;
333
+ readonly template: StaticElement;
334
+ readonly namespaceDeclarations: NamespaceDeclarationMap;
335
+ readonly qualifiedName: QualifiedName;
336
+
337
+ private constructor(
338
+ parent: ParentNodeDefinition,
339
+ bind: BindDefinition,
340
+ bodyElement: RepeatElementDefinition,
341
+ instanceNodes: RepeatInstanceNodes
342
+ ) {
343
+ super(parent, bind, bodyElement);
344
+
345
+ const { root } = parent;
346
+ const [instanceNode] = instanceNodes;
347
+ const template = parseRepeatTemplateElement(instanceNode);
348
+ const self = this as AnyRepeatDefinition;
349
+
350
+ this.template = template;
351
+ this.qualifiedName = template.qualifiedName;
352
+ this.namespaceDeclarations = new NamespaceDeclarationMap(this);
353
+ this.children = root.buildSubtree(self, template);
354
+
355
+ const initialCount = this.omitTemplate(instanceNodes).length;
356
+
357
+ this.count = RepeatCountControlExpression.from(bodyElement, initialCount);
358
+ }
359
+
360
+ isControlled(): this is ControlledRepeatDefinition {
361
+ return this.count != null;
362
+ }
363
+
364
+ isUncontrolled(): this is UncontrolledRepeatDefinition {
365
+ return this.count == null;
366
+ }
367
+
368
+ omitTemplate(instanceNodes: readonly StaticElement[]): readonly StaticElement[] {
369
+ return instanceNodes.filter((instanceNode) => {
370
+ return instanceNode !== this.template;
371
+ });
372
+ }
373
+
374
+ toJSON(): object {
375
+ return {};
376
+ }
377
+ }
378
+
379
+ // prettier-ignore
380
+ export type AnyRepeatDefinition =
381
+ | ControlledRepeatDefinition
382
+ | UncontrolledRepeatDefinition;
@@ -5,10 +5,7 @@ import { escapeXMLText } from '../../lib/xml-serialization.ts';
5
5
  import type { RootDefinition } from './RootDefinition.ts';
6
6
 
7
7
  interface RootAttributeSource {
8
- readonly namespaceURI: string | null;
9
- readonly nodeName: string;
10
- readonly prefix: string | null;
11
- readonly localName: string;
8
+ readonly qualifiedName: QualifiedName;
12
9
  readonly value: string;
13
10
  }
14
11
 
@@ -25,16 +22,18 @@ export class RootAttributeDefinition implements NamedNodeDefinition {
25
22
  readonly value: string;
26
23
 
27
24
  constructor(root: RootDefinition, source: RootAttributeSource) {
28
- const { namespaceURI, nodeName, value } = source;
25
+ const { qualifiedName, value } = source;
29
26
 
30
27
  this.parent = root;
31
- this.qualifiedName = new QualifiedName(source);
28
+ this.qualifiedName = qualifiedName;
32
29
  this.value = value;
33
30
 
34
31
  // We serialize namespace declarations separately
35
- if (namespaceURI === XMLNS_NAMESPACE_URI) {
32
+ if (qualifiedName.namespaceURI?.href === XMLNS_NAMESPACE_URI) {
36
33
  this.serializedXML = '';
37
34
  } else {
35
+ const nodeName = qualifiedName.getPrefixedName();
36
+
38
37
  this.serializedXML = ` ${nodeName}="${escapeXMLText(value, true)}"`;
39
38
  }
40
39
  }