@tradik/xslt3 0.0.0-stage → 1.0.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 (286) hide show
  1. package/LICENSE.md +28 -0
  2. package/README.md +98 -2
  3. package/package.json +43 -4
  4. package/src/errors.js +20 -0
  5. package/src/functions/aggregates.js +144 -0
  6. package/src/functions/arraySort.js +33 -0
  7. package/src/functions/arrays.js +181 -0
  8. package/src/functions/attributeTypes.js +58 -0
  9. package/src/functions/baseUris.js +82 -0
  10. package/src/functions/collations.js +127 -0
  11. package/src/functions/collections.js +84 -0
  12. package/src/functions/context.js +83 -0
  13. package/src/functions/core.js +167 -0
  14. package/src/functions/datetime.js +203 -0
  15. package/src/functions/deepEqual.js +132 -0
  16. package/src/functions/diagnostics.js +88 -0
  17. package/src/functions/focus.js +34 -0
  18. package/src/functions/format/dateComponents.js +176 -0
  19. package/src/functions/format/datePicture.js +115 -0
  20. package/src/functions/format/decimalFormat.js +65 -0
  21. package/src/functions/format/digitPattern.js +145 -0
  22. package/src/functions/format/formatDateTime.js +204 -0
  23. package/src/functions/format/formatInteger.js +109 -0
  24. package/src/functions/format/formatNumber.js +165 -0
  25. package/src/functions/format/fractionFormat.js +80 -0
  26. package/src/functions/format/germanWords.js +89 -0
  27. package/src/functions/format/numberLanguages.js +41 -0
  28. package/src/functions/format/numberPicture.js +202 -0
  29. package/src/functions/format/numberWords.js +155 -0
  30. package/src/functions/format/place.js +74 -0
  31. package/src/functions/format/timezoneFormat.js +89 -0
  32. package/src/functions/higherOrder.js +106 -0
  33. package/src/functions/ids.js +127 -0
  34. package/src/functions/json/index.js +17 -0
  35. package/src/functions/json/jsonChars.js +110 -0
  36. package/src/functions/json/jsonParser.js +203 -0
  37. package/src/functions/json/jsonStrings.js +116 -0
  38. package/src/functions/json/jsonToXml.js +116 -0
  39. package/src/functions/json/parseJson.js +119 -0
  40. package/src/functions/json/xmlRepresentation.js +103 -0
  41. package/src/functions/json/xmlToJson.js +147 -0
  42. package/src/functions/library.js +47 -0
  43. package/src/functions/mapArrayEqual.js +41 -0
  44. package/src/functions/maps.js +152 -0
  45. package/src/functions/math.js +73 -0
  46. package/src/functions/nodePaths.js +181 -0
  47. package/src/functions/nodes.js +199 -0
  48. package/src/functions/numeric.js +148 -0
  49. package/src/functions/options.js +58 -0
  50. package/src/functions/parseIetfDate.js +104 -0
  51. package/src/functions/parseXml.js +77 -0
  52. package/src/functions/qnames.js +68 -0
  53. package/src/functions/random.js +128 -0
  54. package/src/functions/regex/analyzeString.js +144 -0
  55. package/src/functions/regex/charClass.js +112 -0
  56. package/src/functions/regex/compile.js +81 -0
  57. package/src/functions/regex/escapes.js +109 -0
  58. package/src/functions/regex/parser.js +169 -0
  59. package/src/functions/regex/reader.js +37 -0
  60. package/src/functions/regex/regexFunctions.js +140 -0
  61. package/src/functions/regex/translate.js +102 -0
  62. package/src/functions/regex/unicodeBlocks.js +194 -0
  63. package/src/functions/registry.js +140 -0
  64. package/src/functions/sequences.js +173 -0
  65. package/src/functions/serializeFunction.js +53 -0
  66. package/src/functions/signatures.js +105 -0
  67. package/src/functions/sort.js +102 -0
  68. package/src/functions/stringMatch.js +45 -0
  69. package/src/functions/strings.js +194 -0
  70. package/src/functions/stringsCore.js +66 -0
  71. package/src/functions/support.js +106 -0
  72. package/src/functions/textDecoding.js +117 -0
  73. package/src/functions/ucaCollation.js +127 -0
  74. package/src/functions/unparsedText.js +71 -0
  75. package/src/functions/uri.js +166 -0
  76. package/src/functions/xqueryModule.js +24 -0
  77. package/src/index.js +38 -0
  78. package/src/items/array.js +84 -0
  79. package/src/items/function.js +45 -0
  80. package/src/items/map.js +120 -0
  81. package/src/items/mapKey.js +82 -0
  82. package/src/serialize/index.js +129 -0
  83. package/src/serialize/markup/content.js +74 -0
  84. package/src/serialize/markup/dialect.js +178 -0
  85. package/src/serialize/markup/htmlData.js +70 -0
  86. package/src/serialize/markup/namespaces.js +145 -0
  87. package/src/serialize/markup/prolog.js +91 -0
  88. package/src/serialize/markup/writer.js +183 -0
  89. package/src/serialize/methods/adaptive.js +131 -0
  90. package/src/serialize/methods/json.js +158 -0
  91. package/src/serialize/methods/text.js +43 -0
  92. package/src/serialize/output/buffer.js +48 -0
  93. package/src/serialize/output/encoding.js +146 -0
  94. package/src/serialize/output/expander.js +204 -0
  95. package/src/serialize/params/fromElement.js +141 -0
  96. package/src/serialize/params/fromMap.js +128 -0
  97. package/src/serialize/params/names.js +69 -0
  98. package/src/serialize/params/settings.js +153 -0
  99. package/src/serialize/params/values.js +163 -0
  100. package/src/serialize/sequence.js +111 -0
  101. package/src/xdm/arithmetic.js +155 -0
  102. package/src/xdm/atomic.js +142 -0
  103. package/src/xdm/binary.js +92 -0
  104. package/src/xdm/calendar.js +71 -0
  105. package/src/xdm/cast.js +176 -0
  106. package/src/xdm/compare.js +192 -0
  107. package/src/xdm/datetime.js +206 -0
  108. package/src/xdm/decimal.js +200 -0
  109. package/src/xdm/duration.js +128 -0
  110. package/src/xdm/generalCompare.js +152 -0
  111. package/src/xdm/index.js +47 -0
  112. package/src/xdm/lexical.js +126 -0
  113. package/src/xdm/nodes.js +170 -0
  114. package/src/xdm/numeric.js +122 -0
  115. package/src/xdm/qname.js +65 -0
  116. package/src/xdm/strings.js +52 -0
  117. package/src/xdm/temporalArithmetic.js +180 -0
  118. package/src/xdm/timeline.js +68 -0
  119. package/src/xdm/types.js +178 -0
  120. package/src/xpath/eval/atomics.js +45 -0
  121. package/src/xpath/eval/axes.js +212 -0
  122. package/src/xpath/eval/calls.js +168 -0
  123. package/src/xpath/eval/coercion.js +146 -0
  124. package/src/xpath/eval/compiler.js +71 -0
  125. package/src/xpath/eval/constructors.js +129 -0
  126. package/src/xpath/eval/decimalFormats.js +93 -0
  127. package/src/xpath/eval/descendantMemo.js +77 -0
  128. package/src/xpath/eval/documentOrder.js +142 -0
  129. package/src/xpath/eval/domNodes.js +174 -0
  130. package/src/xpath/eval/dynamicCall.js +27 -0
  131. package/src/xpath/eval/dynamicContext.js +161 -0
  132. package/src/xpath/eval/flow.js +115 -0
  133. package/src/xpath/eval/functionItems.js +194 -0
  134. package/src/xpath/eval/groupedChildren.js +88 -0
  135. package/src/xpath/eval/inline.js +71 -0
  136. package/src/xpath/eval/namespaceNodes.js +90 -0
  137. package/src/xpath/eval/nodeTests.js +164 -0
  138. package/src/xpath/eval/operators.js +190 -0
  139. package/src/xpath/eval/paths.js +163 -0
  140. package/src/xpath/eval/positional.js +81 -0
  141. package/src/xpath/eval/predicates.js +56 -0
  142. package/src/xpath/eval/primary.js +99 -0
  143. package/src/xpath/eval/resources.js +149 -0
  144. package/src/xpath/eval/scope.js +108 -0
  145. package/src/xpath/eval/sequenceType.js +193 -0
  146. package/src/xpath/eval/staticContext.js +142 -0
  147. package/src/xpath/eval/steps.js +98 -0
  148. package/src/xpath/eval/subtype.js +154 -0
  149. package/src/xpath/eval/typeExprs.js +147 -0
  150. package/src/xpath/eval/typeNames.js +101 -0
  151. package/src/xpath/eval/uris.js +21 -0
  152. package/src/xpath/eval/values.js +64 -0
  153. package/src/xpath/index.js +217 -0
  154. package/src/xpath/syntax/ast.js +130 -0
  155. package/src/xpath/syntax/chars.js +58 -0
  156. package/src/xpath/syntax/constructors.js +144 -0
  157. package/src/xpath/syntax/expressions.js +107 -0
  158. package/src/xpath/syntax/index.js +44 -0
  159. package/src/xpath/syntax/kindTests.js +134 -0
  160. package/src/xpath/syntax/lexer.js +220 -0
  161. package/src/xpath/syntax/operators.js +111 -0
  162. package/src/xpath/syntax/paths.js +102 -0
  163. package/src/xpath/syntax/postfix.js +91 -0
  164. package/src/xpath/syntax/primaries.js +149 -0
  165. package/src/xpath/syntax/steps.js +146 -0
  166. package/src/xpath/syntax/syntaxError.js +31 -0
  167. package/src/xpath/syntax/tokenStream.js +163 -0
  168. package/src/xpath/syntax/typeAst.js +76 -0
  169. package/src/xpath/syntax/typeOperators.js +127 -0
  170. package/src/xpath/syntax/types.js +158 -0
  171. package/src/xslt/api.js +153 -0
  172. package/src/xslt/compiler/acceptance.js +178 -0
  173. package/src/xslt/compiler/accumulatorDecl.js +146 -0
  174. package/src/xslt/compiler/attributeValues.js +174 -0
  175. package/src/xslt/compiler/attributes.js +211 -0
  176. package/src/xslt/compiler/avt.js +103 -0
  177. package/src/xslt/compiler/body.js +154 -0
  178. package/src/xslt/compiler/children.js +105 -0
  179. package/src/xslt/compiler/compatibility.js +130 -0
  180. package/src/xslt/compiler/components.js +179 -0
  181. package/src/xslt/compiler/contextItem.js +95 -0
  182. package/src/xslt/compiler/decimalFormats.js +132 -0
  183. package/src/xslt/compiler/declarationKinds.js +82 -0
  184. package/src/xslt/compiler/elementInfo.js +246 -0
  185. package/src/xslt/compiler/expressions.js +175 -0
  186. package/src/xslt/compiler/globalContextItem.js +92 -0
  187. package/src/xslt/compiler/globals.js +209 -0
  188. package/src/xslt/compiler/linker.js +134 -0
  189. package/src/xslt/compiler/miscDecl.js +171 -0
  190. package/src/xslt/compiler/modeDecl.js +88 -0
  191. package/src/xslt/compiler/moduleLoading.js +111 -0
  192. package/src/xslt/compiler/modules.js +158 -0
  193. package/src/xslt/compiler/outputDecl.js +209 -0
  194. package/src/xslt/compiler/overrideLinks.js +141 -0
  195. package/src/xslt/compiler/packageChecks.js +84 -0
  196. package/src/xslt/compiler/packageRegistry.js +95 -0
  197. package/src/xslt/compiler/packageTable.js +181 -0
  198. package/src/xslt/compiler/packageVersions.js +143 -0
  199. package/src/xslt/compiler/packages.js +138 -0
  200. package/src/xslt/compiler/registry.js +234 -0
  201. package/src/xslt/compiler/staticStage.js +197 -0
  202. package/src/xslt/compiler/staticVariables.js +93 -0
  203. package/src/xslt/compiler/stylesheet.js +205 -0
  204. package/src/xslt/compiler/tailPosition.js +74 -0
  205. package/src/xslt/compiler/templatesDecl.js +180 -0
  206. package/src/xslt/compiler/useAccumulators.js +76 -0
  207. package/src/xslt/compiler/useWhen.js +94 -0
  208. package/src/xslt/compiler/visibility.js +160 -0
  209. package/src/xslt/index.js +11 -0
  210. package/src/xslt/instructions/analyzeString.js +137 -0
  211. package/src/xslt/instructions/assert.js +72 -0
  212. package/src/xslt/instructions/attributeSets.js +115 -0
  213. package/src/xslt/instructions/conditional.js +99 -0
  214. package/src/xslt/instructions/control.js +123 -0
  215. package/src/xslt/instructions/copy.js +151 -0
  216. package/src/xslt/instructions/elements.js +161 -0
  217. package/src/xslt/instructions/evaluate.js +189 -0
  218. package/src/xslt/instructions/fork.js +35 -0
  219. package/src/xslt/instructions/grouping.js +106 -0
  220. package/src/xslt/instructions/index.js +94 -0
  221. package/src/xslt/instructions/iterate.js +182 -0
  222. package/src/xslt/instructions/literal.js +142 -0
  223. package/src/xslt/instructions/maps.js +72 -0
  224. package/src/xslt/instructions/merge.js +190 -0
  225. package/src/xslt/instructions/number.js +205 -0
  226. package/src/xslt/instructions/output.js +102 -0
  227. package/src/xslt/instructions/params.js +110 -0
  228. package/src/xslt/instructions/resultDocument.js +143 -0
  229. package/src/xslt/instructions/sort.js +114 -0
  230. package/src/xslt/instructions/sourceDocument.js +73 -0
  231. package/src/xslt/instructions/templates.js +153 -0
  232. package/src/xslt/instructions/text.js +151 -0
  233. package/src/xslt/instructions/try.js +186 -0
  234. package/src/xslt/instructions/variables.js +119 -0
  235. package/src/xslt/names.js +204 -0
  236. package/src/xslt/patterns/axisOrigins.js +121 -0
  237. package/src/xslt/patterns/compile.js +151 -0
  238. package/src/xslt/patterns/general.js +132 -0
  239. package/src/xslt/patterns/grammar.js +190 -0
  240. package/src/xslt/patterns/modes.js +153 -0
  241. package/src/xslt/patterns/paths.js +130 -0
  242. package/src/xslt/patterns/patternChecks.js +29 -0
  243. package/src/xslt/patterns/steps.js +162 -0
  244. package/src/xslt/processor.js +178 -0
  245. package/src/xslt/runtime/accumulatorFunctions.js +48 -0
  246. package/src/xslt/runtime/accumulators.js +174 -0
  247. package/src/xslt/runtime/apply.js +153 -0
  248. package/src/xslt/runtime/atomicKeys.js +36 -0
  249. package/src/xslt/runtime/availability.js +162 -0
  250. package/src/xslt/runtime/baseUri.js +64 -0
  251. package/src/xslt/runtime/compilerHook.js +27 -0
  252. package/src/xslt/runtime/conditional.js +110 -0
  253. package/src/xslt/runtime/context.js +106 -0
  254. package/src/xslt/runtime/copy.js +123 -0
  255. package/src/xslt/runtime/copyFunctions.js +71 -0
  256. package/src/xslt/runtime/copyOrigins.js +60 -0
  257. package/src/xslt/runtime/defaultMethod.js +42 -0
  258. package/src/xslt/runtime/documentContent.js +93 -0
  259. package/src/xslt/runtime/dynamicXPath.js +90 -0
  260. package/src/xslt/runtime/functionCache.js +65 -0
  261. package/src/xslt/runtime/functionCall.js +57 -0
  262. package/src/xslt/runtime/functions.js +191 -0
  263. package/src/xslt/runtime/groups.js +108 -0
  264. package/src/xslt/runtime/invocation.js +156 -0
  265. package/src/xslt/runtime/iteration.js +107 -0
  266. package/src/xslt/runtime/keys.js +141 -0
  267. package/src/xslt/runtime/lazy.js +97 -0
  268. package/src/xslt/runtime/locations.js +86 -0
  269. package/src/xslt/runtime/machine.js +137 -0
  270. package/src/xslt/runtime/merging.js +167 -0
  271. package/src/xslt/runtime/namespaceScope.js +141 -0
  272. package/src/xslt/runtime/numberFormat.js +89 -0
  273. package/src/xslt/runtime/numbering.js +168 -0
  274. package/src/xslt/runtime/params.js +59 -0
  275. package/src/xslt/runtime/properties.js +103 -0
  276. package/src/xslt/runtime/rawResults.js +82 -0
  277. package/src/xslt/runtime/sequenceReceiver.js +102 -0
  278. package/src/xslt/runtime/snapshot.js +66 -0
  279. package/src/xslt/runtime/sortKeys.js +119 -0
  280. package/src/xslt/runtime/streamAvailable.js +60 -0
  281. package/src/xslt/runtime/strip.js +102 -0
  282. package/src/xslt/runtime/transformFunction.js +169 -0
  283. package/src/xslt/runtime/transformation.js +168 -0
  284. package/src/xslt/runtime/transformationContext.js +85 -0
  285. package/src/xslt/runtime/treeReceiver.js +194 -0
  286. package/src/xslt/runtime/values.js +92 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Base URIs of nodes: the base URI recorded for document nodes that
3
+ * differ from their document URI (the documents of fn:parse-xml and
4
+ * fn:parse-xml-fragment have the static base URI as base URI and no
5
+ * document URI) and for constructed nodes, and the base URI of any node
6
+ * from these and xml:base attributes.
7
+ *
8
+ * @module @tradik/xslt3/functions/baseUris
9
+ */
10
+
11
+ import { parentOf } from "../xpath/eval/domNodes.js";
12
+ import { XML_NAMESPACE } from "../xpath/eval/namespaceNodes.js";
13
+ import { resolveUri } from "../xpath/eval/uris.js";
14
+ import { resolveUri as resolveReference } from "./uri.js";
15
+
16
+ /** @type {WeakMap<object, string>} */
17
+ const baseUris = new WeakMap();
18
+
19
+ /**
20
+ * Records the base URI of a document node.
21
+ * @param {Node} node
22
+ * @param {string|undefined} uri - Nothing is recorded when undefined
23
+ * @returns {Node} the node
24
+ */
25
+ export function setBaseUri(node, uri) {
26
+ if (uri !== undefined) baseUris.set(node, uri);
27
+ return node;
28
+ }
29
+
30
+ /**
31
+ * @param {Node} node
32
+ * @returns {string|undefined} the base URI recorded for the node
33
+ */
34
+ export const recordedBaseUri = (node) => baseUris.get(node);
35
+
36
+ /**
37
+ * An xml:base attribute resolved against the base URI of the parent
38
+ * (RFC 3986: an absolute URI stays as written).
39
+ * @param {string} value
40
+ * @param {string|undefined} base
41
+ * @returns {string}
42
+ */
43
+ function resolveBase(value, base) {
44
+ try {
45
+ return base === undefined ? value : resolveReference(value, base);
46
+ } catch {
47
+ return resolveUri(value, base);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Base URI of a node: its xml:base attributes resolved against the
53
+ * document URI, or against the base URI recorded for a constructed node.
54
+ * Namespace nodes have none (XDM 3.1 section 6.6.2).
55
+ * @param {Node} node
56
+ * @returns {string|undefined}
57
+ */
58
+ export function nodeBaseUri(node) {
59
+ if (node.nodeType === 13) return undefined;
60
+ const chain = [];
61
+ for (let n = node; n; n = parentOf(n)) chain.unshift(n);
62
+ let base;
63
+ for (const n of chain) {
64
+ const own =
65
+ recordedBaseUri(n) ??
66
+ (n.nodeType === 9 || n.nodeType === 11 ? documentUriOf(n) : undefined);
67
+ if (own !== undefined) base = own;
68
+ if (n.nodeType === 1 && n.hasAttributeNS(XML_NAMESPACE, "base")) {
69
+ base = resolveBase(n.getAttributeNS(XML_NAMESPACE, "base"), base);
70
+ }
71
+ }
72
+ return base;
73
+ }
74
+
75
+ /**
76
+ * @param {Node} node - A document node
77
+ * @returns {string|undefined} its URI, undefined when unknown
78
+ */
79
+ export function documentUriOf(node) {
80
+ const uri = node.documentURI ?? node.URL;
81
+ return uri && uri !== "about:blank" ? uri : undefined;
82
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Collations (F&O 3.1 section 5.3): the Unicode codepoint collation, the
3
+ * HTML ASCII case-insensitive collation and the UCA collation family,
4
+ * which falls back to `Intl.Collator` (allowed by `fallback=yes`, the
5
+ * default).
6
+ *
7
+ * @module @tradik/xslt3/functions/collations
8
+ */
9
+
10
+ import { XPathError } from "../errors.js";
11
+ import { compareCodepoints } from "../xdm/strings.js";
12
+ import { resolveUri } from "../xpath/eval/uris.js";
13
+ import { ucaCollation } from "./ucaCollation.js";
14
+
15
+ /** URI of the Unicode codepoint collation, the default collation. */
16
+ export const CODEPOINT_COLLATION =
17
+ "http://www.w3.org/2005/xpath-functions/collation/codepoint";
18
+ /** URI of the HTML ASCII case-insensitive collation. */
19
+ export const HTML_ASCII_COLLATION =
20
+ "http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive";
21
+ const UCA_PREFIX = "http://www.w3.org/2013/collation/UCA";
22
+
23
+ /**
24
+ * A collation.
25
+ * @typedef {object} Collation
26
+ * @property {string} uri
27
+ * @property {(a: string, b: string) => number} compare - -1, 0 or 1
28
+ * @property {((s: string) => string)|null} key - Maps equal strings to the
29
+ * same key, with the same length (for hashing and substring matching);
30
+ * null when only `compare` is available
31
+ * @property {boolean} [substrings] - false when substring matching is not
32
+ * supported
33
+ */
34
+
35
+ /** @param {string} s @returns {string} A-Z mapped to a-z */
36
+ const asciiLower = (s) => s.replace(/[A-Z]+/g, (m) => m.toLowerCase());
37
+
38
+ const codepoint = Object.freeze({
39
+ uri: CODEPOINT_COLLATION,
40
+ compare: compareCodepoints,
41
+ key: (s) => s,
42
+ });
43
+
44
+ const htmlAscii = Object.freeze({
45
+ uri: HTML_ASCII_COLLATION,
46
+ compare: (a, b) => compareCodepoints(asciiLower(a), asciiLower(b)),
47
+ key: asciiLower,
48
+ });
49
+
50
+ /**
51
+ * Finds the first substring of `text` that is equal to `search` under a
52
+ * collation (the shortest one at the leftmost position).
53
+ * @param {Collation} collation
54
+ * @param {string} text
55
+ * @param {string} search
56
+ * @param {"start"|"end"|null} [anchor] - Require a match at an end
57
+ * @returns {[number, number]|null} [start, end) offsets, null when absent
58
+ * @throws {XPathError} FOCH0004 for collations without substring matching
59
+ */
60
+ export function findSubstring(collation, text, search, anchor = null) {
61
+ if (collation.substrings === false) {
62
+ throw new XPathError(
63
+ "FOCH0004",
64
+ `The collation ${collation.uri} does not support substring matching`,
65
+ );
66
+ }
67
+ if (collation.key) {
68
+ const a = collation.key(text);
69
+ const b = collation.key(search);
70
+ const index =
71
+ anchor === "start"
72
+ ? a.startsWith(b)
73
+ ? 0
74
+ : -1
75
+ : anchor === "end"
76
+ ? a.endsWith(b)
77
+ ? a.length - b.length
78
+ : -1
79
+ : a.indexOf(b);
80
+ return index < 0 ? null : [index, index + b.length];
81
+ }
82
+ const starts = anchor === "start" ? [0] : [...Array(text.length + 1).keys()];
83
+ for (const start of starts) {
84
+ const ends =
85
+ anchor === "end" ? [text.length] : [...Array(text.length + 1).keys()];
86
+ for (const end of ends.filter((e) => e >= start)) {
87
+ if (collation.compare(text.slice(start, end), search) === 0) {
88
+ return [start, end];
89
+ }
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+
95
+ /**
96
+ * Resolves a collation URI.
97
+ * @param {string} [uri] - Collation URI, resolved against the static base
98
+ * URI when relative; the default collation when absent
99
+ * @param {{defaultCollation?: string, staticBaseUri?: string}} [context]
100
+ * @returns {Collation}
101
+ * @throws {XPathError} FOCH0002 for an unsupported collation
102
+ */
103
+ export function getCollation(uri, context = {}) {
104
+ const relative = uri !== undefined && !/^[A-Za-z][A-Za-z0-9+.-]*:/.test(uri);
105
+ const name =
106
+ (relative && context.staticBaseUri
107
+ ? resolveUri(uri, context.staticBaseUri)
108
+ : uri) ??
109
+ context.defaultCollation ??
110
+ CODEPOINT_COLLATION;
111
+ if (name === CODEPOINT_COLLATION) return codepoint;
112
+ if (name === HTML_ASCII_COLLATION) return htmlAscii;
113
+ if (name === UCA_PREFIX || name.startsWith(`${UCA_PREFIX}?`)) {
114
+ return ucaCollation(name);
115
+ }
116
+ throw new XPathError("FOCH0002", `Unsupported collation ${name}`);
117
+ }
118
+
119
+ /**
120
+ * The collation named by an optional xs:string argument.
121
+ * @param {Array<{value: string}>|undefined} sequence - The argument, or
122
+ * undefined for an arity without collation
123
+ * @param {object} context
124
+ * @returns {Collation}
125
+ */
126
+ export const collationArg = (sequence, context) =>
127
+ getCollation(sequence?.[0]?.value, context);
@@ -0,0 +1,84 @@
1
+ /**
2
+ * fn:collection and fn:uri-collection (F&O 3.1 sections 14.6.6 and
3
+ * 14.6.7), through the dynamic context hook `collection` (see
4
+ * xpath/eval/resources.js), and fn:collation-key (section 5.3.6).
5
+ *
6
+ * @module @tradik/xslt3/functions/collections
7
+ */
8
+
9
+ import { XPathError } from "../errors.js";
10
+ import { AtomicValue, isNode } from "../xdm/atomic.js";
11
+ import { types } from "../xdm/types.js";
12
+ import { collationArg } from "./collations.js";
13
+ import { define } from "./support.js";
14
+
15
+ const encoder = new globalThis.TextEncoder();
16
+
17
+ /**
18
+ * The items of a collection.
19
+ * @param {Array|undefined} uri - The optional argument
20
+ * @param {object} context
21
+ * @returns {Array}
22
+ */
23
+ const items = (uri, context) => context.collection(uri?.[0]?.value ?? null);
24
+
25
+ /**
26
+ * The URIs of a collection: document URIs of its document nodes, atomic
27
+ * items (xs:anyURI) as they are; other nodes have no URI.
28
+ * @param {Array|undefined} uri
29
+ * @param {object} context
30
+ * @returns {Array} xs:anyURI values
31
+ */
32
+ function uris(uri, context) {
33
+ const result = [];
34
+ for (const item of items(uri, context)) {
35
+ const text = isNode(item)
36
+ ? item.nodeType === 9 && item.documentURI
37
+ : item.value;
38
+ if (text) result.push(new AtomicValue(types.anyURI, text));
39
+ }
40
+ return result;
41
+ }
42
+
43
+ /**
44
+ * fn:collation-key: the UTF-8 bytes of the collation key of a string,
45
+ * which order as the collation does (UTF-8 keeps the codepoint order).
46
+ * @param {string} text
47
+ * @param {import("./collations.js").Collation} collation
48
+ * @returns {AtomicValue} an xs:base64Binary
49
+ * @throws {XPathError} FOCH0002 for the UCA collations, whose keys
50
+ * Intl.Collator does not expose
51
+ */
52
+ function collationKey(text, collation) {
53
+ if (!collation.key) {
54
+ throw new XPathError(
55
+ "FOCH0002",
56
+ `No collation keys for the collation ${collation.uri}`,
57
+ );
58
+ }
59
+ return new AtomicValue(
60
+ types.base64Binary,
61
+ encoder.encode(collation.key(text)),
62
+ );
63
+ }
64
+
65
+ /** Function definitions. */
66
+ export const collectionFunctions = [
67
+ define("collection", [], "item()*", (_, c) => items(undefined, c)),
68
+ define("collection", ["xs:string?"], "item()*", ([uri], c) => items(uri, c)),
69
+ define("uri-collection", [], "xs:anyURI*", (_, c) => uris(undefined, c)),
70
+ define("uri-collection", ["xs:string?"], "xs:anyURI*", ([uri], c) =>
71
+ uris(uri, c),
72
+ ),
73
+ define("collation-key", ["xs:string"], "xs:base64Binary", ([[key]], c) => [
74
+ collationKey(key.value, collationArg(undefined, c)),
75
+ ]),
76
+ define(
77
+ "collation-key",
78
+ ["xs:string", "xs:string"],
79
+ "xs:base64Binary",
80
+ ([[key], collation], c) => [
81
+ collationKey(key.value, collationArg(collation, c)),
82
+ ],
83
+ ),
84
+ ];
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Functions on the dynamic context (F&O 3.1 section 15): the current date
3
+ * and time, the implicit timezone, the default collation and language,
4
+ * the static base URI. No environment variables are exposed to
5
+ * expressions (the set is implementation-dependent, and empty here).
6
+ *
7
+ * @module @tradik/xslt3/functions/context
8
+ */
9
+
10
+ import { AtomicValue } from "../xdm/atomic.js";
11
+ import { DateTimeValue } from "../xdm/datetime.js";
12
+ import { Decimal } from "../xdm/decimal.js";
13
+ import { DurationValue } from "../xdm/duration.js";
14
+ import { types } from "../xdm/types.js";
15
+
16
+ /**
17
+ * The current date/time projected onto some components.
18
+ * @param {DateTimeValue} now
19
+ * @param {string[]} components
20
+ * @returns {DateTimeValue}
21
+ */
22
+ function project(now, components) {
23
+ const fields = { timezone: now.timezone };
24
+ for (const name of components) fields[name] = now[name];
25
+ return new DateTimeValue(fields);
26
+ }
27
+
28
+ /**
29
+ * Definition of a function of the context without parameters.
30
+ * @param {string} local
31
+ * @param {string} returns
32
+ * @param {(context: object) => Array} impl
33
+ * @returns {object}
34
+ */
35
+ const contextFunction = (local, returns, impl) => ({
36
+ local,
37
+ params: [],
38
+ returns,
39
+ impl: (_, context) => impl(context),
40
+ });
41
+
42
+ /** Function definitions. */
43
+ export const contextFunctions = [
44
+ contextFunction("current-dateTime", "xs:dateTimeStamp", (c) => [
45
+ new AtomicValue(types.dateTime, c.currentDateTime),
46
+ ]),
47
+ contextFunction("current-date", "xs:date", (c) => [
48
+ new AtomicValue(
49
+ types.date,
50
+ project(c.currentDateTime, ["year", "month", "day"]),
51
+ ),
52
+ ]),
53
+ contextFunction("current-time", "xs:time", (c) => [
54
+ new AtomicValue(
55
+ types.time,
56
+ project(c.currentDateTime, ["hour", "minute", "second"]),
57
+ ),
58
+ ]),
59
+ contextFunction("implicit-timezone", "xs:dayTimeDuration", (c) => [
60
+ new AtomicValue(
61
+ types.dayTimeDuration,
62
+ new DurationValue(0, Decimal.of(BigInt(c.implicitTimezone * 60))),
63
+ ),
64
+ ]),
65
+ contextFunction("default-collation", "xs:string", (c) => [
66
+ new AtomicValue(types.string, c.defaultCollation),
67
+ ]),
68
+ contextFunction("default-language", "xs:language", (c) => [
69
+ new AtomicValue(types.language, c.defaultLanguage),
70
+ ]),
71
+ contextFunction("available-environment-variables", "xs:string*", () => []),
72
+ {
73
+ local: "environment-variable",
74
+ params: ["xs:string"],
75
+ returns: "xs:string?",
76
+ impl: () => [],
77
+ },
78
+ contextFunction("static-base-uri", "xs:anyURI?", (c) =>
79
+ c.staticBaseUri === undefined
80
+ ? []
81
+ : [new AtomicValue(types.anyURI, c.staticBaseUri)],
82
+ ),
83
+ ];
@@ -0,0 +1,167 @@
1
+ /**
2
+ * The core functions of F&O 3.1 that depend on the evaluator: booleans,
3
+ * focus, string, data and number conversion, count, empty and exists.
4
+ * `coreFunctions` gathers these and the other modules of this package
5
+ * that depend on the evaluator or on the hooks of the dynamic context
6
+ * (nodes, higher-order functions, maps and arrays, JSON, resources,
7
+ * random numbers, IDs, collections).
8
+ *
9
+ * @module @tradik/xslt3/functions/core
10
+ */
11
+
12
+ import { toNumber } from "../xdm/generalCompare.js";
13
+ import { atomize, effectiveBooleanValue, stringValue } from "../xdm/nodes.js";
14
+ import {
15
+ booleanItem,
16
+ doubleItem,
17
+ integerItem,
18
+ stringItem,
19
+ } from "../xpath/eval/atomics.js";
20
+ import { arrayFunctions } from "./arrays.js";
21
+ import { contextFunctions } from "./context.js";
22
+ import { higherOrderFunctions } from "./higherOrder.js";
23
+ import { coreStringFunctions, libraryFunctions } from "./library.js";
24
+ import { mapFunctions } from "./maps.js";
25
+ import { nodeFunctions } from "./nodes.js";
26
+ import { focusItem } from "./focus.js";
27
+ import { diagnosticFunctions } from "./diagnostics.js";
28
+ import { collectionFunctions } from "./collections.js";
29
+ import { idFunctions } from "./ids.js";
30
+ import { jsonFunctions } from "./json/index.js";
31
+ import { parseXmlFunctions } from "./parseXml.js";
32
+ import { randomFunctions } from "./random.js";
33
+ import { unparsedTextFunctions } from "./unparsedText.js";
34
+ import { xqueryModuleFunctions } from "./xqueryModule.js";
35
+
36
+ /**
37
+ * fn:string of an optional item.
38
+ * @param {Array} arg
39
+ * @returns {Array} an xs:string
40
+ */
41
+ const stringOf = (arg) => [stringItem(arg.length ? stringValue(arg[0]) : "")];
42
+
43
+ /**
44
+ * fn:number of an optional atomic value.
45
+ * @param {Array} arg
46
+ * @returns {Array} an xs:double
47
+ */
48
+ const numberOf = (arg) => [arg.length ? toNumber(arg[0]) : doubleItem(NaN)];
49
+
50
+ /** Core function definitions. */
51
+ export const coreBasics = [
52
+ {
53
+ local: "true",
54
+ params: [],
55
+ returns: "xs:boolean",
56
+ impl: () => [booleanItem(true)],
57
+ },
58
+ {
59
+ local: "false",
60
+ params: [],
61
+ returns: "xs:boolean",
62
+ impl: () => [booleanItem(false)],
63
+ },
64
+ {
65
+ local: "not",
66
+ params: ["item()*"],
67
+ returns: "xs:boolean",
68
+ impl: ([arg]) => [booleanItem(!effectiveBooleanValue(arg))],
69
+ },
70
+ {
71
+ local: "boolean",
72
+ params: ["item()*"],
73
+ returns: "xs:boolean",
74
+ impl: ([arg]) => [booleanItem(effectiveBooleanValue(arg))],
75
+ },
76
+ {
77
+ local: "position",
78
+ params: [],
79
+ returns: "xs:integer",
80
+ focus: true,
81
+ impl: (_, context) => (focusItem(context), [integerItem(context.position)]),
82
+ },
83
+ {
84
+ local: "last",
85
+ params: [],
86
+ returns: "xs:integer",
87
+ focus: true,
88
+ impl: (_, context) => (focusItem(context), [integerItem(context.size)]),
89
+ },
90
+ {
91
+ local: "string",
92
+ params: [],
93
+ returns: "xs:string",
94
+ focus: true,
95
+ impl: (_, context) => stringOf([focusItem(context)]),
96
+ },
97
+ {
98
+ local: "string",
99
+ params: ["item()?"],
100
+ returns: "xs:string",
101
+ impl: ([arg]) => stringOf(arg),
102
+ },
103
+ {
104
+ local: "data",
105
+ params: [],
106
+ returns: "xs:anyAtomicType*",
107
+ focus: true,
108
+ impl: (_, context) => atomize([focusItem(context)]),
109
+ },
110
+ {
111
+ local: "data",
112
+ params: ["item()*"],
113
+ returns: "xs:anyAtomicType*",
114
+ impl: ([arg]) => atomize(arg),
115
+ },
116
+ {
117
+ local: "number",
118
+ params: [],
119
+ returns: "xs:double",
120
+ focus: true,
121
+ impl: (_, context) => numberOf(atomize([focusItem(context)])),
122
+ },
123
+ {
124
+ local: "number",
125
+ params: ["xs:anyAtomicType?"],
126
+ returns: "xs:double",
127
+ impl: ([arg]) => numberOf(arg),
128
+ },
129
+ {
130
+ local: "count",
131
+ params: ["item()*"],
132
+ returns: "xs:integer",
133
+ impl: ([arg]) => [integerItem(arg.length)],
134
+ },
135
+ {
136
+ local: "empty",
137
+ params: ["item()*"],
138
+ returns: "xs:boolean",
139
+ impl: ([arg]) => [booleanItem(arg.length === 0)],
140
+ },
141
+ {
142
+ local: "exists",
143
+ params: ["item()*"],
144
+ returns: "xs:boolean",
145
+ impl: ([arg]) => [booleanItem(arg.length > 0)],
146
+ },
147
+ ];
148
+
149
+ /** All the function definitions of this package's built-in modules. */
150
+ export const coreFunctions = [
151
+ ...libraryFunctions,
152
+ ...coreStringFunctions,
153
+ ...coreBasics,
154
+ ...diagnosticFunctions,
155
+ ...contextFunctions,
156
+ ...nodeFunctions,
157
+ ...higherOrderFunctions,
158
+ ...mapFunctions,
159
+ ...arrayFunctions,
160
+ ...jsonFunctions,
161
+ ...unparsedTextFunctions,
162
+ ...xqueryModuleFunctions,
163
+ ...parseXmlFunctions,
164
+ ...randomFunctions,
165
+ ...idFunctions,
166
+ ...collectionFunctions,
167
+ ];