cx 24.3.0 → 24.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data.js +15 -26
- package/dist/manifest.js +668 -668
- package/dist/util.js +4 -2
- package/dist/widgets.js +53 -32
- package/package.json +1 -1
- package/src/data/Expression.js +212 -212
- package/src/data/Expression.spec.js +174 -174
- package/src/ui/Format.js +87 -87
- package/src/util/getParentFrameBoundingClientRect.js +6 -4
- package/src/widgets/form/ColorPicker.scss +275 -275
- package/src/widgets/form/ColorPicker.variables.scss +22 -22
- package/src/widgets/grid/Grid.js +85 -74
- package/src/widgets/overlay/captureMouse.js +37 -46
package/dist/util.js
CHANGED
|
@@ -546,10 +546,12 @@ function findScrollableParent(sourceEl, horizontal) {
|
|
|
546
546
|
}
|
|
547
547
|
|
|
548
548
|
function getParentFrameBoundingClientRect(el) {
|
|
549
|
-
if
|
|
549
|
+
// if the ownerDocument is null, the element itself is the document
|
|
550
|
+
var ownerDocument = el.ownerDocument || el;
|
|
551
|
+
if (ownerDocument != document) {
|
|
550
552
|
var frames = document.getElementsByTagName("iframe");
|
|
551
553
|
for (var i = 0; i < frames.length; i++) {
|
|
552
|
-
if (frames[i].contentDocument ==
|
|
554
|
+
if (frames[i].contentDocument == ownerDocument) {
|
|
553
555
|
return frames[i].getBoundingClientRect();
|
|
554
556
|
}
|
|
555
557
|
}
|
package/dist/widgets.js
CHANGED
|
@@ -2201,15 +2201,22 @@ function captureMouse2(e, _ref) {
|
|
|
2201
2201
|
surface.className = "cxb-mousecapture";
|
|
2202
2202
|
surface.style.cursor = cursor || getComputedStyle(e.currentTarget).cursor;
|
|
2203
2203
|
document.body.appendChild(surface);
|
|
2204
|
+
|
|
2205
|
+
// In case when the event originates from an iframe,
|
|
2206
|
+
// we use that document as events do not bubble up. //
|
|
2207
|
+
var parentDocument = e.target.ownerDocument;
|
|
2208
|
+
var options = {
|
|
2209
|
+
capture: true,
|
|
2210
|
+
};
|
|
2204
2211
|
var active = true;
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
if (onDblClick)
|
|
2212
|
+
parentDocument.addEventListener("mousemove", move, options);
|
|
2213
|
+
parentDocument.addEventListener("mouseup", end, options);
|
|
2214
|
+
if (onDblClick) parentDocument.addEventListener("dblclick", doubleClick);
|
|
2208
2215
|
function tear() {
|
|
2209
2216
|
if (surface == null) return;
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
if (onDblClick)
|
|
2217
|
+
parentDocument.removeEventListener("mousemove", move, options);
|
|
2218
|
+
parentDocument.removeEventListener("mouseup", end, options);
|
|
2219
|
+
if (onDblClick) parentDocument.removeEventListener("dblclick", onDblClick, options);
|
|
2213
2220
|
document.body.removeChild(surface);
|
|
2214
2221
|
surface = null;
|
|
2215
2222
|
}
|
|
@@ -15768,10 +15775,7 @@ var Grid = /*#__PURE__*/ (function (_Container) {
|
|
|
15768
15775
|
var headerTBody = e.target.parentElement.parentElement.parentElement;
|
|
15769
15776
|
var uniqueColId = e.currentTarget.dataset.uniqueColId;
|
|
15770
15777
|
var headerCell = findFirstChild(headerTBody, function (el) {
|
|
15771
|
-
|
|
15772
|
-
return (
|
|
15773
|
-
el.tagName == "TH" && ((_el$dataset = el.dataset) == null ? void 0 : _el$dataset.uniqueColId) == uniqueColId
|
|
15774
|
-
);
|
|
15778
|
+
return el.tagName == "TH" && el.dataset && el.dataset.uniqueColId == uniqueColId;
|
|
15775
15779
|
});
|
|
15776
15780
|
var scrollAreaEl = headerTBody.parentElement.parentElement;
|
|
15777
15781
|
var gridEl = scrollAreaEl.parentElement;
|
|
@@ -15864,13 +15868,14 @@ var Grid = /*#__PURE__*/ (function (_Container) {
|
|
|
15864
15868
|
var headerRows = [];
|
|
15865
15869
|
if (!header) return null;
|
|
15866
15870
|
var skip = {};
|
|
15867
|
-
|
|
15871
|
+
var lineIndex = 0;
|
|
15872
|
+
header.children.forEach(function (line) {
|
|
15868
15873
|
var empty = [true, true, true];
|
|
15869
15874
|
var result = [[], [], []];
|
|
15870
15875
|
line.children.forEach(function (hdinst, colIndex) {
|
|
15871
15876
|
var hdwidget = hdinst.widget;
|
|
15872
15877
|
var _loop = function _loop(l) {
|
|
15873
|
-
var colKey = lineIndex +
|
|
15878
|
+
var colKey = lineIndex + l + "-" + colIndex;
|
|
15874
15879
|
if (skip[colKey]) return 0; // continue
|
|
15875
15880
|
if (Boolean(hdinst.data.fixed) != fixedColumns) return 0; // continue
|
|
15876
15881
|
var header = hdinst.components["header" + (l + 1)];
|
|
@@ -15927,8 +15932,7 @@ var Grid = /*#__PURE__*/ (function (_Container) {
|
|
|
15927
15932
|
colSpan = header.data.colSpan;
|
|
15928
15933
|
rowSpan = header.data.rowSpan;
|
|
15929
15934
|
for (var r = 0; r < header.data.rowSpan; r++)
|
|
15930
|
-
for (var c = 0; c < header.data.colSpan; c++)
|
|
15931
|
-
skip[lineIndex + "-" + (colIndex + c) + "-" + (l + r)] = true;
|
|
15935
|
+
for (var c = 0; c < header.data.colSpan; c++) skip[lineIndex + l + r + "-" + (colIndex + c)] = true;
|
|
15932
15936
|
}
|
|
15933
15937
|
if ((hdwidget.resizable || header.data.resizable) && header.data.colSpan < 2) {
|
|
15934
15938
|
resizer = _this3.renderResizer(instance, hdinst, header, colIndex);
|
|
@@ -15996,6 +16000,7 @@ var Grid = /*#__PURE__*/ (function (_Container) {
|
|
|
15996
16000
|
result = result.filter(function (_, i) {
|
|
15997
16001
|
return !empty[i];
|
|
15998
16002
|
});
|
|
16003
|
+
lineIndex += result.length;
|
|
15999
16004
|
if (result[0]) {
|
|
16000
16005
|
if (fixed && !fixedColumns) {
|
|
16001
16006
|
result[0].push(
|
|
@@ -16009,28 +16014,29 @@ var Grid = /*#__PURE__*/ (function (_Container) {
|
|
|
16009
16014
|
),
|
|
16010
16015
|
);
|
|
16011
16016
|
}
|
|
16012
|
-
headerRows.push(
|
|
16013
|
-
|
|
16014
|
-
|
|
16015
|
-
|
|
16016
|
-
|
|
16017
|
-
|
|
16018
|
-
|
|
16019
|
-
|
|
16020
|
-
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
i,
|
|
16024
|
-
);
|
|
16025
|
-
}),
|
|
16026
|
-
},
|
|
16027
|
-
"h" + key + lineIndex,
|
|
16028
|
-
),
|
|
16017
|
+
headerRows.push.apply(
|
|
16018
|
+
headerRows,
|
|
16019
|
+
result.map(function (h, i) {
|
|
16020
|
+
return /*#__PURE__*/ jsx(
|
|
16021
|
+
"tr",
|
|
16022
|
+
{
|
|
16023
|
+
children: h,
|
|
16024
|
+
},
|
|
16025
|
+
lineIndex + "-" + i,
|
|
16026
|
+
);
|
|
16027
|
+
}),
|
|
16029
16028
|
);
|
|
16030
16029
|
}
|
|
16031
16030
|
});
|
|
16032
16031
|
if (headerRows.length == 0) return null;
|
|
16033
|
-
return
|
|
16032
|
+
return /*#__PURE__*/ jsx(
|
|
16033
|
+
"tbody",
|
|
16034
|
+
{
|
|
16035
|
+
className: CSS.element(baseClass, "header"),
|
|
16036
|
+
children: headerRows,
|
|
16037
|
+
},
|
|
16038
|
+
"h" + key,
|
|
16039
|
+
);
|
|
16034
16040
|
};
|
|
16035
16041
|
_proto.onHeaderMouseMove = function onHeaderMouseMove(e, column, columnInstance, gridInstance, headerLine) {
|
|
16036
16042
|
var _headerInstance$widge;
|
|
@@ -16634,6 +16640,7 @@ var GridComponent = /*#__PURE__*/ (function (_VDOM$Component) {
|
|
|
16634
16640
|
mod["draggable"] = draggable;
|
|
16635
16641
|
mod["non-draggable"] = !draggable;
|
|
16636
16642
|
var wrap = function wrap(children) {
|
|
16643
|
+
var skipCells = {};
|
|
16637
16644
|
return /*#__PURE__*/ jsx(
|
|
16638
16645
|
GridRowComponent,
|
|
16639
16646
|
{
|
|
@@ -16683,6 +16690,20 @@ var GridComponent = /*#__PURE__*/ (function (_VDOM$Component) {
|
|
|
16683
16690
|
maxWidth: width + "px",
|
|
16684
16691
|
});
|
|
16685
16692
|
}
|
|
16693
|
+
if (skipCells[line + "-" + cellIndex]) return null;
|
|
16694
|
+
if (data.colSpan > 1 || data.rowSpan > 1) {
|
|
16695
|
+
for (var r = line; r < line + ((_data$rowSpan = data.rowSpan) != null ? _data$rowSpan : 1); r++) {
|
|
16696
|
+
var _data$rowSpan;
|
|
16697
|
+
for (
|
|
16698
|
+
var c = cellIndex;
|
|
16699
|
+
c < cellIndex + ((_data$colSpan = data.colSpan) != null ? _data$colSpan : 1);
|
|
16700
|
+
c++
|
|
16701
|
+
) {
|
|
16702
|
+
var _data$colSpan;
|
|
16703
|
+
skipCells[r + "-" + c] = true;
|
|
16704
|
+
}
|
|
16705
|
+
}
|
|
16706
|
+
}
|
|
16686
16707
|
if (cellWrap) content = cellWrap(content);
|
|
16687
16708
|
return /*#__PURE__*/ jsx(
|
|
16688
16709
|
"td",
|
package/package.json
CHANGED
package/src/data/Expression.js
CHANGED
|
@@ -1,212 +1,212 @@
|
|
|
1
|
-
import { computable } from "./computable";
|
|
2
|
-
import { Format } from "../util/Format";
|
|
3
|
-
import { Binding } from "./Binding";
|
|
4
|
-
|
|
5
|
-
import { quoteStr } from "../util/quote";
|
|
6
|
-
import { isDigit } from "../util/isDigit";
|
|
7
|
-
import { isFunction } from "../util/isFunction";
|
|
8
|
-
|
|
9
|
-
/*
|
|
10
|
-
Helper usage example
|
|
11
|
-
|
|
12
|
-
Expression.registerHelper('_', _);
|
|
13
|
-
let e = Expression.compile('_.min({data})');
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
let expCache = {},
|
|
17
|
-
helpers = {},
|
|
18
|
-
helperNames = [],
|
|
19
|
-
helperValues = [],
|
|
20
|
-
expFatArrows = null;
|
|
21
|
-
|
|
22
|
-
function getExpr(expr) {
|
|
23
|
-
if (expr.memoize) return expr;
|
|
24
|
-
|
|
25
|
-
function memoize() {
|
|
26
|
-
let lastValue,
|
|
27
|
-
lastRunBindings = {},
|
|
28
|
-
lastRunResults = {},
|
|
29
|
-
getters = {},
|
|
30
|
-
currentData,
|
|
31
|
-
len = -1;
|
|
32
|
-
|
|
33
|
-
let get = function (bindingWithFormat) {
|
|
34
|
-
let getter = getters[bindingWithFormat];
|
|
35
|
-
if (!getter) {
|
|
36
|
-
let binding = bindingWithFormat,
|
|
37
|
-
format;
|
|
38
|
-
let colonIndex = bindingWithFormat.indexOf(":");
|
|
39
|
-
if (colonIndex != -1) {
|
|
40
|
-
format = Format.parse(bindingWithFormat.substring(colonIndex + 1));
|
|
41
|
-
binding = bindingWithFormat.substring(0, colonIndex);
|
|
42
|
-
} else {
|
|
43
|
-
let nullSeparatorIndex = bindingWithFormat.indexOf(":");
|
|
44
|
-
if (nullSeparatorIndex != -1) {
|
|
45
|
-
format = Format.parse(bindingWithFormat.substring(nullSeparatorIndex));
|
|
46
|
-
binding = bindingWithFormat.substring(0, nullSeparatorIndex - 1);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
let b = Binding.get(binding);
|
|
50
|
-
getter = (data) => {
|
|
51
|
-
let value = b.value(data);
|
|
52
|
-
lastRunBindings[len] = b.value;
|
|
53
|
-
lastRunResults[len] = value;
|
|
54
|
-
len++;
|
|
55
|
-
return value;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
if (format) {
|
|
59
|
-
let valueGetter = getter;
|
|
60
|
-
getter = (data) => format(valueGetter(data));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
getters[bindingWithFormat] = getter;
|
|
64
|
-
}
|
|
65
|
-
return getter(currentData);
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
return function (data) {
|
|
69
|
-
let i = 0;
|
|
70
|
-
for (; i < len; i++) if (lastRunBindings[i](data) !== lastRunResults[i]) break;
|
|
71
|
-
if (i !== len) {
|
|
72
|
-
len = 0;
|
|
73
|
-
currentData = data;
|
|
74
|
-
lastValue = expr(get);
|
|
75
|
-
}
|
|
76
|
-
return lastValue;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
let result = memoize();
|
|
81
|
-
result.memoize = memoize;
|
|
82
|
-
return result;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function expression(str) {
|
|
86
|
-
if (isFunction(str)) return getExpr(str);
|
|
87
|
-
|
|
88
|
-
let r = expCache[str];
|
|
89
|
-
if (r) return r;
|
|
90
|
-
|
|
91
|
-
let quote = false;
|
|
92
|
-
|
|
93
|
-
let termStart = -1,
|
|
94
|
-
curlyBrackets = 0,
|
|
95
|
-
percentExpression;
|
|
96
|
-
|
|
97
|
-
let fb = ["return ("];
|
|
98
|
-
|
|
99
|
-
let args = {};
|
|
100
|
-
let formats = [];
|
|
101
|
-
let subExpr = 0;
|
|
102
|
-
|
|
103
|
-
for (let i = 0; i < str.length; i++) {
|
|
104
|
-
let c = str[i];
|
|
105
|
-
switch (c) {
|
|
106
|
-
case "{":
|
|
107
|
-
if (curlyBrackets > 0) curlyBrackets++;
|
|
108
|
-
else {
|
|
109
|
-
if (!quote && termStart < 0 && (str[i + 1] != "{" || str[i - 1] == "%")) {
|
|
110
|
-
termStart = i + 1;
|
|
111
|
-
curlyBrackets = 1;
|
|
112
|
-
percentExpression = str[i - 1] == "%";
|
|
113
|
-
if (percentExpression) fb.pop(); //%
|
|
114
|
-
} else if (str[i - 1] != "{") fb.push(c);
|
|
115
|
-
}
|
|
116
|
-
break;
|
|
117
|
-
|
|
118
|
-
case "}":
|
|
119
|
-
if (termStart >= 0) {
|
|
120
|
-
if (--curlyBrackets == 0) {
|
|
121
|
-
let term = str.substring(termStart, i);
|
|
122
|
-
let formatStart = 0;
|
|
123
|
-
if (term[0] == "[") formatStart = term.indexOf("]");
|
|
124
|
-
let colon = term.indexOf(":", formatStart > 0 ? formatStart : 0);
|
|
125
|
-
let binding = colon == -1 ? term : term.substring(0, colon);
|
|
126
|
-
let format = colon == -1 ? null : term.substring(colon + 1);
|
|
127
|
-
if (colon == -1) {
|
|
128
|
-
let nullSepIndex = binding.indexOf("|", formatStart);
|
|
129
|
-
if (nullSepIndex != -1) {
|
|
130
|
-
format = binding.substring(nullSepIndex);
|
|
131
|
-
binding = binding.substring(0, nullSepIndex);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
let argName = binding.replace(/\./g, "_");
|
|
135
|
-
if (isDigit(argName[0])) argName = "$" + argName;
|
|
136
|
-
if (percentExpression || (binding[0] == "[" && binding[binding.length - 1] == "]")) {
|
|
137
|
-
argName = `expr${++subExpr}`;
|
|
138
|
-
args[argName] = expression(percentExpression ? binding : binding.substring(1, binding.length - 1));
|
|
139
|
-
} else args[argName] = binding;
|
|
140
|
-
if (format) {
|
|
141
|
-
let formatter = "fmt" + formats.length;
|
|
142
|
-
fb.push(formatter, "(", argName, ", ", quoteStr(format), ")");
|
|
143
|
-
formats.push(Format.parse(format));
|
|
144
|
-
} else fb.push(argName);
|
|
145
|
-
termStart = -1;
|
|
146
|
-
}
|
|
147
|
-
} else fb.push(c);
|
|
148
|
-
|
|
149
|
-
break;
|
|
150
|
-
|
|
151
|
-
case '"':
|
|
152
|
-
case "'":
|
|
153
|
-
if (curlyBrackets == 0) {
|
|
154
|
-
if (!quote) quote = c;
|
|
155
|
-
else if (str[i - 1] != "\\" && quote == c) quote = false;
|
|
156
|
-
fb.push(c);
|
|
157
|
-
}
|
|
158
|
-
break;
|
|
159
|
-
|
|
160
|
-
default:
|
|
161
|
-
if (termStart < 0) fb.push(c);
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
fb.push(")");
|
|
167
|
-
|
|
168
|
-
let body = fb.join("");
|
|
169
|
-
|
|
170
|
-
if (expFatArrows) body = expFatArrows(body);
|
|
171
|
-
|
|
172
|
-
//console.log(body);
|
|
173
|
-
let keys = Object.keys(args);
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
let compute = new Function("fmt", ...formats.map((f, i) => "fmt" + i), ...keys, ...helperNames, body).bind(
|
|
177
|
-
Format,
|
|
178
|
-
Format.value,
|
|
179
|
-
...formats,
|
|
180
|
-
...helperValues
|
|
181
|
-
);
|
|
182
|
-
let selector = computable(...keys.map((k) => args[k]), compute);
|
|
183
|
-
expCache[str] = selector;
|
|
184
|
-
return selector;
|
|
185
|
-
} catch (err) {
|
|
186
|
-
throw new Error(`Failed to parse expression: '${str}'. Error: ${err.message}`);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export const Expression = {
|
|
191
|
-
get: function (str) {
|
|
192
|
-
return expression(str);
|
|
193
|
-
},
|
|
194
|
-
|
|
195
|
-
compile: function (str) {
|
|
196
|
-
return this.get(str).memoize();
|
|
197
|
-
},
|
|
198
|
-
|
|
199
|
-
registerHelper: function (name, helper) {
|
|
200
|
-
helpers[name] = helper;
|
|
201
|
-
helperNames = Object.keys(helpers);
|
|
202
|
-
helperValues = helperNames.map((n) => helpers[n]);
|
|
203
|
-
},
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
export function plugFatArrowExpansion(impl) {
|
|
207
|
-
expFatArrows = impl;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export function invalidateExpressionCache() {
|
|
211
|
-
expCache = {};
|
|
212
|
-
}
|
|
1
|
+
import { computable } from "./computable";
|
|
2
|
+
import { Format } from "../util/Format";
|
|
3
|
+
import { Binding } from "./Binding";
|
|
4
|
+
|
|
5
|
+
import { quoteStr } from "../util/quote";
|
|
6
|
+
import { isDigit } from "../util/isDigit";
|
|
7
|
+
import { isFunction } from "../util/isFunction";
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
Helper usage example
|
|
11
|
+
|
|
12
|
+
Expression.registerHelper('_', _);
|
|
13
|
+
let e = Expression.compile('_.min({data})');
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
let expCache = {},
|
|
17
|
+
helpers = {},
|
|
18
|
+
helperNames = [],
|
|
19
|
+
helperValues = [],
|
|
20
|
+
expFatArrows = null;
|
|
21
|
+
|
|
22
|
+
function getExpr(expr) {
|
|
23
|
+
if (expr.memoize) return expr;
|
|
24
|
+
|
|
25
|
+
function memoize() {
|
|
26
|
+
let lastValue,
|
|
27
|
+
lastRunBindings = {},
|
|
28
|
+
lastRunResults = {},
|
|
29
|
+
getters = {},
|
|
30
|
+
currentData,
|
|
31
|
+
len = -1;
|
|
32
|
+
|
|
33
|
+
let get = function (bindingWithFormat) {
|
|
34
|
+
let getter = getters[bindingWithFormat];
|
|
35
|
+
if (!getter) {
|
|
36
|
+
let binding = bindingWithFormat,
|
|
37
|
+
format;
|
|
38
|
+
let colonIndex = bindingWithFormat.indexOf(":");
|
|
39
|
+
if (colonIndex != -1) {
|
|
40
|
+
format = Format.parse(bindingWithFormat.substring(colonIndex + 1));
|
|
41
|
+
binding = bindingWithFormat.substring(0, colonIndex);
|
|
42
|
+
} else {
|
|
43
|
+
let nullSeparatorIndex = bindingWithFormat.indexOf(":");
|
|
44
|
+
if (nullSeparatorIndex != -1) {
|
|
45
|
+
format = Format.parse(bindingWithFormat.substring(nullSeparatorIndex));
|
|
46
|
+
binding = bindingWithFormat.substring(0, nullSeparatorIndex - 1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
let b = Binding.get(binding);
|
|
50
|
+
getter = (data) => {
|
|
51
|
+
let value = b.value(data);
|
|
52
|
+
lastRunBindings[len] = b.value;
|
|
53
|
+
lastRunResults[len] = value;
|
|
54
|
+
len++;
|
|
55
|
+
return value;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if (format) {
|
|
59
|
+
let valueGetter = getter;
|
|
60
|
+
getter = (data) => format(valueGetter(data));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getters[bindingWithFormat] = getter;
|
|
64
|
+
}
|
|
65
|
+
return getter(currentData);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return function (data) {
|
|
69
|
+
let i = 0;
|
|
70
|
+
for (; i < len; i++) if (lastRunBindings[i](data) !== lastRunResults[i]) break;
|
|
71
|
+
if (i !== len) {
|
|
72
|
+
len = 0;
|
|
73
|
+
currentData = data;
|
|
74
|
+
lastValue = expr(get);
|
|
75
|
+
}
|
|
76
|
+
return lastValue;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let result = memoize();
|
|
81
|
+
result.memoize = memoize;
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function expression(str) {
|
|
86
|
+
if (isFunction(str)) return getExpr(str);
|
|
87
|
+
|
|
88
|
+
let r = expCache[str];
|
|
89
|
+
if (r) return r;
|
|
90
|
+
|
|
91
|
+
let quote = false;
|
|
92
|
+
|
|
93
|
+
let termStart = -1,
|
|
94
|
+
curlyBrackets = 0,
|
|
95
|
+
percentExpression;
|
|
96
|
+
|
|
97
|
+
let fb = ["return ("];
|
|
98
|
+
|
|
99
|
+
let args = {};
|
|
100
|
+
let formats = [];
|
|
101
|
+
let subExpr = 0;
|
|
102
|
+
|
|
103
|
+
for (let i = 0; i < str.length; i++) {
|
|
104
|
+
let c = str[i];
|
|
105
|
+
switch (c) {
|
|
106
|
+
case "{":
|
|
107
|
+
if (curlyBrackets > 0) curlyBrackets++;
|
|
108
|
+
else {
|
|
109
|
+
if (!quote && termStart < 0 && (str[i + 1] != "{" || str[i - 1] == "%")) {
|
|
110
|
+
termStart = i + 1;
|
|
111
|
+
curlyBrackets = 1;
|
|
112
|
+
percentExpression = str[i - 1] == "%";
|
|
113
|
+
if (percentExpression) fb.pop(); //%
|
|
114
|
+
} else if (str[i - 1] != "{") fb.push(c);
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
|
|
118
|
+
case "}":
|
|
119
|
+
if (termStart >= 0) {
|
|
120
|
+
if (--curlyBrackets == 0) {
|
|
121
|
+
let term = str.substring(termStart, i);
|
|
122
|
+
let formatStart = 0;
|
|
123
|
+
if (term[0] == "[") formatStart = term.indexOf("]");
|
|
124
|
+
let colon = term.indexOf(":", formatStart > 0 ? formatStart : 0);
|
|
125
|
+
let binding = colon == -1 ? term : term.substring(0, colon);
|
|
126
|
+
let format = colon == -1 ? null : term.substring(colon + 1);
|
|
127
|
+
if (colon == -1) {
|
|
128
|
+
let nullSepIndex = binding.indexOf("|", formatStart);
|
|
129
|
+
if (nullSepIndex != -1) {
|
|
130
|
+
format = binding.substring(nullSepIndex);
|
|
131
|
+
binding = binding.substring(0, nullSepIndex);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
let argName = binding.replace(/\./g, "_");
|
|
135
|
+
if (isDigit(argName[0])) argName = "$" + argName;
|
|
136
|
+
if (percentExpression || (binding[0] == "[" && binding[binding.length - 1] == "]")) {
|
|
137
|
+
argName = `expr${++subExpr}`;
|
|
138
|
+
args[argName] = expression(percentExpression ? binding : binding.substring(1, binding.length - 1));
|
|
139
|
+
} else args[argName] = binding;
|
|
140
|
+
if (format) {
|
|
141
|
+
let formatter = "fmt" + formats.length;
|
|
142
|
+
fb.push(formatter, "(", argName, ", ", quoteStr(format), ")");
|
|
143
|
+
formats.push(Format.parse(format));
|
|
144
|
+
} else fb.push(argName);
|
|
145
|
+
termStart = -1;
|
|
146
|
+
}
|
|
147
|
+
} else fb.push(c);
|
|
148
|
+
|
|
149
|
+
break;
|
|
150
|
+
|
|
151
|
+
case '"':
|
|
152
|
+
case "'":
|
|
153
|
+
if (curlyBrackets == 0) {
|
|
154
|
+
if (!quote) quote = c;
|
|
155
|
+
else if (str[i - 1] != "\\" && quote == c) quote = false;
|
|
156
|
+
fb.push(c);
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
|
|
160
|
+
default:
|
|
161
|
+
if (termStart < 0) fb.push(c);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
fb.push(")");
|
|
167
|
+
|
|
168
|
+
let body = fb.join("");
|
|
169
|
+
|
|
170
|
+
if (expFatArrows) body = expFatArrows(body);
|
|
171
|
+
|
|
172
|
+
//console.log(body);
|
|
173
|
+
let keys = Object.keys(args);
|
|
174
|
+
|
|
175
|
+
try {
|
|
176
|
+
let compute = new Function("fmt", ...formats.map((f, i) => "fmt" + i), ...keys, ...helperNames, body).bind(
|
|
177
|
+
Format,
|
|
178
|
+
Format.value,
|
|
179
|
+
...formats,
|
|
180
|
+
...helperValues
|
|
181
|
+
);
|
|
182
|
+
let selector = computable(...keys.map((k) => args[k]), compute);
|
|
183
|
+
expCache[str] = selector;
|
|
184
|
+
return selector;
|
|
185
|
+
} catch (err) {
|
|
186
|
+
throw new Error(`Failed to parse expression: '${str}'. Error: ${err.message}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export const Expression = {
|
|
191
|
+
get: function (str) {
|
|
192
|
+
return expression(str);
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
compile: function (str) {
|
|
196
|
+
return this.get(str).memoize();
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
registerHelper: function (name, helper) {
|
|
200
|
+
helpers[name] = helper;
|
|
201
|
+
helperNames = Object.keys(helpers);
|
|
202
|
+
helperValues = helperNames.map((n) => helpers[n]);
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export function plugFatArrowExpansion(impl) {
|
|
207
|
+
expFatArrows = impl;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function invalidateExpressionCache() {
|
|
211
|
+
expCache = {};
|
|
212
|
+
}
|