@getodk/xforms-engine 0.3.0 → 0.5.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 (429) hide show
  1. package/dist/client/BaseNode.d.ts +15 -5
  2. package/dist/client/BaseValueNode.d.ts +32 -0
  3. package/dist/client/EngineConfig.d.ts +49 -49
  4. package/dist/client/GroupNode.d.ts +2 -3
  5. package/dist/client/InputNode.d.ts +53 -0
  6. package/dist/client/ModelValueNode.d.ts +13 -9
  7. package/dist/client/NodeAppearances.d.ts +1 -2
  8. package/dist/client/NoteNode.d.ts +3 -4
  9. package/dist/client/RootNode.d.ts +36 -10
  10. package/dist/client/SelectNode.d.ts +4 -5
  11. package/dist/client/SubtreeNode.d.ts +1 -2
  12. package/dist/client/TextRange.d.ts +3 -4
  13. package/dist/client/TriggerNode.d.ts +25 -0
  14. package/dist/client/ValueType.d.ts +3 -0
  15. package/dist/client/constants.d.ts +50 -1
  16. package/dist/client/hierarchy.d.ts +9 -5
  17. package/dist/client/identity.d.ts +14 -0
  18. package/dist/client/index.d.ts +0 -1
  19. package/dist/client/node-types.d.ts +3 -1
  20. package/dist/client/repeat/BaseRepeatRangeNode.d.ts +1 -2
  21. package/dist/client/repeat/RepeatInstanceNode.d.ts +2 -3
  22. package/dist/client/repeat/RepeatRangeControlledNode.d.ts +1 -2
  23. package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +1 -2
  24. package/dist/client/resources.d.ts +93 -0
  25. package/dist/client/submission/SubmissionData.d.ts +7 -0
  26. package/dist/client/submission/SubmissionDefinition.d.ts +14 -0
  27. package/dist/client/submission/SubmissionInstanceFile.d.ts +6 -0
  28. package/dist/client/submission/SubmissionOptions.d.ts +23 -0
  29. package/dist/client/submission/SubmissionResult.d.ts +91 -0
  30. package/dist/client/submission/SubmissionState.d.ts +12 -0
  31. package/dist/client/unsupported/RangeNode.d.ts +9 -0
  32. package/dist/client/unsupported/RankNode.d.ts +9 -0
  33. package/dist/client/unsupported/UnsupportedControlNode.d.ts +32 -0
  34. package/dist/client/unsupported/UploadNode.d.ts +9 -0
  35. package/dist/client/validation.d.ts +2 -3
  36. package/dist/error/ErrorProductionDesignPendingError.d.ts +7 -0
  37. package/dist/error/ValueTypeInvariantError.d.ts +17 -0
  38. package/dist/error/XPathFunctionalityError.d.ts +14 -0
  39. package/dist/error/XPathFunctionalityNotSupportedError.d.ts +7 -0
  40. package/dist/error/XPathFunctionalityPendingError.d.ts +7 -0
  41. package/dist/index.d.ts +16 -4
  42. package/dist/index.js +8559 -4700
  43. package/dist/index.js.map +1 -1
  44. package/dist/instance/Group.d.ts +9 -5
  45. package/dist/instance/InputControl.d.ts +36 -0
  46. package/dist/instance/ModelValue.d.ts +16 -27
  47. package/dist/instance/Note.d.ts +11 -5
  48. package/dist/instance/PrimaryInstance.d.ts +84 -0
  49. package/dist/instance/Root.d.ts +31 -28
  50. package/dist/instance/SelectField.d.ts +13 -6
  51. package/dist/instance/Subtree.d.ts +10 -6
  52. package/dist/instance/TriggerControl.d.ts +47 -0
  53. package/dist/instance/abstract/DescendantNode.d.ts +33 -26
  54. package/dist/instance/abstract/InstanceNode.d.ts +50 -31
  55. package/dist/instance/abstract/UnsupportedControl.d.ts +53 -0
  56. package/dist/instance/abstract/ValueNode.d.ts +48 -0
  57. package/dist/instance/children.d.ts +0 -1
  58. package/dist/instance/hierarchy.d.ts +13 -8
  59. package/dist/instance/identity.d.ts +2 -7
  60. package/dist/instance/index.d.ts +0 -1
  61. package/dist/instance/internal-api/EvaluationContext.d.ts +53 -13
  62. package/dist/instance/internal-api/InstanceConfig.d.ts +8 -3
  63. package/dist/instance/internal-api/InstanceValueContext.d.ts +20 -0
  64. package/dist/instance/internal-api/PrimaryInstanceDocument.d.ts +36 -0
  65. package/dist/instance/internal-api/TranslationContext.d.ts +3 -3
  66. package/dist/instance/internal-api/ValidationContext.d.ts +12 -6
  67. package/dist/instance/internal-api/ValueContext.d.ts +5 -5
  68. package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +14 -0
  69. package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +31 -0
  70. package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +18 -0
  71. package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +17 -0
  72. package/dist/instance/repeat/BaseRepeatRange.d.ts +40 -85
  73. package/dist/instance/repeat/RepeatInstance.d.ts +11 -30
  74. package/dist/instance/repeat/RepeatRangeControlled.d.ts +3 -4
  75. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +3 -4
  76. package/dist/instance/resource.d.ts +1 -2
  77. package/dist/instance/text/TextChunk.d.ts +0 -1
  78. package/dist/instance/text/TextRange.d.ts +1 -2
  79. package/dist/instance/unsupported/RangeControl.d.ts +6 -0
  80. package/dist/instance/unsupported/RankControl.d.ts +6 -0
  81. package/dist/instance/unsupported/UploadControl.d.ts +6 -0
  82. package/dist/integration/xpath/EngineXPathEvaluator.d.ts +14 -0
  83. package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +71 -0
  84. package/dist/integration/xpath/adapter/engineDOMAdapter.d.ts +5 -0
  85. package/dist/integration/xpath/adapter/kind.d.ts +32 -0
  86. package/dist/integration/xpath/adapter/names.d.ts +16 -0
  87. package/dist/integration/xpath/adapter/traversal.d.ts +25 -0
  88. package/dist/integration/xpath/adapter/values.d.ts +2 -0
  89. package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +19 -0
  90. package/dist/integration/xpath/static-dom/StaticDocument.d.ts +16 -0
  91. package/dist/integration/xpath/static-dom/StaticElement.d.ts +40 -0
  92. package/dist/integration/xpath/static-dom/StaticNamedNode.d.ts +17 -0
  93. package/dist/integration/xpath/static-dom/StaticNode.d.ts +33 -0
  94. package/dist/integration/xpath/static-dom/StaticText.d.ts +16 -0
  95. package/dist/lib/TokenListParser.d.ts +3 -3
  96. package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +3 -0
  97. package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +3 -0
  98. package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +4 -0
  99. package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +4 -0
  100. package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +3 -0
  101. package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +8 -0
  102. package/dist/lib/codecs/DecimalValueCodec.d.ts +6 -0
  103. package/dist/lib/codecs/IntValueCodec.d.ts +6 -0
  104. package/dist/lib/codecs/StringValueCodec.d.ts +4 -0
  105. package/dist/lib/codecs/ValueCodec.d.ts +30 -0
  106. package/dist/lib/codecs/ValueTypePlaceholderCodec.d.ts +12 -0
  107. package/dist/lib/codecs/getSharedValueCodec.d.ts +47 -0
  108. package/dist/lib/dom/query.d.ts +4 -2
  109. package/dist/lib/reactivity/createChildrenState.d.ts +7 -6
  110. package/dist/lib/reactivity/createComputedExpression.d.ts +19 -7
  111. package/dist/lib/reactivity/createInstanceValueState.d.ts +40 -0
  112. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +2 -3
  113. package/dist/lib/reactivity/createSelectItems.d.ts +0 -1
  114. package/dist/lib/reactivity/createTranslationState.d.ts +19 -0
  115. package/dist/lib/reactivity/createValueState.d.ts +6 -11
  116. package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +4 -5
  117. package/dist/lib/reactivity/node-state/createClientState.d.ts +0 -1
  118. package/dist/lib/reactivity/node-state/createCurrentState.d.ts +0 -1
  119. package/dist/lib/reactivity/node-state/createEngineState.d.ts +0 -1
  120. package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +0 -1
  121. package/dist/lib/reactivity/node-state/createSpecifiedPropertyDescriptor.d.ts +0 -1
  122. package/dist/lib/reactivity/node-state/createSpecifiedState.d.ts +0 -1
  123. package/dist/lib/reactivity/node-state/representations.d.ts +0 -1
  124. package/dist/lib/reactivity/scope.d.ts +0 -1
  125. package/dist/lib/reactivity/text/createFieldHint.d.ts +1 -2
  126. package/dist/lib/reactivity/text/createNodeLabel.d.ts +1 -2
  127. package/dist/lib/reactivity/text/createNoteText.d.ts +1 -2
  128. package/dist/lib/reactivity/text/createTextRange.d.ts +0 -1
  129. package/dist/lib/reactivity/types.d.ts +0 -1
  130. package/dist/lib/reactivity/validation/createAggregatedViolations.d.ts +0 -1
  131. package/dist/lib/reactivity/validation/createValidation.d.ts +0 -1
  132. package/dist/lib/xml-serialization.d.ts +41 -0
  133. package/dist/parse/XFormDOM.d.ts +42 -0
  134. package/dist/{XFormDefinition.d.ts → parse/XFormDefinition.d.ts} +3 -5
  135. package/dist/parse/attachments/FormAttachmentResource.d.ts +27 -0
  136. package/dist/{body → parse/body}/BodyDefinition.d.ts +16 -11
  137. package/dist/{body → parse/body}/BodyElementDefinition.d.ts +7 -7
  138. package/dist/{body → parse/body}/RepeatElementDefinition.d.ts +3 -4
  139. package/dist/{body → parse/body}/UnsupportedBodyElementDefinition.d.ts +0 -1
  140. package/dist/parse/body/appearance/inputAppearanceParser.d.ts +3 -0
  141. package/dist/{body → parse/body}/appearance/selectAppearanceParser.d.ts +1 -2
  142. package/dist/{body → parse/body}/appearance/structureElementAppearanceParser.d.ts +1 -2
  143. package/dist/parse/body/appearance/unknownAppearanceParser.d.ts +3 -0
  144. package/dist/{body → parse/body}/control/ControlDefinition.d.ts +3 -4
  145. package/dist/{body/control/InputDefinition.d.ts → parse/body/control/InputControlDefinition.d.ts} +2 -3
  146. package/dist/parse/body/control/RangeControlDefinition.d.ts +11 -0
  147. package/dist/parse/body/control/RankControlDefinition.d.ts +11 -0
  148. package/dist/parse/body/control/TriggerControlDefinition.d.ts +11 -0
  149. package/dist/parse/body/control/UploadControlDefinition.d.ts +11 -0
  150. package/dist/{body → parse/body}/control/select/ItemDefinition.d.ts +2 -3
  151. package/dist/{body → parse/body}/control/select/ItemsetDefinition.d.ts +4 -5
  152. package/dist/{body → parse/body}/control/select/ItemsetNodesetContext.d.ts +1 -4
  153. package/dist/{body → parse/body}/control/select/SelectDefinition.d.ts +3 -12
  154. package/dist/{body → parse/body}/group/BaseGroupDefinition.d.ts +3 -5
  155. package/dist/{body → parse/body}/group/LogicalGroupDefinition.d.ts +0 -1
  156. package/dist/{body → parse/body}/group/PresentationGroupDefinition.d.ts +1 -2
  157. package/dist/{body → parse/body}/group/StructuralGroupDefinition.d.ts +0 -1
  158. package/dist/{model/BindComputation.d.ts → parse/expression/BindComputationExpression.d.ts} +5 -6
  159. package/dist/{body/control/select → parse/expression}/ItemsetNodesetExpression.d.ts +2 -3
  160. package/dist/{body/control/select → parse/expression}/ItemsetValueExpression.d.ts +2 -3
  161. package/dist/parse/expression/RepeatCountControlExpression.d.ts +2 -3
  162. package/dist/parse/expression/TextLiteralExpression.d.ts +9 -0
  163. package/dist/parse/expression/TextOutputExpression.d.ts +7 -0
  164. package/dist/parse/expression/TextReferenceExpression.d.ts +7 -0
  165. package/dist/parse/expression/TextTranslationExpression.d.ts +8 -0
  166. package/dist/parse/expression/abstract/DependencyContext.d.ts +7 -0
  167. package/dist/{expression → parse/expression/abstract}/DependentExpression.d.ts +4 -6
  168. package/dist/parse/expression/abstract/TextChunkExpression.d.ts +17 -0
  169. package/dist/parse/model/BindDefinition.d.ts +38 -0
  170. package/dist/parse/model/BindTypeDefinition.d.ts +20 -0
  171. package/dist/{model → parse/model}/DescendentNodeDefinition.d.ts +0 -2
  172. package/dist/parse/model/FormSubmissionDefinition.d.ts +8 -0
  173. package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +4 -0
  174. package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +8 -0
  175. package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +8 -0
  176. package/dist/{model → parse/model}/LeafNodeDefinition.d.ts +4 -3
  177. package/dist/{model → parse/model}/ModelBindMap.d.ts +1 -2
  178. package/dist/{model → parse/model}/ModelDefinition.d.ts +3 -2
  179. package/dist/{model → parse/model}/NodeDefinition.d.ts +0 -2
  180. package/dist/parse/{NoteNodeDefinition.d.ts → model/NoteNodeDefinition.d.ts} +12 -13
  181. package/dist/{model → parse/model}/RepeatInstanceDefinition.d.ts +1 -2
  182. package/dist/{model → parse/model}/RepeatRangeDefinition.d.ts +2 -3
  183. package/dist/{model → parse/model}/RepeatTemplateDefinition.d.ts +2 -3
  184. package/dist/{model → parse/model}/RootDefinition.d.ts +5 -5
  185. package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +4 -0
  186. package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +7 -0
  187. package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +13 -0
  188. package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +14 -0
  189. package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +22 -0
  190. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.d.ts +23 -0
  191. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.d.ts +9 -0
  192. package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +5 -0
  193. package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +7 -0
  194. package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +13 -0
  195. package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +12 -0
  196. package/dist/{model → parse/model}/SubtreeDefinition.d.ts +1 -2
  197. package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +24 -0
  198. package/dist/parse/text/HintDefinition.d.ts +2 -3
  199. package/dist/parse/text/ItemLabelDefinition.d.ts +2 -3
  200. package/dist/parse/text/ItemsetLabelDefinition.d.ts +3 -4
  201. package/dist/parse/text/LabelDefinition.d.ts +5 -6
  202. package/dist/parse/text/MessageDefinition.d.ts +4 -5
  203. package/dist/parse/text/abstract/TextElementDefinition.d.ts +8 -9
  204. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +4 -7
  205. package/dist/parse/xpath/path-resolution.d.ts +0 -1
  206. package/dist/parse/xpath/predicate-analysis.d.ts +0 -1
  207. package/dist/parse/xpath/reference-parsing.d.ts +0 -1
  208. package/dist/parse/xpath/semantic-analysis.d.ts +5 -1
  209. package/dist/parse/xpath/syntax-traversal.d.ts +0 -1
  210. package/dist/solid.js +8398 -4543
  211. package/dist/solid.js.map +1 -1
  212. package/package.json +14 -12
  213. package/src/client/BaseNode.ts +17 -7
  214. package/src/client/BaseValueNode.ts +35 -0
  215. package/src/client/EngineConfig.ts +52 -51
  216. package/src/client/GroupNode.ts +2 -2
  217. package/src/client/InputNode.ts +77 -0
  218. package/src/client/ModelValueNode.ts +31 -8
  219. package/src/client/NodeAppearances.ts +1 -1
  220. package/src/client/NoteNode.ts +3 -3
  221. package/src/client/RootNode.ts +39 -9
  222. package/src/client/SelectNode.ts +5 -5
  223. package/src/client/SubtreeNode.ts +1 -1
  224. package/src/client/TextRange.ts +4 -5
  225. package/src/client/TriggerNode.ts +29 -0
  226. package/src/client/ValueType.ts +4 -0
  227. package/src/client/constants.ts +67 -0
  228. package/src/client/hierarchy.ts +16 -4
  229. package/src/client/identity.ts +16 -0
  230. package/src/client/node-types.ts +19 -5
  231. package/src/client/repeat/BaseRepeatRangeNode.ts +1 -1
  232. package/src/client/repeat/RepeatInstanceNode.ts +2 -2
  233. package/src/client/repeat/RepeatRangeControlledNode.ts +1 -1
  234. package/src/client/repeat/RepeatRangeUncontrolledNode.ts +1 -1
  235. package/src/client/resources.ts +118 -0
  236. package/src/client/submission/SubmissionData.ts +12 -0
  237. package/src/client/submission/SubmissionDefinition.ts +16 -0
  238. package/src/client/submission/SubmissionInstanceFile.ts +9 -0
  239. package/src/client/submission/SubmissionOptions.ts +28 -0
  240. package/src/client/submission/SubmissionResult.ts +124 -0
  241. package/src/client/submission/SubmissionState.ts +14 -0
  242. package/src/client/unsupported/RangeNode.ts +14 -0
  243. package/src/client/unsupported/RankNode.ts +14 -0
  244. package/src/client/unsupported/UnsupportedControlNode.ts +40 -0
  245. package/src/client/unsupported/UploadNode.ts +14 -0
  246. package/src/client/validation.ts +2 -2
  247. package/src/error/ErrorProductionDesignPendingError.ts +6 -0
  248. package/src/error/ValueTypeInvariantError.ts +22 -0
  249. package/src/error/XPathFunctionalityError.ts +26 -0
  250. package/src/error/XPathFunctionalityNotSupportedError.ts +18 -0
  251. package/src/error/XPathFunctionalityPendingError.ts +18 -0
  252. package/src/index.ts +16 -2
  253. package/src/instance/Group.ts +17 -5
  254. package/src/instance/InputControl.ts +119 -0
  255. package/src/instance/ModelValue.ts +47 -54
  256. package/src/instance/Note.ts +26 -10
  257. package/src/instance/PrimaryInstance.ts +244 -0
  258. package/src/instance/Root.ts +64 -132
  259. package/src/instance/SelectField.ts +62 -25
  260. package/src/instance/Subtree.ts +19 -7
  261. package/src/instance/{StringField.ts → TriggerControl.ts} +61 -30
  262. package/src/instance/abstract/DescendantNode.ts +92 -47
  263. package/src/instance/abstract/InstanceNode.ts +104 -98
  264. package/src/instance/abstract/UnsupportedControl.ts +174 -0
  265. package/src/instance/abstract/ValueNode.ts +127 -0
  266. package/src/instance/children.ts +83 -14
  267. package/src/instance/hierarchy.ts +36 -14
  268. package/src/instance/identity.ts +3 -9
  269. package/src/instance/index.ts +26 -8
  270. package/src/instance/internal-api/EvaluationContext.ts +61 -14
  271. package/src/instance/internal-api/InstanceConfig.ts +9 -2
  272. package/src/instance/internal-api/InstanceValueContext.ts +24 -0
  273. package/src/instance/internal-api/PrimaryInstanceDocument.ts +53 -0
  274. package/src/instance/internal-api/TranslationContext.ts +3 -2
  275. package/src/instance/internal-api/ValidationContext.ts +13 -5
  276. package/src/instance/internal-api/ValueContext.ts +5 -4
  277. package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +20 -0
  278. package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +42 -0
  279. package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +25 -0
  280. package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +23 -0
  281. package/src/instance/repeat/BaseRepeatRange.ts +51 -132
  282. package/src/instance/repeat/RepeatInstance.ts +20 -46
  283. package/src/instance/repeat/RepeatRangeControlled.ts +6 -6
  284. package/src/instance/repeat/RepeatRangeUncontrolled.ts +3 -5
  285. package/src/instance/resource.ts +1 -1
  286. package/src/instance/text/TextChunk.ts +1 -1
  287. package/src/instance/unsupported/RangeControl.ts +9 -0
  288. package/src/instance/unsupported/RankControl.ts +9 -0
  289. package/src/instance/unsupported/UploadControl.ts +9 -0
  290. package/src/integration/xpath/EngineXPathEvaluator.ts +22 -0
  291. package/src/integration/xpath/adapter/XFormsXPathNode.ts +126 -0
  292. package/src/integration/xpath/adapter/engineDOMAdapter.ts +57 -0
  293. package/src/integration/xpath/adapter/kind.ts +114 -0
  294. package/src/integration/xpath/adapter/names.ts +99 -0
  295. package/src/integration/xpath/adapter/traversal.ts +228 -0
  296. package/src/integration/xpath/adapter/values.ts +5 -0
  297. package/src/integration/xpath/static-dom/StaticAttribute.ts +33 -0
  298. package/src/integration/xpath/static-dom/StaticDocument.ts +38 -0
  299. package/src/integration/xpath/static-dom/StaticElement.ts +106 -0
  300. package/src/integration/xpath/static-dom/StaticNamedNode.ts +45 -0
  301. package/src/integration/xpath/static-dom/StaticNode.ts +68 -0
  302. package/src/integration/xpath/static-dom/StaticText.ts +28 -0
  303. package/src/lib/TokenListParser.ts +11 -7
  304. package/src/lib/client-reactivity/README.md +0 -0
  305. package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +12 -0
  306. package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +20 -0
  307. package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +17 -0
  308. package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +22 -0
  309. package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +21 -0
  310. package/src/lib/client-reactivity/submission/prepareSubmission.ts +172 -0
  311. package/src/lib/codecs/DecimalValueCodec.ts +46 -0
  312. package/src/lib/codecs/IntValueCodec.ts +100 -0
  313. package/src/lib/codecs/StringValueCodec.ts +11 -0
  314. package/src/lib/codecs/ValueCodec.ts +106 -0
  315. package/src/lib/codecs/ValueTypePlaceholderCodec.ts +19 -0
  316. package/src/lib/codecs/getSharedValueCodec.ts +77 -0
  317. package/src/lib/dom/query.ts +8 -1
  318. package/src/lib/reactivity/createChildrenState.ts +8 -6
  319. package/src/lib/reactivity/createComputedExpression.ts +59 -36
  320. package/src/lib/reactivity/createInstanceValueState.ts +166 -0
  321. package/src/lib/reactivity/createNoteReadonlyThunk.ts +12 -7
  322. package/src/lib/reactivity/createSelectItems.ts +23 -23
  323. package/src/lib/reactivity/createTranslationState.ts +61 -0
  324. package/src/lib/reactivity/createValueState.ts +64 -122
  325. package/src/lib/reactivity/materializeCurrentStateChildren.ts +7 -7
  326. package/src/lib/reactivity/node-state/createSpecifiedState.ts +1 -1
  327. package/src/lib/reactivity/text/createFieldHint.ts +1 -1
  328. package/src/lib/reactivity/text/createNodeLabel.ts +1 -1
  329. package/src/lib/reactivity/text/createNoteText.ts +1 -1
  330. package/src/lib/reactivity/text/createTextRange.ts +8 -7
  331. package/src/lib/reactivity/validation/createAggregatedViolations.ts +9 -4
  332. package/src/lib/reactivity/validation/createValidation.ts +2 -3
  333. package/src/lib/xml-serialization.ts +96 -0
  334. package/src/{XFormDOM.ts → parse/XFormDOM.ts} +110 -75
  335. package/src/{XFormDefinition.ts → parse/XFormDefinition.ts} +3 -8
  336. package/src/parse/attachments/FormAttachmentResource.ts +40 -0
  337. package/src/{body → parse/body}/BodyDefinition.ts +46 -29
  338. package/src/{body → parse/body}/BodyElementDefinition.ts +12 -6
  339. package/src/{body → parse/body}/RepeatElementDefinition.ts +7 -5
  340. package/src/{body → parse/body}/appearance/inputAppearanceParser.ts +2 -2
  341. package/src/{body → parse/body}/appearance/selectAppearanceParser.ts +1 -1
  342. package/src/{body → parse/body}/appearance/structureElementAppearanceParser.ts +1 -1
  343. package/src/parse/body/appearance/unknownAppearanceParser.ts +5 -0
  344. package/src/{body → parse/body}/control/ControlDefinition.ts +4 -4
  345. package/src/{body/control/InputDefinition.ts → parse/body/control/InputControlDefinition.ts} +3 -5
  346. package/src/parse/body/control/RangeControlDefinition.ts +26 -0
  347. package/src/parse/body/control/RankControlDefinition.ts +27 -0
  348. package/src/parse/body/control/TriggerControlDefinition.ts +26 -0
  349. package/src/parse/body/control/UploadControlDefinition.ts +26 -0
  350. package/src/{body → parse/body}/control/select/ItemDefinition.ts +2 -2
  351. package/src/{body → parse/body}/control/select/ItemsetDefinition.ts +5 -5
  352. package/src/{body → parse/body}/control/select/ItemsetNodesetContext.ts +1 -6
  353. package/src/{body → parse/body}/control/select/SelectDefinition.ts +3 -11
  354. package/src/{body → parse/body}/group/BaseGroupDefinition.ts +11 -22
  355. package/src/{body → parse/body}/group/PresentationGroupDefinition.ts +1 -1
  356. package/src/{model/BindComputation.ts → parse/expression/BindComputationExpression.ts} +8 -8
  357. package/src/{body/control/select → parse/expression}/ItemsetNodesetExpression.ts +2 -2
  358. package/src/{body/control/select → parse/expression}/ItemsetValueExpression.ts +2 -2
  359. package/src/parse/expression/RepeatCountControlExpression.ts +2 -2
  360. package/src/parse/expression/TextLiteralExpression.ts +19 -0
  361. package/src/parse/{text/OutputChunkDefinition.ts → expression/TextOutputExpression.ts} +4 -4
  362. package/src/parse/{text/ReferenceChunkDefinition.ts → expression/TextReferenceExpression.ts} +4 -4
  363. package/src/parse/{text/TranslationChunkDefinition.ts → expression/TextTranslationExpression.ts} +4 -4
  364. package/src/{expression → parse/expression/abstract}/DependencyContext.ts +0 -26
  365. package/src/{expression → parse/expression/abstract}/DependentExpression.ts +5 -16
  366. package/src/parse/expression/abstract/TextChunkExpression.ts +38 -0
  367. package/src/parse/model/BindDefinition.ts +104 -0
  368. package/src/parse/model/BindTypeDefinition.ts +175 -0
  369. package/src/{model → parse/model}/DescendentNodeDefinition.ts +0 -6
  370. package/src/parse/model/FormSubmissionDefinition.ts +44 -0
  371. package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +4 -0
  372. package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +41 -0
  373. package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +31 -0
  374. package/src/{model → parse/model}/LeafNodeDefinition.ts +4 -1
  375. package/src/{model → parse/model}/ModelBindMap.ts +6 -8
  376. package/src/parse/model/ModelDefinition.ts +24 -0
  377. package/src/{model → parse/model}/NodeDefinition.ts +0 -3
  378. package/src/parse/{NoteNodeDefinition.ts → model/NoteNodeDefinition.ts} +12 -12
  379. package/src/{model → parse/model}/RepeatRangeDefinition.ts +1 -1
  380. package/src/{model → parse/model}/RootDefinition.ts +4 -3
  381. package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +4 -0
  382. package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +12 -0
  383. package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +102 -0
  384. package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +40 -0
  385. package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +288 -0
  386. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.ts +222 -0
  387. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.ts +22 -0
  388. package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +414 -0
  389. package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +19 -0
  390. package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +29 -0
  391. package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +32 -0
  392. package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +149 -0
  393. package/src/parse/text/HintDefinition.ts +2 -2
  394. package/src/parse/text/ItemLabelDefinition.ts +2 -2
  395. package/src/parse/text/ItemsetLabelDefinition.ts +7 -7
  396. package/src/parse/text/LabelDefinition.ts +5 -5
  397. package/src/parse/text/MessageDefinition.ts +7 -7
  398. package/src/parse/text/abstract/TextElementDefinition.ts +14 -14
  399. package/src/parse/text/abstract/TextRangeDefinition.ts +4 -10
  400. package/src/parse/xpath/semantic-analysis.ts +29 -0
  401. package/dist/XFormDOM.d.ts +0 -32
  402. package/dist/XFormDataType.d.ts +0 -27
  403. package/dist/body/appearance/inputAppearanceParser.d.ts +0 -4
  404. package/dist/client/StringNode.d.ts +0 -47
  405. package/dist/expression/DependencyContext.d.ts +0 -13
  406. package/dist/instance/StringField.d.ts +0 -45
  407. package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -60
  408. package/dist/model/BindDefinition.d.ts +0 -34
  409. package/dist/parse/text/OutputChunkDefinition.d.ts +0 -8
  410. package/dist/parse/text/ReferenceChunkDefinition.d.ts +0 -8
  411. package/dist/parse/text/StaticTextChunkDefinition.d.ts +0 -10
  412. package/dist/parse/text/TranslationChunkDefinition.d.ts +0 -9
  413. package/dist/parse/text/abstract/TextChunkDefinition.d.ts +0 -18
  414. package/src/XFormDataType.ts +0 -64
  415. package/src/client/StringNode.ts +0 -52
  416. package/src/instance/internal-api/SubscribableDependency.ts +0 -61
  417. package/src/model/BindDefinition.ts +0 -106
  418. package/src/model/ModelDefinition.ts +0 -19
  419. package/src/parse/TODO.md +0 -3
  420. package/src/parse/text/StaticTextChunkDefinition.ts +0 -19
  421. package/src/parse/text/abstract/TextChunkDefinition.ts +0 -38
  422. /package/dist/{model → parse/model}/BindElement.d.ts +0 -0
  423. /package/src/{body → parse/body}/UnsupportedBodyElementDefinition.ts +0 -0
  424. /package/src/{body → parse/body}/group/LogicalGroupDefinition.ts +0 -0
  425. /package/src/{body → parse/body}/group/StructuralGroupDefinition.ts +0 -0
  426. /package/src/{model → parse/model}/BindElement.ts +0 -0
  427. /package/src/{model → parse/model}/RepeatInstanceDefinition.ts +0 -0
  428. /package/src/{model → parse/model}/RepeatTemplateDefinition.ts +0 -0
  429. /package/src/{model → parse/model}/SubtreeDefinition.ts +0 -0
@@ -80,7 +80,7 @@ export type ComputedPropertySpec<T> = Accessor<T>;
80
80
  /**
81
81
  * @see {@link StaticPropertySpec}
82
82
  */
83
- // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any
83
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, @typescript-eslint/no-explicit-any
84
84
  type NonStaticValue = Function | Signal<any> | SimpleAtomicState<any>;
85
85
 
86
86
  /**
@@ -1,7 +1,7 @@
1
1
  import { type Accessor } from 'solid-js';
2
2
  import type { TextRange } from '../../../client/TextRange.ts';
3
3
  import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
4
- import type { LeafNodeDefinition } from '../../../model/LeafNodeDefinition.ts';
4
+ import type { LeafNodeDefinition } from '../../../parse/model/LeafNodeDefinition.ts';
5
5
  import { createTextRange } from './createTextRange.ts';
6
6
 
7
7
  export const createFieldHint = (
@@ -1,7 +1,7 @@
1
1
  import { type Accessor } from 'solid-js';
2
2
  import type { TextRange } from '../../../client/TextRange.ts';
3
3
  import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
4
- import type { AnyNodeDefinition } from '../../../model/NodeDefinition.ts';
4
+ import type { AnyNodeDefinition } from '../../../parse/model/NodeDefinition.ts';
5
5
  import { createTextRange } from './createTextRange.ts';
6
6
 
7
7
  export const createNodeLabel = (
@@ -2,7 +2,7 @@ import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
2
2
  import type { Accessor } from 'solid-js';
3
3
  import type { TextRange } from '../../../client/TextRange.ts';
4
4
  import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
5
- import type { NoteTextDefinition } from '../../../parse/NoteNodeDefinition.ts';
5
+ import type { NoteTextDefinition } from '../../../parse/model/NoteNodeDefinition.ts';
6
6
  import { createTextRange } from './createTextRange.ts';
7
7
 
8
8
  // eslint-disable-next-line @typescript-eslint/sort-type-constituents
@@ -4,7 +4,7 @@ import type { TextChunkSource, TextRole } from '../../../client/TextRange.ts';
4
4
  import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
5
5
  import { TextChunk } from '../../../instance/text/TextChunk.ts';
6
6
  import { TextRange } from '../../../instance/text/TextRange.ts';
7
- import type { AnyTextChunkDefinition } from '../../../parse/text/abstract/TextChunkDefinition.ts';
7
+ import type { AnyTextChunkExpression } from '../../../parse/expression/abstract/TextChunkExpression.ts';
8
8
  import type { TextRangeDefinition } from '../../../parse/text/abstract/TextRangeDefinition.ts';
9
9
  import { createComputedExpression } from '../createComputedExpression.ts';
10
10
 
@@ -15,11 +15,11 @@ interface TextChunkComputation {
15
15
 
16
16
  const createComputedTextChunk = (
17
17
  context: EvaluationContext,
18
- textSource: AnyTextChunkDefinition
18
+ textSource: AnyTextChunkExpression
19
19
  ): TextChunkComputation => {
20
20
  const { source } = textSource;
21
21
 
22
- if (source === 'static') {
22
+ if (source === 'literal') {
23
23
  const { stringValue } = textSource;
24
24
 
25
25
  return {
@@ -29,7 +29,9 @@ const createComputedTextChunk = (
29
29
  }
30
30
 
31
31
  return context.scope.runTask(() => {
32
- const getText = createComputedExpression(context, textSource);
32
+ const getText = createComputedExpression(context, textSource, {
33
+ defaultValue: '',
34
+ });
33
35
 
34
36
  return {
35
37
  source,
@@ -40,17 +42,16 @@ const createComputedTextChunk = (
40
42
 
41
43
  const createTextChunks = (
42
44
  context: EvaluationContext,
43
- textSources: readonly AnyTextChunkDefinition[]
45
+ textSources: readonly AnyTextChunkExpression[]
44
46
  ): Accessor<readonly TextChunk[]> => {
45
47
  return context.scope.runTask(() => {
46
- const { root } = context;
47
48
  const chunkComputations = textSources.map((textSource) => {
48
49
  return createComputedTextChunk(context, textSource);
49
50
  });
50
51
 
51
52
  return createMemo(() => {
52
53
  return chunkComputations.map(({ source, getText }) => {
53
- return new TextChunk(root, source, getText());
54
+ return new TextChunk(context, source, getText());
54
55
  });
55
56
  });
56
57
  });
@@ -4,10 +4,11 @@ import type {
4
4
  AncestorNodeValidationState,
5
5
  DescendantNodeViolationReference,
6
6
  } from '../../../client/validation.ts';
7
- import type { AnyParentNode, AnyValueNode } from '../../../instance/hierarchy.ts';
7
+ import type { AnyParentNode } from '../../../instance/hierarchy.ts';
8
+ import type { ValidationContext } from '../../../instance/internal-api/ValidationContext.ts';
8
9
  import { createSharedNodeState } from '../node-state/createSharedNodeState.ts';
9
10
 
10
- const violationReference = (node: AnyValueNode): DescendantNodeViolationReference | null => {
11
+ const violationReference = (node: ValidationContext): DescendantNodeViolationReference | null => {
11
12
  const violation = node.getViolation();
12
13
 
13
14
  if (violation == null) {
@@ -31,9 +32,13 @@ const collectViolationReferences = (
31
32
  return context.getChildren().flatMap((child) => {
32
33
  switch (child.nodeType) {
33
34
  case 'model-value':
35
+ case 'input':
34
36
  case 'note':
35
- case 'string':
36
- case 'select': {
37
+ case 'select':
38
+ case 'range':
39
+ case 'rank':
40
+ case 'trigger':
41
+ case 'upload': {
37
42
  const reference = violationReference(child);
38
43
 
39
44
  if (reference == null) {
@@ -33,7 +33,7 @@ const engineViolationMessage = <Role extends ValidationTextRole>(
33
33
  role: Role
34
34
  ): Accessor<EngineViolationMessage<Role>> => {
35
35
  const messageText = VALIDATION_TEXT[role];
36
- const chunk = new TextChunk(context.root, 'static', messageText);
36
+ const chunk = new TextChunk(context, 'literal', messageText);
37
37
  const message = new TextRange('engine', role, [chunk]);
38
38
 
39
39
  return () => message;
@@ -75,9 +75,8 @@ const createConstraintValidation = (
75
75
  }
76
76
 
77
77
  const isValid = createComputedExpression(context, constraint, {
78
- arbitraryDependencies: [context],
78
+ defaultValue: true,
79
79
  });
80
-
81
80
  const message = createViolationMessage(context, 'constraintMsg', constraintMsg);
82
81
 
83
82
  return createMemo(() => {
@@ -0,0 +1,96 @@
1
+ declare const ESCAPED_XML_TEXT_BRAND: unique symbol;
2
+
3
+ export type EscapedXMLText = string & { readonly [ESCAPED_XML_TEXT_BRAND]: true };
4
+
5
+ const ATTR_REGEX = /[&<>"]/;
6
+ const CONTENT_REGEX = /[&<>]/;
7
+
8
+ /**
9
+ * This is based on the `escapeHTML` implementation in
10
+ * {@link https://github.com/ryansolid/dom-expressions} (Solid's JSX transform).
11
+ *
12
+ * @see {@link https://github.com/ryansolid/dom-expressions/pull/27} for
13
+ * motivation to derive this implementation approach.
14
+ *
15
+ * The intent is that this can be updated easily if the base implementation
16
+ * changes. As such, some aspects of this implementation differ from some of our
17
+ * typical code style preferences.
18
+ *
19
+ * Notable changes from the base implementation:
20
+ *
21
+ * - Formatting: automated only.
22
+ * - Naming: the {@link text} parameter is named `html` in the base
23
+ * implementation. That would be confusing if preserved.
24
+ * - Types:
25
+ * - Parameter types are added (of course)
26
+ * - Return type is branded as {@link EscapedXMLText}, to allow downstream
27
+ * checks that escaping has been performed. Return statements are cast
28
+ * accordingly.
29
+ * - {@link text} attempts to minimize risk of double-escaping by excluding
30
+ * that same branded type.
31
+ * - The '>' character is also escaped, necessary for producing valid XML.
32
+ *
33
+ * As with the base implementation, we leave some characters unescaped:
34
+ *
35
+ * - " (double quote): except when {@link attr} is `true`.
36
+ *
37
+ * - ' (single quote): on the assumption that attributes are always serialized
38
+ * in double quotes. If we ever move this to `@getodk/common`, we'd want to
39
+ * reconsider this assumption.
40
+ */
41
+ export const escapeXMLText = <Text extends string>(
42
+ text: Exclude<Text, EscapedXMLText>,
43
+ attr?: boolean
44
+ ): EscapedXMLText => {
45
+ const match = (attr ? ATTR_REGEX : CONTENT_REGEX).exec(text);
46
+ if (!match) return text as string as EscapedXMLText;
47
+ let index = 0;
48
+ let lastIndex = 0;
49
+ let out = '';
50
+ let escape = '';
51
+ for (index = match.index; index < text.length; index++) {
52
+ switch (text.charCodeAt(index)) {
53
+ case 34: // "
54
+ if (!attr) continue;
55
+ escape = '&quot;';
56
+ break;
57
+ case 38: // &
58
+ escape = '&amp;';
59
+ break;
60
+ case 60: // <
61
+ escape = '&lt;';
62
+ break;
63
+ case 62: // >
64
+ escape = '&gt;';
65
+ break;
66
+ default:
67
+ continue;
68
+ }
69
+ if (lastIndex !== index) out += text.substring(lastIndex, index);
70
+ lastIndex = index + 1;
71
+ out += escape;
72
+ }
73
+ return lastIndex !== index
74
+ ? ((out + text.substring(lastIndex, index)) as EscapedXMLText)
75
+ : (out as EscapedXMLText);
76
+ };
77
+
78
+ const serializeElementXML = (nodeName: string, children: string): string => {
79
+ if (children === '') {
80
+ return `<${nodeName}/>`;
81
+ }
82
+
83
+ // TODO: attributes
84
+ return `<${nodeName}>${children}</${nodeName}>`;
85
+ };
86
+
87
+ export const serializeParentElementXML = (
88
+ nodeName: string,
89
+ serializedChildren: readonly string[]
90
+ ): string => {
91
+ return serializeElementXML(nodeName, serializedChildren.join(''));
92
+ };
93
+
94
+ export const serializeLeafElementXML = (nodeName: string, xmlValue: EscapedXMLText): string => {
95
+ return serializeElementXML(nodeName, xmlValue.normalize());
96
+ };
@@ -1,5 +1,37 @@
1
1
  import { XFORMS_NAMESPACE_URI, XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
- import { XFormsXPathEvaluator } from '@getodk/xpath';
2
+ import type {
3
+ KnownAttributeLocalNamedElement,
4
+ LocalNamedElement,
5
+ } from '@getodk/common/types/dom.ts';
6
+ import { DefaultEvaluator } from '@getodk/xpath';
7
+
8
+ interface DOMBindElement extends KnownAttributeLocalNamedElement<'bind', 'nodeset'> {}
9
+
10
+ export interface DOMItextTranslationElement
11
+ extends KnownAttributeLocalNamedElement<'translation', 'lang'> {}
12
+
13
+ interface DOMInstanceElement extends LocalNamedElement<'instance'> {}
14
+
15
+ export interface DOMSecondaryInstanceElement
16
+ extends KnownAttributeLocalNamedElement<'instance', 'id'> {}
17
+
18
+ type AssertDOMSecondaryInstanceElement = (
19
+ element: DOMInstanceElement
20
+ ) => asserts element is DOMSecondaryInstanceElement;
21
+
22
+ const assertDOMSecondaryInstanceElement: AssertDOMSecondaryInstanceElement = (element) => {
23
+ if (!element.hasAttribute('id')) {
24
+ throw new Error('Invalid secondary instance element: missing `id` attribute');
25
+ }
26
+ };
27
+
28
+ type AssertDOMSecondaryInstanceElements = (
29
+ elements: readonly DOMInstanceElement[]
30
+ ) => asserts elements is readonly DOMSecondaryInstanceElement[];
31
+
32
+ const assertDOMSecondaryInstanceElements: AssertDOMSecondaryInstanceElements = (elements) => {
33
+ elements.forEach(assertDOMSecondaryInstanceElement);
34
+ };
3
35
 
4
36
  const domParser = new DOMParser();
5
37
 
@@ -145,61 +177,33 @@ const normalizeRepeatGroups = (body: Element): void => {
145
177
  }
146
178
  };
147
179
 
148
- interface NormalizedXForm {
149
- readonly xformDocument: XMLDocument;
150
- readonly rootEvaluator: XFormsXPathEvaluator;
151
- readonly html: Element;
152
- readonly body: Element;
153
- readonly normalizedXML: string;
154
- }
155
-
156
- interface XFormDOMNormalizationOptions {
157
- readonly isNormalized: boolean;
158
- }
159
-
160
180
  /**
161
- * Performs preprocess operations to normalize certain aspects of an XForm
162
- * structure for consistency when building up its runtime representations.
181
+ * Performs preprocess operations to normalize certain aspects of the body of an
182
+ * XForm, for consistency when parsing its runtime representations.
183
+ *
163
184
  * Currently this preprocessing:
164
185
  *
165
- * - Ensures consistent use of `ref` and `nodeset` where ambiguous in the
166
- * ODK XForms spec
167
- * - Ensures `<repeat>` body elements are always enclosed by a `<group>`
168
- * with the same `ref`
186
+ * - Ensures consistent use of `ref` and `nodeset` where ambiguous in the ODK
187
+ * XForms spec
188
+ * - Ensures `<repeat>` body elements are always enclosed by a `<group>` with
189
+ * the same `ref`
169
190
  */
170
- const parseNormalizedXForm = (
171
- sourceXML: string,
172
- options: XFormDOMNormalizationOptions
173
- ): NormalizedXForm => {
174
- const xformDocument: XMLDocument = domParser.parseFromString(sourceXML, 'text/xml');
175
- const rootEvaluator = new XFormsXPathEvaluator({
176
- rootNode: xformDocument,
177
- });
178
- const html = rootEvaluator.evaluateNonNullElement('/h:html');
179
- const body = rootEvaluator.evaluateNonNullElement('./h:body', {
180
- contextNode: html,
181
- });
182
-
183
- let normalizedXML: string;
191
+ const normalizeXFormBody = <T extends Element>(body: T): T => {
192
+ normalizeBodyRefNodesetAttributes(body);
193
+ normalizeRepeatGroups(body);
184
194
 
185
- if (options.isNormalized) {
186
- normalizedXML = sourceXML;
187
- } else {
188
- normalizeBodyRefNodesetAttributes(body);
189
- normalizeRepeatGroups(body);
190
-
191
- normalizedXML = html.outerHTML;
192
- }
193
-
194
- return {
195
- xformDocument,
196
- rootEvaluator,
197
- html,
198
- body,
199
- normalizedXML,
200
- };
195
+ return body;
201
196
  };
202
197
 
198
+ interface XFormDOMOptions {
199
+ readonly isNormalized: boolean;
200
+ }
201
+
202
+ /**
203
+ * @todo **Everything** in this class should be cacheable. Maybe not worth it
204
+ * for small forms, but may make a pretty substantial difference for very large
205
+ * forms (in bytes) in sessions creating multiple instances of the same form.
206
+ */
203
207
  export class XFormDOM {
204
208
  static from(sourceXML: string) {
205
209
  return new this(sourceXML, { isNormalized: false });
@@ -207,10 +211,6 @@ export class XFormDOM {
207
211
 
208
212
  protected readonly normalizedXML: string;
209
213
 
210
- // XPath
211
- readonly rootEvaluator: XFormsXPathEvaluator;
212
- readonly primaryInstanceEvaluator: XFormsXPathEvaluator;
213
-
214
214
  // Commonly accessed landmark nodes
215
215
  readonly xformDocument: XMLDocument;
216
216
 
@@ -220,59 +220,94 @@ export class XFormDOM {
220
220
  readonly title: Element;
221
221
 
222
222
  readonly model: Element;
223
+ readonly binds: readonly DOMBindElement[];
223
224
  readonly primaryInstance: Element;
224
225
  readonly primaryInstanceRoot: Element;
225
226
 
227
+ readonly itextTranslationElements: readonly DOMItextTranslationElement[];
228
+ readonly secondaryInstanceElements: readonly DOMSecondaryInstanceElement[];
229
+
226
230
  readonly body: Element;
227
231
 
228
232
  protected constructor(
229
233
  protected readonly sourceXML: string,
230
- options: XFormDOMNormalizationOptions
234
+ options: XFormDOMOptions
231
235
  ) {
232
- const normalizedXForm: NormalizedXForm = parseNormalizedXForm(sourceXML, options);
233
- const { xformDocument, html, body, rootEvaluator, normalizedXML } = normalizedXForm;
234
- const head = rootEvaluator.evaluateNonNullElement('./h:head', {
236
+ const evaluator = new DefaultEvaluator();
237
+ const xformDocument: XMLDocument = domParser.parseFromString(sourceXML, 'text/xml');
238
+ const html = evaluator.evaluateNonNullElement('/h:html', {
239
+ contextNode: xformDocument,
240
+ });
241
+
242
+ let body = evaluator.evaluateNonNullElement('./h:body', {
235
243
  contextNode: html,
236
244
  });
237
- const title = rootEvaluator.evaluateNonNullElement('./h:title', {
245
+ let normalizedXML: string;
246
+
247
+ if (options.isNormalized) {
248
+ normalizedXML = sourceXML;
249
+ } else {
250
+ body = normalizeXFormBody(body);
251
+
252
+ // TODO: if we keep doing normalization this way long term (or using the DOM
253
+ // for parsing long term, for that matter!), we should measure this. And we
254
+ // should measure against XMLSerializer while we're at it!
255
+ normalizedXML = xformDocument.documentElement.outerHTML;
256
+ }
257
+
258
+ const head = evaluator.evaluateNonNullElement('./h:head', {
259
+ contextNode: html,
260
+ });
261
+ const title = evaluator.evaluateNonNullElement('./h:title', {
238
262
  contextNode: head,
239
263
  });
240
- const model = rootEvaluator.evaluateNonNullElement('./xf:model', {
264
+ const model = evaluator.evaluateNonNullElement('./xf:model', {
241
265
  contextNode: head,
242
266
  });
243
- // TODO: Evidently primary instance root will not always have an id
244
- const primaryInstanceRoot = rootEvaluator.evaluateNonNullElement('./xf:instance/*[@id]', {
267
+ const binds = evaluator.evaluateNodes<DOMBindElement>('./xf:bind[@nodeset]', {
245
268
  contextNode: model,
246
269
  });
247
- // TODO: invert primary instance/root lookups
248
- const primaryInstance = rootEvaluator.evaluateNonNullElement('..', {
249
- contextNode: primaryInstanceRoot,
270
+
271
+ const instances = evaluator.evaluateNodes<DOMInstanceElement>('./xf:instance', {
272
+ contextNode: model,
250
273
  });
251
274
 
252
- this.normalizedXML = normalizedXML;
253
- this.rootEvaluator = rootEvaluator;
254
- this.primaryInstanceEvaluator = new XFormsXPathEvaluator({
255
- rootNode: primaryInstance,
275
+ const [primaryInstance, ...secondaryInstanceElements] = instances;
276
+
277
+ assertDOMSecondaryInstanceElements(secondaryInstanceElements);
278
+
279
+ if (primaryInstance == null) {
280
+ throw new Error('Form is missing primary instance');
281
+ }
282
+
283
+ // TODO: Evidently primary instance root will not always have an id
284
+ const primaryInstanceRoot = evaluator.evaluateNonNullElement('./*[@id]', {
285
+ contextNode: primaryInstance,
256
286
  });
287
+
288
+ const itextTranslationElements = evaluator.evaluateNodes<DOMItextTranslationElement>(
289
+ './xf:itext/xf:translation[@lang]',
290
+ {
291
+ contextNode: model,
292
+ }
293
+ );
294
+
295
+ this.normalizedXML = normalizedXML;
257
296
  this.xformDocument = xformDocument;
258
297
  this.html = html;
259
298
  this.head = head;
260
299
  this.title = title;
261
300
  this.model = model;
301
+ this.binds = binds;
262
302
  this.primaryInstance = primaryInstance;
263
303
  this.primaryInstanceRoot = primaryInstanceRoot;
304
+ this.itextTranslationElements = itextTranslationElements;
305
+ this.secondaryInstanceElements = secondaryInstanceElements;
264
306
  this.body = body;
265
307
  }
266
308
 
267
- // TODO: anticipating this will be an entry point for edits as well
268
- createInstance(): XFormDOM {
269
- return new XFormDOM(this.normalizedXML, { isNormalized: true });
270
- }
271
-
272
309
  toJSON() {
273
310
  const {
274
- rootEvaluator,
275
- primaryInstanceEvaluator,
276
311
  html,
277
312
  head,
278
313
  title,
@@ -1,9 +1,8 @@
1
- import { XFormDOM } from './XFormDOM.ts';
2
- import { BodyDefinition } from './body/BodyDefinition.ts';
1
+ import { BodyDefinition } from '../parse/body/BodyDefinition.ts';
3
2
  import { ModelDefinition } from './model/ModelDefinition.ts';
3
+ import { XFormDOM } from './XFormDOM.ts';
4
4
 
5
5
  export class XFormDefinition {
6
- readonly xformDOM: XFormDOM;
7
6
  readonly xformDocument: XMLDocument;
8
7
 
9
8
  readonly id: string;
@@ -14,11 +13,7 @@ export class XFormDefinition {
14
13
  readonly body: BodyDefinition;
15
14
  readonly model: ModelDefinition;
16
15
 
17
- constructor(readonly sourceXML: string) {
18
- const xformDOM = XFormDOM.from(sourceXML);
19
-
20
- this.xformDOM = xformDOM;
21
-
16
+ constructor(readonly xformDOM: XFormDOM) {
22
17
  const { primaryInstanceRoot, title, xformDocument } = xformDOM;
23
18
  const id = primaryInstanceRoot.getAttribute('id');
24
19
 
@@ -0,0 +1,40 @@
1
+ import type { JRResourceURL } from '@getodk/common/jr-resources/JRResourceURL.ts';
2
+
3
+ export type FormAttachmentDataType = 'media' | 'secondary-instance';
4
+
5
+ /**
6
+ * @todo This type anticipates work to support media form attachments, which
7
+ * will tend to be associated with binary data. The
8
+ * expectation is that:
9
+ *
10
+ * - {@link Blob} would be appropriate for representing data from attachment
11
+ * resources which are conventionally loaded to completion (where network
12
+ * conditions are favorable), such as images
13
+ *
14
+ * - {@link MediaSource} or {@link ReadableStream} may be more appropriate for
15
+ * representing data from resources which are conventionally streamed in a
16
+ * browser context (often regardless of network conditions), such as video and
17
+ * audio
18
+ */
19
+ // prettier-ignore
20
+ export type FormAttachmentMediaData =
21
+ | Blob
22
+ | MediaSource
23
+ | ReadableStream<unknown>;
24
+
25
+ export type FormAttachmentSecondaryInstanceData = string;
26
+
27
+ // prettier-ignore
28
+ type FormAttachmentData<DataType extends FormAttachmentDataType> =
29
+ DataType extends 'media'
30
+ ? FormAttachmentMediaData
31
+ : FormAttachmentSecondaryInstanceData;
32
+
33
+ export abstract class FormAttachmentResource<DataType extends FormAttachmentDataType> {
34
+ protected constructor(
35
+ readonly dataType: DataType,
36
+ readonly resourceURL: JRResourceURL,
37
+ readonly contentType: string,
38
+ readonly data: FormAttachmentData<DataType>
39
+ ) {}
40
+ }