@odoo/o-spreadsheet 16.0.24 → 16.0.27
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/o-spreadsheet.cjs.js +204 -144
- package/dist/o-spreadsheet.d.ts +23 -24
- package/dist/o-spreadsheet.esm.js +204 -144
- package/dist/o-spreadsheet.iife.js +204 -144
- package/dist/o-spreadsheet.iife.min.js +274 -274
- package/dist/o_spreadsheet.xml +6 -7
- package/package.json +1 -1
|
@@ -620,13 +620,6 @@ function getYearFrac(startDate, endDate, _dayCountConvention) {
|
|
|
620
620
|
}
|
|
621
621
|
|
|
622
622
|
//------------------------------------------------------------------------------
|
|
623
|
-
/**
|
|
624
|
-
* Stringify an object, like JSON.stringify, except that the first level of keys
|
|
625
|
-
* is ordered.
|
|
626
|
-
*/
|
|
627
|
-
function stringify(obj) {
|
|
628
|
-
return JSON.stringify(obj, Object.keys(obj).sort());
|
|
629
|
-
}
|
|
630
623
|
/**
|
|
631
624
|
* Remove quotes from a quoted string
|
|
632
625
|
* ```js
|
|
@@ -928,7 +921,7 @@ function isObjectEmptyRecursive(argument) {
|
|
|
928
921
|
*/
|
|
929
922
|
function getItemId(item, itemsDic) {
|
|
930
923
|
for (let [key, value] of Object.entries(itemsDic)) {
|
|
931
|
-
if (
|
|
924
|
+
if (deepEquals(value, item)) {
|
|
932
925
|
return parseInt(key, 10);
|
|
933
926
|
}
|
|
934
927
|
}
|
|
@@ -1064,6 +1057,22 @@ function transpose2dArray(matrix) {
|
|
|
1064
1057
|
if (!matrix.length)
|
|
1065
1058
|
return matrix;
|
|
1066
1059
|
return matrix[0].map((_, i) => matrix.map((row) => row[i]));
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Creates a version of the function that's memoized on the value of its first
|
|
1063
|
+
* argument, if any.
|
|
1064
|
+
*/
|
|
1065
|
+
function memoize(func) {
|
|
1066
|
+
const cache = new Map();
|
|
1067
|
+
const funcName = func.name ? func.name + " (memoized)" : "memoized";
|
|
1068
|
+
return {
|
|
1069
|
+
[funcName](...args) {
|
|
1070
|
+
if (!cache.has(args[0])) {
|
|
1071
|
+
cache.set(args[0], func(...args));
|
|
1072
|
+
}
|
|
1073
|
+
return cache.get(args[0]);
|
|
1074
|
+
},
|
|
1075
|
+
}[funcName];
|
|
1067
1076
|
}
|
|
1068
1077
|
|
|
1069
1078
|
const RBA_REGEX = /rgba?\(|\s+|\)/gi;
|
|
@@ -1343,8 +1352,10 @@ function isSameColor(color1, color2) {
|
|
|
1343
1352
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
1344
1353
|
// Same as above, but matches the exact string (nothing before or after)
|
|
1345
1354
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
1346
|
-
/** Reference of a column header (eg. A, AB) */
|
|
1347
|
-
const colHeader = new RegExp(
|
|
1355
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
1356
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
1357
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
1358
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
1348
1359
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
1349
1360
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
1350
1361
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -1374,6 +1385,9 @@ function isRowReference(xc) {
|
|
|
1374
1385
|
function isColHeader(str) {
|
|
1375
1386
|
return colHeader.test(str);
|
|
1376
1387
|
}
|
|
1388
|
+
function isRowHeader(str) {
|
|
1389
|
+
return rowHeader.test(str);
|
|
1390
|
+
}
|
|
1377
1391
|
/**
|
|
1378
1392
|
* Return true if the given xc is the reference of a single cell,
|
|
1379
1393
|
* without any specified sheet (e.g. A1)
|
|
@@ -2074,18 +2088,10 @@ class RangeImpl {
|
|
|
2074
2088
|
if (isFullCol) {
|
|
2075
2089
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2076
2090
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2077
|
-
if (zone.left === zone.right) {
|
|
2078
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2079
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2080
|
-
}
|
|
2081
2091
|
}
|
|
2082
2092
|
if (isFullRow) {
|
|
2083
2093
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2084
2094
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2085
|
-
if (zone.top === zone.bottom) {
|
|
2086
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2087
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2088
|
-
}
|
|
2089
2095
|
}
|
|
2090
2096
|
return parts;
|
|
2091
2097
|
}
|
|
@@ -3301,6 +3307,7 @@ var CommandResult;
|
|
|
3301
3307
|
CommandResult[CommandResult["ChartDoesNotExist"] = 84] = "ChartDoesNotExist";
|
|
3302
3308
|
CommandResult[CommandResult["InvalidHeaderIndex"] = 85] = "InvalidHeaderIndex";
|
|
3303
3309
|
CommandResult[CommandResult["InvalidQuantity"] = 86] = "InvalidQuantity";
|
|
3310
|
+
CommandResult[CommandResult["NoChanges"] = 87] = "NoChanges";
|
|
3304
3311
|
})(CommandResult || (CommandResult = {}));
|
|
3305
3312
|
|
|
3306
3313
|
function isMatrix(x) {
|
|
@@ -3876,6 +3883,7 @@ function getMenuDescription(node) {
|
|
|
3876
3883
|
return node.description ? node.description : "";
|
|
3877
3884
|
}
|
|
3878
3885
|
|
|
3886
|
+
const macRegex = /Mac/i;
|
|
3879
3887
|
/**
|
|
3880
3888
|
* Return true if the event was triggered from
|
|
3881
3889
|
* a child element.
|
|
@@ -3893,6 +3901,17 @@ function gridOverlayPosition() {
|
|
|
3893
3901
|
}
|
|
3894
3902
|
function getOpenedMenus() {
|
|
3895
3903
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
3904
|
+
}
|
|
3905
|
+
function isMacOS() {
|
|
3906
|
+
return Boolean(macRegex.test(navigator.userAgent));
|
|
3907
|
+
}
|
|
3908
|
+
/**
|
|
3909
|
+
* @param {KeyboardEvent | MouseEvent} ev
|
|
3910
|
+
* @returns Returns true if the event was triggered with the "ctrl" modifier pressed.
|
|
3911
|
+
* On Mac, this is the "meta" or "command" key.
|
|
3912
|
+
*/
|
|
3913
|
+
function isCtrlKey(ev) {
|
|
3914
|
+
return isMacOS() ? ev.metaKey : ev.ctrlKey;
|
|
3896
3915
|
}
|
|
3897
3916
|
|
|
3898
3917
|
/**
|
|
@@ -10976,12 +10995,12 @@ function toString(value) {
|
|
|
10976
10995
|
}
|
|
10977
10996
|
}
|
|
10978
10997
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
10979
|
-
function normalizeString(str) {
|
|
10998
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
10980
10999
|
return str
|
|
10981
11000
|
.toLowerCase()
|
|
10982
11001
|
.normalize("NFD")
|
|
10983
11002
|
.replace(/[\u0300-\u036f]/g, "");
|
|
10984
|
-
}
|
|
11003
|
+
});
|
|
10985
11004
|
/**
|
|
10986
11005
|
* Normalize a value.
|
|
10987
11006
|
* If the cell value is a string, this will set it to lowercase and replacing accent letters with plain letters
|
|
@@ -18556,7 +18575,7 @@ const machine = {
|
|
|
18556
18575
|
SPACE: goTo(State.RightRef),
|
|
18557
18576
|
NUMBER: goTo(State.Found),
|
|
18558
18577
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
18559
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
18578
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
18560
18579
|
},
|
|
18561
18580
|
[State.RightColumnRef]: {
|
|
18562
18581
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -18567,6 +18586,7 @@ const machine = {
|
|
|
18567
18586
|
SPACE: goTo(State.RightRowRef),
|
|
18568
18587
|
NUMBER: goTo(State.Found),
|
|
18569
18588
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
18589
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
18570
18590
|
},
|
|
18571
18591
|
[State.Found]: {},
|
|
18572
18592
|
};
|
|
@@ -19076,6 +19096,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
19076
19096
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
19077
19097
|
case "colrow":
|
|
19078
19098
|
indexOfNumber = xc.search(/[0-9]/);
|
|
19099
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
19100
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
19101
|
+
return "$" + xc;
|
|
19102
|
+
}
|
|
19079
19103
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
19080
19104
|
return "$" + xc;
|
|
19081
19105
|
case "none":
|
|
@@ -21457,7 +21481,10 @@ class GridOverlay extends Component {
|
|
|
21457
21481
|
return;
|
|
21458
21482
|
}
|
|
21459
21483
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
21460
|
-
this.props.onCellClicked(col, row, {
|
|
21484
|
+
this.props.onCellClicked(col, row, {
|
|
21485
|
+
expandZone: ev.shiftKey,
|
|
21486
|
+
addZone: isCtrlKey(ev),
|
|
21487
|
+
});
|
|
21461
21488
|
}
|
|
21462
21489
|
onDoubleClick(ev) {
|
|
21463
21490
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
@@ -21529,6 +21556,7 @@ class AbstractResizer extends Component {
|
|
|
21529
21556
|
draggerShadowThickness: 0,
|
|
21530
21557
|
delta: 0,
|
|
21531
21558
|
base: 0,
|
|
21559
|
+
position: "before",
|
|
21532
21560
|
});
|
|
21533
21561
|
}
|
|
21534
21562
|
_computeHandleDisplay(ev) {
|
|
@@ -21654,11 +21682,13 @@ class AbstractResizer extends Component {
|
|
|
21654
21682
|
this.state.draggerLinePosition = dimensions.start;
|
|
21655
21683
|
this.state.draggerShadowPosition = dimensions.start;
|
|
21656
21684
|
this.state.base = elementIndex;
|
|
21685
|
+
this.state.position = "before";
|
|
21657
21686
|
}
|
|
21658
21687
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
21659
21688
|
this.state.draggerLinePosition = dimensions.end;
|
|
21660
21689
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
21661
|
-
this.state.base = elementIndex
|
|
21690
|
+
this.state.base = elementIndex;
|
|
21691
|
+
this.state.position = "after";
|
|
21662
21692
|
}
|
|
21663
21693
|
else {
|
|
21664
21694
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -21682,7 +21712,7 @@ class AbstractResizer extends Component {
|
|
|
21682
21712
|
this._increaseSelection(index);
|
|
21683
21713
|
}
|
|
21684
21714
|
else {
|
|
21685
|
-
this._selectElement(index, ev
|
|
21715
|
+
this._selectElement(index, isCtrlKey(ev));
|
|
21686
21716
|
}
|
|
21687
21717
|
this.lastSelectedElementIndex = index;
|
|
21688
21718
|
const mouseMoveSelect = (col, row) => {
|
|
@@ -21695,7 +21725,7 @@ class AbstractResizer extends Component {
|
|
|
21695
21725
|
const mouseUpSelect = () => {
|
|
21696
21726
|
this.state.isSelecting = false;
|
|
21697
21727
|
this.lastSelectedElementIndex = null;
|
|
21698
|
-
this.env.model.dispatch(ev
|
|
21728
|
+
this.env.model.dispatch(isCtrlKey(ev) ? "PREPARE_SELECTION_INPUT_EXPANSION" : "STOP_SELECTION_INPUT");
|
|
21699
21729
|
this._computeGrabDisplay(ev);
|
|
21700
21730
|
};
|
|
21701
21731
|
dragAndDropBeyondTheViewport(this.env, mouseMoveSelect, mouseUpSelect);
|
|
@@ -21836,13 +21866,14 @@ class ColResizer extends AbstractResizer {
|
|
|
21836
21866
|
dimension: "COL",
|
|
21837
21867
|
base: this.state.base,
|
|
21838
21868
|
elements,
|
|
21869
|
+
position: this.state.position,
|
|
21839
21870
|
});
|
|
21840
21871
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
21841
21872
|
this.env.raiseError(MergeErrorMessage);
|
|
21842
21873
|
}
|
|
21843
21874
|
}
|
|
21844
|
-
_selectElement(index,
|
|
21845
|
-
this.env.model.selection.selectColumn(index,
|
|
21875
|
+
_selectElement(index, addDistinctHeader) {
|
|
21876
|
+
this.env.model.selection.selectColumn(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
21846
21877
|
}
|
|
21847
21878
|
_increaseSelection(index) {
|
|
21848
21879
|
this.env.model.selection.selectColumn(index, "updateAnchor");
|
|
@@ -22005,13 +22036,14 @@ class RowResizer extends AbstractResizer {
|
|
|
22005
22036
|
dimension: "ROW",
|
|
22006
22037
|
base: this.state.base,
|
|
22007
22038
|
elements,
|
|
22039
|
+
position: this.state.position,
|
|
22008
22040
|
});
|
|
22009
22041
|
if (!result.isSuccessful && result.reasons.includes(2 /* CommandResult.WillRemoveExistingMerge */)) {
|
|
22010
22042
|
this.env.raiseError(MergeErrorMessage);
|
|
22011
22043
|
}
|
|
22012
22044
|
}
|
|
22013
|
-
_selectElement(index,
|
|
22014
|
-
this.env.model.selection.selectRow(index,
|
|
22045
|
+
_selectElement(index, addDistinctHeader) {
|
|
22046
|
+
this.env.model.selection.selectRow(index, addDistinctHeader ? "newAnchor" : "overrideSelection");
|
|
22015
22047
|
}
|
|
22016
22048
|
_increaseSelection(index) {
|
|
22017
22049
|
this.env.model.selection.selectRow(index, "updateAnchor");
|
|
@@ -22107,8 +22139,8 @@ function useWheelHandler(handler) {
|
|
|
22107
22139
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
22108
22140
|
}
|
|
22109
22141
|
const onMouseWheel = (ev) => {
|
|
22110
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
22111
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
22142
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
22143
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
22112
22144
|
handler(deltaX, deltaY);
|
|
22113
22145
|
};
|
|
22114
22146
|
return onMouseWheel;
|
|
@@ -22702,18 +22734,18 @@ class Grid extends Component {
|
|
|
22702
22734
|
// ---------------------------------------------------------------------------
|
|
22703
22735
|
// Zone selection with mouse
|
|
22704
22736
|
// ---------------------------------------------------------------------------
|
|
22705
|
-
onCellClicked(col, row, {
|
|
22706
|
-
if (
|
|
22737
|
+
onCellClicked(col, row, { addZone, expandZone }) {
|
|
22738
|
+
if (addZone) {
|
|
22707
22739
|
this.env.model.dispatch("PREPARE_SELECTION_INPUT_EXPANSION");
|
|
22708
22740
|
}
|
|
22709
22741
|
this.closeOpenedPopover();
|
|
22710
22742
|
if (this.env.model.getters.getEditionMode() === "editing") {
|
|
22711
22743
|
this.env.model.dispatch("STOP_EDITION");
|
|
22712
22744
|
}
|
|
22713
|
-
if (
|
|
22745
|
+
if (expandZone) {
|
|
22714
22746
|
this.env.model.selection.setAnchorCorner(col, row);
|
|
22715
22747
|
}
|
|
22716
|
-
else if (
|
|
22748
|
+
else if (addZone) {
|
|
22717
22749
|
this.env.model.selection.addCellToSelection(col, row);
|
|
22718
22750
|
}
|
|
22719
22751
|
else {
|
|
@@ -22767,10 +22799,10 @@ class Grid extends Component {
|
|
|
22767
22799
|
};
|
|
22768
22800
|
const direction = arrowMap[ev.key];
|
|
22769
22801
|
if (ev.shiftKey) {
|
|
22770
|
-
this.env.model.selection.resizeAnchorZone(direction, ev
|
|
22802
|
+
this.env.model.selection.resizeAnchorZone(direction, isCtrlKey(ev) ? "end" : 1);
|
|
22771
22803
|
}
|
|
22772
22804
|
else {
|
|
22773
|
-
this.env.model.selection.moveAnchorCell(direction, ev
|
|
22805
|
+
this.env.model.selection.moveAnchorCell(direction, isCtrlKey(ev) ? "end" : 1);
|
|
22774
22806
|
}
|
|
22775
22807
|
if (this.env.model.getters.isPaintingFormat()) {
|
|
22776
22808
|
this.env.model.dispatch("PASTE", {
|
|
@@ -22784,9 +22816,7 @@ class Grid extends Component {
|
|
|
22784
22816
|
return;
|
|
22785
22817
|
}
|
|
22786
22818
|
let keyDownString = "";
|
|
22787
|
-
if (ev
|
|
22788
|
-
keyDownString += "CTRL+";
|
|
22789
|
-
if (ev.metaKey)
|
|
22819
|
+
if (isCtrlKey(ev))
|
|
22790
22820
|
keyDownString += "CTRL+";
|
|
22791
22821
|
if (ev.altKey)
|
|
22792
22822
|
keyDownString += "ALT+";
|
|
@@ -27101,6 +27131,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
27101
27131
|
// ---------------------------------------------------------------------------
|
|
27102
27132
|
// Command Handling
|
|
27103
27133
|
// ---------------------------------------------------------------------------
|
|
27134
|
+
allowDispatch(cmd) {
|
|
27135
|
+
switch (cmd.type) {
|
|
27136
|
+
case "SET_BORDER":
|
|
27137
|
+
return this.checkBordersUnchanged(cmd);
|
|
27138
|
+
default:
|
|
27139
|
+
return 0 /* CommandResult.Success */;
|
|
27140
|
+
}
|
|
27141
|
+
}
|
|
27104
27142
|
handle(cmd) {
|
|
27105
27143
|
switch (cmd.type) {
|
|
27106
27144
|
case "ADD_MERGE":
|
|
@@ -27496,6 +27534,15 @@ class BordersPlugin extends CorePlugin {
|
|
|
27496
27534
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right");
|
|
27497
27535
|
}
|
|
27498
27536
|
}
|
|
27537
|
+
checkBordersUnchanged(cmd) {
|
|
27538
|
+
var _a, _b, _c, _d;
|
|
27539
|
+
const currentBorder = this.getCellBorder(cmd.sheetId, cmd.col, cmd.row);
|
|
27540
|
+
const areAllNewBordersUndefined = !((_a = cmd.border) === null || _a === void 0 ? void 0 : _a.bottom) && !((_b = cmd.border) === null || _b === void 0 ? void 0 : _b.left) && !((_c = cmd.border) === null || _c === void 0 ? void 0 : _c.right) && !((_d = cmd.border) === null || _d === void 0 ? void 0 : _d.top);
|
|
27541
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
27542
|
+
return 87 /* CommandResult.NoChanges */;
|
|
27543
|
+
}
|
|
27544
|
+
return 0 /* CommandResult.Success */;
|
|
27545
|
+
}
|
|
27499
27546
|
// ---------------------------------------------------------------------------
|
|
27500
27547
|
// Import/Export
|
|
27501
27548
|
// ---------------------------------------------------------------------------
|
|
@@ -27531,7 +27578,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
27531
27578
|
*/
|
|
27532
27579
|
function getBorderId(border) {
|
|
27533
27580
|
for (let [key, value] of Object.entries(borders)) {
|
|
27534
|
-
if (
|
|
27581
|
+
if (deepEquals(value, border)) {
|
|
27535
27582
|
return parseInt(key, 10);
|
|
27536
27583
|
}
|
|
27537
27584
|
}
|
|
@@ -27574,6 +27621,7 @@ const nbspRegexp = new RegExp(String.fromCharCode(160), "g");
|
|
|
27574
27621
|
class CellPlugin extends CorePlugin {
|
|
27575
27622
|
constructor() {
|
|
27576
27623
|
super(...arguments);
|
|
27624
|
+
this.nextId = 1;
|
|
27577
27625
|
this.cells = {};
|
|
27578
27626
|
this.createCell = cellFactory(this.getters);
|
|
27579
27627
|
}
|
|
@@ -27599,8 +27647,9 @@ class CellPlugin extends CorePlugin {
|
|
|
27599
27647
|
allowDispatch(cmd) {
|
|
27600
27648
|
switch (cmd.type) {
|
|
27601
27649
|
case "UPDATE_CELL":
|
|
27650
|
+
return this.checkCellOutOfSheet(cmd);
|
|
27602
27651
|
case "CLEAR_CELL":
|
|
27603
|
-
return this.
|
|
27652
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
27604
27653
|
default:
|
|
27605
27654
|
return 0 /* CommandResult.Success */;
|
|
27606
27655
|
}
|
|
@@ -27741,7 +27790,7 @@ class CellPlugin extends CorePlugin {
|
|
|
27741
27790
|
importCell(sheetId, cellData, normalizedStyles, normalizedFormats) {
|
|
27742
27791
|
const style = (cellData.style && normalizedStyles[cellData.style]) || undefined;
|
|
27743
27792
|
const format = (cellData.format && normalizedFormats[cellData.format]) || undefined;
|
|
27744
|
-
const cellId = this.
|
|
27793
|
+
const cellId = this.getNextUid();
|
|
27745
27794
|
const properties = { format, style };
|
|
27746
27795
|
return this.createCell(cellId, (cellData === null || cellData === void 0 ? void 0 : cellData.content) || "", properties, sheetId);
|
|
27747
27796
|
}
|
|
@@ -27772,14 +27821,9 @@ class CellPlugin extends CorePlugin {
|
|
|
27772
27821
|
*/
|
|
27773
27822
|
getCellById(cellId) {
|
|
27774
27823
|
// this must be as fast as possible
|
|
27775
|
-
|
|
27776
|
-
|
|
27777
|
-
|
|
27778
|
-
if (cell) {
|
|
27779
|
-
return cell;
|
|
27780
|
-
}
|
|
27781
|
-
}
|
|
27782
|
-
return undefined;
|
|
27824
|
+
const position = this.getters.getCellPosition(cellId);
|
|
27825
|
+
const sheet = this.cells[position.sheetId];
|
|
27826
|
+
return sheet[cellId];
|
|
27783
27827
|
}
|
|
27784
27828
|
/*
|
|
27785
27829
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
@@ -27887,6 +27931,11 @@ class CellPlugin extends CorePlugin {
|
|
|
27887
27931
|
}
|
|
27888
27932
|
return format;
|
|
27889
27933
|
}
|
|
27934
|
+
getNextUid() {
|
|
27935
|
+
const id = this.nextId.toString();
|
|
27936
|
+
this.history.update("nextId", this.nextId + 1);
|
|
27937
|
+
return id;
|
|
27938
|
+
}
|
|
27890
27939
|
updateCell(sheetId, col, row, after) {
|
|
27891
27940
|
var _a;
|
|
27892
27941
|
const before = this.getters.getCell(sheetId, col, row);
|
|
@@ -27925,7 +27974,7 @@ class CellPlugin extends CorePlugin {
|
|
|
27925
27974
|
}
|
|
27926
27975
|
return;
|
|
27927
27976
|
}
|
|
27928
|
-
const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.
|
|
27977
|
+
const cellId = (before === null || before === void 0 ? void 0 : before.id) || this.getNextUid();
|
|
27929
27978
|
const didContentChange = hasContent;
|
|
27930
27979
|
const properties = { format, style };
|
|
27931
27980
|
const cell = this.createCell(cellId, afterContent, properties, sheetId);
|
|
@@ -27939,13 +27988,23 @@ class CellPlugin extends CorePlugin {
|
|
|
27939
27988
|
this.history.update("cells", sheetId, cell.id, cell);
|
|
27940
27989
|
this.dispatch("UPDATE_CELL_POSITION", { cellId: cell.id, col, row, sheetId });
|
|
27941
27990
|
}
|
|
27942
|
-
checkCellOutOfSheet(
|
|
27991
|
+
checkCellOutOfSheet(cmd) {
|
|
27992
|
+
const { sheetId, col, row } = cmd;
|
|
27943
27993
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
27944
27994
|
if (!sheet)
|
|
27945
27995
|
return 27 /* CommandResult.InvalidSheetId */;
|
|
27946
27996
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
27947
27997
|
return isInside(col, row, sheetZone) ? 0 /* CommandResult.Success */ : 18 /* CommandResult.TargetOutOfSheet */;
|
|
27948
27998
|
}
|
|
27999
|
+
checkUselessClearCell(cmd) {
|
|
28000
|
+
const cell = this.getters.getCell(cmd.sheetId, cmd.col, cmd.row);
|
|
28001
|
+
if (!cell)
|
|
28002
|
+
return 87 /* CommandResult.NoChanges */;
|
|
28003
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
28004
|
+
return 87 /* CommandResult.NoChanges */;
|
|
28005
|
+
}
|
|
28006
|
+
return 0 /* CommandResult.Success */;
|
|
28007
|
+
}
|
|
27949
28008
|
}
|
|
27950
28009
|
CellPlugin.getters = [
|
|
27951
28010
|
"zoneToXC",
|
|
@@ -29897,7 +29956,7 @@ class SheetPlugin extends CorePlugin {
|
|
|
29897
29956
|
const elements = cmd.dimension === "COL"
|
|
29898
29957
|
? this.getNumberCols(cmd.sheetId)
|
|
29899
29958
|
: this.getNumberRows(cmd.sheetId);
|
|
29900
|
-
if (cmd.base < 0 || cmd.base
|
|
29959
|
+
if (cmd.base < 0 || cmd.base >= elements) {
|
|
29901
29960
|
return 85 /* CommandResult.InvalidHeaderIndex */;
|
|
29902
29961
|
}
|
|
29903
29962
|
else if (cmd.quantity <= 0) {
|
|
@@ -30510,10 +30569,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
30510
30569
|
// begin with the end.
|
|
30511
30570
|
rows.sort((a, b) => b - a);
|
|
30512
30571
|
for (let group of groupConsecutive(rows)) {
|
|
30572
|
+
// indexes are sorted in the descending order
|
|
30573
|
+
const from = group[group.length - 1];
|
|
30574
|
+
const to = group[0];
|
|
30513
30575
|
// Move the cells.
|
|
30514
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
30515
|
-
// Effectively delete the
|
|
30516
|
-
|
|
30576
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
30577
|
+
// Effectively delete the rows
|
|
30578
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
30517
30579
|
}
|
|
30518
30580
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
30519
30581
|
if (count) {
|
|
@@ -30535,8 +30597,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
30535
30597
|
this.addEmptyRows(sheet, quantity);
|
|
30536
30598
|
// Move the cells.
|
|
30537
30599
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
30538
|
-
// Recompute the left-right/top-bottom.
|
|
30539
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
30540
30600
|
if (index < sheet.panes.ySplit) {
|
|
30541
30601
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
30542
30602
|
}
|
|
@@ -30637,35 +30697,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
30637
30697
|
}
|
|
30638
30698
|
}
|
|
30639
30699
|
}
|
|
30640
|
-
updateRowsStructureOnDeletion(
|
|
30700
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
30641
30701
|
const rows = [];
|
|
30642
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
30702
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
30643
30703
|
for (let i in sheet.rows) {
|
|
30644
|
-
|
|
30704
|
+
const row = Number(i);
|
|
30705
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
30645
30706
|
continue;
|
|
30646
30707
|
}
|
|
30647
30708
|
rows.push({
|
|
30648
|
-
cells: cellsQueue.
|
|
30709
|
+
cells: cellsQueue.pop(),
|
|
30649
30710
|
});
|
|
30650
30711
|
}
|
|
30651
30712
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
30652
30713
|
}
|
|
30653
|
-
/**
|
|
30654
|
-
* Update the rows of the sheet after an addition:
|
|
30655
|
-
* - Rename the rows
|
|
30656
|
-
*
|
|
30657
|
-
* @param sheet Sheet on which the deletion occurs
|
|
30658
|
-
* @param addedRow Index of the added row
|
|
30659
|
-
* @param rowsToAdd Number of the rows to add
|
|
30660
|
-
*/
|
|
30661
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
30662
|
-
const rows = [];
|
|
30663
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
30664
|
-
sheet.rows.forEach(() => rows.push({
|
|
30665
|
-
cells: cellsQueue.shift(),
|
|
30666
|
-
}));
|
|
30667
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
30668
|
-
}
|
|
30669
30714
|
/**
|
|
30670
30715
|
* Add empty rows at the end of the rows
|
|
30671
30716
|
*
|
|
@@ -32532,13 +32577,18 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32532
32577
|
// Getters
|
|
32533
32578
|
// ---------------------------------------------------------------------------
|
|
32534
32579
|
evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
|
|
32535
|
-
|
|
32536
|
-
|
|
32537
|
-
|
|
32538
|
-
|
|
32539
|
-
|
|
32580
|
+
try {
|
|
32581
|
+
const compiledFormula = compile(formulaString);
|
|
32582
|
+
const params = this.getCompilationParameters(() => { });
|
|
32583
|
+
const ranges = [];
|
|
32584
|
+
for (let xc of compiledFormula.dependencies) {
|
|
32585
|
+
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
32586
|
+
}
|
|
32587
|
+
return compiledFormula.execute(ranges, ...params).value;
|
|
32588
|
+
}
|
|
32589
|
+
catch (error) {
|
|
32590
|
+
return error instanceof EvaluationError ? error.errorType : CellErrorType.GenericError;
|
|
32540
32591
|
}
|
|
32541
|
-
return compiledFormula.execute(ranges, ...params).value;
|
|
32542
32592
|
}
|
|
32543
32593
|
/**
|
|
32544
32594
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -32654,6 +32704,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32654
32704
|
}
|
|
32655
32705
|
return cell.evaluated;
|
|
32656
32706
|
}
|
|
32707
|
+
const rangeCache = {};
|
|
32657
32708
|
/**
|
|
32658
32709
|
* Return the values of the cell(s) used in reference, but always in the format of a range even
|
|
32659
32710
|
* if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
|
|
@@ -32670,21 +32721,26 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
32670
32721
|
// Performance issue: Avoid fetching data on positions that are out of the spreadsheet
|
|
32671
32722
|
// e.g. A1:ZZZ9999 in a sheet with 10 cols and 10 rows should ignore everything past J10 and return a 10x10 array
|
|
32672
32723
|
const sheetZone = getters.getSheetZone(sheetId);
|
|
32673
|
-
const result = [];
|
|
32674
32724
|
const zone = intersection(range.zone, sheetZone);
|
|
32675
32725
|
if (!zone) {
|
|
32676
|
-
|
|
32677
|
-
|
|
32726
|
+
return [[]];
|
|
32727
|
+
}
|
|
32728
|
+
const { top, left, bottom, right } = zone;
|
|
32729
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
32730
|
+
if (cacheKey in rangeCache) {
|
|
32731
|
+
return rangeCache[cacheKey];
|
|
32678
32732
|
}
|
|
32733
|
+
const result = new Array(right - left + 1);
|
|
32679
32734
|
// Performance issue: nested loop is faster than a map here
|
|
32680
|
-
for (let col =
|
|
32681
|
-
const rowValues =
|
|
32682
|
-
for (let row =
|
|
32735
|
+
for (let col = left; col <= right; col++) {
|
|
32736
|
+
const rowValues = new Array(bottom - top + 1);
|
|
32737
|
+
for (let row = top; row <= bottom; row++) {
|
|
32683
32738
|
const cell = evalContext.getters.getCell(range.sheetId, col, row);
|
|
32684
|
-
rowValues
|
|
32739
|
+
rowValues[row - top] = cell ? getEvaluatedCell(cell) : undefined;
|
|
32685
32740
|
}
|
|
32686
|
-
result
|
|
32741
|
+
result[col - left] = rowValues;
|
|
32687
32742
|
}
|
|
32743
|
+
rangeCache[cacheKey] = result;
|
|
32688
32744
|
return result;
|
|
32689
32745
|
}
|
|
32690
32746
|
/**
|
|
@@ -32934,39 +32990,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32934
32990
|
this.computedIcons[activeSheetId] = {};
|
|
32935
32991
|
const computedStyle = this.computedStyles[activeSheetId];
|
|
32936
32992
|
for (let cf of this.getters.getConditionalFormats(activeSheetId).reverse()) {
|
|
32937
|
-
|
|
32938
|
-
|
|
32939
|
-
|
|
32940
|
-
|
|
32941
|
-
|
|
32942
|
-
|
|
32943
|
-
|
|
32944
|
-
|
|
32945
|
-
|
|
32946
|
-
|
|
32947
|
-
|
|
32948
|
-
|
|
32949
|
-
|
|
32950
|
-
|
|
32951
|
-
|
|
32952
|
-
for (let
|
|
32953
|
-
|
|
32954
|
-
|
|
32955
|
-
|
|
32956
|
-
if (
|
|
32957
|
-
|
|
32958
|
-
|
|
32959
|
-
|
|
32960
|
-
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32961
|
-
}
|
|
32993
|
+
switch (cf.rule.type) {
|
|
32994
|
+
case "ColorScaleRule":
|
|
32995
|
+
for (let range of cf.ranges) {
|
|
32996
|
+
this.applyColorScale(range, cf.rule);
|
|
32997
|
+
}
|
|
32998
|
+
break;
|
|
32999
|
+
case "IconSetRule":
|
|
33000
|
+
for (let range of cf.ranges) {
|
|
33001
|
+
this.applyIcon(range, cf.rule);
|
|
33002
|
+
}
|
|
33003
|
+
break;
|
|
33004
|
+
default:
|
|
33005
|
+
for (let ref of cf.ranges) {
|
|
33006
|
+
const zone = this.getters.getRangeFromSheetXC(activeSheetId, ref).zone;
|
|
33007
|
+
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
33008
|
+
for (let col = zone.left; col <= zone.right; col++) {
|
|
33009
|
+
const pr = this.rulePredicate[cf.rule.type];
|
|
33010
|
+
let cell = this.getters.getCell(activeSheetId, col, row);
|
|
33011
|
+
if (pr && pr(cell, cf.rule)) {
|
|
33012
|
+
if (!computedStyle[col])
|
|
33013
|
+
computedStyle[col] = [];
|
|
33014
|
+
// we must combine all the properties of all the CF rules applied to the given cell
|
|
33015
|
+
computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
|
|
32962
33016
|
}
|
|
32963
33017
|
}
|
|
32964
33018
|
}
|
|
32965
|
-
|
|
32966
|
-
|
|
32967
|
-
}
|
|
32968
|
-
catch (_) {
|
|
32969
|
-
// we don't care about the errors within the evaluation of a rule
|
|
33019
|
+
}
|
|
33020
|
+
break;
|
|
32970
33021
|
}
|
|
32971
33022
|
}
|
|
32972
33023
|
}
|
|
@@ -32990,7 +33041,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
|
|
|
32990
33041
|
return percentile(rangeValues, Number(threshold.value) / 100, true);
|
|
32991
33042
|
case "formula":
|
|
32992
33043
|
const value = threshold.value && this.getters.evaluateFormula(threshold.value);
|
|
32993
|
-
return
|
|
33044
|
+
return typeof value === "number" ? value : null;
|
|
32994
33045
|
default:
|
|
32995
33046
|
return null;
|
|
32996
33047
|
}
|
|
@@ -34938,7 +34989,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
34938
34989
|
sheetId: cmd.sheetId,
|
|
34939
34990
|
base: cmd.base,
|
|
34940
34991
|
quantity: thickness,
|
|
34941
|
-
position:
|
|
34992
|
+
position: cmd.position,
|
|
34942
34993
|
});
|
|
34943
34994
|
const isCol = cmd.dimension === "COL";
|
|
34944
34995
|
const start = cmd.elements[0];
|
|
@@ -34955,12 +35006,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
34955
35006
|
},
|
|
34956
35007
|
];
|
|
34957
35008
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
35009
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
34958
35010
|
const pasteTarget = [
|
|
34959
35011
|
{
|
|
34960
|
-
left: isCol ?
|
|
34961
|
-
right: isCol ?
|
|
34962
|
-
top: !isCol ?
|
|
34963
|
-
bottom: !isCol ?
|
|
35012
|
+
left: isCol ? base : 0,
|
|
35013
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
35014
|
+
top: !isCol ? base : 0,
|
|
35015
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
34964
35016
|
},
|
|
34965
35017
|
];
|
|
34966
35018
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -34997,6 +35049,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
34997
35049
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
34998
35050
|
return 2 /* CommandResult.WillRemoveExistingMerge */;
|
|
34999
35051
|
}
|
|
35052
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
35053
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
35054
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
35055
|
+
return 85 /* CommandResult.InvalidHeaderIndex */;
|
|
35056
|
+
}
|
|
35000
35057
|
return 0 /* CommandResult.Success */;
|
|
35001
35058
|
}
|
|
35002
35059
|
//-------------------------------------------
|
|
@@ -39063,7 +39120,7 @@ class Spreadsheet extends Component {
|
|
|
39063
39120
|
}
|
|
39064
39121
|
onKeydown(ev) {
|
|
39065
39122
|
let keyDownString = "";
|
|
39066
|
-
if (ev
|
|
39123
|
+
if (isCtrlKey(ev)) {
|
|
39067
39124
|
keyDownString += "CTRL+";
|
|
39068
39125
|
}
|
|
39069
39126
|
keyDownString += ev.key.toUpperCase();
|
|
@@ -39907,9 +39964,9 @@ function revertChanges(revisions) {
|
|
|
39907
39964
|
* Apply the changes of the given HistoryChange to the state
|
|
39908
39965
|
*/
|
|
39909
39966
|
function applyChange(change, target) {
|
|
39910
|
-
let val = change.
|
|
39911
|
-
|
|
39912
|
-
for (let pathIndex =
|
|
39967
|
+
let val = change.path[0];
|
|
39968
|
+
const key = change.path[change.path.length - 1];
|
|
39969
|
+
for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
|
|
39913
39970
|
const p = change.path[pathIndex];
|
|
39914
39971
|
if (val[p] === undefined) {
|
|
39915
39972
|
const nextPath = change.path[pathIndex + 1];
|
|
@@ -41039,13 +41096,14 @@ class StateObserver {
|
|
|
41039
41096
|
}
|
|
41040
41097
|
addChange(...args) {
|
|
41041
41098
|
const val = args.pop();
|
|
41042
|
-
const
|
|
41099
|
+
const root = args[0];
|
|
41043
41100
|
let value = root;
|
|
41044
|
-
let key =
|
|
41045
|
-
|
|
41046
|
-
|
|
41101
|
+
let key = args[args.length - 1];
|
|
41102
|
+
const pathLength = args.length - 2;
|
|
41103
|
+
for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
|
|
41104
|
+
const p = args[pathIndex];
|
|
41047
41105
|
if (value[p] === undefined) {
|
|
41048
|
-
const nextPath =
|
|
41106
|
+
const nextPath = args[pathIndex + 1];
|
|
41049
41107
|
value[p] = createEmptyStructure(nextPath);
|
|
41050
41108
|
}
|
|
41051
41109
|
value = value[p];
|
|
@@ -41054,8 +41112,7 @@ class StateObserver {
|
|
|
41054
41112
|
return;
|
|
41055
41113
|
}
|
|
41056
41114
|
this.changes.push({
|
|
41057
|
-
|
|
41058
|
-
path,
|
|
41115
|
+
path: args,
|
|
41059
41116
|
before: value[key],
|
|
41060
41117
|
after: val,
|
|
41061
41118
|
});
|
|
@@ -42789,7 +42846,10 @@ class Model extends EventBus {
|
|
|
42789
42846
|
*/
|
|
42790
42847
|
checkDispatchAllowed(command) {
|
|
42791
42848
|
const results = this.handlers.map((handler) => handler.allowDispatch(command));
|
|
42792
|
-
|
|
42849
|
+
if (results.some((r) => r !== 0 /* CommandResult.Success */)) {
|
|
42850
|
+
return new DispatchResult(results.flat());
|
|
42851
|
+
}
|
|
42852
|
+
return DispatchResult.Success;
|
|
42793
42853
|
}
|
|
42794
42854
|
finalize() {
|
|
42795
42855
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -42979,6 +43039,6 @@ function addFunction(functionName, functionDescription) {
|
|
|
42979
43039
|
export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
|
|
42980
43040
|
|
|
42981
43041
|
|
|
42982
|
-
__info__.version = '16.0.
|
|
42983
|
-
__info__.date = '
|
|
42984
|
-
__info__.hash = '
|
|
43042
|
+
__info__.version = '16.0.27';
|
|
43043
|
+
__info__.date = '2024-01-04T12:19:11.487Z';
|
|
43044
|
+
__info__.hash = '54006f6';
|