@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,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalized serialization settings: the parameters given to the API
|
|
3
|
+
* (camelCase or hyphenated names) converted, defaulted and checked for the
|
|
4
|
+
* conflicts of Serialization 3.1 (SEPM0009, SEPM0010) and the values this
|
|
5
|
+
* serializer does not support (SESU0007, SESU0011, SESU0013).
|
|
6
|
+
*
|
|
7
|
+
* @module @tradik/xslt3/serialize/params/settings
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { XPathError } from "../../errors.js";
|
|
11
|
+
import { resolveEncoding } from "../output/encoding.js";
|
|
12
|
+
import { PARAMETER_KINDS, toCamelCase, toHyphenated } from "./names.js";
|
|
13
|
+
import { CONVERTERS } from "./values.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {object} Settings
|
|
17
|
+
* @property {string} method
|
|
18
|
+
* @property {boolean} allowDuplicateNames
|
|
19
|
+
* @property {boolean} byteOrderMark - Default: yes for UTF-16 only
|
|
20
|
+
* @property {Set<string>} cdataSectionElements - Clark names
|
|
21
|
+
* @property {string} [doctypePublic]
|
|
22
|
+
* @property {string} [doctypeSystem]
|
|
23
|
+
* @property {import("../output/encoding.js").Encoding} encoding
|
|
24
|
+
* @property {boolean} escapeUriAttributes
|
|
25
|
+
* @property {number} htmlVersion - 5 or 4 (html and xhtml methods)
|
|
26
|
+
* @property {boolean} includeContentType
|
|
27
|
+
* @property {boolean} indent
|
|
28
|
+
* @property {string} [itemSeparator]
|
|
29
|
+
* @property {string} jsonNodeOutputMethod
|
|
30
|
+
* @property {string} mediaType
|
|
31
|
+
* @property {string} normalizationForm - "none", "NFC", "NFD", "NFKC", "NFKD"
|
|
32
|
+
* @property {boolean} omitXmlDeclaration
|
|
33
|
+
* @property {"yes"|"no"|"omit"} standalone
|
|
34
|
+
* @property {Set<string>} suppressIndentation - Clark names
|
|
35
|
+
* @property {boolean} undeclarePrefixes
|
|
36
|
+
* @property {Map<string, string>|null} useCharacterMaps
|
|
37
|
+
* @property {string} version - XML version (xml and xhtml methods)
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/** Defaults of the parameters that have one (camelCase names). */
|
|
41
|
+
const DEFAULTS = Object.freeze({
|
|
42
|
+
method: "xml",
|
|
43
|
+
allowDuplicateNames: false,
|
|
44
|
+
cdataSectionElements: new Set(),
|
|
45
|
+
encoding: "UTF-8",
|
|
46
|
+
escapeUriAttributes: true,
|
|
47
|
+
includeContentType: true,
|
|
48
|
+
indent: false,
|
|
49
|
+
jsonNodeOutputMethod: "xml",
|
|
50
|
+
normalizationForm: "none",
|
|
51
|
+
omitXmlDeclaration: false,
|
|
52
|
+
standalone: "omit",
|
|
53
|
+
suppressIndentation: new Set(),
|
|
54
|
+
undeclarePrefixes: false,
|
|
55
|
+
useCharacterMaps: null,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const NORMALIZATION_FORMS = new Set(["NFC", "NFD", "NFKC", "NFKD", "none"]);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Converts the given parameters (undefined values are absent).
|
|
62
|
+
* @param {Record<string, *>} params
|
|
63
|
+
* @returns {Record<string, *>} converted values by camelCase name
|
|
64
|
+
*/
|
|
65
|
+
function convert(params) {
|
|
66
|
+
const values = {};
|
|
67
|
+
for (const [key, value] of Object.entries(params)) {
|
|
68
|
+
if (value === undefined) continue;
|
|
69
|
+
const hyphenated = key.includes("-") ? key : toHyphenated(key);
|
|
70
|
+
const kind = PARAMETER_KINDS[hyphenated];
|
|
71
|
+
if (!kind) continue;
|
|
72
|
+
values[toCamelCase(hyphenated)] = CONVERTERS[kind](hyphenated, value);
|
|
73
|
+
}
|
|
74
|
+
return values;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The HTML version requested for the html and xhtml methods: html-version,
|
|
79
|
+
* else (html method) version, else 5 for html and 4 (XHTML 1.0) for xhtml.
|
|
80
|
+
* @param {Record<string, *>} values - Converted values
|
|
81
|
+
* @returns {number} 4 or 5
|
|
82
|
+
* @throws {XPathError} SESU0013 for other versions
|
|
83
|
+
*/
|
|
84
|
+
function htmlVersionOf(values) {
|
|
85
|
+
let version = values.htmlVersion;
|
|
86
|
+
if (version === undefined && values.method === "html" && values.version) {
|
|
87
|
+
version = CONVERTERS.decimal("version", values.version);
|
|
88
|
+
}
|
|
89
|
+
if (version === undefined) return values.method === "xhtml" ? 4 : 5;
|
|
90
|
+
// Decimal versions compared with a tolerance: 5, 5.0, 4.0 and 4.01
|
|
91
|
+
const near = (target) => Math.abs(version - target) < 1e-9;
|
|
92
|
+
if (near(5)) return 5;
|
|
93
|
+
if (near(4) || near(4.01)) return 4;
|
|
94
|
+
throw new XPathError("SESU0013", `Unsupported HTML version ${version}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Checks the XML-related parameters of the xml and xhtml methods.
|
|
99
|
+
* @param {Settings} settings
|
|
100
|
+
* @throws {XPathError} SESU0013, SEPM0009 or SEPM0010
|
|
101
|
+
*/
|
|
102
|
+
function checkXml(settings) {
|
|
103
|
+
const { version, omitXmlDeclaration, standalone } = settings;
|
|
104
|
+
if (version !== "1.0" && version !== "1.1") {
|
|
105
|
+
throw new XPathError("SESU0013", `Unsupported XML version ${version}`);
|
|
106
|
+
}
|
|
107
|
+
if (omitXmlDeclaration && standalone !== "omit") {
|
|
108
|
+
throw new XPathError(
|
|
109
|
+
"SEPM0009",
|
|
110
|
+
"standalone conflicts with omit-xml-declaration",
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
if (omitXmlDeclaration && version !== "1.0" && settings.doctypeSystem) {
|
|
114
|
+
throw new XPathError(
|
|
115
|
+
"SEPM0009",
|
|
116
|
+
"doctype-system with XML 1.1 needs the XML declaration",
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
if (settings.undeclarePrefixes && version === "1.0") {
|
|
120
|
+
throw new XPathError("SEPM0010", "undeclare-prefixes needs XML 1.1");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Normalizes serialization parameters.
|
|
126
|
+
* @param {Record<string, *>} [params] - Parameters by camelCase or
|
|
127
|
+
* hyphenated name (unknown names are ignored)
|
|
128
|
+
* @returns {Settings}
|
|
129
|
+
* @throws {XPathError} SEPM0016 for invalid values, SEPM0009/SEPM0010 for
|
|
130
|
+
* conflicts, SESU0007/SESU0011/SESU0013 for unsupported values
|
|
131
|
+
*/
|
|
132
|
+
export function normalizeSettings(params = {}) {
|
|
133
|
+
const values = { ...DEFAULTS, ...convert(params) };
|
|
134
|
+
if (!NORMALIZATION_FORMS.has(values.normalizationForm)) {
|
|
135
|
+
throw new XPathError(
|
|
136
|
+
"SESU0011",
|
|
137
|
+
`Unsupported normalization form ${values.normalizationForm}`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const htmlLike = values.method === "html" || values.method === "xhtml";
|
|
141
|
+
const settings = {
|
|
142
|
+
...values,
|
|
143
|
+
encoding: resolveEncoding(values.encoding),
|
|
144
|
+
byteOrderMark: values.byteOrderMark ?? /^utf-?16$/i.test(values.encoding),
|
|
145
|
+
htmlVersion: htmlLike ? htmlVersionOf(values) : 5,
|
|
146
|
+
mediaType: values.mediaType ?? "text/html",
|
|
147
|
+
version: values.method === "html" ? "1.0" : (values.version ?? "1.0"),
|
|
148
|
+
};
|
|
149
|
+
if (settings.method === "xml" || settings.method === "xhtml") {
|
|
150
|
+
checkXml(settings);
|
|
151
|
+
}
|
|
152
|
+
return settings;
|
|
153
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversion of serialization parameter values given in the JavaScript
|
|
3
|
+
* API (booleans, numbers, strings, arrays, Maps, objects) or as the
|
|
4
|
+
* lexical `value` attributes of an `output:serialization-parameters`
|
|
5
|
+
* element into their normalized form. A value outside the domain of its
|
|
6
|
+
* parameter is a SEPM0016 error (the element form turns it into SEPM0017).
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/serialize/params/values
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { XPathError } from "../../errors.js";
|
|
12
|
+
import { METHODS } from "./names.js";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} name - Parameter name
|
|
16
|
+
* @param {*} value - Rejected value
|
|
17
|
+
* @returns {XPathError} SEPM0016
|
|
18
|
+
*/
|
|
19
|
+
export const invalidValue = (name, value) =>
|
|
20
|
+
new XPathError(
|
|
21
|
+
"SEPM0016",
|
|
22
|
+
`Invalid value ${JSON.stringify(String(value))} of serialization parameter ${name}`,
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const TRUE_WORDS = new Set(["yes", "true", "1"]);
|
|
26
|
+
const FALSE_WORDS = new Set(["no", "false", "0"]);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} name
|
|
30
|
+
* @param {boolean|string} value - A boolean or yes/no, true/false, 1/0
|
|
31
|
+
* @returns {boolean}
|
|
32
|
+
*/
|
|
33
|
+
export function toBoolean(name, value) {
|
|
34
|
+
if (typeof value === "boolean") return value;
|
|
35
|
+
const word = String(value).trim();
|
|
36
|
+
if (TRUE_WORDS.has(word)) return true;
|
|
37
|
+
if (FALSE_WORDS.has(word)) return false;
|
|
38
|
+
throw invalidValue(name, value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} name
|
|
43
|
+
* @param {boolean|string|null} value - A boolean, yes/no/omit or null (omit)
|
|
44
|
+
* @returns {"yes"|"no"|"omit"}
|
|
45
|
+
*/
|
|
46
|
+
export function toStandalone(name, value) {
|
|
47
|
+
if (value === null || String(value).trim() === "omit") return "omit";
|
|
48
|
+
return toBoolean(name, value) ? "yes" : "no";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Expanded name of an element name in Clark notation, the form names are
|
|
53
|
+
* compared in.
|
|
54
|
+
* @param {string} namespaceURI - "" for no namespace
|
|
55
|
+
* @param {string} localName
|
|
56
|
+
* @returns {string} "{uri}local"
|
|
57
|
+
*/
|
|
58
|
+
export const clarkName = (namespaceURI, localName) =>
|
|
59
|
+
`{${namespaceURI}}${localName}`;
|
|
60
|
+
|
|
61
|
+
const EQNAME = /^(?:Q?\{([^{}]*)\})?([^\s{}:]+)$/;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* One element name: a QName object (`{namespaceURI, localName}`), an
|
|
65
|
+
* EQName `Q{uri}local`, Clark notation `{uri}local`, a local name, or a
|
|
66
|
+
* prefixed name when a resolver is given.
|
|
67
|
+
* @param {string} name - Parameter name, for errors
|
|
68
|
+
* @param {*} value
|
|
69
|
+
* @param {(prefix: string) => string|undefined} [resolve] - Prefix lookup
|
|
70
|
+
* @returns {string} the name in Clark notation
|
|
71
|
+
*/
|
|
72
|
+
export function toClarkName(name, value, resolve) {
|
|
73
|
+
if (typeof value === "object" && value !== null) {
|
|
74
|
+
return clarkName(value.namespaceURI ?? "", value.localName);
|
|
75
|
+
}
|
|
76
|
+
const text = String(value);
|
|
77
|
+
const colon = text.indexOf(":");
|
|
78
|
+
if (resolve && colon > 0 && !text.startsWith("Q{")) {
|
|
79
|
+
const uri = resolve(text.slice(0, colon));
|
|
80
|
+
if (uri === undefined) throw invalidValue(name, value);
|
|
81
|
+
return clarkName(uri, text.slice(colon + 1));
|
|
82
|
+
}
|
|
83
|
+
const match = EQNAME.exec(text);
|
|
84
|
+
if (!match) throw invalidValue(name, value);
|
|
85
|
+
return clarkName(match[1] ?? "", match[2]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* A list of element names: an array or Set of names, or one string of
|
|
90
|
+
* whitespace-separated names.
|
|
91
|
+
* @param {string} name
|
|
92
|
+
* @param {*} value
|
|
93
|
+
* @param {(prefix: string) => string|undefined} [resolve]
|
|
94
|
+
* @returns {Set<string>} names in Clark notation
|
|
95
|
+
*/
|
|
96
|
+
export function toNameSet(name, value, resolve) {
|
|
97
|
+
const list =
|
|
98
|
+
typeof value === "string"
|
|
99
|
+
? value.split(/\s+/).filter(Boolean)
|
|
100
|
+
: [...(value[Symbol.iterator] ? value : [value])];
|
|
101
|
+
return new Set(list.map((item) => toClarkName(name, item, resolve)));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The output method: one of {@link METHODS}. Extension methods (QNames
|
|
106
|
+
* in a namespace) are not supported.
|
|
107
|
+
* @param {string} name
|
|
108
|
+
* @param {*} value - A string or a QName object
|
|
109
|
+
* @returns {string}
|
|
110
|
+
*/
|
|
111
|
+
export function toMethod(name, value) {
|
|
112
|
+
if (typeof value === "object" && value !== null) {
|
|
113
|
+
if (value.namespaceURI) {
|
|
114
|
+
throw invalidValue(name, `Q{${value.namespaceURI}}${value.localName}`);
|
|
115
|
+
}
|
|
116
|
+
return toMethod(name, value.localName);
|
|
117
|
+
}
|
|
118
|
+
const text = String(value).trim();
|
|
119
|
+
if (METHODS.includes(text)) return text;
|
|
120
|
+
throw invalidValue(name, value);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {string} name
|
|
125
|
+
* @param {number|string|{toNumber: () => number}} value - A decimal
|
|
126
|
+
* @returns {number}
|
|
127
|
+
*/
|
|
128
|
+
export function toDecimal(name, value) {
|
|
129
|
+
if (typeof value === "number") return value;
|
|
130
|
+
if (typeof value?.toNumber === "function") return value.toNumber();
|
|
131
|
+
const text = String(value).trim();
|
|
132
|
+
if (!/^[+-]?(\d+(\.\d*)?|\.\d+)$/.test(text)) throw invalidValue(name, value);
|
|
133
|
+
return Number(text);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* A character map: a Map or a plain object from single characters to
|
|
138
|
+
* replacement strings.
|
|
139
|
+
* @param {string} name
|
|
140
|
+
* @param {Map<string, string>|Record<string, string>} value
|
|
141
|
+
* @returns {Map<string, string>}
|
|
142
|
+
*/
|
|
143
|
+
export function toCharacterMap(name, value) {
|
|
144
|
+
const entries =
|
|
145
|
+
value instanceof Map ? [...value.entries()] : Object.entries(value);
|
|
146
|
+
const map = new Map();
|
|
147
|
+
for (const [character, replacement] of entries) {
|
|
148
|
+
if ([...character].length !== 1) throw invalidValue(name, character);
|
|
149
|
+
map.set(character, String(replacement));
|
|
150
|
+
}
|
|
151
|
+
return map;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Converters by parameter kind (see PARAMETER_KINDS). */
|
|
155
|
+
export const CONVERTERS = Object.freeze({
|
|
156
|
+
boolean: toBoolean,
|
|
157
|
+
string: (_, value) => String(value),
|
|
158
|
+
qnames: toNameSet,
|
|
159
|
+
method: toMethod,
|
|
160
|
+
decimal: toDecimal,
|
|
161
|
+
standalone: toStandalone,
|
|
162
|
+
characterMap: toCharacterMap,
|
|
163
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sequence normalization (Serialization 3.1 section 2), done by the xml,
|
|
3
|
+
* xhtml, html and text methods before they write anything: arrays are
|
|
4
|
+
* flattened, atomic values become strings (joined by a space, or by the
|
|
5
|
+
* item-separator between all items), document nodes are replaced by their
|
|
6
|
+
* children and adjacent text is merged.
|
|
7
|
+
*
|
|
8
|
+
* The result is the list of the children of the normalized document:
|
|
9
|
+
* strings for text nodes and DOM nodes for elements, comments and
|
|
10
|
+
* processing instructions.
|
|
11
|
+
*
|
|
12
|
+
* @module @tradik/xslt3/serialize/sequence
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { XPathError } from "../errors.js";
|
|
16
|
+
import { canonicalString, itemKind } from "../xdm/index.js";
|
|
17
|
+
|
|
18
|
+
const ATTRIBUTE_NODE = 2;
|
|
19
|
+
const TEXT_NODE = 3;
|
|
20
|
+
const CDATA_SECTION_NODE = 4;
|
|
21
|
+
const DOCUMENT_NODE = 9;
|
|
22
|
+
const DOCUMENT_TYPE_NODE = 10;
|
|
23
|
+
const DOCUMENT_FRAGMENT_NODE = 11;
|
|
24
|
+
const NAMESPACE_NODE = 13;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Flattens arrays, without recursion.
|
|
28
|
+
* @param {Array} sequence
|
|
29
|
+
* @returns {Array} the items, arrays replaced by their members' items
|
|
30
|
+
*/
|
|
31
|
+
export function flattenArrays(sequence) {
|
|
32
|
+
const result = [];
|
|
33
|
+
const pending = [[sequence, 0]];
|
|
34
|
+
while (pending.length) {
|
|
35
|
+
const top = pending[pending.length - 1];
|
|
36
|
+
if (top[1] === top[0].length) {
|
|
37
|
+
pending.pop();
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const item = top[0][top[1]++];
|
|
41
|
+
if (itemKind(item) === "array") pending.push([item.members.flat(), 0]);
|
|
42
|
+
else result.push(item);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Appends a node, or the children of a document node, merging text.
|
|
49
|
+
* @param {Array<string|Node>} out
|
|
50
|
+
* @param {Node} node
|
|
51
|
+
*/
|
|
52
|
+
function appendNode(out, node) {
|
|
53
|
+
const type = node.nodeType;
|
|
54
|
+
if (type === DOCUMENT_NODE || type === DOCUMENT_FRAGMENT_NODE) {
|
|
55
|
+
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
56
|
+
if (child.nodeType !== DOCUMENT_TYPE_NODE) appendNode(out, child);
|
|
57
|
+
}
|
|
58
|
+
} else if (type === TEXT_NODE || type === CDATA_SECTION_NODE) {
|
|
59
|
+
appendText(out, node.nodeValue);
|
|
60
|
+
} else if (type === ATTRIBUTE_NODE || type === NAMESPACE_NODE) {
|
|
61
|
+
throw new XPathError(
|
|
62
|
+
"SENR0001",
|
|
63
|
+
"An attribute or namespace node cannot be serialized on its own",
|
|
64
|
+
);
|
|
65
|
+
} else {
|
|
66
|
+
out.push(node);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Appends text, merging it with preceding text.
|
|
72
|
+
* @param {Array<string|Node>} out
|
|
73
|
+
* @param {string} text
|
|
74
|
+
*/
|
|
75
|
+
function appendText(out, text) {
|
|
76
|
+
if (text === "") return;
|
|
77
|
+
const last = out.length - 1;
|
|
78
|
+
if (typeof out[last] === "string") out[last] += text;
|
|
79
|
+
else out.push(text);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Normalizes a sequence.
|
|
84
|
+
* @param {Array} sequence - XDM items
|
|
85
|
+
* @param {string} [itemSeparator] - Separator between all items; when
|
|
86
|
+
* absent, adjacent atomic values are separated by a space
|
|
87
|
+
* @returns {Array<string|Node>} the content of the normalized document
|
|
88
|
+
* @throws {XPathError} SENR0001 for attribute and namespace nodes, maps
|
|
89
|
+
* and function items
|
|
90
|
+
*/
|
|
91
|
+
export function normalizeSequence(sequence, itemSeparator) {
|
|
92
|
+
const out = [];
|
|
93
|
+
let previousAtomic = false;
|
|
94
|
+
flattenArrays(sequence).forEach((item, index) => {
|
|
95
|
+
const kind = itemKind(item);
|
|
96
|
+
if (itemSeparator !== undefined && index > 0) {
|
|
97
|
+
appendText(out, itemSeparator);
|
|
98
|
+
}
|
|
99
|
+
if (kind === "atomic") {
|
|
100
|
+
const separator =
|
|
101
|
+
previousAtomic && itemSeparator === undefined ? " " : "";
|
|
102
|
+
appendText(out, separator + canonicalString(item));
|
|
103
|
+
} else if (kind === "node") {
|
|
104
|
+
appendNode(out, item);
|
|
105
|
+
} else {
|
|
106
|
+
throw new XPathError("SENR0001", `A ${kind} cannot be serialized`);
|
|
107
|
+
}
|
|
108
|
+
previousAtomic = kind === "atomic";
|
|
109
|
+
});
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arithmetic operators of XPath 3.1 (section 3.5, appendix B.2) on atomic
|
|
3
|
+
* values: numeric operators with type promotion here, date/time and
|
|
4
|
+
* duration operators in {@link module:@tradik/xslt3/xdm/temporalArithmetic}.
|
|
5
|
+
*
|
|
6
|
+
* xs:integer arithmetic is exact (BigInt), xs:decimal arithmetic is exact
|
|
7
|
+
* except division, which keeps {@link DIVISION_SCALE} fraction digits;
|
|
8
|
+
* xs:float results are rounded with Math.fround; xs:double follows IEEE 754.
|
|
9
|
+
*
|
|
10
|
+
* @module @tradik/xslt3/xdm/arithmetic
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { XPathError } from "../errors.js";
|
|
14
|
+
import { AtomicValue } from "./atomic.js";
|
|
15
|
+
import { cast } from "./cast.js";
|
|
16
|
+
import { Decimal } from "./decimal.js";
|
|
17
|
+
import { temporalArithmetic } from "./temporalArithmetic.js";
|
|
18
|
+
import { isNumericType, types } from "./types.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* xs:untypedAtomic operands are cast to xs:double (XPath 3.1 3.5).
|
|
22
|
+
* @param {AtomicValue} item
|
|
23
|
+
* @returns {AtomicValue}
|
|
24
|
+
*/
|
|
25
|
+
function prepare(item) {
|
|
26
|
+
return item.type === types.untypedAtomic ? cast(item, types.double) : item;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** @param {string} what @returns {never} */
|
|
30
|
+
function divisionByZero(what) {
|
|
31
|
+
throw new XPathError("FOAR0001", `Division by zero in ${what}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Exact operators on BigInt (xs:integer) operands. */
|
|
35
|
+
const integerOps = {
|
|
36
|
+
"+": (a, b) => a + b,
|
|
37
|
+
"-": (a, b) => a - b,
|
|
38
|
+
"*": (a, b) => a * b,
|
|
39
|
+
div: (a, b) => decimalOps.div(Decimal.of(a), Decimal.of(b)),
|
|
40
|
+
idiv: (a, b) => (b === 0n ? divisionByZero("idiv") : a / b),
|
|
41
|
+
mod: (a, b) => (b === 0n ? divisionByZero("mod") : a % b),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** Operators on {@link Decimal} operands. */
|
|
45
|
+
const decimalOps = {
|
|
46
|
+
"+": (a, b) => a.add(b),
|
|
47
|
+
"-": (a, b) => a.sub(b),
|
|
48
|
+
"*": (a, b) => a.mul(b),
|
|
49
|
+
div: (a, b) => (b.sign() === 0 ? divisionByZero("div") : a.div(b)),
|
|
50
|
+
idiv: (a, b) => (b.sign() === 0 ? divisionByZero("idiv") : a.idiv(b)),
|
|
51
|
+
mod: (a, b) => (b.sign() === 0 ? divisionByZero("mod") : a.mod(b)),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/** IEEE operators on JS numbers; `round` is Math.fround for xs:float. */
|
|
55
|
+
function floatingOp(op, a, b, round) {
|
|
56
|
+
switch (op) {
|
|
57
|
+
case "+":
|
|
58
|
+
return round(a + b);
|
|
59
|
+
case "-":
|
|
60
|
+
return round(a - b);
|
|
61
|
+
case "*":
|
|
62
|
+
return round(a * b);
|
|
63
|
+
case "div":
|
|
64
|
+
return round(a / b);
|
|
65
|
+
case "mod":
|
|
66
|
+
return round(a % b);
|
|
67
|
+
default: {
|
|
68
|
+
if (b === 0) divisionByZero("idiv");
|
|
69
|
+
const quotient = round(a / b);
|
|
70
|
+
if (!Number.isFinite(quotient)) {
|
|
71
|
+
throw new XPathError("FOAR0002", "idiv of NaN or infinite values");
|
|
72
|
+
}
|
|
73
|
+
return BigInt(Math.trunc(quotient));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Numeric operation with promotion integer → decimal → float → double.
|
|
80
|
+
* @param {AtomicValue} a
|
|
81
|
+
* @param {string} op
|
|
82
|
+
* @param {AtomicValue} b
|
|
83
|
+
* @returns {AtomicValue}
|
|
84
|
+
*/
|
|
85
|
+
function numericArithmetic(a, op, b) {
|
|
86
|
+
const pa = a.type.primitive.localName;
|
|
87
|
+
const pb = b.type.primitive.localName;
|
|
88
|
+
if (pa === "decimal" && pb === "decimal") {
|
|
89
|
+
const integers = typeof a.value === "bigint" && typeof b.value === "bigint";
|
|
90
|
+
const toDecimal = (v) => (typeof v === "bigint" ? Decimal.of(v) : v);
|
|
91
|
+
const value = integers
|
|
92
|
+
? integerOps[op](a.value, b.value)
|
|
93
|
+
: decimalOps[op](toDecimal(a.value), toDecimal(b.value));
|
|
94
|
+
return new AtomicValue(
|
|
95
|
+
typeof value === "bigint" ? types.integer : types.decimal,
|
|
96
|
+
value,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
const isDouble = pa === "double" || pb === "double";
|
|
100
|
+
const asNumber = (item) =>
|
|
101
|
+
cast(item, isDouble ? types.double : types.float).value;
|
|
102
|
+
const value = floatingOp(
|
|
103
|
+
op,
|
|
104
|
+
asNumber(a),
|
|
105
|
+
asNumber(b),
|
|
106
|
+
isDouble ? Number : Math.fround,
|
|
107
|
+
);
|
|
108
|
+
if (typeof value === "bigint") return new AtomicValue(types.integer, value);
|
|
109
|
+
return new AtomicValue(isDouble ? types.double : types.float, value);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Binary arithmetic `a op b` on two atomic values: numbers, durations,
|
|
114
|
+
* dates and times (empty operands are the evaluator's concern).
|
|
115
|
+
* @param {AtomicValue} a
|
|
116
|
+
* @param {"+"|"-"|"*"|"div"|"idiv"|"mod"} op
|
|
117
|
+
* @param {AtomicValue} b
|
|
118
|
+
* @param {{implicitTimezone?: number}} [options] - Implicit timezone in
|
|
119
|
+
* minutes, for subtracting dates and times
|
|
120
|
+
* @returns {AtomicValue}
|
|
121
|
+
* @throws {XPathError} XPTY0004 for unsupported operand types, FOAR0001
|
|
122
|
+
* for division by zero, FOAR0002 for idiv of NaN/INF, FORG0001 for
|
|
123
|
+
* untyped operands that are not numbers, FODT0001/FODT0002/FOCA0005 for
|
|
124
|
+
* date and duration arithmetic
|
|
125
|
+
*/
|
|
126
|
+
export function arithmetic(a, op, b, options = {}) {
|
|
127
|
+
const x = prepare(a);
|
|
128
|
+
const y = prepare(b);
|
|
129
|
+
if (isNumericType(x.type) && isNumericType(y.type)) {
|
|
130
|
+
return numericArithmetic(x, op, y);
|
|
131
|
+
}
|
|
132
|
+
return temporalArithmetic(x, op, y, options);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Unary minus or plus on a numeric value (xs:untypedAtomic is cast to
|
|
137
|
+
* xs:double). The result has the operand's primitive numeric type.
|
|
138
|
+
* @param {"-"|"+"} op
|
|
139
|
+
* @param {AtomicValue} a
|
|
140
|
+
* @returns {AtomicValue}
|
|
141
|
+
* @throws {XPathError} XPTY0004 for non-numeric operands
|
|
142
|
+
*/
|
|
143
|
+
export function unaryArithmetic(op, a) {
|
|
144
|
+
const x = prepare(a);
|
|
145
|
+
if (!isNumericType(x.type)) {
|
|
146
|
+
throw new XPathError(
|
|
147
|
+
"XPTY0004",
|
|
148
|
+
`Unary ${op} is not defined for ${x.type.prefixedName}`,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
const { value } = x;
|
|
152
|
+
const type = typeof value === "bigint" ? types.integer : x.type.primitive;
|
|
153
|
+
if (op === "+") return new AtomicValue(type, value);
|
|
154
|
+
return new AtomicValue(type, value instanceof Decimal ? value.neg() : -value);
|
|
155
|
+
}
|