@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.
- package/LICENSE.md +28 -0
- package/README.md +98 -2
- package/package.json +43 -4
- package/src/errors.js +20 -0
- package/src/functions/aggregates.js +144 -0
- package/src/functions/arraySort.js +33 -0
- package/src/functions/arrays.js +181 -0
- package/src/functions/attributeTypes.js +58 -0
- package/src/functions/baseUris.js +82 -0
- package/src/functions/collations.js +127 -0
- package/src/functions/collections.js +84 -0
- package/src/functions/context.js +83 -0
- package/src/functions/core.js +167 -0
- package/src/functions/datetime.js +203 -0
- package/src/functions/deepEqual.js +132 -0
- package/src/functions/diagnostics.js +88 -0
- package/src/functions/focus.js +34 -0
- package/src/functions/format/dateComponents.js +176 -0
- package/src/functions/format/datePicture.js +115 -0
- package/src/functions/format/decimalFormat.js +65 -0
- package/src/functions/format/digitPattern.js +145 -0
- package/src/functions/format/formatDateTime.js +204 -0
- package/src/functions/format/formatInteger.js +109 -0
- package/src/functions/format/formatNumber.js +165 -0
- package/src/functions/format/fractionFormat.js +80 -0
- package/src/functions/format/germanWords.js +89 -0
- package/src/functions/format/numberLanguages.js +41 -0
- package/src/functions/format/numberPicture.js +202 -0
- package/src/functions/format/numberWords.js +155 -0
- package/src/functions/format/place.js +74 -0
- package/src/functions/format/timezoneFormat.js +89 -0
- package/src/functions/higherOrder.js +106 -0
- package/src/functions/ids.js +127 -0
- package/src/functions/json/index.js +17 -0
- package/src/functions/json/jsonChars.js +110 -0
- package/src/functions/json/jsonParser.js +203 -0
- package/src/functions/json/jsonStrings.js +116 -0
- package/src/functions/json/jsonToXml.js +116 -0
- package/src/functions/json/parseJson.js +119 -0
- package/src/functions/json/xmlRepresentation.js +103 -0
- package/src/functions/json/xmlToJson.js +147 -0
- package/src/functions/library.js +47 -0
- package/src/functions/mapArrayEqual.js +41 -0
- package/src/functions/maps.js +152 -0
- package/src/functions/math.js +73 -0
- package/src/functions/nodePaths.js +181 -0
- package/src/functions/nodes.js +199 -0
- package/src/functions/numeric.js +148 -0
- package/src/functions/options.js +58 -0
- package/src/functions/parseIetfDate.js +104 -0
- package/src/functions/parseXml.js +77 -0
- package/src/functions/qnames.js +68 -0
- package/src/functions/random.js +128 -0
- package/src/functions/regex/analyzeString.js +144 -0
- package/src/functions/regex/charClass.js +112 -0
- package/src/functions/regex/compile.js +81 -0
- package/src/functions/regex/escapes.js +109 -0
- package/src/functions/regex/parser.js +169 -0
- package/src/functions/regex/reader.js +37 -0
- package/src/functions/regex/regexFunctions.js +140 -0
- package/src/functions/regex/translate.js +102 -0
- package/src/functions/regex/unicodeBlocks.js +194 -0
- package/src/functions/registry.js +140 -0
- package/src/functions/sequences.js +173 -0
- package/src/functions/serializeFunction.js +53 -0
- package/src/functions/signatures.js +105 -0
- package/src/functions/sort.js +102 -0
- package/src/functions/stringMatch.js +45 -0
- package/src/functions/strings.js +194 -0
- package/src/functions/stringsCore.js +66 -0
- package/src/functions/support.js +106 -0
- package/src/functions/textDecoding.js +117 -0
- package/src/functions/ucaCollation.js +127 -0
- package/src/functions/unparsedText.js +71 -0
- package/src/functions/uri.js +166 -0
- package/src/functions/xqueryModule.js +24 -0
- package/src/index.js +38 -0
- package/src/items/array.js +84 -0
- package/src/items/function.js +45 -0
- package/src/items/map.js +120 -0
- package/src/items/mapKey.js +82 -0
- package/src/serialize/index.js +129 -0
- package/src/serialize/markup/content.js +74 -0
- package/src/serialize/markup/dialect.js +178 -0
- package/src/serialize/markup/htmlData.js +70 -0
- package/src/serialize/markup/namespaces.js +145 -0
- package/src/serialize/markup/prolog.js +91 -0
- package/src/serialize/markup/writer.js +183 -0
- package/src/serialize/methods/adaptive.js +131 -0
- package/src/serialize/methods/json.js +158 -0
- package/src/serialize/methods/text.js +43 -0
- package/src/serialize/output/buffer.js +48 -0
- package/src/serialize/output/encoding.js +146 -0
- package/src/serialize/output/expander.js +204 -0
- package/src/serialize/params/fromElement.js +141 -0
- package/src/serialize/params/fromMap.js +128 -0
- package/src/serialize/params/names.js +69 -0
- package/src/serialize/params/settings.js +153 -0
- package/src/serialize/params/values.js +163 -0
- package/src/serialize/sequence.js +111 -0
- package/src/xdm/arithmetic.js +155 -0
- package/src/xdm/atomic.js +142 -0
- package/src/xdm/binary.js +92 -0
- package/src/xdm/calendar.js +71 -0
- package/src/xdm/cast.js +176 -0
- package/src/xdm/compare.js +192 -0
- package/src/xdm/datetime.js +206 -0
- package/src/xdm/decimal.js +200 -0
- package/src/xdm/duration.js +128 -0
- package/src/xdm/generalCompare.js +152 -0
- package/src/xdm/index.js +47 -0
- package/src/xdm/lexical.js +126 -0
- package/src/xdm/nodes.js +170 -0
- package/src/xdm/numeric.js +122 -0
- package/src/xdm/qname.js +65 -0
- package/src/xdm/strings.js +52 -0
- package/src/xdm/temporalArithmetic.js +180 -0
- package/src/xdm/timeline.js +68 -0
- package/src/xdm/types.js +178 -0
- package/src/xpath/eval/atomics.js +45 -0
- package/src/xpath/eval/axes.js +212 -0
- package/src/xpath/eval/calls.js +168 -0
- package/src/xpath/eval/coercion.js +146 -0
- package/src/xpath/eval/compiler.js +71 -0
- package/src/xpath/eval/constructors.js +129 -0
- package/src/xpath/eval/decimalFormats.js +93 -0
- package/src/xpath/eval/descendantMemo.js +77 -0
- package/src/xpath/eval/documentOrder.js +142 -0
- package/src/xpath/eval/domNodes.js +174 -0
- package/src/xpath/eval/dynamicCall.js +27 -0
- package/src/xpath/eval/dynamicContext.js +161 -0
- package/src/xpath/eval/flow.js +115 -0
- package/src/xpath/eval/functionItems.js +194 -0
- package/src/xpath/eval/groupedChildren.js +88 -0
- package/src/xpath/eval/inline.js +71 -0
- package/src/xpath/eval/namespaceNodes.js +90 -0
- package/src/xpath/eval/nodeTests.js +164 -0
- package/src/xpath/eval/operators.js +190 -0
- package/src/xpath/eval/paths.js +163 -0
- package/src/xpath/eval/positional.js +81 -0
- package/src/xpath/eval/predicates.js +56 -0
- package/src/xpath/eval/primary.js +99 -0
- package/src/xpath/eval/resources.js +149 -0
- package/src/xpath/eval/scope.js +108 -0
- package/src/xpath/eval/sequenceType.js +193 -0
- package/src/xpath/eval/staticContext.js +142 -0
- package/src/xpath/eval/steps.js +98 -0
- package/src/xpath/eval/subtype.js +154 -0
- package/src/xpath/eval/typeExprs.js +147 -0
- package/src/xpath/eval/typeNames.js +101 -0
- package/src/xpath/eval/uris.js +21 -0
- package/src/xpath/eval/values.js +64 -0
- package/src/xpath/index.js +217 -0
- package/src/xpath/syntax/ast.js +130 -0
- package/src/xpath/syntax/chars.js +58 -0
- package/src/xpath/syntax/constructors.js +144 -0
- package/src/xpath/syntax/expressions.js +107 -0
- package/src/xpath/syntax/index.js +44 -0
- package/src/xpath/syntax/kindTests.js +134 -0
- package/src/xpath/syntax/lexer.js +220 -0
- package/src/xpath/syntax/operators.js +111 -0
- package/src/xpath/syntax/paths.js +102 -0
- package/src/xpath/syntax/postfix.js +91 -0
- package/src/xpath/syntax/primaries.js +149 -0
- package/src/xpath/syntax/steps.js +146 -0
- package/src/xpath/syntax/syntaxError.js +31 -0
- package/src/xpath/syntax/tokenStream.js +163 -0
- package/src/xpath/syntax/typeAst.js +76 -0
- package/src/xpath/syntax/typeOperators.js +127 -0
- package/src/xpath/syntax/types.js +158 -0
- package/src/xslt/api.js +153 -0
- package/src/xslt/compiler/acceptance.js +178 -0
- package/src/xslt/compiler/accumulatorDecl.js +146 -0
- package/src/xslt/compiler/attributeValues.js +174 -0
- package/src/xslt/compiler/attributes.js +211 -0
- package/src/xslt/compiler/avt.js +103 -0
- package/src/xslt/compiler/body.js +154 -0
- package/src/xslt/compiler/children.js +105 -0
- package/src/xslt/compiler/compatibility.js +130 -0
- package/src/xslt/compiler/components.js +179 -0
- package/src/xslt/compiler/contextItem.js +95 -0
- package/src/xslt/compiler/decimalFormats.js +132 -0
- package/src/xslt/compiler/declarationKinds.js +82 -0
- package/src/xslt/compiler/elementInfo.js +246 -0
- package/src/xslt/compiler/expressions.js +175 -0
- package/src/xslt/compiler/globalContextItem.js +92 -0
- package/src/xslt/compiler/globals.js +209 -0
- package/src/xslt/compiler/linker.js +134 -0
- package/src/xslt/compiler/miscDecl.js +171 -0
- package/src/xslt/compiler/modeDecl.js +88 -0
- package/src/xslt/compiler/moduleLoading.js +111 -0
- package/src/xslt/compiler/modules.js +158 -0
- package/src/xslt/compiler/outputDecl.js +209 -0
- package/src/xslt/compiler/overrideLinks.js +141 -0
- package/src/xslt/compiler/packageChecks.js +84 -0
- package/src/xslt/compiler/packageRegistry.js +95 -0
- package/src/xslt/compiler/packageTable.js +181 -0
- package/src/xslt/compiler/packageVersions.js +143 -0
- package/src/xslt/compiler/packages.js +138 -0
- package/src/xslt/compiler/registry.js +234 -0
- package/src/xslt/compiler/staticStage.js +197 -0
- package/src/xslt/compiler/staticVariables.js +93 -0
- package/src/xslt/compiler/stylesheet.js +205 -0
- package/src/xslt/compiler/tailPosition.js +74 -0
- package/src/xslt/compiler/templatesDecl.js +180 -0
- package/src/xslt/compiler/useAccumulators.js +76 -0
- package/src/xslt/compiler/useWhen.js +94 -0
- package/src/xslt/compiler/visibility.js +160 -0
- package/src/xslt/index.js +11 -0
- package/src/xslt/instructions/analyzeString.js +137 -0
- package/src/xslt/instructions/assert.js +72 -0
- package/src/xslt/instructions/attributeSets.js +115 -0
- package/src/xslt/instructions/conditional.js +99 -0
- package/src/xslt/instructions/control.js +123 -0
- package/src/xslt/instructions/copy.js +151 -0
- package/src/xslt/instructions/elements.js +161 -0
- package/src/xslt/instructions/evaluate.js +189 -0
- package/src/xslt/instructions/fork.js +35 -0
- package/src/xslt/instructions/grouping.js +106 -0
- package/src/xslt/instructions/index.js +94 -0
- package/src/xslt/instructions/iterate.js +182 -0
- package/src/xslt/instructions/literal.js +142 -0
- package/src/xslt/instructions/maps.js +72 -0
- package/src/xslt/instructions/merge.js +190 -0
- package/src/xslt/instructions/number.js +205 -0
- package/src/xslt/instructions/output.js +102 -0
- package/src/xslt/instructions/params.js +110 -0
- package/src/xslt/instructions/resultDocument.js +143 -0
- package/src/xslt/instructions/sort.js +114 -0
- package/src/xslt/instructions/sourceDocument.js +73 -0
- package/src/xslt/instructions/templates.js +153 -0
- package/src/xslt/instructions/text.js +151 -0
- package/src/xslt/instructions/try.js +186 -0
- package/src/xslt/instructions/variables.js +119 -0
- package/src/xslt/names.js +204 -0
- package/src/xslt/patterns/axisOrigins.js +121 -0
- package/src/xslt/patterns/compile.js +151 -0
- package/src/xslt/patterns/general.js +132 -0
- package/src/xslt/patterns/grammar.js +190 -0
- package/src/xslt/patterns/modes.js +153 -0
- package/src/xslt/patterns/paths.js +130 -0
- package/src/xslt/patterns/patternChecks.js +29 -0
- package/src/xslt/patterns/steps.js +162 -0
- package/src/xslt/processor.js +178 -0
- package/src/xslt/runtime/accumulatorFunctions.js +48 -0
- package/src/xslt/runtime/accumulators.js +174 -0
- package/src/xslt/runtime/apply.js +153 -0
- package/src/xslt/runtime/atomicKeys.js +36 -0
- package/src/xslt/runtime/availability.js +162 -0
- package/src/xslt/runtime/baseUri.js +64 -0
- package/src/xslt/runtime/compilerHook.js +27 -0
- package/src/xslt/runtime/conditional.js +110 -0
- package/src/xslt/runtime/context.js +106 -0
- package/src/xslt/runtime/copy.js +123 -0
- package/src/xslt/runtime/copyFunctions.js +71 -0
- package/src/xslt/runtime/copyOrigins.js +60 -0
- package/src/xslt/runtime/defaultMethod.js +42 -0
- package/src/xslt/runtime/documentContent.js +93 -0
- package/src/xslt/runtime/dynamicXPath.js +90 -0
- package/src/xslt/runtime/functionCache.js +65 -0
- package/src/xslt/runtime/functionCall.js +57 -0
- package/src/xslt/runtime/functions.js +191 -0
- package/src/xslt/runtime/groups.js +108 -0
- package/src/xslt/runtime/invocation.js +156 -0
- package/src/xslt/runtime/iteration.js +107 -0
- package/src/xslt/runtime/keys.js +141 -0
- package/src/xslt/runtime/lazy.js +97 -0
- package/src/xslt/runtime/locations.js +86 -0
- package/src/xslt/runtime/machine.js +137 -0
- package/src/xslt/runtime/merging.js +167 -0
- package/src/xslt/runtime/namespaceScope.js +141 -0
- package/src/xslt/runtime/numberFormat.js +89 -0
- package/src/xslt/runtime/numbering.js +168 -0
- package/src/xslt/runtime/params.js +59 -0
- package/src/xslt/runtime/properties.js +103 -0
- package/src/xslt/runtime/rawResults.js +82 -0
- package/src/xslt/runtime/sequenceReceiver.js +102 -0
- package/src/xslt/runtime/snapshot.js +66 -0
- package/src/xslt/runtime/sortKeys.js +119 -0
- package/src/xslt/runtime/streamAvailable.js +60 -0
- package/src/xslt/runtime/strip.js +102 -0
- package/src/xslt/runtime/transformFunction.js +169 -0
- package/src/xslt/runtime/transformation.js +168 -0
- package/src/xslt/runtime/transformationContext.js +85 -0
- package/src/xslt/runtime/treeReceiver.js +194 -0
- package/src/xslt/runtime/values.js +92 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the compiled stylesheet holds, filled during compilation and read
|
|
3
|
+
* at run time: global variable names, named templates, modes and their
|
|
4
|
+
* rules, attribute sets, keys and stylesheet functions.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/xslt/compiler/registry
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Mode } from "../patterns/modes.js";
|
|
10
|
+
import { useStaticContext } from "../runtime/context.js";
|
|
11
|
+
import { callFunction } from "../runtime/functionCall.js";
|
|
12
|
+
import { attr, displayName, tokens, xsltError } from "../names.js";
|
|
13
|
+
import { infoOf } from "./elementInfo.js";
|
|
14
|
+
import { expandCharacterMaps } from "./outputDecl.js";
|
|
15
|
+
import { StaticStage } from "./staticStage.js";
|
|
16
|
+
|
|
17
|
+
/** Registries of a stylesheet. */
|
|
18
|
+
export class CompilerRegistry extends StaticStage {
|
|
19
|
+
/** @param {object} options - See compileStylesheet */
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super(options);
|
|
22
|
+
/** @type {Array<() => void>} checks run once everything is compiled */
|
|
23
|
+
this.deferred = [];
|
|
24
|
+
this.attributeSets = new Map();
|
|
25
|
+
/** @type {Map<string, object>} */
|
|
26
|
+
this.namedTemplates = new Map();
|
|
27
|
+
/** @type {Map<string, Mode>} */
|
|
28
|
+
this.modes = new Map();
|
|
29
|
+
this.allModeRules = [];
|
|
30
|
+
this.keys = new Map();
|
|
31
|
+
this.functionBodies = new Map();
|
|
32
|
+
this.declarationPrecedence = new WeakMap();
|
|
33
|
+
this.positions = 0;
|
|
34
|
+
this.globalKeys = [];
|
|
35
|
+
this.globalVars = null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** @param {string[]} keys - Clark names of the global variables */
|
|
39
|
+
setGlobals(keys) {
|
|
40
|
+
this.globalKeys = keys;
|
|
41
|
+
let vars = null;
|
|
42
|
+
for (const key of keys) vars = { key, next: vars };
|
|
43
|
+
this.globalVars = vars;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** @returns {{vars: object|null}} the scope of top-level declarations */
|
|
47
|
+
globalScope() {
|
|
48
|
+
return { vars: this.globalVars };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** @returns {number} the next declaration position */
|
|
52
|
+
nextPosition() {
|
|
53
|
+
return this.positions++;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @param {Element} element - A top-level declaration
|
|
58
|
+
* @returns {number} its import precedence
|
|
59
|
+
*/
|
|
60
|
+
precedenceOf(element) {
|
|
61
|
+
return this.declarationPrecedence.get(element) ?? 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Registers a named template (the highest precedence wins).
|
|
66
|
+
* @param {string} key
|
|
67
|
+
* @param {object} template
|
|
68
|
+
*/
|
|
69
|
+
addNamedTemplate(key, template) {
|
|
70
|
+
const current = this.namedTemplates.get(key);
|
|
71
|
+
if (current && current.precedence === template.precedence) {
|
|
72
|
+
throw xsltError("XTSE0660", `Two templates are named ${key}`);
|
|
73
|
+
}
|
|
74
|
+
if (!current || current.precedence < template.precedence) {
|
|
75
|
+
this.namedTemplates.set(key, template);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Gets or creates a mode.
|
|
81
|
+
* @param {string} name - Clark name, "" for the unnamed mode
|
|
82
|
+
* @returns {Mode}
|
|
83
|
+
*/
|
|
84
|
+
mode(name) {
|
|
85
|
+
let mode = this.modes.get(name);
|
|
86
|
+
if (!mode) {
|
|
87
|
+
mode = new Mode(name);
|
|
88
|
+
for (const rule of this.allModeRules) mode.add({ ...rule });
|
|
89
|
+
this.modes.set(name, mode);
|
|
90
|
+
}
|
|
91
|
+
return mode;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Adds a template rule to a mode ("#all": every mode).
|
|
96
|
+
* @param {string} name
|
|
97
|
+
* @param {object} rule
|
|
98
|
+
*/
|
|
99
|
+
addRule(name, rule) {
|
|
100
|
+
if (name === "#all") {
|
|
101
|
+
this.allModeRules.push(rule);
|
|
102
|
+
for (const mode of this.modes.values()) mode.add({ ...rule });
|
|
103
|
+
} else this.mode(name).add(rule);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Makes sure the unnamed mode exists. */
|
|
107
|
+
finishModes() {
|
|
108
|
+
this.mode("");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Resolves the mode attribute of xsl:apply-templates.
|
|
113
|
+
* @param {string|undefined} text
|
|
114
|
+
* @param {Element} element
|
|
115
|
+
* @returns {{current: boolean, name: string}}
|
|
116
|
+
*/
|
|
117
|
+
modeRef(text, element) {
|
|
118
|
+
const token = text?.trim();
|
|
119
|
+
if (token === "#current") return { current: true, name: "" };
|
|
120
|
+
if (token === undefined || token === "#default") {
|
|
121
|
+
return { current: false, name: infoOf(element).defaultMode };
|
|
122
|
+
}
|
|
123
|
+
if (token === "#unnamed") return { current: false, name: "" };
|
|
124
|
+
if (tokens(token).length !== 1) {
|
|
125
|
+
throw xsltError("XTSE0550", `Invalid mode ${text}`);
|
|
126
|
+
}
|
|
127
|
+
const name = this.exprs.qname(token, element);
|
|
128
|
+
return { current: false, name: `{${name.uri}}${name.local}` };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Static checks of xsl:call-template once all templates are known.
|
|
133
|
+
* @param {string} key
|
|
134
|
+
* @param {{names: Set<string>}} params - Its xsl:with-param children
|
|
135
|
+
* @param {Element} element
|
|
136
|
+
*/
|
|
137
|
+
checkCall(key, params, element) {
|
|
138
|
+
const template = this.namedTemplates.get(key);
|
|
139
|
+
if (!template) {
|
|
140
|
+
throw xsltError("XTSE0650", `No template named ${displayName(key)}`);
|
|
141
|
+
}
|
|
142
|
+
const declared = new Set(
|
|
143
|
+
template.params.filter((p) => !p.tunnel).map((p) => p.key),
|
|
144
|
+
);
|
|
145
|
+
for (const name of params.names) {
|
|
146
|
+
if (!declared.has(name) && infoOf(element).version >= 2) {
|
|
147
|
+
throw xsltError(
|
|
148
|
+
"XTSE0680",
|
|
149
|
+
`The template ${key} has no parameter ${name}`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
for (const param of template.params) {
|
|
154
|
+
if (param.required && !param.tunnel && !params.names.has(param.key)) {
|
|
155
|
+
throw xsltError("XTSE0690", `The parameter ${param.key} is required`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The function library definition of a stylesheet function.
|
|
162
|
+
* @param {object} signature
|
|
163
|
+
* @returns {object}
|
|
164
|
+
*/
|
|
165
|
+
functionDefinition(signature) {
|
|
166
|
+
// filled by compileFunction once every signature is known
|
|
167
|
+
const compiled = { params: [], body: [], convert: null };
|
|
168
|
+
this.functionBodies.set(signature.key, compiled);
|
|
169
|
+
return {
|
|
170
|
+
namespace: signature.uri,
|
|
171
|
+
local: signature.local,
|
|
172
|
+
params: Array(signature.arity).fill("item()*"),
|
|
173
|
+
returns: "item()*",
|
|
174
|
+
impl: (args, context) => callFunction(compiled, args, context),
|
|
175
|
+
// xsl:evaluate sees the public and final functions only
|
|
176
|
+
visibility:
|
|
177
|
+
attr(signature.declaration.element, "visibility")?.trim() ?? "private",
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* The XPath context in which a pattern's predicates are evaluated.
|
|
183
|
+
* @param {*} item - The node a step of the pattern tests
|
|
184
|
+
* @param {object} xc - XSLT context (its item is the item matched)
|
|
185
|
+
* @param {boolean} [local] - The pattern sees the local variables of xc
|
|
186
|
+
* @returns {object}
|
|
187
|
+
*/
|
|
188
|
+
patternContext(item, xc, local = false) {
|
|
189
|
+
const dyn = Object.create(xc.tx.dyn);
|
|
190
|
+
dyn.xc = xc;
|
|
191
|
+
// no current output URI in patterns (XSLT 3.0 section 20.3.?)
|
|
192
|
+
dyn.dynamicCall = true;
|
|
193
|
+
useStaticContext(dyn, xc.tx.stylesheet.sc);
|
|
194
|
+
const env = local ? xc.env : xc.tx.globalEnv;
|
|
195
|
+
return { item, position: 1, size: 1, env, dyn };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* The parameters of a named output definition.
|
|
200
|
+
* @param {string|null} name - Lexical QName, null for the unnamed one
|
|
201
|
+
* @param {Element} element - Element on which the name is written
|
|
202
|
+
* @param {object} [overrides] - Parameters that take precedence (those
|
|
203
|
+
* of an xsl:result-document)
|
|
204
|
+
* @returns {object}
|
|
205
|
+
*/
|
|
206
|
+
outputFor(name, element, overrides = {}) {
|
|
207
|
+
let output = this.outputs.get("") ?? {};
|
|
208
|
+
if (name !== null) {
|
|
209
|
+
const qname = this.exprs.qname(name, element, { code: "XTDE1460" });
|
|
210
|
+
output = this.outputs.get(`{${qname.uri}}${qname.local}`);
|
|
211
|
+
if (!output) throw xsltError("XTDE1460", `No output definition ${name}`);
|
|
212
|
+
}
|
|
213
|
+
const params = { ...output, ...overrides };
|
|
214
|
+
if (params["item-separator"] === "#absent") delete params["item-separator"];
|
|
215
|
+
// The default html-version is implementation-defined (XSLT 3.0 section
|
|
216
|
+
// 26.1): HTML 4.01, as in XSLT 1.0 and 2.0, for an XSLT 1.0 or 2.0
|
|
217
|
+
// principal stylesheet module, else HTML5.
|
|
218
|
+
if (
|
|
219
|
+
(params.method === undefined || params.method === "html") &&
|
|
220
|
+
params["html-version"] === undefined &&
|
|
221
|
+
params.version === undefined &&
|
|
222
|
+
infoOf(this.tree.root).version < 3
|
|
223
|
+
) {
|
|
224
|
+
params["html-version"] = "4.01";
|
|
225
|
+
}
|
|
226
|
+
if (params["use-character-maps"]) {
|
|
227
|
+
params["use-character-maps"] = expandCharacterMaps(
|
|
228
|
+
params["use-character-maps"],
|
|
229
|
+
this.characterMaps,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
return params;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The static stage of compilation (XSLT 3.0 section 3.13): stylesheet
|
|
3
|
+
* modules loaded, elements kept or dropped by use-when, static variables
|
|
4
|
+
* and parameters evaluated in document order, shadow attributes
|
|
5
|
+
* replaced by their values.
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/xslt/compiler/staticStage
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { toSequence } from "../../xpath/eval/values.js";
|
|
11
|
+
import { stringItem } from "../../xpath/eval/atomics.js";
|
|
12
|
+
import {
|
|
13
|
+
attr,
|
|
14
|
+
clarkOf,
|
|
15
|
+
isXsl,
|
|
16
|
+
resolveQName,
|
|
17
|
+
setShadowAttributes,
|
|
18
|
+
XSL_NS,
|
|
19
|
+
xsltError,
|
|
20
|
+
} from "../names.js";
|
|
21
|
+
import { significantChildren } from "./children.js";
|
|
22
|
+
import { forgetInfo, infoOf } from "./elementInfo.js";
|
|
23
|
+
import {
|
|
24
|
+
isModuleReference,
|
|
25
|
+
loadModuleDocument,
|
|
26
|
+
preloadModule,
|
|
27
|
+
} from "./moduleLoading.js";
|
|
28
|
+
import { declareConsistently } from "./staticVariables.js";
|
|
29
|
+
import { evaluateStatic, evaluateStaticAvt, useWhen } from "./useWhen.js";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {Element} element
|
|
33
|
+
* @returns {boolean} whether an element declares a static variable or
|
|
34
|
+
* parameter
|
|
35
|
+
*/
|
|
36
|
+
const isStaticDeclaration = (element) =>
|
|
37
|
+
(isXsl(element, "variable") || isXsl(element, "param")) &&
|
|
38
|
+
["yes", "true", "1"].includes(attr(element, "static")?.trim()) &&
|
|
39
|
+
(isXsl(element.parentNode, "stylesheet") ||
|
|
40
|
+
isXsl(element.parentNode, "transform") ||
|
|
41
|
+
isXsl(element.parentNode, "package"));
|
|
42
|
+
|
|
43
|
+
/** Module loading and the static stage. */
|
|
44
|
+
export class StaticStage {
|
|
45
|
+
/**
|
|
46
|
+
* @param {object} options - See compileStylesheet: `loadStylesheet`,
|
|
47
|
+
* `parse`, `staticParams` (Map of Clark names to values)
|
|
48
|
+
*/
|
|
49
|
+
constructor(options) {
|
|
50
|
+
this.options = options;
|
|
51
|
+
/** @type {Map<string, Array>} static variables by Clark name */
|
|
52
|
+
this.statics = new Map();
|
|
53
|
+
/** @type {Map<string, Document>} stylesheet modules by URI */
|
|
54
|
+
this.moduleDocuments = new Map();
|
|
55
|
+
this.childCache = new WeakMap();
|
|
56
|
+
this.includedCache = new WeakMap();
|
|
57
|
+
/** @type {Map<string, Document|Element>} loaded modules by URI */
|
|
58
|
+
this.loadedModules = new Map();
|
|
59
|
+
/** @type {Map<string, object>} static declarations by Clark name */
|
|
60
|
+
this.staticDeclarations = new Map();
|
|
61
|
+
/** @type {number[]} the xsl:import elements being loaded, outermost first */
|
|
62
|
+
this.importPath = [];
|
|
63
|
+
this.imports = 0;
|
|
64
|
+
/** @type {Set<string>} modules being loaded ahead (cycles) */
|
|
65
|
+
this.preloading = new Set();
|
|
66
|
+
// static expressions parse XML and build nodes with the XML parser
|
|
67
|
+
const parse = (text) => options.parse(text);
|
|
68
|
+
this.resources = {
|
|
69
|
+
xmlParser: parse,
|
|
70
|
+
createDocument: () => {
|
|
71
|
+
const document = parse("<x/>");
|
|
72
|
+
document.removeChild(document.documentElement);
|
|
73
|
+
return document;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @param {Element} element
|
|
80
|
+
* @returns {Array<Element|object>} the significant children
|
|
81
|
+
*/
|
|
82
|
+
children(element) {
|
|
83
|
+
let children = this.childCache.get(element);
|
|
84
|
+
if (!children) {
|
|
85
|
+
children = significantChildren(element, (child) => this.included(child));
|
|
86
|
+
this.childCache.set(element, children);
|
|
87
|
+
}
|
|
88
|
+
return children;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Whether use-when keeps an element; a kept element has its shadow
|
|
93
|
+
* attributes evaluated, and a static declaration is evaluated.
|
|
94
|
+
* @param {Element} element
|
|
95
|
+
* @returns {boolean}
|
|
96
|
+
*/
|
|
97
|
+
included(element) {
|
|
98
|
+
let included = this.includedCache.get(element);
|
|
99
|
+
if (included === undefined) {
|
|
100
|
+
// a shadow use-when (_use-when) is evaluated before the condition
|
|
101
|
+
const early = element.hasAttribute?.("_use-when");
|
|
102
|
+
if (early) this.applyShadows(element);
|
|
103
|
+
included = useWhen(element, this.statics, this.resources);
|
|
104
|
+
this.includedCache.set(element, included);
|
|
105
|
+
if (included) {
|
|
106
|
+
if (!early) this.applyShadows(element);
|
|
107
|
+
if (isStaticDeclaration(element)) this.declareStatic(element);
|
|
108
|
+
if (isModuleReference(element)) this.preload(element);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return included;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Evaluates the shadow attributes (`_name`) of an XSLT element.
|
|
116
|
+
* @param {Element} element
|
|
117
|
+
*/
|
|
118
|
+
applyShadows(element) {
|
|
119
|
+
if (element.namespaceURI !== XSL_NS) return;
|
|
120
|
+
const values = new Map();
|
|
121
|
+
for (const attribute of element.attributes) {
|
|
122
|
+
const name = attribute.name;
|
|
123
|
+
if (!name.startsWith("_") || attribute.namespaceURI) continue;
|
|
124
|
+
const value = evaluateStaticAvt(
|
|
125
|
+
attribute.value,
|
|
126
|
+
element,
|
|
127
|
+
this.statics,
|
|
128
|
+
this.resources,
|
|
129
|
+
);
|
|
130
|
+
values.set(name.slice(1), value);
|
|
131
|
+
}
|
|
132
|
+
if (values.size > 0) {
|
|
133
|
+
setShadowAttributes(element, values);
|
|
134
|
+
forgetInfo(element);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Evaluates a static variable or parameter.
|
|
140
|
+
* @param {Element} element
|
|
141
|
+
*/
|
|
142
|
+
declareStatic(element) {
|
|
143
|
+
const name = attr(element, "name");
|
|
144
|
+
if (name === undefined) {
|
|
145
|
+
throw xsltError("XTSE0010", "A static variable needs a name");
|
|
146
|
+
}
|
|
147
|
+
if (this.children(element).length > 0) {
|
|
148
|
+
throw xsltError(
|
|
149
|
+
attr(element, "select") === undefined ? "XTSE0010" : "XTSE0620",
|
|
150
|
+
"A static variable has no content",
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (
|
|
154
|
+
isXsl(element, "param") &&
|
|
155
|
+
["yes", "true", "1"].includes(attr(element, "required")?.trim()) &&
|
|
156
|
+
attr(element, "select") !== undefined
|
|
157
|
+
) {
|
|
158
|
+
throw xsltError("XTSE0010", "A required static parameter has no select");
|
|
159
|
+
}
|
|
160
|
+
const key = clarkOf(resolveQName(name, infoOf(element).namespaces));
|
|
161
|
+
const supplied = this.options.staticParams?.get?.(key);
|
|
162
|
+
const select = attr(element, "select");
|
|
163
|
+
let value;
|
|
164
|
+
if (isXsl(element, "param") && supplied !== undefined) {
|
|
165
|
+
value = toSequence(supplied);
|
|
166
|
+
} else if (select !== undefined) {
|
|
167
|
+
value = evaluateStatic(select, element, this.statics, this.resources);
|
|
168
|
+
} else {
|
|
169
|
+
// no select, no content: "" without "as", else the empty sequence
|
|
170
|
+
value = attr(element, "as") === undefined ? [stringItem("")] : [];
|
|
171
|
+
}
|
|
172
|
+
declareConsistently(this, key, {
|
|
173
|
+
element,
|
|
174
|
+
value,
|
|
175
|
+
path: [...this.importPath],
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Loads the module of an xsl:import or xsl:include as soon as it is
|
|
181
|
+
* met (see moduleLoading.js).
|
|
182
|
+
* @param {Element} element
|
|
183
|
+
*/
|
|
184
|
+
preload(element) {
|
|
185
|
+
preloadModule(this, element);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Loads an included or imported module (see moduleLoading.js).
|
|
190
|
+
* @param {string} uri - Absolute URI
|
|
191
|
+
* @param {string} [base] - Base URI it was resolved against
|
|
192
|
+
* @returns {Document|Element}
|
|
193
|
+
*/
|
|
194
|
+
loadModule(uri, base) {
|
|
195
|
+
return loadModuleDocument(this, uri, base);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static variables declared more than once (XSLT 3.0 section 9.7): a
|
|
3
|
+
* declaration that comes later in stylesheet tree order than one of
|
|
4
|
+
* lower import precedence must be consistent with it (the same value),
|
|
5
|
+
* else XTSE3450; one of lower precedence than an earlier declaration is
|
|
6
|
+
* left out. The precedence of declarations met in tree order is told by
|
|
7
|
+
* their import paths: a declaration inside an import of the module of
|
|
8
|
+
* another has the lower precedence.
|
|
9
|
+
*
|
|
10
|
+
* @module @tradik/xslt3/xslt/compiler/staticVariables
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { isAtomic } from "../../xdm/atomic.js";
|
|
14
|
+
import { canonicalString } from "../../xdm/lexical.js";
|
|
15
|
+
import { xsltError } from "../names.js";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A static declaration.
|
|
19
|
+
* @typedef {object} StaticDeclaration
|
|
20
|
+
* @property {Element} element
|
|
21
|
+
* @property {Array} value
|
|
22
|
+
* @property {number[]} path - The xsl:import elements it is inside
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {number[]} outer
|
|
27
|
+
* @param {number[]} inner
|
|
28
|
+
* @returns {boolean} whether `outer` is a prefix of `inner`
|
|
29
|
+
*/
|
|
30
|
+
const isPrefix = (outer, inner) =>
|
|
31
|
+
outer.length <= inner.length && outer.every((step, i) => inner[i] === step);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether two declarations are consistent: the same kind (variable or
|
|
35
|
+
* param), type and value.
|
|
36
|
+
* @param {StaticDeclaration} a
|
|
37
|
+
* @param {StaticDeclaration} b
|
|
38
|
+
* @returns {boolean}
|
|
39
|
+
*/
|
|
40
|
+
const consistent = (a, b) =>
|
|
41
|
+
a.element.localName === b.element.localName &&
|
|
42
|
+
a.element.getAttribute("as")?.trim() ===
|
|
43
|
+
b.element.getAttribute("as")?.trim() &&
|
|
44
|
+
sameValue(a.value, b.value);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {Array} a
|
|
48
|
+
* @param {Array} b
|
|
49
|
+
* @returns {boolean} whether two values are the same
|
|
50
|
+
*/
|
|
51
|
+
function sameValue(a, b) {
|
|
52
|
+
return (
|
|
53
|
+
a.length === b.length &&
|
|
54
|
+
a.every((item, i) => {
|
|
55
|
+
const other = b[i];
|
|
56
|
+
if (!isAtomic(item) || !isAtomic(other)) return item === other;
|
|
57
|
+
return (
|
|
58
|
+
item.type === other.type &&
|
|
59
|
+
canonicalString(item) === canonicalString(other)
|
|
60
|
+
);
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Records a static variable, checked against an earlier declaration of
|
|
67
|
+
* the name.
|
|
68
|
+
* @param {{statics: Map, staticDeclarations: Map}} stage - The static
|
|
69
|
+
* stage (values and declarations by Clark name)
|
|
70
|
+
* @param {string} key - Clark name
|
|
71
|
+
* @param {StaticDeclaration} declaration
|
|
72
|
+
* @throws {import("../../errors.js").XPathError} XTSE3450
|
|
73
|
+
*/
|
|
74
|
+
export function declareConsistently(stage, key, declaration) {
|
|
75
|
+
const earlier = stage.staticDeclarations.get(key);
|
|
76
|
+
if (earlier && earlier.element === declaration.element) return;
|
|
77
|
+
if (earlier && earlier.path.length !== declaration.path.length) {
|
|
78
|
+
// the earlier one is outside the import holding this one: it wins
|
|
79
|
+
if (isPrefix(earlier.path, declaration.path)) return;
|
|
80
|
+
}
|
|
81
|
+
if (
|
|
82
|
+
earlier &&
|
|
83
|
+
!isPrefix(earlier.path, declaration.path) &&
|
|
84
|
+
!consistent(earlier, declaration)
|
|
85
|
+
) {
|
|
86
|
+
throw xsltError(
|
|
87
|
+
"XTSE3450",
|
|
88
|
+
`The static variable ${key} is declared with another value`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
stage.staticDeclarations.set(key, declaration);
|
|
92
|
+
stage.statics.set(key, declaration.value);
|
|
93
|
+
}
|