jtlt 0.3.0 → 0.4.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/CHANGES.md +9 -0
- package/README.md +46 -78
- package/demo/codemirror.esm.js +28242 -0
- package/demo/codemirror.js +94 -0
- package/demo/index.css +7 -0
- package/demo/index.html +11 -14
- package/demo/index.js +206 -26
- package/demo/vendor/jamilih/dist/jml.mjs +2341 -0
- package/demo/vendor/jhtml/src/SAJJ/SAJJ.ObjectArrayDelegator.js +356 -0
- package/demo/vendor/jhtml/src/SAJJ/SAJJ.Stringifier.js +186 -0
- package/demo/vendor/jhtml/src/SAJJ/SAJJ.js +746 -0
- package/demo/vendor/jhtml/src/SAJJ/testing/SAJJ.html +33 -0
- package/demo/vendor/jhtml/src/SAJJ/testing/SAJJ.testing.js +25 -0
- package/demo/vendor/jhtml/src/jhtml-browser.js +5 -0
- package/demo/vendor/jhtml/src/jhtml-node.cts +3 -0
- package/demo/vendor/jhtml/src/jhtml-node.js +8 -0
- package/demo/vendor/jhtml/src/jhtml-node.mts +1 -0
- package/demo/vendor/jhtml/src/jhtml.cts +3 -0
- package/demo/vendor/jhtml/src/jhtml.js +602 -0
- package/demo/vendor/jhtml/src/jhtml.mts +1 -0
- package/demo/vendor/jsonpath-plus/dist/index-browser-esm.js +2158 -0
- package/demo/vendor/simple-get-json/dist/index-es.js +151 -0
- package/dist/JSONPathTransformerContext.d.ts +88 -4
- package/dist/JSONPathTransformerContext.d.ts.map +1 -1
- package/dist/XPathTransformer.d.ts +2 -2
- package/dist/XPathTransformerContext.d.ts +92 -8
- package/dist/XPathTransformerContext.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/docs/API.expanded.md +5 -3
- package/docs/API.md +1 -1
- package/docs/TO-DO.md +55 -31
- package/eslint.config.js +3 -1
- package/package.json +24 -4
- package/rollup.config.js +13 -0
- package/src/JSONPathTransformerContext.js +422 -4
- package/src/XPathTransformer.js +1 -1
- package/src/XPathTransformerContext.js +462 -11
- package/src/index.js +9 -6
- package/tsconfig.json +5 -2
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import {JSONPath as jsonpath} from 'jsonpath-plus';
|
|
2
2
|
import JSONPathTransformer from './JSONPathTransformer.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {number|string|{
|
|
6
|
+
* value?: number|string,
|
|
7
|
+
* count?: string,
|
|
8
|
+
* format?: string,
|
|
9
|
+
* groupingSeparator?: string,
|
|
10
|
+
* groupingSize?: number,
|
|
11
|
+
* lang?: string,
|
|
12
|
+
* letterValue?: string
|
|
13
|
+
* }} NumberValue
|
|
14
|
+
*/
|
|
15
|
+
|
|
4
16
|
/**
|
|
5
17
|
* Sort spec types used by applyTemplates() and forEach().
|
|
6
18
|
* @typedef {{
|
|
@@ -46,6 +58,11 @@ import JSONPathTransformer from './JSONPathTransformer.js';
|
|
|
46
58
|
* @template [T = "json"]
|
|
47
59
|
*/
|
|
48
60
|
class JSONPathTransformerContext {
|
|
61
|
+
/**
|
|
62
|
+
* Holds the current iteration state (for position calculations).
|
|
63
|
+
* @type {{ index?: number } | undefined}
|
|
64
|
+
*/
|
|
65
|
+
iterationState;
|
|
49
66
|
/**
|
|
50
67
|
* @param {JSONPathTransformerContextConfig<T>} config
|
|
51
68
|
* @param {import('./index.js').JSONPathTemplateObject<T>[]} templates - Array
|
|
@@ -627,6 +644,146 @@ class JSONPathTransformerContext {
|
|
|
627
644
|
return this;
|
|
628
645
|
}
|
|
629
646
|
|
|
647
|
+
/**
|
|
648
|
+
* Analyze a string with a regular expression, equivalent to
|
|
649
|
+
* xsl:analyze-string. Processes matching and non-matching substrings
|
|
650
|
+
* with separate callbacks.
|
|
651
|
+
* @param {string} str - The string to analyze
|
|
652
|
+
* @param {string|RegExp} regex - Regular expression to match against
|
|
653
|
+
* @param {{
|
|
654
|
+
* matchingSubstring?: (
|
|
655
|
+
* this: JSONPathTransformerContext<T>,
|
|
656
|
+
* substring: string,
|
|
657
|
+
* groups: string[],
|
|
658
|
+
* regexGroup: (n: number) => string
|
|
659
|
+
* ) => void,
|
|
660
|
+
* nonMatchingSubstring?: (
|
|
661
|
+
* this: JSONPathTransformerContext<T>,
|
|
662
|
+
* substring: string
|
|
663
|
+
* ) => void,
|
|
664
|
+
* flags?: string
|
|
665
|
+
* }} options - Options object
|
|
666
|
+
* @returns {this}
|
|
667
|
+
*/
|
|
668
|
+
analyzeString (str, regex, options = {}) {
|
|
669
|
+
// Ensure we have a string
|
|
670
|
+
const inputString = String(str || '');
|
|
671
|
+
|
|
672
|
+
// If empty string, do nothing
|
|
673
|
+
if (inputString.length === 0) {
|
|
674
|
+
return this;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
const {
|
|
678
|
+
matchingSubstring,
|
|
679
|
+
nonMatchingSubstring,
|
|
680
|
+
flags = ''
|
|
681
|
+
} = options;
|
|
682
|
+
|
|
683
|
+
// Convert regex to RegExp if it's a string
|
|
684
|
+
let regexObj;
|
|
685
|
+
if (typeof regex === 'string') {
|
|
686
|
+
// Ensure 'g' flag is present for global matching
|
|
687
|
+
const actualFlags = flags.includes('g') ? flags : flags + 'g';
|
|
688
|
+
regexObj = new RegExp(regex, actualFlags);
|
|
689
|
+
} else {
|
|
690
|
+
regexObj = regex;
|
|
691
|
+
// Ensure global flag is set
|
|
692
|
+
if (!regexObj.global) {
|
|
693
|
+
regexObj = new RegExp(
|
|
694
|
+
regexObj.source,
|
|
695
|
+
regexObj.flags + 'g'
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// Check for zero-length matches (error condition in XSLT)
|
|
701
|
+
if (regexObj.test('')) {
|
|
702
|
+
throw new Error(
|
|
703
|
+
'Regular expression matches zero-length string'
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// Store captured groups for access during callback
|
|
708
|
+
/** @type {string[] | undefined} */
|
|
709
|
+
let currentCapturedGroups;
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Get captured group by index.
|
|
713
|
+
* @param {number} groupNumber - Group index
|
|
714
|
+
* @returns {string} - Captured group or empty string
|
|
715
|
+
*/
|
|
716
|
+
const getRegexGroup = (groupNumber) => {
|
|
717
|
+
if (!currentCapturedGroups ||
|
|
718
|
+
groupNumber < 0 ||
|
|
719
|
+
groupNumber >= currentCapturedGroups.length) {
|
|
720
|
+
return '';
|
|
721
|
+
}
|
|
722
|
+
return currentCapturedGroups[groupNumber] || '';
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
// Save previous context to restore later
|
|
726
|
+
const prevContext = this._contextObj;
|
|
727
|
+
|
|
728
|
+
let lastIndex = 0;
|
|
729
|
+
let match;
|
|
730
|
+
|
|
731
|
+
// Bind callbacks to this context
|
|
732
|
+
const boundMatchingSubstring = matchingSubstring
|
|
733
|
+
? matchingSubstring.bind(this)
|
|
734
|
+
: undefined;
|
|
735
|
+
const boundNonMatchingSubstring = nonMatchingSubstring
|
|
736
|
+
? nonMatchingSubstring.bind(this)
|
|
737
|
+
: undefined;
|
|
738
|
+
|
|
739
|
+
// Find all matches
|
|
740
|
+
while ((match = regexObj.exec(inputString)) !== null) {
|
|
741
|
+
// Process non-matching substring before this match
|
|
742
|
+
if (match.index > lastIndex) {
|
|
743
|
+
const nonMatchingStr = inputString.slice(lastIndex, match.index);
|
|
744
|
+
if (boundNonMatchingSubstring) {
|
|
745
|
+
this._contextObj = nonMatchingStr;
|
|
746
|
+
boundNonMatchingSubstring(nonMatchingStr);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Process matching substring
|
|
751
|
+
if (boundMatchingSubstring) {
|
|
752
|
+
const matchingStr = match[0];
|
|
753
|
+
// Store captured groups: [full match, group1, group2, ...]
|
|
754
|
+
currentCapturedGroups = [...match];
|
|
755
|
+
this._contextObj = matchingStr;
|
|
756
|
+
boundMatchingSubstring(
|
|
757
|
+
matchingStr, currentCapturedGroups, getRegexGroup
|
|
758
|
+
);
|
|
759
|
+
currentCapturedGroups = undefined;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
const {lastIndex: newLastIndex} = regexObj;
|
|
763
|
+
lastIndex = newLastIndex;
|
|
764
|
+
|
|
765
|
+
// Prevent infinite loop on zero-length matches (shouldn't happen
|
|
766
|
+
// due to earlier check, but defensive)
|
|
767
|
+
if (match.index === regexObj.lastIndex) {
|
|
768
|
+
regexObj.lastIndex++;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
// Process final non-matching substring
|
|
773
|
+
if (lastIndex < inputString.length) {
|
|
774
|
+
const nonMatchingStr = inputString.slice(lastIndex);
|
|
775
|
+
if (boundNonMatchingSubstring) {
|
|
776
|
+
this._contextObj = nonMatchingStr;
|
|
777
|
+
boundNonMatchingSubstring(nonMatchingStr);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Restore previous context
|
|
782
|
+
this._contextObj = prevContext;
|
|
783
|
+
|
|
784
|
+
return this;
|
|
785
|
+
}
|
|
786
|
+
|
|
630
787
|
/**
|
|
631
788
|
* Deep copy selection or current context when omitted.
|
|
632
789
|
* @param {string} [select] - JSONPath selector
|
|
@@ -735,16 +892,277 @@ class JSONPathTransformerContext {
|
|
|
735
892
|
}
|
|
736
893
|
|
|
737
894
|
/**
|
|
738
|
-
* Append a number to JSON output
|
|
739
|
-
*
|
|
740
|
-
*
|
|
895
|
+
* Append a number to JSON output with xsl:number-like formatting.
|
|
896
|
+
* @param {NumberValue} num - Number value, "position()" string, or
|
|
897
|
+
* options object
|
|
741
898
|
* @returns {this}
|
|
742
899
|
*/
|
|
743
900
|
number (num) {
|
|
744
|
-
|
|
901
|
+
// Handle xsl:number-like functionality
|
|
902
|
+
if (typeof num === 'object' && num !== null) {
|
|
903
|
+
const opts = num;
|
|
904
|
+
let {value} = opts;
|
|
905
|
+
|
|
906
|
+
// Handle position() and hierarchical numbering
|
|
907
|
+
if (value === 'position()' || value === undefined) {
|
|
908
|
+
const {count} = opts;
|
|
909
|
+
// @ts-expect-error: dynamic property access
|
|
910
|
+
const level = opts.level || 'single';
|
|
911
|
+
|
|
912
|
+
switch (level) {
|
|
913
|
+
case 'single': {
|
|
914
|
+
value = this.calculatePosition(count);
|
|
915
|
+
// If count is set, simulate count by returning total items
|
|
916
|
+
// in current context
|
|
917
|
+
if (count) {
|
|
918
|
+
const arr = Array.isArray(this.get(count, true))
|
|
919
|
+
? this.get(count, true)
|
|
920
|
+
/* c8 ignore next -- defensive: get(wrap) always returns array */
|
|
921
|
+
: [];
|
|
922
|
+
value = arr.length;
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
break;
|
|
926
|
+
}
|
|
927
|
+
case 'multiple': {
|
|
928
|
+
// Hierarchical numbering: get position for each ancestor up to root
|
|
929
|
+
const positions = [];
|
|
930
|
+
let state = /** @type {any} */ (this._config).iterationState;
|
|
931
|
+
while (state) {
|
|
932
|
+
// If count is set, use count for each ancestor if possible
|
|
933
|
+
if (count) {
|
|
934
|
+
const arr = Array.isArray(this.get(count, true))
|
|
935
|
+
? this.get(count, true)
|
|
936
|
+
/* c8 ignore next -- defensive: get(wrap) returns array */
|
|
937
|
+
: [];
|
|
938
|
+
positions.unshift(arr.length);
|
|
939
|
+
} else {
|
|
940
|
+
positions.unshift(
|
|
941
|
+
state.index !== undefined
|
|
942
|
+
? state.index + 1
|
|
943
|
+
/* c8 ignore next -- defensive: state always has index */
|
|
944
|
+
: 1
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
state = state.parentState;
|
|
948
|
+
}
|
|
949
|
+
value = positions.join('.');
|
|
950
|
+
|
|
951
|
+
break;
|
|
952
|
+
}
|
|
953
|
+
case 'any': {
|
|
954
|
+
// Count all matching items up to current
|
|
955
|
+
value = this.calculatePosition(count);
|
|
956
|
+
|
|
957
|
+
break;
|
|
958
|
+
}
|
|
959
|
+
// No default
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// Determine format string and locale
|
|
964
|
+
let format = opts.format || '1';
|
|
965
|
+
const locale = opts.lang || 'en';
|
|
966
|
+
const {letterValue} = opts;
|
|
967
|
+
|
|
968
|
+
// If letterValue is 'alphabetic', force alphabetic format
|
|
969
|
+
if (letterValue === 'alphabetic') {
|
|
970
|
+
format = (opts.format && (/^[aA]$/v).test(opts.format)) ? opts.format : 'a';
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// Ensure value is a number or string for formatting
|
|
974
|
+
let numValue = value;
|
|
975
|
+
// If value is undefined, fallback to opts.value
|
|
976
|
+
if (typeof numValue === 'undefined') {
|
|
977
|
+
numValue = opts.value;
|
|
978
|
+
}
|
|
979
|
+
if (typeof numValue === 'string') {
|
|
980
|
+
numValue = Number(numValue);
|
|
981
|
+
}
|
|
982
|
+
if (typeof numValue !== 'number' || Number.isNaN(numValue)) {
|
|
983
|
+
numValue = 1;
|
|
984
|
+
}
|
|
985
|
+
const formatted = this._formatNumber(
|
|
986
|
+
numValue,
|
|
987
|
+
format,
|
|
988
|
+
opts.groupingSeparator,
|
|
989
|
+
opts.groupingSize,
|
|
990
|
+
locale
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
// Output as string if formatted, otherwise as number
|
|
994
|
+
if (format && format !== '1') {
|
|
995
|
+
this._getJoiningTransformer().plainText(formatted);
|
|
996
|
+
} else {
|
|
997
|
+
this._getJoiningTransformer().number(Number(formatted));
|
|
998
|
+
}
|
|
999
|
+
} else if (num === 'position()') {
|
|
1000
|
+
// Simple position() call
|
|
1001
|
+
const pos = this.calculatePosition();
|
|
1002
|
+
this._getJoiningTransformer().number(pos);
|
|
1003
|
+
} else {
|
|
1004
|
+
// Simple number
|
|
1005
|
+
this._getJoiningTransformer().number(
|
|
1006
|
+
typeof num === 'string' ? Number(num) : num
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
745
1009
|
return this;
|
|
746
1010
|
}
|
|
747
1011
|
|
|
1012
|
+
/**
|
|
1013
|
+
* Calculate position in current iteration context.
|
|
1014
|
+
* @param {string} [count] - JSONPath expression to match
|
|
1015
|
+
* @returns {number}
|
|
1016
|
+
*/
|
|
1017
|
+
calculatePosition (count) {
|
|
1018
|
+
// If count is provided, return the length of the matched array from
|
|
1019
|
+
// the root data
|
|
1020
|
+
if (count) {
|
|
1021
|
+
const result = jsonpath({
|
|
1022
|
+
path: count, json: this._origObj, resultType: 'value', wrap: true
|
|
1023
|
+
});
|
|
1024
|
+
if (Array.isArray(result)) {
|
|
1025
|
+
if (result.length === 0) {
|
|
1026
|
+
return 0;
|
|
1027
|
+
}
|
|
1028
|
+
// If the first item is an array, return its length
|
|
1029
|
+
if (Array.isArray(result[0])) {
|
|
1030
|
+
return result[0].length;
|
|
1031
|
+
}
|
|
1032
|
+
// Otherwise, return the number of matches
|
|
1033
|
+
return result.length;
|
|
1034
|
+
}
|
|
1035
|
+
/* c8 ignore next 3 -- defensive:
|
|
1036
|
+
jsonpath-plus with wrap:true always returns arrays */
|
|
1037
|
+
return 0;
|
|
1038
|
+
}
|
|
1039
|
+
// Get current index from iteration state
|
|
1040
|
+
const state = this.iterationState;
|
|
1041
|
+
if (state && typeof state.index === 'number') {
|
|
1042
|
+
return state.index + 1; // 1-indexed
|
|
1043
|
+
}
|
|
1044
|
+
return 1;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/**
|
|
1048
|
+
* Format a number according to format string.
|
|
1049
|
+
* @param {number} num - Number to format
|
|
1050
|
+
* @param {string} format - Format string (1, a, A, i, I, 01, etc.)
|
|
1051
|
+
* @param {string} [groupingSeparator] - Separator for grouping
|
|
1052
|
+
* @param {number} [groupingSize] - Size of groups
|
|
1053
|
+
* @param {string} [locale]
|
|
1054
|
+
* @returns {string}
|
|
1055
|
+
*/
|
|
1056
|
+
_formatNumber (num, format, groupingSeparator, groupingSize, locale = 'en') {
|
|
1057
|
+
if (Number.isNaN(num)) {
|
|
1058
|
+
return String(num);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
let result;
|
|
1062
|
+
const formatChar = format.charAt(0);
|
|
1063
|
+
|
|
1064
|
+
switch (formatChar) {
|
|
1065
|
+
case 'i': {
|
|
1066
|
+
result = this._toRoman(num).toLowerCase();
|
|
1067
|
+
|
|
1068
|
+
break;
|
|
1069
|
+
}
|
|
1070
|
+
case 'I': {
|
|
1071
|
+
result = this._toRoman(num);
|
|
1072
|
+
|
|
1073
|
+
break;
|
|
1074
|
+
}
|
|
1075
|
+
case 'a': {
|
|
1076
|
+
result = this._toAlphabetic(num, false);
|
|
1077
|
+
|
|
1078
|
+
break;
|
|
1079
|
+
}
|
|
1080
|
+
case 'A': {
|
|
1081
|
+
result = this._toAlphabetic(num, true);
|
|
1082
|
+
|
|
1083
|
+
break;
|
|
1084
|
+
}
|
|
1085
|
+
case '0': {
|
|
1086
|
+
const width = format.length;
|
|
1087
|
+
result = String(num).padStart(width, '0');
|
|
1088
|
+
|
|
1089
|
+
break;
|
|
1090
|
+
}
|
|
1091
|
+
default: {
|
|
1092
|
+
// Use Intl.NumberFormat for decimal formatting if grouping/locale
|
|
1093
|
+
// options are provided
|
|
1094
|
+
let options = {};
|
|
1095
|
+
if (groupingSeparator || groupingSize) {
|
|
1096
|
+
options = {
|
|
1097
|
+
useGrouping: true
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
try {
|
|
1102
|
+
result = new Intl.NumberFormat(locale, options).format(num);
|
|
1103
|
+
if (groupingSeparator) {
|
|
1104
|
+
result = result.replaceAll(',', groupingSeparator);
|
|
1105
|
+
}
|
|
1106
|
+
} catch (e) {
|
|
1107
|
+
result = String(num);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
return result;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Convert number to Roman numerals.
|
|
1116
|
+
* @param {number} num - Number to convert (1-3999)
|
|
1117
|
+
* @returns {string}
|
|
1118
|
+
* @private
|
|
1119
|
+
*/
|
|
1120
|
+
// eslint-disable-next-line class-methods-use-this -- Avoid for now
|
|
1121
|
+
_toRoman (num) {
|
|
1122
|
+
if (num < 1 || num > 3999) {
|
|
1123
|
+
return String(num);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
const vals = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
|
|
1127
|
+
const syms = [
|
|
1128
|
+
'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'
|
|
1129
|
+
];
|
|
1130
|
+
|
|
1131
|
+
let result = '';
|
|
1132
|
+
for (const [i, val] of vals.entries()) {
|
|
1133
|
+
while (num >= val) {
|
|
1134
|
+
result += syms[i];
|
|
1135
|
+
num -= val;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
return result;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Convert number to alphabetic sequence.
|
|
1143
|
+
* @param {number} num - Number to convert
|
|
1144
|
+
* @param {boolean} uppercase - Use uppercase letters
|
|
1145
|
+
* @returns {string}
|
|
1146
|
+
* @private
|
|
1147
|
+
*/
|
|
1148
|
+
// eslint-disable-next-line class-methods-use-this -- Avoid for now
|
|
1149
|
+
_toAlphabetic (num, uppercase) {
|
|
1150
|
+
if (num < 1) {
|
|
1151
|
+
return String(num);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
let result = '';
|
|
1155
|
+
const base = uppercase ? 65 : 97; // 'A' or 'a'
|
|
1156
|
+
|
|
1157
|
+
while (num > 0) {
|
|
1158
|
+
num--; // Make 0-indexed
|
|
1159
|
+
result = String.fromCodePoint(base + (num % 26)) + result;
|
|
1160
|
+
num = Math.floor(num / 26);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
return result;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
748
1166
|
/**
|
|
749
1167
|
* Append plain text directly to the output without escaping or JSON
|
|
750
1168
|
* stringification. Mirrors the joining transformer API so templates can
|
package/src/XPathTransformer.js
CHANGED
|
@@ -6,7 +6,7 @@ import XPathTransformerContext from './XPathTransformerContext.js';
|
|
|
6
6
|
* @property {boolean} [errorOnEqualPriority] Throw on equal priority
|
|
7
7
|
* @property {import('./index.js').
|
|
8
8
|
* XPathTemplateArray<T>} templates Template objects
|
|
9
|
-
* @property {number} [xpathVersion] XPath version (1|2)
|
|
9
|
+
* @property {number} [xpathVersion] XPath version (1|2|3.1)
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/**
|