@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,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output encodings: which characters an encoding can represent (the others
|
|
3
|
+
* are written as character references, or are an error where references
|
|
4
|
+
* are not possible) and the conversion of the serialized string to bytes.
|
|
5
|
+
*
|
|
6
|
+
* Supported: UTF-8, UTF-16 (big-endian, or UTF-16BE/UTF-16LE), ISO-8859-1,
|
|
7
|
+
* US-ASCII, and the single-byte encodings of the WHATWG Encoding Standard
|
|
8
|
+
* that the platform's TextDecoder knows (windows-1252, ISO-8859-2, KOI8-R,
|
|
9
|
+
* ...). Other encodings are a SESU0007 error.
|
|
10
|
+
*
|
|
11
|
+
* @module @tradik/xslt3/serialize/output/encoding
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { XPathError } from "../../errors.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} Encoding
|
|
18
|
+
* @property {string} name - The name as requested (written in the XML
|
|
19
|
+
* declaration and the HTML content type)
|
|
20
|
+
* @property {string} kind - "utf-8", "utf-16be", "utf-16le" or "single-byte"
|
|
21
|
+
* @property {((codePoint: number) => boolean)|null} encodable - null when
|
|
22
|
+
* every character can be encoded
|
|
23
|
+
* @property {Map<number, number>} [table] - Code point to byte
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const ALIASES = {
|
|
27
|
+
"utf-8": "utf-8",
|
|
28
|
+
utf8: "utf-8",
|
|
29
|
+
"utf-16": "utf-16be",
|
|
30
|
+
utf16: "utf-16be",
|
|
31
|
+
"utf-16be": "utf-16be",
|
|
32
|
+
"utf-16le": "utf-16le",
|
|
33
|
+
"iso-8859-1": "latin1",
|
|
34
|
+
iso_8859_1: "latin1",
|
|
35
|
+
"iso_8859-1": "latin1",
|
|
36
|
+
latin1: "latin1",
|
|
37
|
+
l1: "latin1",
|
|
38
|
+
"us-ascii": "ascii",
|
|
39
|
+
ascii: "ascii",
|
|
40
|
+
"iso-646": "ascii",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** Canonical names of the WHATWG single-byte encodings. */
|
|
44
|
+
const SINGLE_BYTE = new Set([
|
|
45
|
+
"ibm866",
|
|
46
|
+
"koi8-r",
|
|
47
|
+
"koi8-u",
|
|
48
|
+
"macintosh",
|
|
49
|
+
"windows-874",
|
|
50
|
+
"x-mac-cyrillic",
|
|
51
|
+
...[2, 3, 4, 5, 6, 7, 8, 10, 13, 14, 15, 16].map((n) => `iso-8859-${n}`),
|
|
52
|
+
...[0, 1, 2, 3, 4, 5, 6, 7, 8].map((n) => `windows-125${n}`),
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
/** What a decoder returns for a byte it does not map. */
|
|
56
|
+
const REPLACEMENT_CHARACTER = String.fromCharCode(0xfffd);
|
|
57
|
+
|
|
58
|
+
/** @type {Map<string, Map<number, number>>} tables by canonical name */
|
|
59
|
+
const tables = new Map();
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Code point to byte table of a single-byte encoding, from the platform
|
|
63
|
+
* decoder.
|
|
64
|
+
* @param {string} canonical - Canonical WHATWG name
|
|
65
|
+
* @returns {Map<number, number>}
|
|
66
|
+
*/
|
|
67
|
+
function singleByteTable(canonical) {
|
|
68
|
+
let table = tables.get(canonical);
|
|
69
|
+
if (!table) {
|
|
70
|
+
const decoder = new globalThis.TextDecoder(canonical);
|
|
71
|
+
table = new Map();
|
|
72
|
+
for (let byte = 0; byte < 256; byte++) {
|
|
73
|
+
const char = decoder.decode(Uint8Array.of(byte));
|
|
74
|
+
if (char !== REPLACEMENT_CHARACTER) table.set(char.codePointAt(0), byte);
|
|
75
|
+
}
|
|
76
|
+
tables.set(canonical, table);
|
|
77
|
+
}
|
|
78
|
+
return table;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The canonical WHATWG name of an encoding label, or null.
|
|
83
|
+
* @param {string} label
|
|
84
|
+
* @returns {string|null}
|
|
85
|
+
*/
|
|
86
|
+
function whatwgName(label) {
|
|
87
|
+
try {
|
|
88
|
+
return new globalThis.TextDecoder(label).encoding;
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Resolves the encoding parameter.
|
|
96
|
+
* @param {string} name - Encoding name, case-insensitive
|
|
97
|
+
* @returns {Encoding}
|
|
98
|
+
* @throws {XPathError} SESU0007 when the encoding is not supported
|
|
99
|
+
*/
|
|
100
|
+
export function resolveEncoding(name) {
|
|
101
|
+
const alias = ALIASES[name.trim().toLowerCase()];
|
|
102
|
+
if (alias === "latin1" || alias === "ascii") {
|
|
103
|
+
const limit = alias === "latin1" ? 0xff : 0x7f;
|
|
104
|
+
return { name, kind: "single-byte", encodable: (cp) => cp <= limit };
|
|
105
|
+
}
|
|
106
|
+
if (alias) return { name, kind: alias, encodable: null };
|
|
107
|
+
const canonical = whatwgName(name.trim());
|
|
108
|
+
if (canonical === null || !SINGLE_BYTE.has(canonical)) {
|
|
109
|
+
throw new XPathError("SESU0007", `Unsupported encoding ${name}`);
|
|
110
|
+
}
|
|
111
|
+
const table = singleByteTable(canonical);
|
|
112
|
+
return { name, kind: "single-byte", encodable: (cp) => table.has(cp), table };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** U+FEFF, written first with byte-order-mark. */
|
|
116
|
+
const BYTE_ORDER_MARK = String.fromCharCode(0xfeff);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Encodes serialized text (already free of unencodable characters).
|
|
120
|
+
* @param {string} text
|
|
121
|
+
* @param {Encoding} encoding
|
|
122
|
+
* @param {boolean} byteOrderMark - Start with the byte order mark (UTF-8
|
|
123
|
+
* and UTF-16 only)
|
|
124
|
+
* @returns {Uint8Array}
|
|
125
|
+
*/
|
|
126
|
+
export function encodeText(text, encoding, byteOrderMark) {
|
|
127
|
+
const { kind } = encoding;
|
|
128
|
+
const content =
|
|
129
|
+
byteOrderMark && kind !== "single-byte" ? BYTE_ORDER_MARK + text : text;
|
|
130
|
+
if (kind === "utf-8") return new globalThis.TextEncoder().encode(content);
|
|
131
|
+
if (kind === "single-byte") {
|
|
132
|
+
const bytes = new Uint8Array(content.length);
|
|
133
|
+
for (let i = 0; i < content.length; i++) {
|
|
134
|
+
const cp = content.charCodeAt(i);
|
|
135
|
+
bytes[i] = encoding.table ? encoding.table.get(cp) : cp;
|
|
136
|
+
}
|
|
137
|
+
return bytes;
|
|
138
|
+
}
|
|
139
|
+
const bytes = new Uint8Array(content.length * 2);
|
|
140
|
+
const view = new DataView(bytes.buffer);
|
|
141
|
+
const littleEndian = kind === "utf-16le";
|
|
142
|
+
for (let i = 0; i < content.length; i++) {
|
|
143
|
+
view.setUint16(i * 2, content.charCodeAt(i), littleEndian);
|
|
144
|
+
}
|
|
145
|
+
return bytes;
|
|
146
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Character expansion (Serialization 3.1 section 4, phase 2): character
|
|
3
|
+
* maps, Unicode normalization, escaping of the characters markup gives a
|
|
4
|
+
* meaning to, and character references for the characters the encoding
|
|
5
|
+
* cannot represent. A character replaced by a character map is written as
|
|
6
|
+
* it is mapped: it is neither normalized nor escaped.
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/serialize/output/expander
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { XPathError } from "../../errors.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {number} codePoint
|
|
15
|
+
* @returns {string} a hexadecimal character reference, e.g. "é"
|
|
16
|
+
*/
|
|
17
|
+
export const characterReference = (codePoint) =>
|
|
18
|
+
`&#x${codePoint.toString(16).toUpperCase()};`;
|
|
19
|
+
|
|
20
|
+
const NAMED = { "&": "&", "<": "<", ">": ">", '"': """ };
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Characters escaped in each context. XML escapes CR, NEL, LINE
|
|
24
|
+
* SEPARATOR, DEL and the C1 controls as references, attributes also tab
|
|
25
|
+
* and newline (which attribute value normalization would turn into
|
|
26
|
+
* spaces); the other C0 controls are only allowed, as references, in XML
|
|
27
|
+
* 1.1. HTML attributes keep "&{" (a script macro) and "<" unescaped.
|
|
28
|
+
*/
|
|
29
|
+
const C0 = "\\u0001-\\u0008\\u000B\\u000C\\u000E-\\u001F";
|
|
30
|
+
const C1 = "\\u007F-\\u009F\\u2028";
|
|
31
|
+
const PATTERNS = {
|
|
32
|
+
xmlText: `[&<>\\r${C0}${C1}]`,
|
|
33
|
+
xmlAttribute: `[&<>"\\t\\n\\r${C0}${C1}]`,
|
|
34
|
+
htmlText: "[&<>]",
|
|
35
|
+
htmlAttribute: '&(?!\\{)|"',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Expands characters for one serialization. */
|
|
39
|
+
export class Expander {
|
|
40
|
+
/**
|
|
41
|
+
* @param {import("../params/settings.js").Settings} settings
|
|
42
|
+
*/
|
|
43
|
+
constructor(settings) {
|
|
44
|
+
this.map = settings.useCharacterMaps;
|
|
45
|
+
this.form =
|
|
46
|
+
settings.normalizationForm === "none" ? null : settings.normalizationForm;
|
|
47
|
+
this.encodable = settings.encoding.encodable;
|
|
48
|
+
this.xml11 = settings.version === "1.1";
|
|
49
|
+
this.html = settings.method === "html";
|
|
50
|
+
const restricted = this.encodable ? "|[^\\u0000-\\u007F]" : "";
|
|
51
|
+
const compile = (name) => new RegExp(PATTERNS[name] + restricted, "gu");
|
|
52
|
+
this.textPattern = compile(this.html ? "htmlText" : "xmlText");
|
|
53
|
+
this.attributePattern = compile(
|
|
54
|
+
this.html ? "htmlAttribute" : "xmlAttribute",
|
|
55
|
+
);
|
|
56
|
+
this.replace = (char) => this.replacement(char);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The escaped form of a character matched by a pattern.
|
|
61
|
+
* @param {string} char
|
|
62
|
+
* @returns {string}
|
|
63
|
+
*/
|
|
64
|
+
replacement(char) {
|
|
65
|
+
const named = NAMED[char];
|
|
66
|
+
if (named) return named;
|
|
67
|
+
const cp = char.codePointAt(0);
|
|
68
|
+
if (cp < 0x20 && cp !== 9 && cp !== 10 && cp !== 13 && !this.xml11) {
|
|
69
|
+
throw new XPathError(
|
|
70
|
+
"SERE0006",
|
|
71
|
+
`Character #x${cp.toString(16)} is not allowed in XML 1.0`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (cp < 0xa0 || cp === 0x2028 || !this.encodable(cp)) {
|
|
75
|
+
return characterReference(cp);
|
|
76
|
+
}
|
|
77
|
+
return char;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Splits text into the runs of unmapped characters (normalized and
|
|
82
|
+
* passed to `write`) and the replacements of mapped ones (kept as they
|
|
83
|
+
* are).
|
|
84
|
+
* @param {string} text
|
|
85
|
+
* @param {(run: string) => string} write - Expands an unmapped run
|
|
86
|
+
* @returns {string}
|
|
87
|
+
*/
|
|
88
|
+
mapped(text, write) {
|
|
89
|
+
const expand = (run) => write(this.form ? run.normalize(this.form) : run);
|
|
90
|
+
if (!this.map) return expand(text);
|
|
91
|
+
let result = "";
|
|
92
|
+
let run = "";
|
|
93
|
+
for (const char of text) {
|
|
94
|
+
const replacement = this.map.get(char);
|
|
95
|
+
if (replacement === undefined) {
|
|
96
|
+
run += char;
|
|
97
|
+
} else {
|
|
98
|
+
if (run) result += expand(run);
|
|
99
|
+
result += replacement;
|
|
100
|
+
run = "";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return run ? result + expand(run) : result;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Checks the characters of HTML output (SERE0014: C1 controls).
|
|
108
|
+
* @param {string} text
|
|
109
|
+
*/
|
|
110
|
+
checkHtml(text) {
|
|
111
|
+
if (this.html && /[\u007F-\u009F]/.test(text)) {
|
|
112
|
+
throw new XPathError(
|
|
113
|
+
"SERE0014",
|
|
114
|
+
"The HTML output method cannot write the characters #x7F to #x9F",
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* @param {string} text - Content of a text node
|
|
121
|
+
* @returns {string} escaped character data
|
|
122
|
+
*/
|
|
123
|
+
text(text) {
|
|
124
|
+
this.checkHtml(text);
|
|
125
|
+
return this.mapped(text, (run) =>
|
|
126
|
+
run.replace(this.textPattern, this.replace),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @param {string} value - Attribute value
|
|
132
|
+
* @returns {string} the escaped value, to be written between quotes
|
|
133
|
+
*/
|
|
134
|
+
attribute(value) {
|
|
135
|
+
this.checkHtml(value);
|
|
136
|
+
return this.mapped(value, (run) =>
|
|
137
|
+
run.replace(this.attributePattern, this.replace),
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Text written as CDATA sections; a mapped or unencodable character
|
|
143
|
+
* ends the section, and "]]>" is split across two sections.
|
|
144
|
+
* @param {string} text
|
|
145
|
+
* @returns {string}
|
|
146
|
+
*/
|
|
147
|
+
cdata(text) {
|
|
148
|
+
return this.mapped(text, (run) => {
|
|
149
|
+
let result = "";
|
|
150
|
+
let section = "";
|
|
151
|
+
const flush = () => {
|
|
152
|
+
if (section) {
|
|
153
|
+
const safe = section.replaceAll("]]>", "]]]]><![CDATA[>");
|
|
154
|
+
result += `<![CDATA[${safe}]]>`;
|
|
155
|
+
}
|
|
156
|
+
section = "";
|
|
157
|
+
};
|
|
158
|
+
for (const char of run) {
|
|
159
|
+
const cp = char.codePointAt(0);
|
|
160
|
+
if (this.encodable && !this.encodable(cp)) {
|
|
161
|
+
flush();
|
|
162
|
+
result += characterReference(cp);
|
|
163
|
+
} else {
|
|
164
|
+
section += char;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
flush();
|
|
168
|
+
return result;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Text written without escaping (HTML script and style content, the
|
|
174
|
+
* text output method): character maps and normalization only.
|
|
175
|
+
* @param {string} text
|
|
176
|
+
* @returns {string}
|
|
177
|
+
* @throws {XPathError} SERE0008 for characters the encoding lacks
|
|
178
|
+
*/
|
|
179
|
+
raw(text) {
|
|
180
|
+
this.checkHtml(text);
|
|
181
|
+
return this.mapped(text, (run) => this.unescaped(run));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Text written as it is, which must be encodable: names, comments,
|
|
186
|
+
* processing instructions, unescaped text.
|
|
187
|
+
* @param {string} text
|
|
188
|
+
* @returns {string}
|
|
189
|
+
* @throws {XPathError} SERE0008 for characters the encoding lacks
|
|
190
|
+
*/
|
|
191
|
+
unescaped(text) {
|
|
192
|
+
if (this.encodable) {
|
|
193
|
+
for (const char of text) {
|
|
194
|
+
if (!this.encodable(char.codePointAt(0))) {
|
|
195
|
+
throw new XPathError(
|
|
196
|
+
"SERE0008",
|
|
197
|
+
`Character ${char} cannot be written in the output encoding`,
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return text;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialization parameters given as an `output:serialization-parameters`
|
|
3
|
+
* element (Serialization 3.1 section 3.1), as fn:serialize accepts them.
|
|
4
|
+
*
|
|
5
|
+
* Errors: XPTY0004 when the element is not output:serialization-parameters,
|
|
6
|
+
* SEPM0017 for an invalid element (unknown output:* parameter, element in
|
|
7
|
+
* no namespace, unknown attribute, invalid value), SEPM0018 for a
|
|
8
|
+
* character mapped twice, SEPM0019 for a parameter given twice. Elements
|
|
9
|
+
* in other namespaces are extension parameters, ignored.
|
|
10
|
+
*
|
|
11
|
+
* @module @tradik/xslt3/serialize/params/fromElement
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { compareCodepoints } from "../../xdm/strings.js";
|
|
15
|
+
import { XPathError } from "../../errors.js";
|
|
16
|
+
import { isNamespaceDeclaration } from "../../xpath/eval/domNodes.js";
|
|
17
|
+
import { inScopeNamespaces } from "../../xpath/eval/namespaceNodes.js";
|
|
18
|
+
import { OUTPUT_NAMESPACE, PARAMETER_KINDS } from "./names.js";
|
|
19
|
+
import { clarkName, CONVERTERS } from "./values.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} message
|
|
23
|
+
* @returns {XPathError} SEPM0017
|
|
24
|
+
*/
|
|
25
|
+
const invalid = (message) => new XPathError("SEPM0017", message);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @param {Element} element
|
|
29
|
+
* @returns {string[]} local names of its attributes in no namespace
|
|
30
|
+
*/
|
|
31
|
+
function plainAttributes(element) {
|
|
32
|
+
const names = [];
|
|
33
|
+
for (const attribute of element.attributes) {
|
|
34
|
+
if (!isNamespaceDeclaration(attribute) && !attribute.namespaceURI) {
|
|
35
|
+
names.push(attribute.localName ?? attribute.name);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return names;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {Element} element
|
|
43
|
+
* @returns {Element[]} its element children
|
|
44
|
+
*/
|
|
45
|
+
function elementChildren(element) {
|
|
46
|
+
const children = [];
|
|
47
|
+
for (let child = element.firstChild; child; child = child.nextSibling) {
|
|
48
|
+
if (child.nodeType === 1) children.push(child);
|
|
49
|
+
}
|
|
50
|
+
return children;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Reads the character map of output:use-character-maps.
|
|
55
|
+
* @param {Element} element
|
|
56
|
+
* @returns {Map<string, string>}
|
|
57
|
+
*/
|
|
58
|
+
function characterMap(element) {
|
|
59
|
+
const map = new Map();
|
|
60
|
+
for (const child of elementChildren(element)) {
|
|
61
|
+
const attributes = plainAttributes(child).sort(compareCodepoints).join(" ");
|
|
62
|
+
if (
|
|
63
|
+
child.namespaceURI !== OUTPUT_NAMESPACE ||
|
|
64
|
+
child.localName !== "character-map" ||
|
|
65
|
+
attributes !== "character map-string"
|
|
66
|
+
) {
|
|
67
|
+
throw invalid("Invalid content of output:use-character-maps");
|
|
68
|
+
}
|
|
69
|
+
const character = child.getAttribute("character");
|
|
70
|
+
if ([...character].length !== 1) {
|
|
71
|
+
throw invalid(`Not a single character: ${character}`);
|
|
72
|
+
}
|
|
73
|
+
if (map.has(character)) {
|
|
74
|
+
throw new XPathError("SEPM0018", `Character ${character} mapped twice`);
|
|
75
|
+
}
|
|
76
|
+
map.set(character, child.getAttribute("map-string"));
|
|
77
|
+
}
|
|
78
|
+
return map;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Reads one parameter element.
|
|
83
|
+
* @param {Element} element - output:* parameter element
|
|
84
|
+
* @param {string} name - Its local name
|
|
85
|
+
* @returns {*} the converted value
|
|
86
|
+
*/
|
|
87
|
+
function parameterValue(element, name) {
|
|
88
|
+
const attributes = plainAttributes(element);
|
|
89
|
+
if (name === "use-character-maps") {
|
|
90
|
+
if (attributes.length) throw invalid(`Attributes on output:${name}`);
|
|
91
|
+
return characterMap(element);
|
|
92
|
+
}
|
|
93
|
+
if (attributes.join(" ") !== "value") {
|
|
94
|
+
throw invalid(`output:${name} needs exactly a value attribute`);
|
|
95
|
+
}
|
|
96
|
+
const value = element.getAttribute("value");
|
|
97
|
+
const bindings = inScopeNamespaces(element);
|
|
98
|
+
const resolve = (prefix) => bindings.get(prefix);
|
|
99
|
+
try {
|
|
100
|
+
return CONVERTERS[PARAMETER_KINDS[name]](name, value, resolve);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
throw invalid(error.message);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Reads serialization parameters from an element.
|
|
108
|
+
* @param {Element} element - An output:serialization-parameters element
|
|
109
|
+
* @returns {Record<string, *>} parameters by hyphenated name
|
|
110
|
+
*/
|
|
111
|
+
export function parametersFromElement(element) {
|
|
112
|
+
if (
|
|
113
|
+
element.nodeType !== 1 ||
|
|
114
|
+
element.namespaceURI !== OUTPUT_NAMESPACE ||
|
|
115
|
+
element.localName !== "serialization-parameters"
|
|
116
|
+
) {
|
|
117
|
+
throw new XPathError(
|
|
118
|
+
"XPTY0004",
|
|
119
|
+
"Serialization parameters must be an output:serialization-parameters element",
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
if (plainAttributes(element).length) {
|
|
123
|
+
throw invalid("Attributes on output:serialization-parameters");
|
|
124
|
+
}
|
|
125
|
+
const params = {};
|
|
126
|
+
const seen = new Set();
|
|
127
|
+
for (const child of elementChildren(element)) {
|
|
128
|
+
const namespace = child.namespaceURI ?? "";
|
|
129
|
+
const local = child.localName;
|
|
130
|
+
const key = clarkName(namespace, local);
|
|
131
|
+
if (seen.has(key)) {
|
|
132
|
+
throw new XPathError("SEPM0019", `Parameter ${local} given twice`);
|
|
133
|
+
}
|
|
134
|
+
seen.add(key);
|
|
135
|
+
if (namespace === "") throw invalid(`Parameter ${local} in no namespace`);
|
|
136
|
+
if (namespace !== OUTPUT_NAMESPACE) continue;
|
|
137
|
+
if (!PARAMETER_KINDS[local]) throw invalid(`Unknown parameter ${local}`);
|
|
138
|
+
params[local] = parameterValue(child, local);
|
|
139
|
+
}
|
|
140
|
+
return params;
|
|
141
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialization parameters given as a map (F&O 3.1 section 14.6.3): the
|
|
3
|
+
* keys are parameter names (xs:string), the values are converted to the
|
|
4
|
+
* type of each parameter with the function conversion rules (XPTY0004
|
|
5
|
+
* when they do not fit). Entries with other keys (QNames, unknown names)
|
|
6
|
+
* are ignored.
|
|
7
|
+
*
|
|
8
|
+
* | Kind | Type |
|
|
9
|
+
* |--------------|----------------------------|
|
|
10
|
+
* | boolean | xs:boolean? |
|
|
11
|
+
* | string | xs:string? |
|
|
12
|
+
* | decimal | xs:decimal? |
|
|
13
|
+
* | qnames | xs:QName* |
|
|
14
|
+
* | method | (xs:string \| xs:QName)? |
|
|
15
|
+
* | standalone | xs:boolean? (empty: omit) |
|
|
16
|
+
* | characterMap | map(xs:string, xs:string)? |
|
|
17
|
+
*
|
|
18
|
+
* @module @tradik/xslt3/serialize/params/fromMap
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { XPathError } from "../../errors.js";
|
|
22
|
+
import { atomize, cast, derivesFrom, isMap } from "../../xdm/index.js";
|
|
23
|
+
import { PARAMETER_KINDS } from "./names.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {string} name
|
|
27
|
+
* @returns {XPathError} XPTY0004
|
|
28
|
+
*/
|
|
29
|
+
const wrongType = (name) =>
|
|
30
|
+
new XPathError("XPTY0004", `Wrong type for serialization parameter ${name}`);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {import("../../xdm/atomic.js").AtomicValue} item
|
|
34
|
+
* @param {string} type - Local name of an xs: type
|
|
35
|
+
* @returns {boolean} whether the item is an instance of the type
|
|
36
|
+
*/
|
|
37
|
+
const isA = (item, type) => derivesFrom(item.type, type);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Converts one atomic value to a type: instances are kept, untyped values
|
|
41
|
+
* are cast, xs:anyURI is promoted to xs:string.
|
|
42
|
+
* @param {string} name - Parameter name
|
|
43
|
+
* @param {import("../../xdm/atomic.js").AtomicValue} item
|
|
44
|
+
* @param {string} type
|
|
45
|
+
* @returns {*} the value
|
|
46
|
+
*/
|
|
47
|
+
function convertAtomic(name, item, type) {
|
|
48
|
+
if (isA(item, type)) return item.value;
|
|
49
|
+
if (type === "string" && isA(item, "anyURI")) return item.value;
|
|
50
|
+
if (isA(item, "untypedAtomic") && type !== "QName") {
|
|
51
|
+
try {
|
|
52
|
+
return cast(item, type).value;
|
|
53
|
+
} catch {
|
|
54
|
+
throw wrongType(name);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
throw wrongType(name);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} name
|
|
62
|
+
* @param {Array} value
|
|
63
|
+
* @returns {Map<string, string>} the character map
|
|
64
|
+
*/
|
|
65
|
+
function characterMapValue(name, value) {
|
|
66
|
+
if (value.length !== 1 || !isMap(value[0])) throw wrongType(name);
|
|
67
|
+
const map = new Map();
|
|
68
|
+
for (const { key, value: replacement } of value[0].entries.values()) {
|
|
69
|
+
const [item] = replacement;
|
|
70
|
+
if (
|
|
71
|
+
!isA(key, "string") ||
|
|
72
|
+
replacement.length !== 1 ||
|
|
73
|
+
!isA(item, "string")
|
|
74
|
+
) {
|
|
75
|
+
throw wrongType(name);
|
|
76
|
+
}
|
|
77
|
+
map.set(key.value, item.value);
|
|
78
|
+
}
|
|
79
|
+
return map;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Converts the value of one parameter.
|
|
84
|
+
* @param {string} name - Parameter name
|
|
85
|
+
* @param {Array} value - Entry value
|
|
86
|
+
* @returns {*} the value for the API, undefined when absent
|
|
87
|
+
*/
|
|
88
|
+
function parameterValue(name, value) {
|
|
89
|
+
const kind = PARAMETER_KINDS[name];
|
|
90
|
+
if (kind === "characterMap") {
|
|
91
|
+
return value.length ? characterMapValue(name, value) : undefined;
|
|
92
|
+
}
|
|
93
|
+
const items = atomize(value);
|
|
94
|
+
if (kind === "qnames") {
|
|
95
|
+
return items.map((item) => convertAtomic(name, item, "QName"));
|
|
96
|
+
}
|
|
97
|
+
if (items.length > 1) throw wrongType(name);
|
|
98
|
+
if (!items.length) return kind === "standalone" ? null : undefined;
|
|
99
|
+
const [item] = items;
|
|
100
|
+
switch (kind) {
|
|
101
|
+
case "boolean":
|
|
102
|
+
case "standalone":
|
|
103
|
+
return convertAtomic(name, item, "boolean");
|
|
104
|
+
case "decimal":
|
|
105
|
+
return convertAtomic(name, item, "decimal");
|
|
106
|
+
case "method":
|
|
107
|
+
return isA(item, "QName")
|
|
108
|
+
? item.value
|
|
109
|
+
: convertAtomic(name, item, "string");
|
|
110
|
+
default:
|
|
111
|
+
return convertAtomic(name, item, "string");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Reads serialization parameters from a map.
|
|
117
|
+
* @param {import("../../items/map.js").XdmMap} map
|
|
118
|
+
* @returns {Record<string, *>} parameters by hyphenated name
|
|
119
|
+
*/
|
|
120
|
+
export function parametersFromMap(map) {
|
|
121
|
+
const params = {};
|
|
122
|
+
for (const { key, value } of map.entries.values()) {
|
|
123
|
+
if (!isA(key, "string") || !PARAMETER_KINDS[key.value]) continue;
|
|
124
|
+
const converted = parameterValue(key.value, value);
|
|
125
|
+
if (converted !== undefined) params[key.value] = converted;
|
|
126
|
+
}
|
|
127
|
+
return params;
|
|
128
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The serialization parameters of Serialization 3.1 section 3: their
|
|
3
|
+
* names (hyphenated as in the specs, camelCase in the JavaScript API) and
|
|
4
|
+
* the kind of value each one takes.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/serialize/params/names
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Namespace of the serialization parameter elements (prefix output). */
|
|
10
|
+
export const OUTPUT_NAMESPACE =
|
|
11
|
+
"http://www.w3.org/2010/xslt-xquery-serialization";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Kind of value of each parameter, by hyphenated name:
|
|
15
|
+
* - "boolean": yes/no (true/false, 1/0)
|
|
16
|
+
* - "string": any string
|
|
17
|
+
* - "qnames": a list of element names (EQNames)
|
|
18
|
+
* - "method": xml, xhtml, html, text, json, adaptive or an extension QName
|
|
19
|
+
* - "decimal": a decimal number (html-version)
|
|
20
|
+
* - "standalone": yes, no or omit
|
|
21
|
+
* - "characterMap": character to replacement string
|
|
22
|
+
*/
|
|
23
|
+
export const PARAMETER_KINDS = Object.freeze({
|
|
24
|
+
"allow-duplicate-names": "boolean",
|
|
25
|
+
"byte-order-mark": "boolean",
|
|
26
|
+
"cdata-section-elements": "qnames",
|
|
27
|
+
"doctype-public": "string",
|
|
28
|
+
"doctype-system": "string",
|
|
29
|
+
encoding: "string",
|
|
30
|
+
"escape-uri-attributes": "boolean",
|
|
31
|
+
"html-version": "decimal",
|
|
32
|
+
"include-content-type": "boolean",
|
|
33
|
+
indent: "boolean",
|
|
34
|
+
"item-separator": "string",
|
|
35
|
+
"json-node-output-method": "method",
|
|
36
|
+
"media-type": "string",
|
|
37
|
+
method: "method",
|
|
38
|
+
"normalization-form": "string",
|
|
39
|
+
"omit-xml-declaration": "boolean",
|
|
40
|
+
standalone: "standalone",
|
|
41
|
+
"suppress-indentation": "qnames",
|
|
42
|
+
"undeclare-prefixes": "boolean",
|
|
43
|
+
"use-character-maps": "characterMap",
|
|
44
|
+
version: "string",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {string} name - Hyphenated name, e.g. "omit-xml-declaration"
|
|
49
|
+
* @returns {string} the camelCase name, e.g. "omitXmlDeclaration"
|
|
50
|
+
*/
|
|
51
|
+
export const toCamelCase = (name) =>
|
|
52
|
+
name.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {string} name - camelCase name, e.g. "omitXmlDeclaration"
|
|
56
|
+
* @returns {string} the hyphenated name, e.g. "omit-xml-declaration"
|
|
57
|
+
*/
|
|
58
|
+
export const toHyphenated = (name) =>
|
|
59
|
+
name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
60
|
+
|
|
61
|
+
/** Output methods of Serialization 3.1. */
|
|
62
|
+
export const METHODS = Object.freeze([
|
|
63
|
+
"xml",
|
|
64
|
+
"xhtml",
|
|
65
|
+
"html",
|
|
66
|
+
"text",
|
|
67
|
+
"json",
|
|
68
|
+
"adaptive",
|
|
69
|
+
]);
|