@optionfactory/fml 9.0.0-rc3 → 9.0.0-rc31
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/README.md +16 -88
- package/dist/client-errors.iife.js +40 -49
- package/dist/client-errors.iife.js.map +1 -1
- package/dist/client-errors.iife.min.js +1 -1
- package/dist/client-errors.iife.min.js.map +1 -1
- package/dist/custom-elements.json +491 -51
- package/dist/fml.css +25 -20
- package/dist/fml.css.map +1 -1
- package/dist/fml.iife.js +5866 -2563
- package/dist/fml.iife.js.map +1 -1
- package/dist/fml.iife.min.js +1 -1
- package/dist/fml.iife.min.js.map +1 -1
- package/dist/ftl.d.mts +425 -231
- package/dist/ftl.iife.js +774 -1044
- package/dist/ftl.iife.js.map +1 -1
- package/dist/ftl.iife.min.js +1 -1
- package/dist/ftl.iife.min.js.map +1 -1
- package/dist/ftl.min.mjs +1 -1
- package/dist/ftl.min.mjs.map +1 -1
- package/dist/ftl.mjs +774 -1044
- package/dist/ftl.mjs.map +1 -1
- package/dist/ful.css +25 -20
- package/dist/ful.css.map +1 -1
- package/dist/ful.d.mts +3048 -556
- package/dist/ful.iife.js +4977 -1395
- package/dist/ful.iife.js.map +1 -1
- package/dist/ful.iife.min.js +1 -1
- package/dist/ful.iife.min.js.map +1 -1
- package/dist/ful.min.mjs +1 -1
- package/dist/ful.min.mjs.map +1 -1
- package/dist/ful.mjs +4975 -1396
- package/dist/ful.mjs.map +1 -1
- package/dist/httpc.d.mts +143 -123
- package/dist/httpc.iife.js +163 -175
- package/dist/httpc.iife.js.map +1 -1
- package/dist/httpc.iife.min.js +1 -1
- package/dist/httpc.iife.min.js.map +1 -1
- package/dist/httpc.min.mjs +1 -1
- package/dist/httpc.min.mjs.map +1 -1
- package/dist/httpc.mjs +163 -175
- package/dist/httpc.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +239 -39
- package/dist/web-types.json +498 -51
- package/package.json +2 -2
package/dist/ftl.iife.js
CHANGED
|
@@ -2,12 +2,8 @@ var ftl = (function (exports) {
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* A Map bounded by entry count, evicting
|
|
6
|
-
*
|
|
7
|
-
* expressions, compiled masks, formatter instances) from growing forever. The
|
|
8
|
-
* capacity is sized so eviction never happens on a sane page: hitting it means
|
|
9
|
-
* dynamically generated keys, where FIFO's worst case (evicting a hot entry)
|
|
10
|
-
* costs one recomputation.
|
|
5
|
+
* A Map bounded by entry count, evicting the oldest entry when full. A hit does
|
|
6
|
+
* not refresh an entry: eviction follows insertion order, not use.
|
|
11
7
|
*/
|
|
12
8
|
class BoundedCache {
|
|
13
9
|
#max;
|
|
@@ -36,6 +32,7 @@ var ftl = (function (exports) {
|
|
|
36
32
|
this.#entries.set(key, value);
|
|
37
33
|
return value;
|
|
38
34
|
}
|
|
35
|
+
/** @returns {number} the number of entries held */
|
|
39
36
|
get size() {
|
|
40
37
|
return this.#entries.size;
|
|
41
38
|
}
|
|
@@ -74,14 +71,10 @@ var ftl = (function (exports) {
|
|
|
74
71
|
},
|
|
75
72
|
};
|
|
76
73
|
|
|
77
|
-
// @generated by Peggy 5.1.
|
|
74
|
+
// @generated by Peggy 5.1.1.
|
|
78
75
|
//
|
|
79
76
|
// https://peggyjs.org/
|
|
80
77
|
|
|
81
|
-
//keyword classification lives here, not in the grammar's ordered choice: the
|
|
82
|
-
//identifier rule consumes the whole word and the action decides, so no keyword
|
|
83
|
-
//can grab a longer identifier's prefix. A Map, not a plain object: `in` on the
|
|
84
|
-
//latter would classify inherited names such as `constructor` as keywords
|
|
85
78
|
const keywords = new Map([
|
|
86
79
|
['true', true],
|
|
87
80
|
['false', false],
|
|
@@ -144,10 +137,9 @@ var ftl = (function (exports) {
|
|
|
144
137
|
return s;
|
|
145
138
|
}
|
|
146
139
|
|
|
147
|
-
function
|
|
140
|
+
function escape(s, special) {
|
|
148
141
|
return unicodeEscape(s
|
|
149
|
-
.replace(
|
|
150
|
-
.replace(/"/g, "\\\"")
|
|
142
|
+
.replace(special, "\\$&")
|
|
151
143
|
.replace(/\0/g, "\\0")
|
|
152
144
|
.replace(/\t/g, "\\t")
|
|
153
145
|
.replace(/\n/g, "\\n")
|
|
@@ -156,18 +148,12 @@ var ftl = (function (exports) {
|
|
|
156
148
|
.replace(/[\x10-\x1F\x7F-\x9F]/g, ch => "\\x" + hex(ch)));
|
|
157
149
|
}
|
|
158
150
|
|
|
151
|
+
function literalEscape(s) {
|
|
152
|
+
return escape(s, /[\\"]/g);
|
|
153
|
+
}
|
|
154
|
+
|
|
159
155
|
function classEscape(s) {
|
|
160
|
-
return
|
|
161
|
-
.replace(/\\/g, "\\\\")
|
|
162
|
-
.replace(/\]/g, "\\]")
|
|
163
|
-
.replace(/\^/g, "\\^")
|
|
164
|
-
.replace(/-/g, "\\-")
|
|
165
|
-
.replace(/\0/g, "\\0")
|
|
166
|
-
.replace(/\t/g, "\\t")
|
|
167
|
-
.replace(/\n/g, "\\n")
|
|
168
|
-
.replace(/\r/g, "\\r")
|
|
169
|
-
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
|
170
|
-
.replace(/[\x10-\x1F\x7F-\x9F]/g, ch => "\\x" + hex(ch)));
|
|
156
|
+
return escape(s, /[\\\]^-]/g);
|
|
171
157
|
}
|
|
172
158
|
|
|
173
159
|
const DESCRIBE_EXPECTATION_FNS = {
|
|
@@ -285,14 +271,6 @@ var ftl = (function (exports) {
|
|
|
285
271
|
const peg$c53 = "<=";
|
|
286
272
|
const peg$c54 = "<";
|
|
287
273
|
|
|
288
|
-
const peg$r0 = /^[^\\{]/;
|
|
289
|
-
const peg$r1 = /^[0-9]/;
|
|
290
|
-
const peg$r2 = /^[^']/;
|
|
291
|
-
const peg$r3 = /^[^"]/;
|
|
292
|
-
const peg$r4 = /^[^\\`{]/;
|
|
293
|
-
const peg$r5 = /^[a-zA-Z$_]/;
|
|
294
|
-
const peg$r6 = /^[a-zA-Z$_0-9]/;
|
|
295
|
-
const peg$r7 = /^[ \t\n\r]/;
|
|
296
274
|
|
|
297
275
|
const peg$e0 = peg$literalExpectation("{{{{", false);
|
|
298
276
|
const peg$e1 = peg$literalExpectation("}}}}", false);
|
|
@@ -450,9 +428,10 @@ var ftl = (function (exports) {
|
|
|
450
428
|
let peg$maxFailExpected = options.peg$maxFailExpected || [];
|
|
451
429
|
let peg$silentFails = options.peg$silentFails | 0;
|
|
452
430
|
|
|
453
|
-
let peg$resultsCache =
|
|
431
|
+
let peg$resultsCache = new Map();
|
|
454
432
|
|
|
455
433
|
let peg$result;
|
|
434
|
+
let peg$charCode;
|
|
456
435
|
|
|
457
436
|
if (options.startRule) {
|
|
458
437
|
if (!(options.startRule in peg$startRuleFunctions)) {
|
|
@@ -571,7 +550,7 @@ var ftl = (function (exports) {
|
|
|
571
550
|
let s0, s1;
|
|
572
551
|
|
|
573
552
|
const key = peg$currPos * 38 + 0;
|
|
574
|
-
const cached = peg$resultsCache
|
|
553
|
+
const cached = peg$resultsCache.get(key);
|
|
575
554
|
|
|
576
555
|
if (cached) {
|
|
577
556
|
peg$currPos = cached.nextPos;
|
|
@@ -580,13 +559,13 @@ var ftl = (function (exports) {
|
|
|
580
559
|
}
|
|
581
560
|
|
|
582
561
|
s0 = [];
|
|
583
|
-
|
|
584
|
-
while (s1 !== peg$FAILED) {
|
|
585
|
-
s0.push(s1);
|
|
562
|
+
for (;;) {
|
|
586
563
|
s1 = peg$parseTemplatedExpression();
|
|
564
|
+
if (s1 === peg$FAILED) { break; }
|
|
565
|
+
s0.push(s1);
|
|
587
566
|
}
|
|
588
567
|
|
|
589
|
-
peg$resultsCache
|
|
568
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
590
569
|
|
|
591
570
|
return s0;
|
|
592
571
|
}
|
|
@@ -595,7 +574,7 @@ var ftl = (function (exports) {
|
|
|
595
574
|
let s0, s1, s2, s3, s4;
|
|
596
575
|
|
|
597
576
|
const key = peg$currPos * 38 + 1;
|
|
598
|
-
const cached = peg$resultsCache
|
|
577
|
+
const cached = peg$resultsCache.get(key);
|
|
599
578
|
|
|
600
579
|
if (cached) {
|
|
601
580
|
peg$currPos = cached.nextPos;
|
|
@@ -691,7 +670,7 @@ var ftl = (function (exports) {
|
|
|
691
670
|
}
|
|
692
671
|
}
|
|
693
672
|
|
|
694
|
-
peg$resultsCache
|
|
673
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
695
674
|
|
|
696
675
|
return s0;
|
|
697
676
|
}
|
|
@@ -700,7 +679,7 @@ var ftl = (function (exports) {
|
|
|
700
679
|
let s0;
|
|
701
680
|
|
|
702
681
|
const key = peg$currPos * 38 + 2;
|
|
703
|
-
const cached = peg$resultsCache
|
|
682
|
+
const cached = peg$resultsCache.get(key);
|
|
704
683
|
|
|
705
684
|
if (cached) {
|
|
706
685
|
peg$currPos = cached.nextPos;
|
|
@@ -716,7 +695,7 @@ var ftl = (function (exports) {
|
|
|
716
695
|
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
|
717
696
|
}
|
|
718
697
|
|
|
719
|
-
peg$resultsCache
|
|
698
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
720
699
|
|
|
721
700
|
return s0;
|
|
722
701
|
}
|
|
@@ -725,7 +704,7 @@ var ftl = (function (exports) {
|
|
|
725
704
|
let s0;
|
|
726
705
|
|
|
727
706
|
const key = peg$currPos * 38 + 3;
|
|
728
|
-
const cached = peg$resultsCache
|
|
707
|
+
const cached = peg$resultsCache.get(key);
|
|
729
708
|
|
|
730
709
|
if (cached) {
|
|
731
710
|
peg$currPos = cached.nextPos;
|
|
@@ -741,7 +720,7 @@ var ftl = (function (exports) {
|
|
|
741
720
|
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
|
742
721
|
}
|
|
743
722
|
|
|
744
|
-
peg$resultsCache
|
|
723
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
745
724
|
|
|
746
725
|
return s0;
|
|
747
726
|
}
|
|
@@ -750,7 +729,7 @@ var ftl = (function (exports) {
|
|
|
750
729
|
let s0;
|
|
751
730
|
|
|
752
731
|
const key = peg$currPos * 38 + 4;
|
|
753
|
-
const cached = peg$resultsCache
|
|
732
|
+
const cached = peg$resultsCache.get(key);
|
|
754
733
|
|
|
755
734
|
if (cached) {
|
|
756
735
|
peg$currPos = cached.nextPos;
|
|
@@ -766,7 +745,7 @@ var ftl = (function (exports) {
|
|
|
766
745
|
if (peg$silentFails === 0) { peg$fail(peg$e2); }
|
|
767
746
|
}
|
|
768
747
|
|
|
769
|
-
peg$resultsCache
|
|
748
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
770
749
|
|
|
771
750
|
return s0;
|
|
772
751
|
}
|
|
@@ -775,7 +754,7 @@ var ftl = (function (exports) {
|
|
|
775
754
|
let s0;
|
|
776
755
|
|
|
777
756
|
const key = peg$currPos * 38 + 5;
|
|
778
|
-
const cached = peg$resultsCache
|
|
757
|
+
const cached = peg$resultsCache.get(key);
|
|
779
758
|
|
|
780
759
|
if (cached) {
|
|
781
760
|
peg$currPos = cached.nextPos;
|
|
@@ -791,7 +770,7 @@ var ftl = (function (exports) {
|
|
|
791
770
|
if (peg$silentFails === 0) { peg$fail(peg$e3); }
|
|
792
771
|
}
|
|
793
772
|
|
|
794
|
-
peg$resultsCache
|
|
773
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
795
774
|
|
|
796
775
|
return s0;
|
|
797
776
|
}
|
|
@@ -800,7 +779,7 @@ var ftl = (function (exports) {
|
|
|
800
779
|
let s0;
|
|
801
780
|
|
|
802
781
|
const key = peg$currPos * 38 + 6;
|
|
803
|
-
const cached = peg$resultsCache
|
|
782
|
+
const cached = peg$resultsCache.get(key);
|
|
804
783
|
|
|
805
784
|
if (cached) {
|
|
806
785
|
peg$currPos = cached.nextPos;
|
|
@@ -816,7 +795,7 @@ var ftl = (function (exports) {
|
|
|
816
795
|
if (peg$silentFails === 0) { peg$fail(peg$e4); }
|
|
817
796
|
}
|
|
818
797
|
|
|
819
|
-
peg$resultsCache
|
|
798
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
820
799
|
|
|
821
800
|
return s0;
|
|
822
801
|
}
|
|
@@ -825,7 +804,7 @@ var ftl = (function (exports) {
|
|
|
825
804
|
let s0;
|
|
826
805
|
|
|
827
806
|
const key = peg$currPos * 38 + 7;
|
|
828
|
-
const cached = peg$resultsCache
|
|
807
|
+
const cached = peg$resultsCache.get(key);
|
|
829
808
|
|
|
830
809
|
if (cached) {
|
|
831
810
|
peg$currPos = cached.nextPos;
|
|
@@ -841,7 +820,7 @@ var ftl = (function (exports) {
|
|
|
841
820
|
if (peg$silentFails === 0) { peg$fail(peg$e5); }
|
|
842
821
|
}
|
|
843
822
|
|
|
844
|
-
peg$resultsCache
|
|
823
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
845
824
|
|
|
846
825
|
return s0;
|
|
847
826
|
}
|
|
@@ -850,7 +829,7 @@ var ftl = (function (exports) {
|
|
|
850
829
|
let s0, s1, s2, s3, s4, s5, s6;
|
|
851
830
|
|
|
852
831
|
const key = peg$currPos * 38 + 8;
|
|
853
|
-
const cached = peg$resultsCache
|
|
832
|
+
const cached = peg$resultsCache.get(key);
|
|
854
833
|
|
|
855
834
|
if (cached) {
|
|
856
835
|
peg$currPos = cached.nextPos;
|
|
@@ -860,211 +839,104 @@ var ftl = (function (exports) {
|
|
|
860
839
|
|
|
861
840
|
s0 = peg$currPos;
|
|
862
841
|
s1 = [];
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
peg$currPos++;
|
|
868
|
-
} else {
|
|
869
|
-
s4 = peg$FAILED;
|
|
870
|
-
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
871
|
-
}
|
|
872
|
-
if (s4 !== peg$FAILED) {
|
|
873
|
-
while (s4 !== peg$FAILED) {
|
|
874
|
-
s3.push(s4);
|
|
842
|
+
for (;;) {
|
|
843
|
+
s2 = peg$currPos;
|
|
844
|
+
s3 = [];
|
|
845
|
+
for (;;) {
|
|
875
846
|
s4 = input.charAt(peg$currPos);
|
|
876
|
-
if (peg$
|
|
847
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 92 || peg$charCode === 123)) {
|
|
877
848
|
peg$currPos++;
|
|
878
849
|
} else {
|
|
879
850
|
s4 = peg$FAILED;
|
|
880
851
|
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
881
852
|
}
|
|
853
|
+
if (s4 === peg$FAILED) { break; }
|
|
854
|
+
s3.push(s4);
|
|
882
855
|
}
|
|
883
|
-
|
|
884
|
-
s3 = peg$FAILED;
|
|
885
|
-
}
|
|
886
|
-
if (s3 !== peg$FAILED) {
|
|
887
|
-
s2 = input.substring(s2, peg$currPos);
|
|
888
|
-
} else {
|
|
889
|
-
s2 = s3;
|
|
890
|
-
}
|
|
891
|
-
if (s2 === peg$FAILED) {
|
|
892
|
-
s2 = peg$currPos;
|
|
893
|
-
if (input.charCodeAt(peg$currPos) === 92) {
|
|
894
|
-
s3 = peg$c7;
|
|
895
|
-
peg$currPos++;
|
|
896
|
-
} else {
|
|
856
|
+
if (s3.length < 1) {
|
|
897
857
|
s3 = peg$FAILED;
|
|
898
|
-
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
899
858
|
}
|
|
900
859
|
if (s3 !== peg$FAILED) {
|
|
901
|
-
|
|
902
|
-
s4 = input.charAt(peg$currPos);
|
|
903
|
-
peg$currPos++;
|
|
904
|
-
} else {
|
|
905
|
-
s4 = peg$FAILED;
|
|
906
|
-
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
907
|
-
}
|
|
908
|
-
if (s4 !== peg$FAILED) {
|
|
909
|
-
s2 = peg$f4(s4);
|
|
910
|
-
} else {
|
|
911
|
-
peg$currPos = s2;
|
|
912
|
-
s2 = peg$FAILED;
|
|
913
|
-
}
|
|
860
|
+
s2 = input.substring(s2, peg$currPos);
|
|
914
861
|
} else {
|
|
915
|
-
|
|
916
|
-
s2 = peg$FAILED;
|
|
862
|
+
s2 = s3;
|
|
917
863
|
}
|
|
918
864
|
if (s2 === peg$FAILED) {
|
|
919
865
|
s2 = peg$currPos;
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
s4 = peg$c9;
|
|
866
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
867
|
+
s3 = peg$c7;
|
|
923
868
|
peg$currPos++;
|
|
924
869
|
} else {
|
|
925
|
-
|
|
926
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
870
|
+
s3 = peg$FAILED;
|
|
871
|
+
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
927
872
|
}
|
|
928
|
-
if (
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
if (input.charCodeAt(peg$currPos) === 123) {
|
|
932
|
-
s6 = peg$c9;
|
|
873
|
+
if (s3 !== peg$FAILED) {
|
|
874
|
+
if (input.length > peg$currPos) {
|
|
875
|
+
s4 = input.charAt(peg$currPos);
|
|
933
876
|
peg$currPos++;
|
|
934
877
|
} else {
|
|
935
|
-
|
|
936
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
937
|
-
}
|
|
938
|
-
peg$silentFails--;
|
|
939
|
-
if (s6 === peg$FAILED) {
|
|
940
|
-
s5 = undefined;
|
|
941
|
-
} else {
|
|
942
|
-
peg$currPos = s5;
|
|
943
|
-
s5 = peg$FAILED;
|
|
878
|
+
s4 = peg$FAILED;
|
|
879
|
+
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
944
880
|
}
|
|
945
|
-
if (
|
|
946
|
-
|
|
947
|
-
s3 = s4;
|
|
881
|
+
if (s4 !== peg$FAILED) {
|
|
882
|
+
s2 = peg$f4(s4);
|
|
948
883
|
} else {
|
|
949
|
-
peg$currPos =
|
|
950
|
-
|
|
951
|
-
}
|
|
952
|
-
} else {
|
|
953
|
-
peg$currPos = s3;
|
|
954
|
-
s3 = peg$FAILED;
|
|
955
|
-
}
|
|
956
|
-
if (s3 !== peg$FAILED) {
|
|
957
|
-
s2 = input.substring(s2, peg$currPos);
|
|
958
|
-
} else {
|
|
959
|
-
s2 = s3;
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
if (s2 !== peg$FAILED) {
|
|
964
|
-
while (s2 !== peg$FAILED) {
|
|
965
|
-
s1.push(s2);
|
|
966
|
-
s2 = peg$currPos;
|
|
967
|
-
s3 = [];
|
|
968
|
-
s4 = input.charAt(peg$currPos);
|
|
969
|
-
if (peg$r0.test(s4)) {
|
|
970
|
-
peg$currPos++;
|
|
971
|
-
} else {
|
|
972
|
-
s4 = peg$FAILED;
|
|
973
|
-
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
974
|
-
}
|
|
975
|
-
if (s4 !== peg$FAILED) {
|
|
976
|
-
while (s4 !== peg$FAILED) {
|
|
977
|
-
s3.push(s4);
|
|
978
|
-
s4 = input.charAt(peg$currPos);
|
|
979
|
-
if (peg$r0.test(s4)) {
|
|
980
|
-
peg$currPos++;
|
|
981
|
-
} else {
|
|
982
|
-
s4 = peg$FAILED;
|
|
983
|
-
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
984
|
-
}
|
|
884
|
+
peg$currPos = s2;
|
|
885
|
+
s2 = peg$FAILED;
|
|
985
886
|
}
|
|
986
887
|
} else {
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
if (s3 !== peg$FAILED) {
|
|
990
|
-
s2 = input.substring(s2, peg$currPos);
|
|
991
|
-
} else {
|
|
992
|
-
s2 = s3;
|
|
888
|
+
peg$currPos = s2;
|
|
889
|
+
s2 = peg$FAILED;
|
|
993
890
|
}
|
|
994
891
|
if (s2 === peg$FAILED) {
|
|
995
892
|
s2 = peg$currPos;
|
|
996
|
-
|
|
997
|
-
|
|
893
|
+
s3 = peg$currPos;
|
|
894
|
+
if (input.charCodeAt(peg$currPos) === 123) {
|
|
895
|
+
s4 = peg$c9;
|
|
998
896
|
peg$currPos++;
|
|
999
897
|
} else {
|
|
1000
|
-
|
|
1001
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
1002
|
-
}
|
|
1003
|
-
if (s3 !== peg$FAILED) {
|
|
1004
|
-
if (input.length > peg$currPos) {
|
|
1005
|
-
s4 = input.charAt(peg$currPos);
|
|
1006
|
-
peg$currPos++;
|
|
1007
|
-
} else {
|
|
1008
|
-
s4 = peg$FAILED;
|
|
1009
|
-
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
1010
|
-
}
|
|
1011
|
-
if (s4 !== peg$FAILED) {
|
|
1012
|
-
s2 = peg$f4(s4);
|
|
1013
|
-
} else {
|
|
1014
|
-
peg$currPos = s2;
|
|
1015
|
-
s2 = peg$FAILED;
|
|
1016
|
-
}
|
|
1017
|
-
} else {
|
|
1018
|
-
peg$currPos = s2;
|
|
1019
|
-
s2 = peg$FAILED;
|
|
898
|
+
s4 = peg$FAILED;
|
|
899
|
+
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
|
1020
900
|
}
|
|
1021
|
-
if (
|
|
1022
|
-
|
|
1023
|
-
|
|
901
|
+
if (s4 !== peg$FAILED) {
|
|
902
|
+
s5 = peg$currPos;
|
|
903
|
+
peg$silentFails++;
|
|
1024
904
|
if (input.charCodeAt(peg$currPos) === 123) {
|
|
1025
|
-
|
|
905
|
+
s6 = peg$c9;
|
|
1026
906
|
peg$currPos++;
|
|
1027
907
|
} else {
|
|
1028
|
-
|
|
908
|
+
s6 = peg$FAILED;
|
|
1029
909
|
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
|
1030
910
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
if (input.charCodeAt(peg$currPos) === 123) {
|
|
1035
|
-
s6 = peg$c9;
|
|
1036
|
-
peg$currPos++;
|
|
1037
|
-
} else {
|
|
1038
|
-
s6 = peg$FAILED;
|
|
1039
|
-
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
|
1040
|
-
}
|
|
1041
|
-
peg$silentFails--;
|
|
1042
|
-
if (s6 === peg$FAILED) {
|
|
1043
|
-
s5 = undefined;
|
|
1044
|
-
} else {
|
|
1045
|
-
peg$currPos = s5;
|
|
1046
|
-
s5 = peg$FAILED;
|
|
1047
|
-
}
|
|
1048
|
-
if (s5 !== peg$FAILED) {
|
|
1049
|
-
s4 = [s4, s5];
|
|
1050
|
-
s3 = s4;
|
|
1051
|
-
} else {
|
|
1052
|
-
peg$currPos = s3;
|
|
1053
|
-
s3 = peg$FAILED;
|
|
1054
|
-
}
|
|
911
|
+
peg$silentFails--;
|
|
912
|
+
if (s6 === peg$FAILED) {
|
|
913
|
+
s5 = undefined;
|
|
1055
914
|
} else {
|
|
1056
|
-
peg$currPos =
|
|
1057
|
-
|
|
915
|
+
peg$currPos = s5;
|
|
916
|
+
s5 = peg$FAILED;
|
|
1058
917
|
}
|
|
1059
|
-
if (
|
|
1060
|
-
|
|
918
|
+
if (s5 !== peg$FAILED) {
|
|
919
|
+
s4 = [s4, s5];
|
|
920
|
+
s3 = s4;
|
|
1061
921
|
} else {
|
|
1062
|
-
|
|
922
|
+
peg$currPos = s3;
|
|
923
|
+
s3 = peg$FAILED;
|
|
1063
924
|
}
|
|
925
|
+
} else {
|
|
926
|
+
peg$currPos = s3;
|
|
927
|
+
s3 = peg$FAILED;
|
|
928
|
+
}
|
|
929
|
+
if (s3 !== peg$FAILED) {
|
|
930
|
+
s2 = input.substring(s2, peg$currPos);
|
|
931
|
+
} else {
|
|
932
|
+
s2 = s3;
|
|
1064
933
|
}
|
|
1065
934
|
}
|
|
1066
935
|
}
|
|
1067
|
-
|
|
936
|
+
if (s2 === peg$FAILED) { break; }
|
|
937
|
+
s1.push(s2);
|
|
938
|
+
}
|
|
939
|
+
if (s1.length < 1) {
|
|
1068
940
|
s1 = peg$FAILED;
|
|
1069
941
|
}
|
|
1070
942
|
if (s1 !== peg$FAILED) {
|
|
@@ -1072,7 +944,7 @@ var ftl = (function (exports) {
|
|
|
1072
944
|
}
|
|
1073
945
|
s0 = s1;
|
|
1074
946
|
|
|
1075
|
-
peg$resultsCache
|
|
947
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1076
948
|
|
|
1077
949
|
return s0;
|
|
1078
950
|
}
|
|
@@ -1081,7 +953,7 @@ var ftl = (function (exports) {
|
|
|
1081
953
|
let s0, s2;
|
|
1082
954
|
|
|
1083
955
|
const key = peg$currPos * 38 + 9;
|
|
1084
|
-
const cached = peg$resultsCache
|
|
956
|
+
const cached = peg$resultsCache.get(key);
|
|
1085
957
|
|
|
1086
958
|
if (cached) {
|
|
1087
959
|
peg$currPos = cached.nextPos;
|
|
@@ -1100,7 +972,7 @@ var ftl = (function (exports) {
|
|
|
1100
972
|
s0 = peg$FAILED;
|
|
1101
973
|
}
|
|
1102
974
|
|
|
1103
|
-
peg$resultsCache
|
|
975
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1104
976
|
|
|
1105
977
|
return s0;
|
|
1106
978
|
}
|
|
@@ -1109,7 +981,7 @@ var ftl = (function (exports) {
|
|
|
1109
981
|
let s0, s1, s3, s5, s7, s9;
|
|
1110
982
|
|
|
1111
983
|
const key = peg$currPos * 38 + 10;
|
|
1112
|
-
const cached = peg$resultsCache
|
|
984
|
+
const cached = peg$resultsCache.get(key);
|
|
1113
985
|
|
|
1114
986
|
if (cached) {
|
|
1115
987
|
peg$currPos = cached.nextPos;
|
|
@@ -1169,7 +1041,7 @@ var ftl = (function (exports) {
|
|
|
1169
1041
|
s0 = peg$parseElvisExpression();
|
|
1170
1042
|
}
|
|
1171
1043
|
|
|
1172
|
-
peg$resultsCache
|
|
1044
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1173
1045
|
|
|
1174
1046
|
return s0;
|
|
1175
1047
|
}
|
|
@@ -1178,7 +1050,7 @@ var ftl = (function (exports) {
|
|
|
1178
1050
|
let s0, s1, s3, s5;
|
|
1179
1051
|
|
|
1180
1052
|
const key = peg$currPos * 38 + 11;
|
|
1181
|
-
const cached = peg$resultsCache
|
|
1053
|
+
const cached = peg$resultsCache.get(key);
|
|
1182
1054
|
|
|
1183
1055
|
if (cached) {
|
|
1184
1056
|
peg$currPos = cached.nextPos;
|
|
@@ -1218,7 +1090,7 @@ var ftl = (function (exports) {
|
|
|
1218
1090
|
s0 = peg$parseNullCoalescingExpression();
|
|
1219
1091
|
}
|
|
1220
1092
|
|
|
1221
|
-
peg$resultsCache
|
|
1093
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1222
1094
|
|
|
1223
1095
|
return s0;
|
|
1224
1096
|
}
|
|
@@ -1227,7 +1099,7 @@ var ftl = (function (exports) {
|
|
|
1227
1099
|
let s0, s1, s3, s5;
|
|
1228
1100
|
|
|
1229
1101
|
const key = peg$currPos * 38 + 12;
|
|
1230
|
-
const cached = peg$resultsCache
|
|
1102
|
+
const cached = peg$resultsCache.get(key);
|
|
1231
1103
|
|
|
1232
1104
|
if (cached) {
|
|
1233
1105
|
peg$currPos = cached.nextPos;
|
|
@@ -1267,7 +1139,7 @@ var ftl = (function (exports) {
|
|
|
1267
1139
|
s0 = peg$parseOrExpression();
|
|
1268
1140
|
}
|
|
1269
1141
|
|
|
1270
|
-
peg$resultsCache
|
|
1142
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1271
1143
|
|
|
1272
1144
|
return s0;
|
|
1273
1145
|
}
|
|
@@ -1276,7 +1148,7 @@ var ftl = (function (exports) {
|
|
|
1276
1148
|
let s0, s1, s2, s3, s5, s7;
|
|
1277
1149
|
|
|
1278
1150
|
const key = peg$currPos * 38 + 13;
|
|
1279
|
-
const cached = peg$resultsCache
|
|
1151
|
+
const cached = peg$resultsCache.get(key);
|
|
1280
1152
|
|
|
1281
1153
|
if (cached) {
|
|
1282
1154
|
peg$currPos = cached.nextPos;
|
|
@@ -1288,30 +1160,7 @@ var ftl = (function (exports) {
|
|
|
1288
1160
|
s1 = peg$parseAndExpression();
|
|
1289
1161
|
if (s1 !== peg$FAILED) {
|
|
1290
1162
|
s2 = [];
|
|
1291
|
-
|
|
1292
|
-
peg$parse_();
|
|
1293
|
-
if (input.substr(peg$currPos, 2) === peg$c22) {
|
|
1294
|
-
s5 = peg$c22;
|
|
1295
|
-
peg$currPos += 2;
|
|
1296
|
-
} else {
|
|
1297
|
-
s5 = peg$FAILED;
|
|
1298
|
-
if (peg$silentFails === 0) { peg$fail(peg$e14); }
|
|
1299
|
-
}
|
|
1300
|
-
if (s5 !== peg$FAILED) {
|
|
1301
|
-
peg$parse_();
|
|
1302
|
-
s7 = peg$parseAndExpression();
|
|
1303
|
-
if (s7 !== peg$FAILED) {
|
|
1304
|
-
s3 = s7;
|
|
1305
|
-
} else {
|
|
1306
|
-
peg$currPos = s3;
|
|
1307
|
-
s3 = peg$FAILED;
|
|
1308
|
-
}
|
|
1309
|
-
} else {
|
|
1310
|
-
peg$currPos = s3;
|
|
1311
|
-
s3 = peg$FAILED;
|
|
1312
|
-
}
|
|
1313
|
-
while (s3 !== peg$FAILED) {
|
|
1314
|
-
s2.push(s3);
|
|
1163
|
+
for (;;) {
|
|
1315
1164
|
s3 = peg$currPos;
|
|
1316
1165
|
peg$parse_();
|
|
1317
1166
|
if (input.substr(peg$currPos, 2) === peg$c22) {
|
|
@@ -1334,6 +1183,8 @@ var ftl = (function (exports) {
|
|
|
1334
1183
|
peg$currPos = s3;
|
|
1335
1184
|
s3 = peg$FAILED;
|
|
1336
1185
|
}
|
|
1186
|
+
if (s3 === peg$FAILED) { break; }
|
|
1187
|
+
s2.push(s3);
|
|
1337
1188
|
}
|
|
1338
1189
|
s0 = peg$f10(s1, s2);
|
|
1339
1190
|
} else {
|
|
@@ -1341,7 +1192,7 @@ var ftl = (function (exports) {
|
|
|
1341
1192
|
s0 = peg$FAILED;
|
|
1342
1193
|
}
|
|
1343
1194
|
|
|
1344
|
-
peg$resultsCache
|
|
1195
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1345
1196
|
|
|
1346
1197
|
return s0;
|
|
1347
1198
|
}
|
|
@@ -1350,7 +1201,7 @@ var ftl = (function (exports) {
|
|
|
1350
1201
|
let s0, s1, s2, s3, s5, s7;
|
|
1351
1202
|
|
|
1352
1203
|
const key = peg$currPos * 38 + 14;
|
|
1353
|
-
const cached = peg$resultsCache
|
|
1204
|
+
const cached = peg$resultsCache.get(key);
|
|
1354
1205
|
|
|
1355
1206
|
if (cached) {
|
|
1356
1207
|
peg$currPos = cached.nextPos;
|
|
@@ -1362,30 +1213,7 @@ var ftl = (function (exports) {
|
|
|
1362
1213
|
s1 = peg$parseEqExpression();
|
|
1363
1214
|
if (s1 !== peg$FAILED) {
|
|
1364
1215
|
s2 = [];
|
|
1365
|
-
|
|
1366
|
-
peg$parse_();
|
|
1367
|
-
if (input.substr(peg$currPos, 2) === peg$c24) {
|
|
1368
|
-
s5 = peg$c24;
|
|
1369
|
-
peg$currPos += 2;
|
|
1370
|
-
} else {
|
|
1371
|
-
s5 = peg$FAILED;
|
|
1372
|
-
if (peg$silentFails === 0) { peg$fail(peg$e15); }
|
|
1373
|
-
}
|
|
1374
|
-
if (s5 !== peg$FAILED) {
|
|
1375
|
-
peg$parse_();
|
|
1376
|
-
s7 = peg$parseEqExpression();
|
|
1377
|
-
if (s7 !== peg$FAILED) {
|
|
1378
|
-
s3 = s7;
|
|
1379
|
-
} else {
|
|
1380
|
-
peg$currPos = s3;
|
|
1381
|
-
s3 = peg$FAILED;
|
|
1382
|
-
}
|
|
1383
|
-
} else {
|
|
1384
|
-
peg$currPos = s3;
|
|
1385
|
-
s3 = peg$FAILED;
|
|
1386
|
-
}
|
|
1387
|
-
while (s3 !== peg$FAILED) {
|
|
1388
|
-
s2.push(s3);
|
|
1216
|
+
for (;;) {
|
|
1389
1217
|
s3 = peg$currPos;
|
|
1390
1218
|
peg$parse_();
|
|
1391
1219
|
if (input.substr(peg$currPos, 2) === peg$c24) {
|
|
@@ -1408,6 +1236,8 @@ var ftl = (function (exports) {
|
|
|
1408
1236
|
peg$currPos = s3;
|
|
1409
1237
|
s3 = peg$FAILED;
|
|
1410
1238
|
}
|
|
1239
|
+
if (s3 === peg$FAILED) { break; }
|
|
1240
|
+
s2.push(s3);
|
|
1411
1241
|
}
|
|
1412
1242
|
s0 = peg$f11(s1, s2);
|
|
1413
1243
|
} else {
|
|
@@ -1415,7 +1245,7 @@ var ftl = (function (exports) {
|
|
|
1415
1245
|
s0 = peg$FAILED;
|
|
1416
1246
|
}
|
|
1417
1247
|
|
|
1418
|
-
peg$resultsCache
|
|
1248
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1419
1249
|
|
|
1420
1250
|
return s0;
|
|
1421
1251
|
}
|
|
@@ -1424,7 +1254,7 @@ var ftl = (function (exports) {
|
|
|
1424
1254
|
let s0, s1, s2, s3, s5, s7;
|
|
1425
1255
|
|
|
1426
1256
|
const key = peg$currPos * 38 + 15;
|
|
1427
|
-
const cached = peg$resultsCache
|
|
1257
|
+
const cached = peg$resultsCache.get(key);
|
|
1428
1258
|
|
|
1429
1259
|
if (cached) {
|
|
1430
1260
|
peg$currPos = cached.nextPos;
|
|
@@ -1436,24 +1266,7 @@ var ftl = (function (exports) {
|
|
|
1436
1266
|
s1 = peg$parseRelExpression();
|
|
1437
1267
|
if (s1 !== peg$FAILED) {
|
|
1438
1268
|
s2 = [];
|
|
1439
|
-
|
|
1440
|
-
peg$parse_();
|
|
1441
|
-
s5 = peg$parseEqualityOp();
|
|
1442
|
-
if (s5 !== peg$FAILED) {
|
|
1443
|
-
peg$parse_();
|
|
1444
|
-
s7 = peg$parseRelExpression();
|
|
1445
|
-
if (s7 !== peg$FAILED) {
|
|
1446
|
-
s3 = peg$f12(s1, s5, s7);
|
|
1447
|
-
} else {
|
|
1448
|
-
peg$currPos = s3;
|
|
1449
|
-
s3 = peg$FAILED;
|
|
1450
|
-
}
|
|
1451
|
-
} else {
|
|
1452
|
-
peg$currPos = s3;
|
|
1453
|
-
s3 = peg$FAILED;
|
|
1454
|
-
}
|
|
1455
|
-
while (s3 !== peg$FAILED) {
|
|
1456
|
-
s2.push(s3);
|
|
1269
|
+
for (;;) {
|
|
1457
1270
|
s3 = peg$currPos;
|
|
1458
1271
|
peg$parse_();
|
|
1459
1272
|
s5 = peg$parseEqualityOp();
|
|
@@ -1470,6 +1283,8 @@ var ftl = (function (exports) {
|
|
|
1470
1283
|
peg$currPos = s3;
|
|
1471
1284
|
s3 = peg$FAILED;
|
|
1472
1285
|
}
|
|
1286
|
+
if (s3 === peg$FAILED) { break; }
|
|
1287
|
+
s2.push(s3);
|
|
1473
1288
|
}
|
|
1474
1289
|
s0 = peg$f13(s1, s2);
|
|
1475
1290
|
} else {
|
|
@@ -1477,7 +1292,7 @@ var ftl = (function (exports) {
|
|
|
1477
1292
|
s0 = peg$FAILED;
|
|
1478
1293
|
}
|
|
1479
1294
|
|
|
1480
|
-
peg$resultsCache
|
|
1295
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1481
1296
|
|
|
1482
1297
|
return s0;
|
|
1483
1298
|
}
|
|
@@ -1486,7 +1301,7 @@ var ftl = (function (exports) {
|
|
|
1486
1301
|
let s0, s1, s2, s3, s5, s7;
|
|
1487
1302
|
|
|
1488
1303
|
const key = peg$currPos * 38 + 16;
|
|
1489
|
-
const cached = peg$resultsCache
|
|
1304
|
+
const cached = peg$resultsCache.get(key);
|
|
1490
1305
|
|
|
1491
1306
|
if (cached) {
|
|
1492
1307
|
peg$currPos = cached.nextPos;
|
|
@@ -1498,24 +1313,7 @@ var ftl = (function (exports) {
|
|
|
1498
1313
|
s1 = peg$parseNotExpression();
|
|
1499
1314
|
if (s1 !== peg$FAILED) {
|
|
1500
1315
|
s2 = [];
|
|
1501
|
-
|
|
1502
|
-
peg$parse_();
|
|
1503
|
-
s5 = peg$parseRelationalOp();
|
|
1504
|
-
if (s5 !== peg$FAILED) {
|
|
1505
|
-
peg$parse_();
|
|
1506
|
-
s7 = peg$parseNotExpression();
|
|
1507
|
-
if (s7 !== peg$FAILED) {
|
|
1508
|
-
s3 = peg$f14(s1, s5, s7);
|
|
1509
|
-
} else {
|
|
1510
|
-
peg$currPos = s3;
|
|
1511
|
-
s3 = peg$FAILED;
|
|
1512
|
-
}
|
|
1513
|
-
} else {
|
|
1514
|
-
peg$currPos = s3;
|
|
1515
|
-
s3 = peg$FAILED;
|
|
1516
|
-
}
|
|
1517
|
-
while (s3 !== peg$FAILED) {
|
|
1518
|
-
s2.push(s3);
|
|
1316
|
+
for (;;) {
|
|
1519
1317
|
s3 = peg$currPos;
|
|
1520
1318
|
peg$parse_();
|
|
1521
1319
|
s5 = peg$parseRelationalOp();
|
|
@@ -1532,6 +1330,8 @@ var ftl = (function (exports) {
|
|
|
1532
1330
|
peg$currPos = s3;
|
|
1533
1331
|
s3 = peg$FAILED;
|
|
1534
1332
|
}
|
|
1333
|
+
if (s3 === peg$FAILED) { break; }
|
|
1334
|
+
s2.push(s3);
|
|
1535
1335
|
}
|
|
1536
1336
|
s0 = peg$f15(s1, s2);
|
|
1537
1337
|
} else {
|
|
@@ -1539,7 +1339,7 @@ var ftl = (function (exports) {
|
|
|
1539
1339
|
s0 = peg$FAILED;
|
|
1540
1340
|
}
|
|
1541
1341
|
|
|
1542
|
-
peg$resultsCache
|
|
1342
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1543
1343
|
|
|
1544
1344
|
return s0;
|
|
1545
1345
|
}
|
|
@@ -1548,7 +1348,7 @@ var ftl = (function (exports) {
|
|
|
1548
1348
|
let s0, s1, s3;
|
|
1549
1349
|
|
|
1550
1350
|
const key = peg$currPos * 38 + 17;
|
|
1551
|
-
const cached = peg$resultsCache
|
|
1351
|
+
const cached = peg$resultsCache.get(key);
|
|
1552
1352
|
|
|
1553
1353
|
if (cached) {
|
|
1554
1354
|
peg$currPos = cached.nextPos;
|
|
@@ -1581,7 +1381,7 @@ var ftl = (function (exports) {
|
|
|
1581
1381
|
s0 = peg$parseAccess();
|
|
1582
1382
|
}
|
|
1583
1383
|
|
|
1584
|
-
peg$resultsCache
|
|
1384
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1585
1385
|
|
|
1586
1386
|
return s0;
|
|
1587
1387
|
}
|
|
@@ -1590,7 +1390,7 @@ var ftl = (function (exports) {
|
|
|
1590
1390
|
let s0, s1, s3, s4, s5;
|
|
1591
1391
|
|
|
1592
1392
|
const key = peg$currPos * 38 + 18;
|
|
1593
|
-
const cached = peg$resultsCache
|
|
1393
|
+
const cached = peg$resultsCache.get(key);
|
|
1594
1394
|
|
|
1595
1395
|
if (cached) {
|
|
1596
1396
|
peg$currPos = cached.nextPos;
|
|
@@ -1603,29 +1403,20 @@ var ftl = (function (exports) {
|
|
|
1603
1403
|
if (s1 !== peg$FAILED) {
|
|
1604
1404
|
peg$parse_();
|
|
1605
1405
|
s3 = [];
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
peg$
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
if (s4 !== peg$FAILED) {
|
|
1616
|
-
while (s4 !== peg$FAILED) {
|
|
1617
|
-
s3.push(s4);
|
|
1618
|
-
s4 = peg$currPos;
|
|
1619
|
-
s5 = peg$parseAccessExpression();
|
|
1620
|
-
if (s5 !== peg$FAILED) {
|
|
1621
|
-
peg$parse_();
|
|
1622
|
-
s4 = s5;
|
|
1623
|
-
} else {
|
|
1624
|
-
peg$currPos = s4;
|
|
1625
|
-
s4 = peg$FAILED;
|
|
1626
|
-
}
|
|
1406
|
+
for (;;) {
|
|
1407
|
+
s4 = peg$currPos;
|
|
1408
|
+
s5 = peg$parseAccessExpression();
|
|
1409
|
+
if (s5 !== peg$FAILED) {
|
|
1410
|
+
peg$parse_();
|
|
1411
|
+
s4 = s5;
|
|
1412
|
+
} else {
|
|
1413
|
+
peg$currPos = s4;
|
|
1414
|
+
s4 = peg$FAILED;
|
|
1627
1415
|
}
|
|
1628
|
-
|
|
1416
|
+
if (s4 === peg$FAILED) { break; }
|
|
1417
|
+
s3.push(s4);
|
|
1418
|
+
}
|
|
1419
|
+
if (s3.length < 1) {
|
|
1629
1420
|
s3 = peg$FAILED;
|
|
1630
1421
|
}
|
|
1631
1422
|
if (s3 !== peg$FAILED) {
|
|
@@ -1642,7 +1433,7 @@ var ftl = (function (exports) {
|
|
|
1642
1433
|
s0 = peg$parseGroupingExpression();
|
|
1643
1434
|
}
|
|
1644
1435
|
|
|
1645
|
-
peg$resultsCache
|
|
1436
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1646
1437
|
|
|
1647
1438
|
return s0;
|
|
1648
1439
|
}
|
|
@@ -1651,7 +1442,7 @@ var ftl = (function (exports) {
|
|
|
1651
1442
|
let s0;
|
|
1652
1443
|
|
|
1653
1444
|
const key = peg$currPos * 38 + 19;
|
|
1654
|
-
const cached = peg$resultsCache
|
|
1445
|
+
const cached = peg$resultsCache.get(key);
|
|
1655
1446
|
|
|
1656
1447
|
if (cached) {
|
|
1657
1448
|
peg$currPos = cached.nextPos;
|
|
@@ -1667,7 +1458,7 @@ var ftl = (function (exports) {
|
|
|
1667
1458
|
}
|
|
1668
1459
|
}
|
|
1669
1460
|
|
|
1670
|
-
peg$resultsCache
|
|
1461
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1671
1462
|
|
|
1672
1463
|
return s0;
|
|
1673
1464
|
}
|
|
@@ -1676,7 +1467,7 @@ var ftl = (function (exports) {
|
|
|
1676
1467
|
let s0, s1, s3;
|
|
1677
1468
|
|
|
1678
1469
|
const key = peg$currPos * 38 + 20;
|
|
1679
|
-
const cached = peg$resultsCache
|
|
1470
|
+
const cached = peg$resultsCache.get(key);
|
|
1680
1471
|
|
|
1681
1472
|
if (cached) {
|
|
1682
1473
|
peg$currPos = cached.nextPos;
|
|
@@ -1721,7 +1512,7 @@ var ftl = (function (exports) {
|
|
|
1721
1512
|
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
|
1722
1513
|
}
|
|
1723
1514
|
|
|
1724
|
-
peg$resultsCache
|
|
1515
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1725
1516
|
|
|
1726
1517
|
return s0;
|
|
1727
1518
|
}
|
|
@@ -1730,7 +1521,7 @@ var ftl = (function (exports) {
|
|
|
1730
1521
|
let s0, s1, s2, s4, s6;
|
|
1731
1522
|
|
|
1732
1523
|
const key = peg$currPos * 38 + 21;
|
|
1733
|
-
const cached = peg$resultsCache
|
|
1524
|
+
const cached = peg$resultsCache.get(key);
|
|
1734
1525
|
|
|
1735
1526
|
if (cached) {
|
|
1736
1527
|
peg$currPos = cached.nextPos;
|
|
@@ -1789,7 +1580,7 @@ var ftl = (function (exports) {
|
|
|
1789
1580
|
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
|
1790
1581
|
}
|
|
1791
1582
|
|
|
1792
|
-
peg$resultsCache
|
|
1583
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1793
1584
|
|
|
1794
1585
|
return s0;
|
|
1795
1586
|
}
|
|
@@ -1798,7 +1589,7 @@ var ftl = (function (exports) {
|
|
|
1798
1589
|
let s0, s1, s2, s4, s5, s6, s7, s9;
|
|
1799
1590
|
|
|
1800
1591
|
const key = peg$currPos * 38 + 22;
|
|
1801
|
-
const cached = peg$resultsCache
|
|
1592
|
+
const cached = peg$resultsCache.get(key);
|
|
1802
1593
|
|
|
1803
1594
|
if (cached) {
|
|
1804
1595
|
peg$currPos = cached.nextPos;
|
|
@@ -1840,30 +1631,7 @@ var ftl = (function (exports) {
|
|
|
1840
1631
|
s4 = null;
|
|
1841
1632
|
}
|
|
1842
1633
|
s5 = [];
|
|
1843
|
-
|
|
1844
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
1845
|
-
s7 = peg$c34;
|
|
1846
|
-
peg$currPos++;
|
|
1847
|
-
} else {
|
|
1848
|
-
s7 = peg$FAILED;
|
|
1849
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
1850
|
-
}
|
|
1851
|
-
if (s7 !== peg$FAILED) {
|
|
1852
|
-
peg$parse_();
|
|
1853
|
-
s9 = peg$parseTernaryExpression();
|
|
1854
|
-
if (s9 !== peg$FAILED) {
|
|
1855
|
-
peg$parse_();
|
|
1856
|
-
s6 = s9;
|
|
1857
|
-
} else {
|
|
1858
|
-
peg$currPos = s6;
|
|
1859
|
-
s6 = peg$FAILED;
|
|
1860
|
-
}
|
|
1861
|
-
} else {
|
|
1862
|
-
peg$currPos = s6;
|
|
1863
|
-
s6 = peg$FAILED;
|
|
1864
|
-
}
|
|
1865
|
-
while (s6 !== peg$FAILED) {
|
|
1866
|
-
s5.push(s6);
|
|
1634
|
+
for (;;) {
|
|
1867
1635
|
s6 = peg$currPos;
|
|
1868
1636
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
1869
1637
|
s7 = peg$c34;
|
|
@@ -1886,6 +1654,8 @@ var ftl = (function (exports) {
|
|
|
1886
1654
|
peg$currPos = s6;
|
|
1887
1655
|
s6 = peg$FAILED;
|
|
1888
1656
|
}
|
|
1657
|
+
if (s6 === peg$FAILED) { break; }
|
|
1658
|
+
s5.push(s6);
|
|
1889
1659
|
}
|
|
1890
1660
|
if (input.charCodeAt(peg$currPos) === 41) {
|
|
1891
1661
|
s6 = peg$c36;
|
|
@@ -1910,7 +1680,7 @@ var ftl = (function (exports) {
|
|
|
1910
1680
|
if (peg$silentFails === 0) { peg$fail(peg$e23); }
|
|
1911
1681
|
}
|
|
1912
1682
|
|
|
1913
|
-
peg$resultsCache
|
|
1683
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1914
1684
|
|
|
1915
1685
|
return s0;
|
|
1916
1686
|
}
|
|
@@ -1919,7 +1689,7 @@ var ftl = (function (exports) {
|
|
|
1919
1689
|
let s0, s1, s3, s5;
|
|
1920
1690
|
|
|
1921
1691
|
const key = peg$currPos * 38 + 23;
|
|
1922
|
-
const cached = peg$resultsCache
|
|
1692
|
+
const cached = peg$resultsCache.get(key);
|
|
1923
1693
|
|
|
1924
1694
|
if (cached) {
|
|
1925
1695
|
peg$currPos = cached.nextPos;
|
|
@@ -1971,7 +1741,7 @@ var ftl = (function (exports) {
|
|
|
1971
1741
|
}
|
|
1972
1742
|
}
|
|
1973
1743
|
|
|
1974
|
-
peg$resultsCache
|
|
1744
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
1975
1745
|
|
|
1976
1746
|
return s0;
|
|
1977
1747
|
}
|
|
@@ -1980,7 +1750,7 @@ var ftl = (function (exports) {
|
|
|
1980
1750
|
let s0, s1, s2, s4, s5, s6, s7, s9;
|
|
1981
1751
|
|
|
1982
1752
|
const key = peg$currPos * 38 + 24;
|
|
1983
|
-
const cached = peg$resultsCache
|
|
1753
|
+
const cached = peg$resultsCache.get(key);
|
|
1984
1754
|
|
|
1985
1755
|
if (cached) {
|
|
1986
1756
|
peg$currPos = cached.nextPos;
|
|
@@ -2014,30 +1784,7 @@ var ftl = (function (exports) {
|
|
|
2014
1784
|
s4 = null;
|
|
2015
1785
|
}
|
|
2016
1786
|
s5 = [];
|
|
2017
|
-
|
|
2018
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2019
|
-
s7 = peg$c34;
|
|
2020
|
-
peg$currPos++;
|
|
2021
|
-
} else {
|
|
2022
|
-
s7 = peg$FAILED;
|
|
2023
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
2024
|
-
}
|
|
2025
|
-
if (s7 !== peg$FAILED) {
|
|
2026
|
-
peg$parse_();
|
|
2027
|
-
s9 = peg$parseTernaryExpression();
|
|
2028
|
-
if (s9 !== peg$FAILED) {
|
|
2029
|
-
peg$parse_();
|
|
2030
|
-
s6 = s9;
|
|
2031
|
-
} else {
|
|
2032
|
-
peg$currPos = s6;
|
|
2033
|
-
s6 = peg$FAILED;
|
|
2034
|
-
}
|
|
2035
|
-
} else {
|
|
2036
|
-
peg$currPos = s6;
|
|
2037
|
-
s6 = peg$FAILED;
|
|
2038
|
-
}
|
|
2039
|
-
while (s6 !== peg$FAILED) {
|
|
2040
|
-
s5.push(s6);
|
|
1787
|
+
for (;;) {
|
|
2041
1788
|
s6 = peg$currPos;
|
|
2042
1789
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2043
1790
|
s7 = peg$c34;
|
|
@@ -2060,6 +1807,8 @@ var ftl = (function (exports) {
|
|
|
2060
1807
|
peg$currPos = s6;
|
|
2061
1808
|
s6 = peg$FAILED;
|
|
2062
1809
|
}
|
|
1810
|
+
if (s6 === peg$FAILED) { break; }
|
|
1811
|
+
s5.push(s6);
|
|
2063
1812
|
}
|
|
2064
1813
|
if (input.charCodeAt(peg$currPos) === 41) {
|
|
2065
1814
|
s6 = peg$c36;
|
|
@@ -2088,7 +1837,7 @@ var ftl = (function (exports) {
|
|
|
2088
1837
|
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
|
2089
1838
|
}
|
|
2090
1839
|
|
|
2091
|
-
peg$resultsCache
|
|
1840
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2092
1841
|
|
|
2093
1842
|
return s0;
|
|
2094
1843
|
}
|
|
@@ -2097,7 +1846,7 @@ var ftl = (function (exports) {
|
|
|
2097
1846
|
let s0;
|
|
2098
1847
|
|
|
2099
1848
|
const key = peg$currPos * 38 + 25;
|
|
2100
|
-
const cached = peg$resultsCache
|
|
1849
|
+
const cached = peg$resultsCache.get(key);
|
|
2101
1850
|
|
|
2102
1851
|
if (cached) {
|
|
2103
1852
|
peg$currPos = cached.nextPos;
|
|
@@ -2116,7 +1865,7 @@ var ftl = (function (exports) {
|
|
|
2116
1865
|
}
|
|
2117
1866
|
}
|
|
2118
1867
|
|
|
2119
|
-
peg$resultsCache
|
|
1868
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2120
1869
|
|
|
2121
1870
|
return s0;
|
|
2122
1871
|
}
|
|
@@ -2125,7 +1874,7 @@ var ftl = (function (exports) {
|
|
|
2125
1874
|
let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
|
|
2126
1875
|
|
|
2127
1876
|
const key = peg$currPos * 38 + 26;
|
|
2128
|
-
const cached = peg$resultsCache
|
|
1877
|
+
const cached = peg$resultsCache.get(key);
|
|
2129
1878
|
|
|
2130
1879
|
if (cached) {
|
|
2131
1880
|
peg$currPos = cached.nextPos;
|
|
@@ -2149,25 +1898,18 @@ var ftl = (function (exports) {
|
|
|
2149
1898
|
}
|
|
2150
1899
|
s4 = peg$currPos;
|
|
2151
1900
|
s5 = [];
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
peg$
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
if (s6 !== peg$FAILED) {
|
|
2160
|
-
while (s6 !== peg$FAILED) {
|
|
2161
|
-
s5.push(s6);
|
|
2162
|
-
s6 = input.charAt(peg$currPos);
|
|
2163
|
-
if (peg$r1.test(s6)) {
|
|
2164
|
-
peg$currPos++;
|
|
2165
|
-
} else {
|
|
2166
|
-
s6 = peg$FAILED;
|
|
2167
|
-
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2168
|
-
}
|
|
1901
|
+
for (;;) {
|
|
1902
|
+
s6 = input.charAt(peg$currPos);
|
|
1903
|
+
if ((peg$charCode = s6.charCodeAt(0), (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
1904
|
+
peg$currPos++;
|
|
1905
|
+
} else {
|
|
1906
|
+
s6 = peg$FAILED;
|
|
1907
|
+
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2169
1908
|
}
|
|
2170
|
-
|
|
1909
|
+
if (s6 === peg$FAILED) { break; }
|
|
1910
|
+
s5.push(s6);
|
|
1911
|
+
}
|
|
1912
|
+
if (s5.length < 1) {
|
|
2171
1913
|
s5 = peg$FAILED;
|
|
2172
1914
|
}
|
|
2173
1915
|
if (s5 !== peg$FAILED) {
|
|
@@ -2181,22 +1923,16 @@ var ftl = (function (exports) {
|
|
|
2181
1923
|
}
|
|
2182
1924
|
if (s7 !== peg$FAILED) {
|
|
2183
1925
|
s8 = [];
|
|
2184
|
-
|
|
2185
|
-
if (peg$r1.test(s9)) {
|
|
2186
|
-
peg$currPos++;
|
|
2187
|
-
} else {
|
|
2188
|
-
s9 = peg$FAILED;
|
|
2189
|
-
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2190
|
-
}
|
|
2191
|
-
while (s9 !== peg$FAILED) {
|
|
2192
|
-
s8.push(s9);
|
|
1926
|
+
for (;;) {
|
|
2193
1927
|
s9 = input.charAt(peg$currPos);
|
|
2194
|
-
if (peg$
|
|
1928
|
+
if ((peg$charCode = s9.charCodeAt(0), (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
2195
1929
|
peg$currPos++;
|
|
2196
1930
|
} else {
|
|
2197
1931
|
s9 = peg$FAILED;
|
|
2198
1932
|
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2199
1933
|
}
|
|
1934
|
+
if (s9 === peg$FAILED) { break; }
|
|
1935
|
+
s8.push(s9);
|
|
2200
1936
|
}
|
|
2201
1937
|
s7 = [s7, s8];
|
|
2202
1938
|
s6 = s7;
|
|
@@ -2224,25 +1960,18 @@ var ftl = (function (exports) {
|
|
|
2224
1960
|
}
|
|
2225
1961
|
if (s5 !== peg$FAILED) {
|
|
2226
1962
|
s6 = [];
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
peg$
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
if (s7 !== peg$FAILED) {
|
|
2235
|
-
while (s7 !== peg$FAILED) {
|
|
2236
|
-
s6.push(s7);
|
|
2237
|
-
s7 = input.charAt(peg$currPos);
|
|
2238
|
-
if (peg$r1.test(s7)) {
|
|
2239
|
-
peg$currPos++;
|
|
2240
|
-
} else {
|
|
2241
|
-
s7 = peg$FAILED;
|
|
2242
|
-
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2243
|
-
}
|
|
1963
|
+
for (;;) {
|
|
1964
|
+
s7 = input.charAt(peg$currPos);
|
|
1965
|
+
if ((peg$charCode = s7.charCodeAt(0), (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
1966
|
+
peg$currPos++;
|
|
1967
|
+
} else {
|
|
1968
|
+
s7 = peg$FAILED;
|
|
1969
|
+
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
2244
1970
|
}
|
|
2245
|
-
|
|
1971
|
+
if (s7 === peg$FAILED) { break; }
|
|
1972
|
+
s6.push(s7);
|
|
1973
|
+
}
|
|
1974
|
+
if (s6.length < 1) {
|
|
2246
1975
|
s6 = peg$FAILED;
|
|
2247
1976
|
}
|
|
2248
1977
|
if (s6 !== peg$FAILED) {
|
|
@@ -2279,7 +2008,7 @@ var ftl = (function (exports) {
|
|
|
2279
2008
|
if (peg$silentFails === 0) { peg$fail(peg$e28); }
|
|
2280
2009
|
}
|
|
2281
2010
|
|
|
2282
|
-
peg$resultsCache
|
|
2011
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2283
2012
|
|
|
2284
2013
|
return s0;
|
|
2285
2014
|
}
|
|
@@ -2288,7 +2017,7 @@ var ftl = (function (exports) {
|
|
|
2288
2017
|
let s0, s1, s2, s3, s4;
|
|
2289
2018
|
|
|
2290
2019
|
const key = peg$currPos * 38 + 27;
|
|
2291
|
-
const cached = peg$resultsCache
|
|
2020
|
+
const cached = peg$resultsCache.get(key);
|
|
2292
2021
|
|
|
2293
2022
|
if (cached) {
|
|
2294
2023
|
peg$currPos = cached.nextPos;
|
|
@@ -2308,22 +2037,16 @@ var ftl = (function (exports) {
|
|
|
2308
2037
|
if (s1 !== peg$FAILED) {
|
|
2309
2038
|
s2 = peg$currPos;
|
|
2310
2039
|
s3 = [];
|
|
2311
|
-
|
|
2312
|
-
if (peg$r2.test(s4)) {
|
|
2313
|
-
peg$currPos++;
|
|
2314
|
-
} else {
|
|
2315
|
-
s4 = peg$FAILED;
|
|
2316
|
-
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
|
2317
|
-
}
|
|
2318
|
-
while (s4 !== peg$FAILED) {
|
|
2319
|
-
s3.push(s4);
|
|
2040
|
+
for (;;) {
|
|
2320
2041
|
s4 = input.charAt(peg$currPos);
|
|
2321
|
-
if (peg$
|
|
2042
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 39)) {
|
|
2322
2043
|
peg$currPos++;
|
|
2323
2044
|
} else {
|
|
2324
2045
|
s4 = peg$FAILED;
|
|
2325
2046
|
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
|
2326
2047
|
}
|
|
2048
|
+
if (s4 === peg$FAILED) { break; }
|
|
2049
|
+
s3.push(s4);
|
|
2327
2050
|
}
|
|
2328
2051
|
s2 = input.substring(s2, peg$currPos);
|
|
2329
2052
|
if (input.charCodeAt(peg$currPos) === 39) {
|
|
@@ -2355,22 +2078,16 @@ var ftl = (function (exports) {
|
|
|
2355
2078
|
if (s1 !== peg$FAILED) {
|
|
2356
2079
|
s2 = peg$currPos;
|
|
2357
2080
|
s3 = [];
|
|
2358
|
-
|
|
2359
|
-
if (peg$r3.test(s4)) {
|
|
2360
|
-
peg$currPos++;
|
|
2361
|
-
} else {
|
|
2362
|
-
s4 = peg$FAILED;
|
|
2363
|
-
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
2364
|
-
}
|
|
2365
|
-
while (s4 !== peg$FAILED) {
|
|
2366
|
-
s3.push(s4);
|
|
2081
|
+
for (;;) {
|
|
2367
2082
|
s4 = input.charAt(peg$currPos);
|
|
2368
|
-
if (peg$
|
|
2083
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 34)) {
|
|
2369
2084
|
peg$currPos++;
|
|
2370
2085
|
} else {
|
|
2371
2086
|
s4 = peg$FAILED;
|
|
2372
2087
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
2373
2088
|
}
|
|
2089
|
+
if (s4 === peg$FAILED) { break; }
|
|
2090
|
+
s3.push(s4);
|
|
2374
2091
|
}
|
|
2375
2092
|
s2 = input.substring(s2, peg$currPos);
|
|
2376
2093
|
if (input.charCodeAt(peg$currPos) === 34) {
|
|
@@ -2401,16 +2118,13 @@ var ftl = (function (exports) {
|
|
|
2401
2118
|
}
|
|
2402
2119
|
if (s1 !== peg$FAILED) {
|
|
2403
2120
|
s2 = [];
|
|
2404
|
-
|
|
2405
|
-
if (s3 === peg$FAILED) {
|
|
2406
|
-
s3 = peg$parseTemplateStringLiteral();
|
|
2407
|
-
}
|
|
2408
|
-
while (s3 !== peg$FAILED) {
|
|
2409
|
-
s2.push(s3);
|
|
2121
|
+
for (;;) {
|
|
2410
2122
|
s3 = peg$parseTemplateStringExpression();
|
|
2411
2123
|
if (s3 === peg$FAILED) {
|
|
2412
2124
|
s3 = peg$parseTemplateStringLiteral();
|
|
2413
2125
|
}
|
|
2126
|
+
if (s3 === peg$FAILED) { break; }
|
|
2127
|
+
s2.push(s3);
|
|
2414
2128
|
}
|
|
2415
2129
|
if (input.charCodeAt(peg$currPos) === 96) {
|
|
2416
2130
|
s3 = peg$c42;
|
|
@@ -2437,7 +2151,7 @@ var ftl = (function (exports) {
|
|
|
2437
2151
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
2438
2152
|
}
|
|
2439
2153
|
|
|
2440
|
-
peg$resultsCache
|
|
2154
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2441
2155
|
|
|
2442
2156
|
return s0;
|
|
2443
2157
|
}
|
|
@@ -2446,7 +2160,7 @@ var ftl = (function (exports) {
|
|
|
2446
2160
|
let s0, s1, s3, s5;
|
|
2447
2161
|
|
|
2448
2162
|
const key = peg$currPos * 38 + 28;
|
|
2449
|
-
const cached = peg$resultsCache
|
|
2163
|
+
const cached = peg$resultsCache.get(key);
|
|
2450
2164
|
|
|
2451
2165
|
if (cached) {
|
|
2452
2166
|
peg$currPos = cached.nextPos;
|
|
@@ -2495,7 +2209,7 @@ var ftl = (function (exports) {
|
|
|
2495
2209
|
if (peg$silentFails === 0) { peg$fail(peg$e37); }
|
|
2496
2210
|
}
|
|
2497
2211
|
|
|
2498
|
-
peg$resultsCache
|
|
2212
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2499
2213
|
|
|
2500
2214
|
return s0;
|
|
2501
2215
|
}
|
|
@@ -2504,134 +2218,71 @@ var ftl = (function (exports) {
|
|
|
2504
2218
|
let s0, s1, s2, s3, s4;
|
|
2505
2219
|
|
|
2506
2220
|
const key = peg$currPos * 38 + 29;
|
|
2507
|
-
const cached = peg$resultsCache
|
|
2221
|
+
const cached = peg$resultsCache.get(key);
|
|
2508
2222
|
|
|
2509
2223
|
if (cached) {
|
|
2510
2224
|
peg$currPos = cached.nextPos;
|
|
2511
2225
|
|
|
2512
2226
|
return cached.result;
|
|
2513
2227
|
}
|
|
2514
|
-
|
|
2515
|
-
peg$silentFails++;
|
|
2516
|
-
s0 = peg$currPos;
|
|
2517
|
-
s1 = [];
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
peg$currPos++;
|
|
2523
|
-
} else {
|
|
2524
|
-
s4 = peg$FAILED;
|
|
2525
|
-
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2526
|
-
}
|
|
2527
|
-
if (s4 !== peg$FAILED) {
|
|
2528
|
-
while (s4 !== peg$FAILED) {
|
|
2529
|
-
s3.push(s4);
|
|
2530
|
-
s4 = input.charAt(peg$currPos);
|
|
2531
|
-
if (peg$r4.test(s4)) {
|
|
2532
|
-
peg$currPos++;
|
|
2533
|
-
} else {
|
|
2534
|
-
s4 = peg$FAILED;
|
|
2535
|
-
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
} else {
|
|
2539
|
-
s3 = peg$FAILED;
|
|
2540
|
-
}
|
|
2541
|
-
if (s3 !== peg$FAILED) {
|
|
2542
|
-
s2 = input.substring(s2, peg$currPos);
|
|
2543
|
-
} else {
|
|
2544
|
-
s2 = s3;
|
|
2545
|
-
}
|
|
2546
|
-
if (s2 === peg$FAILED) {
|
|
2547
|
-
s2 = peg$currPos;
|
|
2548
|
-
if (input.charCodeAt(peg$currPos) === 92) {
|
|
2549
|
-
s3 = peg$c7;
|
|
2550
|
-
peg$currPos++;
|
|
2551
|
-
} else {
|
|
2552
|
-
s3 = peg$FAILED;
|
|
2553
|
-
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
2554
|
-
}
|
|
2555
|
-
if (s3 !== peg$FAILED) {
|
|
2556
|
-
if (input.length > peg$currPos) {
|
|
2557
|
-
s4 = input.charAt(peg$currPos);
|
|
2558
|
-
peg$currPos++;
|
|
2559
|
-
} else {
|
|
2560
|
-
s4 = peg$FAILED;
|
|
2561
|
-
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
2562
|
-
}
|
|
2563
|
-
if (s4 !== peg$FAILED) {
|
|
2564
|
-
s2 = peg$f28(s4);
|
|
2565
|
-
} else {
|
|
2566
|
-
peg$currPos = s2;
|
|
2567
|
-
s2 = peg$FAILED;
|
|
2568
|
-
}
|
|
2569
|
-
} else {
|
|
2570
|
-
peg$currPos = s2;
|
|
2571
|
-
s2 = peg$FAILED;
|
|
2572
|
-
}
|
|
2573
|
-
}
|
|
2574
|
-
if (s2 !== peg$FAILED) {
|
|
2575
|
-
while (s2 !== peg$FAILED) {
|
|
2576
|
-
s1.push(s2);
|
|
2577
|
-
s2 = peg$currPos;
|
|
2578
|
-
s3 = [];
|
|
2228
|
+
|
|
2229
|
+
peg$silentFails++;
|
|
2230
|
+
s0 = peg$currPos;
|
|
2231
|
+
s1 = [];
|
|
2232
|
+
for (;;) {
|
|
2233
|
+
s2 = peg$currPos;
|
|
2234
|
+
s3 = [];
|
|
2235
|
+
for (;;) {
|
|
2579
2236
|
s4 = input.charAt(peg$currPos);
|
|
2580
|
-
if (peg$
|
|
2237
|
+
if (s4 !== "" && !(peg$charCode = s4.charCodeAt(0), peg$charCode === 92 || peg$charCode === 96 || peg$charCode === 123)) {
|
|
2581
2238
|
peg$currPos++;
|
|
2582
2239
|
} else {
|
|
2583
2240
|
s4 = peg$FAILED;
|
|
2584
2241
|
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
2585
2242
|
}
|
|
2586
|
-
if (s4
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2243
|
+
if (s4 === peg$FAILED) { break; }
|
|
2244
|
+
s3.push(s4);
|
|
2245
|
+
}
|
|
2246
|
+
if (s3.length < 1) {
|
|
2247
|
+
s3 = peg$FAILED;
|
|
2248
|
+
}
|
|
2249
|
+
if (s3 !== peg$FAILED) {
|
|
2250
|
+
s2 = input.substring(s2, peg$currPos);
|
|
2251
|
+
} else {
|
|
2252
|
+
s2 = s3;
|
|
2253
|
+
}
|
|
2254
|
+
if (s2 === peg$FAILED) {
|
|
2255
|
+
s2 = peg$currPos;
|
|
2256
|
+
if (input.charCodeAt(peg$currPos) === 92) {
|
|
2257
|
+
s3 = peg$c7;
|
|
2258
|
+
peg$currPos++;
|
|
2597
2259
|
} else {
|
|
2598
2260
|
s3 = peg$FAILED;
|
|
2261
|
+
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
2599
2262
|
}
|
|
2600
2263
|
if (s3 !== peg$FAILED) {
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
s2 = s3;
|
|
2604
|
-
}
|
|
2605
|
-
if (s2 === peg$FAILED) {
|
|
2606
|
-
s2 = peg$currPos;
|
|
2607
|
-
if (input.charCodeAt(peg$currPos) === 92) {
|
|
2608
|
-
s3 = peg$c7;
|
|
2264
|
+
if (input.length > peg$currPos) {
|
|
2265
|
+
s4 = input.charAt(peg$currPos);
|
|
2609
2266
|
peg$currPos++;
|
|
2610
2267
|
} else {
|
|
2611
|
-
|
|
2612
|
-
if (peg$silentFails === 0) { peg$fail(peg$
|
|
2268
|
+
s4 = peg$FAILED;
|
|
2269
|
+
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
2613
2270
|
}
|
|
2614
|
-
if (
|
|
2615
|
-
|
|
2616
|
-
s4 = input.charAt(peg$currPos);
|
|
2617
|
-
peg$currPos++;
|
|
2618
|
-
} else {
|
|
2619
|
-
s4 = peg$FAILED;
|
|
2620
|
-
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
2621
|
-
}
|
|
2622
|
-
if (s4 !== peg$FAILED) {
|
|
2623
|
-
s2 = peg$f28(s4);
|
|
2624
|
-
} else {
|
|
2625
|
-
peg$currPos = s2;
|
|
2626
|
-
s2 = peg$FAILED;
|
|
2627
|
-
}
|
|
2271
|
+
if (s4 !== peg$FAILED) {
|
|
2272
|
+
s2 = peg$f28(s4);
|
|
2628
2273
|
} else {
|
|
2629
2274
|
peg$currPos = s2;
|
|
2630
2275
|
s2 = peg$FAILED;
|
|
2631
2276
|
}
|
|
2277
|
+
} else {
|
|
2278
|
+
peg$currPos = s2;
|
|
2279
|
+
s2 = peg$FAILED;
|
|
2632
2280
|
}
|
|
2633
2281
|
}
|
|
2634
|
-
|
|
2282
|
+
if (s2 === peg$FAILED) { break; }
|
|
2283
|
+
s1.push(s2);
|
|
2284
|
+
}
|
|
2285
|
+
if (s1.length < 1) {
|
|
2635
2286
|
s1 = peg$FAILED;
|
|
2636
2287
|
}
|
|
2637
2288
|
if (s1 !== peg$FAILED) {
|
|
@@ -2658,7 +2309,7 @@ var ftl = (function (exports) {
|
|
|
2658
2309
|
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
|
2659
2310
|
}
|
|
2660
2311
|
|
|
2661
|
-
peg$resultsCache
|
|
2312
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2662
2313
|
|
|
2663
2314
|
return s0;
|
|
2664
2315
|
}
|
|
@@ -2667,7 +2318,7 @@ var ftl = (function (exports) {
|
|
|
2667
2318
|
let s0, s1, s3, s5, s6, s7, s9;
|
|
2668
2319
|
|
|
2669
2320
|
const key = peg$currPos * 38 + 30;
|
|
2670
|
-
const cached = peg$resultsCache
|
|
2321
|
+
const cached = peg$resultsCache.get(key);
|
|
2671
2322
|
|
|
2672
2323
|
if (cached) {
|
|
2673
2324
|
peg$currPos = cached.nextPos;
|
|
@@ -2692,30 +2343,7 @@ var ftl = (function (exports) {
|
|
|
2692
2343
|
}
|
|
2693
2344
|
peg$parse_();
|
|
2694
2345
|
s5 = [];
|
|
2695
|
-
|
|
2696
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2697
|
-
s7 = peg$c34;
|
|
2698
|
-
peg$currPos++;
|
|
2699
|
-
} else {
|
|
2700
|
-
s7 = peg$FAILED;
|
|
2701
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
2702
|
-
}
|
|
2703
|
-
if (s7 !== peg$FAILED) {
|
|
2704
|
-
peg$parse_();
|
|
2705
|
-
s9 = peg$parseTernaryExpression();
|
|
2706
|
-
if (s9 !== peg$FAILED) {
|
|
2707
|
-
peg$parse_();
|
|
2708
|
-
s6 = s9;
|
|
2709
|
-
} else {
|
|
2710
|
-
peg$currPos = s6;
|
|
2711
|
-
s6 = peg$FAILED;
|
|
2712
|
-
}
|
|
2713
|
-
} else {
|
|
2714
|
-
peg$currPos = s6;
|
|
2715
|
-
s6 = peg$FAILED;
|
|
2716
|
-
}
|
|
2717
|
-
while (s6 !== peg$FAILED) {
|
|
2718
|
-
s5.push(s6);
|
|
2346
|
+
for (;;) {
|
|
2719
2347
|
s6 = peg$currPos;
|
|
2720
2348
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2721
2349
|
s7 = peg$c34;
|
|
@@ -2738,6 +2366,8 @@ var ftl = (function (exports) {
|
|
|
2738
2366
|
peg$currPos = s6;
|
|
2739
2367
|
s6 = peg$FAILED;
|
|
2740
2368
|
}
|
|
2369
|
+
if (s6 === peg$FAILED) { break; }
|
|
2370
|
+
s5.push(s6);
|
|
2741
2371
|
}
|
|
2742
2372
|
if (input.charCodeAt(peg$currPos) === 93) {
|
|
2743
2373
|
s6 = peg$c31;
|
|
@@ -2762,7 +2392,7 @@ var ftl = (function (exports) {
|
|
|
2762
2392
|
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
|
2763
2393
|
}
|
|
2764
2394
|
|
|
2765
|
-
peg$resultsCache
|
|
2395
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2766
2396
|
|
|
2767
2397
|
return s0;
|
|
2768
2398
|
}
|
|
@@ -2771,7 +2401,7 @@ var ftl = (function (exports) {
|
|
|
2771
2401
|
let s0, s1, s3, s4, s5, s6, s7, s8, s9, s11, s13;
|
|
2772
2402
|
|
|
2773
2403
|
const key = peg$currPos * 38 + 31;
|
|
2774
|
-
const cached = peg$resultsCache
|
|
2404
|
+
const cached = peg$resultsCache.get(key);
|
|
2775
2405
|
|
|
2776
2406
|
if (cached) {
|
|
2777
2407
|
peg$currPos = cached.nextPos;
|
|
@@ -2823,50 +2453,7 @@ var ftl = (function (exports) {
|
|
|
2823
2453
|
}
|
|
2824
2454
|
s4 = peg$parse_();
|
|
2825
2455
|
s5 = [];
|
|
2826
|
-
|
|
2827
|
-
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2828
|
-
s7 = peg$c34;
|
|
2829
|
-
peg$currPos++;
|
|
2830
|
-
} else {
|
|
2831
|
-
s7 = peg$FAILED;
|
|
2832
|
-
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
2833
|
-
}
|
|
2834
|
-
if (s7 !== peg$FAILED) {
|
|
2835
|
-
s8 = peg$parse_();
|
|
2836
|
-
s9 = peg$parseStringLiteral();
|
|
2837
|
-
if (s9 !== peg$FAILED) {
|
|
2838
|
-
peg$parse_();
|
|
2839
|
-
if (input.charCodeAt(peg$currPos) === 58) {
|
|
2840
|
-
s11 = peg$c15;
|
|
2841
|
-
peg$currPos++;
|
|
2842
|
-
} else {
|
|
2843
|
-
s11 = peg$FAILED;
|
|
2844
|
-
if (peg$silentFails === 0) { peg$fail(peg$e11); }
|
|
2845
|
-
}
|
|
2846
|
-
if (s11 !== peg$FAILED) {
|
|
2847
|
-
peg$parse_();
|
|
2848
|
-
s13 = peg$parseTernaryExpression();
|
|
2849
|
-
if (s13 !== peg$FAILED) {
|
|
2850
|
-
peg$parse_();
|
|
2851
|
-
s6 = [ s9, s13 ];
|
|
2852
|
-
} else {
|
|
2853
|
-
peg$currPos = s6;
|
|
2854
|
-
s6 = peg$FAILED;
|
|
2855
|
-
}
|
|
2856
|
-
} else {
|
|
2857
|
-
peg$currPos = s6;
|
|
2858
|
-
s6 = peg$FAILED;
|
|
2859
|
-
}
|
|
2860
|
-
} else {
|
|
2861
|
-
peg$currPos = s6;
|
|
2862
|
-
s6 = peg$FAILED;
|
|
2863
|
-
}
|
|
2864
|
-
} else {
|
|
2865
|
-
peg$currPos = s6;
|
|
2866
|
-
s6 = peg$FAILED;
|
|
2867
|
-
}
|
|
2868
|
-
while (s6 !== peg$FAILED) {
|
|
2869
|
-
s5.push(s6);
|
|
2456
|
+
for (;;) {
|
|
2870
2457
|
s6 = peg$currPos;
|
|
2871
2458
|
if (input.charCodeAt(peg$currPos) === 44) {
|
|
2872
2459
|
s7 = peg$c34;
|
|
@@ -2909,6 +2496,8 @@ var ftl = (function (exports) {
|
|
|
2909
2496
|
peg$currPos = s6;
|
|
2910
2497
|
s6 = peg$FAILED;
|
|
2911
2498
|
}
|
|
2499
|
+
if (s6 === peg$FAILED) { break; }
|
|
2500
|
+
s5.push(s6);
|
|
2912
2501
|
}
|
|
2913
2502
|
if (input.charCodeAt(peg$currPos) === 125) {
|
|
2914
2503
|
s6 = peg$c43;
|
|
@@ -2933,7 +2522,7 @@ var ftl = (function (exports) {
|
|
|
2933
2522
|
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
|
2934
2523
|
}
|
|
2935
2524
|
|
|
2936
|
-
peg$resultsCache
|
|
2525
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
2937
2526
|
|
|
2938
2527
|
return s0;
|
|
2939
2528
|
}
|
|
@@ -2942,7 +2531,7 @@ var ftl = (function (exports) {
|
|
|
2942
2531
|
let s0, s1, s2, s3, s4;
|
|
2943
2532
|
|
|
2944
2533
|
const key = peg$currPos * 38 + 32;
|
|
2945
|
-
const cached = peg$resultsCache
|
|
2534
|
+
const cached = peg$resultsCache.get(key);
|
|
2946
2535
|
|
|
2947
2536
|
if (cached) {
|
|
2948
2537
|
peg$currPos = cached.nextPos;
|
|
@@ -3000,7 +2589,7 @@ var ftl = (function (exports) {
|
|
|
3000
2589
|
if (peg$silentFails === 0) { peg$fail(peg$e43); }
|
|
3001
2590
|
}
|
|
3002
2591
|
|
|
3003
|
-
peg$resultsCache
|
|
2592
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3004
2593
|
|
|
3005
2594
|
return s0;
|
|
3006
2595
|
}
|
|
@@ -3009,7 +2598,7 @@ var ftl = (function (exports) {
|
|
|
3009
2598
|
let s0, s1, s2, s3, s4;
|
|
3010
2599
|
|
|
3011
2600
|
const key = peg$currPos * 38 + 33;
|
|
3012
|
-
const cached = peg$resultsCache
|
|
2601
|
+
const cached = peg$resultsCache.get(key);
|
|
3013
2602
|
|
|
3014
2603
|
if (cached) {
|
|
3015
2604
|
peg$currPos = cached.nextPos;
|
|
@@ -3020,7 +2609,7 @@ var ftl = (function (exports) {
|
|
|
3020
2609
|
s0 = peg$currPos;
|
|
3021
2610
|
s1 = peg$currPos;
|
|
3022
2611
|
s2 = input.charAt(peg$currPos);
|
|
3023
|
-
if (peg$
|
|
2612
|
+
if ((peg$charCode = s2.charCodeAt(0), (peg$charCode >= 97 && peg$charCode <= 122) || (peg$charCode >= 65 && peg$charCode <= 90) || peg$charCode === 36 || peg$charCode === 95)) {
|
|
3024
2613
|
peg$currPos++;
|
|
3025
2614
|
} else {
|
|
3026
2615
|
s2 = peg$FAILED;
|
|
@@ -3028,22 +2617,16 @@ var ftl = (function (exports) {
|
|
|
3028
2617
|
}
|
|
3029
2618
|
if (s2 !== peg$FAILED) {
|
|
3030
2619
|
s3 = [];
|
|
3031
|
-
|
|
3032
|
-
if (peg$r6.test(s4)) {
|
|
3033
|
-
peg$currPos++;
|
|
3034
|
-
} else {
|
|
3035
|
-
s4 = peg$FAILED;
|
|
3036
|
-
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
|
3037
|
-
}
|
|
3038
|
-
while (s4 !== peg$FAILED) {
|
|
3039
|
-
s3.push(s4);
|
|
2620
|
+
for (;;) {
|
|
3040
2621
|
s4 = input.charAt(peg$currPos);
|
|
3041
|
-
if (peg$
|
|
2622
|
+
if ((peg$charCode = s4.charCodeAt(0), (peg$charCode >= 97 && peg$charCode <= 122) || (peg$charCode >= 65 && peg$charCode <= 90) || peg$charCode === 36 || peg$charCode === 95 || (peg$charCode >= 48 && peg$charCode <= 57))) {
|
|
3042
2623
|
peg$currPos++;
|
|
3043
2624
|
} else {
|
|
3044
2625
|
s4 = peg$FAILED;
|
|
3045
2626
|
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
|
3046
2627
|
}
|
|
2628
|
+
if (s4 === peg$FAILED) { break; }
|
|
2629
|
+
s3.push(s4);
|
|
3047
2630
|
}
|
|
3048
2631
|
s2 = [s2, s3];
|
|
3049
2632
|
s1 = s2;
|
|
@@ -3057,7 +2640,7 @@ var ftl = (function (exports) {
|
|
|
3057
2640
|
s0 = s1;
|
|
3058
2641
|
}
|
|
3059
2642
|
|
|
3060
|
-
peg$resultsCache
|
|
2643
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3061
2644
|
|
|
3062
2645
|
return s0;
|
|
3063
2646
|
}
|
|
@@ -3066,7 +2649,7 @@ var ftl = (function (exports) {
|
|
|
3066
2649
|
let s0, s1;
|
|
3067
2650
|
|
|
3068
2651
|
const key = peg$currPos * 38 + 34;
|
|
3069
|
-
const cached = peg$resultsCache
|
|
2652
|
+
const cached = peg$resultsCache.get(key);
|
|
3070
2653
|
|
|
3071
2654
|
if (cached) {
|
|
3072
2655
|
peg$currPos = cached.nextPos;
|
|
@@ -3087,7 +2670,7 @@ var ftl = (function (exports) {
|
|
|
3087
2670
|
if (peg$silentFails === 0) { peg$fail(peg$e47); }
|
|
3088
2671
|
}
|
|
3089
2672
|
|
|
3090
|
-
peg$resultsCache
|
|
2673
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3091
2674
|
|
|
3092
2675
|
return s0;
|
|
3093
2676
|
}
|
|
@@ -3096,7 +2679,7 @@ var ftl = (function (exports) {
|
|
|
3096
2679
|
let s0;
|
|
3097
2680
|
|
|
3098
2681
|
const key = peg$currPos * 38 + 35;
|
|
3099
|
-
const cached = peg$resultsCache
|
|
2682
|
+
const cached = peg$resultsCache.get(key);
|
|
3100
2683
|
|
|
3101
2684
|
if (cached) {
|
|
3102
2685
|
peg$currPos = cached.nextPos;
|
|
@@ -3121,7 +2704,7 @@ var ftl = (function (exports) {
|
|
|
3121
2704
|
}
|
|
3122
2705
|
}
|
|
3123
2706
|
|
|
3124
|
-
peg$resultsCache
|
|
2707
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3125
2708
|
|
|
3126
2709
|
return s0;
|
|
3127
2710
|
}
|
|
@@ -3130,7 +2713,7 @@ var ftl = (function (exports) {
|
|
|
3130
2713
|
let s0;
|
|
3131
2714
|
|
|
3132
2715
|
const key = peg$currPos * 38 + 36;
|
|
3133
|
-
const cached = peg$resultsCache
|
|
2716
|
+
const cached = peg$resultsCache.get(key);
|
|
3134
2717
|
|
|
3135
2718
|
if (cached) {
|
|
3136
2719
|
peg$currPos = cached.nextPos;
|
|
@@ -3173,7 +2756,7 @@ var ftl = (function (exports) {
|
|
|
3173
2756
|
}
|
|
3174
2757
|
}
|
|
3175
2758
|
|
|
3176
|
-
peg$resultsCache
|
|
2759
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3177
2760
|
|
|
3178
2761
|
return s0;
|
|
3179
2762
|
}
|
|
@@ -3182,7 +2765,7 @@ var ftl = (function (exports) {
|
|
|
3182
2765
|
let s0, s1;
|
|
3183
2766
|
|
|
3184
2767
|
const key = peg$currPos * 38 + 37;
|
|
3185
|
-
const cached = peg$resultsCache
|
|
2768
|
+
const cached = peg$resultsCache.get(key);
|
|
3186
2769
|
|
|
3187
2770
|
if (cached) {
|
|
3188
2771
|
peg$currPos = cached.nextPos;
|
|
@@ -3192,26 +2775,20 @@ var ftl = (function (exports) {
|
|
|
3192
2775
|
|
|
3193
2776
|
peg$silentFails++;
|
|
3194
2777
|
s0 = [];
|
|
3195
|
-
|
|
3196
|
-
if (peg$r7.test(s1)) {
|
|
3197
|
-
peg$currPos++;
|
|
3198
|
-
} else {
|
|
3199
|
-
s1 = peg$FAILED;
|
|
3200
|
-
if (peg$silentFails === 0) { peg$fail(peg$e54); }
|
|
3201
|
-
}
|
|
3202
|
-
while (s1 !== peg$FAILED) {
|
|
3203
|
-
s0.push(s1);
|
|
2778
|
+
for (;;) {
|
|
3204
2779
|
s1 = input.charAt(peg$currPos);
|
|
3205
|
-
if (peg$
|
|
2780
|
+
if ((peg$charCode = s1.charCodeAt(0), peg$charCode === 32 || peg$charCode === 9 || peg$charCode === 10 || peg$charCode === 13)) {
|
|
3206
2781
|
peg$currPos++;
|
|
3207
2782
|
} else {
|
|
3208
2783
|
s1 = peg$FAILED;
|
|
3209
2784
|
if (peg$silentFails === 0) { peg$fail(peg$e54); }
|
|
3210
2785
|
}
|
|
2786
|
+
if (s1 === peg$FAILED) { break; }
|
|
2787
|
+
s0.push(s1);
|
|
3211
2788
|
}
|
|
3212
2789
|
peg$silentFails--;
|
|
3213
2790
|
|
|
3214
|
-
peg$resultsCache
|
|
2791
|
+
peg$resultsCache.set(key, { nextPos: peg$currPos, result: s0 });
|
|
3215
2792
|
|
|
3216
2793
|
return s0;
|
|
3217
2794
|
}
|
|
@@ -3253,10 +2830,10 @@ var ftl = (function (exports) {
|
|
|
3253
2830
|
/**
|
|
3254
2831
|
* The one lookup against a data stack: the innermost overlay carrying the name
|
|
3255
2832
|
* wins, `self` is the innermost overlay itself, and a function overlay counts
|
|
3256
|
-
* like an object one.
|
|
3257
|
-
* imperative facades cannot drift from what a template sees.
|
|
2833
|
+
* like an object one.
|
|
3258
2834
|
* @param {any[]} dataStack
|
|
3259
2835
|
* @param {string|symbol} prop
|
|
2836
|
+
* @returns {any} undefined when no overlay carries the name
|
|
3260
2837
|
*/
|
|
3261
2838
|
const resolveInStack = (dataStack, prop) => {
|
|
3262
2839
|
if (prop === 'self') {
|
|
@@ -3273,6 +2850,8 @@ var ftl = (function (exports) {
|
|
|
3273
2850
|
return undefined;
|
|
3274
2851
|
};
|
|
3275
2852
|
|
|
2853
|
+
const BOUND = Symbol('BOUND');
|
|
2854
|
+
|
|
3276
2855
|
/**
|
|
3277
2856
|
* Evaluates a parsed expression against a scope. One instance per evaluation:
|
|
3278
2857
|
* it holds the modules and the data stack that names resolve against, and keeps
|
|
@@ -3281,9 +2860,11 @@ var ftl = (function (exports) {
|
|
|
3281
2860
|
class EvaluatingVisitor {
|
|
3282
2861
|
#modules;
|
|
3283
2862
|
#dataStack;
|
|
3284
|
-
|
|
2863
|
+
#bound;
|
|
2864
|
+
constructor(modules, dataStack, bound) {
|
|
3285
2865
|
this.#modules = modules;
|
|
3286
2866
|
this.#dataStack = dataStack;
|
|
2867
|
+
this.#bound = bound ?? dataStack.length;
|
|
3287
2868
|
}
|
|
3288
2869
|
#resolve(prop) {
|
|
3289
2870
|
return resolveInStack(this.#dataStack, prop);
|
|
@@ -3307,8 +2888,9 @@ var ftl = (function (exports) {
|
|
|
3307
2888
|
#cached_resolve_proxy;
|
|
3308
2889
|
#resolve_proxy() {
|
|
3309
2890
|
if (!this.#cached_resolve_proxy) {
|
|
2891
|
+
const bound = (name) => resolveInStack(this.#dataStack.slice(0, this.#bound), name);
|
|
3310
2892
|
this.#cached_resolve_proxy = new Proxy(this.#dataStack, {
|
|
3311
|
-
get: (target, prop) => this.#resolve(prop),
|
|
2893
|
+
get: (target, prop) => (prop === BOUND ? bound : this.#resolve(prop)),
|
|
3312
2894
|
});
|
|
3313
2895
|
}
|
|
3314
2896
|
return this.#cached_resolve_proxy;
|
|
@@ -3320,8 +2902,7 @@ var ftl = (function (exports) {
|
|
|
3320
2902
|
return this.visit(node.lhs) || this.visit(node.rhs);
|
|
3321
2903
|
}
|
|
3322
2904
|
[nodes.nullc](node) {
|
|
3323
|
-
|
|
3324
|
-
return lhs !== null && lhs !== undefined ? lhs : this.visit(node.rhs);
|
|
2905
|
+
return this.visit(node.lhs) ?? this.visit(node.rhs);
|
|
3325
2906
|
}
|
|
3326
2907
|
[nodes.not](node) {
|
|
3327
2908
|
return !this.visit(node.expr);
|
|
@@ -3388,8 +2969,7 @@ var ftl = (function (exports) {
|
|
|
3388
2969
|
return this.visit(node.cond) ? this.visit(node.ifTrue) : this.visit(node.ifFalse);
|
|
3389
2970
|
}
|
|
3390
2971
|
[nodes.elv](node) {
|
|
3391
|
-
|
|
3392
|
-
return cond ? cond : this.visit(node.ifFalse);
|
|
2972
|
+
return this.visit(node.cond) || this.visit(node.ifFalse);
|
|
3393
2973
|
}
|
|
3394
2974
|
[nodes.access](node) {
|
|
3395
2975
|
let prev;
|
|
@@ -3455,16 +3035,33 @@ var ftl = (function (exports) {
|
|
|
3455
3035
|
* spliced into the expression text.
|
|
3456
3036
|
*/
|
|
3457
3037
|
class Expressions {
|
|
3038
|
+
/** Parses the whole text as one expression: `user.name`. */
|
|
3458
3039
|
static MODE_EXPRESSION = Symbol('MODE_EXPRESSION');
|
|
3040
|
+
/**
|
|
3041
|
+
* Parses text with interpolations, `Hello {{ user.name }}`, evaluating to
|
|
3042
|
+
* its parts: `{ type, value }` for each literal run and each `{{ }}` (text),
|
|
3043
|
+
* `{{{ }}}` (html) or `{{{{ }}}}` (node) interpolation, in order.
|
|
3044
|
+
*/
|
|
3459
3045
|
static MODE_TEMPLATED = Symbol('MODE_TEMPLATED');
|
|
3046
|
+
/**
|
|
3047
|
+
* The key under which the receiver of a module function answers a lookup
|
|
3048
|
+
* against the bound data alone: `this[Expressions.BOUND](name)` resolves
|
|
3049
|
+
* the name in the layers the scope was created with (a registry's data,
|
|
3050
|
+
* the data handed to a Template factory) and never in an overlay pushed
|
|
3051
|
+
* afterwards, by `data-tpl-each`, `data-tpl-with` or `withOverlay`. It is
|
|
3052
|
+
* how a module reads what the page configured without the rendered data
|
|
3053
|
+
* being able to supply or replace it. No name on the data stack reaches it.
|
|
3054
|
+
*/
|
|
3055
|
+
static BOUND = BOUND;
|
|
3460
3056
|
|
|
3461
3057
|
static #astCache = new BoundedCache(1000);
|
|
3462
3058
|
|
|
3463
3059
|
/**
|
|
3464
|
-
* Parses an expression.
|
|
3060
|
+
* Parses an expression, caching the ast by mode and text.
|
|
3465
3061
|
* @param {string} expression
|
|
3466
|
-
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
3467
|
-
* @returns the ast
|
|
3062
|
+
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode] MODE_EXPRESSION when omitted
|
|
3063
|
+
* @returns {any} the ast
|
|
3064
|
+
* @throws a peggy syntax error when the text does not parse
|
|
3468
3065
|
*/
|
|
3469
3066
|
static parse(expression, mode) {
|
|
3470
3067
|
const key = mode?.toString() + expression;
|
|
@@ -3475,26 +3072,28 @@ var ftl = (function (exports) {
|
|
|
3475
3072
|
);
|
|
3476
3073
|
}
|
|
3477
3074
|
/**
|
|
3478
|
-
* Evaluates
|
|
3075
|
+
* Evaluates a parsed ast against the modules and the data stack.
|
|
3479
3076
|
* @param {{[k: string]: any } | null | undefined } modules
|
|
3480
|
-
* @param {any[]} dataStack
|
|
3481
|
-
* @param {any} ast
|
|
3482
|
-
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
3483
|
-
* @
|
|
3077
|
+
* @param {any[]} dataStack innermost overlay last
|
|
3078
|
+
* @param {any} ast what `parse` answered
|
|
3079
|
+
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode] the mode it was parsed in
|
|
3080
|
+
* @param {number} [bound] how many layers, from the outermost, are the bound data; all of them when omitted
|
|
3081
|
+
* @returns {any} the value, or the list of parts in MODE_TEMPLATED
|
|
3484
3082
|
*/
|
|
3485
|
-
static evaluate(modules, dataStack, ast, mode) {
|
|
3486
|
-
return new EvaluatingVisitor(modules, dataStack).visitRoot(ast, mode === Expressions.MODE_TEMPLATED);
|
|
3083
|
+
static evaluate(modules, dataStack, ast, mode, bound) {
|
|
3084
|
+
return new EvaluatingVisitor(modules, dataStack, bound).visitRoot(ast, mode === Expressions.MODE_TEMPLATED);
|
|
3487
3085
|
}
|
|
3488
3086
|
/**
|
|
3489
3087
|
* Parses and evaluates an expression.
|
|
3490
3088
|
* @param {{ [x: string]: any; } | null | undefined} modules
|
|
3491
|
-
* @param {any[]} dataStack
|
|
3089
|
+
* @param {any[]} dataStack innermost overlay last
|
|
3492
3090
|
* @param {string} expression
|
|
3493
|
-
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
3494
|
-
* @
|
|
3091
|
+
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode] MODE_EXPRESSION when omitted
|
|
3092
|
+
* @param {number} [bound] how many layers, from the outermost, are the bound data; all of them when omitted
|
|
3093
|
+
* @returns {any} the value, or the list of parts in MODE_TEMPLATED
|
|
3495
3094
|
*/
|
|
3496
|
-
static interpret(modules, dataStack, expression, mode) {
|
|
3497
|
-
return Expressions.evaluate(modules, dataStack, Expressions.parse(expression, mode), mode);
|
|
3095
|
+
static interpret(modules, dataStack, expression, mode, bound) {
|
|
3096
|
+
return Expressions.evaluate(modules, dataStack, Expressions.parse(expression, mode), mode, bound);
|
|
3498
3097
|
}
|
|
3499
3098
|
}
|
|
3500
3099
|
|
|
@@ -3503,48 +3102,89 @@ var ftl = (function (exports) {
|
|
|
3503
3102
|
* that a bare identifier resolves against, as a single value. Adding an overlay
|
|
3504
3103
|
* returns a new evaluator instead of modifying this one, so a template can add
|
|
3505
3104
|
* data for one subtree without affecting the rest of the render.
|
|
3105
|
+
*
|
|
3106
|
+
* The layers an evaluator is created with are its bound data; the overlays
|
|
3107
|
+
* pushed afterwards are not. A bare identifier resolves against both, while a
|
|
3108
|
+
* module function can ask for the bound data alone through `Expressions.BOUND`.
|
|
3506
3109
|
*/
|
|
3507
3110
|
class ExpressionEvaluator {
|
|
3508
3111
|
#modules;
|
|
3509
3112
|
#dataStack;
|
|
3510
|
-
|
|
3113
|
+
#bound;
|
|
3114
|
+
/**
|
|
3115
|
+
* @param {{ [k: string]: any } | null | undefined} modules
|
|
3116
|
+
* @param {any[]} dataStack innermost overlay last
|
|
3117
|
+
* @param {number} [bound] how many layers, from the outermost, are the bound data; all of them when omitted
|
|
3118
|
+
*/
|
|
3119
|
+
constructor(modules, dataStack, bound) {
|
|
3511
3120
|
this.#modules = modules;
|
|
3512
3121
|
this.#dataStack = dataStack;
|
|
3122
|
+
this.#bound = bound ?? dataStack.length;
|
|
3513
3123
|
}
|
|
3124
|
+
/**
|
|
3125
|
+
* A new evaluator with one more module: `#name:fn()` resolves into it, and an
|
|
3126
|
+
* empty name merges a whole map whose functions resolve bare, as `#fn()`.
|
|
3127
|
+
* @param {string} name
|
|
3128
|
+
* @param {object} value
|
|
3129
|
+
* @returns {ExpressionEvaluator}
|
|
3130
|
+
*/
|
|
3514
3131
|
withModule(name, value) {
|
|
3515
3132
|
const module = name ? { [name]: value } : value;
|
|
3516
|
-
return new ExpressionEvaluator({ ...this.#modules, ...module }, this.#dataStack);
|
|
3133
|
+
return new ExpressionEvaluator({ ...this.#modules, ...module }, this.#dataStack, this.#bound);
|
|
3517
3134
|
}
|
|
3135
|
+
/**
|
|
3136
|
+
* A new evaluator with the data pushed as the innermost overlays, the last
|
|
3137
|
+
* one winning a shared name. The bound data stays what it was.
|
|
3138
|
+
* @param {...any} data
|
|
3139
|
+
* @returns {ExpressionEvaluator}
|
|
3140
|
+
*/
|
|
3518
3141
|
withOverlay(...data) {
|
|
3519
3142
|
return new ExpressionEvaluator(
|
|
3520
3143
|
this.#modules,
|
|
3521
3144
|
data.length === 0 ? this.#dataStack : [...this.#dataStack, ...data],
|
|
3145
|
+
this.#bound,
|
|
3522
3146
|
);
|
|
3523
3147
|
}
|
|
3524
3148
|
/**
|
|
3525
3149
|
* Resolves a name against the data stack, with no parse round trip: the
|
|
3526
3150
|
* lookup a template's bare identifier makes, for an imperative caller.
|
|
3527
3151
|
* @param {string} name
|
|
3152
|
+
* @returns {any} undefined when no overlay carries the name
|
|
3528
3153
|
*/
|
|
3529
3154
|
resolve(name) {
|
|
3530
3155
|
return resolveInStack(this.#dataStack, name);
|
|
3531
3156
|
}
|
|
3532
|
-
/**
|
|
3157
|
+
/**
|
|
3158
|
+
* Evaluates an expression against this scope.
|
|
3159
|
+
* @param {string} expression
|
|
3160
|
+
* @returns {any}
|
|
3161
|
+
*/
|
|
3533
3162
|
evaluateExpression(expression) {
|
|
3534
|
-
return Expressions.interpret(
|
|
3163
|
+
return Expressions.interpret(
|
|
3164
|
+
this.#modules,
|
|
3165
|
+
this.#dataStack,
|
|
3166
|
+
expression,
|
|
3167
|
+
Expressions.MODE_EXPRESSION,
|
|
3168
|
+
this.#bound,
|
|
3169
|
+
);
|
|
3535
3170
|
}
|
|
3536
|
-
/**
|
|
3171
|
+
/**
|
|
3172
|
+
* Evaluates a templated text, the `{{ }}` form, against this scope.
|
|
3173
|
+
* @param {string} text
|
|
3174
|
+
* @returns {{ type: symbol, value: any }[]} its parts, as MODE_TEMPLATED describes
|
|
3175
|
+
*/
|
|
3537
3176
|
evaluateTemplated(text) {
|
|
3538
|
-
return Expressions.interpret(this.#modules, this.#dataStack, text, Expressions.MODE_TEMPLATED);
|
|
3177
|
+
return Expressions.interpret(this.#modules, this.#dataStack, text, Expressions.MODE_TEMPLATED, this.#bound);
|
|
3539
3178
|
}
|
|
3540
3179
|
}
|
|
3541
3180
|
|
|
3542
|
-
/** Creates and inspects
|
|
3181
|
+
/** Creates, serializes and inspects DocumentFragments. */
|
|
3543
3182
|
class Fragments {
|
|
3544
3183
|
/**
|
|
3545
|
-
*
|
|
3546
|
-
*
|
|
3547
|
-
* @
|
|
3184
|
+
* Parses html into a DocumentFragment adopted by the document, each piece
|
|
3185
|
+
* trimmed and the pieces joined.
|
|
3186
|
+
* @param {...string} html
|
|
3187
|
+
* @returns {DocumentFragment}
|
|
3548
3188
|
*/
|
|
3549
3189
|
static fromHtml(...html) {
|
|
3550
3190
|
const el = document.createElement('template');
|
|
@@ -3552,11 +3192,11 @@ var ftl = (function (exports) {
|
|
|
3552
3192
|
return document.adoptNode(el.content);
|
|
3553
3193
|
}
|
|
3554
3194
|
/**
|
|
3555
|
-
*
|
|
3556
|
-
*
|
|
3195
|
+
* Serializes a fragment, or a single node, to html, consuming it: the nodes
|
|
3196
|
+
* are moved out, not copied, and a fragment is left empty. Pass
|
|
3557
3197
|
* `fragment.cloneNode(true)` to keep the original usable.
|
|
3558
|
-
* @param {DocumentFragment} fragment
|
|
3559
|
-
* @returns {string}
|
|
3198
|
+
* @param {DocumentFragment|Node} fragment
|
|
3199
|
+
* @returns {string}
|
|
3560
3200
|
*/
|
|
3561
3201
|
static toHtml(fragment) {
|
|
3562
3202
|
var el = document.createElement('template');
|
|
@@ -3564,17 +3204,17 @@ var ftl = (function (exports) {
|
|
|
3564
3204
|
return el.innerHTML;
|
|
3565
3205
|
}
|
|
3566
3206
|
/**
|
|
3567
|
-
*
|
|
3207
|
+
* Whether a fragment holds no element and no text but whitespace.
|
|
3568
3208
|
* @param {DocumentFragment} fragment
|
|
3569
|
-
* @returns {boolean}
|
|
3209
|
+
* @returns {boolean}
|
|
3570
3210
|
*/
|
|
3571
3211
|
static isBlank(fragment) {
|
|
3572
3212
|
return fragment.childElementCount === 0 && fragment.textContent.trim() === '';
|
|
3573
3213
|
}
|
|
3574
3214
|
/**
|
|
3575
|
-
*
|
|
3576
|
-
* @param
|
|
3577
|
-
* @returns {DocumentFragment}
|
|
3215
|
+
* Moves the nodes, in order, into a new DocumentFragment.
|
|
3216
|
+
* @param {...Node} nodes
|
|
3217
|
+
* @returns {DocumentFragment}
|
|
3578
3218
|
*/
|
|
3579
3219
|
static from(...nodes) {
|
|
3580
3220
|
const fragment = new DocumentFragment();
|
|
@@ -3584,9 +3224,10 @@ var ftl = (function (exports) {
|
|
|
3584
3224
|
return fragment;
|
|
3585
3225
|
}
|
|
3586
3226
|
/**
|
|
3587
|
-
*
|
|
3227
|
+
* Moves the children of a node into a new DocumentFragment, leaving the
|
|
3228
|
+
* node empty.
|
|
3588
3229
|
* @param {Node} el
|
|
3589
|
-
* @returns {DocumentFragment}
|
|
3230
|
+
* @returns {DocumentFragment}
|
|
3590
3231
|
*/
|
|
3591
3232
|
static fromChildNodes(el) {
|
|
3592
3233
|
const fragment = new DocumentFragment();
|
|
@@ -3597,23 +3238,23 @@ var ftl = (function (exports) {
|
|
|
3597
3238
|
}
|
|
3598
3239
|
}
|
|
3599
3240
|
|
|
3600
|
-
/** Attribute
|
|
3241
|
+
/** Attribute helpers: unique ids, defaults, prefixed forwarding, and writes where a nullish value removes the attribute. */
|
|
3601
3242
|
class Attributes {
|
|
3602
3243
|
static id = 0;
|
|
3603
3244
|
/**
|
|
3604
|
-
*
|
|
3245
|
+
* A page-unique id under the prefix, as `prefix-n`.
|
|
3605
3246
|
* @param {string} prefix
|
|
3606
|
-
* @returns
|
|
3247
|
+
* @returns {string}
|
|
3607
3248
|
*/
|
|
3608
3249
|
static uid(prefix) {
|
|
3609
3250
|
return `${prefix}-${++Attributes.id}`;
|
|
3610
3251
|
}
|
|
3611
3252
|
/**
|
|
3612
|
-
* Sets an attribute
|
|
3253
|
+
* Sets an attribute when the element does not carry it.
|
|
3613
3254
|
* @param {Element} el
|
|
3614
3255
|
* @param {string} k
|
|
3615
3256
|
* @param {string} v
|
|
3616
|
-
* @returns
|
|
3257
|
+
* @returns {string|null} the attribute's value afterwards
|
|
3617
3258
|
*/
|
|
3618
3259
|
static defaultValue(el, k, v) {
|
|
3619
3260
|
if (!el.hasAttribute(k)) {
|
|
@@ -3622,7 +3263,9 @@ var ftl = (function (exports) {
|
|
|
3622
3263
|
return el.getAttribute(k);
|
|
3623
3264
|
}
|
|
3624
3265
|
/**
|
|
3625
|
-
*
|
|
3266
|
+
* Copies every attribute whose name starts with the prefix onto another
|
|
3267
|
+
* element, under the name without the prefix. `<prefix>class` adds its
|
|
3268
|
+
* classes to the target's instead of replacing them.
|
|
3626
3269
|
* @param {string} prefix
|
|
3627
3270
|
* @param {Element} from
|
|
3628
3271
|
* @param {Element} to
|
|
@@ -3645,7 +3288,7 @@ var ftl = (function (exports) {
|
|
|
3645
3288
|
});
|
|
3646
3289
|
}
|
|
3647
3290
|
/**
|
|
3648
|
-
* Sets
|
|
3291
|
+
* Sets an attribute, or removes it when the value is nullish.
|
|
3649
3292
|
* @param {Element} el
|
|
3650
3293
|
* @param {string} attr
|
|
3651
3294
|
* @param {string | null | undefined} value
|
|
@@ -3667,13 +3310,14 @@ var ftl = (function (exports) {
|
|
|
3667
3310
|
*/
|
|
3668
3311
|
class LightSlots {
|
|
3669
3312
|
/**
|
|
3670
|
-
*
|
|
3313
|
+
* Takes an element's children apart into slots, leaving the element empty.
|
|
3314
|
+
* A named child is removed and contributes what `slotFromNode` answers;
|
|
3315
|
+
* children sharing a name are gathered in order. A child with an empty
|
|
3316
|
+
* `slot` belongs to the default slot, in document order among the rest.
|
|
3671
3317
|
* @param {Element} el
|
|
3672
|
-
* @returns the slots
|
|
3318
|
+
* @returns {Record<string, DocumentFragment>} the slots by name, `default` always present
|
|
3673
3319
|
*/
|
|
3674
3320
|
static from(el) {
|
|
3675
|
-
//the platform reads slot="" as the default slot: such children stay in
|
|
3676
|
-
//the document order of the default content, their claim stripped like any named one
|
|
3677
3321
|
for (const child of el.children) {
|
|
3678
3322
|
if (child.matches('[slot=""]')) {
|
|
3679
3323
|
child.removeAttribute('slot');
|
|
@@ -3688,7 +3332,7 @@ var ftl = (function (exports) {
|
|
|
3688
3332
|
el.removeAttribute('slot');
|
|
3689
3333
|
return [slot, LightSlots.slotFromNode(el)];
|
|
3690
3334
|
});
|
|
3691
|
-
const slots =
|
|
3335
|
+
const slots = Object.create(null);
|
|
3692
3336
|
slots.default = new DocumentFragment();
|
|
3693
3337
|
slots.default.append(...el.childNodes);
|
|
3694
3338
|
for (const [name, el] of namedSlots) {
|
|
@@ -3699,6 +3343,12 @@ var ftl = (function (exports) {
|
|
|
3699
3343
|
}
|
|
3700
3344
|
return slots;
|
|
3701
3345
|
}
|
|
3346
|
+
/**
|
|
3347
|
+
* What a slotted node contributes: a template's content, the parsed markup
|
|
3348
|
+
* of a `<script type="text/html">`, or the node itself.
|
|
3349
|
+
* @param {Element} el
|
|
3350
|
+
* @returns {Element|DocumentFragment}
|
|
3351
|
+
*/
|
|
3702
3352
|
static slotFromNode(el) {
|
|
3703
3353
|
if (el instanceof HTMLTemplateElement) {
|
|
3704
3354
|
return document.adoptNode(el.content);
|
|
@@ -3710,12 +3360,13 @@ var ftl = (function (exports) {
|
|
|
3710
3360
|
}
|
|
3711
3361
|
}
|
|
3712
3362
|
|
|
3713
|
-
/** Waits
|
|
3363
|
+
/** Waits on the parser and the document, and queries an element's own children. */
|
|
3714
3364
|
class Nodes {
|
|
3715
3365
|
/**
|
|
3716
|
-
*
|
|
3366
|
+
* Whether the parser has moved past the element: the element, or one of
|
|
3367
|
+
* its ancestors, has a next sibling.
|
|
3717
3368
|
* @param {Element} el
|
|
3718
|
-
* @returns
|
|
3369
|
+
* @returns {boolean}
|
|
3719
3370
|
*/
|
|
3720
3371
|
static isParsed(el) {
|
|
3721
3372
|
for (let c = /** @type {Node | null} */ (el); c; c = c.parentNode) {
|
|
@@ -3727,13 +3378,12 @@ var ftl = (function (exports) {
|
|
|
3727
3378
|
}
|
|
3728
3379
|
|
|
3729
3380
|
/**
|
|
3730
|
-
* Waits for the document's DOMContentLoaded
|
|
3731
|
-
*
|
|
3732
|
-
*
|
|
3733
|
-
*
|
|
3734
|
-
*
|
|
3735
|
-
*
|
|
3736
|
-
* never early.
|
|
3381
|
+
* Waits for the document's DOMContentLoaded. Resolves at once when that
|
|
3382
|
+
* moment already passed, and for a document with no view, which receives
|
|
3383
|
+
* no events. Never resolves early for a document still running its
|
|
3384
|
+
* deferred scripts.
|
|
3385
|
+
* @param {Document} doc
|
|
3386
|
+
* @returns {Promise<void>}
|
|
3737
3387
|
*/
|
|
3738
3388
|
static waitDomContentLoaded(doc) {
|
|
3739
3389
|
if (doc.readyState === 'loading') {
|
|
@@ -3746,7 +3396,13 @@ var ftl = (function (exports) {
|
|
|
3746
3396
|
}
|
|
3747
3397
|
const win = doc.defaultView;
|
|
3748
3398
|
if (win === null) {
|
|
3749
|
-
|
|
3399
|
+
return Promise.resolve();
|
|
3400
|
+
}
|
|
3401
|
+
// interactive spans both the deferred scripts and the time between DOMContentLoaded and load
|
|
3402
|
+
const [navigation] = /** @type {PerformanceNavigationTiming[]} */ (
|
|
3403
|
+
win.performance?.getEntriesByType('navigation') ?? []
|
|
3404
|
+
);
|
|
3405
|
+
if (navigation?.domContentLoadedEventStart > 0) {
|
|
3750
3406
|
return Promise.resolve();
|
|
3751
3407
|
}
|
|
3752
3408
|
return new Promise((resolve) => {
|
|
@@ -3765,22 +3421,12 @@ var ftl = (function (exports) {
|
|
|
3765
3421
|
* resolves once the element, or any of its ancestors, gains a next sibling,
|
|
3766
3422
|
* which is the parser having moved past this subtree. The document's
|
|
3767
3423
|
* DOMContentLoaded is the deadline. Resolves immediately for an element
|
|
3768
|
-
* that is already parsed.
|
|
3769
|
-
*
|
|
3770
|
-
*
|
|
3771
|
-
* predicate reads: an element last among its siblings becomes parsed when
|
|
3772
|
-
* an ancestor gains one, and a childList observer on the parent never sees
|
|
3773
|
-
* that. Formatted markup usually hides the difference, the whitespace
|
|
3774
|
-
* before a closing tag being a text node the parent does gain, so the gap
|
|
3775
|
-
* shows on whitespace-free markup, where the wait fell back to the
|
|
3776
|
-
* deadline. One observer takes many targets, so the cost is one observe()
|
|
3777
|
-
* per level, and it is disconnected at the first checkpoint past the
|
|
3778
|
-
* element either way.
|
|
3779
|
-
* @param {any} el
|
|
3780
|
-
* @returns {Promise<any>}
|
|
3424
|
+
* that is already parsed, or once the parser has finished the document.
|
|
3425
|
+
* @param {Element} el
|
|
3426
|
+
* @returns {Promise<Element>} the element
|
|
3781
3427
|
*/
|
|
3782
3428
|
static waitParsed(el) {
|
|
3783
|
-
if (Nodes.isParsed(el)) {
|
|
3429
|
+
if (Nodes.isParsed(el) || el.ownerDocument.readyState !== 'loading') {
|
|
3784
3430
|
return Promise.resolve(el);
|
|
3785
3431
|
}
|
|
3786
3432
|
return new Promise((resolve) => {
|
|
@@ -3802,10 +3448,10 @@ var ftl = (function (exports) {
|
|
|
3802
3448
|
}
|
|
3803
3449
|
|
|
3804
3450
|
/**
|
|
3805
|
-
*
|
|
3806
|
-
* @param {Element} el
|
|
3451
|
+
* The first child element matching the selector, descendants excluded.
|
|
3452
|
+
* @param {Element|DocumentFragment} el
|
|
3807
3453
|
* @param {string} selector
|
|
3808
|
-
* @returns
|
|
3454
|
+
* @returns {Element|null}
|
|
3809
3455
|
*/
|
|
3810
3456
|
static queryChildren(el, selector) {
|
|
3811
3457
|
for (const c of el.children) {
|
|
@@ -3816,10 +3462,10 @@ var ftl = (function (exports) {
|
|
|
3816
3462
|
return null;
|
|
3817
3463
|
}
|
|
3818
3464
|
/**
|
|
3819
|
-
*
|
|
3820
|
-
* @param {Element} el
|
|
3465
|
+
* Every child element matching the selector, descendants excluded.
|
|
3466
|
+
* @param {Element|DocumentFragment} el
|
|
3821
3467
|
* @param {string} selector
|
|
3822
|
-
* @returns
|
|
3468
|
+
* @returns {Element[]}
|
|
3823
3469
|
*/
|
|
3824
3470
|
static queryChildrenAll(el, selector) {
|
|
3825
3471
|
const r = [];
|
|
@@ -3876,9 +3522,11 @@ var ftl = (function (exports) {
|
|
|
3876
3522
|
|
|
3877
3523
|
/** The `data-tpl-*` commands, each taking the node it is written on and the scope it evaluates in. */
|
|
3878
3524
|
class CommandsHandler {
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3525
|
+
/**
|
|
3526
|
+
* The order the commands run in on one element, each seeing the node as the
|
|
3527
|
+
* ones before left it: tplIf gates before tplWith and tplEach push their
|
|
3528
|
+
* overlay, tplWhen gates after, inside the scope that overlay opened.
|
|
3529
|
+
*/
|
|
3882
3530
|
static ORDERED_COMMANDS = [
|
|
3883
3531
|
'tplIf',
|
|
3884
3532
|
'tplWith',
|
|
@@ -3889,8 +3537,7 @@ var ftl = (function (exports) {
|
|
|
3889
3537
|
'tplRemove',
|
|
3890
3538
|
'tplVerbatim',
|
|
3891
3539
|
];
|
|
3892
|
-
|
|
3893
|
-
//if evaluates in the outer scope, before with/each
|
|
3540
|
+
/** Removes the node when the expression is falsy, evaluated before tplWith and tplEach open their overlay. */
|
|
3894
3541
|
static tplIf(node, expression, ops, evaluator) {
|
|
3895
3542
|
const accept = evaluator.evaluateExpression(expression);
|
|
3896
3543
|
if (!accept) {
|
|
@@ -3905,49 +3552,37 @@ var ftl = (function (exports) {
|
|
|
3905
3552
|
.render();
|
|
3906
3553
|
ops.replace(node, newNode);
|
|
3907
3554
|
}
|
|
3555
|
+
/**
|
|
3556
|
+
* Renders the node once per entry, in place of the node. A Map iterates as
|
|
3557
|
+
* `{ key, value }` entries in its own order, a plain object as `{ key, value }`
|
|
3558
|
+
* entries in `Object.entries` order, and any other iterable as itself; a
|
|
3559
|
+
* value that is none of these throws. Each render sees its entry under
|
|
3560
|
+
* `data-tpl-var`, or as the whole overlay without one. `data-tpl-stat` names
|
|
3561
|
+
* an overlay beneath the entry carrying `index`, `count`, `size`, `first`,
|
|
3562
|
+
* `last`, `even` and `odd`, so an entry property of the same name wins; the
|
|
3563
|
+
* size, and so `last`, is null for a collection that knows neither its
|
|
3564
|
+
* `length` nor its `size`, which is never consumed to learn it.
|
|
3565
|
+
*/
|
|
3908
3566
|
static tplEach(node, expression, ops, evaluator) {
|
|
3909
3567
|
const varName = ops.popData(node, 'tplVar');
|
|
3910
3568
|
const statName = ops.popData(node, 'tplStat');
|
|
3911
3569
|
const template = new Template(node, evaluator);
|
|
3912
3570
|
const evaluated = evaluator.evaluateExpression(expression);
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
const proto = evaluated === null || typeof evaluated !== 'object' ? undefined : Object.getPrototypeOf(evaluated);
|
|
3919
|
-
const keyed =
|
|
3920
|
-
evaluated instanceof Map
|
|
3921
|
-
? [...evaluated]
|
|
3922
|
-
: !evaluated?.[Symbol.iterator] && (proto === Object.prototype || proto === null)
|
|
3923
|
-
? Object.entries(evaluated)
|
|
3924
|
-
: null;
|
|
3571
|
+
const proto =
|
|
3572
|
+
evaluated === null || typeof evaluated !== 'object' ? undefined : Object.getPrototypeOf(evaluated);
|
|
3573
|
+
const plain = !evaluated?.[Symbol.iterator] && (proto === Object.prototype || proto === null);
|
|
3574
|
+
const dict = plain ? Object.entries(evaluated) : null;
|
|
3575
|
+
const keyed = evaluated instanceof Map ? [...evaluated] : dict;
|
|
3925
3576
|
const entries = keyed === null ? evaluated : keyed.map(([key, value]) => ({ key, value }));
|
|
3926
3577
|
if (!entries?.[Symbol.iterator]) {
|
|
3927
3578
|
throw new Error(`Expected an iterable got '${evaluated}'`);
|
|
3928
3579
|
}
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
}
|
|
3933
|
-
ops.remove(node);
|
|
3934
|
-
return;
|
|
3935
|
-
}
|
|
3936
|
-
//the stat rides grouped under its declared name, overlaid below the
|
|
3937
|
-
//item, so data can never collide with its fields and an item property
|
|
3938
|
-
//sharing the stat's very name wins, as data always does. The size is
|
|
3939
|
-
//read where the collection already knows it (arrays and keyed entries
|
|
3940
|
-
//by length, sets and the like by size): an arbitrary iterator is never
|
|
3941
|
-
//consumed to learn it, so its size and last read null, the unknown
|
|
3942
|
-
const size = Array.isArray(entries)
|
|
3943
|
-
? entries.length
|
|
3944
|
-
: typeof entries.length === 'number'
|
|
3945
|
-
? entries.length
|
|
3946
|
-
: typeof entries.size === 'number'
|
|
3947
|
-
? entries.size
|
|
3948
|
-
: null;
|
|
3580
|
+
const measured = statName ? entries : null;
|
|
3581
|
+
const counted = typeof measured?.length === 'number' ? measured.length : measured?.size;
|
|
3582
|
+
const size = typeof counted === 'number' ? counted : null;
|
|
3949
3583
|
let index = 0;
|
|
3950
3584
|
for (const v of entries) {
|
|
3585
|
+
const item = varName ? { [varName]: v } : v;
|
|
3951
3586
|
const stat = {
|
|
3952
3587
|
index,
|
|
3953
3588
|
count: index + 1,
|
|
@@ -3957,16 +3592,13 @@ var ftl = (function (exports) {
|
|
|
3957
3592
|
even: index % 2 === 0,
|
|
3958
3593
|
odd: index % 2 === 1,
|
|
3959
3594
|
};
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
template.withOverlay({ [statName]: stat }, varName ? { [varName]: v } : v).render(),
|
|
3963
|
-
);
|
|
3595
|
+
const layers = statName ? [{ [statName]: stat }, item] : [item];
|
|
3596
|
+
ops.prepend(node, template.withOverlay(...layers).render());
|
|
3964
3597
|
++index;
|
|
3965
3598
|
}
|
|
3966
3599
|
ops.remove(node);
|
|
3967
3600
|
}
|
|
3968
|
-
|
|
3969
|
-
//when evaluates after with/each, in the scope their overlay opened
|
|
3601
|
+
/** Removes the node when the expression is falsy, evaluated in the overlay tplWith or tplEach opened. */
|
|
3970
3602
|
static tplWhen(node, expression, ops, evaluator) {
|
|
3971
3603
|
const accept = evaluator.evaluateExpression(expression);
|
|
3972
3604
|
if (!accept) {
|
|
@@ -3980,12 +3612,8 @@ var ftl = (function (exports) {
|
|
|
3980
3612
|
static tplRemove(node, value, ops, evaluator) {
|
|
3981
3613
|
switch (value.toLowerCase()) {
|
|
3982
3614
|
case 'tag': {
|
|
3983
|
-
const fragment =
|
|
3984
|
-
while (node.firstChild) {
|
|
3985
|
-
fragment.appendChild(node.firstChild);
|
|
3986
|
-
}
|
|
3615
|
+
const fragment = Fragments.fromChildNodes(node);
|
|
3987
3616
|
if ('tplVerbatim' in node.dataset) {
|
|
3988
|
-
//we are removing the parent element so we have to handle the lower priority commands
|
|
3989
3617
|
ops.popData(node, 'tplVerbatim');
|
|
3990
3618
|
ops.replace(node, fragment);
|
|
3991
3619
|
} else {
|
|
@@ -4021,6 +3649,9 @@ var ftl = (function (exports) {
|
|
|
4021
3649
|
}
|
|
4022
3650
|
const tuples = Array.isArray(attributesAndValues[0]) ? attributesAndValues : [attributesAndValues];
|
|
4023
3651
|
tuples.forEach(([k, v]) => {
|
|
3652
|
+
if (v === null || v === undefined) {
|
|
3653
|
+
return;
|
|
3654
|
+
}
|
|
4024
3655
|
node.setAttribute(k, v);
|
|
4025
3656
|
});
|
|
4026
3657
|
}
|
|
@@ -4048,12 +3679,10 @@ var ftl = (function (exports) {
|
|
|
4048
3679
|
}
|
|
4049
3680
|
}
|
|
4050
3681
|
|
|
4051
|
-
// Module-isolated string cache for dataset-to-attribute conversions
|
|
4052
3682
|
const attributeCache = new BoundedCache(1000);
|
|
4053
3683
|
|
|
4054
3684
|
/**
|
|
4055
|
-
*
|
|
4056
|
-
* Uses a cache lookup to avoid repetitive regex/string splitting.
|
|
3685
|
+
* The attribute a `tpl` dataset key targets: `tplAriaLabel` is `aria-label`.
|
|
4057
3686
|
* @param {string} dataSetKey
|
|
4058
3687
|
* @returns {string}
|
|
4059
3688
|
*/
|
|
@@ -4075,38 +3704,40 @@ var ftl = (function (exports) {
|
|
|
4075
3704
|
*/
|
|
4076
3705
|
class Template {
|
|
4077
3706
|
/**
|
|
4078
|
-
* Creates a template from
|
|
3707
|
+
* Creates a template from html.
|
|
4079
3708
|
* @param {string} html
|
|
4080
3709
|
* @param {{ [k: string] : any }?} [modules]
|
|
4081
|
-
* @param {...*} data
|
|
4082
|
-
* @returns
|
|
3710
|
+
* @param {...*} data the data stack, innermost last
|
|
3711
|
+
* @returns {Template}
|
|
4083
3712
|
*/
|
|
4084
3713
|
static fromHtml(html, modules, ...data) {
|
|
4085
3714
|
return new Template(Fragments.fromHtml(html), new ExpressionEvaluator(modules, data));
|
|
4086
3715
|
}
|
|
4087
3716
|
|
|
4088
3717
|
/**
|
|
4089
|
-
* Creates a template from the content of the first
|
|
3718
|
+
* Creates a template from the content of the first element matching the
|
|
3719
|
+
* selector, which is adopted: the template element is left empty.
|
|
4090
3720
|
* @param {string} selector for an HTMLTemplateElement
|
|
4091
3721
|
* @param {{ [k: string] : any }?} [modules]
|
|
4092
|
-
* @param {...*} data
|
|
4093
|
-
* @returns
|
|
3722
|
+
* @param {...*} data the data stack, innermost last
|
|
3723
|
+
* @returns {Template}
|
|
3724
|
+
* @throws when the selector matches no template element
|
|
4094
3725
|
*/
|
|
4095
3726
|
static fromSelector(selector, modules, ...data) {
|
|
4096
3727
|
const templateEl = document.querySelector(selector);
|
|
4097
3728
|
if (!(templateEl instanceof HTMLTemplateElement)) {
|
|
4098
3729
|
throw new Error('template selector does not match any template tag');
|
|
4099
3730
|
}
|
|
4100
|
-
|
|
4101
|
-
return new Template(fragment, new ExpressionEvaluator(modules, data));
|
|
3731
|
+
return Template.fromTemplate(templateEl, modules, ...data);
|
|
4102
3732
|
}
|
|
4103
3733
|
|
|
4104
3734
|
/**
|
|
4105
|
-
* Creates a template from the content of
|
|
3735
|
+
* Creates a template from the content of a template element, which is
|
|
3736
|
+
* adopted: the template element is left empty.
|
|
4106
3737
|
* @param {HTMLTemplateElement} templateEl
|
|
4107
3738
|
* @param {{ [k: string] : any }?} [modules]
|
|
4108
|
-
* @param {...*} data
|
|
4109
|
-
* @returns
|
|
3739
|
+
* @param {...*} data the data stack, innermost last
|
|
3740
|
+
* @returns {Template}
|
|
4110
3741
|
*/
|
|
4111
3742
|
static fromTemplate(templateEl, modules, ...data) {
|
|
4112
3743
|
const fragment = document.adoptNode(templateEl.content);
|
|
@@ -4114,11 +3745,12 @@ var ftl = (function (exports) {
|
|
|
4114
3745
|
}
|
|
4115
3746
|
|
|
4116
3747
|
/**
|
|
4117
|
-
* Creates a template
|
|
3748
|
+
* Creates a template over a fragment, which is imported afresh on every
|
|
3749
|
+
* render and never modified.
|
|
4118
3750
|
* @param {DocumentFragment} fragment
|
|
4119
3751
|
* @param { { [k: string] : any }? } [modules]
|
|
4120
|
-
* @param {...*} data
|
|
4121
|
-
* @returns
|
|
3752
|
+
* @param {...*} data the data stack, innermost last
|
|
3753
|
+
* @returns {Template}
|
|
4122
3754
|
*/
|
|
4123
3755
|
static fromFragment(fragment, modules, ...data) {
|
|
4124
3756
|
return new Template(fragment, new ExpressionEvaluator(modules, data));
|
|
@@ -4138,28 +3770,32 @@ var ftl = (function (exports) {
|
|
|
4138
3770
|
* Creates a new Template rendering in another scope: the one way to rebind
|
|
4139
3771
|
* a compiled template to a registry's modules and data.
|
|
4140
3772
|
* @param {ExpressionEvaluator} evaluator
|
|
3773
|
+
* @returns {Template}
|
|
4141
3774
|
*/
|
|
4142
3775
|
withEvaluator(evaluator) {
|
|
4143
3776
|
return new Template(this.#fragment, evaluator);
|
|
4144
3777
|
}
|
|
4145
3778
|
/**
|
|
4146
|
-
* Creates a new Template
|
|
3779
|
+
* Creates a new Template over another fragment, in the same scope.
|
|
4147
3780
|
* @param {DocumentFragment} fragment
|
|
3781
|
+
* @returns {Template}
|
|
4148
3782
|
*/
|
|
4149
3783
|
withFragment(fragment) {
|
|
4150
3784
|
return new Template(fragment, this.#evaluator);
|
|
4151
3785
|
}
|
|
4152
3786
|
/**
|
|
4153
|
-
* Creates a new Template with a
|
|
3787
|
+
* Creates a new Template with a module added, as `ExpressionEvaluator.withModule` does.
|
|
4154
3788
|
* @param {string?} name
|
|
4155
3789
|
* @param {{[k: string]: any}} value
|
|
3790
|
+
* @returns {Template}
|
|
4156
3791
|
*/
|
|
4157
3792
|
withModule(name, value) {
|
|
4158
3793
|
return new Template(this.#fragment, this.#evaluator.withModule(name, value));
|
|
4159
3794
|
}
|
|
4160
3795
|
/**
|
|
4161
|
-
* Creates a new Template with
|
|
3796
|
+
* Creates a new Template with the data pushed as the innermost overlays.
|
|
4162
3797
|
* @param {...*} data
|
|
3798
|
+
* @returns {Template}
|
|
4163
3799
|
*/
|
|
4164
3800
|
withOverlay(...data) {
|
|
4165
3801
|
return new Template(this.#fragment, this.#evaluator.withOverlay(...data));
|
|
@@ -4168,7 +3804,7 @@ var ftl = (function (exports) {
|
|
|
4168
3804
|
* Evaluates an expression in this template's scope, widened by the overlays.
|
|
4169
3805
|
* @param {string} expression
|
|
4170
3806
|
* @param {...*} data
|
|
4171
|
-
* @returns
|
|
3807
|
+
* @returns {any}
|
|
4172
3808
|
*/
|
|
4173
3809
|
evaluateExpression(expression, ...data) {
|
|
4174
3810
|
return this.#evaluator.withOverlay(...data).evaluateExpression(expression);
|
|
@@ -4177,33 +3813,29 @@ var ftl = (function (exports) {
|
|
|
4177
3813
|
* Evaluates a templated text, the `{{ }}` form, in this template's scope.
|
|
4178
3814
|
* @param {string} text
|
|
4179
3815
|
* @param {...*} data
|
|
4180
|
-
* @returns the parts
|
|
3816
|
+
* @returns {{ type: symbol, value: any }[]} the parts, as `Expressions.MODE_TEMPLATED` describes
|
|
4181
3817
|
*/
|
|
4182
3818
|
evaluateTemplated(text, ...data) {
|
|
4183
3819
|
return this.#evaluator.withOverlay(...data).evaluateTemplated(text);
|
|
4184
3820
|
}
|
|
4185
3821
|
/**
|
|
4186
|
-
*
|
|
3822
|
+
* The scope this template renders in.
|
|
3823
|
+
* @returns {ExpressionEvaluator}
|
|
4187
3824
|
*/
|
|
4188
3825
|
evaluator() {
|
|
4189
3826
|
return this.#evaluator;
|
|
4190
3827
|
}
|
|
4191
3828
|
/**
|
|
4192
|
-
* Renders the template
|
|
4193
|
-
*
|
|
3829
|
+
* Renders the template into a new fragment, applying the `data-tpl-*`
|
|
3830
|
+
* commands and bindings and the `{{ }}` interpolations.
|
|
3831
|
+
* @returns {DocumentFragment}
|
|
3832
|
+
* @throws {RenderError} naming the node and the directive that failed
|
|
4194
3833
|
*/
|
|
4195
3834
|
render() {
|
|
4196
3835
|
try {
|
|
4197
3836
|
const ops = new NodeOperations();
|
|
4198
3837
|
const imported = document.importNode(this.#fragment, true);
|
|
4199
|
-
const fragment =
|
|
4200
|
-
imported.nodeType === Node.DOCUMENT_FRAGMENT_NODE
|
|
4201
|
-
? imported
|
|
4202
|
-
: (() => {
|
|
4203
|
-
const d = new DocumentFragment();
|
|
4204
|
-
d.appendChild(imported);
|
|
4205
|
-
return d;
|
|
4206
|
-
})();
|
|
3838
|
+
const fragment = imported.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? imported : Fragments.from(imported);
|
|
4207
3839
|
const iterator = document.createNodeIterator(
|
|
4208
3840
|
fragment,
|
|
4209
3841
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
|
|
@@ -4229,8 +3861,6 @@ var ftl = (function (exports) {
|
|
|
4229
3861
|
try {
|
|
4230
3862
|
CommandsHandler[command](el, value, ops, this.#evaluator);
|
|
4231
3863
|
} catch (ex) {
|
|
4232
|
-
//the directive is popped before it runs, so the open tag no
|
|
4233
|
-
//longer carries it: the frame names it and its expression
|
|
4234
3864
|
throw RenderError.wrap(`Error evaluating data-tpl-${toAttr(command)}="${value}"`, el, ex);
|
|
4235
3865
|
}
|
|
4236
3866
|
if (ops.removed(el)) {
|
|
@@ -4253,17 +3883,13 @@ var ftl = (function (exports) {
|
|
|
4253
3883
|
el.setAttribute(attributeName, evaluated);
|
|
4254
3884
|
}
|
|
4255
3885
|
} catch (ex) {
|
|
4256
|
-
throw RenderError.wrap(`Error evaluating data-tpl-${
|
|
3886
|
+
throw RenderError.wrap(`Error evaluating data-tpl-${attributeName}="${expression}"`, el, ex);
|
|
4257
3887
|
}
|
|
4258
3888
|
}
|
|
4259
3889
|
}
|
|
4260
3890
|
ops.cleanup();
|
|
4261
3891
|
return fragment;
|
|
4262
3892
|
} catch (ex) {
|
|
4263
|
-
//a command, a text node or a nested render already named the node it
|
|
4264
|
-
//failed on: wrapping again would add a frame for the fragment that
|
|
4265
|
-
//contains it, one per level, serializing the whole template into the
|
|
4266
|
-
//message that survives. Only a failure outside those is framed here
|
|
4267
3893
|
if (ex instanceof RenderError) {
|
|
4268
3894
|
throw ex;
|
|
4269
3895
|
}
|
|
@@ -4271,22 +3897,26 @@ var ftl = (function (exports) {
|
|
|
4271
3897
|
}
|
|
4272
3898
|
}
|
|
4273
3899
|
/**
|
|
4274
|
-
* Renders this template
|
|
3900
|
+
* Renders this template into the element, replacing its children.
|
|
4275
3901
|
* @param {Element} el
|
|
3902
|
+
* @throws {RenderError}
|
|
4276
3903
|
*/
|
|
4277
3904
|
renderTo(el) {
|
|
4278
3905
|
el.replaceChildren(this.render());
|
|
4279
3906
|
}
|
|
4280
3907
|
/**
|
|
4281
|
-
* Renders this template
|
|
3908
|
+
* Renders this template and appends the result to the element.
|
|
4282
3909
|
* @param {Element} el
|
|
3910
|
+
* @throws {RenderError}
|
|
4283
3911
|
*/
|
|
4284
3912
|
appendTo(el) {
|
|
4285
3913
|
el.appendChild(this.render());
|
|
4286
3914
|
}
|
|
4287
3915
|
/**
|
|
4288
|
-
* Renders this template
|
|
3916
|
+
* Renders this template into the first element matching the selector,
|
|
3917
|
+
* replacing its children; does nothing when none matches.
|
|
4289
3918
|
* @param {string} selector
|
|
3919
|
+
* @throws {RenderError}
|
|
4290
3920
|
*/
|
|
4291
3921
|
renderToSelector(selector) {
|
|
4292
3922
|
const el = document.querySelector(selector);
|
|
@@ -4295,8 +3925,10 @@ var ftl = (function (exports) {
|
|
|
4295
3925
|
}
|
|
4296
3926
|
}
|
|
4297
3927
|
/**
|
|
4298
|
-
* Renders this template
|
|
3928
|
+
* Renders this template and appends the result to the first element
|
|
3929
|
+
* matching the selector; does nothing when none matches.
|
|
4299
3930
|
* @param {string} selector
|
|
3931
|
+
* @throws {RenderError}
|
|
4300
3932
|
*/
|
|
4301
3933
|
appendToSelector(selector) {
|
|
4302
3934
|
const el = document.querySelector(selector);
|
|
@@ -4320,30 +3952,26 @@ var ftl = (function (exports) {
|
|
|
4320
3952
|
}
|
|
4321
3953
|
|
|
4322
3954
|
/**
|
|
4323
|
-
* A render failure, one frame per nesting level
|
|
4324
|
-
*
|
|
4325
|
-
*
|
|
4326
|
-
*
|
|
4327
|
-
* the
|
|
4328
|
-
* `node`, so a failure costs no clone and a nested failure does not embed the
|
|
4329
|
-
* page in its own message.
|
|
3955
|
+
* A render failure, one frame per nesting level, chained through `cause` from
|
|
3956
|
+
* the outermost frame down to the error that failed the expression. A frame's
|
|
3957
|
+
* message names what was being evaluated and the node's open tag, with the
|
|
3958
|
+
* attributes it still carries: the directive being evaluated is already off
|
|
3959
|
+
* the tag. The subtree is not in the message; `html` serializes it on demand.
|
|
4330
3960
|
*/
|
|
4331
3961
|
class RenderError extends Error {
|
|
4332
|
-
/**
|
|
4333
|
-
* How many frames a chain keeps. The innermost are the specific ones, so a
|
|
4334
|
-
* deeper nesting drops the outer context rather than the failure site: three
|
|
4335
|
-
* frames name the offending node and the two levels that hold it, which is
|
|
4336
|
-
* the path a reader follows without the page arriving with it.
|
|
4337
|
-
*/
|
|
3962
|
+
/** How many frames a chain keeps: a deeper nesting drops the outermost ones and marks the chain `truncated`. */
|
|
4338
3963
|
static FRAMES = 3;
|
|
4339
3964
|
#node;
|
|
4340
3965
|
#depth;
|
|
4341
|
-
/**
|
|
3966
|
+
/** Whether the chain dropped outer frames to stay within FRAMES. */
|
|
4342
3967
|
truncated = false;
|
|
4343
3968
|
/**
|
|
4344
|
-
* Frames a failure, unless the chain already
|
|
4345
|
-
* cause
|
|
4346
|
-
*
|
|
3969
|
+
* Frames a failure, unless the chain already holds FRAMES frames: then the
|
|
3970
|
+
* cause is returned as it is, marked `truncated`.
|
|
3971
|
+
* @param {string} message
|
|
3972
|
+
* @param {Node} nodeOrFragment the node that failed
|
|
3973
|
+
* @param {any} cause
|
|
3974
|
+
* @returns {RenderError}
|
|
4347
3975
|
*/
|
|
4348
3976
|
static wrap(message, nodeOrFragment, cause) {
|
|
4349
3977
|
if (cause instanceof RenderError && cause.depth >= RenderError.FRAMES) {
|
|
@@ -4352,27 +3980,44 @@ var ftl = (function (exports) {
|
|
|
4352
3980
|
}
|
|
4353
3981
|
return new RenderError(message, nodeOrFragment, cause);
|
|
4354
3982
|
}
|
|
3983
|
+
/**
|
|
3984
|
+
* @param {string} message
|
|
3985
|
+
* @param {Node} nodeOrFragment the node that failed
|
|
3986
|
+
* @param {any} cause
|
|
3987
|
+
*/
|
|
4355
3988
|
constructor(message, nodeOrFragment, cause) {
|
|
4356
3989
|
super(`${message} in \`${RenderError.describe(nodeOrFragment)}\``, { cause });
|
|
4357
3990
|
this.name = 'RenderError';
|
|
4358
3991
|
this.#node = nodeOrFragment;
|
|
4359
3992
|
this.#depth = (cause instanceof RenderError ? cause.depth : 0) + 1;
|
|
4360
3993
|
}
|
|
4361
|
-
/**
|
|
3994
|
+
/**
|
|
3995
|
+
* How many frames this chain carries, this one included.
|
|
3996
|
+
* @returns {number}
|
|
3997
|
+
*/
|
|
4362
3998
|
get depth() {
|
|
4363
3999
|
return this.#depth;
|
|
4364
4000
|
}
|
|
4365
|
-
/**
|
|
4001
|
+
/**
|
|
4002
|
+
* The node the render failed on, live in the fragment being built.
|
|
4003
|
+
* @returns {Node}
|
|
4004
|
+
*/
|
|
4366
4005
|
get node() {
|
|
4367
4006
|
return this.#node;
|
|
4368
4007
|
}
|
|
4369
|
-
/**
|
|
4008
|
+
/**
|
|
4009
|
+
* The failed node's markup, whitespace trimmed, serialized on each read.
|
|
4010
|
+
* @returns {string}
|
|
4011
|
+
*/
|
|
4370
4012
|
get html() {
|
|
4371
4013
|
return RenderError.stringify(this.#node);
|
|
4372
4014
|
}
|
|
4373
4015
|
/**
|
|
4374
4016
|
* What identifies a node in a frame: an element by its open tag, a text node
|
|
4375
|
-
* by its source, a fragment by the open tags of the elements it holds
|
|
4017
|
+
* by its source, a fragment by the open tags of the elements it holds, cut
|
|
4018
|
+
* at 120 characters.
|
|
4019
|
+
* @param {Node} nodeOrFragment
|
|
4020
|
+
* @returns {string}
|
|
4376
4021
|
*/
|
|
4377
4022
|
static describe(nodeOrFragment) {
|
|
4378
4023
|
if (nodeOrFragment.nodeType === Node.TEXT_NODE) {
|
|
@@ -4391,10 +4036,13 @@ var ftl = (function (exports) {
|
|
|
4391
4036
|
static #ellipsize(text) {
|
|
4392
4037
|
return text.length > 120 ? `${text.slice(0, 120)}…` : text;
|
|
4393
4038
|
}
|
|
4039
|
+
/**
|
|
4040
|
+
* A node's markup with its whitespace-only text dropped and the rest trimmed.
|
|
4041
|
+
* @param {Node} nodeOrFragment left untouched: a clone is serialized
|
|
4042
|
+
* @returns {string}
|
|
4043
|
+
*/
|
|
4394
4044
|
static stringify(nodeOrFragment) {
|
|
4395
|
-
|
|
4396
|
-
t.content.appendChild(RenderError.#cleanup(nodeOrFragment.cloneNode(true)));
|
|
4397
|
-
return t.innerHTML;
|
|
4045
|
+
return Fragments.toHtml(RenderError.#cleanup(nodeOrFragment.cloneNode(true)));
|
|
4398
4046
|
}
|
|
4399
4047
|
static #cleanup(node) {
|
|
4400
4048
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
@@ -4416,31 +4064,28 @@ var ftl = (function (exports) {
|
|
|
4416
4064
|
}
|
|
4417
4065
|
}
|
|
4418
4066
|
|
|
4419
|
-
/**
|
|
4420
|
-
* Tracks the elements waiting to render. `ready` resolves once the queue has
|
|
4421
|
-
* drained and never rejects; the promise kept per element resolves when that
|
|
4422
|
-
* element has rendered and rejects with whatever its upgrade threw.
|
|
4423
|
-
*/
|
|
4424
4067
|
class UpgradeQueue {
|
|
4425
4068
|
#q = new Map();
|
|
4426
4069
|
#readyResolve;
|
|
4427
4070
|
#ready = new Promise((resolve) => {
|
|
4428
4071
|
this.#readyResolve = resolve;
|
|
4429
4072
|
});
|
|
4073
|
+
#configured = /** @type {PromiseWithResolvers<void>} */ (Promise.withResolvers());
|
|
4430
4074
|
constructor() {
|
|
4431
|
-
Nodes.waitDomContentLoaded(document).then(() => {
|
|
4075
|
+
Promise.all([Nodes.waitDomContentLoaded(document), this.#configured.promise]).then(() => {
|
|
4432
4076
|
this.#start();
|
|
4433
4077
|
});
|
|
4434
4078
|
}
|
|
4435
|
-
/**
|
|
4436
|
-
* Waits for the page's readiness: the promise resolves right after the
|
|
4437
|
-
* ftl:ready event is dispatched, and immediately when that moment already
|
|
4438
|
-
* passed.
|
|
4439
|
-
* @returns {Promise<void>}
|
|
4440
|
-
*/
|
|
4441
4079
|
ready() {
|
|
4442
4080
|
return this.#ready;
|
|
4443
4081
|
}
|
|
4082
|
+
/**
|
|
4083
|
+
* Marks the registry as configured: until then nothing is defined, so an
|
|
4084
|
+
* empty queue says nothing about the page and readiness is held back.
|
|
4085
|
+
*/
|
|
4086
|
+
configured() {
|
|
4087
|
+
this.#configured.resolve();
|
|
4088
|
+
}
|
|
4444
4089
|
async #start() {
|
|
4445
4090
|
await this.settled();
|
|
4446
4091
|
document.dispatchEvent(
|
|
@@ -4453,13 +4098,8 @@ var ftl = (function (exports) {
|
|
|
4453
4098
|
}
|
|
4454
4099
|
enqueue(el) {
|
|
4455
4100
|
if (this.#q.has(el)) {
|
|
4456
|
-
//already upgrading, can happen when disconnecting an element
|
|
4457
|
-
//while it's already queued for upgrade (e.g.: ful-form)
|
|
4458
4101
|
return;
|
|
4459
4102
|
}
|
|
4460
|
-
//one entry, two signals: readiness waits on a signal that only ever
|
|
4461
|
-
//resolves, so nothing here attaches a rejection handler to the upgrade
|
|
4462
|
-
//itself and a component that fails is still reported the way it always was
|
|
4463
4103
|
const { promise: finished, resolve: markFinished } = /** @type {PromiseWithResolvers<void>} */ (
|
|
4464
4104
|
Promise.withResolvers()
|
|
4465
4105
|
);
|
|
@@ -4471,11 +4111,6 @@ var ftl = (function (exports) {
|
|
|
4471
4111
|
});
|
|
4472
4112
|
this.#q.set(el, { upgrade, finished });
|
|
4473
4113
|
}
|
|
4474
|
-
/**
|
|
4475
|
-
* The one fixed-point loop: drains the accepted entries, including the ones
|
|
4476
|
-
* enqueued while waiting, since a component is only queued once its parent
|
|
4477
|
-
* connects it and a single pass would miss everything nested.
|
|
4478
|
-
*/
|
|
4479
4114
|
async #drain(accept, pick) {
|
|
4480
4115
|
for (;;) {
|
|
4481
4116
|
const pending = Array.from(this.#q)
|
|
@@ -4488,22 +4123,28 @@ var ftl = (function (exports) {
|
|
|
4488
4123
|
}
|
|
4489
4124
|
}
|
|
4490
4125
|
/**
|
|
4491
|
-
* Waits for the whole queue to drain
|
|
4492
|
-
*
|
|
4493
|
-
*
|
|
4126
|
+
* Waits for the whole queue to drain, the upgrades enqueued meanwhile included.
|
|
4127
|
+
* Never rejects: a failed upgrade counts as drained.
|
|
4128
|
+
* @returns {Promise<void>}
|
|
4494
4129
|
*/
|
|
4495
4130
|
settled() {
|
|
4496
|
-
return this.#drain(
|
|
4131
|
+
return this.#drain(
|
|
4132
|
+
() => true,
|
|
4133
|
+
(entry) => entry.finished,
|
|
4134
|
+
);
|
|
4497
4135
|
}
|
|
4498
|
-
/**
|
|
4136
|
+
/**
|
|
4137
|
+
* Waits for the accepted upgrades, the ones enqueued meanwhile included,
|
|
4138
|
+
* rejecting with the first that failed.
|
|
4139
|
+
* @param {(el: Element) => boolean} accept
|
|
4140
|
+
* @returns {Promise<void>}
|
|
4141
|
+
*/
|
|
4499
4142
|
upgraded(accept) {
|
|
4500
4143
|
return this.#drain(accept, (entry) => entry.upgrade);
|
|
4501
4144
|
}
|
|
4502
|
-
/** The pending upgrade of one element, undefined when it is not queued. */
|
|
4503
4145
|
whenUpgraded(el) {
|
|
4504
4146
|
return this.#q.get(el)?.upgrade;
|
|
4505
4147
|
}
|
|
4506
|
-
/** The elements whose upgrade is still pending, in queue order. */
|
|
4507
4148
|
pending() {
|
|
4508
4149
|
return Array.from(this.#q.keys());
|
|
4509
4150
|
}
|
|
@@ -4514,8 +4155,8 @@ var ftl = (function (exports) {
|
|
|
4514
4155
|
* and attribute mappers. Elements defined before configure() are deferred and
|
|
4515
4156
|
* defined by it; from then on every defineElement takes effect immediately.
|
|
4516
4157
|
* The exported `registry` singleton is the page's own; a `new Registry()` is a
|
|
4517
|
-
* separate instance
|
|
4518
|
-
* singleton alone.
|
|
4158
|
+
* separate instance with its own upgrade queue, which dispatches its own
|
|
4159
|
+
* ftl:ready on the document, while Rendering waits on the singleton alone.
|
|
4519
4160
|
*/
|
|
4520
4161
|
class Registry {
|
|
4521
4162
|
#tagToClass = {};
|
|
@@ -4584,9 +4225,12 @@ var ftl = (function (exports) {
|
|
|
4584
4225
|
* Registers a custom element under its tag: the class is augmented with its
|
|
4585
4226
|
* BITS (observed attributes, mappers, templates) and handed to the platform.
|
|
4586
4227
|
* Before configure() the definition is deferred, so import order never
|
|
4587
|
-
* matters.
|
|
4228
|
+
* matters. The element resolves its templates and components through this
|
|
4229
|
+
* registry, whichever one a module imports, and its `static config` is read
|
|
4230
|
+
* here, so a page replacing it does so before the definition.
|
|
4588
4231
|
* @param {string} tag
|
|
4589
4232
|
* @param {*} klass a ParsedElement subclass
|
|
4233
|
+
* @returns {Registry} this registry
|
|
4590
4234
|
*/
|
|
4591
4235
|
defineElement(tag, klass) {
|
|
4592
4236
|
if (!this.#configured) {
|
|
@@ -4604,13 +4248,8 @@ var ftl = (function (exports) {
|
|
|
4604
4248
|
* ancestors', so a base class declares what every subclass keeps observing
|
|
4605
4249
|
* (a protocol attribute such as Field's disabled claim) and a leaf refines a
|
|
4606
4250
|
* mapping, or moves a name's position, without repeating the whole list.
|
|
4607
|
-
*
|
|
4608
|
-
*
|
|
4609
|
-
* stop can work, since a registered ancestor carries an own BITS of its own,
|
|
4610
|
-
* and nothing above the elements declares anything.
|
|
4611
|
-
*
|
|
4612
|
-
* Everything deriving a component's attribute vocabulary reads it here, so
|
|
4613
|
-
* the runtime and whatever documents it cannot walk the chain differently.
|
|
4251
|
+
* The observed attributes are applied in the composed order, a re-declared
|
|
4252
|
+
* name taking the position of its last declaration.
|
|
4614
4253
|
* @param {*} klass a ParsedElement subclass
|
|
4615
4254
|
* @returns {{ observed: string[], attributes: string[] }}
|
|
4616
4255
|
*/
|
|
@@ -4626,14 +4265,7 @@ var ftl = (function (exports) {
|
|
|
4626
4265
|
* The property an observed attribute drives, by the platform's own
|
|
4627
4266
|
* dash-to-camel rule: the one `dataset` applies, so `clear-invalid-on-change`
|
|
4628
4267
|
* would reach `clearInvalidOnChange` the way `data-clear-invalid-on-change`
|
|
4629
|
-
* reaches `dataset.clearInvalidOnChange`.
|
|
4630
|
-
* unchanged, which is what every observed attribute in the library is.
|
|
4631
|
-
*
|
|
4632
|
-
* It exists because the observed tier is the one that becomes properties:
|
|
4633
|
-
* without it an attribute could only be observed if its name happened to be
|
|
4634
|
-
* a usable identifier, which is why every multiword observed attribute here
|
|
4635
|
-
* used to be squashed into one word while the configuration tier, which
|
|
4636
|
-
* never becomes a property, spelled the same idea with a dash.
|
|
4268
|
+
* reaches `dataset.clearInvalidOnChange`.
|
|
4637
4269
|
*
|
|
4638
4270
|
* Only this direction is mapped. A property never derives its attribute: a
|
|
4639
4271
|
* setter reflects through `reflectTo`, naming the attribute it writes.
|
|
@@ -4646,10 +4278,6 @@ var ftl = (function (exports) {
|
|
|
4646
4278
|
#augmentAndDefineElement(tag, klass) {
|
|
4647
4279
|
const { observed, attributes } = Registry.declarationsOf(klass);
|
|
4648
4280
|
const { template, templates, slots, mappers, config } = klass;
|
|
4649
|
-
//a name a subclass re-declares takes the subclass's position, which is
|
|
4650
|
-
//how a field whose value setter reads its own shape attributes declares
|
|
4651
|
-
//that its value lands after them: the order the declarations compose in
|
|
4652
|
-
//is the order the base applies them
|
|
4653
4281
|
const declaredNames = observed.map((a) => a.split(':')[0]);
|
|
4654
4282
|
const observedNames = [...new Set(declaredNames.reverse())].reverse();
|
|
4655
4283
|
const attrToMapper = [...attributes, ...observed].reduce((acc, a) => {
|
|
@@ -4668,20 +4296,13 @@ var ftl = (function (exports) {
|
|
|
4668
4296
|
const nameToTemplate = Object.fromEntries(namesAndTemplates);
|
|
4669
4297
|
|
|
4670
4298
|
klass.BITS = {
|
|
4671
|
-
//the defining registry travels with the definition: an element resolves
|
|
4672
|
-
//its templates and its components through the registry that defined it,
|
|
4673
|
-
//not through whichever one a module happened to import
|
|
4674
4299
|
registry: this,
|
|
4675
4300
|
enqueue: (el) => this.#upgradeQueue.enqueue(el),
|
|
4676
4301
|
SLOTS: slots,
|
|
4677
|
-
//the class's own constants, overlaid on its templates as `config`:
|
|
4678
|
-
//read here with the rest of the declaration, so a page replacing them
|
|
4679
|
-
//does it before configure() like every other definition-time choice
|
|
4680
4302
|
CONFIG: config,
|
|
4681
4303
|
OBSERVED: observedNames,
|
|
4682
4304
|
DECLARED: [...new Set([...observedNames, ...attributes.map((a) => a.split(':')[0])])],
|
|
4683
4305
|
ATTR_TO_MAPPER: attrToMapper,
|
|
4684
|
-
//resolved once here rather than at every attribute write
|
|
4685
4306
|
ATTR_TO_PROPERTY: Object.fromEntries(observedNames.map((a) => [a, Registry.propertyOf(a)])),
|
|
4686
4307
|
TEMPLATES: nameToTemplate,
|
|
4687
4308
|
};
|
|
@@ -4693,6 +4314,7 @@ var ftl = (function (exports) {
|
|
|
4693
4314
|
* as `#fn`.
|
|
4694
4315
|
* @param {string} name
|
|
4695
4316
|
* @param {object} value
|
|
4317
|
+
* @returns {Registry} this registry
|
|
4696
4318
|
*/
|
|
4697
4319
|
defineModule(name, value) {
|
|
4698
4320
|
const module = name ? { [name]: value } : value;
|
|
@@ -4703,6 +4325,7 @@ var ftl = (function (exports) {
|
|
|
4703
4325
|
/**
|
|
4704
4326
|
* Replaces the whole module map.
|
|
4705
4327
|
* @param {object} ms
|
|
4328
|
+
* @returns {Registry} this registry
|
|
4706
4329
|
*/
|
|
4707
4330
|
defineModules(ms) {
|
|
4708
4331
|
this.#modules = ms;
|
|
@@ -4714,6 +4337,7 @@ var ftl = (function (exports) {
|
|
|
4714
4337
|
* through component().
|
|
4715
4338
|
* @param {string} name
|
|
4716
4339
|
* @param {*} value
|
|
4340
|
+
* @returns {Registry} this registry
|
|
4717
4341
|
*/
|
|
4718
4342
|
defineComponent(name, value) {
|
|
4719
4343
|
this.#components[name] = value;
|
|
@@ -4722,6 +4346,7 @@ var ftl = (function (exports) {
|
|
|
4722
4346
|
/**
|
|
4723
4347
|
* Replaces the data stack the templates evaluate over.
|
|
4724
4348
|
* @param {...any} data
|
|
4349
|
+
* @returns {Registry} this registry
|
|
4725
4350
|
*/
|
|
4726
4351
|
defineData(...data) {
|
|
4727
4352
|
this.#data = data;
|
|
@@ -4731,6 +4356,7 @@ var ftl = (function (exports) {
|
|
|
4731
4356
|
/**
|
|
4732
4357
|
* Appends to the data stack, the later entry winning a shared name.
|
|
4733
4358
|
* @param {...any} data
|
|
4359
|
+
* @returns {Registry} this registry
|
|
4734
4360
|
*/
|
|
4735
4361
|
defineOverlay(...data) {
|
|
4736
4362
|
this.#data = [...this.#data, ...data];
|
|
@@ -4742,6 +4368,7 @@ var ftl = (function (exports) {
|
|
|
4742
4368
|
* `name:type` declaration.
|
|
4743
4369
|
* @param {string} k
|
|
4744
4370
|
* @param {{ unmarshal(str: string|null, name: string, el: Element): any, marshal(value: any, name: string, el: Element): string|null }} v
|
|
4371
|
+
* @returns {Registry} this registry
|
|
4745
4372
|
*/
|
|
4746
4373
|
defineMapper(k, v) {
|
|
4747
4374
|
this.#mappers[k] = v;
|
|
@@ -4750,6 +4377,7 @@ var ftl = (function (exports) {
|
|
|
4750
4377
|
/**
|
|
4751
4378
|
* Hands the registry over to the plugin's configure.
|
|
4752
4379
|
* @param {{ configure(registry: Registry): void }} p
|
|
4380
|
+
* @returns {Registry} this registry
|
|
4753
4381
|
*/
|
|
4754
4382
|
plugin(p) {
|
|
4755
4383
|
p.configure(this);
|
|
@@ -4757,7 +4385,10 @@ var ftl = (function (exports) {
|
|
|
4757
4385
|
}
|
|
4758
4386
|
/**
|
|
4759
4387
|
* Defines every element deferred so far; from then on, defineElement takes
|
|
4760
|
-
* effect immediately.
|
|
4388
|
+
* effect immediately. Readiness waits for the first call: a page that
|
|
4389
|
+
* configures late (translations fetched first) gets its ftl:ready once the
|
|
4390
|
+
* elements this defines have upgraded, not at DOMContentLoaded.
|
|
4391
|
+
* @returns {Registry} this registry
|
|
4761
4392
|
*/
|
|
4762
4393
|
configure() {
|
|
4763
4394
|
for (const [tag, klass] of Object.entries(this.#tagToClass)) {
|
|
@@ -4765,27 +4396,43 @@ var ftl = (function (exports) {
|
|
|
4765
4396
|
delete this.#tagToClass[tag];
|
|
4766
4397
|
}
|
|
4767
4398
|
this.#configured = true;
|
|
4399
|
+
this.#upgradeQueue.configured();
|
|
4768
4400
|
return this;
|
|
4769
4401
|
}
|
|
4770
4402
|
/**
|
|
4771
4403
|
* Waits for the queued upgrades the filter accepts, rejecting with the first
|
|
4772
|
-
* that failed
|
|
4404
|
+
* that failed, the upgrades enqueued meanwhile included: the rejecting
|
|
4405
|
+
* barrier Rendering is a facade over.
|
|
4773
4406
|
* @param {(el: Element) => boolean} accept
|
|
4407
|
+
* @returns {Promise<void>}
|
|
4774
4408
|
*/
|
|
4775
4409
|
settle(accept) {
|
|
4776
4410
|
return this.#upgradeQueue.upgraded(accept);
|
|
4777
4411
|
}
|
|
4778
|
-
/**
|
|
4412
|
+
/**
|
|
4413
|
+
* The pending upgrade of one element: resolving when it has rendered,
|
|
4414
|
+
* rejecting with what its upgrade threw.
|
|
4415
|
+
* @param {Element} el
|
|
4416
|
+
* @returns {Promise<void>|undefined} undefined when the element is not queued
|
|
4417
|
+
*/
|
|
4779
4418
|
whenUpgraded(el) {
|
|
4780
4419
|
return this.#upgradeQueue.whenUpgraded(el);
|
|
4781
4420
|
}
|
|
4782
|
-
/**
|
|
4421
|
+
/**
|
|
4422
|
+
* The elements whose upgrade is still pending, in queue order.
|
|
4423
|
+
* @returns {Element[]}
|
|
4424
|
+
*/
|
|
4783
4425
|
pending() {
|
|
4784
4426
|
return this.#upgradeQueue.pending();
|
|
4785
4427
|
}
|
|
4786
4428
|
/**
|
|
4787
|
-
* Waits for
|
|
4788
|
-
* dispatched
|
|
4429
|
+
* Waits for this registry's readiness: resolves right after its ftl:ready
|
|
4430
|
+
* event is dispatched on the document, and immediately when that already
|
|
4431
|
+
* happened. The event is dispatched once DOMContentLoaded has passed,
|
|
4432
|
+
* configure() has been called and the queue has drained, so a registry
|
|
4433
|
+
* that is never configured is never ready. Never rejects: a failed
|
|
4434
|
+
* upgrade counts as settled, and its rejection is left unhandled so it
|
|
4435
|
+
* still reaches the console and the page's error reporting.
|
|
4789
4436
|
* @returns {Promise<void>}
|
|
4790
4437
|
*/
|
|
4791
4438
|
ready() {
|
|
@@ -4798,11 +4445,16 @@ var ftl = (function (exports) {
|
|
|
4798
4445
|
* The scope every template on this registry renders in: the modules and the
|
|
4799
4446
|
* data stack, as one value. Replaced whenever either is defined, so a holder
|
|
4800
4447
|
* of an older one keeps rendering against what it was handed.
|
|
4448
|
+
* @returns {ExpressionEvaluator}
|
|
4801
4449
|
*/
|
|
4802
4450
|
evaluator() {
|
|
4803
4451
|
return this.#evaluator;
|
|
4804
4452
|
}
|
|
4805
|
-
/**
|
|
4453
|
+
/**
|
|
4454
|
+
* The component registered under the name.
|
|
4455
|
+
* @param {string} name
|
|
4456
|
+
* @returns {any} undefined when none is
|
|
4457
|
+
*/
|
|
4806
4458
|
component(name) {
|
|
4807
4459
|
return this.#components[name];
|
|
4808
4460
|
}
|
|
@@ -4810,33 +4462,59 @@ var ftl = (function (exports) {
|
|
|
4810
4462
|
|
|
4811
4463
|
const registry = new Registry();
|
|
4812
4464
|
|
|
4813
|
-
/** The Template factories, each bound to the page registry's scope. */
|
|
4814
4465
|
/** The Template factories bound to the page's own registry: the same four sources, with its modules and data already applied. */
|
|
4815
4466
|
class Templates {
|
|
4467
|
+
/**
|
|
4468
|
+
* @param {string} html
|
|
4469
|
+
* @returns {Template}
|
|
4470
|
+
*/
|
|
4816
4471
|
static fromHtml(html) {
|
|
4817
4472
|
return Template.fromHtml(html).withEvaluator(registry.evaluator());
|
|
4818
4473
|
}
|
|
4474
|
+
/**
|
|
4475
|
+
* @param {string} selector for an HTMLTemplateElement
|
|
4476
|
+
* @returns {Template}
|
|
4477
|
+
*/
|
|
4819
4478
|
static fromSelector(selector) {
|
|
4820
4479
|
return Template.fromSelector(selector).withEvaluator(registry.evaluator());
|
|
4821
4480
|
}
|
|
4481
|
+
/**
|
|
4482
|
+
* @param {HTMLTemplateElement} templateEl consumed: its content is adopted
|
|
4483
|
+
* @returns {Template}
|
|
4484
|
+
*/
|
|
4822
4485
|
static fromTemplate(templateEl) {
|
|
4823
4486
|
return Template.fromTemplate(templateEl).withEvaluator(registry.evaluator());
|
|
4824
4487
|
}
|
|
4488
|
+
/**
|
|
4489
|
+
* @param {DocumentFragment} fragment
|
|
4490
|
+
* @returns {Template}
|
|
4491
|
+
*/
|
|
4825
4492
|
static fromFragment(fragment) {
|
|
4826
4493
|
return Template.fromFragment(fragment).withEvaluator(registry.evaluator());
|
|
4827
4494
|
}
|
|
4828
4495
|
}
|
|
4829
4496
|
|
|
4830
4497
|
/**
|
|
4831
|
-
*
|
|
4832
|
-
*
|
|
4833
|
-
*
|
|
4834
|
-
* leaves a failed component to its own unhandled-rejection report.
|
|
4498
|
+
* Waits for elements queued on the page's `registry` to render. Unlike
|
|
4499
|
+
* `registry.ready()`, these reject when an awaited upgrade fails. An element
|
|
4500
|
+
* defined by another Registry is awaited through that registry instead.
|
|
4835
4501
|
*/
|
|
4836
4502
|
class Rendering {
|
|
4503
|
+
/**
|
|
4504
|
+
* Waits for the element and its descendants, the ones their own renders
|
|
4505
|
+
* enqueue included.
|
|
4506
|
+
* @param {Element} el
|
|
4507
|
+
* @returns {Promise<void>} rejecting with the first upgrade that failed
|
|
4508
|
+
*/
|
|
4837
4509
|
static waitFor(el) {
|
|
4838
4510
|
return registry.settle((child) => el.contains(child));
|
|
4839
4511
|
}
|
|
4512
|
+
/**
|
|
4513
|
+
* Waits for the element's descendants, the element itself excluded: what a
|
|
4514
|
+
* component awaits from inside its own render.
|
|
4515
|
+
* @param {Element} el
|
|
4516
|
+
* @returns {Promise<void>} rejecting with the first upgrade that failed
|
|
4517
|
+
*/
|
|
4840
4518
|
static waitForChildren(el) {
|
|
4841
4519
|
return registry.settle((child) => el !== child && el.contains(child));
|
|
4842
4520
|
}
|
|
@@ -4850,9 +4528,15 @@ var ftl = (function (exports) {
|
|
|
4850
4528
|
* @property {(val: any, name: string, el: Element) => string|null} marshal
|
|
4851
4529
|
*/
|
|
4852
4530
|
|
|
4531
|
+
/**
|
|
4532
|
+
* The base of every fml element. A subclass declares its attributes, slots and
|
|
4533
|
+
* templates in statics and builds its dom in `render`; the base reads the light
|
|
4534
|
+
* slots, reads the declared attributes through their mappers, renders once, and
|
|
4535
|
+
* then forwards observed attribute writes to the matching properties. An element
|
|
4536
|
+
* resolves templates and components through the registry that defined it.
|
|
4537
|
+
*/
|
|
4853
4538
|
class ParsedElement extends HTMLElement {
|
|
4854
4539
|
static BITS = {
|
|
4855
|
-
//an element the registry never defined still answers the page's own
|
|
4856
4540
|
registry,
|
|
4857
4541
|
enqueue: (el) => {},
|
|
4858
4542
|
SLOTS: false,
|
|
@@ -4876,14 +4560,12 @@ var ftl = (function (exports) {
|
|
|
4876
4560
|
this.internals = this.attachInternals();
|
|
4877
4561
|
}
|
|
4878
4562
|
/**
|
|
4879
|
-
* The
|
|
4880
|
-
*
|
|
4881
|
-
*
|
|
4882
|
-
*
|
|
4883
|
-
*
|
|
4884
|
-
*
|
|
4885
|
-
* A subclass must not redeclare it: a class field with no initializer
|
|
4886
|
-
* assigns undefined after super() returns, which would wipe it.
|
|
4563
|
+
* The element's ElementInternals, attached by the base for every element: a
|
|
4564
|
+
* subclass never calls attachInternals itself, since a second call throws.
|
|
4565
|
+
* A subclass declaring `static formAssociated` gets the form apis here.
|
|
4566
|
+
* A subclass must not redeclare the field: a class field without an
|
|
4567
|
+
* initializer assigns undefined after super() returns, wiping it.
|
|
4568
|
+
* @type {ElementInternals}
|
|
4887
4569
|
*/
|
|
4888
4570
|
internals;
|
|
4889
4571
|
#parsed = false;
|
|
@@ -4900,26 +4582,36 @@ var ftl = (function (exports) {
|
|
|
4900
4582
|
#mapper(attr) {
|
|
4901
4583
|
const mapper = this.#bits().ATTR_TO_MAPPER[attr];
|
|
4902
4584
|
if (!mapper) {
|
|
4903
|
-
//an attribute the class never declared has no type to read it as:
|
|
4904
|
-
//say so rather than dying on the missing mapper. Content this
|
|
4905
|
-
//element does not own, such as a custom loader's own configuration,
|
|
4906
|
-
//is read with getAttribute, the platform's own answer
|
|
4907
4585
|
throw new Error(
|
|
4908
4586
|
`${this.constructor.name} declares no attribute '${attr}': declare it in static observed or static attributes, or read it with getAttribute`,
|
|
4909
4587
|
);
|
|
4910
4588
|
}
|
|
4911
4589
|
return mapper;
|
|
4912
4590
|
}
|
|
4591
|
+
/**
|
|
4592
|
+
* Reads an attribute value through the mapper it was declared with.
|
|
4593
|
+
* @param {string} attr
|
|
4594
|
+
* @param {string|null} str
|
|
4595
|
+
* @returns {any}
|
|
4596
|
+
* @throws when the class declares no such attribute; read undeclared ones with getAttribute
|
|
4597
|
+
*/
|
|
4913
4598
|
unmarshal(attr, str) {
|
|
4914
4599
|
return this.#mapper(attr).unmarshal(str, attr, this);
|
|
4915
4600
|
}
|
|
4601
|
+
/**
|
|
4602
|
+
* Writes a value as the attribute string its declared mapper produces.
|
|
4603
|
+
* @param {string} attr
|
|
4604
|
+
* @param {any} value
|
|
4605
|
+
* @returns {string|null} null for a value that removes the attribute
|
|
4606
|
+
* @throws when the class declares no such attribute
|
|
4607
|
+
*/
|
|
4916
4608
|
marshal(attr, value) {
|
|
4917
4609
|
return this.#mapper(attr).marshal(value, attr, this);
|
|
4918
4610
|
}
|
|
4919
4611
|
/**
|
|
4920
|
-
*
|
|
4612
|
+
* The registry that defined this element, the page's own for an undefined one.
|
|
4613
|
+
* @returns {typeof registry}
|
|
4921
4614
|
*/
|
|
4922
|
-
/** The registry that defined this element, the page's own for an undefined one. */
|
|
4923
4615
|
get _registry() {
|
|
4924
4616
|
return this.#bits().registry;
|
|
4925
4617
|
}
|
|
@@ -4927,10 +4619,18 @@ var ftl = (function (exports) {
|
|
|
4927
4619
|
* The component registered under the name on this element's registry, the
|
|
4928
4620
|
* one every ful loader and mapper resolves through.
|
|
4929
4621
|
* @param {string} name
|
|
4622
|
+
* @returns {any} undefined when none is registered
|
|
4930
4623
|
*/
|
|
4931
4624
|
component(name) {
|
|
4932
4625
|
return this.#bits().registry.component(name);
|
|
4933
4626
|
}
|
|
4627
|
+
/**
|
|
4628
|
+
* One of the class's templates, bound to its registry's scope with the
|
|
4629
|
+
* class's `static config` overlaid as `config`.
|
|
4630
|
+
* @param {string} [name] 'default', the `static template`, when omitted
|
|
4631
|
+
* @returns {Template}
|
|
4632
|
+
* @throws when the class declares no template of that name
|
|
4633
|
+
*/
|
|
4934
4634
|
template(name) {
|
|
4935
4635
|
const target = this.#bits().TEMPLATES[name ?? 'default'];
|
|
4936
4636
|
if (!target) {
|
|
@@ -4950,15 +4650,9 @@ var ftl = (function (exports) {
|
|
|
4950
4650
|
if (oldValue === newValue) {
|
|
4951
4651
|
return;
|
|
4952
4652
|
}
|
|
4953
|
-
//the mute is the attribute being reflected, not the element: a component
|
|
4954
|
-
//that legitimately changes another observed attribute while one reflects
|
|
4955
|
-
//is a change like any other, and used to be swallowed
|
|
4956
4653
|
if (this.#reflecting.has(attr)) {
|
|
4957
4654
|
return;
|
|
4958
4655
|
}
|
|
4959
|
-
//the properties go live only once the render is done: before that, an
|
|
4960
|
-
//attribute write lands in the observed snapshot and the base applies it
|
|
4961
|
-
//with the rest of the declared state
|
|
4962
4656
|
if (!this.#parsed) {
|
|
4963
4657
|
if (this.#pending !== null && attr in this.#pending) {
|
|
4964
4658
|
this.#pending[attr] = this.unmarshal(attr, newValue);
|
|
@@ -4968,14 +4662,18 @@ var ftl = (function (exports) {
|
|
|
4968
4662
|
this[this.#bits().ATTR_TO_PROPERTY[attr]] = this.unmarshal(attr, newValue);
|
|
4969
4663
|
}
|
|
4970
4664
|
/**
|
|
4971
|
-
* Upgrades once
|
|
4972
|
-
* to writes made while the render is
|
|
4973
|
-
*
|
|
4665
|
+
* Upgrades once, however often the element is connected: reads the declared
|
|
4666
|
+
* attributes, keeps the observed ones open to writes made while the render is
|
|
4667
|
+
* pending, renders, then applies the observed values to their properties in
|
|
4668
|
+
* the order the registry composed them, a base class's before a subclass's.
|
|
4669
|
+
* Only then do attribute writes forward to properties, and the element gains
|
|
4670
|
+
* the `rendered` custom state. A render that throws leaves the forwarding
|
|
4671
|
+
* shut and the state unset.
|
|
4974
4672
|
*
|
|
4975
4673
|
* An observed attribute drives the property the registry's `propertyOf`
|
|
4976
4674
|
* names, so a hyphenated attribute is authored with its dashes and read as
|
|
4977
|
-
* a camelCase property.
|
|
4978
|
-
*
|
|
4675
|
+
* a camelCase property.
|
|
4676
|
+
* @returns {Promise<void>} rejecting with what the render threw
|
|
4979
4677
|
*/
|
|
4980
4678
|
async upgrade() {
|
|
4981
4679
|
if (this.#started) {
|
|
@@ -4983,9 +4681,6 @@ var ftl = (function (exports) {
|
|
|
4983
4681
|
}
|
|
4984
4682
|
this.#started = true;
|
|
4985
4683
|
const slots = this.#bits().SLOTS ? LightSlots.from(this) : undefined;
|
|
4986
|
-
//both tiers are read here: the observed ones forward to a property once
|
|
4987
|
-
//the render is done, the rest are the element's configuration, read the
|
|
4988
|
-
//one time and never again
|
|
4989
4684
|
const declared = Object.fromEntries(
|
|
4990
4685
|
this.#bits().DECLARED.map((attribute) => [
|
|
4991
4686
|
attribute,
|
|
@@ -4997,21 +4692,11 @@ var ftl = (function (exports) {
|
|
|
4997
4692
|
this.#pending = declared;
|
|
4998
4693
|
try {
|
|
4999
4694
|
await this.render({ slots });
|
|
5000
|
-
//the declared state reaches the properties once the dom the setters
|
|
5001
|
-
//drive exists, in the order the registry composed the declarations:
|
|
5002
|
-
//a base class's attributes before the subclass's own
|
|
5003
4695
|
const properties = this.#bits().ATTR_TO_PROPERTY;
|
|
5004
4696
|
for (const name of this.#bits().OBSERVED) {
|
|
5005
4697
|
this[properties[name]] = declared[name];
|
|
5006
4698
|
}
|
|
5007
|
-
//the properties go live once the render is done: from here on, an
|
|
5008
|
-
//attribute write forwards to the property. A render that threw
|
|
5009
|
-
//leaves it shut, so a later attribute write cannot reach setters
|
|
5010
|
-
//that assume pieces the failed render never adopted
|
|
5011
4699
|
this.#parsed = true;
|
|
5012
|
-
//the same moment, said to css. :defined is true from the constructor,
|
|
5013
|
-
//which is before the dom exists, so a guard written against it reveals
|
|
5014
|
-
//an element that has nothing in it yet
|
|
5015
4700
|
this.internals.states.add('rendered');
|
|
5016
4701
|
} finally {
|
|
5017
4702
|
this.#pending = null;
|
|
@@ -5022,8 +4707,9 @@ var ftl = (function (exports) {
|
|
|
5022
4707
|
* drive, and the base applies the declared state onto the properties as
|
|
5023
4708
|
* soon as it returns. A render needing a declared value while it builds
|
|
5024
4709
|
* reads it through `declared(name)`. The slots are undefined for an element
|
|
5025
|
-
* declaring no slots.
|
|
5026
|
-
* @param {{ slots:
|
|
4710
|
+
* declaring no slots. It may be async; the upgrade awaits it.
|
|
4711
|
+
* @param {{ slots: Record<string, DocumentFragment> | undefined }} c
|
|
4712
|
+
* @returns {void | Promise<void>}
|
|
5027
4713
|
*/
|
|
5028
4714
|
render(c) {}
|
|
5029
4715
|
/**
|
|
@@ -5035,12 +4721,9 @@ var ftl = (function (exports) {
|
|
|
5035
4721
|
* observed name answers the snapshot while the render is pending, kept
|
|
5036
4722
|
* open to attribute writes landing in that window, and the live attribute
|
|
5037
4723
|
* afterwards, the property being live by then.
|
|
5038
|
-
*
|
|
5039
|
-
* The snapshot exists rather than a read of the dom because an element may
|
|
5040
|
-
* write its own observed attributes while it renders, whether a reflection
|
|
5041
|
-
* or a value the platform normalizes on the way in, and what the author
|
|
5042
|
-
* declared is what the base applies, not what the render left behind.
|
|
5043
4724
|
* @param {string} name
|
|
4725
|
+
* @returns {any}
|
|
4726
|
+
* @throws when the class declares no such attribute
|
|
5044
4727
|
*/
|
|
5045
4728
|
declared(name) {
|
|
5046
4729
|
if (name in this.#frozen) {
|
|
@@ -5051,15 +4734,18 @@ var ftl = (function (exports) {
|
|
|
5051
4734
|
}
|
|
5052
4735
|
return this.unmarshal(name, this.getAttribute(name));
|
|
5053
4736
|
}
|
|
5054
|
-
/**
|
|
4737
|
+
/**
|
|
4738
|
+
* Whether the element's render completed: the moment its properties went
|
|
4739
|
+
* live, which css reads as `:state(rendered)`. Unlike `:defined`, which holds
|
|
4740
|
+
* from the constructor, it is false until the dom exists.
|
|
4741
|
+
* @returns {boolean}
|
|
4742
|
+
*/
|
|
5055
4743
|
get rendered() {
|
|
5056
4744
|
return this.#parsed;
|
|
5057
4745
|
}
|
|
5058
4746
|
/**
|
|
5059
4747
|
* Projects a property back onto its observed attribute, marshalled through
|
|
5060
|
-
* the mapper the attribute was declared with
|
|
5061
|
-
* reaches its attribute, so a setter never has to know how its own type
|
|
5062
|
-
* serializes.
|
|
4748
|
+
* the mapper the attribute was declared with.
|
|
5063
4749
|
*
|
|
5064
4750
|
* A value the attribute already carries is not written at all, so reflecting
|
|
5065
4751
|
* what an attribute write just delivered ends there rather than looping, and
|
|
@@ -5090,18 +4776,37 @@ var ftl = (function (exports) {
|
|
|
5090
4776
|
*/
|
|
5091
4777
|
|
|
5092
4778
|
/**
|
|
5093
|
-
* The receiver contract of the module functions:
|
|
5094
|
-
*
|
|
4779
|
+
* The receiver contract of the module functions: a plain object carrying the
|
|
4780
|
+
* translations and the locale, as Localization.of() binds them, or the proxy
|
|
4781
|
+
* over the data stack a template calls them with.
|
|
5095
4782
|
*
|
|
5096
4783
|
* @typedef {{ l10n?: Messages, locale?: string }} Receiver
|
|
5097
4784
|
*/
|
|
5098
4785
|
|
|
4786
|
+
/**
|
|
4787
|
+
* The translations or the locale of a receiver. From a template they are read
|
|
4788
|
+
* from the bound data alone (the registry's overlays, or the data handed to
|
|
4789
|
+
* the Template factory): the rows and responses a render pushes on top are
|
|
4790
|
+
* what arrives later, and must not supply or replace the page's own messages.
|
|
4791
|
+
* @param {any} receiver
|
|
4792
|
+
* @param {'l10n' | 'locale'} name
|
|
4793
|
+
* @returns {any}
|
|
4794
|
+
*/
|
|
4795
|
+
const configured = (receiver, name) => {
|
|
4796
|
+
const bound = receiver[Expressions.BOUND];
|
|
4797
|
+
return typeof bound === 'function' ? bound(name) : receiver[name];
|
|
4798
|
+
};
|
|
4799
|
+
|
|
5099
4800
|
const PLACEHOLDER = /\{(\w+)\}/g;
|
|
5100
4801
|
const POSITIONAL = /\{(\d+)\}/g;
|
|
5101
4802
|
/** @param {any} v @returns {v is Record<string, string>} */
|
|
5102
|
-
const isPlainObject = (v) =>
|
|
4803
|
+
const isPlainObject = (v) =>
|
|
4804
|
+
typeof v === 'object' && v !== null && [Object.prototype, null].includes(Object.getPrototypeOf(v));
|
|
4805
|
+
|
|
4806
|
+
/** @param {any} problem @returns {string|undefined} the reason, unless it is missing or blank */
|
|
4807
|
+
const reasonOf = (problem) =>
|
|
4808
|
+
typeof problem?.reason === 'string' && problem.reason.trim() !== '' ? problem.reason : undefined;
|
|
5103
4809
|
|
|
5104
|
-
/** every l10n problem is reported once per session: a missing key in a row template must not flood the console */
|
|
5105
4810
|
const warned = new Set();
|
|
5106
4811
|
const warnOnce = (problem) => {
|
|
5107
4812
|
if (!warned.has(problem)) {
|
|
@@ -5112,11 +4817,7 @@ var ftl = (function (exports) {
|
|
|
5112
4817
|
|
|
5113
4818
|
const formatters = new BoundedCache(100);
|
|
5114
4819
|
/**
|
|
5115
|
-
* Intl
|
|
5116
|
-
* lookups), while formatting on a built instance is near free: a list rendering
|
|
5117
|
-
* a size per row must not rebuild a NumberFormat per cell, so instances are
|
|
5118
|
-
* memoized by constructor, locale and options.
|
|
5119
|
-
*
|
|
4820
|
+
* An Intl instance, memoized by constructor, locale and options.
|
|
5120
4821
|
* @param {{ new (locale: string | undefined, options: any): any }} ctor
|
|
5121
4822
|
* @param {string | undefined} locale
|
|
5122
4823
|
* @param {any} [options]
|
|
@@ -5130,35 +4831,40 @@ var ftl = (function (exports) {
|
|
|
5130
4831
|
* The translations as a template module: `#l10n:t()` for messages, plus date,
|
|
5131
4832
|
* number and bytes formatting in the page's locale. The template form and the
|
|
5132
4833
|
* imperative `of()` facade both resolve through the registry's scope, so they
|
|
5133
|
-
* always produce the same result for the same key.
|
|
4834
|
+
* always produce the same result for the same key. A template reads `l10n`
|
|
4835
|
+
* and `locale` from its bound data only, the most recent layer winning: an
|
|
4836
|
+
* overlay pushed while rendering (a row, a response) never reaches them.
|
|
5134
4837
|
*/
|
|
5135
4838
|
class Localization {
|
|
5136
4839
|
/**
|
|
5137
4840
|
* Resolves a message from the translations and interpolates its arguments.
|
|
5138
|
-
* A single plain object argument
|
|
5139
|
-
* ({name}); anything else interpolates positional ones ({0}).
|
|
4841
|
+
* A single plain object argument (an object literal, or one with a null
|
|
4842
|
+
* prototype) interpolates named placeholders ({name}); anything else interpolates positional ones ({0}).
|
|
5140
4843
|
* A plural leaf selects its form through Intl.PluralRules over the
|
|
5141
4844
|
* numeric {count} named argument.
|
|
5142
4845
|
*
|
|
5143
4846
|
* @param {string} key
|
|
5144
4847
|
* @param {...any} args
|
|
4848
|
+
* Each problem (a missing key, placeholder or plural form) is warned once
|
|
4849
|
+
* per page.
|
|
4850
|
+
*
|
|
5145
4851
|
* @this {Receiver}
|
|
5146
4852
|
* @returns {string} the message, or the key itself when the translations do not carry it
|
|
5147
4853
|
*/
|
|
5148
4854
|
static t(key, ...args) {
|
|
5149
|
-
const messages = this
|
|
5150
|
-
let message = messages[key];
|
|
4855
|
+
const messages = configured(this, 'l10n') ?? {};
|
|
4856
|
+
let message = Object.hasOwn(messages, key) ? messages[key] : undefined;
|
|
5151
4857
|
if (message === undefined) {
|
|
5152
4858
|
warnOnce(`missing message "${key}"`);
|
|
5153
4859
|
return key;
|
|
5154
4860
|
}
|
|
4861
|
+
const named = args.length === 1 && isPlainObject(args[0]) ? args[0] : null;
|
|
5155
4862
|
if (isPlainObject(message)) {
|
|
5156
|
-
|
|
5157
|
-
if (typeof named.count !== 'number') {
|
|
4863
|
+
if (typeof named?.count !== 'number') {
|
|
5158
4864
|
warnOnce(`plural message "${key}" needs a numeric {count}`);
|
|
5159
4865
|
message = message.other;
|
|
5160
4866
|
} else {
|
|
5161
|
-
const locale = this
|
|
4867
|
+
const locale = configured(this, 'locale') ?? navigator?.language ?? 'en';
|
|
5162
4868
|
const category = formatter(Intl.PluralRules, locale).select(named.count);
|
|
5163
4869
|
message = message[category] ?? message.other;
|
|
5164
4870
|
}
|
|
@@ -5167,10 +4873,9 @@ var ftl = (function (exports) {
|
|
|
5167
4873
|
warnOnce(`plural message "${key}" has no "other" form`);
|
|
5168
4874
|
return key;
|
|
5169
4875
|
}
|
|
5170
|
-
if (
|
|
5171
|
-
const named = args[0];
|
|
4876
|
+
if (named) {
|
|
5172
4877
|
return message.replace(PLACEHOLDER, (literal, name) => {
|
|
5173
|
-
if (!(name
|
|
4878
|
+
if (!Object.hasOwn(named, name)) {
|
|
5174
4879
|
warnOnce(`message "${key}" wants {${name}}`);
|
|
5175
4880
|
return literal;
|
|
5176
4881
|
}
|
|
@@ -5196,9 +4901,10 @@ var ftl = (function (exports) {
|
|
|
5196
4901
|
* @param {Date | number} value
|
|
5197
4902
|
* @param {Intl.DateTimeFormatOptions} [options]
|
|
5198
4903
|
* @this {Receiver}
|
|
4904
|
+
* @returns {string}
|
|
5199
4905
|
*/
|
|
5200
4906
|
static date(value, options) {
|
|
5201
|
-
return formatter(Intl.DateTimeFormat, this
|
|
4907
|
+
return formatter(Intl.DateTimeFormat, configured(this, 'locale'), options).format(value);
|
|
5202
4908
|
}
|
|
5203
4909
|
|
|
5204
4910
|
/**
|
|
@@ -5207,9 +4913,10 @@ var ftl = (function (exports) {
|
|
|
5207
4913
|
* @param {number} value
|
|
5208
4914
|
* @param {Intl.NumberFormatOptions} [options]
|
|
5209
4915
|
* @this {Receiver}
|
|
4916
|
+
* @returns {string}
|
|
5210
4917
|
*/
|
|
5211
4918
|
static number(value, options) {
|
|
5212
|
-
return formatter(Intl.NumberFormat, this
|
|
4919
|
+
return formatter(Intl.NumberFormat, configured(this, 'locale'), options).format(value);
|
|
5213
4920
|
}
|
|
5214
4921
|
|
|
5215
4922
|
/**
|
|
@@ -5219,9 +4926,10 @@ var ftl = (function (exports) {
|
|
|
5219
4926
|
*
|
|
5220
4927
|
* @param {number} value
|
|
5221
4928
|
* @this {Receiver}
|
|
4929
|
+
* @returns {string}
|
|
5222
4930
|
*/
|
|
5223
4931
|
static bytes(value) {
|
|
5224
|
-
const format = formatter(Intl.NumberFormat, this
|
|
4932
|
+
const format = formatter(Intl.NumberFormat, configured(this, 'locale'), { maximumFractionDigits: 2 }).format;
|
|
5225
4933
|
if (value >= 1024 * 1024 * 1024) {
|
|
5226
4934
|
return `${format(value / 1024 / 1024 / 1024)}GiB`;
|
|
5227
4935
|
}
|
|
@@ -5234,16 +4942,37 @@ var ftl = (function (exports) {
|
|
|
5234
4942
|
return `${format(value)}B`;
|
|
5235
4943
|
}
|
|
5236
4944
|
|
|
4945
|
+
/**
|
|
4946
|
+
* What went wrong, as text for the reader. A value carrying a non-empty
|
|
4947
|
+
* `problems` array reads as their reasons, one per line, a blank or missing
|
|
4948
|
+
* reason reading as the `failure.no-reason` message. Any other value with a
|
|
4949
|
+
* `message` reads as that message; anything else as its string form, and
|
|
4950
|
+
* null or undefined as the empty string.
|
|
4951
|
+
*
|
|
4952
|
+
* @param {any} value what was thrown or rejected with
|
|
4953
|
+
* @this {Receiver}
|
|
4954
|
+
* @returns {string}
|
|
4955
|
+
*/
|
|
4956
|
+
static failure(value) {
|
|
4957
|
+
if (Array.isArray(value?.problems) && value.problems.length > 0) {
|
|
4958
|
+
return value.problems.map((p) => reasonOf(p) ?? Localization.t.call(this, 'failure.no-reason')).join('\n');
|
|
4959
|
+
}
|
|
4960
|
+
if (value?.message !== undefined) {
|
|
4961
|
+
return String(value.message);
|
|
4962
|
+
}
|
|
4963
|
+
return value == null ? '' : String(value);
|
|
4964
|
+
}
|
|
4965
|
+
|
|
5237
4966
|
/**
|
|
5238
4967
|
* An imperative facade over the module functions, resolving the translations
|
|
5239
|
-
* and the locale from the registry overlays on every call
|
|
4968
|
+
* and the locale from the registry overlays on every call, the same lookup a
|
|
4969
|
+
* template makes: a facade taken at module scope, before the plugin
|
|
4970
|
+
* configures, still sees the translations.
|
|
5240
4971
|
*
|
|
5241
4972
|
* @param {{ locale?: string }} [overrides] an explicit locale, winning over the registry one
|
|
4973
|
+
* @returns {{ t: (key: string, ...args: any[]) => string, date: (value: Date | number, options?: Intl.DateTimeFormatOptions) => string, number: (value: number, options?: Intl.NumberFormatOptions) => string, bytes: (value: number) => string, failure: (value: any) => string }}
|
|
5242
4974
|
*/
|
|
5243
4975
|
static of(overrides = {}) {
|
|
5244
|
-
//resolved per call, not per facade: a module-scope `Localization.of()` is
|
|
5245
|
-
//bound before the plugin configures. The registry's own evaluator does the
|
|
5246
|
-
//lookup, so this cannot drift from what a template sees
|
|
5247
4976
|
const resolve = (prop) => registry.evaluator().resolve(prop);
|
|
5248
4977
|
/** @param {any} fn */
|
|
5249
4978
|
const bind =
|
|
@@ -5255,6 +4984,7 @@ var ftl = (function (exports) {
|
|
|
5255
4984
|
date: bind(Localization.date),
|
|
5256
4985
|
number: bind(Localization.number),
|
|
5257
4986
|
bytes: bind(Localization.bytes),
|
|
4987
|
+
failure: bind(Localization.failure),
|
|
5258
4988
|
};
|
|
5259
4989
|
}
|
|
5260
4990
|
}
|