@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,79 @@
1
+ import type { ValueType } from '../../client/ValueType.ts';
2
+ import {
3
+ DecimalValueCodec,
4
+ type DecimalInputValue,
5
+ type DecimalRuntimeValue,
6
+ } from './DecimalValueCodec.ts';
7
+ import type { GeopointInputValue, GeopointRuntimeValue } from './Geopoint/Geopoint.ts';
8
+ import { GeopointValueCodec } from './Geopoint/GeopointValueCodec.ts';
9
+ import { IntValueCodec, type IntInputValue, type IntRuntimeValue } from './IntValueCodec.ts';
10
+ import { StringValueCodec } from './StringValueCodec.ts';
11
+ import type { ValueCodec } from './ValueCodec.ts';
12
+ import { ValueTypePlaceholderCodec } from './ValueTypePlaceholderCodec.ts';
13
+
14
+ interface RuntimeValuesByType {
15
+ readonly string: string;
16
+ readonly int: IntRuntimeValue;
17
+ readonly decimal: DecimalRuntimeValue;
18
+ readonly boolean: string;
19
+ readonly date: string;
20
+ readonly time: string;
21
+ readonly dateTime: string;
22
+ readonly geopoint: GeopointRuntimeValue;
23
+ readonly geotrace: string;
24
+ readonly geoshape: string;
25
+ readonly binary: string;
26
+ readonly barcode: string;
27
+ readonly intent: string;
28
+ }
29
+
30
+ export type RuntimeValue<V extends ValueType> = RuntimeValuesByType[V];
31
+
32
+ interface RuntimeInputValuesByType {
33
+ readonly string: string;
34
+ readonly int: IntInputValue;
35
+ readonly decimal: DecimalInputValue;
36
+ readonly boolean: string;
37
+ readonly date: string;
38
+ readonly time: string;
39
+ readonly dateTime: string;
40
+ readonly geopoint: GeopointInputValue;
41
+ readonly geotrace: string;
42
+ readonly geoshape: string;
43
+ readonly binary: string;
44
+ readonly barcode: string;
45
+ readonly intent: string;
46
+ }
47
+
48
+ export type RuntimeInputValue<V extends ValueType> = RuntimeInputValuesByType[V];
49
+
50
+ type SharedValueCodecs = {
51
+ readonly [V in ValueType]: ValueCodec<V, RuntimeValue<V>, RuntimeInputValue<V>>;
52
+ };
53
+
54
+ export type SharedValueCodec<V extends ValueType> = SharedValueCodecs[V];
55
+
56
+ /**
57
+ * Provides codecs for each {@link ValueType | value type}, for nodes with a
58
+ * common representation of those value types.
59
+ */
60
+ export const sharedValueCodecs: SharedValueCodecs = {
61
+ string: new StringValueCodec(),
62
+
63
+ int: new IntValueCodec(),
64
+ decimal: new DecimalValueCodec(),
65
+ boolean: new ValueTypePlaceholderCodec('boolean'),
66
+ date: new ValueTypePlaceholderCodec('date'),
67
+ time: new ValueTypePlaceholderCodec('time'),
68
+ dateTime: new ValueTypePlaceholderCodec('dateTime'),
69
+ geopoint: new GeopointValueCodec(),
70
+ geotrace: new ValueTypePlaceholderCodec('geotrace'),
71
+ geoshape: new ValueTypePlaceholderCodec('geoshape'),
72
+ binary: new ValueTypePlaceholderCodec('binary'),
73
+ barcode: new ValueTypePlaceholderCodec('barcode'),
74
+ intent: new ValueTypePlaceholderCodec('intent'),
75
+ };
76
+
77
+ export const getSharedValueCodec = <V extends ValueType>(valueType: V): SharedValueCodec<V> => {
78
+ return sharedValueCodecs[valueType];
79
+ };
@@ -0,0 +1,20 @@
1
+ import type { ValueType } from '../../../client/ValueType.ts';
2
+ import type { SharedValueCodec } from '../getSharedValueCodec.ts';
3
+ import { ValueArrayCodec } from '../ValueArrayCodec.ts';
4
+ import type { CodecDecoder, CodecEncoder } from '../ValueCodec.ts';
5
+
6
+ export type BaseItemValueType = 'string';
7
+
8
+ export type UnsupportedBaseItemValueType = Exclude<ValueType, BaseItemValueType>;
9
+
10
+ export abstract class BaseItemCodec<
11
+ Values extends readonly string[] = readonly string[],
12
+ > extends ValueArrayCodec<BaseItemValueType, Values> {
13
+ constructor(
14
+ baseCodec: SharedValueCodec<'string'>,
15
+ encodeValue: CodecEncoder<Values>,
16
+ decodeValue: CodecDecoder<Values>
17
+ ) {
18
+ super(baseCodec, encodeValue, decodeValue);
19
+ }
20
+ }
@@ -0,0 +1,28 @@
1
+ import { xmlXPathWhitespaceSeparatedList } from '@getodk/common/lib/string/whitespace.ts';
2
+ import type { SharedValueCodec } from '../getSharedValueCodec.ts';
3
+ import type { CodecDecoder, CodecEncoder } from '../ValueCodec.ts';
4
+ import { BaseItemCodec } from './BaseItemCodec.ts';
5
+
6
+ /**
7
+ * Value codec implementation for `<select>` and `<odk:rank>` controls.
8
+ *
9
+ * This generalizes the application of a {@link SharedValueCodec} implementation
10
+ * over individual select and rank values, where those values are serialized as a
11
+ * whitespace-separated list. All other encoding and decoding logic is deferred
12
+ * to the provided {@link baseCodec}, ensuring that select and rank value types are
13
+ * treated consistently with the same underlying data types for other controls.
14
+ */
15
+ export class MultipleValueItemCodec extends BaseItemCodec<readonly string[]> {
16
+ constructor(baseCodec: SharedValueCodec<'string'>) {
17
+ const encodeValue: CodecEncoder<readonly string[]> = (value) => {
18
+ return value.join(' ');
19
+ };
20
+ const decodeValue: CodecDecoder<readonly string[]> = (value) => {
21
+ return xmlXPathWhitespaceSeparatedList(value, {
22
+ ignoreEmpty: true,
23
+ });
24
+ };
25
+
26
+ super(baseCodec, encodeValue, decodeValue);
27
+ }
28
+ }
@@ -0,0 +1,67 @@
1
+ import type { SharedValueCodec } from '../getSharedValueCodec.ts';
2
+ import { type CodecDecoder, type CodecEncoder } from '../ValueCodec.ts';
3
+ import { BaseItemCodec } from './BaseItemCodec.ts';
4
+ import type { MultipleValueItemCodec } from './MultipleValueItemCodec.ts';
5
+
6
+ // prettier-ignore
7
+ export type SingleValueSelectRuntimeValues =
8
+ | readonly []
9
+ | readonly [string];
10
+
11
+ /**
12
+ * @see {@link encodeValueFactory}
13
+ */
14
+ // prettier-ignore
15
+ type SingleValueSelectCodecValues =
16
+ | SingleValueSelectRuntimeValues
17
+ | readonly string[];
18
+
19
+ /**
20
+ * @todo This is more permissive than it should be, allowing an array of any
21
+ * length. It's not clear whether a runtime check **MUST** happen here, but
22
+ * if we identify bugs where `<select1>` controls are somehow allowing more
23
+ * than one value to be set, this is where we'd start looking. The check is
24
+ * skipped for now, to reduce performance overhead.
25
+ */
26
+ const encodeValueFactory = (
27
+ baseCodec: SharedValueCodec<'string'>
28
+ ): CodecEncoder<SingleValueSelectCodecValues> => {
29
+ return (values) => {
30
+ const [value] = values;
31
+
32
+ if (value == null) {
33
+ return '';
34
+ }
35
+
36
+ return baseCodec.encodeValue(value);
37
+ };
38
+ };
39
+
40
+ /**
41
+ * Value codec implementation for `<select1>` controls.
42
+ *
43
+ * Note: this implementation is a specialization of the same principles
44
+ * underlying {@link MultipleValueItemCodec}. It is implemented separately:
45
+ *
46
+ * 1. to address a semantic difference between `<select>` and `<select1>`
47
+ * values: the former are serialized as a space-separated list, but that does
48
+ * not apply to the latter;
49
+ *
50
+ * 2. as an optimization, as the more general implementation performs poorly on
51
+ * forms which we monitor for performance.
52
+ */
53
+ export class SingleValueItemCodec extends BaseItemCodec<SingleValueSelectCodecValues> {
54
+ constructor(baseCodec: SharedValueCodec<'string'>) {
55
+ const encodeValue = encodeValueFactory(baseCodec);
56
+
57
+ const decodeValue: CodecDecoder<SingleValueSelectRuntimeValues> = (value) => {
58
+ if (value == null) {
59
+ return [];
60
+ }
61
+
62
+ return [value];
63
+ };
64
+
65
+ super(baseCodec, encodeValue, decodeValue);
66
+ }
67
+ }
@@ -3,7 +3,6 @@ import type {
3
3
  KnownAttributeLocalNamedElement,
4
4
  LocalNamedElement,
5
5
  } from '@getodk/common/types/dom.ts';
6
- import type { SelectElement } from '../../parse/body/control/select/SelectDefinition';
7
6
 
8
7
  const hintLookup = new ScopedElementLookup(':scope > hint', 'hint');
9
8
  const itemLookup = new ScopedElementLookup(':scope > item', 'item');
@@ -15,6 +14,7 @@ const repeatGroupLabelLookup = new ScopedElementLookup(
15
14
  );
16
15
  const repeatLookup = new ScopedElementLookup(':scope > repeat[nodeset]', 'repeat[nodeset]');
17
16
  const valueLookup = new ScopedElementLookup(':scope > value', 'value');
17
+ const submissionLookup = new ScopedElementLookup(':scope > submission', 'submission');
18
18
 
19
19
  export interface HintElement extends LocalNamedElement<'hint'> {}
20
20
 
@@ -37,7 +37,7 @@ export const getHintElement = (parent: Element): HintElement | null => {
37
37
  return hintLookup.getElement<HintElement>(parent);
38
38
  };
39
39
 
40
- export const getItemElements = (parent: SelectElement): readonly ItemElement[] => {
40
+ export const getItemElements = (parent: Element): readonly ItemElement[] => {
41
41
  return Array.from(itemLookup.getElements<ItemElement>(parent));
42
42
  };
43
43
 
@@ -60,3 +60,9 @@ export const getRepeatElement = (parent: Element): RepeatElement | null => {
60
60
  export const getValueElement = (parent: ItemElement | ItemsetElement): ValueElement | null => {
61
61
  return valueLookup.getElement<ValueElement>(parent);
62
62
  };
63
+
64
+ export interface SubmissionElement extends LocalNamedElement<'submission'> {}
65
+
66
+ export const getSubmissionElement = (parent: Element): SubmissionElement | null => {
67
+ return submissionLookup.getElement<SubmissionElement>(parent);
68
+ };
@@ -0,0 +1,106 @@
1
+ import { XMLNS_NAMESPACE_URI, XMLNS_PREFIX } from '@getodk/common/constants/xmlns.ts';
2
+ import { escapeXMLText } from '../xml-serialization.ts';
3
+ import type { NamespaceDeclarationMap } from './NamespaceDeclarationMap.ts';
4
+ import type { NamespaceURI } from './QualifiedName.ts';
5
+ import { QualifiedName } from './QualifiedName.ts';
6
+
7
+ interface NamespaceDeclarationXMLSerializationOptions {
8
+ readonly omitDefaultNamespace?: boolean;
9
+ }
10
+
11
+ export interface NamespaceDeclarationOptions {
12
+ readonly declaredPrefix: string | null;
13
+ readonly declaredURI: NamespaceURI;
14
+ }
15
+
16
+ /**
17
+ * Provides a generalized representation of an XML namespace declaration, which
18
+ * can be used for:
19
+ *
20
+ * - Resolution of a declared namespace URI, by its declared prefix
21
+ * - Resolution of a declared namespace prefix associated with its namespace URI
22
+ * - Scoped resolution of same in an arbitrary DOM-like tree of nodes (or
23
+ * representations thereof)
24
+ * - Serialization of the namespace declaration as an XML representation, as
25
+ * part of broader XML serialization logic from an arbitrary DOM-like tree of
26
+ * nodes (or representations thereof)
27
+ *
28
+ * @see {@link NamespaceDeclarationMap} for details on scoped usage
29
+ */
30
+ export class NamespaceDeclaration {
31
+ private readonly serializedXML: string;
32
+
33
+ /**
34
+ * A namespace is declared as either:
35
+ *
36
+ * - a "default" namespace (for which no prefix is declared, in which case
37
+ * this value will be `null`)
38
+ *
39
+ * - a namespace prefix (for which the prefix can be used to reference the
40
+ * declared namespace, in which case this value will be a `string`)
41
+ */
42
+ readonly declaredPrefix: string | null;
43
+
44
+ /**
45
+ * A namespace is declared for a {@link NamespaceURI}, i.e. either a
46
+ * {@link URL} or `null`, where `null` corresponds to the "null namespace"
47
+ * (i.e. `xmlns=""` or `xmlns:prefix=""`, in serialized XML).
48
+ */
49
+ readonly declaredURI: NamespaceURI;
50
+
51
+ constructor(options: NamespaceDeclarationOptions) {
52
+ const { declaredPrefix, declaredURI } = options;
53
+
54
+ /**
55
+ * Represents the {@link QualifiedName} **of the {@link NamespaceDeclaration} itself, used only for consistent XML serialization logic.
56
+ */
57
+ let qualifiedName: QualifiedName;
58
+
59
+ switch (declaredPrefix) {
60
+ // Declaring a "null prefix" is equivalent to the following XML syntax:
61
+ // `xmlns="..."`
62
+ case null:
63
+ qualifiedName = new QualifiedName({
64
+ namespaceURI: XMLNS_NAMESPACE_URI,
65
+ prefix: null,
66
+ localName: XMLNS_PREFIX,
67
+ });
68
+
69
+ break;
70
+
71
+ // Declaring a non-null prefix is equivalent to the following XML syntax:
72
+ // `xmlns:$declaredPrefix="..."
73
+ default:
74
+ qualifiedName = new QualifiedName({
75
+ namespaceURI: XMLNS_NAMESPACE_URI,
76
+ prefix: XMLNS_PREFIX,
77
+ localName: declaredPrefix,
78
+ });
79
+ break;
80
+ }
81
+
82
+ this.declaredPrefix = declaredPrefix;
83
+ this.declaredURI = declaredURI;
84
+
85
+ const serializedName = qualifiedName.getPrefixedName();
86
+ const serializedValue = escapeXMLText(declaredURI?.href ?? '');
87
+
88
+ this.serializedXML = ` ${serializedName}="${serializedValue}"`;
89
+ }
90
+
91
+ declaresNamespaceURI(namespaceURI: NamespaceURI) {
92
+ if (namespaceURI == null) {
93
+ return this.declaredURI === null;
94
+ }
95
+
96
+ return this.declaredURI?.href === namespaceURI.href;
97
+ }
98
+
99
+ serializeNamespaceDeclarationXML(options?: NamespaceDeclarationXMLSerializationOptions): string {
100
+ if (options?.omitDefaultNamespace && this.declaredPrefix == null) {
101
+ return '';
102
+ }
103
+
104
+ return this.serializedXML;
105
+ }
106
+ }
@@ -0,0 +1,228 @@
1
+ import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
2
+ import { NamespaceDeclaration } from './NamespaceDeclaration.ts';
3
+ import type { NamespaceURI, QualifiedName } from './QualifiedName.ts';
4
+
5
+ export interface NamedNodeDefinition {
6
+ readonly qualifiedName: QualifiedName;
7
+ }
8
+
9
+ type NamedNodeDefinitionMap = ReadonlyMap<QualifiedName, NamedNodeDefinition>;
10
+
11
+ export interface NamedSubtreeDefinition extends NamedNodeDefinition {
12
+ readonly namespaceDeclarations: NamespaceDeclarationMap;
13
+ readonly parent: NamedSubtreeDefinition | null;
14
+ readonly attributes?: NamedNodeDefinitionMap;
15
+ }
16
+
17
+ /**
18
+ * @todo This is a bit of a code style experiment! Responsive to
19
+ * {@link https://github.com/getodk/web-forms/issues/296 | How should we represent enumerated types?}.
20
+ * Observations to be considered for that issue...
21
+ *
22
+ * This more or less works as one would expect, with one really irritating
23
+ * downside: unlike a **TypeScript `enum`**, code completions (in VSCode, but
24
+ * I'd expect the same for any TypeScript language server/LSP implementation)
25
+ * automatically suggest the bare string values rather than the equivalent
26
+ * syntax referencing the enumerations as defined here. Without care, it would
27
+ * be fairly trivial to lose consistency between the source "enum" and consuming
28
+ * code which we presume to be an exhaustive check (such as the `switch`
29
+ * statement operating on it below). This is somewhat mitigated for now by
30
+ * habitual use of {@link UnreachableError} (and would be better mitigated by a
31
+ * lint rule to enforce exhaustiveness checks over similar enumerations). But
32
+ * there is an obvious _stylistic mismatch_ between how an editor treats "thing
33
+ * shaped like `enum` but not semantically an `enum`", whereas there's no such
34
+ * mismatch in how it treats a plain "union of strings". If nothing else, that
35
+ * mismatch would tend to exacerbate exhaustiveness drift as an enumeration
36
+ * evolves.
37
+ */
38
+ const DECLARE_NAMESPACE_RESULTS = {
39
+ SUCCESS: 'SUCCESS',
40
+ HOISTED: 'HOISTED',
41
+ DEFERRED: 'DEFERRED',
42
+ REDUNDANT: 'REDUNDANT',
43
+ CONFLICT: 'CONFLICT',
44
+ } as const;
45
+
46
+ type DeclareNamespaceResultEnum = typeof DECLARE_NAMESPACE_RESULTS;
47
+
48
+ type DeclareNamespaceResult = DeclareNamespaceResultEnum[keyof DeclareNamespaceResultEnum];
49
+
50
+ export class NamespaceDeclarationMap extends Map<string | null, NamespaceDeclaration> {
51
+ constructor(readonly subtree: NamedSubtreeDefinition) {
52
+ super();
53
+
54
+ this.declareNamespace(subtree);
55
+
56
+ const { attributes } = subtree;
57
+
58
+ if (attributes != null) {
59
+ for (const attribute of attributes.values()) {
60
+ this.declareNamespace(attribute);
61
+ }
62
+ }
63
+ }
64
+
65
+ /**
66
+ * For any {@link definition | named node definition}, we can _infer_ a
67
+ * namespace declaration (rather than parsing it directly, which is error
68
+ * prone depending on parsing context) from that definition's
69
+ * {@link QualifiedName.namespaceURI} and {@link QualifiedName.prefix} (if the
70
+ * latter is defined).
71
+ *
72
+ * If a namespace declaration can be inferred, we "declare" (set, in
73
+ * {@link Map} semantics) it in **EITHER**:
74
+ *
75
+ * - An ancestor {@link NamedSubtreeDefinition | named subtree definition}'s
76
+ * {@link NamespaceDeclarationMap}: if such an ancestor exists and has no
77
+ * conflicting declaration for the same prefix; **OR**
78
+ * - This {@link NamespaceDeclarationMap}, if no suitable ancestor exists
79
+ *
80
+ * This can be described as "hoisting" the declaration to the uppermost node
81
+ * (or definitional representation of same) where it would be valid to declare
82
+ * the namespace for its prefix.
83
+ *
84
+ * In the following example, note that this logic applies for arbitrary tree
85
+ * structures satisfying the {@link NamedNodeDefinition} and
86
+ * {@link NamedSubtreeDefinition} interfaces. XML syntax is used to provide a
87
+ * concise explanation, but it should not be inferred that this is operating
88
+ * directly on an XML value (or any platform-native DOM structure of the
89
+ * same).
90
+ *
91
+ * @example Given an input tree like:
92
+ *
93
+ * ```xml
94
+ * <foo xmlns="https://example.com/DEFAULT_ONE">
95
+ * <bar:bat xmlns:bar="https://example.com/bar"/>
96
+ * <baz xmlns="https://example.com/DEFAULT_TWO"/>
97
+ * </foo>
98
+ * ```
99
+ *
100
+ * The namespace declarations will be assigned as if they'd been declared
101
+ * like:
102
+ *
103
+ * ```xml
104
+ * <foo
105
+ * xmlns="https://example.com/DEFAULT_ONE"
106
+ * xmlns:bar="https://example.com/bar"
107
+ * >
108
+ * <!-- bar declaration has no conflict in foo, hoisted to parent -->
109
+ * <bar:bat/>
110
+ * <!-- default declaration conflicts with foo's default, not hoisted -->
111
+ * <baz xmlns="https://example.com/DEFAULT_TWO"/>
112
+ * </foo>
113
+ * ```
114
+ *
115
+ * **IMPORTANT:** this behavior may seem overly complicated! It should be
116
+ * noted that the behavior:
117
+ *
118
+ * 1. ... is conceptually similar to behavior observable in a web standard
119
+ * WHAT Working Group DOM (as in browser DOM, XML DOM) implementation.
120
+ * There, serializing any subtree element will produce namespace
121
+ * declarations on the root element for any namespaces _referenced within
122
+ * its subtree but declared on an ancestor_. Note that in this case, the
123
+ * hierarchical behavior is inverted, but it demonstrates the same
124
+ * effective namespace scoping semantics.
125
+ *
126
+ * 2. ... vastly simplifies our ability to produce a compact XML
127
+ * representation from any arbitrary tree representation of its nodes.
128
+ * Hoisting namespace declarations to their uppermost scope, and
129
+ * deduplicating recursively up the ancestor tree, ensures that we only
130
+ * declare a given namespace once as it is referenced.
131
+ *
132
+ * @todo While this design is intended to help with producing compact
133
+ * serialized XML, at time of writing there is still an aspect which is
134
+ * unaddressed in the serialization logic: we assume namespace declarations
135
+ * are referenced if they've been parsed. This logic doesn't hold for nodes
136
+ * which are ultimately omitted from serialization, which would occur for
137
+ * non-relevant nodes, and repeat ranges with zero repeat instances (or any of
138
+ * their descendants). A future iteration of this same behavior could produce
139
+ * XML which is theoretically more compact, by performing the same declaration
140
+ * hoisting logic _dynamically at call time_ rather than at parse time.
141
+ */
142
+ declareNamespace(definition: NamedNodeDefinition): DeclareNamespaceResult {
143
+ const { prefix, namespaceURI } = definition.qualifiedName;
144
+
145
+ if (typeof prefix === 'symbol') {
146
+ return DECLARE_NAMESPACE_RESULTS.DEFERRED;
147
+ }
148
+
149
+ const parentNamespaceDeclarations = this.subtree.parent?.namespaceDeclarations;
150
+
151
+ if (parentNamespaceDeclarations != null) {
152
+ const ancestorResult = parentNamespaceDeclarations.declareNamespace(definition);
153
+
154
+ switch (ancestorResult) {
155
+ case DECLARE_NAMESPACE_RESULTS.CONFLICT:
156
+ break;
157
+
158
+ case DECLARE_NAMESPACE_RESULTS.DEFERRED:
159
+ return ancestorResult;
160
+
161
+ case DECLARE_NAMESPACE_RESULTS.HOISTED:
162
+ return ancestorResult;
163
+
164
+ case DECLARE_NAMESPACE_RESULTS.SUCCESS:
165
+ case DECLARE_NAMESPACE_RESULTS.REDUNDANT:
166
+ return DECLARE_NAMESPACE_RESULTS.HOISTED;
167
+
168
+ default:
169
+ throw new UnreachableError(ancestorResult);
170
+ }
171
+ }
172
+
173
+ const currentDeclaration = this.get(prefix);
174
+
175
+ if (currentDeclaration == null) {
176
+ this.set(
177
+ prefix,
178
+ new NamespaceDeclaration({
179
+ declaredPrefix: prefix,
180
+ declaredURI: namespaceURI,
181
+ })
182
+ );
183
+
184
+ return DECLARE_NAMESPACE_RESULTS.SUCCESS;
185
+ }
186
+
187
+ if (currentDeclaration.declaresNamespaceURI(namespaceURI)) {
188
+ return DECLARE_NAMESPACE_RESULTS.REDUNDANT;
189
+ }
190
+
191
+ return DECLARE_NAMESPACE_RESULTS.CONFLICT;
192
+ }
193
+
194
+ /**
195
+ * Given a {@link namespaceURI}, resolves a declared prefix (which may be
196
+ * `null`) for the {@link subtree} context **or any of its ancestors**. This
197
+ * is an important semantic detail:
198
+ *
199
+ * - Namespace declarations on a given subtree are effective for all of its
200
+ * descendants _until another declaration for the same prefix or namespace
201
+ * URI is encountered_
202
+ * - We "hoist" namespace declarations up to the uppermost {@link subtree}'s
203
+ * {@link NamespaceDeclarationMap} during parsing (as described in more
204
+ * detail on {@link declareNamespace}).
205
+ */
206
+ lookupPrefix(namespaceURI: NamespaceURI): string | null {
207
+ const namespace = String(namespaceURI);
208
+
209
+ // Note: this is a dynamic lookup on the _very unlikely_ chance that a
210
+ // lookup occurs while parsing is still in progress. It's expected that we
211
+ // collect all namespace declarations by the time parsing is complete, at
212
+ // which point we could theoretically collect a companion map where the
213
+ // namespace URI is used as a key. This has been deferred for now, because
214
+ // we'd need:
215
+ //
216
+ // 1. To know _in this class_ when parsing is complete (which seems like a
217
+ // huge excess of mixed responsibilities!)
218
+ // 2. To resolve the "object-as-value-as-map-key" problem, which has also
219
+ // been deferred.
220
+ for (const namespaceDeclaration of this.values()) {
221
+ if (String(namespaceDeclaration.declaredURI) === namespace) {
222
+ return namespaceDeclaration.declaredPrefix;
223
+ }
224
+ }
225
+
226
+ return this.subtree.parent?.namespaceDeclarations.lookupPrefix(namespaceURI) ?? null;
227
+ }
228
+ }
@@ -0,0 +1,44 @@
1
+ import type { NamespaceDeclaration } from './NamespaceDeclaration.ts';
2
+
3
+ /**
4
+ * Convenience wrapper to represent an XML namespace URI as a {@link URL}. This
5
+ * representation is used/responsible for:
6
+ *
7
+ * - normalized logic for XML semantics around special namespace URI values, in
8
+ * particular for consistent handling of the "null namespace" (input for such
9
+ * is accepted as either an empty string or `null`)
10
+ * - validation of input: a non-"null namespace" value will be rejected if it is
11
+ * not a valid URI string
12
+ * - type-level distinction between a namespace URI and a
13
+ * {@link NamespaceDeclaration.declaredPrefix | namespace declaration's prefix},
14
+ * as an aide to avoid using one in place of the other as e.g. a positional
15
+ * argument
16
+ *
17
+ * @todo Test the finer distinctions between "URL" and "URI"!
18
+ *
19
+ * @todo Probably not a huge deal in the scheme of things, but this is almost
20
+ * entirely pure overhead at runtime! The "validation" use case is kind of a
21
+ * stretch, and may well be wrong. The type-level distinction from a namespace
22
+ * prefix, however, has proved useful **quite a few times** during iteration of
23
+ * this change. If we can actually measure an impact, it might be worth instead
24
+ * considering "branded types" for the type-level distinct (in which case we
25
+ * could use a factory function to handle both the branding and special XML
26
+ * semantics).
27
+ */
28
+ export class NamespaceURL extends URL {
29
+ static from(namespaceURI: NamespaceURL | string | null): NamespaceURL | null {
30
+ if (namespaceURI == null || namespaceURI === '') {
31
+ return null;
32
+ }
33
+
34
+ return new this(String(namespaceURI));
35
+ }
36
+
37
+ override readonly href: string;
38
+
39
+ private constructor(href: string) {
40
+ super(href);
41
+
42
+ this.href = href;
43
+ }
44
+ }