@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,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The namespaces of an element under construction: its own namespace
|
|
3
|
+
* nodes (from its name, its attributes' names and namespace
|
|
4
|
+
* instructions) and those in scope from its ancestors, with the `xmlns`
|
|
5
|
+
* declarations the DOM needs (XSLT 3.0 section 5.7.3, namespace fixup).
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/xslt/runtime/namespaceScope
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { XML_NS, XMLNS_NS } from "../names.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {string} qname
|
|
14
|
+
* @returns {string} the prefix of a lexical QName, "" for none
|
|
15
|
+
*/
|
|
16
|
+
export const prefixOf = (qname) => {
|
|
17
|
+
const colon = qname.indexOf(":");
|
|
18
|
+
return colon < 0 ? "" : qname.slice(0, colon);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Namespace bookkeeping of the element a receiver builds. */
|
|
22
|
+
export class NamespaceScope {
|
|
23
|
+
/**
|
|
24
|
+
* @param {Node} parent - The element (or document) built
|
|
25
|
+
* @param {Map<string, string>} namespaces - In scope at its parent
|
|
26
|
+
*/
|
|
27
|
+
constructor(parent, namespaces) {
|
|
28
|
+
this.parent = parent;
|
|
29
|
+
this.inherited = namespaces;
|
|
30
|
+
this.namespaces = namespaces;
|
|
31
|
+
this.ownNamespaces = false;
|
|
32
|
+
/** @type {Map<string, string>|null} namespace nodes of this element */
|
|
33
|
+
this.own = null;
|
|
34
|
+
/** @type {Set<string>} prefixes of namespace nodes added explicitly */
|
|
35
|
+
this.explicit = new Set();
|
|
36
|
+
/** @type {((old: Element, element: Element) => void)|null} */
|
|
37
|
+
this.onReplace = null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Gives the element a namespace node that conflicts with the prefix of
|
|
42
|
+
* its name: the element is renamed with a new prefix (namespace fixup).
|
|
43
|
+
* @param {string} prefix
|
|
44
|
+
* @param {string} uri
|
|
45
|
+
* @returns {boolean} false when the conflict is not with the name, or
|
|
46
|
+
* when the name's namespace node was itself added explicitly
|
|
47
|
+
*/
|
|
48
|
+
rebind(prefix, uri) {
|
|
49
|
+
const old = this.parent;
|
|
50
|
+
if (prefix === "" || old.prefix !== prefix || this.explicit.has(prefix)) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
let fresh;
|
|
54
|
+
for (let i = 0; this.namespaces.has((fresh = `${prefix}_${i}`)); i++);
|
|
55
|
+
const element = old.ownerDocument.createElementNS(
|
|
56
|
+
old.namespaceURI,
|
|
57
|
+
`${fresh}:${old.localName}`,
|
|
58
|
+
);
|
|
59
|
+
for (const attribute of old.attributes) {
|
|
60
|
+
if (attribute.name === `xmlns:${prefix}`) continue;
|
|
61
|
+
element.setAttributeNS(
|
|
62
|
+
attribute.namespaceURI,
|
|
63
|
+
attribute.name,
|
|
64
|
+
attribute.value,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
old.parentNode?.replaceChild(element, old);
|
|
68
|
+
this.onReplace?.(old, element);
|
|
69
|
+
this.parent = element;
|
|
70
|
+
this.own.delete(prefix);
|
|
71
|
+
if (this.ownNamespaces) {
|
|
72
|
+
const before = this.inherited.get(prefix);
|
|
73
|
+
if (before === undefined) this.namespaces.delete(prefix);
|
|
74
|
+
else this.namespaces.set(prefix, before);
|
|
75
|
+
}
|
|
76
|
+
this.declare(fresh, old.namespaceURI);
|
|
77
|
+
return this.declare(prefix, uri);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Gives the element a namespace node, declared when not in scope.
|
|
82
|
+
* @param {string} prefix
|
|
83
|
+
* @param {string} uri
|
|
84
|
+
* @returns {boolean} false when the element already binds the prefix to
|
|
85
|
+
* another URI
|
|
86
|
+
*/
|
|
87
|
+
declare(prefix, uri) {
|
|
88
|
+
if (prefix === "xml") return uri === XML_NS;
|
|
89
|
+
const own = this.own?.get(prefix);
|
|
90
|
+
if (own !== undefined) return own === uri;
|
|
91
|
+
if (prefix !== "" && uri === "") return true;
|
|
92
|
+
if (!this.own) this.own = new Map();
|
|
93
|
+
this.own.set(prefix, uri);
|
|
94
|
+
if ((this.namespaces.get(prefix) ?? "") !== uri) {
|
|
95
|
+
if (!this.ownNamespaces) {
|
|
96
|
+
this.namespaces = new Map(this.namespaces);
|
|
97
|
+
this.ownNamespaces = true;
|
|
98
|
+
}
|
|
99
|
+
this.namespaces.set(prefix, uri);
|
|
100
|
+
const name = prefix === "" ? "xmlns" : `xmlns:${prefix}`;
|
|
101
|
+
this.parent.setAttributeNS(XMLNS_NS, name, uri);
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Gives the element a namespace node that it must keep (copied by a
|
|
108
|
+
* literal result element or xsl:copy, or built by xsl:namespace): two
|
|
109
|
+
* such nodes for one prefix conflict (XTDE0430), rather than causing a
|
|
110
|
+
* namespace fixup.
|
|
111
|
+
* @param {string} prefix
|
|
112
|
+
* @param {string} uri
|
|
113
|
+
* @returns {boolean} as {@link NamespaceScope#declare}
|
|
114
|
+
*/
|
|
115
|
+
declareExplicit(prefix, uri) {
|
|
116
|
+
const declared = this.declare(prefix, uri);
|
|
117
|
+
if (declared) this.explicit.add(prefix);
|
|
118
|
+
return declared;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* A prefix bound to a URI on the element, declared when needed: one in
|
|
123
|
+
* scope, else `base_1`, `base_2`... (`ns0`, `ns1`... without base).
|
|
124
|
+
* @param {string} uri
|
|
125
|
+
* @param {string} base - Preferred prefix, "" for none
|
|
126
|
+
* @returns {string}
|
|
127
|
+
*/
|
|
128
|
+
prefixFor(uri, base) {
|
|
129
|
+
for (const [prefix, bound] of this.namespaces) {
|
|
130
|
+
if (bound === uri && prefix !== "" && this.declare(prefix, uri)) {
|
|
131
|
+
return prefix;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (let i = base ? 1 : 0; ; i++) {
|
|
135
|
+
const prefix = base ? `${base}_${i}` : `ns${i}`;
|
|
136
|
+
if (!this.namespaces.has(prefix) && this.declare(prefix, uri)) {
|
|
137
|
+
return prefix;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The format string of xsl:number (XSLT 3.0 section 12.4): alphanumeric
|
|
3
|
+
* format tokens separated by punctuation, with a prefix and a suffix,
|
|
4
|
+
* applied to a list of numbers.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/xslt/runtime/numberFormat
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { formatToken } from "../../functions/format/formatInteger.js";
|
|
10
|
+
import { numberLanguage } from "../../functions/format/numberLanguages.js";
|
|
11
|
+
|
|
12
|
+
const ALPHANUMERIC = /[\p{L}\p{N}]/u;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Splits a format string into a prefix, tokens with their separators,
|
|
16
|
+
* and a suffix.
|
|
17
|
+
* @param {string} format
|
|
18
|
+
* @returns {{prefix: string, tokens: string[], separators: string[], suffix: string}}
|
|
19
|
+
*/
|
|
20
|
+
export function parseFormat(format) {
|
|
21
|
+
const parts = [];
|
|
22
|
+
let current = "";
|
|
23
|
+
let alnum = null;
|
|
24
|
+
for (const c of format) {
|
|
25
|
+
const isAlnum = ALPHANUMERIC.test(c);
|
|
26
|
+
if (alnum !== null && isAlnum !== alnum) {
|
|
27
|
+
parts.push({ text: current, alnum });
|
|
28
|
+
current = "";
|
|
29
|
+
}
|
|
30
|
+
current += c;
|
|
31
|
+
alnum = isAlnum;
|
|
32
|
+
}
|
|
33
|
+
if (current) parts.push({ text: current, alnum });
|
|
34
|
+
let prefix = "";
|
|
35
|
+
let suffix = "";
|
|
36
|
+
if (parts[0] && !parts[0].alnum) prefix = parts.shift().text;
|
|
37
|
+
if (parts.length && !parts.at(-1).alnum) suffix = parts.pop().text;
|
|
38
|
+
const tokens = parts.filter((p) => p.alnum).map((p) => p.text);
|
|
39
|
+
const separators = parts.filter((p) => !p.alnum).map((p) => p.text);
|
|
40
|
+
if (tokens.length === 0) {
|
|
41
|
+
// no format token: "1", with the punctuation as prefix and suffix
|
|
42
|
+
return { prefix, tokens: ["1"], separators: [], suffix: prefix };
|
|
43
|
+
}
|
|
44
|
+
return { prefix, tokens, separators, suffix };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Inserts a grouping separator every `size` digits.
|
|
49
|
+
* @param {string} digits
|
|
50
|
+
* @param {string} separator
|
|
51
|
+
* @param {number} size
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
function group(digits, separator, size) {
|
|
55
|
+
if (!separator || !(size > 0) || !/^\p{Nd}+$/u.test(digits)) return digits;
|
|
56
|
+
const chars = [...digits];
|
|
57
|
+
let result = "";
|
|
58
|
+
chars.forEach((c, i) => {
|
|
59
|
+
if (i > 0 && (chars.length - i) % size === 0) result += separator;
|
|
60
|
+
result += c;
|
|
61
|
+
});
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Formats a list of numbers.
|
|
67
|
+
* @param {bigint[]} numbers
|
|
68
|
+
* @param {string} format
|
|
69
|
+
* @param {{ordinal: boolean|string, separator: string, size: number,
|
|
70
|
+
* lang?: string|null}} options - ordinal: false, or the value of the
|
|
71
|
+
* ordinal attribute
|
|
72
|
+
* @returns {string}
|
|
73
|
+
*/
|
|
74
|
+
export function formatNumbers(numbers, format, options) {
|
|
75
|
+
const { prefix, tokens, separators, suffix } = parseFormat(format);
|
|
76
|
+
const language = numberLanguage(options.lang);
|
|
77
|
+
let result = prefix;
|
|
78
|
+
numbers.forEach((n, i) => {
|
|
79
|
+
if (i > 0) {
|
|
80
|
+
result += separators[Math.min(i, separators.length) - 1] ?? ".";
|
|
81
|
+
}
|
|
82
|
+
const token = tokens[Math.min(i, tokens.length - 1)];
|
|
83
|
+
// a negative number (start-at below 1) gets a minus sign
|
|
84
|
+
const text = formatToken(n < 0n ? -n : n, token, options.ordinal, language);
|
|
85
|
+
result +=
|
|
86
|
+
(n < 0n ? "-" : "") + group(text, options.separator, options.size);
|
|
87
|
+
});
|
|
88
|
+
return result + suffix;
|
|
89
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The place of a node in a document as xsl:number counts it (XSLT 3.0
|
|
3
|
+
* section 12.2): levels single, multiple and any, with count and from
|
|
4
|
+
* patterns.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/xslt/runtime/numbering
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
nodeLocalName,
|
|
11
|
+
nodeNamespace,
|
|
12
|
+
parentOf,
|
|
13
|
+
} from "../../xpath/eval/domNodes.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The default count pattern: nodes of the same kind and name.
|
|
17
|
+
* @param {Node} node
|
|
18
|
+
* @returns {(other: Node) => boolean}
|
|
19
|
+
*/
|
|
20
|
+
export function sameKindAndName(node) {
|
|
21
|
+
const type = node.nodeType === 4 ? 3 : node.nodeType;
|
|
22
|
+
const local = nodeLocalName(node);
|
|
23
|
+
const uri = nodeNamespace(node);
|
|
24
|
+
return (other) => {
|
|
25
|
+
const otherType = other.nodeType === 4 ? 3 : other.nodeType;
|
|
26
|
+
return (
|
|
27
|
+
otherType === type &&
|
|
28
|
+
nodeLocalName(other) === local &&
|
|
29
|
+
nodeNamespace(other) === uri
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The key of the default count pattern of a node (see sameKindAndName):
|
|
36
|
+
* numbers memoized for one key are not valid for another.
|
|
37
|
+
* @param {Node} node
|
|
38
|
+
* @returns {string}
|
|
39
|
+
*/
|
|
40
|
+
export function countKey(node) {
|
|
41
|
+
const type = node.nodeType === 4 ? 3 : node.nodeType;
|
|
42
|
+
return `${type}|${nodeNamespace(node) ?? ""}|${nodeLocalName(node)}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The memo of an xsl:number instruction in a transformation: the numbers
|
|
47
|
+
* already given to nodes, so that numbering a long list stays linear.
|
|
48
|
+
* Only valid while counting depends on nothing but the tree: the caller
|
|
49
|
+
* does not memoize patterns that read variables.
|
|
50
|
+
* @param {object} tx - The transformation (holds the memos)
|
|
51
|
+
* @param {object} instruction - Identity of the instruction
|
|
52
|
+
* @param {string} key - The count pattern ("" for an explicit one, else
|
|
53
|
+
* the {@link countKey} of the numbered node)
|
|
54
|
+
* @returns {WeakMap<Node, number>}
|
|
55
|
+
*/
|
|
56
|
+
export function numberMemo(tx, instruction, key) {
|
|
57
|
+
tx.numberMemos ??= new WeakMap();
|
|
58
|
+
let byKey = tx.numberMemos.get(instruction);
|
|
59
|
+
if (!byKey) tx.numberMemos.set(instruction, (byKey = new Map()));
|
|
60
|
+
let memo = byKey.get(key);
|
|
61
|
+
if (!memo) byKey.set(key, (memo = new WeakMap()));
|
|
62
|
+
return memo;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Number of preceding siblings that match, plus one; the walk stops at a
|
|
67
|
+
* sibling whose number is memoized (a counted node: its number includes
|
|
68
|
+
* itself and the counted siblings before it).
|
|
69
|
+
* @param {Node} node - A counted node
|
|
70
|
+
* @param {(node: Node) => boolean} count
|
|
71
|
+
* @param {WeakMap<Node, number>|null} memo
|
|
72
|
+
* @returns {number}
|
|
73
|
+
*/
|
|
74
|
+
function siblingNumber(node, count, memo) {
|
|
75
|
+
if (node.nodeType === 2 || node.nodeType === 13) return 1;
|
|
76
|
+
const own = memo?.get(node);
|
|
77
|
+
if (own !== undefined) return own;
|
|
78
|
+
let n = 1;
|
|
79
|
+
for (let s = node.previousSibling; s; s = s.previousSibling) {
|
|
80
|
+
const known = memo?.get(s);
|
|
81
|
+
if (known !== undefined) {
|
|
82
|
+
n += known;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
if (s.nodeType !== 10 && count(s)) n++;
|
|
86
|
+
}
|
|
87
|
+
memo?.set(node, n);
|
|
88
|
+
return n;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Ancestors-or-self of a node, innermost first, up to (including) the
|
|
93
|
+
* first one matching `from` (all of them when none matches).
|
|
94
|
+
* @param {Node} node
|
|
95
|
+
* @param {((node: Node) => boolean)|null} from
|
|
96
|
+
* @returns {Node[]}
|
|
97
|
+
*/
|
|
98
|
+
function ancestorsBelowFrom(node, from) {
|
|
99
|
+
const result = [];
|
|
100
|
+
for (let a = node; a; a = parentOf(a)) {
|
|
101
|
+
result.push(a);
|
|
102
|
+
if (from && from(a)) break;
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* level="single" and level="multiple".
|
|
109
|
+
* @param {Node} node
|
|
110
|
+
* @param {(node: Node) => boolean} count
|
|
111
|
+
* @param {((node: Node) => boolean)|null} from
|
|
112
|
+
* @param {boolean} multiple
|
|
113
|
+
* @param {WeakMap<Node, number>|null} [memo] - Sibling numbers already
|
|
114
|
+
* computed with the same count pattern (see numberMemo)
|
|
115
|
+
* @returns {number[]}
|
|
116
|
+
*/
|
|
117
|
+
export function numberHierarchy(node, count, from, multiple, memo = null) {
|
|
118
|
+
const numbers = [];
|
|
119
|
+
for (const a of ancestorsBelowFrom(node, from)) {
|
|
120
|
+
if (!count(a)) continue;
|
|
121
|
+
numbers.unshift(siblingNumber(a, count, memo));
|
|
122
|
+
if (!multiple) break;
|
|
123
|
+
}
|
|
124
|
+
return numbers;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* The node before another in document order (preceding or ancestor).
|
|
129
|
+
* @param {Node} node
|
|
130
|
+
* @returns {Node|null}
|
|
131
|
+
*/
|
|
132
|
+
function previousInDocument(node) {
|
|
133
|
+
if (node.nodeType === 2 || node.nodeType === 13) return parentOf(node);
|
|
134
|
+
const sibling = node.previousSibling;
|
|
135
|
+
if (!sibling) return parentOf(node);
|
|
136
|
+
let last = sibling;
|
|
137
|
+
while (last.lastChild) last = last.lastChild;
|
|
138
|
+
return last;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* level="any": the counted nodes met walking back in document order from
|
|
143
|
+
* the node to a `from` node or the root. The walk from a node is the walk
|
|
144
|
+
* from any node it meets, so it stops at a node whose total is memoized:
|
|
145
|
+
* numbering in document order (for-each, apply-templates) only walks back
|
|
146
|
+
* to the node numbered before, and is linear instead of quadratic. In
|
|
147
|
+
* other orders nothing memoized is met and the walk is complete.
|
|
148
|
+
* @param {Node} node
|
|
149
|
+
* @param {(node: Node) => boolean} count
|
|
150
|
+
* @param {((node: Node) => boolean)|null} from
|
|
151
|
+
* @param {WeakMap<Node, number>|null} [memo] - Totals already computed
|
|
152
|
+
* with the same count and from patterns (see numberMemo)
|
|
153
|
+
* @returns {number[]}
|
|
154
|
+
*/
|
|
155
|
+
export function numberAny(node, count, from, memo = null) {
|
|
156
|
+
let n = 0;
|
|
157
|
+
for (let p = node; p; p = previousInDocument(p)) {
|
|
158
|
+
const known = memo?.get(p);
|
|
159
|
+
if (known !== undefined) {
|
|
160
|
+
n += known;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
if (p.nodeType !== 10 && count(p)) n++;
|
|
164
|
+
if (from && from(p)) break;
|
|
165
|
+
}
|
|
166
|
+
memo?.set(node, n);
|
|
167
|
+
return n === 0 ? [] : [n];
|
|
168
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Names and values given to the API: parameters by name, template and
|
|
3
|
+
* function names.
|
|
4
|
+
*
|
|
5
|
+
* @module @tradik/xslt3/xslt/runtime/params
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { toSequence } from "../../xpath/eval/values.js";
|
|
9
|
+
import { AtomicValue } from "../../xdm/atomic.js";
|
|
10
|
+
import { types } from "../../xdm/types.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The Clark name of a name given to the API: `local` (no namespace),
|
|
14
|
+
* `Q{uri}local` or `{uri}local`.
|
|
15
|
+
* @param {string} name
|
|
16
|
+
* @returns {string} `{uri}local`
|
|
17
|
+
*/
|
|
18
|
+
export function clarkName(name) {
|
|
19
|
+
if (name.startsWith("Q{")) return name.slice(1);
|
|
20
|
+
return name.startsWith("{") ? name : `{}${name}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* An xs:untypedAtomic value, for parameters that should convert to the
|
|
25
|
+
* declared type of the parameter (as a string from a command line does)
|
|
26
|
+
* instead of being checked as an xs:string.
|
|
27
|
+
* @param {*} value - Converted to a string
|
|
28
|
+
* @returns {AtomicValue}
|
|
29
|
+
*/
|
|
30
|
+
export const untypedAtomic = (value) =>
|
|
31
|
+
new AtomicValue(types.untypedAtomic, String(value));
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* A parameter value whose JavaScript strings become xs:untypedAtomic.
|
|
35
|
+
* @param {*} value
|
|
36
|
+
* @returns {*}
|
|
37
|
+
*/
|
|
38
|
+
const untypedStrings = (value) => {
|
|
39
|
+
if (typeof value === "string") return untypedAtomic(value);
|
|
40
|
+
return Array.isArray(value) ? value.map(untypedStrings) : value;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Normalizes parameters given by name to Clark names with XDM values
|
|
45
|
+
* (JavaScript values are converted, see xpath/eval/values.js).
|
|
46
|
+
* @param {object|Map|undefined} params
|
|
47
|
+
* @param {boolean} [asUntyped] - JavaScript strings are xs:untypedAtomic
|
|
48
|
+
* @returns {Map<string, Array>}
|
|
49
|
+
*/
|
|
50
|
+
export function normalizeParams(params, asUntyped = false) {
|
|
51
|
+
const result = new Map();
|
|
52
|
+
const entries =
|
|
53
|
+
params instanceof Map ? [...params] : Object.entries(params ?? {});
|
|
54
|
+
for (const [name, value] of entries) {
|
|
55
|
+
const converted = asUntyped ? untypedStrings(value) : value;
|
|
56
|
+
result.set(clarkName(name), toSequence(converted));
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the processor reports about itself: system-property() values
|
|
3
|
+
* (XSLT 3.0 section 20.4.4) and the instructions element-available()
|
|
4
|
+
* knows.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/xslt/runtime/properties
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** System properties in the XSLT namespace. */
|
|
10
|
+
const PROPERTIES = {
|
|
11
|
+
version: "3.0",
|
|
12
|
+
vendor: "tradik",
|
|
13
|
+
"vendor-url": "https://xslt-processor.tradik.com/",
|
|
14
|
+
"product-name": "@tradik/xslt3",
|
|
15
|
+
"product-version": "0.0.0",
|
|
16
|
+
"is-schema-aware": "no",
|
|
17
|
+
"supports-serialization": "yes",
|
|
18
|
+
"supports-backwards-compatibility": "yes",
|
|
19
|
+
"supports-namespace-axis": "yes",
|
|
20
|
+
"supports-streaming": "no",
|
|
21
|
+
"supports-dynamic-evaluation": "yes",
|
|
22
|
+
"supports-higher-order-functions": "yes",
|
|
23
|
+
"xpath-version": "3.1",
|
|
24
|
+
"xsd-version": "1.1",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The value of a system property in the XSLT namespace.
|
|
29
|
+
* @param {string} local - Local name
|
|
30
|
+
* @returns {string} "" for an unknown property
|
|
31
|
+
*/
|
|
32
|
+
export const systemProperty = (local) => PROPERTIES[local] ?? "";
|
|
33
|
+
|
|
34
|
+
/** @returns {string[]} the local names of the system properties */
|
|
35
|
+
export const systemPropertyNames = () => Object.keys(PROPERTIES);
|
|
36
|
+
|
|
37
|
+
/** Local names of the XSLT elements (instructions and declarations) implemented. */
|
|
38
|
+
export const availableInstructions = new Set([
|
|
39
|
+
"attribute-set",
|
|
40
|
+
"character-map",
|
|
41
|
+
"decimal-format",
|
|
42
|
+
"function",
|
|
43
|
+
"import",
|
|
44
|
+
"include",
|
|
45
|
+
"key",
|
|
46
|
+
"mode",
|
|
47
|
+
"namespace-alias",
|
|
48
|
+
"output",
|
|
49
|
+
"param",
|
|
50
|
+
"preserve-space",
|
|
51
|
+
"strip-space",
|
|
52
|
+
"stylesheet",
|
|
53
|
+
"template",
|
|
54
|
+
"transform",
|
|
55
|
+
"analyze-string",
|
|
56
|
+
"apply-imports",
|
|
57
|
+
"apply-templates",
|
|
58
|
+
"attribute",
|
|
59
|
+
"call-template",
|
|
60
|
+
"choose",
|
|
61
|
+
"comment",
|
|
62
|
+
"copy",
|
|
63
|
+
"copy-of",
|
|
64
|
+
"document",
|
|
65
|
+
"element",
|
|
66
|
+
"fallback",
|
|
67
|
+
"for-each",
|
|
68
|
+
"for-each-group",
|
|
69
|
+
"if",
|
|
70
|
+
"message",
|
|
71
|
+
"namespace",
|
|
72
|
+
"next-match",
|
|
73
|
+
"number",
|
|
74
|
+
"perform-sort",
|
|
75
|
+
"processing-instruction",
|
|
76
|
+
"result-document",
|
|
77
|
+
"sequence",
|
|
78
|
+
"text",
|
|
79
|
+
"value-of",
|
|
80
|
+
"try",
|
|
81
|
+
"catch",
|
|
82
|
+
"map",
|
|
83
|
+
"map-entry",
|
|
84
|
+
"variable",
|
|
85
|
+
// XSLT 3.0 instructions of task 0031
|
|
86
|
+
"accumulator",
|
|
87
|
+
"accumulator-rule",
|
|
88
|
+
"assert",
|
|
89
|
+
"break",
|
|
90
|
+
"evaluate",
|
|
91
|
+
"fork",
|
|
92
|
+
"iterate",
|
|
93
|
+
"merge",
|
|
94
|
+
"merge-action",
|
|
95
|
+
"merge-key",
|
|
96
|
+
"merge-source",
|
|
97
|
+
"next-iteration",
|
|
98
|
+
"on-completion",
|
|
99
|
+
"on-empty",
|
|
100
|
+
"on-non-empty",
|
|
101
|
+
"source-document",
|
|
102
|
+
"where-populated",
|
|
103
|
+
]);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Results of a transformation (XSLT 3.0 section 2.3.6, build-tree in
|
|
3
|
+
* Serialization 3.1 section 3): a result whose serialization parameters
|
|
4
|
+
* have build-tree "no" (the default of the json and adaptive methods) is
|
|
5
|
+
* the raw sequence the sequence constructor delivers, so that maps,
|
|
6
|
+
* arrays and atomic values reach the serializer as they are. Otherwise a
|
|
7
|
+
* result tree is built from it by sequence normalization: with an
|
|
8
|
+
* item-separator, the separator goes between all items.
|
|
9
|
+
*
|
|
10
|
+
* @module @tradik/xslt3/xslt/runtime/rawResults
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { normalizeSequence } from "../../serialize/sequence.js";
|
|
14
|
+
import { SequenceReceiver } from "./sequenceReceiver.js";
|
|
15
|
+
import { TreeReceiver } from "./treeReceiver.js";
|
|
16
|
+
|
|
17
|
+
/** Methods whose results are raw unless build-tree says otherwise. */
|
|
18
|
+
const RAW_METHODS = new Set(["json", "adaptive"]);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Whether a result with these serialization parameters is a tree.
|
|
22
|
+
* @param {object} [output] - Serialization parameters (spec names)
|
|
23
|
+
* @returns {boolean}
|
|
24
|
+
*/
|
|
25
|
+
export function buildsTree(output) {
|
|
26
|
+
const value = output?.["build-tree"];
|
|
27
|
+
if (typeof value === "boolean") return value;
|
|
28
|
+
if (typeof value === "string") return /^\s*(yes|true|1)\s*$/.test(value);
|
|
29
|
+
return !RAW_METHODS.has(output?.method);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A result tree from a raw sequence, normalized with an item separator.
|
|
34
|
+
* Nodes are copied, as the sequence may hold nodes of other trees.
|
|
35
|
+
* @param {Array} items
|
|
36
|
+
* @param {string} separator
|
|
37
|
+
* @param {DocumentFragment} fragment - Receives the tree
|
|
38
|
+
* @returns {DocumentFragment}
|
|
39
|
+
*/
|
|
40
|
+
function normalizedTree(items, separator, fragment) {
|
|
41
|
+
const document = fragment.ownerDocument;
|
|
42
|
+
for (const entry of normalizeSequence(items, separator)) {
|
|
43
|
+
fragment.appendChild(
|
|
44
|
+
typeof entry === "string"
|
|
45
|
+
? document.createTextNode(entry)
|
|
46
|
+
: document.importNode(entry, true),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return fragment;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The receiver of a result: a tree under a new document fragment, or a
|
|
54
|
+
* sequence for a raw result.
|
|
55
|
+
* @param {object} output - Serialization parameters
|
|
56
|
+
* @param {() => Document} owner - Owner document of the result's nodes
|
|
57
|
+
* @param {boolean} [buildTree] - Overrides build-tree (the `buildTree`
|
|
58
|
+
* option of the transformation)
|
|
59
|
+
* @returns {{receiver: object, value: () => (DocumentFragment|Array)}}
|
|
60
|
+
* the receiver and, once the result is complete, the fragment or the
|
|
61
|
+
* sequence
|
|
62
|
+
*/
|
|
63
|
+
export function resultReceiver(output, owner, buildTree) {
|
|
64
|
+
const separator = output?.["item-separator"];
|
|
65
|
+
const tree = buildTree ?? buildsTree(output);
|
|
66
|
+
if (!tree || separator !== undefined) {
|
|
67
|
+
const receiver = new SequenceReceiver(owner);
|
|
68
|
+
const value = tree
|
|
69
|
+
? () =>
|
|
70
|
+
normalizedTree(
|
|
71
|
+
receiver.items,
|
|
72
|
+
separator,
|
|
73
|
+
owner().createDocumentFragment(),
|
|
74
|
+
)
|
|
75
|
+
: () => receiver.items;
|
|
76
|
+
return { receiver, value };
|
|
77
|
+
}
|
|
78
|
+
const fragment = owner().createDocumentFragment();
|
|
79
|
+
const receiver = new TreeReceiver(fragment, new Map());
|
|
80
|
+
receiver.resultTree = true;
|
|
81
|
+
return { receiver, value: () => fragment };
|
|
82
|
+
}
|