xslt-processor 5.0.7 → 5.0.9

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/dist/index.mjs CHANGED
@@ -11130,7 +11130,7 @@ function xmlElementLogicTrivial(node, buffer, options) {
11130
11130
  }
11131
11131
  childNodes = childNodes.sort((a, b) => a.siblingPosition - b.siblingPosition);
11132
11132
  if (childNodes.length === 0) {
11133
- if (options.outputMethod === "html" && ["hr", "link", "meta"].includes(node.nodeName)) {
11133
+ if (options.outputMethod === "html" && ["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"].includes(node.nodeName)) {
11134
11134
  buffer.push(">");
11135
11135
  } else if (options.selfClosingTags) {
11136
11136
  buffer.push("/>");
@@ -11831,7 +11831,9 @@ var NodeConverter = class {
11831
11831
  * We add missing properties but keep the original XNode reference.
11832
11832
  */
11833
11833
  adaptXNode(node) {
11834
- if (!node) return null;
11834
+ if (!node) {
11835
+ throw new Error("Cannot adapt undefined XPath node.");
11836
+ }
11835
11837
  const adapted = node;
11836
11838
  if (!("textContent" in adapted)) {
11837
11839
  Object.defineProperty(adapted, "textContent", {
@@ -11917,7 +11919,12 @@ var NodeConverter = class {
11917
11919
  }
11918
11920
  for (let i = contexts.length - 1; i >= 0; i--) {
11919
11921
  const current = contexts[i];
11920
- for (const [name, value] of Object.entries(current.variables || {})) {
11922
+ const currentVariables = current.variables || {};
11923
+ for (const name in currentVariables) {
11924
+ if (!Object.prototype.hasOwnProperty.call(currentVariables, name)) {
11925
+ continue;
11926
+ }
11927
+ const value = currentVariables[name];
11921
11928
  if (value && typeof value === "object" && "stringValue" in value) {
11922
11929
  const nodeValue = value;
11923
11930
  if (nodeValue.type === "node-set") {
@@ -11966,7 +11973,7 @@ var NodeConverter = class {
11966
11973
  };
11967
11974
  functions["format-number"] = (_context, number, format, decimalFormatName) => {
11968
11975
  const settings = exprContext.decimalFormatSettings;
11969
- return number.toLocaleString();
11976
+ return this.formatXsltNumberPicture(Number(number), String(format), settings);
11970
11977
  };
11971
11978
  functions["xml-to-json"] = (_context, nodes) => {
11972
11979
  if (exprContext.xsltVersion !== "3.0") {
@@ -12047,7 +12054,7 @@ var NodeConverter = class {
12047
12054
  "xsl:with-param"
12048
12055
  ];
12049
12056
  const normalizedName = name.startsWith("xsl:") ? name : `xsl:${name}`;
12050
- return xsltElements.includes(normalizedName) || xsltElements.includes(name);
12057
+ return xsltElements.indexOf(normalizedName) >= 0 || xsltElements.indexOf(name) >= 0;
12051
12058
  };
12052
12059
  functions["function-available"] = (_context, functionName2) => {
12053
12060
  const name = String(functionName2);
@@ -12098,7 +12105,7 @@ var NodeConverter = class {
12098
12105
  "json-to-xml"
12099
12106
  ];
12100
12107
  const allFunctions = [...xpathCoreFunctions, ...xsltFunctions, ...additionalFunctions];
12101
- return allFunctions.includes(name);
12108
+ return allFunctions.indexOf(name) >= 0;
12102
12109
  };
12103
12110
  functions["document"] = (_context, uriOrNodeSet, _baseNode) => {
12104
12111
  var _a, _b;
@@ -12142,6 +12149,95 @@ var NodeConverter = class {
12142
12149
  }
12143
12150
  return functions;
12144
12151
  }
12152
+ /**
12153
+ * Minimal XSLT/XPath format-number() picture formatter.
12154
+ * Supports grouping, decimal precision, percent/per-mille scaling and positive/negative subpictures.
12155
+ */
12156
+ formatXsltNumberPicture(value, picture, settings) {
12157
+ if (Number.isNaN(value)) {
12158
+ return settings.naN;
12159
+ }
12160
+ if (!Number.isFinite(value)) {
12161
+ return value < 0 ? `${settings.minusSign}${settings.infinity}` : settings.infinity;
12162
+ }
12163
+ const subPictures = picture.split(settings.patternSeparator);
12164
+ const isNegative = value < 0;
12165
+ const activePicture = (isNegative && subPictures.length > 1 ? subPictures[1] : subPictures[0]) || "";
12166
+ const absValue = Math.abs(value);
12167
+ const placeholders = /* @__PURE__ */ new Set([settings.digit, settings.zeroDigit, settings.groupingSeparator, settings.decimalSeparator]);
12168
+ let firstPatternIndex = -1;
12169
+ let lastPatternIndex = -1;
12170
+ for (let i = 0; i < activePicture.length; i++) {
12171
+ if (placeholders.has(activePicture[i])) {
12172
+ if (firstPatternIndex === -1) {
12173
+ firstPatternIndex = i;
12174
+ }
12175
+ lastPatternIndex = i;
12176
+ }
12177
+ }
12178
+ if (firstPatternIndex === -1) {
12179
+ return activePicture;
12180
+ }
12181
+ const prefix = activePicture.slice(0, firstPatternIndex);
12182
+ const suffix = activePicture.slice(lastPatternIndex + 1);
12183
+ const numericPicture = activePicture.slice(firstPatternIndex, lastPatternIndex + 1);
12184
+ let scaledValue = absValue;
12185
+ if (activePicture.includes(settings.percent)) {
12186
+ scaledValue *= 100;
12187
+ }
12188
+ if (activePicture.includes(settings.perMille)) {
12189
+ scaledValue *= 1e3;
12190
+ }
12191
+ const decimalIndex = numericPicture.indexOf(settings.decimalSeparator);
12192
+ const integerPattern = decimalIndex >= 0 ? numericPicture.slice(0, decimalIndex) : numericPicture;
12193
+ const fractionPattern = decimalIndex >= 0 ? numericPicture.slice(decimalIndex + 1) : "";
12194
+ const minIntegerDigits = integerPattern.split("").filter((c) => c === settings.zeroDigit).length;
12195
+ const minFractionDigits = fractionPattern.split("").filter((c) => c === settings.zeroDigit).length;
12196
+ const maxFractionDigits = fractionPattern.split("").filter((c) => c === settings.zeroDigit || c === settings.digit).length;
12197
+ const rounded = maxFractionDigits > 0 ? scaledValue.toFixed(maxFractionDigits) : Math.round(scaledValue).toString();
12198
+ let [integerPart, fractionPart = ""] = rounded.split(".");
12199
+ if (integerPart.length < minIntegerDigits) {
12200
+ integerPart = this.leftPad(integerPart, minIntegerDigits, settings.zeroDigit);
12201
+ }
12202
+ while (fractionPart.length > minFractionDigits && fractionPart.endsWith(settings.zeroDigit)) {
12203
+ fractionPart = fractionPart.slice(0, -1);
12204
+ }
12205
+ const lastGroupingPos = integerPattern.lastIndexOf(settings.groupingSeparator);
12206
+ if (lastGroupingPos >= 0) {
12207
+ const groupSize = integerPattern.slice(lastGroupingPos + 1).split("").filter((c) => c === settings.zeroDigit || c === settings.digit).length;
12208
+ if (groupSize > 0) {
12209
+ integerPart = this.applyGrouping(integerPart, settings.groupingSeparator, groupSize);
12210
+ }
12211
+ }
12212
+ const numberText = fractionPart.length > 0 ? `${integerPart}${settings.decimalSeparator}${fractionPart}` : integerPart;
12213
+ if (isNegative && subPictures.length < 2) {
12214
+ return `${settings.minusSign}${prefix}${numberText}${suffix}`;
12215
+ }
12216
+ return `${prefix}${numberText}${suffix}`;
12217
+ }
12218
+ applyGrouping(numberText, separator, groupSize) {
12219
+ if (groupSize <= 0 || numberText.length <= groupSize) {
12220
+ return numberText;
12221
+ }
12222
+ const chunks = [];
12223
+ for (let i = numberText.length; i > 0; i -= groupSize) {
12224
+ const start = Math.max(0, i - groupSize);
12225
+ chunks.unshift(numberText.slice(start, i));
12226
+ }
12227
+ return chunks.join(separator);
12228
+ }
12229
+ leftPad(value, width, fillChar) {
12230
+ if (value.length >= width) {
12231
+ return value;
12232
+ }
12233
+ const padChar = fillChar && fillChar.length > 0 ? fillChar.charAt(0) : "0";
12234
+ const missing = width - value.length;
12235
+ let padding = "";
12236
+ for (let i = 0; i < missing; i++) {
12237
+ padding += padChar;
12238
+ }
12239
+ return padding + value;
12240
+ }
12145
12241
  /**
12146
12242
  * Convert an XPathNode interface tree to actual XNode objects.
12147
12243
  * This is needed to convert json-to-xml() output to XSLT-compatible nodes.
@@ -12154,7 +12250,11 @@ var NodeConverter = class {
12154
12250
  if (xpathNode.nodeType === DOM_DOCUMENT_NODE) {
12155
12251
  if (xpathNode.childNodes && xpathNode.childNodes.length > 0) {
12156
12252
  const rootChild = xpathNode.childNodes[0];
12157
- node = this.convertXPathNodeToXNode(rootChild, ownerDoc);
12253
+ const convertedNode = this.convertXPathNodeToXNode(rootChild, ownerDoc);
12254
+ if (!convertedNode) {
12255
+ return null;
12256
+ }
12257
+ node = convertedNode;
12158
12258
  return node;
12159
12259
  }
12160
12260
  return null;