@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,127 @@
1
+ /**
2
+ * Parser of the XPath 3.1 expressions between the binary operators and the
3
+ * paths: productions [25] InstanceofExpr to [35] SimpleMapExpr of Appendix
4
+ * A.1 (instance of, treat as, castable as, cast as, `=>`, unary signs and
5
+ * `!`).
6
+ *
7
+ * @module @tradik/xslt3/xpath/syntax/typeOperators
8
+ */
9
+
10
+ import { makeNode } from "./ast.js";
11
+ import { parsePathExpr } from "./paths.js";
12
+ import { parseArgumentList } from "./postfix.js";
13
+ import { parseParenthesizedExpr, parseVarRef } from "./primaries.js";
14
+ import { qName } from "./tokenStream.js";
15
+ import { parseSequenceType, parseSingleType } from "./types.js";
16
+
17
+ /** @typedef {import("./tokenStream.js").TokenStream} TokenStream */
18
+ /** @typedef {import("./ast.js").Expr} Expr */
19
+
20
+ /**
21
+ * SimpleMapExpr ::= PathExpr ("!" PathExpr)*
22
+ *
23
+ * @param {TokenStream} p - Tokens
24
+ * @returns {Expr} The node
25
+ */
26
+ function parseSimpleMapExpr(p) {
27
+ let left = parsePathExpr(p);
28
+ while (p.acceptSymbol("!")) {
29
+ const right = parsePathExpr(p);
30
+ left = makeNode("SimpleMapExpr", { left, right }, left.start, right.end);
31
+ }
32
+ return left;
33
+ }
34
+
35
+ /**
36
+ * UnaryExpr ::= ("-" | "+")* ValueExpr, ValueExpr being a SimpleMapExpr.
37
+ *
38
+ * @param {TokenStream} p - Tokens
39
+ * @returns {Expr} The node
40
+ */
41
+ function parseUnaryExpr(p) {
42
+ const sign = p.acceptSymbol("-") ?? p.acceptSymbol("+");
43
+ if (!sign) return parseSimpleMapExpr(p);
44
+ const operand = parseUnaryExpr(p);
45
+ const fields = { operator: sign.value, operand };
46
+ return makeNode("UnaryExpr", fields, sign.start, operand.end);
47
+ }
48
+
49
+ /**
50
+ * ArrowExpr ::= UnaryExpr ("=>" ArrowFunctionSpecifier ArgumentList)*,
51
+ * the specifier being an EQName, a VarRef or a ParenthesizedExpr.
52
+ *
53
+ * @param {TokenStream} p - Tokens
54
+ * @returns {Expr} The node
55
+ */
56
+ function parseArrowExpr(p) {
57
+ let expr = parseUnaryExpr(p);
58
+ while (p.acceptSymbol("=>")) {
59
+ let functionName = null;
60
+ let functionExpr = null;
61
+ if (p.peek().type === "name") functionName = qName(p.next());
62
+ else if (p.isSymbol("$")) functionExpr = parseVarRef(p);
63
+ else if (p.isSymbol("(")) functionExpr = parseParenthesizedExpr(p);
64
+ else p.fail('Expected a function after "=>"');
65
+ const { arguments: args, end } = parseArgumentList(p);
66
+ const fields = { expr, functionName, functionExpr, arguments: args };
67
+ expr = makeNode("ArrowExpr", fields, expr.start, end);
68
+ }
69
+ return expr;
70
+ }
71
+
72
+ /**
73
+ * Builds the parser of `E keyword1 keyword2 Type` (instance of, treat as,
74
+ * castable as, cast as). Each operator may appear at most once.
75
+ *
76
+ * @param {string} type - Node type
77
+ * @param {string} keywords - The two keywords, space-separated
78
+ * @param {(p: TokenStream) => Expr} operand - Parser of the next level
79
+ * @param {boolean} single - SingleType (cast, castable) or SequenceType
80
+ * @returns {(p: TokenStream) => Expr} Parser of the level
81
+ */
82
+ function typeLevel(type, keywords, operand, single) {
83
+ const [first, second] = keywords.split(" ");
84
+ return (p) => {
85
+ const expr = operand(p);
86
+ if (!p.acceptKeyword(first)) return expr;
87
+ p.expectKeyword(second);
88
+ if (single) {
89
+ const { name, emptyAllowed, end } = parseSingleType(p);
90
+ const fields = { expr, targetType: name, emptyAllowed };
91
+ return makeNode(type, fields, expr.start, end);
92
+ }
93
+ const sequenceType = parseSequenceType(p);
94
+ return makeNode(type, { expr, sequenceType }, expr.start, sequenceType.end);
95
+ };
96
+ }
97
+
98
+ const parseCastExpr = typeLevel("CastExpr", "cast as", parseArrowExpr, true);
99
+ const parseCastableExpr = typeLevel(
100
+ "CastableExpr",
101
+ "castable as",
102
+ parseCastExpr,
103
+ true,
104
+ );
105
+ const parseTreatExpr = typeLevel(
106
+ "TreatExpr",
107
+ "treat as",
108
+ parseCastableExpr,
109
+ false,
110
+ );
111
+ const parseInstanceof = typeLevel(
112
+ "InstanceOfExpr",
113
+ "instance of",
114
+ parseTreatExpr,
115
+ false,
116
+ );
117
+
118
+ /**
119
+ * InstanceofExpr ::= TreatExpr ("instance" "of" SequenceType)?, the entry
120
+ * point of this module.
121
+ *
122
+ * @param {TokenStream} p - Tokens
123
+ * @returns {Expr} The node
124
+ */
125
+ export function parseInstanceofExpr(p) {
126
+ return parseInstanceof(p);
127
+ }
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Parser of XPath 3.1 types: SingleType, SequenceType and ItemType with the
3
+ * function, map and array tests (productions [77] SingleType to [116]
4
+ * ParenthesizedItemType of Appendix A.1). Kind tests are in kindTests.js.
5
+ *
6
+ * Occurrence-indicators constraint (A.1.2): a `?`, `*` or `+` right after
7
+ * an item type always belongs to it, so `4 treat as item() + - 5` is
8
+ * `(4 treat as item()+) - 5`.
9
+ *
10
+ * @module @tradik/xslt3/xpath/syntax/types
11
+ */
12
+
13
+ import { makeNode } from "./ast.js";
14
+ import { isKindTestName, parseKindTest } from "./kindTests.js";
15
+ import { isPlainName, qName } from "./tokenStream.js";
16
+
17
+ /** @typedef {import("./tokenStream.js").TokenStream} TokenStream */
18
+ /** @typedef {import("./typeAst.js").SequenceType} SequenceType */
19
+ /** @typedef {import("./typeAst.js").ItemType} ItemType */
20
+
21
+ const OCCURRENCES = ["?", "*", "+"];
22
+
23
+ /**
24
+ * SingleType ::= SimpleTypeName "?"?
25
+ *
26
+ * @param {TokenStream} p - Tokens
27
+ * @returns {{name: import("./ast.js").QName, emptyAllowed: boolean, end: number}}
28
+ * The type name, whether "?" follows, and the offset after the type
29
+ */
30
+ export function parseSingleType(p) {
31
+ const token = p.expectName("a type name");
32
+ const question = p.acceptSymbol("?");
33
+ const end = question ? question.end : token.end;
34
+ return { name: qName(token), emptyAllowed: Boolean(question), end };
35
+ }
36
+
37
+ /**
38
+ * SequenceType ::= ("empty-sequence" "(" ")") | (ItemType OccurrenceIndicator?)
39
+ *
40
+ * @param {TokenStream} p - Tokens
41
+ * @returns {SequenceType} The type
42
+ */
43
+ export function parseSequenceType(p) {
44
+ const start = p.peek().start;
45
+ if (p.isKeyword("empty-sequence") && p.isSymbol("(", 1)) {
46
+ p.next();
47
+ p.next();
48
+ const end = p.expectSymbol(")").end;
49
+ return makeNode(
50
+ "SequenceType",
51
+ { itemType: null, occurrence: "" },
52
+ start,
53
+ end,
54
+ );
55
+ }
56
+ const itemType = parseItemType(p);
57
+ const indicator = OCCURRENCES.find((symbol) => p.isSymbol(symbol));
58
+ const end = indicator ? p.next().end : itemType.end;
59
+ return makeNode(
60
+ "SequenceType",
61
+ { itemType, occurrence: indicator ?? "" },
62
+ start,
63
+ end,
64
+ );
65
+ }
66
+
67
+ /**
68
+ * ItemType ::= KindTest | ("item" "(" ")") | FunctionTest | MapTest |
69
+ * ArrayTest | AtomicOrUnionType | ParenthesizedItemType
70
+ *
71
+ * @param {TokenStream} p - Tokens
72
+ * @returns {ItemType} The type
73
+ */
74
+ export function parseItemType(p) {
75
+ const token = p.peek();
76
+ if (p.acceptSymbol("(")) {
77
+ const inner = parseItemType(p);
78
+ p.expectSymbol(")");
79
+ return inner;
80
+ }
81
+ if (token.type !== "name") p.fail("Expected an item type");
82
+ if (p.isSymbol("(", 1)) {
83
+ if (isKindTestName(token)) return parseKindTest(p);
84
+ const parse =
85
+ isPlainName(token) && Object.hasOwn(TYPE_TESTS, token.local)
86
+ ? TYPE_TESTS[token.local]
87
+ : null;
88
+ if (parse) {
89
+ p.next();
90
+ p.next();
91
+ const { type, ...fields } = parse(p);
92
+ let end = p.expectSymbol(")").end;
93
+ if (type === "TypedFunctionTest") {
94
+ p.expectKeyword("as");
95
+ fields.returnType = parseSequenceType(p);
96
+ end = fields.returnType.end;
97
+ }
98
+ return makeNode(type, fields, token.start, end);
99
+ }
100
+ }
101
+ p.next();
102
+ return makeNode("AtomicType", { name: qName(token) }, token.start, token.end);
103
+ }
104
+
105
+ /** Parsers of the item tests with a keyword, after the "(". */
106
+ const TYPE_TESTS = {
107
+ item: () => ({ type: "AnyItemTest" }),
108
+ function: parseFunctionTestBody,
109
+ map: parseMapTestBody,
110
+ array: parseArrayTestBody,
111
+ };
112
+
113
+ /**
114
+ * Inside `function(...)`: "*" or the parameter types; the caller reads the
115
+ * `as` return type of a typed test after the ")".
116
+ *
117
+ * @param {TokenStream} p - Tokens
118
+ * @returns {object} Fields of the test
119
+ */
120
+ function parseFunctionTestBody(p) {
121
+ if (p.acceptSymbol("*")) return { type: "AnyFunctionTest" };
122
+ const paramTypes = [];
123
+ if (!p.isSymbol(")")) {
124
+ do paramTypes.push(parseSequenceType(p));
125
+ while (p.acceptSymbol(","));
126
+ }
127
+ return { type: "TypedFunctionTest", paramTypes };
128
+ }
129
+
130
+ /**
131
+ * Inside `map(...)`: "*" or AtomicOrUnionType "," SequenceType.
132
+ *
133
+ * @param {TokenStream} p - Tokens
134
+ * @returns {object} Fields of the test
135
+ */
136
+ function parseMapTestBody(p) {
137
+ if (p.acceptSymbol("*")) return { type: "AnyMapTest" };
138
+ const token = p.expectName("an atomic type");
139
+ const keyType = makeNode(
140
+ "AtomicType",
141
+ { name: qName(token) },
142
+ token.start,
143
+ token.end,
144
+ );
145
+ p.expectSymbol(",");
146
+ return { type: "TypedMapTest", keyType, valueType: parseSequenceType(p) };
147
+ }
148
+
149
+ /**
150
+ * Inside `array(...)`: "*" or SequenceType.
151
+ *
152
+ * @param {TokenStream} p - Tokens
153
+ * @returns {object} Fields of the test
154
+ */
155
+ function parseArrayTestBody(p) {
156
+ if (p.acceptSymbol("*")) return { type: "AnyArrayTest" };
157
+ return { type: "TypedArrayTest", memberType: parseSequenceType(p) };
158
+ }
@@ -0,0 +1,153 @@
1
+ /**
2
+ * XSLT 3.0 and 2.0 (and 1.0 in backwards-compatible mode): compile a
3
+ * stylesheet once, run it on many documents.
4
+ *
5
+ * ```js
6
+ * import { compileStylesheet } from "@tradik/xslt3";
7
+ * const stylesheet = compileStylesheet(xslDocument, { baseUri });
8
+ * const { principal, secondary, messages } = stylesheet.transform({
9
+ * source: xmlDocument,
10
+ * params: { title: "Report" },
11
+ * });
12
+ * ```
13
+ *
14
+ * @module @tradik/xslt3/xslt
15
+ */
16
+
17
+ import { StylesheetCompiler } from "./compiler/stylesheet.js";
18
+ import { normalizeParams } from "./runtime/params.js";
19
+ import { withDefaultMethod } from "./runtime/defaultMethod.js";
20
+ import { setCompiler } from "./runtime/compilerHook.js";
21
+ import { runTransformation } from "./runtime/transformation.js";
22
+ import { xsltError } from "./names.js";
23
+
24
+ /**
25
+ * Parses XML text with the given parser or the global DOMParser.
26
+ * @param {string} text
27
+ * @param {string|undefined} uri
28
+ * @param {((text: string, uri?: string) => Document)|undefined} parseXml
29
+ * @returns {Document}
30
+ */
31
+ function parse(text, uri, parseXml) {
32
+ if (parseXml) return parseXml(text, uri);
33
+ const Parser = globalThis.DOMParser;
34
+ if (!Parser) {
35
+ throw xsltError("XTSE0165", "No XML parser: pass the parseXml option");
36
+ }
37
+ return new Parser().parseFromString(text, "application/xml");
38
+ }
39
+
40
+ /** A compiled stylesheet. */
41
+ export class CompiledStylesheet {
42
+ /** @param {StylesheetCompiler} compiled */
43
+ constructor(compiled) {
44
+ this.compiled = compiled;
45
+ /** @type {Map<string, object>} xsl:output parameters by Clark name ("" unnamed) */
46
+ this.outputs = compiled.outputs;
47
+ }
48
+
49
+ /**
50
+ * The parameters of the unnamed output definition, with
51
+ * `use-character-maps` expanded to a Map of characters to strings.
52
+ * @returns {object}
53
+ */
54
+ get output() {
55
+ return this.compiled.outputFor(null);
56
+ }
57
+
58
+ /**
59
+ * Runs the stylesheet.
60
+ * @param {object} [options]
61
+ * @param {Node} [options.source] - Source document (global context item
62
+ * and initial match selection)
63
+ * @param {string} [options.initialTemplate] - Name of the initial
64
+ * template (`local`, `Q{uri}local`)
65
+ * @param {string} [options.initialMode] - Clark name of the initial mode
66
+ * @param {Array} [options.initialMatchSelection] - Items to apply
67
+ * templates to (default: the source)
68
+ * @param {object|Map} [options.params] - Stylesheet parameters by name
69
+ * @param {boolean} [options.paramsAsUntyped] - JavaScript strings among
70
+ * the stylesheet parameters are xs:untypedAtomic, so that they convert
71
+ * to the declared type (`as="xs:integer"`) as command-line parameters
72
+ * do in other processors; see also `untypedAtomic()`
73
+ * @param {object|Map} [options.templateParams] - Parameters of the
74
+ * initial template or mode
75
+ * @param {object|Map} [options.tunnelParams] - Tunnel parameters
76
+ * @param {(uri: string, base?: string) => Document} [options.documentLoader]
77
+ * - Loads documents for doc() and document(): gets the absolute URI
78
+ * and the base URI the reference was resolved against
79
+ * @param {(uri: string) => (string|Uint8Array|object|null)} [options.textLoader]
80
+ * - Reads text resources for unparsed-text(), json-doc() and the like
81
+ * (default: none; `readFileUri` reads `file:` URIs)
82
+ * @param {(uri: string|null) => Array|null} [options.collections] - The
83
+ * items of a collection for collection() and uri-collection(), `uri`
84
+ * null for the default collection (default: none)
85
+ * @param {(text: string, baseUri?: string) => Document} [options.xmlParser]
86
+ * - Parser for parse-xml() (default: the global DOMParser)
87
+ * @param {() => Document} [options.createDocument] - Creates documents
88
+ * @param {(message: Node) => void} [options.onMessage] - xsl:message
89
+ * @param {string} [options.baseOutputUri] - Base of result-document URIs
90
+ * @param {{name: string, args: Array}} [options.initialFunction] - A
91
+ * stylesheet function to call instead (its result is the principal
92
+ * result)
93
+ * @param {*} [options.globalContextItem] - Default: the source
94
+ * @param {number} [options.implicitTimezone] - Minutes, default 0
95
+ * @param {Date} [options.currentDateTime] - Default: now
96
+ * @param {boolean} [options.buildTree] - Overrides the build-tree
97
+ * serialization parameter of every result: false delivers the raw
98
+ * sequences (as fn:transform does for delivery-format "raw")
99
+ * @param {number} [options.maxDepth] - Deepest nesting of instructions
100
+ * (default 1,000,000; deeper is reported as an infinite recursion)
101
+ * @returns {{principal: Node|Array, secondary: Map<string, {document:
102
+ * Node, output: object}>, messages: Array, output: object}} the
103
+ * results; `output` holds the serialization parameters of the
104
+ * principal result: those of the xsl:result-document that wrote it,
105
+ * else those of the `output` getter
106
+ */
107
+ transform(options = {}) {
108
+ const { principalOutput, ...result } = runTransformation(
109
+ this.compiled,
110
+ options,
111
+ );
112
+ const output =
113
+ principalOutput ??
114
+ withDefaultMethod(
115
+ this.output,
116
+ result.principal,
117
+ this.compiled.versionOf(this.compiled.tree.root) === 1,
118
+ );
119
+ return { ...result, output };
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Compiles a stylesheet.
125
+ * @param {Document|Element|string} stylesheet - The principal module
126
+ * @param {object} [options]
127
+ * @param {string} [options.baseUri] - URI of the principal module
128
+ * @param {(uri: string, base?: string) => Document|string} [options.loadStylesheet]
129
+ * - Loads included and imported modules (and parameter documents): gets
130
+ * the absolute URI and the base URI the href was resolved against
131
+ * @param {(text: string, uri?: string) => Document} [options.parseXml] -
132
+ * XML parser (default: the global DOMParser)
133
+ * @param {object|Map} [options.staticParams] - Values of static
134
+ * parameters (XSLT 3.0) by name
135
+ * @returns {CompiledStylesheet}
136
+ * @throws {import("../errors.js").XPathError} the static errors (XTSE...)
137
+ */
138
+ export function compileStylesheet(stylesheet, options = {}) {
139
+ const parseXml = (text, uri) => parse(text, uri, options.parseXml);
140
+ const source =
141
+ typeof stylesheet === "string"
142
+ ? parseXml(stylesheet, options.baseUri)
143
+ : stylesheet;
144
+ const compiler = new StylesheetCompiler({
145
+ ...options,
146
+ parse: parseXml,
147
+ staticParams: normalizeParams(options.staticParams),
148
+ });
149
+ const uri = options.baseUri ?? (source.documentURI || undefined);
150
+ return new CompiledStylesheet(compiler.compile(source, uri));
151
+ }
152
+
153
+ setCompiler(compileStylesheet);
@@ -0,0 +1,178 @@
1
+ /**
2
+ * The components of a used package seen from the using package (XSLT 3.0
3
+ * sections 3.5.3.2 and 3.5.3.3): the overriding declarations matched to
4
+ * the components they override, and the visibility of every other
5
+ * component after xsl:accept.
6
+ *
7
+ * @module @tradik/xslt3/xslt/compiler/acceptance
8
+ */
9
+
10
+ import { attr, clarkOf, isXsl, tokens, xsltError } from "../names.js";
11
+ import { checkCompatible } from "./compatibility.js";
12
+ import { declaredVisibility } from "./components.js";
13
+ import { infoOf } from "./elementInfo.js";
14
+ import { splitParams } from "./templatesDecl.js";
15
+ import { EXPLICIT, matchesOf } from "./visibility.js";
16
+
17
+ /** Errors of two overriding declarations of the same component. */
18
+ const DUPLICATE = {
19
+ template: "XTSE0660",
20
+ function: "XTSE0770",
21
+ variable: "XTSE0630",
22
+ "attribute-set": "XTSE3055",
23
+ };
24
+
25
+ /** Visibilities in the used package that each xsl:accept value allows. */
26
+ const ACCEPTABLE = {
27
+ public: ["public"],
28
+ private: ["public", "final"],
29
+ final: ["public", "final"],
30
+ abstract: ["abstract"],
31
+ hidden: ["public", "final", "abstract"],
32
+ };
33
+
34
+ /**
35
+ * The visibility in the using package of a component that is not
36
+ * overridden (Visibility of Components in Used and Using Packages).
37
+ * @param {object} component - Exported by the used package
38
+ * @param {object[]} rules - Parsed xsl:accept rules
39
+ * @returns {string}
40
+ */
41
+ function acceptedVisibility(component, rules) {
42
+ if (component.isParam) return "public";
43
+ for (const { rule, precision } of matchesOf(rules, component)) {
44
+ if (ACCEPTABLE[rule.visibility].includes(component.visibility)) {
45
+ return rule.visibility;
46
+ }
47
+ if (precision === EXPLICIT) {
48
+ throw xsltError(
49
+ "XTSE3040",
50
+ `${component.local} cannot be accepted as ${rule.visibility}`,
51
+ );
52
+ }
53
+ }
54
+ return ["public", "final"].includes(component.visibility)
55
+ ? "private"
56
+ : "hidden";
57
+ }
58
+
59
+ /**
60
+ * The component an overriding declaration names.
61
+ * @param {Element} element - Child of xsl:override
62
+ * @param {object} cx
63
+ * @returns {object|null} `{kind, uri, local, arity, key}`, null for a
64
+ * template rule without a name
65
+ */
66
+ function overrideSymbol(element, cx) {
67
+ const name = attr(element, "name");
68
+ if (name === undefined) return null;
69
+ const qname = cx.exprs.qname(name, element);
70
+ const kind = element.localName === "param" ? "variable" : element.localName;
71
+ const key = `{${qname.uri}}${qname.local}`;
72
+ if (kind !== "function") return { kind, ...qname, arity: null, key };
73
+ const arity = splitParams(cx.children(element)).params.length;
74
+ return { kind, ...qname, arity, key: `${key}#${arity}` };
75
+ }
76
+
77
+ /**
78
+ * Checks that the modes of an overriding template rule are public modes
79
+ * of the used package (XTSE3440 for the unnamed mode, XTSE3060).
80
+ * @param {Element} element - xsl:template with a match pattern
81
+ * @param {Map<string, object>} byKey - Exported components
82
+ * @param {object} cx
83
+ */
84
+ function checkRuleModes(element, byKey, cx) {
85
+ const text = attr(element, "mode");
86
+ const { defaultMode } = infoOf(element);
87
+ const keys =
88
+ text === undefined
89
+ ? [defaultMode]
90
+ : tokens(text).map((token) => {
91
+ if (token === "#default") return defaultMode;
92
+ return token.startsWith("#")
93
+ ? ""
94
+ : clarkOf(cx.exprs.qname(token, element));
95
+ });
96
+ for (const key of keys) {
97
+ if (key === "") {
98
+ throw xsltError("XTSE3440", "An overriding template rule needs a mode");
99
+ }
100
+ if (byKey.get(`mode ${key}`)?.visibility !== "public") {
101
+ throw xsltError("XTSE3060", `No template rules can be added to ${key}`);
102
+ }
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Matches the overriding declarations of an xsl:use-package with the
108
+ * components they override.
109
+ * @param {Element[]} overrides - Children of xsl:override
110
+ * @param {object[]} rules - Parsed xsl:accept rules
111
+ * @param {Map<string, object>} byKey - Exported components by "kind key"
112
+ * @param {object} cx - The using package's compiler
113
+ * @returns {{list: object[], overridden: Map<object, Element>}} the
114
+ * declarations `{element, symbol, component}` and the overridden
115
+ * components
116
+ */
117
+ export function matchOverrides(overrides, rules, byKey, cx) {
118
+ const overridden = new Map();
119
+ const list = [];
120
+ for (const element of overrides) {
121
+ const symbol = overrideSymbol(element, cx);
122
+ if (attr(element, "match") !== undefined) {
123
+ checkRuleModes(element, byKey, cx);
124
+ }
125
+ if (!symbol) {
126
+ list.push({ element, symbol: null, component: null });
127
+ continue;
128
+ }
129
+ const component = byKey.get(`${symbol.kind} ${symbol.key}`);
130
+ if (!component) {
131
+ throw xsltError("XTSE3058", `${symbol.local} overrides nothing`);
132
+ }
133
+ if (!["public", "abstract"].includes(component.visibility)) {
134
+ throw xsltError("XTSE3060", `${symbol.local} cannot be overridden`);
135
+ }
136
+ if (matchesOf(rules, symbol).some((m) => m.precision === EXPLICIT)) {
137
+ throw xsltError("XTSE3051", `${symbol.local} is accepted and overridden`);
138
+ }
139
+ if (overridden.has(component)) {
140
+ throw xsltError(DUPLICATE[symbol.kind], `${symbol.local} twice`);
141
+ }
142
+ checkCompatible(element, component, cx);
143
+ overridden.set(component, element);
144
+ list.push({ element, symbol, component });
145
+ }
146
+ return { list, overridden };
147
+ }
148
+
149
+ /**
150
+ * The components of the used package with their visibility in the using
151
+ * package, hidden ones left out.
152
+ * @param {object[]} exported - Components exported by the used package
153
+ * @param {Map<object, Element>} overridden - From {@link matchOverrides}
154
+ * @param {object[]} rules - Parsed xsl:accept rules
155
+ * @param {boolean} [implicit] - The using package is an implicit one (an
156
+ * xsl:stylesheet), whose templates and modes are public by default
157
+ * @returns {object[]} `{component, visibility, override}`
158
+ */
159
+ export function acceptComponents(exported, overridden, rules, implicit) {
160
+ const accepted = [];
161
+ for (const component of exported) {
162
+ const element = overridden.get(component);
163
+ let visibility;
164
+ if (!element) visibility = acceptedVisibility(component, rules);
165
+ else if (isXsl(element, "param")) visibility = "public";
166
+ else {
167
+ const fallback =
168
+ implicit && ["template", "mode"].includes(component.kind)
169
+ ? "public"
170
+ : "private";
171
+ visibility = declaredVisibility(element, component.kind) ?? fallback;
172
+ }
173
+ if (visibility !== "hidden") {
174
+ accepted.push({ component, visibility, override: element ?? null });
175
+ }
176
+ }
177
+ return accepted;
178
+ }