@getodk/xforms-engine 0.4.0 → 0.6.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 (392) hide show
  1. package/README.md +1 -1
  2. package/dist/client/BaseNode.d.ts +18 -3
  3. package/dist/client/BaseValueNode.d.ts +32 -0
  4. package/dist/client/EngineConfig.d.ts +49 -48
  5. package/dist/client/GroupNode.d.ts +1 -0
  6. package/dist/client/InputNode.d.ts +82 -0
  7. package/dist/client/ModelValueNode.d.ts +13 -7
  8. package/dist/client/NoteNode.d.ts +26 -9
  9. package/dist/client/RangeNode.d.ts +36 -0
  10. package/dist/client/RankNode.d.ts +46 -0
  11. package/dist/client/RootNode.d.ts +37 -7
  12. package/dist/client/SelectNode.d.ts +47 -25
  13. package/dist/client/SubtreeNode.d.ts +1 -0
  14. package/dist/client/TriggerNode.d.ts +10 -6
  15. package/dist/client/ValueType.d.ts +3 -0
  16. package/dist/client/constants.d.ts +50 -0
  17. package/dist/client/hierarchy.d.ts +8 -8
  18. package/dist/client/identity.d.ts +14 -0
  19. package/dist/client/node-types.d.ts +3 -2
  20. package/dist/client/resources.d.ts +93 -0
  21. package/dist/client/submission/SubmissionData.d.ts +7 -0
  22. package/dist/client/submission/SubmissionDefinition.d.ts +14 -0
  23. package/dist/client/submission/SubmissionInstanceFile.d.ts +6 -0
  24. package/dist/client/submission/SubmissionOptions.d.ts +23 -0
  25. package/dist/client/submission/SubmissionResult.d.ts +91 -0
  26. package/dist/client/submission/SubmissionState.d.ts +12 -0
  27. package/dist/client/unsupported/UnsupportedControlNode.d.ts +1 -3
  28. package/dist/client/validation.d.ts +2 -2
  29. package/dist/error/ErrorProductionDesignPendingError.d.ts +7 -0
  30. package/dist/error/RankMissingValueError.d.ts +3 -0
  31. package/dist/error/RankValueTypeError.d.ts +6 -0
  32. package/dist/error/SelectValueTypeError.d.ts +15 -0
  33. package/dist/error/ValueTypeInvariantError.d.ts +17 -0
  34. package/dist/error/XFormsSpecViolationError.d.ts +2 -0
  35. package/dist/error/XPathFunctionalityError.d.ts +14 -0
  36. package/dist/error/XPathFunctionalityNotSupportedError.d.ts +7 -0
  37. package/dist/error/XPathFunctionalityPendingError.d.ts +7 -0
  38. package/dist/index.d.ts +12 -4
  39. package/dist/index.js +17864 -14655
  40. package/dist/index.js.map +1 -1
  41. package/dist/instance/Group.d.ts +10 -4
  42. package/dist/instance/InputControl.d.ts +38 -0
  43. package/dist/instance/ModelValue.d.ts +17 -25
  44. package/dist/instance/Note.d.ts +16 -21
  45. package/dist/instance/PrimaryInstance.d.ts +85 -0
  46. package/dist/instance/RangeControl.d.ts +34 -0
  47. package/dist/instance/RankControl.d.ts +40 -0
  48. package/dist/instance/Root.d.ts +30 -25
  49. package/dist/instance/SelectControl.d.ts +66 -0
  50. package/dist/instance/Subtree.d.ts +11 -5
  51. package/dist/instance/TriggerControl.d.ts +13 -19
  52. package/dist/instance/abstract/DescendantNode.d.ts +32 -25
  53. package/dist/instance/abstract/InstanceNode.d.ts +52 -30
  54. package/dist/instance/abstract/UnsupportedControl.d.ts +11 -3
  55. package/dist/instance/abstract/ValueNode.d.ts +47 -0
  56. package/dist/instance/hierarchy.d.ts +13 -12
  57. package/dist/instance/identity.d.ts +2 -7
  58. package/dist/instance/internal-api/EvaluationContext.d.ts +53 -12
  59. package/dist/instance/internal-api/InstanceConfig.d.ts +8 -2
  60. package/dist/instance/internal-api/InstanceValueContext.d.ts +22 -0
  61. package/dist/instance/internal-api/PrimaryInstanceDocument.d.ts +36 -0
  62. package/dist/instance/internal-api/TranslationContext.d.ts +3 -2
  63. package/dist/instance/internal-api/ValidationContext.d.ts +3 -4
  64. package/dist/instance/internal-api/ValueContext.d.ts +2 -1
  65. package/dist/instance/internal-api/submission/ClientReactiveSubmittableInstance.d.ts +14 -0
  66. package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +32 -0
  67. package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +19 -0
  68. package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +18 -0
  69. package/dist/instance/repeat/BaseRepeatRange.d.ts +40 -83
  70. package/dist/instance/repeat/RepeatInstance.d.ts +12 -29
  71. package/dist/instance/repeat/RepeatRangeControlled.d.ts +2 -2
  72. package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +2 -2
  73. package/dist/instance/resource.d.ts +1 -1
  74. package/dist/instance/text/TextRange.d.ts +1 -1
  75. package/dist/instance/unsupported/UploadControl.d.ts +3 -1
  76. package/dist/integration/xpath/EngineXPathEvaluator.d.ts +14 -0
  77. package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +71 -0
  78. package/dist/integration/xpath/adapter/engineDOMAdapter.d.ts +5 -0
  79. package/dist/integration/xpath/adapter/kind.d.ts +32 -0
  80. package/dist/integration/xpath/adapter/names.d.ts +6 -0
  81. package/dist/integration/xpath/adapter/traversal.d.ts +26 -0
  82. package/dist/integration/xpath/adapter/values.d.ts +2 -0
  83. package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +26 -0
  84. package/dist/integration/xpath/static-dom/StaticDocument.d.ts +15 -0
  85. package/dist/integration/xpath/static-dom/StaticElement.d.ts +48 -0
  86. package/dist/integration/xpath/static-dom/StaticNode.d.ts +33 -0
  87. package/dist/integration/xpath/static-dom/StaticText.d.ts +16 -0
  88. package/dist/lib/client-reactivity/submission/createInstanceSubmissionState.d.ts +3 -0
  89. package/dist/lib/client-reactivity/submission/createLeafNodeSubmissionState.d.ts +3 -0
  90. package/dist/lib/client-reactivity/submission/createNodeRangeSubmissionState.d.ts +4 -0
  91. package/dist/lib/client-reactivity/submission/createParentNodeSubmissionState.d.ts +4 -0
  92. package/dist/lib/client-reactivity/submission/createRootSubmissionState.d.ts +3 -0
  93. package/dist/lib/client-reactivity/submission/createValueNodeSubmissionState.d.ts +3 -0
  94. package/dist/lib/client-reactivity/submission/prepareSubmission.d.ts +8 -0
  95. package/dist/lib/codecs/DecimalValueCodec.d.ts +6 -0
  96. package/dist/lib/codecs/Geopoint/Geopoint.d.ts +48 -0
  97. package/dist/lib/codecs/Geopoint/GeopointValueCodec.d.ts +5 -0
  98. package/dist/lib/codecs/IntValueCodec.d.ts +6 -0
  99. package/dist/lib/codecs/NoteCodec.d.ts +8 -0
  100. package/dist/lib/codecs/RangeCodec.d.ts +8 -0
  101. package/dist/lib/codecs/StringValueCodec.d.ts +4 -0
  102. package/dist/lib/codecs/TriggerCodec.d.ts +7 -0
  103. package/dist/lib/codecs/ValueArrayCodec.d.ts +11 -0
  104. package/dist/lib/codecs/ValueCodec.d.ts +30 -0
  105. package/dist/lib/codecs/ValueTypePlaceholderCodec.d.ts +12 -0
  106. package/dist/lib/codecs/getNoteCodec.d.ts +3 -0
  107. package/dist/lib/codecs/getSelectCodec.d.ts +5 -0
  108. package/dist/lib/codecs/getSharedValueCodec.d.ts +48 -0
  109. package/dist/lib/codecs/items/BaseItemCodec.d.ts +9 -0
  110. package/dist/lib/codecs/items/MultipleValueItemCodec.d.ts +14 -0
  111. package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +24 -0
  112. package/dist/lib/dom/query.d.ts +4 -2
  113. package/dist/lib/names/NamespaceDeclaration.d.ts +45 -0
  114. package/dist/lib/names/NamespaceDeclarationMap.d.ts +137 -0
  115. package/dist/lib/names/NamespaceURL.d.ts +30 -0
  116. package/dist/lib/names/QualifiedName.d.ts +113 -0
  117. package/dist/lib/number-parsers.d.ts +2 -0
  118. package/dist/lib/reactivity/createChildrenState.d.ts +7 -5
  119. package/dist/lib/reactivity/createComputedExpression.d.ts +18 -5
  120. package/dist/lib/reactivity/createInstanceValueState.d.ts +40 -0
  121. package/dist/lib/reactivity/createItemCollection.d.ts +21 -0
  122. package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +2 -2
  123. package/dist/lib/reactivity/createTranslationState.d.ts +19 -0
  124. package/dist/lib/reactivity/createValueState.d.ts +6 -10
  125. package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +4 -4
  126. package/dist/lib/xml-serialization.d.ts +50 -0
  127. package/dist/parse/XFormDOM.d.ts +18 -7
  128. package/dist/parse/XFormDefinition.d.ts +1 -2
  129. package/dist/parse/attachments/FormAttachmentResource.d.ts +27 -0
  130. package/dist/parse/body/BodyDefinition.d.ts +4 -4
  131. package/dist/parse/body/RepeatElementDefinition.d.ts +1 -1
  132. package/dist/parse/body/appearance/inputAppearanceParser.d.ts +1 -1
  133. package/dist/parse/body/appearance/rangeAppearanceParser.d.ts +3 -0
  134. package/dist/parse/body/control/{InputDefinition.d.ts → InputControlDefinition.d.ts} +4 -1
  135. package/dist/parse/body/control/ItemDefinition.d.ts +14 -0
  136. package/dist/parse/body/control/ItemsetDefinition.d.ts +18 -0
  137. package/dist/parse/body/control/RangeControlDefinition.d.ts +31 -2
  138. package/dist/parse/body/control/RankControlDefinition.d.ts +7 -3
  139. package/dist/parse/body/control/{select/SelectDefinition.d.ts → SelectControlDefinition.d.ts} +9 -9
  140. package/dist/parse/expression/ItemsetNodesetExpression.d.ts +1 -1
  141. package/dist/parse/expression/ItemsetValueExpression.d.ts +1 -1
  142. package/dist/parse/expression/abstract/DependencyContext.d.ts +0 -5
  143. package/dist/parse/expression/abstract/DependentExpression.d.ts +2 -3
  144. package/dist/parse/model/BindDefinition.d.ts +6 -5
  145. package/dist/parse/model/BindPreloadDefinition.d.ts +42 -0
  146. package/dist/parse/model/BindTypeDefinition.d.ts +20 -0
  147. package/dist/parse/model/DescendentNodeDefinition.d.ts +4 -14
  148. package/dist/parse/model/FormSubmissionDefinition.d.ts +8 -0
  149. package/dist/parse/model/ItextTranslation/ItextTranslationDefinition.d.ts +4 -0
  150. package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +9 -0
  151. package/dist/parse/model/ItextTranslation/ItextTranslationsDefinition.d.ts +8 -0
  152. package/dist/parse/model/LeafNodeDefinition.d.ts +9 -4
  153. package/dist/parse/model/ModelBindMap.d.ts +1 -1
  154. package/dist/parse/model/ModelDefinition.d.ts +2 -0
  155. package/dist/parse/model/NodeDefinition.d.ts +16 -20
  156. package/dist/parse/model/NoteNodeDefinition.d.ts +9 -8
  157. package/dist/parse/model/RangeNodeDefinition.d.ts +41 -0
  158. package/dist/parse/model/RepeatInstanceDefinition.d.ts +7 -4
  159. package/dist/parse/model/RepeatRangeDefinition.d.ts +7 -4
  160. package/dist/parse/model/RepeatTemplateDefinition.d.ts +7 -4
  161. package/dist/parse/model/RootAttributeDefinition.d.ts +24 -0
  162. package/dist/parse/model/RootAttributeMap.d.ts +23 -0
  163. package/dist/parse/model/RootDefinition.d.ts +12 -9
  164. package/dist/parse/model/SecondaryInstance/SecondaryInstanceDefinition.d.ts +4 -0
  165. package/dist/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.d.ts +7 -0
  166. package/dist/parse/model/SecondaryInstance/SecondaryInstancesDefinition.d.ts +13 -0
  167. package/dist/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.d.ts +14 -0
  168. package/dist/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.d.ts +22 -0
  169. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.d.ts +23 -0
  170. package/dist/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.d.ts +9 -0
  171. package/dist/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.d.ts +5 -0
  172. package/dist/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.d.ts +7 -0
  173. package/dist/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.d.ts +13 -0
  174. package/dist/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.d.ts +12 -0
  175. package/dist/parse/model/SubtreeDefinition.d.ts +7 -4
  176. package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +23 -0
  177. package/dist/parse/text/ItemLabelDefinition.d.ts +1 -1
  178. package/dist/parse/text/ItemsetLabelDefinition.d.ts +2 -2
  179. package/dist/parse/text/abstract/TextElementDefinition.d.ts +1 -1
  180. package/dist/parse/text/abstract/TextRangeDefinition.d.ts +0 -2
  181. package/dist/parse/xpath/semantic-analysis.d.ts +6 -3
  182. package/dist/solid.js +15437 -12246
  183. package/dist/solid.js.map +1 -1
  184. package/package.json +18 -13
  185. package/src/client/BaseNode.ts +21 -6
  186. package/src/client/BaseValueNode.ts +35 -0
  187. package/src/client/EngineConfig.ts +52 -51
  188. package/src/client/GroupNode.ts +1 -0
  189. package/src/client/InputNode.ts +113 -0
  190. package/src/client/ModelValueNode.ts +31 -7
  191. package/src/client/NoteNode.ts +45 -9
  192. package/src/client/RangeNode.ts +51 -0
  193. package/src/client/RankNode.ts +54 -0
  194. package/src/client/RootNode.ts +43 -7
  195. package/src/client/SelectNode.ts +53 -26
  196. package/src/client/SubtreeNode.ts +1 -0
  197. package/src/client/TriggerNode.ts +12 -6
  198. package/src/client/ValueType.ts +4 -0
  199. package/src/client/constants.ts +67 -0
  200. package/src/client/hierarchy.ts +12 -13
  201. package/src/client/identity.ts +16 -0
  202. package/src/client/node-types.ts +13 -7
  203. package/src/client/resources.ts +118 -0
  204. package/src/client/submission/SubmissionData.ts +12 -0
  205. package/src/client/submission/SubmissionDefinition.ts +16 -0
  206. package/src/client/submission/SubmissionInstanceFile.ts +9 -0
  207. package/src/client/submission/SubmissionOptions.ts +28 -0
  208. package/src/client/submission/SubmissionResult.ts +124 -0
  209. package/src/client/submission/SubmissionState.ts +14 -0
  210. package/src/client/unsupported/UnsupportedControlNode.ts +2 -6
  211. package/src/client/validation.ts +2 -2
  212. package/src/error/ErrorProductionDesignPendingError.ts +6 -0
  213. package/src/error/RankMissingValueError.ts +5 -0
  214. package/src/error/RankValueTypeError.ts +13 -0
  215. package/src/error/SelectValueTypeError.ts +22 -0
  216. package/src/error/ValueTypeInvariantError.ts +22 -0
  217. package/src/error/XFormsSpecViolationError.ts +1 -0
  218. package/src/error/XPathFunctionalityError.ts +26 -0
  219. package/src/error/XPathFunctionalityNotSupportedError.ts +18 -0
  220. package/src/error/XPathFunctionalityPendingError.ts +18 -0
  221. package/src/index.ts +12 -13
  222. package/src/instance/Group.ts +18 -5
  223. package/src/instance/InputControl.ts +159 -0
  224. package/src/instance/ModelValue.ts +48 -53
  225. package/src/instance/Note.ts +40 -49
  226. package/src/instance/PrimaryInstance.ts +245 -0
  227. package/src/instance/RangeControl.ts +113 -0
  228. package/src/instance/RankControl.ts +199 -0
  229. package/src/instance/Root.ts +63 -134
  230. package/src/instance/SelectControl.ts +219 -0
  231. package/src/instance/Subtree.ts +20 -7
  232. package/src/instance/TriggerControl.ts +44 -66
  233. package/src/instance/abstract/DescendantNode.ts +91 -51
  234. package/src/instance/abstract/InstanceNode.ts +113 -107
  235. package/src/instance/abstract/UnsupportedControl.ts +29 -5
  236. package/src/instance/abstract/ValueNode.ts +128 -0
  237. package/src/instance/children.ts +80 -40
  238. package/src/instance/hierarchy.ts +39 -30
  239. package/src/instance/identity.ts +3 -9
  240. package/src/instance/index.ts +25 -7
  241. package/src/instance/internal-api/EvaluationContext.ts +60 -13
  242. package/src/instance/internal-api/InstanceConfig.ts +9 -2
  243. package/src/instance/internal-api/InstanceValueContext.ts +26 -0
  244. package/src/instance/internal-api/PrimaryInstanceDocument.ts +53 -0
  245. package/src/instance/internal-api/TranslationContext.ts +3 -2
  246. package/src/instance/internal-api/ValidationContext.ts +3 -4
  247. package/src/instance/internal-api/ValueContext.ts +2 -1
  248. package/src/instance/internal-api/submission/ClientReactiveSubmittableInstance.ts +20 -0
  249. package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +43 -0
  250. package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +26 -0
  251. package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +24 -0
  252. package/src/instance/repeat/BaseRepeatRange.ts +52 -131
  253. package/src/instance/repeat/RepeatInstance.ts +21 -46
  254. package/src/instance/repeat/RepeatRangeControlled.ts +5 -5
  255. package/src/instance/repeat/RepeatRangeUncontrolled.ts +2 -4
  256. package/src/instance/resource.ts +5 -2
  257. package/src/instance/text/TextChunk.ts +1 -1
  258. package/src/instance/unsupported/UploadControl.ts +5 -1
  259. package/src/integration/xpath/EngineXPathEvaluator.ts +22 -0
  260. package/src/integration/xpath/adapter/XFormsXPathNode.ts +126 -0
  261. package/src/integration/xpath/adapter/engineDOMAdapter.ts +57 -0
  262. package/src/integration/xpath/adapter/kind.ts +114 -0
  263. package/src/integration/xpath/adapter/names.ts +148 -0
  264. package/src/integration/xpath/adapter/traversal.ts +229 -0
  265. package/src/integration/xpath/adapter/values.ts +5 -0
  266. package/src/integration/xpath/static-dom/StaticAttribute.ts +41 -0
  267. package/src/integration/xpath/static-dom/StaticDocument.ts +36 -0
  268. package/src/integration/xpath/static-dom/StaticElement.ts +119 -0
  269. package/src/integration/xpath/static-dom/StaticNode.ts +68 -0
  270. package/src/integration/xpath/static-dom/StaticText.ts +28 -0
  271. package/src/lib/client-reactivity/README.md +0 -0
  272. package/src/lib/client-reactivity/submission/createInstanceSubmissionState.ts +12 -0
  273. package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +20 -0
  274. package/src/lib/client-reactivity/submission/createNodeRangeSubmissionState.ts +17 -0
  275. package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +22 -0
  276. package/src/lib/client-reactivity/submission/createRootSubmissionState.ts +19 -0
  277. package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +21 -0
  278. package/src/lib/client-reactivity/submission/prepareSubmission.ts +172 -0
  279. package/src/lib/codecs/DecimalValueCodec.ts +46 -0
  280. package/src/lib/codecs/Geopoint/Geopoint.ts +150 -0
  281. package/src/lib/codecs/Geopoint/GeopointValueCodec.ts +20 -0
  282. package/src/lib/codecs/IntValueCodec.ts +100 -0
  283. package/src/lib/codecs/NoteCodec.ts +32 -0
  284. package/src/lib/codecs/RangeCodec.ts +65 -0
  285. package/src/lib/codecs/StringValueCodec.ts +11 -0
  286. package/src/lib/codecs/TriggerCodec.ts +64 -0
  287. package/src/lib/codecs/ValueArrayCodec.ts +42 -0
  288. package/src/lib/codecs/ValueCodec.ts +106 -0
  289. package/src/lib/codecs/ValueTypePlaceholderCodec.ts +19 -0
  290. package/src/lib/codecs/getNoteCodec.ts +27 -0
  291. package/src/lib/codecs/getSelectCodec.ts +27 -0
  292. package/src/lib/codecs/getSharedValueCodec.ts +79 -0
  293. package/src/lib/codecs/items/BaseItemCodec.ts +20 -0
  294. package/src/lib/codecs/items/MultipleValueItemCodec.ts +28 -0
  295. package/src/lib/codecs/items/SingleValueItemCodec.ts +67 -0
  296. package/src/lib/dom/query.ts +8 -2
  297. package/src/lib/names/NamespaceDeclaration.ts +106 -0
  298. package/src/lib/names/NamespaceDeclarationMap.ts +228 -0
  299. package/src/lib/names/NamespaceURL.ts +44 -0
  300. package/src/lib/names/QualifiedName.ts +170 -0
  301. package/src/lib/number-parsers.ts +25 -0
  302. package/src/lib/reactivity/createChildrenState.ts +8 -6
  303. package/src/lib/reactivity/createComputedExpression.ts +57 -34
  304. package/src/lib/reactivity/createInstanceValueState.ts +216 -0
  305. package/src/lib/reactivity/createItemCollection.ts +173 -0
  306. package/src/lib/reactivity/createNoteReadonlyThunk.ts +12 -7
  307. package/src/lib/reactivity/createTranslationState.ts +61 -0
  308. package/src/lib/reactivity/createValueState.ts +62 -120
  309. package/src/lib/reactivity/materializeCurrentStateChildren.ts +7 -7
  310. package/src/lib/reactivity/text/createTextRange.ts +4 -3
  311. package/src/lib/reactivity/validation/createAggregatedViolations.ts +1 -1
  312. package/src/lib/reactivity/validation/createValidation.ts +2 -3
  313. package/src/lib/xml-serialization.ts +163 -0
  314. package/src/parse/XFormDOM.ts +231 -76
  315. package/src/parse/XFormDefinition.ts +2 -10
  316. package/src/parse/attachments/FormAttachmentResource.ts +40 -0
  317. package/src/parse/body/BodyDefinition.ts +7 -7
  318. package/src/parse/body/appearance/inputAppearanceParser.ts +1 -1
  319. package/src/parse/body/appearance/rangeAppearanceParser.ts +11 -0
  320. package/src/parse/body/control/InputControlDefinition.ts +29 -0
  321. package/src/parse/body/control/{select/ItemDefinition.ts → ItemDefinition.ts} +8 -6
  322. package/src/parse/body/control/{select/ItemsetDefinition.ts → ItemsetDefinition.ts} +11 -9
  323. package/src/parse/body/control/RangeControlDefinition.ts +91 -6
  324. package/src/parse/body/control/RankControlDefinition.ts +25 -7
  325. package/src/parse/body/control/{select/SelectDefinition.ts → SelectControlDefinition.ts} +9 -9
  326. package/src/parse/expression/ItemsetNodesetExpression.ts +1 -1
  327. package/src/parse/expression/ItemsetValueExpression.ts +1 -1
  328. package/src/parse/expression/abstract/DependencyContext.ts +0 -26
  329. package/src/parse/expression/abstract/DependentExpression.ts +2 -13
  330. package/src/parse/model/BindDefinition.ts +9 -8
  331. package/src/parse/model/BindPreloadDefinition.ts +100 -0
  332. package/src/parse/model/BindTypeDefinition.ts +175 -0
  333. package/src/parse/model/DescendentNodeDefinition.ts +7 -31
  334. package/src/parse/model/FormSubmissionDefinition.ts +44 -0
  335. package/src/parse/model/ItextTranslation/ItextTranslationDefinition.ts +4 -0
  336. package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +42 -0
  337. package/src/parse/model/ItextTranslation/ItextTranslationsDefinition.ts +31 -0
  338. package/src/parse/model/LeafNodeDefinition.ts +15 -5
  339. package/src/parse/model/ModelBindMap.ts +6 -8
  340. package/src/parse/model/ModelDefinition.ts +6 -1
  341. package/src/parse/model/NodeDefinition.ts +24 -48
  342. package/src/parse/model/NoteNodeDefinition.ts +11 -10
  343. package/src/parse/model/RangeNodeDefinition.ts +118 -0
  344. package/src/parse/model/RepeatInstanceDefinition.ts +11 -7
  345. package/src/parse/model/RepeatRangeDefinition.ts +11 -7
  346. package/src/parse/model/RepeatTemplateDefinition.ts +11 -7
  347. package/src/parse/model/RootAttributeDefinition.ts +45 -0
  348. package/src/parse/model/RootAttributeMap.ts +44 -0
  349. package/src/parse/model/RootDefinition.ts +31 -29
  350. package/src/parse/model/SecondaryInstance/SecondaryInstanceDefinition.ts +4 -0
  351. package/src/parse/model/SecondaryInstance/SecondaryInstanceRootDefinition.ts +12 -0
  352. package/src/parse/model/SecondaryInstance/SecondaryInstancesDefinition.ts +102 -0
  353. package/src/parse/model/SecondaryInstance/sources/BlankSecondaryInstanceSource.ts +40 -0
  354. package/src/parse/model/SecondaryInstance/sources/CSVExternalSecondaryInstance.ts +288 -0
  355. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceResource.ts +222 -0
  356. package/src/parse/model/SecondaryInstance/sources/ExternalSecondaryInstanceSource.ts +22 -0
  357. package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +415 -0
  358. package/src/parse/model/SecondaryInstance/sources/InternalSecondaryInstanceSource.ts +19 -0
  359. package/src/parse/model/SecondaryInstance/sources/SecondaryInstanceSource.ts +29 -0
  360. package/src/parse/model/SecondaryInstance/sources/XMLExternalSecondaryInstanceSource.ts +32 -0
  361. package/src/parse/model/SubtreeDefinition.ts +12 -12
  362. package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +149 -0
  363. package/src/parse/text/ItemLabelDefinition.ts +1 -1
  364. package/src/parse/text/ItemsetLabelDefinition.ts +2 -2
  365. package/src/parse/text/abstract/TextElementDefinition.ts +1 -1
  366. package/src/parse/text/abstract/TextRangeDefinition.ts +0 -6
  367. package/src/parse/xpath/semantic-analysis.ts +33 -3
  368. package/dist/client/StringNode.d.ts +0 -46
  369. package/dist/client/unsupported/RangeNode.d.ts +0 -9
  370. package/dist/client/unsupported/RankNode.d.ts +0 -9
  371. package/dist/instance/SelectField.d.ts +0 -50
  372. package/dist/instance/StringField.d.ts +0 -44
  373. package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -59
  374. package/dist/instance/unsupported/RangeControl.d.ts +0 -4
  375. package/dist/instance/unsupported/RankControl.d.ts +0 -4
  376. package/dist/lib/reactivity/createSelectItems.d.ts +0 -16
  377. package/dist/parse/XFormDataType.d.ts +0 -25
  378. package/dist/parse/body/control/select/ItemDefinition.d.ts +0 -13
  379. package/dist/parse/body/control/select/ItemsetDefinition.d.ts +0 -17
  380. package/dist/parse/body/control/select/ItemsetNodesetContext.d.ts +0 -11
  381. package/src/client/StringNode.ts +0 -52
  382. package/src/client/unsupported/RangeNode.ts +0 -14
  383. package/src/client/unsupported/RankNode.ts +0 -14
  384. package/src/instance/SelectField.ts +0 -226
  385. package/src/instance/StringField.ts +0 -120
  386. package/src/instance/internal-api/SubscribableDependency.ts +0 -61
  387. package/src/instance/unsupported/RangeControl.ts +0 -5
  388. package/src/instance/unsupported/RankControl.ts +0 -5
  389. package/src/lib/reactivity/createSelectItems.ts +0 -168
  390. package/src/parse/XFormDataType.ts +0 -62
  391. package/src/parse/body/control/InputDefinition.ts +0 -22
  392. package/src/parse/body/control/select/ItemsetNodesetContext.ts +0 -26
@@ -0,0 +1,163 @@
1
+ import type { NamespaceDeclarationMap } from './names/NamespaceDeclarationMap.ts';
2
+ import type { QualifiedName } from './names/QualifiedName.ts';
3
+
4
+ declare const ESCAPED_XML_TEXT_BRAND: unique symbol;
5
+
6
+ export type EscapedXMLText = string & { readonly [ESCAPED_XML_TEXT_BRAND]: true };
7
+
8
+ const ATTR_REGEX = /[&<>"]/;
9
+ const CONTENT_REGEX = /[&<>]/;
10
+
11
+ /**
12
+ * This is based on the `escapeHTML` implementation in
13
+ * {@link https://github.com/ryansolid/dom-expressions} (Solid's JSX transform).
14
+ *
15
+ * @see {@link https://github.com/ryansolid/dom-expressions/pull/27} for
16
+ * motivation to derive this implementation approach.
17
+ *
18
+ * The intent is that this can be updated easily if the base implementation
19
+ * changes. As such, some aspects of this implementation differ from some of our
20
+ * typical code style preferences.
21
+ *
22
+ * Notable changes from the base implementation:
23
+ *
24
+ * - Formatting: automated only.
25
+ * - Naming: the {@link text} parameter is named `html` in the base
26
+ * implementation. That would be confusing if preserved.
27
+ * - Types:
28
+ * - Parameter types are added (of course)
29
+ * - Return type is branded as {@link EscapedXMLText}, to allow downstream
30
+ * checks that escaping has been performed. Return statements are cast
31
+ * accordingly.
32
+ * - {@link text} attempts to minimize risk of double-escaping by excluding
33
+ * that same branded type.
34
+ * - The '>' character is also escaped, necessary for producing valid XML.
35
+ *
36
+ * As with the base implementation, we leave some characters unescaped:
37
+ *
38
+ * - " (double quote): except when {@link attr} is `true`.
39
+ *
40
+ * - ' (single quote): on the assumption that attributes are always serialized
41
+ * in double quotes. If we ever move this to `@getodk/common`, we'd want to
42
+ * reconsider this assumption.
43
+ */
44
+ export const escapeXMLText = <Text extends string>(
45
+ text: Exclude<Text, EscapedXMLText>,
46
+ attr?: boolean
47
+ ): EscapedXMLText => {
48
+ const match = (attr ? ATTR_REGEX : CONTENT_REGEX).exec(text);
49
+ if (!match) return text as string as EscapedXMLText;
50
+ let index = 0;
51
+ let lastIndex = 0;
52
+ let out = '';
53
+ let escape = '';
54
+ for (index = match.index; index < text.length; index++) {
55
+ switch (text.charCodeAt(index)) {
56
+ case 34: // "
57
+ if (!attr) continue;
58
+ escape = '&quot;';
59
+ break;
60
+ case 38: // &
61
+ escape = '&amp;';
62
+ break;
63
+ case 60: // <
64
+ escape = '&lt;';
65
+ break;
66
+ case 62: // >
67
+ escape = '&gt;';
68
+ break;
69
+ default:
70
+ continue;
71
+ }
72
+ if (lastIndex !== index) out += text.substring(lastIndex, index);
73
+ lastIndex = index + 1;
74
+ out += escape;
75
+ }
76
+ return lastIndex !== index
77
+ ? ((out + text.substring(lastIndex, index)) as EscapedXMLText)
78
+ : (out as EscapedXMLText);
79
+ };
80
+
81
+ interface SerializableElementAttribute {
82
+ serializeAttributeXML(): string;
83
+ }
84
+
85
+ interface ElementXMLSerializationOptions {
86
+ readonly namespaceDeclarations?: NamespaceDeclarationMap;
87
+ readonly attributes?: readonly SerializableElementAttribute[];
88
+ }
89
+
90
+ const serializeElementNamespaceDeclarationXML = (
91
+ namespaceDeclarations?: NamespaceDeclarationMap
92
+ ): string => {
93
+ if (namespaceDeclarations == null) {
94
+ return '';
95
+ }
96
+
97
+ return Array.from(namespaceDeclarations.values())
98
+ .map((namespaceDeclaration) => {
99
+ return namespaceDeclaration.serializeNamespaceDeclarationXML({
100
+ omitDefaultNamespace: true,
101
+ });
102
+ })
103
+ .join('');
104
+ };
105
+
106
+ const serializeElementAttributeXML = (
107
+ attributes?: readonly SerializableElementAttribute[]
108
+ ): string => {
109
+ if (attributes == null) {
110
+ return '';
111
+ }
112
+
113
+ return attributes
114
+ .map((attribute) => {
115
+ return attribute.serializeAttributeXML();
116
+ })
117
+ .join('');
118
+ };
119
+
120
+ const serializeElementXML = (
121
+ qualifiedName: QualifiedName,
122
+ children: string,
123
+ options: ElementXMLSerializationOptions = {}
124
+ ): string => {
125
+ // See JSDoc for the `getPrefixedName` method. If we find we do actually need
126
+ // custom element (subtree) prefix resolution, we'd uncomment the argument
127
+ // below. (Either way, at time of writing the affected tests pass where
128
+ // expected when the option is passed. It's omitted on the presumption that it
129
+ // would be redundant, since the nodes being serialized are already resolved
130
+ // with the same set of namespace declarations which would affect them.)
131
+ //
132
+ // prettier-ignore
133
+ const nodeName = qualifiedName.getPrefixedName(
134
+ // options.namespaceDeclarations
135
+ );
136
+ const namespaceDeclarations = serializeElementNamespaceDeclarationXML(
137
+ options.namespaceDeclarations
138
+ );
139
+ const attributes = serializeElementAttributeXML(options.attributes);
140
+ const prefix = `<${nodeName}${namespaceDeclarations}${attributes}`;
141
+
142
+ if (children === '') {
143
+ return `${prefix}/>`;
144
+ }
145
+
146
+ return `${prefix}>${children}</${nodeName}>`;
147
+ };
148
+
149
+ export const serializeParentElementXML = (
150
+ qualifiedName: QualifiedName,
151
+ serializedChildren: readonly string[],
152
+ options?: ElementXMLSerializationOptions
153
+ ): string => {
154
+ return serializeElementXML(qualifiedName, serializedChildren.join(''), options);
155
+ };
156
+
157
+ export const serializeLeafElementXML = (
158
+ qualifiedName: QualifiedName,
159
+ xmlValue: EscapedXMLText,
160
+ options?: ElementXMLSerializationOptions
161
+ ): string => {
162
+ return serializeElementXML(qualifiedName, xmlValue.normalize(), options);
163
+ };
@@ -1,5 +1,154 @@
1
- import { XFORMS_NAMESPACE_URI, XMLNS_NAMESPACE_URI } from '@getodk/common/constants/xmlns.ts';
2
- import { XFormsXPathEvaluator } from '@getodk/xpath';
1
+ import {
2
+ JAVAROSA_NAMESPACE_URI,
3
+ OPENROSA_XFORMS_NAMESPACE_URI,
4
+ XFORMS_NAMESPACE_URI,
5
+ XMLNS_NAMESPACE_URI,
6
+ } from '@getodk/common/constants/xmlns.ts';
7
+ import type {
8
+ KnownAttributeLocalNamedElement,
9
+ LocalNamedElement,
10
+ } from '@getodk/common/types/dom.ts';
11
+ import { DefaultEvaluator } from '@getodk/xpath';
12
+
13
+ interface DOMBindElement extends KnownAttributeLocalNamedElement<'bind', 'nodeset'> {}
14
+
15
+ const getMetaElement = (primaryInstanceRoot: Element): Element | null => {
16
+ for (const child of primaryInstanceRoot.children) {
17
+ const { localName, namespaceURI } = child;
18
+
19
+ if (
20
+ (namespaceURI === OPENROSA_XFORMS_NAMESPACE_URI || namespaceURI === XFORMS_NAMESPACE_URI) &&
21
+ localName === 'meta'
22
+ ) {
23
+ return child;
24
+ }
25
+ }
26
+
27
+ return null;
28
+ };
29
+
30
+ const getMetaChildElement = (meta: Element | null, localName: string): Element | null => {
31
+ if (meta == null) {
32
+ return null;
33
+ }
34
+
35
+ const { namespaceURI } = meta;
36
+
37
+ for (const child of meta.children) {
38
+ if (child.localName === localName && child.namespaceURI === namespaceURI) {
39
+ return child;
40
+ }
41
+ }
42
+
43
+ return null;
44
+ };
45
+
46
+ const getQualifiedName = (
47
+ contextNode: Node,
48
+ namespaceURI: string | null,
49
+ localName: string
50
+ ): string => {
51
+ const prefix = contextNode.lookupPrefix(namespaceURI);
52
+
53
+ if (prefix == null) {
54
+ return localName;
55
+ }
56
+
57
+ return `${prefix}:${localName}`;
58
+ };
59
+
60
+ const createNamespacedChildElement = (
61
+ parent: Element,
62
+ namespaceURI: string | null,
63
+ localName: string
64
+ ): Element => {
65
+ const qualifiedName = getQualifiedName(parent, namespaceURI, localName);
66
+ const child = parent.ownerDocument.createElementNS(namespaceURI, qualifiedName);
67
+
68
+ parent.append(child);
69
+
70
+ return child;
71
+ };
72
+
73
+ const setNamespacedAttributeValue = (
74
+ element: Element,
75
+ namespaceURI: string | null,
76
+ localName: string,
77
+ value: string
78
+ ) => {
79
+ const qualifiedName = getQualifiedName(element, namespaceURI, localName);
80
+
81
+ element.setAttributeNS(namespaceURI, qualifiedName, value);
82
+ };
83
+
84
+ const createDefaultInstanceIDBinding = (
85
+ model: Element,
86
+ primaryInstanceRoot: Element,
87
+ meta: Element,
88
+ instanceID: Element
89
+ ): DOMBindElement => {
90
+ const bind = createNamespacedChildElement(model, model.namespaceURI, 'bind');
91
+ const nodeset = `/${primaryInstanceRoot.nodeName}/${meta.nodeName}/${instanceID.nodeName}`;
92
+
93
+ bind.setAttribute('nodeset', nodeset);
94
+ setNamespacedAttributeValue(bind, JAVAROSA_NAMESPACE_URI, 'preload', 'uid');
95
+
96
+ return bind as DOMBindElement;
97
+ };
98
+
99
+ const normalizeDefaultMetaBindings = (
100
+ model: Element,
101
+ primaryInstanceRoot: Element,
102
+ binds: readonly DOMBindElement[]
103
+ ): readonly DOMBindElement[] => {
104
+ let meta = getMetaElement(primaryInstanceRoot);
105
+ let instanceID = getMetaChildElement(meta, 'instanceID');
106
+
107
+ if (meta == null) {
108
+ meta = createNamespacedChildElement(primaryInstanceRoot, OPENROSA_XFORMS_NAMESPACE_URI, 'meta');
109
+ }
110
+
111
+ if (instanceID == null) {
112
+ instanceID = createNamespacedChildElement(meta, meta.namespaceURI, 'instanceID');
113
+
114
+ const instanceIDBinding = createDefaultInstanceIDBinding(
115
+ model,
116
+ primaryInstanceRoot,
117
+ meta,
118
+ instanceID
119
+ );
120
+
121
+ return [...binds, instanceIDBinding];
122
+ }
123
+
124
+ return binds;
125
+ };
126
+
127
+ export interface DOMItextTranslationElement
128
+ extends KnownAttributeLocalNamedElement<'translation', 'lang'> {}
129
+
130
+ interface DOMInstanceElement extends LocalNamedElement<'instance'> {}
131
+
132
+ export interface DOMSecondaryInstanceElement
133
+ extends KnownAttributeLocalNamedElement<'instance', 'id'> {}
134
+
135
+ type AssertDOMSecondaryInstanceElement = (
136
+ element: DOMInstanceElement
137
+ ) => asserts element is DOMSecondaryInstanceElement;
138
+
139
+ const assertDOMSecondaryInstanceElement: AssertDOMSecondaryInstanceElement = (element) => {
140
+ if (!element.hasAttribute('id')) {
141
+ throw new Error('Invalid secondary instance element: missing `id` attribute');
142
+ }
143
+ };
144
+
145
+ type AssertDOMSecondaryInstanceElements = (
146
+ elements: readonly DOMInstanceElement[]
147
+ ) => asserts elements is readonly DOMSecondaryInstanceElement[];
148
+
149
+ const assertDOMSecondaryInstanceElements: AssertDOMSecondaryInstanceElements = (elements) => {
150
+ elements.forEach(assertDOMSecondaryInstanceElement);
151
+ };
3
152
 
4
153
  const domParser = new DOMParser();
5
154
 
@@ -145,61 +294,33 @@ const normalizeRepeatGroups = (body: Element): void => {
145
294
  }
146
295
  };
147
296
 
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
297
  /**
161
- * Performs preprocess operations to normalize certain aspects of an XForm
162
- * structure for consistency when building up its runtime representations.
298
+ * Performs preprocess operations to normalize certain aspects of the body of an
299
+ * XForm, for consistency when parsing its runtime representations.
300
+ *
163
301
  * Currently this preprocessing:
164
302
  *
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`
303
+ * - Ensures consistent use of `ref` and `nodeset` where ambiguous in the ODK
304
+ * XForms spec
305
+ * - Ensures `<repeat>` body elements are always enclosed by a `<group>` with
306
+ * the same `ref`
169
307
  */
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;
184
-
185
- if (options.isNormalized) {
186
- normalizedXML = sourceXML;
187
- } else {
188
- normalizeBodyRefNodesetAttributes(body);
189
- normalizeRepeatGroups(body);
308
+ const normalizeXFormBody = <T extends Element>(body: T): T => {
309
+ normalizeBodyRefNodesetAttributes(body);
310
+ normalizeRepeatGroups(body);
190
311
 
191
- normalizedXML = html.outerHTML;
192
- }
193
-
194
- return {
195
- xformDocument,
196
- rootEvaluator,
197
- html,
198
- body,
199
- normalizedXML,
200
- };
312
+ return body;
201
313
  };
202
314
 
315
+ interface XFormDOMOptions {
316
+ readonly isNormalized: boolean;
317
+ }
318
+
319
+ /**
320
+ * @todo **Everything** in this class should be cacheable. Maybe not worth it
321
+ * for small forms, but may make a pretty substantial difference for very large
322
+ * forms (in bytes) in sessions creating multiple instances of the same form.
323
+ */
203
324
  export class XFormDOM {
204
325
  static from(sourceXML: string) {
205
326
  return new this(sourceXML, { isNormalized: false });
@@ -207,10 +328,6 @@ export class XFormDOM {
207
328
 
208
329
  protected readonly normalizedXML: string;
209
330
 
210
- // XPath
211
- readonly rootEvaluator: XFormsXPathEvaluator;
212
- readonly primaryInstanceEvaluator: XFormsXPathEvaluator;
213
-
214
331
  // Commonly accessed landmark nodes
215
332
  readonly xformDocument: XMLDocument;
216
333
 
@@ -220,59 +337,97 @@ export class XFormDOM {
220
337
  readonly title: Element;
221
338
 
222
339
  readonly model: Element;
340
+ readonly binds: readonly DOMBindElement[];
223
341
  readonly primaryInstance: Element;
224
342
  readonly primaryInstanceRoot: Element;
225
343
 
344
+ readonly itextTranslationElements: readonly DOMItextTranslationElement[];
345
+ readonly secondaryInstanceElements: readonly DOMSecondaryInstanceElement[];
346
+
226
347
  readonly body: Element;
227
348
 
228
349
  protected constructor(
229
350
  protected readonly sourceXML: string,
230
- options: XFormDOMNormalizationOptions
351
+ options: XFormDOMOptions
231
352
  ) {
232
- const normalizedXForm: NormalizedXForm = parseNormalizedXForm(sourceXML, options);
233
- const { xformDocument, html, body, rootEvaluator, normalizedXML } = normalizedXForm;
234
- const head = rootEvaluator.evaluateNonNullElement('./h:head', {
353
+ const evaluator = new DefaultEvaluator();
354
+ const xformDocument: XMLDocument = domParser.parseFromString(sourceXML, 'text/xml');
355
+ const html = evaluator.evaluateNonNullElement('/h:html', {
356
+ contextNode: xformDocument,
357
+ });
358
+ const head = evaluator.evaluateNonNullElement('./h:head', {
235
359
  contextNode: html,
236
360
  });
237
- const title = rootEvaluator.evaluateNonNullElement('./h:title', {
361
+ const title = evaluator.evaluateNonNullElement('./h:title', {
238
362
  contextNode: head,
239
363
  });
240
- const model = rootEvaluator.evaluateNonNullElement('./xf:model', {
364
+ const model = evaluator.evaluateNonNullElement('./xf:model', {
241
365
  contextNode: head,
242
366
  });
243
- // TODO: Evidently primary instance root will not always have an id
244
- const primaryInstanceRoot = rootEvaluator.evaluateNonNullElement('./xf:instance/*[@id]', {
367
+ let binds: readonly DOMBindElement[] = evaluator.evaluateNodes<DOMBindElement>(
368
+ './xf:bind[@nodeset]',
369
+ {
370
+ contextNode: model,
371
+ }
372
+ );
373
+
374
+ const instances = evaluator.evaluateNodes<DOMInstanceElement>('./xf:instance', {
245
375
  contextNode: model,
246
376
  });
247
- // TODO: invert primary instance/root lookups
248
- const primaryInstance = rootEvaluator.evaluateNonNullElement('..', {
249
- contextNode: primaryInstanceRoot,
377
+
378
+ const [primaryInstance, ...secondaryInstanceElements] = instances;
379
+
380
+ assertDOMSecondaryInstanceElements(secondaryInstanceElements);
381
+
382
+ if (primaryInstance == null) {
383
+ throw new Error('Form is missing primary instance');
384
+ }
385
+
386
+ // TODO: Evidently primary instance root will not always have an id
387
+ const primaryInstanceRoot = evaluator.evaluateNonNullElement('./*[@id]', {
388
+ contextNode: primaryInstance,
250
389
  });
251
390
 
252
- this.normalizedXML = normalizedXML;
253
- this.rootEvaluator = rootEvaluator;
254
- this.primaryInstanceEvaluator = new XFormsXPathEvaluator({
255
- rootNode: primaryInstance,
391
+ const itextTranslationElements = evaluator.evaluateNodes<DOMItextTranslationElement>(
392
+ './xf:itext/xf:translation[@lang]',
393
+ {
394
+ contextNode: model,
395
+ }
396
+ );
397
+
398
+ let body = evaluator.evaluateNonNullElement('./h:body', {
399
+ contextNode: html,
256
400
  });
401
+ let normalizedXML: string;
402
+
403
+ if (options.isNormalized) {
404
+ normalizedXML = sourceXML;
405
+ } else {
406
+ body = normalizeXFormBody(body);
407
+ binds = normalizeDefaultMetaBindings(model, primaryInstanceRoot, binds);
408
+
409
+ // TODO: if we keep doing normalization this way long term (or using the DOM
410
+ // for parsing long term, for that matter!), we should measure this. And we
411
+ // should measure against XMLSerializer while we're at it!
412
+ normalizedXML = xformDocument.documentElement.outerHTML;
413
+ }
414
+
415
+ this.normalizedXML = normalizedXML;
257
416
  this.xformDocument = xformDocument;
258
417
  this.html = html;
259
418
  this.head = head;
260
419
  this.title = title;
261
420
  this.model = model;
421
+ this.binds = binds;
262
422
  this.primaryInstance = primaryInstance;
263
423
  this.primaryInstanceRoot = primaryInstanceRoot;
424
+ this.itextTranslationElements = itextTranslationElements;
425
+ this.secondaryInstanceElements = secondaryInstanceElements;
264
426
  this.body = body;
265
427
  }
266
428
 
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
429
  toJSON() {
273
430
  const {
274
- rootEvaluator,
275
- primaryInstanceEvaluator,
276
431
  html,
277
432
  head,
278
433
  title,
@@ -3,7 +3,6 @@ import { ModelDefinition } from './model/ModelDefinition.ts';
3
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
 
@@ -29,10 +24,7 @@ export class XFormDefinition {
29
24
  this.xformDocument = xformDocument;
30
25
  this.id = id;
31
26
  this.title = title.textContent ?? '';
32
-
33
- // TODO: highly unlikely primary instance root will need a namespace prefix
34
- // but noting it just in case there is such weird usage...
35
- this.rootReference = `/${primaryInstanceRoot.localName}`;
27
+ this.rootReference = `/${primaryInstanceRoot.nodeName}`;
36
28
 
37
29
  this.body = new BodyDefinition(this);
38
30
  this.model = new ModelDefinition(this);
@@ -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
+ }
@@ -3,11 +3,11 @@ import { TokenListParser } from '../../lib/TokenListParser.ts';
3
3
  import type { XFormDefinition } from '../../parse/XFormDefinition.ts';
4
4
  import { DependencyContext } from '../expression/abstract/DependencyContext.ts';
5
5
  import { ControlDefinition } from './control/ControlDefinition.ts';
6
- import { InputDefinition } from './control/InputDefinition.ts';
6
+ import { InputControlDefinition } from './control/InputControlDefinition.ts';
7
7
  import { RangeControlDefinition } from './control/RangeControlDefinition.ts';
8
8
  import { RankControlDefinition } from './control/RankControlDefinition.ts';
9
- import type { AnySelectDefinition } from './control/select/SelectDefinition.ts';
10
- import { SelectDefinition } from './control/select/SelectDefinition.ts';
9
+ import type { AnySelectControlDefinition } from './control/SelectControlDefinition.ts';
10
+ import { SelectControlDefinition } from './control/SelectControlDefinition.ts';
11
11
  import { TriggerControlDefinition } from './control/TriggerControlDefinition.ts';
12
12
  import { UploadControlDefinition } from './control/UploadControlDefinition.ts';
13
13
  import { LogicalGroupDefinition } from './group/LogicalGroupDefinition.ts';
@@ -24,8 +24,8 @@ export interface BodyElementParentContext {
24
24
 
25
25
  // prettier-ignore
26
26
  export type ControlElementDefinition =
27
- | AnySelectDefinition
28
- | InputDefinition
27
+ | AnySelectControlDefinition
28
+ | InputControlDefinition
29
29
  | RangeControlDefinition
30
30
  | RankControlDefinition
31
31
  | TriggerControlDefinition
@@ -47,8 +47,8 @@ const BodyElementDefinitionConstructors = [
47
47
  LogicalGroupDefinition,
48
48
  PresentationGroupDefinition,
49
49
  StructuralGroupDefinition,
50
- InputDefinition,
51
- SelectDefinition,
50
+ InputControlDefinition,
51
+ SelectControlDefinition,
52
52
  RangeControlDefinition,
53
53
  RankControlDefinition,
54
54
  TriggerControlDefinition,
@@ -4,7 +4,7 @@ export const inputAppearanceParser = new TokenListParser([
4
4
  'multiline',
5
5
  'numbers',
6
6
  'url',
7
- 'thousand-sep',
7
+ 'thousands-sep',
8
8
 
9
9
  // date (TODO: data types)
10
10
  'no-calendar',
@@ -0,0 +1,11 @@
1
+ import type { ParsedTokenList } from '../../../lib/TokenListParser.ts';
2
+ import { TokenListParser } from '../../../lib/TokenListParser.ts';
3
+
4
+ export const rangeAppearanceParser = new TokenListParser([
5
+ 'no-ticks',
6
+ 'picker',
7
+ 'rating',
8
+ 'vertical',
9
+ ]);
10
+
11
+ export type RangeAppearanceDefinition = ParsedTokenList<typeof rangeAppearanceParser>;
@@ -0,0 +1,29 @@
1
+ import type { XFormDefinition } from '../../XFormDefinition.ts';
2
+ import type { InputAppearanceDefinition } from '../appearance/inputAppearanceParser.ts';
3
+ import { inputAppearanceParser } from '../appearance/inputAppearanceParser.ts';
4
+ import type { BodyElementParentContext } from '../BodyDefinition.ts';
5
+ import { parseToFloat, parseToInteger } from '../../../lib/number-parsers.ts';
6
+ import { ControlDefinition } from './ControlDefinition.ts';
7
+
8
+ export class InputControlDefinition extends ControlDefinition<'input'> {
9
+ static override isCompatible(localName: string): boolean {
10
+ return localName === 'input';
11
+ }
12
+
13
+ readonly type = 'input';
14
+ readonly appearances: InputAppearanceDefinition;
15
+ readonly rows: number | null;
16
+ readonly accuracyThreshold: number | null;
17
+ readonly unacceptableAccuracyThreshold: number | null;
18
+
19
+ constructor(form: XFormDefinition, parent: BodyElementParentContext, element: Element) {
20
+ super(form, parent, element);
21
+
22
+ this.appearances = inputAppearanceParser.parseFrom(element, 'appearance');
23
+ this.rows = parseToInteger(element.getAttribute('rows'));
24
+ this.accuracyThreshold = parseToFloat(element.getAttribute('accuracyThreshold'));
25
+ this.unacceptableAccuracyThreshold = parseToFloat(
26
+ element.getAttribute('unacceptableAccuracyThreshold')
27
+ );
28
+ }
29
+ }