@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,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The receiver that collects the result of a sequence constructor as a
|
|
3
|
+
* sequence (variables and parameters with `as`, function bodies,
|
|
4
|
+
* xsl:sequence content...): constructed nodes are parentless, existing
|
|
5
|
+
* nodes are kept as they are.
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/xslt/runtime/sequenceReceiver
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { NamespaceNode } from "../../xpath/eval/namespaceNodes.js";
|
|
11
|
+
import { copyNode } from "./copy.js";
|
|
12
|
+
import { prefixOf, TreeReceiver } from "./treeReceiver.js";
|
|
13
|
+
|
|
14
|
+
/** Collects items. */
|
|
15
|
+
export class SequenceReceiver {
|
|
16
|
+
/**
|
|
17
|
+
* @param {() => Document} scratch - Gives the document that owns new
|
|
18
|
+
* nodes
|
|
19
|
+
*/
|
|
20
|
+
constructor(scratch) {
|
|
21
|
+
this.scratch = scratch;
|
|
22
|
+
/** @type {Array} the items received */
|
|
23
|
+
this.items = [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} uri
|
|
28
|
+
* @param {string} qname
|
|
29
|
+
* @returns {TreeReceiver} the receiver of the new element's content
|
|
30
|
+
*/
|
|
31
|
+
element(uri, qname) {
|
|
32
|
+
const element = this.scratch().createElementNS(uri || null, qname);
|
|
33
|
+
this.items.push(element);
|
|
34
|
+
const content = new TreeReceiver(element, new Map());
|
|
35
|
+
content.declare(prefixOf(qname), uri);
|
|
36
|
+
content.onReplace = (old, renamed) => {
|
|
37
|
+
this.items[this.items.indexOf(old)] = renamed;
|
|
38
|
+
};
|
|
39
|
+
return content;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {string} uri
|
|
44
|
+
* @param {string} qname
|
|
45
|
+
* @param {string} value
|
|
46
|
+
*/
|
|
47
|
+
attribute(uri, qname, value) {
|
|
48
|
+
let name = qname;
|
|
49
|
+
if (uri && !prefixOf(qname)) name = `ns0:${qname}`;
|
|
50
|
+
const attribute = this.scratch().createAttributeNS(uri || null, name);
|
|
51
|
+
attribute.value = value;
|
|
52
|
+
attribute.nodeValue = value;
|
|
53
|
+
this.items.push(attribute);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @param {string} prefix
|
|
58
|
+
* @param {string} uri
|
|
59
|
+
*/
|
|
60
|
+
namespace(prefix, uri) {
|
|
61
|
+
this.items.push(new NamespaceNode(null, prefix, uri));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** @param {string} text */
|
|
65
|
+
text(text) {
|
|
66
|
+
this.items.push(this.scratch().createTextNode(text));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** @param {string} text */
|
|
70
|
+
comment(text) {
|
|
71
|
+
this.items.push(this.scratch().createComment(text));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {string} target
|
|
76
|
+
* @param {string} data
|
|
77
|
+
*/
|
|
78
|
+
pi(target, data) {
|
|
79
|
+
this.items.push(this.scratch().createProcessingInstruction(target, data));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** @param {*} item - Any item, kept as it is */
|
|
83
|
+
item(item) {
|
|
84
|
+
this.items.push(item);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Adds a copy of a node.
|
|
89
|
+
* @param {Node} node
|
|
90
|
+
* @param {boolean} copyNamespaces
|
|
91
|
+
*/
|
|
92
|
+
copy(node, copyNamespaces) {
|
|
93
|
+
copyNode(node, this, copyNamespaces);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** @returns {TreeReceiver} the receiver of a new document node */
|
|
97
|
+
document() {
|
|
98
|
+
const fragment = this.scratch().createDocumentFragment();
|
|
99
|
+
this.items.push(fragment);
|
|
100
|
+
return new TreeReceiver(fragment, new Map());
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fn:snapshot of one node (XSLT 3.0 section 20.7): a deep copy of the
|
|
3
|
+
* node inside copies of its ancestors. Each ancestor is copied with its
|
|
4
|
+
* attributes and namespaces but without its other children, so the copy
|
|
5
|
+
* keeps the node's root, parent, attributes and namespaces.
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/xslt/runtime/snapshot
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { namedAttributeOf, parentOf } from "../../xpath/eval/domNodes.js";
|
|
11
|
+
import { namespaceNodesOf } from "../../xpath/eval/namespaceNodes.js";
|
|
12
|
+
import { copyNode, startElementCopy } from "./copy.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Copies the ancestors of a node, outermost first.
|
|
16
|
+
* @param {Node[]} ancestors - Root first
|
|
17
|
+
* @param {object} receiver - Sequence receiver that gets the root copy
|
|
18
|
+
* @param {(copy: Node, original: Node) => void} record - Told of each copy
|
|
19
|
+
* @returns {object} the tree receiver of the innermost copy's content
|
|
20
|
+
*/
|
|
21
|
+
function copyAncestors(ancestors, receiver, record) {
|
|
22
|
+
const [root, ...rest] = ancestors;
|
|
23
|
+
let content =
|
|
24
|
+
root.nodeType === 1
|
|
25
|
+
? startElementCopy(root, receiver, true)
|
|
26
|
+
: receiver.document();
|
|
27
|
+
record(content.parent, root);
|
|
28
|
+
for (const element of rest) {
|
|
29
|
+
content = startElementCopy(element, content, true);
|
|
30
|
+
record(content.parent, element);
|
|
31
|
+
}
|
|
32
|
+
return content;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The snapshot of a node.
|
|
37
|
+
* @param {Node} node
|
|
38
|
+
* @param {object} receiver - Sequence receiver (items get the root copy)
|
|
39
|
+
* @param {(copy: Node, original: Node) => void} record - Told of the
|
|
40
|
+
* copy of each ancestor (accumulator values are those of the originals)
|
|
41
|
+
* @returns {Node} the copy of the node inside the copied tree
|
|
42
|
+
*/
|
|
43
|
+
export function snapshotNode(node, receiver, record) {
|
|
44
|
+
const ancestors = [];
|
|
45
|
+
for (let p = parentOf(node); p; p = parentOf(p)) ancestors.unshift(p);
|
|
46
|
+
if (ancestors.length === 0) {
|
|
47
|
+
copyNode(node, receiver, true);
|
|
48
|
+
return receiver.items.at(-1);
|
|
49
|
+
}
|
|
50
|
+
const content = copyAncestors(ancestors, receiver, record);
|
|
51
|
+
const parent = content.parent;
|
|
52
|
+
if (node.nodeType === 2) {
|
|
53
|
+
return namedAttributeOf(
|
|
54
|
+
parent,
|
|
55
|
+
node.namespaceURI ?? "",
|
|
56
|
+
node.localName ?? node.nodeName,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (node.nodeType === 13) {
|
|
60
|
+
return namespaceNodesOf(parent).find(
|
|
61
|
+
(ns) => ns.localName === node.localName,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
copyNode(node, content, true);
|
|
65
|
+
return parent.lastChild;
|
|
66
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort keys at run time (XSLT 3.0 sections 13.1.2 and 13.1.3): the
|
|
3
|
+
* settings of a key from its attribute value templates, the key value of
|
|
4
|
+
* an item, and the comparison of key values (empty first, then NaN).
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/xslt/runtime/sortKeys
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { getCollation } from "../../functions/collations.js";
|
|
10
|
+
import { stringItem } from "../../xpath/eval/atomics.js";
|
|
11
|
+
import { compareAtomic } from "../../xdm/compare.js";
|
|
12
|
+
import { toNumber } from "../../xdm/generalCompare.js";
|
|
13
|
+
import { atomize, stringValue } from "../../xdm/nodes.js";
|
|
14
|
+
import { types } from "../../xdm/types.js";
|
|
15
|
+
import { cast } from "../../xdm/cast.js";
|
|
16
|
+
import { xsltError } from "../names.js";
|
|
17
|
+
import { evaluate } from "./context.js";
|
|
18
|
+
import { bodySequence } from "./values.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The comparison function of a lang or case-order setting.
|
|
22
|
+
* @param {string|undefined} lang
|
|
23
|
+
* @param {string|undefined} caseOrder
|
|
24
|
+
* @returns {(a: string, b: string) => number}
|
|
25
|
+
*/
|
|
26
|
+
function languageCollation(lang, caseOrder) {
|
|
27
|
+
let collator;
|
|
28
|
+
try {
|
|
29
|
+
collator = new Intl.Collator(lang || "en", {
|
|
30
|
+
caseFirst: caseOrder === "lower-first" ? "lower" : "upper",
|
|
31
|
+
});
|
|
32
|
+
} catch {
|
|
33
|
+
throw xsltError("XTDE0030", `Invalid lang ${lang}`);
|
|
34
|
+
}
|
|
35
|
+
return (a, b) => collator.compare(a, b);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The comparison settings of a key, from its attribute value templates.
|
|
40
|
+
* @param {object} key - Compiled xsl:sort
|
|
41
|
+
* @param {object} xc
|
|
42
|
+
* @returns {{descending: boolean, dataType: string, compare: Function}}
|
|
43
|
+
*/
|
|
44
|
+
export function settingsOf(key, xc) {
|
|
45
|
+
const order = key.order?.(xc).trim() ?? "ascending";
|
|
46
|
+
if (order !== "ascending" && order !== "descending") {
|
|
47
|
+
throw xsltError("XTDE0030", `Invalid sort order ${order}`);
|
|
48
|
+
}
|
|
49
|
+
const dataType = key.dataType?.(xc).trim() ?? "";
|
|
50
|
+
if (!["", "text", "number"].includes(dataType) && !dataType.includes(":")) {
|
|
51
|
+
throw xsltError("XTDE0030", `Invalid data-type ${dataType}`);
|
|
52
|
+
}
|
|
53
|
+
const caseOrder = key.caseOrder?.(xc).trim();
|
|
54
|
+
if (caseOrder && caseOrder !== "upper-first" && caseOrder !== "lower-first") {
|
|
55
|
+
throw xsltError("XTDE0030", `Invalid case-order ${caseOrder}`);
|
|
56
|
+
}
|
|
57
|
+
const lang = key.lang?.(xc).trim();
|
|
58
|
+
let compare;
|
|
59
|
+
if (key.collation) {
|
|
60
|
+
const uri = key.collation(xc).trim();
|
|
61
|
+
try {
|
|
62
|
+
compare = getCollation(uri, xc.tx.dyn).compare;
|
|
63
|
+
} catch {
|
|
64
|
+
throw xsltError("XTDE1035", `Unknown collation ${uri}`);
|
|
65
|
+
}
|
|
66
|
+
} else if (lang || caseOrder) compare = languageCollation(lang, caseOrder);
|
|
67
|
+
return { descending: order === "descending", dataType, compare };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The sort key value of one item.
|
|
72
|
+
* @param {object} key - Compiled xsl:sort
|
|
73
|
+
* @param {object} settings
|
|
74
|
+
* @param {object} xc - Context with the item as focus
|
|
75
|
+
* @param {object} machine
|
|
76
|
+
* @returns {*} an atomic value, or null for the empty sequence
|
|
77
|
+
*/
|
|
78
|
+
export function keyValue(key, settings, xc, machine) {
|
|
79
|
+
let values = key.expr
|
|
80
|
+
? evaluate(key.expr, xc)
|
|
81
|
+
: bodySequence(key.body, xc, machine);
|
|
82
|
+
if (key.compatible) values = values.slice(0, 1);
|
|
83
|
+
if (settings.dataType === "text") {
|
|
84
|
+
return values.length ? stringItem(values.map(stringValue).join(" ")) : null;
|
|
85
|
+
}
|
|
86
|
+
const atoms = atomize(values);
|
|
87
|
+
if (atoms.length > 1) {
|
|
88
|
+
throw xsltError("XTTE1020", "A sort key must be a single value");
|
|
89
|
+
}
|
|
90
|
+
if (atoms.length === 0) return null;
|
|
91
|
+
if (settings.dataType === "number") return toNumber(atoms[0]);
|
|
92
|
+
const [value] = atoms;
|
|
93
|
+
return value.type === types.untypedAtomic ? cast(value, types.string) : value;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const isNaNValue = (v) => typeof v.value === "number" && Number.isNaN(v.value);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Compares two key values: the empty sequence first, then NaN.
|
|
100
|
+
* @param {*} a
|
|
101
|
+
* @param {*} b
|
|
102
|
+
* @param {object} settings
|
|
103
|
+
* @param {object} xc
|
|
104
|
+
* @returns {number}
|
|
105
|
+
*/
|
|
106
|
+
export function compareValues(a, b, settings, xc) {
|
|
107
|
+
if (a === null || b === null) {
|
|
108
|
+
return (a === null ? 0 : 1) - (b === null ? 0 : 1);
|
|
109
|
+
}
|
|
110
|
+
if (isNaNValue(a) || isNaNValue(b)) {
|
|
111
|
+
return Number(!isNaNValue(a)) - Number(!isNaNValue(b));
|
|
112
|
+
}
|
|
113
|
+
const options = { ...xc.tx.dyn.compareOptions, collation: settings.compare };
|
|
114
|
+
try {
|
|
115
|
+
return compareAtomic(a, b, options).order || 0;
|
|
116
|
+
} catch {
|
|
117
|
+
throw xsltError("XTDE1030", "Sort key values are not comparable");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fn:stream-available (XSLT 3.0 section 18.1): whether a call of
|
|
3
|
+
* xsl:source-document with streamable="yes" on the URI would start
|
|
4
|
+
* successfully. The processor does not stream, so this holds when the
|
|
5
|
+
* resource is a well-formed document or, as a streaming parser would see
|
|
6
|
+
* it, a resource that starts with a well-formed prolog and an element
|
|
7
|
+
* (a later well-formedness error is only met while streaming).
|
|
8
|
+
*
|
|
9
|
+
* @module @tradik/xslt3/xslt/runtime/streamAvailable
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { booleanItem } from "../../functions/support.js";
|
|
13
|
+
|
|
14
|
+
/** XML declaration, comments, processing instructions and whitespace. */
|
|
15
|
+
const MISC = String.raw`(?:\s+|<!--[\s\S]*?-->|<\?[\s\S]*?\?>)*`;
|
|
16
|
+
|
|
17
|
+
/** A prolog (with an optional document type declaration), then a tag. */
|
|
18
|
+
const STARTS_WITH_ELEMENT = new RegExp(
|
|
19
|
+
`^\\uFEFF?${MISC}(?:<!DOCTYPE[^\\[>]*(?:\\[[\\s\\S]*?\\]\\s*)?>${MISC})?<[\\p{L}_:]`,
|
|
20
|
+
"u",
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Whether a text starts as an XML document with an element.
|
|
25
|
+
* @param {string} text
|
|
26
|
+
* @returns {boolean}
|
|
27
|
+
*/
|
|
28
|
+
export const startsWithElement = (text) => STARTS_WITH_ELEMENT.test(text);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Whether a document is available for streaming.
|
|
32
|
+
* @param {string} uri
|
|
33
|
+
* @param {object} context - XPath dynamic context
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
function available(uri, context) {
|
|
37
|
+
try {
|
|
38
|
+
const document = context.loadDocument(uri);
|
|
39
|
+
if (document.documentElement) return true;
|
|
40
|
+
} catch {
|
|
41
|
+
// not a well-formed document: perhaps one that starts well
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return startsWithElement(context.loadText(uri));
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Function definitions. */
|
|
51
|
+
export const streamAvailableFunctions = [
|
|
52
|
+
{
|
|
53
|
+
local: "stream-available",
|
|
54
|
+
params: ["xs:string?"],
|
|
55
|
+
returns: "xs:boolean",
|
|
56
|
+
impl: ([uri], context) => [
|
|
57
|
+
booleanItem(uri.length > 0 && available(uri[0].value, context)),
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whitespace stripping of source documents (XSLT 3.0 section 4.3): the
|
|
3
|
+
* whitespace-only text nodes whose parent element matches xsl:strip-space
|
|
4
|
+
* (and no better xsl:preserve-space rule), outside xml:space="preserve",
|
|
5
|
+
* are removed from a copy of the document.
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/xslt/runtime/strip
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { XML_NS } from "../names.js";
|
|
11
|
+
|
|
12
|
+
const WHITESPACE = /^[ \t\r\n]*$/;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Builds the decision of the rules for an element name.
|
|
16
|
+
* @param {object[]} rules - Best first (see compileSpaceRules)
|
|
17
|
+
* @returns {(element: Element) => boolean} whether to strip its children
|
|
18
|
+
*/
|
|
19
|
+
export function stripDecider(rules) {
|
|
20
|
+
const cache = new Map();
|
|
21
|
+
return (element) => {
|
|
22
|
+
const uri = element.namespaceURI ?? "";
|
|
23
|
+
const local = element.localName;
|
|
24
|
+
const key = `{${uri}}${local}`;
|
|
25
|
+
let strip = cache.get(key);
|
|
26
|
+
if (strip === undefined) {
|
|
27
|
+
const rule = rules.find(
|
|
28
|
+
(r) =>
|
|
29
|
+
(r.uri === null || r.uri === uri) &&
|
|
30
|
+
(r.local === null || r.local === local),
|
|
31
|
+
);
|
|
32
|
+
strip = rule ? rule.strip : false;
|
|
33
|
+
cache.set(key, strip);
|
|
34
|
+
}
|
|
35
|
+
return strip;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Whether a text node is one that stripping removes: whitespace only,
|
|
41
|
+
* its parent element matched by xsl:strip-space and not under
|
|
42
|
+
* xml:space="preserve".
|
|
43
|
+
* @param {Node} node
|
|
44
|
+
* @param {object[]} rules
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
export function isStrippedText(node, rules) {
|
|
48
|
+
const parent = node.parentNode;
|
|
49
|
+
if (node.nodeType !== 3 || parent?.nodeType !== 1) return false;
|
|
50
|
+
if (!WHITESPACE.test(node.nodeValue) || !stripDecider(rules)(parent)) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
for (let e = parent; e?.nodeType === 1; e = e.parentNode) {
|
|
54
|
+
const space = e.getAttributeNS(XML_NS, "space");
|
|
55
|
+
if (space) return space !== "preserve";
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A stripped copy of a document (the document itself when no rule
|
|
62
|
+
* strips anything).
|
|
63
|
+
* @param {Document} document
|
|
64
|
+
* @param {object[]} rules
|
|
65
|
+
* @returns {Document}
|
|
66
|
+
*/
|
|
67
|
+
export function stripDocument(document, rules) {
|
|
68
|
+
if (!rules.some((rule) => rule.strip)) return document;
|
|
69
|
+
const decide = stripDecider(rules);
|
|
70
|
+
const copy = document.implementation.createDocument(null, null, null);
|
|
71
|
+
for (const child of document.childNodes) {
|
|
72
|
+
if (child.nodeType !== 10) copy.appendChild(copy.importNode(child, true));
|
|
73
|
+
}
|
|
74
|
+
if (document.documentURI) {
|
|
75
|
+
try {
|
|
76
|
+
copy.documentURI = document.documentURI;
|
|
77
|
+
} catch {
|
|
78
|
+
// read-only in some DOMs
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const stack = [[copy.documentElement, false]];
|
|
82
|
+
while (stack.length > 0) {
|
|
83
|
+
const [element, preserved] = stack.pop();
|
|
84
|
+
if (!element) continue;
|
|
85
|
+
const space = element.getAttributeNS(XML_NS, "space");
|
|
86
|
+
const keep = space === "preserve" || (space !== "default" && preserved);
|
|
87
|
+
const strip = !keep && decide(element);
|
|
88
|
+
for (let child = element.firstChild; child;) {
|
|
89
|
+
const next = child.nextSibling;
|
|
90
|
+
if (child.nodeType === 1) stack.push([child, keep]);
|
|
91
|
+
else if (
|
|
92
|
+
strip &&
|
|
93
|
+
child.nodeType === 3 &&
|
|
94
|
+
WHITESPACE.test(child.nodeValue)
|
|
95
|
+
) {
|
|
96
|
+
element.removeChild(child);
|
|
97
|
+
}
|
|
98
|
+
child = next;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return copy;
|
|
102
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fn:transform (F&O 3.1, "Dynamic loading"): runs another stylesheet from an
|
|
3
|
+
* XPath expression and returns its results as a map: "output" for the
|
|
4
|
+
* principal result and the absolute URI of each secondary result, each
|
|
5
|
+
* delivered as a document (default), serialized as a string, or raw.
|
|
6
|
+
* The stylesheet is compiled with the options of the calling one (module
|
|
7
|
+
* and package loaders) and runs with the resource loaders of the calling
|
|
8
|
+
* transformation.
|
|
9
|
+
*
|
|
10
|
+
* @module @tradik/xslt3/xslt/runtime/transformFunction
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { XdmMap } from "../../items/map.js";
|
|
14
|
+
import { serialize } from "../../serialize/index.js";
|
|
15
|
+
import { atomize } from "../../xdm/nodes.js";
|
|
16
|
+
import { parametersFromMap } from "../../serialize/params/fromMap.js";
|
|
17
|
+
import { stringItem } from "../../xpath/eval/atomics.js";
|
|
18
|
+
import { resolveUri } from "../../xpath/eval/uris.js";
|
|
19
|
+
import { xsltError } from "../names.js";
|
|
20
|
+
import { compileWith } from "./compilerHook.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {*} item - An xs:QName value
|
|
24
|
+
* @returns {string} its Clark name
|
|
25
|
+
*/
|
|
26
|
+
const clark = (item) => `{${item.value.namespaceURI}}${item.value.localName}`;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A map with QName keys as a Map by Clark name.
|
|
30
|
+
* @param {XdmMap|undefined} map
|
|
31
|
+
* @returns {Map<string, Array>}
|
|
32
|
+
*/
|
|
33
|
+
function byClarkName(map) {
|
|
34
|
+
const result = new Map();
|
|
35
|
+
for (const { key, value } of map?.entries.values() ?? []) {
|
|
36
|
+
result.set(clark(key), value);
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The string value of an option, atomized (a value built by
|
|
43
|
+
* xsl:map-entry content is a text node).
|
|
44
|
+
* @param {Array|undefined} value
|
|
45
|
+
* @returns {string|undefined}
|
|
46
|
+
*/
|
|
47
|
+
const text = (value) =>
|
|
48
|
+
value?.length ? String(atomize(value.slice(0, 1))[0]?.value) : undefined;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Reads the options map.
|
|
52
|
+
* @param {XdmMap} map
|
|
53
|
+
* @returns {(name: string) => Array|undefined} the value of an option
|
|
54
|
+
*/
|
|
55
|
+
const reader = (map) => (name) => map.get(stringItem(name));
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The stylesheet to run, compiled.
|
|
59
|
+
* @param {(name: string) => Array|undefined} option
|
|
60
|
+
* @param {object} context - XPath dynamic context
|
|
61
|
+
* @param {object} compileOptions - Options of the calling stylesheet
|
|
62
|
+
* @returns {object} the CompiledStylesheet
|
|
63
|
+
* @throws {import("../../errors.js").XPathError} FOXT0002 when no
|
|
64
|
+
* stylesheet is given or it cannot be loaded
|
|
65
|
+
*/
|
|
66
|
+
function compiled(option, context, compileOptions) {
|
|
67
|
+
const value = (name) => option(name)?.[0];
|
|
68
|
+
const staticParams = byClarkName(value("static-params"));
|
|
69
|
+
const base = text(option("stylesheet-base-uri"));
|
|
70
|
+
const compile = (source, baseUri) =>
|
|
71
|
+
compileWith(source, { ...compileOptions, baseUri, staticParams });
|
|
72
|
+
const location = text(option("stylesheet-location"));
|
|
73
|
+
if (location !== undefined) {
|
|
74
|
+
const uri = resolveUri(location, context.staticBaseUri);
|
|
75
|
+
let source;
|
|
76
|
+
try {
|
|
77
|
+
source = compileOptions.loadStylesheet?.(uri, context.staticBaseUri);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
throw xsltError("FOXT0002", `Cannot load ${uri}: ${error.message}`);
|
|
80
|
+
}
|
|
81
|
+
if (!source) throw xsltError("FOXT0002", `No stylesheet at ${uri}`);
|
|
82
|
+
return compile(source, uri);
|
|
83
|
+
}
|
|
84
|
+
const node = value("stylesheet-node") ?? text(option("stylesheet-text"));
|
|
85
|
+
if (node !== undefined) return compile(node, base);
|
|
86
|
+
const name = text(option("package-name"));
|
|
87
|
+
const found =
|
|
88
|
+
name === undefined
|
|
89
|
+
? undefined
|
|
90
|
+
: compileOptions.resolvePackage?.(
|
|
91
|
+
name,
|
|
92
|
+
text(option("package-version")) ?? "*",
|
|
93
|
+
);
|
|
94
|
+
if (!found) throw xsltError("FOXT0002", "fn:transform: no stylesheet");
|
|
95
|
+
return compile(found.source ?? found, found.baseUri ?? base);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* A result in the requested delivery format.
|
|
100
|
+
* @param {*} value - Document, fragment or raw sequence
|
|
101
|
+
* @param {string} format - "document", "serialized" or "raw"
|
|
102
|
+
* @param {object} output - Its serialization parameters
|
|
103
|
+
* @returns {Array}
|
|
104
|
+
*/
|
|
105
|
+
function delivered(value, format, output) {
|
|
106
|
+
const sequence = [value].flat();
|
|
107
|
+
if (format === "serialized") return [stringItem(serialize(sequence, output))];
|
|
108
|
+
return sequence;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* fn:transform.
|
|
113
|
+
* @param {Array} args - The options map
|
|
114
|
+
* @param {object} context - XPath dynamic context
|
|
115
|
+
* @returns {Array} the result map
|
|
116
|
+
*/
|
|
117
|
+
function transform([[map]], context) {
|
|
118
|
+
const option = reader(map);
|
|
119
|
+
const value = (name) => option(name)?.[0];
|
|
120
|
+
const tx = context.xc?.tx;
|
|
121
|
+
const compileOptions =
|
|
122
|
+
tx?.stylesheet.options ?? context.sc?.owner?.options ?? {};
|
|
123
|
+
const format = text(option("delivery-format")) ?? "document";
|
|
124
|
+
const stylesheet = compiled(option, context, compileOptions);
|
|
125
|
+
const initial = (name) => (value(name) ? clark(value(name)) : undefined);
|
|
126
|
+
const functionParams = value("function-params");
|
|
127
|
+
const result = stylesheet.transform({
|
|
128
|
+
...tx?.options,
|
|
129
|
+
source: value("source-node"),
|
|
130
|
+
initialTemplate: initial("initial-template"),
|
|
131
|
+
initialMode: initial("initial-mode"),
|
|
132
|
+
initialMatchSelection: option("initial-match-selection"),
|
|
133
|
+
initialFunction: value("initial-function") && {
|
|
134
|
+
name: initial("initial-function"),
|
|
135
|
+
args: functionParams?.members ?? [],
|
|
136
|
+
},
|
|
137
|
+
globalContextItem: value("global-context-item"),
|
|
138
|
+
params: byClarkName(value("stylesheet-params")),
|
|
139
|
+
templateParams: byClarkName(value("template-params")),
|
|
140
|
+
tunnelParams: byClarkName(value("tunnel-params")),
|
|
141
|
+
baseOutputUri: text(option("base-output-uri")),
|
|
142
|
+
buildTree: format === "raw" ? false : undefined,
|
|
143
|
+
onMessage: undefined,
|
|
144
|
+
});
|
|
145
|
+
const extra = value("serialization-params");
|
|
146
|
+
const params = extra ? parametersFromMap(extra) : {};
|
|
147
|
+
const entries = [];
|
|
148
|
+
const principal = [result.principal].flat();
|
|
149
|
+
if (principal.length > 0 || format !== "raw") {
|
|
150
|
+
entries.push([
|
|
151
|
+
stringItem("output"),
|
|
152
|
+
delivered(result.principal, format, { ...result.output, ...params }),
|
|
153
|
+
]);
|
|
154
|
+
}
|
|
155
|
+
for (const [uri, { document, output }] of result.secondary) {
|
|
156
|
+
entries.push([stringItem(uri), delivered(document, format, output)]);
|
|
157
|
+
}
|
|
158
|
+
return [XdmMap.from(entries)];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Function definitions. */
|
|
162
|
+
export const transformFunctions = [
|
|
163
|
+
{
|
|
164
|
+
local: "transform",
|
|
165
|
+
params: ["map(*)"],
|
|
166
|
+
returns: "map(*)",
|
|
167
|
+
impl: transform,
|
|
168
|
+
},
|
|
169
|
+
];
|