@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,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base URIs of nodes: the base URI recorded for document nodes that
|
|
3
|
+
* differ from their document URI (the documents of fn:parse-xml and
|
|
4
|
+
* fn:parse-xml-fragment have the static base URI as base URI and no
|
|
5
|
+
* document URI) and for constructed nodes, and the base URI of any node
|
|
6
|
+
* from these and xml:base attributes.
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/functions/baseUris
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { parentOf } from "../xpath/eval/domNodes.js";
|
|
12
|
+
import { XML_NAMESPACE } from "../xpath/eval/namespaceNodes.js";
|
|
13
|
+
import { resolveUri } from "../xpath/eval/uris.js";
|
|
14
|
+
import { resolveUri as resolveReference } from "./uri.js";
|
|
15
|
+
|
|
16
|
+
/** @type {WeakMap<object, string>} */
|
|
17
|
+
const baseUris = new WeakMap();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Records the base URI of a document node.
|
|
21
|
+
* @param {Node} node
|
|
22
|
+
* @param {string|undefined} uri - Nothing is recorded when undefined
|
|
23
|
+
* @returns {Node} the node
|
|
24
|
+
*/
|
|
25
|
+
export function setBaseUri(node, uri) {
|
|
26
|
+
if (uri !== undefined) baseUris.set(node, uri);
|
|
27
|
+
return node;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {Node} node
|
|
32
|
+
* @returns {string|undefined} the base URI recorded for the node
|
|
33
|
+
*/
|
|
34
|
+
export const recordedBaseUri = (node) => baseUris.get(node);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* An xml:base attribute resolved against the base URI of the parent
|
|
38
|
+
* (RFC 3986: an absolute URI stays as written).
|
|
39
|
+
* @param {string} value
|
|
40
|
+
* @param {string|undefined} base
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
function resolveBase(value, base) {
|
|
44
|
+
try {
|
|
45
|
+
return base === undefined ? value : resolveReference(value, base);
|
|
46
|
+
} catch {
|
|
47
|
+
return resolveUri(value, base);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Base URI of a node: its xml:base attributes resolved against the
|
|
53
|
+
* document URI, or against the base URI recorded for a constructed node.
|
|
54
|
+
* Namespace nodes have none (XDM 3.1 section 6.6.2).
|
|
55
|
+
* @param {Node} node
|
|
56
|
+
* @returns {string|undefined}
|
|
57
|
+
*/
|
|
58
|
+
export function nodeBaseUri(node) {
|
|
59
|
+
if (node.nodeType === 13) return undefined;
|
|
60
|
+
const chain = [];
|
|
61
|
+
for (let n = node; n; n = parentOf(n)) chain.unshift(n);
|
|
62
|
+
let base;
|
|
63
|
+
for (const n of chain) {
|
|
64
|
+
const own =
|
|
65
|
+
recordedBaseUri(n) ??
|
|
66
|
+
(n.nodeType === 9 || n.nodeType === 11 ? documentUriOf(n) : undefined);
|
|
67
|
+
if (own !== undefined) base = own;
|
|
68
|
+
if (n.nodeType === 1 && n.hasAttributeNS(XML_NAMESPACE, "base")) {
|
|
69
|
+
base = resolveBase(n.getAttributeNS(XML_NAMESPACE, "base"), base);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return base;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param {Node} node - A document node
|
|
77
|
+
* @returns {string|undefined} its URI, undefined when unknown
|
|
78
|
+
*/
|
|
79
|
+
export function documentUriOf(node) {
|
|
80
|
+
const uri = node.documentURI ?? node.URL;
|
|
81
|
+
return uri && uri !== "about:blank" ? uri : undefined;
|
|
82
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collations (F&O 3.1 section 5.3): the Unicode codepoint collation, the
|
|
3
|
+
* HTML ASCII case-insensitive collation and the UCA collation family,
|
|
4
|
+
* which falls back to `Intl.Collator` (allowed by `fallback=yes`, the
|
|
5
|
+
* default).
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/functions/collations
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { XPathError } from "../errors.js";
|
|
11
|
+
import { compareCodepoints } from "../xdm/strings.js";
|
|
12
|
+
import { resolveUri } from "../xpath/eval/uris.js";
|
|
13
|
+
import { ucaCollation } from "./ucaCollation.js";
|
|
14
|
+
|
|
15
|
+
/** URI of the Unicode codepoint collation, the default collation. */
|
|
16
|
+
export const CODEPOINT_COLLATION =
|
|
17
|
+
"http://www.w3.org/2005/xpath-functions/collation/codepoint";
|
|
18
|
+
/** URI of the HTML ASCII case-insensitive collation. */
|
|
19
|
+
export const HTML_ASCII_COLLATION =
|
|
20
|
+
"http://www.w3.org/2005/xpath-functions/collation/html-ascii-case-insensitive";
|
|
21
|
+
const UCA_PREFIX = "http://www.w3.org/2013/collation/UCA";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A collation.
|
|
25
|
+
* @typedef {object} Collation
|
|
26
|
+
* @property {string} uri
|
|
27
|
+
* @property {(a: string, b: string) => number} compare - -1, 0 or 1
|
|
28
|
+
* @property {((s: string) => string)|null} key - Maps equal strings to the
|
|
29
|
+
* same key, with the same length (for hashing and substring matching);
|
|
30
|
+
* null when only `compare` is available
|
|
31
|
+
* @property {boolean} [substrings] - false when substring matching is not
|
|
32
|
+
* supported
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/** @param {string} s @returns {string} A-Z mapped to a-z */
|
|
36
|
+
const asciiLower = (s) => s.replace(/[A-Z]+/g, (m) => m.toLowerCase());
|
|
37
|
+
|
|
38
|
+
const codepoint = Object.freeze({
|
|
39
|
+
uri: CODEPOINT_COLLATION,
|
|
40
|
+
compare: compareCodepoints,
|
|
41
|
+
key: (s) => s,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const htmlAscii = Object.freeze({
|
|
45
|
+
uri: HTML_ASCII_COLLATION,
|
|
46
|
+
compare: (a, b) => compareCodepoints(asciiLower(a), asciiLower(b)),
|
|
47
|
+
key: asciiLower,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Finds the first substring of `text` that is equal to `search` under a
|
|
52
|
+
* collation (the shortest one at the leftmost position).
|
|
53
|
+
* @param {Collation} collation
|
|
54
|
+
* @param {string} text
|
|
55
|
+
* @param {string} search
|
|
56
|
+
* @param {"start"|"end"|null} [anchor] - Require a match at an end
|
|
57
|
+
* @returns {[number, number]|null} [start, end) offsets, null when absent
|
|
58
|
+
* @throws {XPathError} FOCH0004 for collations without substring matching
|
|
59
|
+
*/
|
|
60
|
+
export function findSubstring(collation, text, search, anchor = null) {
|
|
61
|
+
if (collation.substrings === false) {
|
|
62
|
+
throw new XPathError(
|
|
63
|
+
"FOCH0004",
|
|
64
|
+
`The collation ${collation.uri} does not support substring matching`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (collation.key) {
|
|
68
|
+
const a = collation.key(text);
|
|
69
|
+
const b = collation.key(search);
|
|
70
|
+
const index =
|
|
71
|
+
anchor === "start"
|
|
72
|
+
? a.startsWith(b)
|
|
73
|
+
? 0
|
|
74
|
+
: -1
|
|
75
|
+
: anchor === "end"
|
|
76
|
+
? a.endsWith(b)
|
|
77
|
+
? a.length - b.length
|
|
78
|
+
: -1
|
|
79
|
+
: a.indexOf(b);
|
|
80
|
+
return index < 0 ? null : [index, index + b.length];
|
|
81
|
+
}
|
|
82
|
+
const starts = anchor === "start" ? [0] : [...Array(text.length + 1).keys()];
|
|
83
|
+
for (const start of starts) {
|
|
84
|
+
const ends =
|
|
85
|
+
anchor === "end" ? [text.length] : [...Array(text.length + 1).keys()];
|
|
86
|
+
for (const end of ends.filter((e) => e >= start)) {
|
|
87
|
+
if (collation.compare(text.slice(start, end), search) === 0) {
|
|
88
|
+
return [start, end];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Resolves a collation URI.
|
|
97
|
+
* @param {string} [uri] - Collation URI, resolved against the static base
|
|
98
|
+
* URI when relative; the default collation when absent
|
|
99
|
+
* @param {{defaultCollation?: string, staticBaseUri?: string}} [context]
|
|
100
|
+
* @returns {Collation}
|
|
101
|
+
* @throws {XPathError} FOCH0002 for an unsupported collation
|
|
102
|
+
*/
|
|
103
|
+
export function getCollation(uri, context = {}) {
|
|
104
|
+
const relative = uri !== undefined && !/^[A-Za-z][A-Za-z0-9+.-]*:/.test(uri);
|
|
105
|
+
const name =
|
|
106
|
+
(relative && context.staticBaseUri
|
|
107
|
+
? resolveUri(uri, context.staticBaseUri)
|
|
108
|
+
: uri) ??
|
|
109
|
+
context.defaultCollation ??
|
|
110
|
+
CODEPOINT_COLLATION;
|
|
111
|
+
if (name === CODEPOINT_COLLATION) return codepoint;
|
|
112
|
+
if (name === HTML_ASCII_COLLATION) return htmlAscii;
|
|
113
|
+
if (name === UCA_PREFIX || name.startsWith(`${UCA_PREFIX}?`)) {
|
|
114
|
+
return ucaCollation(name);
|
|
115
|
+
}
|
|
116
|
+
throw new XPathError("FOCH0002", `Unsupported collation ${name}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The collation named by an optional xs:string argument.
|
|
121
|
+
* @param {Array<{value: string}>|undefined} sequence - The argument, or
|
|
122
|
+
* undefined for an arity without collation
|
|
123
|
+
* @param {object} context
|
|
124
|
+
* @returns {Collation}
|
|
125
|
+
*/
|
|
126
|
+
export const collationArg = (sequence, context) =>
|
|
127
|
+
getCollation(sequence?.[0]?.value, context);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* fn:collection and fn:uri-collection (F&O 3.1 sections 14.6.6 and
|
|
3
|
+
* 14.6.7), through the dynamic context hook `collection` (see
|
|
4
|
+
* xpath/eval/resources.js), and fn:collation-key (section 5.3.6).
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/functions/collections
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { XPathError } from "../errors.js";
|
|
10
|
+
import { AtomicValue, isNode } from "../xdm/atomic.js";
|
|
11
|
+
import { types } from "../xdm/types.js";
|
|
12
|
+
import { collationArg } from "./collations.js";
|
|
13
|
+
import { define } from "./support.js";
|
|
14
|
+
|
|
15
|
+
const encoder = new globalThis.TextEncoder();
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The items of a collection.
|
|
19
|
+
* @param {Array|undefined} uri - The optional argument
|
|
20
|
+
* @param {object} context
|
|
21
|
+
* @returns {Array}
|
|
22
|
+
*/
|
|
23
|
+
const items = (uri, context) => context.collection(uri?.[0]?.value ?? null);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The URIs of a collection: document URIs of its document nodes, atomic
|
|
27
|
+
* items (xs:anyURI) as they are; other nodes have no URI.
|
|
28
|
+
* @param {Array|undefined} uri
|
|
29
|
+
* @param {object} context
|
|
30
|
+
* @returns {Array} xs:anyURI values
|
|
31
|
+
*/
|
|
32
|
+
function uris(uri, context) {
|
|
33
|
+
const result = [];
|
|
34
|
+
for (const item of items(uri, context)) {
|
|
35
|
+
const text = isNode(item)
|
|
36
|
+
? item.nodeType === 9 && item.documentURI
|
|
37
|
+
: item.value;
|
|
38
|
+
if (text) result.push(new AtomicValue(types.anyURI, text));
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* fn:collation-key: the UTF-8 bytes of the collation key of a string,
|
|
45
|
+
* which order as the collation does (UTF-8 keeps the codepoint order).
|
|
46
|
+
* @param {string} text
|
|
47
|
+
* @param {import("./collations.js").Collation} collation
|
|
48
|
+
* @returns {AtomicValue} an xs:base64Binary
|
|
49
|
+
* @throws {XPathError} FOCH0002 for the UCA collations, whose keys
|
|
50
|
+
* Intl.Collator does not expose
|
|
51
|
+
*/
|
|
52
|
+
function collationKey(text, collation) {
|
|
53
|
+
if (!collation.key) {
|
|
54
|
+
throw new XPathError(
|
|
55
|
+
"FOCH0002",
|
|
56
|
+
`No collation keys for the collation ${collation.uri}`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return new AtomicValue(
|
|
60
|
+
types.base64Binary,
|
|
61
|
+
encoder.encode(collation.key(text)),
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Function definitions. */
|
|
66
|
+
export const collectionFunctions = [
|
|
67
|
+
define("collection", [], "item()*", (_, c) => items(undefined, c)),
|
|
68
|
+
define("collection", ["xs:string?"], "item()*", ([uri], c) => items(uri, c)),
|
|
69
|
+
define("uri-collection", [], "xs:anyURI*", (_, c) => uris(undefined, c)),
|
|
70
|
+
define("uri-collection", ["xs:string?"], "xs:anyURI*", ([uri], c) =>
|
|
71
|
+
uris(uri, c),
|
|
72
|
+
),
|
|
73
|
+
define("collation-key", ["xs:string"], "xs:base64Binary", ([[key]], c) => [
|
|
74
|
+
collationKey(key.value, collationArg(undefined, c)),
|
|
75
|
+
]),
|
|
76
|
+
define(
|
|
77
|
+
"collation-key",
|
|
78
|
+
["xs:string", "xs:string"],
|
|
79
|
+
"xs:base64Binary",
|
|
80
|
+
([[key], collation], c) => [
|
|
81
|
+
collationKey(key.value, collationArg(collation, c)),
|
|
82
|
+
],
|
|
83
|
+
),
|
|
84
|
+
];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functions on the dynamic context (F&O 3.1 section 15): the current date
|
|
3
|
+
* and time, the implicit timezone, the default collation and language,
|
|
4
|
+
* the static base URI. No environment variables are exposed to
|
|
5
|
+
* expressions (the set is implementation-dependent, and empty here).
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/functions/context
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { AtomicValue } from "../xdm/atomic.js";
|
|
11
|
+
import { DateTimeValue } from "../xdm/datetime.js";
|
|
12
|
+
import { Decimal } from "../xdm/decimal.js";
|
|
13
|
+
import { DurationValue } from "../xdm/duration.js";
|
|
14
|
+
import { types } from "../xdm/types.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The current date/time projected onto some components.
|
|
18
|
+
* @param {DateTimeValue} now
|
|
19
|
+
* @param {string[]} components
|
|
20
|
+
* @returns {DateTimeValue}
|
|
21
|
+
*/
|
|
22
|
+
function project(now, components) {
|
|
23
|
+
const fields = { timezone: now.timezone };
|
|
24
|
+
for (const name of components) fields[name] = now[name];
|
|
25
|
+
return new DateTimeValue(fields);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Definition of a function of the context without parameters.
|
|
30
|
+
* @param {string} local
|
|
31
|
+
* @param {string} returns
|
|
32
|
+
* @param {(context: object) => Array} impl
|
|
33
|
+
* @returns {object}
|
|
34
|
+
*/
|
|
35
|
+
const contextFunction = (local, returns, impl) => ({
|
|
36
|
+
local,
|
|
37
|
+
params: [],
|
|
38
|
+
returns,
|
|
39
|
+
impl: (_, context) => impl(context),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
/** Function definitions. */
|
|
43
|
+
export const contextFunctions = [
|
|
44
|
+
contextFunction("current-dateTime", "xs:dateTimeStamp", (c) => [
|
|
45
|
+
new AtomicValue(types.dateTime, c.currentDateTime),
|
|
46
|
+
]),
|
|
47
|
+
contextFunction("current-date", "xs:date", (c) => [
|
|
48
|
+
new AtomicValue(
|
|
49
|
+
types.date,
|
|
50
|
+
project(c.currentDateTime, ["year", "month", "day"]),
|
|
51
|
+
),
|
|
52
|
+
]),
|
|
53
|
+
contextFunction("current-time", "xs:time", (c) => [
|
|
54
|
+
new AtomicValue(
|
|
55
|
+
types.time,
|
|
56
|
+
project(c.currentDateTime, ["hour", "minute", "second"]),
|
|
57
|
+
),
|
|
58
|
+
]),
|
|
59
|
+
contextFunction("implicit-timezone", "xs:dayTimeDuration", (c) => [
|
|
60
|
+
new AtomicValue(
|
|
61
|
+
types.dayTimeDuration,
|
|
62
|
+
new DurationValue(0, Decimal.of(BigInt(c.implicitTimezone * 60))),
|
|
63
|
+
),
|
|
64
|
+
]),
|
|
65
|
+
contextFunction("default-collation", "xs:string", (c) => [
|
|
66
|
+
new AtomicValue(types.string, c.defaultCollation),
|
|
67
|
+
]),
|
|
68
|
+
contextFunction("default-language", "xs:language", (c) => [
|
|
69
|
+
new AtomicValue(types.language, c.defaultLanguage),
|
|
70
|
+
]),
|
|
71
|
+
contextFunction("available-environment-variables", "xs:string*", () => []),
|
|
72
|
+
{
|
|
73
|
+
local: "environment-variable",
|
|
74
|
+
params: ["xs:string"],
|
|
75
|
+
returns: "xs:string?",
|
|
76
|
+
impl: () => [],
|
|
77
|
+
},
|
|
78
|
+
contextFunction("static-base-uri", "xs:anyURI?", (c) =>
|
|
79
|
+
c.staticBaseUri === undefined
|
|
80
|
+
? []
|
|
81
|
+
: [new AtomicValue(types.anyURI, c.staticBaseUri)],
|
|
82
|
+
),
|
|
83
|
+
];
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The core functions of F&O 3.1 that depend on the evaluator: booleans,
|
|
3
|
+
* focus, string, data and number conversion, count, empty and exists.
|
|
4
|
+
* `coreFunctions` gathers these and the other modules of this package
|
|
5
|
+
* that depend on the evaluator or on the hooks of the dynamic context
|
|
6
|
+
* (nodes, higher-order functions, maps and arrays, JSON, resources,
|
|
7
|
+
* random numbers, IDs, collections).
|
|
8
|
+
*
|
|
9
|
+
* @module @tradik/xslt3/functions/core
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { toNumber } from "../xdm/generalCompare.js";
|
|
13
|
+
import { atomize, effectiveBooleanValue, stringValue } from "../xdm/nodes.js";
|
|
14
|
+
import {
|
|
15
|
+
booleanItem,
|
|
16
|
+
doubleItem,
|
|
17
|
+
integerItem,
|
|
18
|
+
stringItem,
|
|
19
|
+
} from "../xpath/eval/atomics.js";
|
|
20
|
+
import { arrayFunctions } from "./arrays.js";
|
|
21
|
+
import { contextFunctions } from "./context.js";
|
|
22
|
+
import { higherOrderFunctions } from "./higherOrder.js";
|
|
23
|
+
import { coreStringFunctions, libraryFunctions } from "./library.js";
|
|
24
|
+
import { mapFunctions } from "./maps.js";
|
|
25
|
+
import { nodeFunctions } from "./nodes.js";
|
|
26
|
+
import { focusItem } from "./focus.js";
|
|
27
|
+
import { diagnosticFunctions } from "./diagnostics.js";
|
|
28
|
+
import { collectionFunctions } from "./collections.js";
|
|
29
|
+
import { idFunctions } from "./ids.js";
|
|
30
|
+
import { jsonFunctions } from "./json/index.js";
|
|
31
|
+
import { parseXmlFunctions } from "./parseXml.js";
|
|
32
|
+
import { randomFunctions } from "./random.js";
|
|
33
|
+
import { unparsedTextFunctions } from "./unparsedText.js";
|
|
34
|
+
import { xqueryModuleFunctions } from "./xqueryModule.js";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* fn:string of an optional item.
|
|
38
|
+
* @param {Array} arg
|
|
39
|
+
* @returns {Array} an xs:string
|
|
40
|
+
*/
|
|
41
|
+
const stringOf = (arg) => [stringItem(arg.length ? stringValue(arg[0]) : "")];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* fn:number of an optional atomic value.
|
|
45
|
+
* @param {Array} arg
|
|
46
|
+
* @returns {Array} an xs:double
|
|
47
|
+
*/
|
|
48
|
+
const numberOf = (arg) => [arg.length ? toNumber(arg[0]) : doubleItem(NaN)];
|
|
49
|
+
|
|
50
|
+
/** Core function definitions. */
|
|
51
|
+
export const coreBasics = [
|
|
52
|
+
{
|
|
53
|
+
local: "true",
|
|
54
|
+
params: [],
|
|
55
|
+
returns: "xs:boolean",
|
|
56
|
+
impl: () => [booleanItem(true)],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
local: "false",
|
|
60
|
+
params: [],
|
|
61
|
+
returns: "xs:boolean",
|
|
62
|
+
impl: () => [booleanItem(false)],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
local: "not",
|
|
66
|
+
params: ["item()*"],
|
|
67
|
+
returns: "xs:boolean",
|
|
68
|
+
impl: ([arg]) => [booleanItem(!effectiveBooleanValue(arg))],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
local: "boolean",
|
|
72
|
+
params: ["item()*"],
|
|
73
|
+
returns: "xs:boolean",
|
|
74
|
+
impl: ([arg]) => [booleanItem(effectiveBooleanValue(arg))],
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
local: "position",
|
|
78
|
+
params: [],
|
|
79
|
+
returns: "xs:integer",
|
|
80
|
+
focus: true,
|
|
81
|
+
impl: (_, context) => (focusItem(context), [integerItem(context.position)]),
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
local: "last",
|
|
85
|
+
params: [],
|
|
86
|
+
returns: "xs:integer",
|
|
87
|
+
focus: true,
|
|
88
|
+
impl: (_, context) => (focusItem(context), [integerItem(context.size)]),
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
local: "string",
|
|
92
|
+
params: [],
|
|
93
|
+
returns: "xs:string",
|
|
94
|
+
focus: true,
|
|
95
|
+
impl: (_, context) => stringOf([focusItem(context)]),
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
local: "string",
|
|
99
|
+
params: ["item()?"],
|
|
100
|
+
returns: "xs:string",
|
|
101
|
+
impl: ([arg]) => stringOf(arg),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
local: "data",
|
|
105
|
+
params: [],
|
|
106
|
+
returns: "xs:anyAtomicType*",
|
|
107
|
+
focus: true,
|
|
108
|
+
impl: (_, context) => atomize([focusItem(context)]),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
local: "data",
|
|
112
|
+
params: ["item()*"],
|
|
113
|
+
returns: "xs:anyAtomicType*",
|
|
114
|
+
impl: ([arg]) => atomize(arg),
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
local: "number",
|
|
118
|
+
params: [],
|
|
119
|
+
returns: "xs:double",
|
|
120
|
+
focus: true,
|
|
121
|
+
impl: (_, context) => numberOf(atomize([focusItem(context)])),
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
local: "number",
|
|
125
|
+
params: ["xs:anyAtomicType?"],
|
|
126
|
+
returns: "xs:double",
|
|
127
|
+
impl: ([arg]) => numberOf(arg),
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
local: "count",
|
|
131
|
+
params: ["item()*"],
|
|
132
|
+
returns: "xs:integer",
|
|
133
|
+
impl: ([arg]) => [integerItem(arg.length)],
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
local: "empty",
|
|
137
|
+
params: ["item()*"],
|
|
138
|
+
returns: "xs:boolean",
|
|
139
|
+
impl: ([arg]) => [booleanItem(arg.length === 0)],
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
local: "exists",
|
|
143
|
+
params: ["item()*"],
|
|
144
|
+
returns: "xs:boolean",
|
|
145
|
+
impl: ([arg]) => [booleanItem(arg.length > 0)],
|
|
146
|
+
},
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
/** All the function definitions of this package's built-in modules. */
|
|
150
|
+
export const coreFunctions = [
|
|
151
|
+
...libraryFunctions,
|
|
152
|
+
...coreStringFunctions,
|
|
153
|
+
...coreBasics,
|
|
154
|
+
...diagnosticFunctions,
|
|
155
|
+
...contextFunctions,
|
|
156
|
+
...nodeFunctions,
|
|
157
|
+
...higherOrderFunctions,
|
|
158
|
+
...mapFunctions,
|
|
159
|
+
...arrayFunctions,
|
|
160
|
+
...jsonFunctions,
|
|
161
|
+
...unparsedTextFunctions,
|
|
162
|
+
...xqueryModuleFunctions,
|
|
163
|
+
...parseXmlFunctions,
|
|
164
|
+
...randomFunctions,
|
|
165
|
+
...idFunctions,
|
|
166
|
+
...collectionFunctions,
|
|
167
|
+
];
|