@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,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stylesheet compiler: loads the modules, collects the declarations
|
|
3
|
+
* by kind and compiles them in dependency order (namespace aliases,
|
|
4
|
+
* decimal formats and function signatures before any expression; global
|
|
5
|
+
* names before any body), then runs the checks that need everything
|
|
6
|
+
* (called templates, attribute sets).
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/xslt/compiler/stylesheet
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { defaultFunctionLibrary } from "../../xpath/index.js";
|
|
12
|
+
import { xsltFunctions } from "../runtime/functions.js";
|
|
13
|
+
import { declareAttributeSet } from "../instructions/attributeSets.js";
|
|
14
|
+
import { declareAccumulators } from "./accumulatorDecl.js";
|
|
15
|
+
import { declareGlobalContextItem } from "./globalContextItem.js";
|
|
16
|
+
import { infoOf } from "./elementInfo.js";
|
|
17
|
+
import { ExpressionCompiler } from "./expressions.js";
|
|
18
|
+
import {
|
|
19
|
+
collectGlobals,
|
|
20
|
+
compileFunction,
|
|
21
|
+
functionSignature,
|
|
22
|
+
winners,
|
|
23
|
+
} from "./globals.js";
|
|
24
|
+
import { collectDeclarations } from "./declarationKinds.js";
|
|
25
|
+
import { loadModuleTree } from "./modules.js";
|
|
26
|
+
import { collectDecimalFormats } from "./decimalFormats.js";
|
|
27
|
+
import {
|
|
28
|
+
checkCharacterMaps,
|
|
29
|
+
collectCharacterMaps,
|
|
30
|
+
collectOutputs,
|
|
31
|
+
} from "./outputDecl.js";
|
|
32
|
+
import { collectAliases, compileSpaceRules, declareKey } from "./miscDecl.js";
|
|
33
|
+
import { checkModeDeclarations, declareMode } from "./modeDecl.js";
|
|
34
|
+
import {
|
|
35
|
+
compileSlots,
|
|
36
|
+
importAccepted,
|
|
37
|
+
layoutGlobals,
|
|
38
|
+
markAbstract,
|
|
39
|
+
} from "./linker.js";
|
|
40
|
+
import { linkOverrides } from "./overrideLinks.js";
|
|
41
|
+
import { buildTable, packageHeader } from "./packageTable.js";
|
|
42
|
+
import { usePackage } from "./packages.js";
|
|
43
|
+
import { checkDeclaredModes, checkExecutable } from "./packageChecks.js";
|
|
44
|
+
import { PackageRegistry } from "./packageRegistry.js";
|
|
45
|
+
import { declareSimplified, declareTemplate } from "./templatesDecl.js";
|
|
46
|
+
|
|
47
|
+
/** Compiles a stylesheet; it is also the `cx` handed to every compiler. */
|
|
48
|
+
export class StylesheetCompiler extends PackageRegistry {
|
|
49
|
+
/**
|
|
50
|
+
* @param {Element} element
|
|
51
|
+
* @returns {number} the effective version of an element
|
|
52
|
+
*/
|
|
53
|
+
versionOf(element) {
|
|
54
|
+
return infoOf(element).version;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {Element} element
|
|
59
|
+
* @returns {string|undefined} its base URI
|
|
60
|
+
*/
|
|
61
|
+
baseUriOf(element) {
|
|
62
|
+
return infoOf(element).baseUri;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The declarations of a module tree by kind, checked.
|
|
67
|
+
* @param {object} tree - See modules.js
|
|
68
|
+
* @returns {(kind: string) => object[]} the declarations of a kind
|
|
69
|
+
*/
|
|
70
|
+
collectDeclarations(tree) {
|
|
71
|
+
return collectDeclarations(tree, this);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Compiles the declarations that every expression depends on: function
|
|
76
|
+
* signatures, decimal formats, global variable names.
|
|
77
|
+
* @param {(kind: string) => object[]} all
|
|
78
|
+
* @returns {{signatures: Map, globals: Map, definitions: Map}}
|
|
79
|
+
*/
|
|
80
|
+
compileContext(all) {
|
|
81
|
+
this.aliases = collectAliases(all("namespace-alias"));
|
|
82
|
+
const signatures = winners(
|
|
83
|
+
all("function").map((d) => ({
|
|
84
|
+
...d,
|
|
85
|
+
signature: functionSignature(d, this),
|
|
86
|
+
})),
|
|
87
|
+
(d) => d.signature.key,
|
|
88
|
+
"XTSE0770",
|
|
89
|
+
);
|
|
90
|
+
const definitions = new Map(
|
|
91
|
+
[...signatures.values()].map((d) => [
|
|
92
|
+
d.signature.key,
|
|
93
|
+
this.functionDefinition(d.signature),
|
|
94
|
+
]),
|
|
95
|
+
);
|
|
96
|
+
const accepted = this.uses.flatMap((use) =>
|
|
97
|
+
use.accepted
|
|
98
|
+
.filter(({ component }) => component.kind === "function")
|
|
99
|
+
.map(({ component }) => component.definition),
|
|
100
|
+
);
|
|
101
|
+
this.exprs = new ExpressionCompiler({
|
|
102
|
+
library: defaultFunctionLibrary.extend(xsltFunctions, accepted, [
|
|
103
|
+
...definitions.values(),
|
|
104
|
+
]),
|
|
105
|
+
decimalFormats: collectDecimalFormats(all("decimal-format"), this),
|
|
106
|
+
owner: this,
|
|
107
|
+
});
|
|
108
|
+
const globals = collectGlobals([...all("variable"), ...all("param")], this);
|
|
109
|
+
return { signatures, globals, definitions };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A compiler for a package used by this one.
|
|
114
|
+
* @param {string[]} chain - Names of the packages being compiled
|
|
115
|
+
* @returns {StylesheetCompiler}
|
|
116
|
+
*/
|
|
117
|
+
usedPackage(chain) {
|
|
118
|
+
return new StylesheetCompiler({
|
|
119
|
+
...this.options,
|
|
120
|
+
staticParams: new Map(),
|
|
121
|
+
packageChain: chain,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The first stage: modules loaded, used packages prepared, names and
|
|
127
|
+
* visibilities of the components known.
|
|
128
|
+
* @param {Document|Element} source
|
|
129
|
+
* @param {string|undefined} uri
|
|
130
|
+
*/
|
|
131
|
+
prepare(source, uri) {
|
|
132
|
+
const tree = loadModuleTree(source, uri, this);
|
|
133
|
+
this.tree = tree;
|
|
134
|
+
this.header = packageHeader(tree.root);
|
|
135
|
+
this.packageName = this.header.name;
|
|
136
|
+
this.packageVersion = this.header.version;
|
|
137
|
+
const all = this.collectDeclarations(tree);
|
|
138
|
+
this.all = all;
|
|
139
|
+
this.exprs = new ExpressionCompiler({ library: defaultFunctionLibrary });
|
|
140
|
+
this.uses = all("use-package").map((d) =>
|
|
141
|
+
usePackage({ ...d, imported: d.precedence !== tree.precedence }, this),
|
|
142
|
+
);
|
|
143
|
+
this.level = Math.max(-1, ...this.uses.map((use) => use.child.level)) + 1;
|
|
144
|
+
this.context = this.compileContext(all);
|
|
145
|
+
buildTable(this, all, this.context);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** The second stage: every declaration compiled and linked. */
|
|
149
|
+
finish() {
|
|
150
|
+
for (const use of this.uses) use.child.finish();
|
|
151
|
+
const { all, tree } = this;
|
|
152
|
+
const { signatures } = this.context;
|
|
153
|
+
importAccepted(this);
|
|
154
|
+
this.outputs = collectOutputs(all("output"), this);
|
|
155
|
+
this.characterMaps = collectCharacterMaps(all("character-map"), this);
|
|
156
|
+
checkCharacterMaps(this.outputs, this.characterMaps);
|
|
157
|
+
this.spaceRules = compileSpaceRules(
|
|
158
|
+
[...all("strip-space"), ...all("preserve-space")],
|
|
159
|
+
this,
|
|
160
|
+
);
|
|
161
|
+
for (const declaration of all("mode")) declareMode(declaration, this);
|
|
162
|
+
checkModeDeclarations(this.modes.values());
|
|
163
|
+
this.globals = compileSlots(this);
|
|
164
|
+
declareAccumulators(all, this);
|
|
165
|
+
declareGlobalContextItem(all("global-context-item"), this);
|
|
166
|
+
for (const { element } of all("attribute-set")) {
|
|
167
|
+
declareAttributeSet(element, this);
|
|
168
|
+
}
|
|
169
|
+
for (const declaration of all("key")) declareKey(declaration, this);
|
|
170
|
+
for (const declaration of all("template")) {
|
|
171
|
+
declareTemplate(declaration, this);
|
|
172
|
+
}
|
|
173
|
+
for (const declaration of all("simplified")) {
|
|
174
|
+
declareSimplified(declaration, this);
|
|
175
|
+
}
|
|
176
|
+
for (const { signature } of signatures.values()) {
|
|
177
|
+
Object.assign(
|
|
178
|
+
this.functionBodies.get(signature.key),
|
|
179
|
+
compileFunction(signature, this),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
markAbstract(this);
|
|
183
|
+
linkOverrides(this, this.level);
|
|
184
|
+
for (const check of this.deferred) check();
|
|
185
|
+
checkDeclaredModes(this);
|
|
186
|
+
this.finishModes();
|
|
187
|
+
this.sc = this.exprs.staticContext(tree.root);
|
|
188
|
+
this.defaultModeName = infoOf(tree.root).defaultMode;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Compiles the stylesheet (the top-level package and the packages it
|
|
193
|
+
* uses).
|
|
194
|
+
* @param {Document|Element} source
|
|
195
|
+
* @param {string|undefined} uri
|
|
196
|
+
* @returns {StylesheetCompiler} this, with everything compiled
|
|
197
|
+
*/
|
|
198
|
+
compile(source, uri) {
|
|
199
|
+
this.prepare(source, uri);
|
|
200
|
+
checkExecutable(this);
|
|
201
|
+
layoutGlobals(this);
|
|
202
|
+
this.finish();
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tail positions (XSLT 3.0 section 7.2): xsl:break and
|
|
3
|
+
* xsl:next-iteration must be the last instruction of the body of the
|
|
4
|
+
* innermost xsl:iterate, or of an xsl:if, xsl:when, xsl:otherwise,
|
|
5
|
+
* xsl:try or xsl:catch that is itself in a tail position (XTSE3120).
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/xslt/compiler/tailPosition
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { isXsl, xsltError } from "../names.js";
|
|
11
|
+
|
|
12
|
+
/** Containers through which a tail position extends, to the element in tail position. */
|
|
13
|
+
const CONTAINERS = {
|
|
14
|
+
if: (parent) => parent,
|
|
15
|
+
when: (parent) => parent.parentNode,
|
|
16
|
+
otherwise: (parent) => parent.parentNode,
|
|
17
|
+
try: (parent) => parent,
|
|
18
|
+
catch: (parent) => parent.parentNode,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Whether a child is the last instruction of its parent, ignoring
|
|
23
|
+
* xsl:fallback (and the xsl:catch children of xsl:try).
|
|
24
|
+
* @param {object} child
|
|
25
|
+
* @param {Element} parent
|
|
26
|
+
* @param {object} cx - Stylesheet compiler (`children`)
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
*/
|
|
29
|
+
function isLast(child, parent, cx) {
|
|
30
|
+
const children = cx.children(parent);
|
|
31
|
+
const index = children.indexOf(child);
|
|
32
|
+
return children
|
|
33
|
+
.slice(index + 1)
|
|
34
|
+
.every(
|
|
35
|
+
(next) =>
|
|
36
|
+
isXsl(next, "fallback") ||
|
|
37
|
+
(isXsl(parent, "try") && isXsl(next, "catch")),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Checks that an xsl:break or xsl:next-iteration is in a tail position
|
|
43
|
+
* of an xsl:iterate body.
|
|
44
|
+
* @param {Element} element
|
|
45
|
+
* @param {object} cx
|
|
46
|
+
* @throws {import("../../errors.js").XPathError} XTSE0010 outside
|
|
47
|
+
* xsl:iterate, XTSE3120 elsewhere than in a tail position
|
|
48
|
+
*/
|
|
49
|
+
export function checkTailPosition(element, cx) {
|
|
50
|
+
let ancestor = element.parentNode;
|
|
51
|
+
while (ancestor?.nodeType === 1 && !isXsl(ancestor, "iterate")) {
|
|
52
|
+
ancestor = ancestor.parentNode;
|
|
53
|
+
}
|
|
54
|
+
if (ancestor?.nodeType !== 1) {
|
|
55
|
+
throw xsltError(
|
|
56
|
+
"XTSE0010",
|
|
57
|
+
`xsl:${element.localName} is only allowed within xsl:iterate`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
let node = element;
|
|
61
|
+
for (;;) {
|
|
62
|
+
const parent = node.parentNode;
|
|
63
|
+
const container = parent?.nodeType === 1 && isXsl(parent) && parent;
|
|
64
|
+
if (!container || !isLast(node, parent, cx)) break;
|
|
65
|
+
if (isXsl(parent, "iterate")) return;
|
|
66
|
+
const up = CONTAINERS[parent.localName];
|
|
67
|
+
if (!up) break;
|
|
68
|
+
node = up(parent);
|
|
69
|
+
}
|
|
70
|
+
throw xsltError(
|
|
71
|
+
"XTSE3120",
|
|
72
|
+
`xsl:${element.localName} must be in a tail position of xsl:iterate`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xsl:template declarations (XSLT 3.0 section 6.1): named templates and
|
|
3
|
+
* template rules, registered in their modes.
|
|
4
|
+
*
|
|
5
|
+
* @module @tradik/xslt3/xslt/compiler/templatesDecl
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { compileParams } from "../instructions/params.js";
|
|
9
|
+
import { typeConverter } from "../instructions/variables.js";
|
|
10
|
+
import {
|
|
11
|
+
attr,
|
|
12
|
+
declaredName,
|
|
13
|
+
isXsl,
|
|
14
|
+
tokens,
|
|
15
|
+
XSL_NS,
|
|
16
|
+
xsltError,
|
|
17
|
+
} from "../names.js";
|
|
18
|
+
import { compilePattern } from "../patterns/compile.js";
|
|
19
|
+
import { splitContextItem } from "./contextItem.js";
|
|
20
|
+
import { compileBody } from "./body.js";
|
|
21
|
+
import { splitLeading } from "./children.js";
|
|
22
|
+
import { infoOf } from "./elementInfo.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Separates the leading xsl:param children of a template or function.
|
|
26
|
+
* @param {Array<object>} children
|
|
27
|
+
* @returns {{params: Element[], rest: Array<object>}}
|
|
28
|
+
*/
|
|
29
|
+
export function splitParams(children) {
|
|
30
|
+
const { leading, rest } = splitLeading(children, "param");
|
|
31
|
+
if (rest.some((child) => isXsl(child, "param"))) {
|
|
32
|
+
throw xsltError("XTSE0010", "xsl:param must come first");
|
|
33
|
+
}
|
|
34
|
+
return { params: leading, rest };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The priority attribute of a template.
|
|
39
|
+
* @param {string|undefined} text
|
|
40
|
+
* @returns {number|null}
|
|
41
|
+
*/
|
|
42
|
+
function parsePriority(text) {
|
|
43
|
+
if (text === undefined) return null;
|
|
44
|
+
const value = text.trim();
|
|
45
|
+
if (!/^[+-]?(\d+(\.\d*)?|\.\d+)$/.test(value)) {
|
|
46
|
+
throw xsltError("XTSE0530", `Invalid priority "${text}"`);
|
|
47
|
+
}
|
|
48
|
+
return Number(value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The modes of a template rule.
|
|
53
|
+
* @param {Element} element
|
|
54
|
+
* @param {object} cx
|
|
55
|
+
* @returns {string[]} Clark names, "#all" for all modes
|
|
56
|
+
*/
|
|
57
|
+
export function modesOf(element, cx) {
|
|
58
|
+
const text = attr(element, "mode");
|
|
59
|
+
if (text === undefined) return [infoOf(element).defaultMode];
|
|
60
|
+
const names = tokens(text).map((token) => {
|
|
61
|
+
if (token === "#all") return "#all";
|
|
62
|
+
if (token === "#default") return infoOf(element).defaultMode;
|
|
63
|
+
if (token === "#unnamed") return "";
|
|
64
|
+
const name = cx.exprs.qname(token, element, { syntaxCode: "XTSE0550" });
|
|
65
|
+
return `{${name.uri}}${name.local}`;
|
|
66
|
+
});
|
|
67
|
+
if (names.length === 0 || new Set(names).size !== names.length) {
|
|
68
|
+
throw xsltError("XTSE0550", "Invalid mode attribute");
|
|
69
|
+
}
|
|
70
|
+
if (names.includes("#all") && names.length > 1) {
|
|
71
|
+
throw xsltError("XTSE0550", "#all must be alone");
|
|
72
|
+
}
|
|
73
|
+
return names;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The alternatives of a union pattern as one.
|
|
78
|
+
* @param {object[]} alternatives
|
|
79
|
+
* @returns {object} an alternative matching when any of them does
|
|
80
|
+
*/
|
|
81
|
+
function unionAlternative(alternatives) {
|
|
82
|
+
const keys = new Set(alternatives.map((alternative) => alternative.key));
|
|
83
|
+
return {
|
|
84
|
+
matches: (item, xc) => alternatives.some((a) => a.matches(item, xc)),
|
|
85
|
+
priority: 0.5,
|
|
86
|
+
key: keys.size === 1 ? alternatives[0].key : "*",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Compiles an xsl:template and registers it.
|
|
92
|
+
* @param {object} declaration - `{element, precedence, importLow}`
|
|
93
|
+
* @param {object} cx - Stylesheet compiler
|
|
94
|
+
*/
|
|
95
|
+
export function declareTemplate(declaration, cx) {
|
|
96
|
+
const { element, precedence, importLow } = declaration;
|
|
97
|
+
const match = attr(element, "match");
|
|
98
|
+
const nameText = attr(element, "name");
|
|
99
|
+
if (match === undefined) {
|
|
100
|
+
if (nameText === undefined) {
|
|
101
|
+
throw xsltError("XTSE0500", "xsl:template needs match or name");
|
|
102
|
+
}
|
|
103
|
+
if (
|
|
104
|
+
attr(element, "mode") !== undefined ||
|
|
105
|
+
attr(element, "priority") !== undefined
|
|
106
|
+
) {
|
|
107
|
+
throw xsltError("XTSE0500", "mode and priority need a match pattern");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const contextItem = splitContextItem(cx.children(element), element, cx);
|
|
111
|
+
const { params: paramElements, rest } = splitParams(contextItem.rest);
|
|
112
|
+
const { params, scope } = compileParams(paramElements, cx, cx.globalScope());
|
|
113
|
+
const asText = attr(element, "as");
|
|
114
|
+
const template = {
|
|
115
|
+
params,
|
|
116
|
+
body: [...contextItem.steps, ...compileBody(element, cx, scope, rest)],
|
|
117
|
+
convert: asText
|
|
118
|
+
? typeConverter(
|
|
119
|
+
cx.exprs.sequenceType(asText, element),
|
|
120
|
+
"XTTE0505",
|
|
121
|
+
"result of the template",
|
|
122
|
+
)
|
|
123
|
+
: null,
|
|
124
|
+
precedence,
|
|
125
|
+
importLow,
|
|
126
|
+
element,
|
|
127
|
+
};
|
|
128
|
+
if (nameText !== undefined) {
|
|
129
|
+
const name = declaredName(
|
|
130
|
+
cx.exprs.qname(nameText, element),
|
|
131
|
+
`{${XSL_NS}}initial-template`,
|
|
132
|
+
);
|
|
133
|
+
cx.addNamedTemplate(`{${name.uri}}${name.local}`, template);
|
|
134
|
+
}
|
|
135
|
+
if (match === undefined) return;
|
|
136
|
+
const pattern = compilePattern(match, element, cx);
|
|
137
|
+
const explicit = parsePriority(attr(element, "priority"));
|
|
138
|
+
// with a priority, a union pattern is one rule, not one per alternative
|
|
139
|
+
const alternatives =
|
|
140
|
+
explicit === null || pattern.alternatives.length === 1
|
|
141
|
+
? pattern.alternatives
|
|
142
|
+
: [unionAlternative(pattern.alternatives)];
|
|
143
|
+
for (const mode of modesOf(element, cx)) {
|
|
144
|
+
for (const alternative of alternatives) {
|
|
145
|
+
cx.addRule(mode, {
|
|
146
|
+
template,
|
|
147
|
+
alternative,
|
|
148
|
+
priority: explicit ?? alternative.priority,
|
|
149
|
+
precedence,
|
|
150
|
+
position: cx.nextPosition(),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Builds the template of a simplified stylesheet: a rule for "/" whose
|
|
158
|
+
* body is the literal result element.
|
|
159
|
+
* @param {object} declaration
|
|
160
|
+
* @param {object} cx
|
|
161
|
+
*/
|
|
162
|
+
export function declareSimplified(declaration, cx) {
|
|
163
|
+
const { element, precedence, importLow } = declaration;
|
|
164
|
+
const template = {
|
|
165
|
+
params: [],
|
|
166
|
+
body: compileBody(element.parentNode, cx, cx.globalScope(), [element]),
|
|
167
|
+
convert: null,
|
|
168
|
+
precedence,
|
|
169
|
+
importLow,
|
|
170
|
+
element,
|
|
171
|
+
};
|
|
172
|
+
const pattern = compilePattern("/", element, cx);
|
|
173
|
+
cx.addRule("", {
|
|
174
|
+
template,
|
|
175
|
+
alternative: pattern.alternatives[0],
|
|
176
|
+
priority: -0.5,
|
|
177
|
+
precedence,
|
|
178
|
+
position: cx.nextPosition(),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The use-accumulators attributes (XSLT 3.0 section 18.2.2) of xsl:mode,
|
|
3
|
+
* xsl:global-context-item, xsl:source-document and xsl:merge-source: the
|
|
4
|
+
* accumulators that apply to a tree.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/xslt/compiler/useAccumulators
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { compareCodepoints } from "../../xdm/strings.js";
|
|
10
|
+
import { attr, clarkOf, tokens, xsltError } from "../names.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The use-accumulators attributes of the xsl:mode declarations: the one
|
|
14
|
+
* of the highest import precedence wins.
|
|
15
|
+
* @param {object[]} declarations
|
|
16
|
+
* @param {object} cx
|
|
17
|
+
* @throws {import("../../errors.js").XPathError} XTSE0545 for different
|
|
18
|
+
* values at the same precedence
|
|
19
|
+
*/
|
|
20
|
+
export function declareModeAccumulators(declarations, cx) {
|
|
21
|
+
const chosen = new Map();
|
|
22
|
+
for (const { element, precedence } of declarations) {
|
|
23
|
+
const text = attr(element, "use-accumulators");
|
|
24
|
+
if (text === undefined) continue;
|
|
25
|
+
const nameText = attr(element, "name");
|
|
26
|
+
const name =
|
|
27
|
+
nameText === undefined || nameText.trim() === "#unnamed"
|
|
28
|
+
? ""
|
|
29
|
+
: clarkOf(cx.exprs.qname(nameText, element));
|
|
30
|
+
const accumulators = useAccumulators(text, element, cx);
|
|
31
|
+
const key =
|
|
32
|
+
accumulators === "all"
|
|
33
|
+
? "#all"
|
|
34
|
+
: [...accumulators].sort(compareCodepoints).join();
|
|
35
|
+
const current = chosen.get(name);
|
|
36
|
+
if (current?.precedence === precedence && current.key !== key) {
|
|
37
|
+
current.conflict = true;
|
|
38
|
+
} else if (!current || current.precedence < precedence) {
|
|
39
|
+
chosen.set(name, { precedence, key, accumulators, conflict: false });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
for (const [name, { accumulators, conflict }] of chosen) {
|
|
43
|
+
if (conflict) {
|
|
44
|
+
throw xsltError("XTSE0545", "Conflicting use-accumulators for a mode");
|
|
45
|
+
}
|
|
46
|
+
cx.mode(name).accumulators = accumulators;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Parses a use-accumulators attribute.
|
|
52
|
+
* @param {string} text
|
|
53
|
+
* @param {Element} element
|
|
54
|
+
* @param {object} cx
|
|
55
|
+
* @returns {Set<string>|"all"} Clark names of the accumulators, or all
|
|
56
|
+
* @throws {import("../../errors.js").XPathError} XTSE3300
|
|
57
|
+
*/
|
|
58
|
+
export function useAccumulators(text, element, cx) {
|
|
59
|
+
const names = tokens(text);
|
|
60
|
+
if (names.includes("#all")) {
|
|
61
|
+
if (names.length > 1) {
|
|
62
|
+
throw xsltError("XTSE3300", "#all must be alone in use-accumulators");
|
|
63
|
+
}
|
|
64
|
+
return "all";
|
|
65
|
+
}
|
|
66
|
+
const keys = new Set();
|
|
67
|
+
for (const token of names) {
|
|
68
|
+
const name = cx.exprs.qname(token, element, { code: "XTSE3300" });
|
|
69
|
+
const key = clarkOf(name);
|
|
70
|
+
if (keys.has(key) || !cx.accumulators.has(key)) {
|
|
71
|
+
throw xsltError("XTSE3300", `Invalid accumulator ${token}`);
|
|
72
|
+
}
|
|
73
|
+
keys.add(key);
|
|
74
|
+
}
|
|
75
|
+
return keys;
|
|
76
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static expressions (XSLT 3.0 section 9.7): use-when conditions, the
|
|
3
|
+
* values of static variables and parameters, and shadow attributes,
|
|
4
|
+
* evaluated at compile time in a restricted static context: the
|
|
5
|
+
* namespaces in scope, the static variables declared before, the
|
|
6
|
+
* standard functions and system-property(), function-available(),
|
|
7
|
+
* element-available() and type-available(); no context item.
|
|
8
|
+
*
|
|
9
|
+
* @module @tradik/xslt3/xslt/compiler/useWhen
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { defaultFunctionLibrary } from "../../xpath/index.js";
|
|
13
|
+
import { compileNode } from "../../xpath/eval/compiler.js";
|
|
14
|
+
import { createDynamicContext } from "../../xpath/eval/dynamicContext.js";
|
|
15
|
+
import { createStaticContext } from "../../xpath/eval/staticContext.js";
|
|
16
|
+
import { parseXPath } from "../../xpath/syntax/index.js";
|
|
17
|
+
import { effectiveBooleanValue } from "../../xdm/nodes.js";
|
|
18
|
+
import { standardAttr } from "../names.js";
|
|
19
|
+
import { availabilityFunctions } from "../runtime/availability.js";
|
|
20
|
+
import { simpleContent } from "../runtime/values.js";
|
|
21
|
+
import { parseAvt } from "./avt.js";
|
|
22
|
+
import { infoOf } from "./elementInfo.js";
|
|
23
|
+
|
|
24
|
+
const library = defaultFunctionLibrary.extend(availabilityFunctions);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Evaluates a static expression written on a stylesheet element.
|
|
28
|
+
* @param {string} text
|
|
29
|
+
* @param {Element} element
|
|
30
|
+
* @param {Map<string, Array>} statics - Static variables by Clark name
|
|
31
|
+
* @param {object} [resources] - Dynamic options: `xmlParser` and
|
|
32
|
+
* `createDocument`, for parse-xml(), json-to-xml() and the like
|
|
33
|
+
* @returns {Array} the value
|
|
34
|
+
*/
|
|
35
|
+
export function evaluateStatic(text, element, statics, resources = {}) {
|
|
36
|
+
const info = infoOf(element);
|
|
37
|
+
const sc = createStaticContext(
|
|
38
|
+
{
|
|
39
|
+
namespaces: new Map(
|
|
40
|
+
[...info.namespaces].filter(([prefix]) => prefix !== ""),
|
|
41
|
+
),
|
|
42
|
+
defaultElementNamespace: info.xpathDefaultNs,
|
|
43
|
+
baseUri: info.baseUri,
|
|
44
|
+
},
|
|
45
|
+
library,
|
|
46
|
+
);
|
|
47
|
+
sc.defaultNamespace = info.namespaces.get("") ?? "";
|
|
48
|
+
let vars = null;
|
|
49
|
+
let env = null;
|
|
50
|
+
for (const [key, value] of statics) {
|
|
51
|
+
vars = { key, next: vars };
|
|
52
|
+
env = { value, next: env };
|
|
53
|
+
}
|
|
54
|
+
const run = compileNode(parseXPath(text), { sc, vars });
|
|
55
|
+
const dyn = createDynamicContext(sc, resources, undefined);
|
|
56
|
+
dyn.sc = sc;
|
|
57
|
+
return run({ item: undefined, position: 0, size: 0, env, dyn });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Evaluates a static attribute value template (shadow attributes).
|
|
62
|
+
* @param {string} text
|
|
63
|
+
* @param {Element} element
|
|
64
|
+
* @param {Map<string, Array>} statics
|
|
65
|
+
* @param {object} [resources] - See {@link evaluateStatic}
|
|
66
|
+
* @returns {string}
|
|
67
|
+
*/
|
|
68
|
+
export function evaluateStaticAvt(text, element, statics, resources) {
|
|
69
|
+
return parseAvt(text)
|
|
70
|
+
.map((part) =>
|
|
71
|
+
typeof part === "string"
|
|
72
|
+
? part
|
|
73
|
+
: simpleContent(
|
|
74
|
+
evaluateStatic(part.expr, element, statics, resources),
|
|
75
|
+
" ",
|
|
76
|
+
),
|
|
77
|
+
)
|
|
78
|
+
.join("");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Evaluates the use-when condition of an element.
|
|
83
|
+
* @param {Element} element
|
|
84
|
+
* @param {Map<string, Array>} [statics] - Static variables in scope
|
|
85
|
+
* @param {object} [resources] - See {@link evaluateStatic}
|
|
86
|
+
* @returns {boolean} true when the element is included
|
|
87
|
+
*/
|
|
88
|
+
export function useWhen(element, statics = new Map(), resources = {}) {
|
|
89
|
+
const condition = standardAttr(element, "use-when");
|
|
90
|
+
if (condition === undefined) return true;
|
|
91
|
+
return effectiveBooleanValue(
|
|
92
|
+
evaluateStatic(condition, element, statics, resources),
|
|
93
|
+
);
|
|
94
|
+
}
|