@odoo/o-spreadsheet 17.0.3 → 17.0.5
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 +276 -207
- package/dist/o-spreadsheet.d.ts +16 -20
- package/dist/o-spreadsheet.esm.js +276 -207
- package/dist/o-spreadsheet.iife.js +276 -207
- package/dist/o-spreadsheet.iife.min.js +284 -286
- package/dist/o_spreadsheet.xml +7 -8
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 17.0.
|
|
6
|
-
* @date 2023-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 17.0.5
|
|
6
|
+
* @date 2023-12-05T09:51:44.657Z
|
|
7
|
+
* @hash 2480a5d
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
|
|
@@ -691,8 +691,7 @@ function removeFalsyAttributes(obj) {
|
|
|
691
691
|
*
|
|
692
692
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
|
|
693
693
|
*/
|
|
694
|
-
const
|
|
695
|
-
" ",
|
|
694
|
+
const whiteSpaceSpecialCharacters = [
|
|
696
695
|
"\t",
|
|
697
696
|
"\f",
|
|
698
697
|
"\v",
|
|
@@ -707,8 +706,7 @@ const whiteSpaceCharacters = [
|
|
|
707
706
|
String.fromCharCode(parseInt("3000", 16)),
|
|
708
707
|
String.fromCharCode(parseInt("feff", 16)),
|
|
709
708
|
];
|
|
710
|
-
const whiteSpaceRegexp = new RegExp(
|
|
711
|
-
const newLineRegex = /\r\n|\r|\n/g;
|
|
709
|
+
const whiteSpaceRegexp = new RegExp(whiteSpaceSpecialCharacters.join("|") + "|(\r\n|\r|\n)", "g");
|
|
712
710
|
/**
|
|
713
711
|
* Replace all the special spaces in a string (non-breaking, tabs, ...) by normal spaces, and all the
|
|
714
712
|
* different newlines types by \n.
|
|
@@ -716,9 +714,9 @@ const newLineRegex = /\r\n|\r|\n/g;
|
|
|
716
714
|
function replaceSpecialSpaces(text) {
|
|
717
715
|
if (!text)
|
|
718
716
|
return "";
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
return text;
|
|
717
|
+
if (!whiteSpaceRegexp.test(text))
|
|
718
|
+
return text;
|
|
719
|
+
return text.replace(whiteSpaceRegexp, (match, newLine) => (newLine ? NEWLINE : " "));
|
|
722
720
|
}
|
|
723
721
|
/**
|
|
724
722
|
* Determine if the numbers are consecutive.
|
|
@@ -2060,6 +2058,7 @@ var CommandResult;
|
|
|
2060
2058
|
CommandResult["InvalidNumberOfCriterionValues"] = "InvalidNumberOfCriterionValues";
|
|
2061
2059
|
CommandResult["BlockingValidationRule"] = "BlockingValidationRule";
|
|
2062
2060
|
CommandResult["InvalidCopyPasteSelection"] = "InvalidCopyPasteSelection";
|
|
2061
|
+
CommandResult["NoChanges"] = "NoChanges";
|
|
2063
2062
|
})(CommandResult || (CommandResult = {}));
|
|
2064
2063
|
|
|
2065
2064
|
const DEFAULT_LOCALES = [
|
|
@@ -2189,12 +2188,12 @@ function toString(value) {
|
|
|
2189
2188
|
}
|
|
2190
2189
|
}
|
|
2191
2190
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
2192
|
-
function normalizeString(str) {
|
|
2191
|
+
const normalizeString = memoize(function normalizeString(str) {
|
|
2193
2192
|
return str
|
|
2194
2193
|
.toLowerCase()
|
|
2195
2194
|
.normalize("NFD")
|
|
2196
2195
|
.replace(/[\u0300-\u036f]/g, "");
|
|
2197
|
-
}
|
|
2196
|
+
});
|
|
2198
2197
|
const expectBooleanValueError = (value) => _t("The function [[FUNCTION_NAME]] expects a boolean value, but '%s' is a text, and cannot be coerced to a number.", value);
|
|
2199
2198
|
function toBoolean(value) {
|
|
2200
2199
|
switch (typeof value) {
|
|
@@ -3388,8 +3387,10 @@ function convertInternalFormatToFormat(internalFormat) {
|
|
|
3388
3387
|
const cellReference = new RegExp(/\$?([A-Z]{1,3})\$?([0-9]{1,7})/, "i");
|
|
3389
3388
|
// Same as above, but matches the exact string (nothing before or after)
|
|
3390
3389
|
const singleCellReference = new RegExp(/^\$?([A-Z]{1,3})\$?([0-9]{1,7})$/, "i");
|
|
3391
|
-
/** Reference of a column header (eg. A, AB) */
|
|
3392
|
-
const colHeader = new RegExp(
|
|
3390
|
+
/** Reference of a column header (eg. A, AB, $A) */
|
|
3391
|
+
const colHeader = new RegExp(/^\$?([A-Z]{1,3})+$/, "i");
|
|
3392
|
+
/** Reference of a row header (eg. 1, $1) */
|
|
3393
|
+
const rowHeader = new RegExp(/^\$?([0-9]{1,7})+$/, "i");
|
|
3393
3394
|
/** Reference of a column (eg. A, $CA, Sheet1!B) */
|
|
3394
3395
|
const colReference = new RegExp(/^\s*('.+'!|[^']+!)?\$?([A-Z]{1,3})$/, "i");
|
|
3395
3396
|
/** Reference of a row (eg. 1, 59, Sheet1!9) */
|
|
@@ -3419,6 +3420,9 @@ function isRowReference(xc) {
|
|
|
3419
3420
|
function isColHeader(str) {
|
|
3420
3421
|
return colHeader.test(str);
|
|
3421
3422
|
}
|
|
3423
|
+
function isRowHeader(str) {
|
|
3424
|
+
return rowHeader.test(str);
|
|
3425
|
+
}
|
|
3422
3426
|
/**
|
|
3423
3427
|
* Return true if the given xc is the reference of a single cell,
|
|
3424
3428
|
* without any specified sheet (e.g. A1)
|
|
@@ -4102,18 +4106,10 @@ class RangeImpl {
|
|
|
4102
4106
|
if (isFullCol) {
|
|
4103
4107
|
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4104
4108
|
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4105
|
-
if (zone.left === zone.right) {
|
|
4106
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4107
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4108
|
-
}
|
|
4109
4109
|
}
|
|
4110
4110
|
if (isFullRow) {
|
|
4111
4111
|
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4112
4112
|
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
4113
|
-
if (zone.top === zone.bottom) {
|
|
4114
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4115
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
4116
|
-
}
|
|
4117
4113
|
}
|
|
4118
4114
|
return parts;
|
|
4119
4115
|
}
|
|
@@ -4355,7 +4351,7 @@ function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
|
|
|
4355
4351
|
function getDefaultCellHeight(ctx, cell, colSize) {
|
|
4356
4352
|
if (!cell || !cell.content)
|
|
4357
4353
|
return DEFAULT_CELL_HEIGHT;
|
|
4358
|
-
const maxWidth = cell.style?.wrapping ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
|
|
4354
|
+
const maxWidth = cell.style?.wrapping === "wrap" ? colSize - 2 * MIN_CELL_TEXT_MARGIN : undefined;
|
|
4359
4355
|
const numberOfLines = cell.isFormula
|
|
4360
4356
|
? 1
|
|
4361
4357
|
: splitTextToWidth(ctx, cell.content, cell.style, maxWidth).length;
|
|
@@ -6250,10 +6246,6 @@ css /* scss */ `
|
|
|
6250
6246
|
|
|
6251
6247
|
.o-error-tooltip-message {
|
|
6252
6248
|
overflow: hidden;
|
|
6253
|
-
display: -webkit-box; /* Limit to 3 lines */
|
|
6254
|
-
-webkit-line-clamp: 3;
|
|
6255
|
-
line-clamp: 3;
|
|
6256
|
-
-webkit-box-orient: vertical;
|
|
6257
6249
|
}
|
|
6258
6250
|
}
|
|
6259
6251
|
`;
|
|
@@ -6636,6 +6628,9 @@ function* iterateChildren(el) {
|
|
|
6636
6628
|
function getOpenedMenus() {
|
|
6637
6629
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
6638
6630
|
}
|
|
6631
|
+
function isMacOS() {
|
|
6632
|
+
return navigator.userAgent.toUpperCase().indexOf("MAC") >= 0;
|
|
6633
|
+
}
|
|
6639
6634
|
|
|
6640
6635
|
/**
|
|
6641
6636
|
* Return the o-spreadsheet element position relative
|
|
@@ -7329,7 +7324,7 @@ function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
|
7329
7324
|
return result;
|
|
7330
7325
|
}
|
|
7331
7326
|
function tokenizeDebugger(chars) {
|
|
7332
|
-
if (chars.current
|
|
7327
|
+
if (chars.current === "?") {
|
|
7333
7328
|
chars.shift();
|
|
7334
7329
|
return { type: "DEBUGGER", value: "?" };
|
|
7335
7330
|
}
|
|
@@ -7340,7 +7335,7 @@ const misc$1 = {
|
|
|
7340
7335
|
")": "RIGHT_PAREN",
|
|
7341
7336
|
};
|
|
7342
7337
|
function tokenizeMisc(chars) {
|
|
7343
|
-
if (chars.current
|
|
7338
|
+
if (chars.current in misc$1) {
|
|
7344
7339
|
const value = chars.shift();
|
|
7345
7340
|
const type = misc$1[value];
|
|
7346
7341
|
return { type, value };
|
|
@@ -7348,7 +7343,7 @@ function tokenizeMisc(chars) {
|
|
|
7348
7343
|
return null;
|
|
7349
7344
|
}
|
|
7350
7345
|
function tokenizeArgsSeparator(chars, locale) {
|
|
7351
|
-
if (chars.current
|
|
7346
|
+
if (chars.current === locale.formulaArgSeparator) {
|
|
7352
7347
|
const value = chars.shift();
|
|
7353
7348
|
const type = "ARG_SEPARATOR";
|
|
7354
7349
|
return { type, value };
|
|
@@ -7373,14 +7368,13 @@ function tokenizeNumber(chars, locale) {
|
|
|
7373
7368
|
return null;
|
|
7374
7369
|
}
|
|
7375
7370
|
function tokenizeString(chars) {
|
|
7376
|
-
if (chars.current
|
|
7371
|
+
if (chars.current === '"') {
|
|
7377
7372
|
const startChar = chars.shift();
|
|
7378
7373
|
let letters = startChar;
|
|
7379
|
-
while (chars.current()
|
|
7380
|
-
(chars.current() !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7374
|
+
while (chars.current && (chars.current !== startChar || letters[letters.length - 1] === "\\")) {
|
|
7381
7375
|
letters += chars.shift();
|
|
7382
7376
|
}
|
|
7383
|
-
if (chars.current
|
|
7377
|
+
if (chars.current === '"') {
|
|
7384
7378
|
letters += chars.shift();
|
|
7385
7379
|
}
|
|
7386
7380
|
return {
|
|
@@ -7407,14 +7401,14 @@ function tokenizeSymbol(chars) {
|
|
|
7407
7401
|
let result = "";
|
|
7408
7402
|
// there are two main cases to manage: either something which starts with
|
|
7409
7403
|
// a ', like 'Sheet 2'A2, or a word-like element.
|
|
7410
|
-
if (chars.current
|
|
7404
|
+
if (chars.current === "'") {
|
|
7411
7405
|
let lastChar = chars.shift();
|
|
7412
7406
|
result += lastChar;
|
|
7413
|
-
while (chars.current
|
|
7407
|
+
while (chars.current) {
|
|
7414
7408
|
lastChar = chars.shift();
|
|
7415
7409
|
result += lastChar;
|
|
7416
7410
|
if (lastChar === "'") {
|
|
7417
|
-
if (chars.current
|
|
7411
|
+
if (chars.current && chars.current === "'") {
|
|
7418
7412
|
lastChar = chars.shift();
|
|
7419
7413
|
result += lastChar;
|
|
7420
7414
|
}
|
|
@@ -7430,7 +7424,7 @@ function tokenizeSymbol(chars) {
|
|
|
7430
7424
|
};
|
|
7431
7425
|
}
|
|
7432
7426
|
}
|
|
7433
|
-
while (chars.current
|
|
7427
|
+
while (chars.current && separatorRegexp.test(chars.current)) {
|
|
7434
7428
|
result += chars.shift();
|
|
7435
7429
|
}
|
|
7436
7430
|
if (result.length) {
|
|
@@ -7445,14 +7439,14 @@ function tokenizeSymbol(chars) {
|
|
|
7445
7439
|
}
|
|
7446
7440
|
function tokenizeSpace(chars) {
|
|
7447
7441
|
let length = 0;
|
|
7448
|
-
while (chars.current
|
|
7442
|
+
while (chars.current === NEWLINE) {
|
|
7449
7443
|
length++;
|
|
7450
7444
|
chars.shift();
|
|
7451
7445
|
}
|
|
7452
7446
|
if (length) {
|
|
7453
7447
|
return { type: "SPACE", value: NEWLINE.repeat(length) };
|
|
7454
7448
|
}
|
|
7455
|
-
while (chars.current
|
|
7449
|
+
while (chars.current === " ") {
|
|
7456
7450
|
length++;
|
|
7457
7451
|
chars.shift();
|
|
7458
7452
|
}
|
|
@@ -7471,17 +7465,20 @@ function tokenizeInvalidRange(chars) {
|
|
|
7471
7465
|
class TokenizingChars {
|
|
7472
7466
|
text;
|
|
7473
7467
|
currentIndex = 0;
|
|
7468
|
+
current;
|
|
7474
7469
|
constructor(text) {
|
|
7475
7470
|
this.text = text;
|
|
7476
|
-
|
|
7477
|
-
current() {
|
|
7478
|
-
return this.text[this.currentIndex];
|
|
7471
|
+
this.current = text[0];
|
|
7479
7472
|
}
|
|
7480
7473
|
shift() {
|
|
7481
|
-
|
|
7474
|
+
const current = this.current;
|
|
7475
|
+
const next = this.text[++this.currentIndex];
|
|
7476
|
+
this.current = next;
|
|
7477
|
+
return current;
|
|
7482
7478
|
}
|
|
7483
7479
|
advanceBy(length) {
|
|
7484
7480
|
this.currentIndex += length;
|
|
7481
|
+
this.current = this.text[this.currentIndex];
|
|
7485
7482
|
}
|
|
7486
7483
|
isOver() {
|
|
7487
7484
|
return this.currentIndex >= this.text.length;
|
|
@@ -28278,6 +28275,7 @@ class AbstractResizer extends Component {
|
|
|
28278
28275
|
draggerShadowThickness: 0,
|
|
28279
28276
|
delta: 0,
|
|
28280
28277
|
base: 0,
|
|
28278
|
+
position: "before",
|
|
28281
28279
|
});
|
|
28282
28280
|
_computeHandleDisplay(ev) {
|
|
28283
28281
|
const position = this._getEvOffset(ev);
|
|
@@ -28402,11 +28400,13 @@ class AbstractResizer extends Component {
|
|
|
28402
28400
|
this.state.draggerLinePosition = dimensions.start;
|
|
28403
28401
|
this.state.draggerShadowPosition = dimensions.start;
|
|
28404
28402
|
this.state.base = elementIndex;
|
|
28403
|
+
this.state.position = "before";
|
|
28405
28404
|
}
|
|
28406
28405
|
else if (this._getSelectedZoneEnd() < elementIndex) {
|
|
28407
28406
|
this.state.draggerLinePosition = dimensions.end;
|
|
28408
28407
|
this.state.draggerShadowPosition = dimensions.end - this.state.draggerShadowThickness;
|
|
28409
|
-
this.state.base = elementIndex
|
|
28408
|
+
this.state.base = elementIndex;
|
|
28409
|
+
this.state.position = "after";
|
|
28410
28410
|
}
|
|
28411
28411
|
else {
|
|
28412
28412
|
this.state.draggerLinePosition = startDimensions.start;
|
|
@@ -28588,6 +28588,7 @@ class ColResizer extends AbstractResizer {
|
|
|
28588
28588
|
dimension: "COL",
|
|
28589
28589
|
base: this.state.base,
|
|
28590
28590
|
elements,
|
|
28591
|
+
position: this.state.position,
|
|
28591
28592
|
});
|
|
28592
28593
|
if (!result.isSuccessful && result.reasons.includes("WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */)) {
|
|
28593
28594
|
this.env.raiseError(MergeErrorMessage);
|
|
@@ -28761,6 +28762,7 @@ class RowResizer extends AbstractResizer {
|
|
|
28761
28762
|
dimension: "ROW",
|
|
28762
28763
|
base: this.state.base,
|
|
28763
28764
|
elements,
|
|
28765
|
+
position: this.state.position,
|
|
28764
28766
|
});
|
|
28765
28767
|
if (!result.isSuccessful && result.reasons.includes("WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */)) {
|
|
28766
28768
|
this.env.raiseError(MergeErrorMessage);
|
|
@@ -28868,8 +28870,8 @@ function useWheelHandler(handler) {
|
|
|
28868
28870
|
return val * (deltaMode === 0 ? 1 : DEFAULT_CELL_HEIGHT);
|
|
28869
28871
|
}
|
|
28870
28872
|
const onMouseWheel = (ev) => {
|
|
28871
|
-
const deltaX = normalize(ev.shiftKey ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
28872
|
-
const deltaY = normalize(ev.shiftKey ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
28873
|
+
const deltaX = normalize(ev.shiftKey && !isMacOS() ? ev.deltaY : ev.deltaX, ev.deltaMode);
|
|
28874
|
+
const deltaY = normalize(ev.shiftKey && !isMacOS() ? ev.deltaX : ev.deltaY, ev.deltaMode);
|
|
28873
28875
|
handler(deltaX, deltaY);
|
|
28874
28876
|
};
|
|
28875
28877
|
return onMouseWheel;
|
|
@@ -29757,6 +29759,7 @@ class Grid extends Component {
|
|
|
29757
29759
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
29758
29760
|
const target = this.env.model.getters.getSelectedZones();
|
|
29759
29761
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
29762
|
+
const isCutOperation = this.env.model.getters.isCutOperation();
|
|
29760
29763
|
if (clipboardString === content) {
|
|
29761
29764
|
// the paste actually comes from o-spreadsheet itself
|
|
29762
29765
|
interactivePaste(this.env, target);
|
|
@@ -29764,7 +29767,7 @@ class Grid extends Component {
|
|
|
29764
29767
|
else {
|
|
29765
29768
|
interactivePasteFromOS(this.env, target, content);
|
|
29766
29769
|
}
|
|
29767
|
-
if (
|
|
29770
|
+
if (isCutOperation) {
|
|
29768
29771
|
await this.env.clipboard.write({ [ClipboardMIMEType.PlainText]: "" });
|
|
29769
29772
|
}
|
|
29770
29773
|
}
|
|
@@ -33322,7 +33325,7 @@ const machine = {
|
|
|
33322
33325
|
SPACE: goTo(State.RightRef),
|
|
33323
33326
|
NUMBER: goTo(State.Found),
|
|
33324
33327
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
33325
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
33328
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
33326
33329
|
},
|
|
33327
33330
|
[State.RightColumnRef]: {
|
|
33328
33331
|
SPACE: goTo(State.RightColumnRef),
|
|
@@ -33333,6 +33336,7 @@ const machine = {
|
|
|
33333
33336
|
SPACE: goTo(State.RightRowRef),
|
|
33334
33337
|
NUMBER: goTo(State.Found),
|
|
33335
33338
|
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
33339
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
33336
33340
|
},
|
|
33337
33341
|
[State.Found]: {},
|
|
33338
33342
|
};
|
|
@@ -34058,6 +34062,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34058
34062
|
// ---------------------------------------------------------------------------
|
|
34059
34063
|
// Command Handling
|
|
34060
34064
|
// ---------------------------------------------------------------------------
|
|
34065
|
+
allowDispatch(cmd) {
|
|
34066
|
+
switch (cmd.type) {
|
|
34067
|
+
case "SET_BORDER":
|
|
34068
|
+
return this.checkBordersUnchanged(cmd);
|
|
34069
|
+
default:
|
|
34070
|
+
return "Success" /* CommandResult.Success */;
|
|
34071
|
+
}
|
|
34072
|
+
}
|
|
34061
34073
|
handle(cmd) {
|
|
34062
34074
|
switch (cmd.type) {
|
|
34063
34075
|
case "ADD_MERGE":
|
|
@@ -34477,6 +34489,14 @@ class BordersPlugin extends CorePlugin {
|
|
|
34477
34489
|
this.setBorders(sheetId, [{ ...zone, left: right }], "right", bordersTopLeft.right);
|
|
34478
34490
|
}
|
|
34479
34491
|
}
|
|
34492
|
+
checkBordersUnchanged(cmd) {
|
|
34493
|
+
const currentBorder = this.getCellBorder(cmd);
|
|
34494
|
+
const areAllNewBordersUndefined = !cmd.border?.bottom && !cmd.border?.left && !cmd.border?.right && !cmd.border?.top;
|
|
34495
|
+
if ((!currentBorder && areAllNewBordersUndefined) || deepEquals(currentBorder, cmd.border)) {
|
|
34496
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
34497
|
+
}
|
|
34498
|
+
return "Success" /* CommandResult.Success */;
|
|
34499
|
+
}
|
|
34480
34500
|
// ---------------------------------------------------------------------------
|
|
34481
34501
|
// Import/Export
|
|
34482
34502
|
// ---------------------------------------------------------------------------
|
|
@@ -35332,8 +35352,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35332
35352
|
allowDispatch(cmd) {
|
|
35333
35353
|
switch (cmd.type) {
|
|
35334
35354
|
case "UPDATE_CELL":
|
|
35355
|
+
return this.checkCellOutOfSheet(cmd);
|
|
35335
35356
|
case "CLEAR_CELL":
|
|
35336
|
-
return this.
|
|
35357
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkCellOutOfSheet, this.checkUselessClearCell));
|
|
35337
35358
|
default:
|
|
35338
35359
|
return "Success" /* CommandResult.Success */;
|
|
35339
35360
|
}
|
|
@@ -35502,14 +35523,9 @@ class CellPlugin extends CorePlugin {
|
|
|
35502
35523
|
*/
|
|
35503
35524
|
getCellById(cellId) {
|
|
35504
35525
|
// this must be as fast as possible
|
|
35505
|
-
|
|
35506
|
-
|
|
35507
|
-
|
|
35508
|
-
if (cell) {
|
|
35509
|
-
return cell;
|
|
35510
|
-
}
|
|
35511
|
-
}
|
|
35512
|
-
return undefined;
|
|
35526
|
+
const position = this.getters.getCellPosition(cellId);
|
|
35527
|
+
const sheet = this.cells[position.sheetId];
|
|
35528
|
+
return sheet[cellId];
|
|
35513
35529
|
}
|
|
35514
35530
|
/*
|
|
35515
35531
|
* Reconstructs the original formula string based on a normalized form and its dependencies
|
|
@@ -35740,13 +35756,23 @@ class CellPlugin extends CorePlugin {
|
|
|
35740
35756
|
},
|
|
35741
35757
|
};
|
|
35742
35758
|
}
|
|
35743
|
-
checkCellOutOfSheet(
|
|
35759
|
+
checkCellOutOfSheet(cmd) {
|
|
35760
|
+
const { sheetId, col, row } = cmd;
|
|
35744
35761
|
const sheet = this.getters.tryGetSheet(sheetId);
|
|
35745
35762
|
if (!sheet)
|
|
35746
35763
|
return "InvalidSheetId" /* CommandResult.InvalidSheetId */;
|
|
35747
35764
|
const sheetZone = this.getters.getSheetZone(sheetId);
|
|
35748
35765
|
return isInside(col, row, sheetZone) ? "Success" /* CommandResult.Success */ : "TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */;
|
|
35749
35766
|
}
|
|
35767
|
+
checkUselessClearCell(cmd) {
|
|
35768
|
+
const cell = this.getters.getCell(cmd);
|
|
35769
|
+
if (!cell)
|
|
35770
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35771
|
+
if (!cell.content && !cell.style && !cell.format) {
|
|
35772
|
+
return "NoChanges" /* CommandResult.NoChanges */;
|
|
35773
|
+
}
|
|
35774
|
+
return "Success" /* CommandResult.Success */;
|
|
35775
|
+
}
|
|
35750
35776
|
}
|
|
35751
35777
|
class FormulaCellWithDependencies {
|
|
35752
35778
|
id;
|
|
@@ -36436,6 +36462,9 @@ class DataValidationPlugin extends CorePlugin {
|
|
|
36436
36462
|
return this.rules[sheetId].find((rule) => rule.id === id);
|
|
36437
36463
|
}
|
|
36438
36464
|
getValidationRuleForCell({ sheetId, col, row }) {
|
|
36465
|
+
if (!this.rules[sheetId]) {
|
|
36466
|
+
return undefined;
|
|
36467
|
+
}
|
|
36439
36468
|
for (const rule of this.rules[sheetId]) {
|
|
36440
36469
|
for (const range of rule.ranges) {
|
|
36441
36470
|
if (isInside(col, row, range.zone)) {
|
|
@@ -37289,7 +37318,16 @@ class HeaderVisibilityPlugin extends CorePlugin {
|
|
|
37289
37318
|
return consecutiveIndexes;
|
|
37290
37319
|
}
|
|
37291
37320
|
getAllVisibleHeaders(sheetId, dimension) {
|
|
37292
|
-
|
|
37321
|
+
const headers = range(0, this.getters.getNumberHeaders(sheetId, dimension));
|
|
37322
|
+
const foldedHeaders = [];
|
|
37323
|
+
this.getters.getHeaderGroups(sheetId, dimension).forEach((group) => {
|
|
37324
|
+
if (group.isFolded) {
|
|
37325
|
+
foldedHeaders.push(...range(group.start, group.end + 1));
|
|
37326
|
+
}
|
|
37327
|
+
});
|
|
37328
|
+
return headers.filter((i) => {
|
|
37329
|
+
return !this.hiddenHeaders[sheetId][dimension][i] && !foldedHeaders.includes(i);
|
|
37330
|
+
});
|
|
37293
37331
|
}
|
|
37294
37332
|
import(data) {
|
|
37295
37333
|
for (let sheet of data.sheets) {
|
|
@@ -39033,10 +39071,13 @@ class SheetPlugin extends CorePlugin {
|
|
|
39033
39071
|
// begin with the end.
|
|
39034
39072
|
rows.sort((a, b) => b - a);
|
|
39035
39073
|
for (let group of groupConsecutive(rows)) {
|
|
39074
|
+
// indexes are sorted in the descending order
|
|
39075
|
+
const from = group[group.length - 1];
|
|
39076
|
+
const to = group[0];
|
|
39036
39077
|
// Move the cells.
|
|
39037
|
-
this.moveCellOnRowsDeletion(sheet,
|
|
39038
|
-
// Effectively delete the
|
|
39039
|
-
|
|
39078
|
+
this.moveCellOnRowsDeletion(sheet, from, to);
|
|
39079
|
+
// Effectively delete the rows
|
|
39080
|
+
this.updateRowsStructureOnDeletion(sheet, from, to);
|
|
39040
39081
|
}
|
|
39041
39082
|
const count = rows.filter((row) => row < sheet.panes.ySplit).length;
|
|
39042
39083
|
if (count) {
|
|
@@ -39058,8 +39099,6 @@ class SheetPlugin extends CorePlugin {
|
|
|
39058
39099
|
this.addEmptyRows(sheet, quantity);
|
|
39059
39100
|
// Move the cells.
|
|
39060
39101
|
this.moveCellsOnAddition(sheet, index, quantity, "rows");
|
|
39061
|
-
// Recompute the left-right/top-bottom.
|
|
39062
|
-
this.updateRowsStructureOnAddition(sheet, row, quantity);
|
|
39063
39102
|
if (index < sheet.panes.ySplit) {
|
|
39064
39103
|
this.setPaneDivisions(sheet.id, sheet.panes.ySplit + quantity, "ROW");
|
|
39065
39104
|
}
|
|
@@ -39160,35 +39199,20 @@ class SheetPlugin extends CorePlugin {
|
|
|
39160
39199
|
}
|
|
39161
39200
|
}
|
|
39162
39201
|
}
|
|
39163
|
-
updateRowsStructureOnDeletion(
|
|
39202
|
+
updateRowsStructureOnDeletion(sheet, deleteFromRow, deleteToRow) {
|
|
39164
39203
|
const rows = [];
|
|
39165
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39204
|
+
const cellsQueue = sheet.rows.map((row) => row.cells).reverse();
|
|
39166
39205
|
for (let i in sheet.rows) {
|
|
39167
|
-
|
|
39206
|
+
const row = Number(i);
|
|
39207
|
+
if (row >= deleteFromRow && row <= deleteToRow) {
|
|
39168
39208
|
continue;
|
|
39169
39209
|
}
|
|
39170
39210
|
rows.push({
|
|
39171
|
-
cells: cellsQueue.
|
|
39211
|
+
cells: cellsQueue.pop(),
|
|
39172
39212
|
});
|
|
39173
39213
|
}
|
|
39174
39214
|
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39175
39215
|
}
|
|
39176
|
-
/**
|
|
39177
|
-
* Update the rows of the sheet after an addition:
|
|
39178
|
-
* - Rename the rows
|
|
39179
|
-
*
|
|
39180
|
-
* @param sheet Sheet on which the deletion occurs
|
|
39181
|
-
* @param addedRow Index of the added row
|
|
39182
|
-
* @param rowsToAdd Number of the rows to add
|
|
39183
|
-
*/
|
|
39184
|
-
updateRowsStructureOnAddition(sheet, addedRow, rowsToAdd) {
|
|
39185
|
-
const rows = [];
|
|
39186
|
-
const cellsQueue = sheet.rows.map((row) => row.cells);
|
|
39187
|
-
sheet.rows.forEach(() => rows.push({
|
|
39188
|
-
cells: cellsQueue.shift(),
|
|
39189
|
-
}));
|
|
39190
|
-
this.history.update("sheets", sheet.id, "rows", rows);
|
|
39191
|
-
}
|
|
39192
39216
|
/**
|
|
39193
39217
|
* Add empty rows at the end of the rows
|
|
39194
39218
|
*
|
|
@@ -39715,6 +39739,7 @@ class CompilationParametersBuilder {
|
|
|
39715
39739
|
getters;
|
|
39716
39740
|
computeCell;
|
|
39717
39741
|
evalContext;
|
|
39742
|
+
rangeCache = {};
|
|
39718
39743
|
constructor(context, getters, computeCell) {
|
|
39719
39744
|
this.getters = getters;
|
|
39720
39745
|
this.computeCell = computeCell;
|
|
@@ -39762,10 +39787,13 @@ class CompilationParametersBuilder {
|
|
|
39762
39787
|
if (evaluatedCell === undefined) {
|
|
39763
39788
|
return { value: null, format: this.getters.getCell(position)?.format };
|
|
39764
39789
|
}
|
|
39790
|
+
if (evaluatedCell.type === CellValueType.error) {
|
|
39791
|
+
throw evaluatedCell.error;
|
|
39792
|
+
}
|
|
39765
39793
|
return evaluatedCell;
|
|
39766
39794
|
}
|
|
39767
39795
|
getEvaluatedCellIfNotEmpty(position) {
|
|
39768
|
-
const evaluatedCell = this.
|
|
39796
|
+
const evaluatedCell = this.computeCell(position);
|
|
39769
39797
|
if (evaluatedCell.type === CellValueType.empty) {
|
|
39770
39798
|
const cell = this.getters.getCell(position);
|
|
39771
39799
|
if (!cell || (!cell.isFormula && cell.content === "")) {
|
|
@@ -39774,13 +39802,6 @@ class CompilationParametersBuilder {
|
|
|
39774
39802
|
}
|
|
39775
39803
|
return evaluatedCell;
|
|
39776
39804
|
}
|
|
39777
|
-
getEvaluatedCell(position) {
|
|
39778
|
-
const evaluatedCell = this.computeCell(position);
|
|
39779
|
-
if (evaluatedCell.type === CellValueType.error) {
|
|
39780
|
-
throw evaluatedCell.error;
|
|
39781
|
-
}
|
|
39782
|
-
return evaluatedCell;
|
|
39783
|
-
}
|
|
39784
39805
|
/**
|
|
39785
39806
|
* Return the values of the cell(s) used in reference, but always in the format of a range even
|
|
39786
39807
|
* if a single cell is referenced. It is a list of col values. This is useful for the formulas that describe parameters as
|
|
@@ -39800,17 +39821,33 @@ class CompilationParametersBuilder {
|
|
|
39800
39821
|
if (!_zone) {
|
|
39801
39822
|
return [[]];
|
|
39802
39823
|
}
|
|
39824
|
+
const { top, left, bottom, right } = zone;
|
|
39825
|
+
const cacheKey = `${sheetId}-${top}-${left}-${bottom}-${right}`;
|
|
39826
|
+
if (cacheKey in this.rangeCache) {
|
|
39827
|
+
const result = this.rangeCache[cacheKey];
|
|
39828
|
+
if (result instanceof EvaluationError) {
|
|
39829
|
+
throw result;
|
|
39830
|
+
}
|
|
39831
|
+
return result;
|
|
39832
|
+
}
|
|
39803
39833
|
const height = _zone.bottom - _zone.top + 1;
|
|
39804
39834
|
const width = _zone.right - _zone.left + 1;
|
|
39805
|
-
const matrix = Array
|
|
39835
|
+
const matrix = new Array(width);
|
|
39806
39836
|
// Performance issue: nested loop is faster than a map here
|
|
39807
39837
|
for (let col = _zone.left; col <= _zone.right; col++) {
|
|
39838
|
+
const colIndex = col - _zone.left;
|
|
39839
|
+
matrix[colIndex] = new Array(height);
|
|
39808
39840
|
for (let row = _zone.top; row <= _zone.bottom; row++) {
|
|
39809
|
-
const
|
|
39841
|
+
const evaluatedCell = this.getEvaluatedCellIfNotEmpty({ sheetId, col, row });
|
|
39842
|
+
if (evaluatedCell?.type === CellValueType.error) {
|
|
39843
|
+
this.rangeCache[cacheKey] = evaluatedCell.error;
|
|
39844
|
+
throw evaluatedCell.error;
|
|
39845
|
+
}
|
|
39810
39846
|
const rowIndex = row - _zone.top;
|
|
39811
39847
|
matrix[colIndex][rowIndex] = this.readCell({ sheetId, col, row });
|
|
39812
39848
|
}
|
|
39813
39849
|
}
|
|
39850
|
+
this.rangeCache[cacheKey] = matrix;
|
|
39814
39851
|
return matrix;
|
|
39815
39852
|
}
|
|
39816
39853
|
}
|
|
@@ -40016,6 +40053,7 @@ class Evaluator {
|
|
|
40016
40053
|
this.formulaDependencies().addDependencies(positionId, dependencies);
|
|
40017
40054
|
}
|
|
40018
40055
|
updateCompilationParameters() {
|
|
40056
|
+
// rebuild the compilation parameters (with a clean cache)
|
|
40019
40057
|
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
|
40020
40058
|
}
|
|
40021
40059
|
evaluateCells(positions) {
|
|
@@ -40059,6 +40097,16 @@ class Evaluator {
|
|
|
40059
40097
|
this.evaluatedCells = new Map();
|
|
40060
40098
|
this.evaluate(this.getAllCells());
|
|
40061
40099
|
}
|
|
40100
|
+
evaluateFormula(sheetId, formulaString) {
|
|
40101
|
+
const compiledFormula = compile(formulaString);
|
|
40102
|
+
const ranges = compiledFormula.dependencies.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40103
|
+
this.updateCompilationParameters();
|
|
40104
|
+
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40105
|
+
if (isMatrix(array)) {
|
|
40106
|
+
return matrixMap(array, (cell) => cell.value);
|
|
40107
|
+
}
|
|
40108
|
+
return array.value;
|
|
40109
|
+
}
|
|
40062
40110
|
getAllCells() {
|
|
40063
40111
|
const positionIds = new JetSet();
|
|
40064
40112
|
for (const sheetId of this.getters.getSheetIds()) {
|
|
@@ -40085,6 +40133,7 @@ class Evaluator {
|
|
|
40085
40133
|
this.nextPositionsToUpdate = cells;
|
|
40086
40134
|
let currentIteration = 0;
|
|
40087
40135
|
while (this.nextPositionsToUpdate.size && currentIteration++ < MAX_ITERATION) {
|
|
40136
|
+
this.updateCompilationParameters();
|
|
40088
40137
|
const positionIds = Array.from(this.nextPositionsToUpdate);
|
|
40089
40138
|
this.nextPositionsToUpdate.clear();
|
|
40090
40139
|
for (let i = 0; i < positionIds.length; ++i) {
|
|
@@ -40448,7 +40497,6 @@ class PositionBitsEncoder {
|
|
|
40448
40497
|
// of other cells depending on it, at the next iteration.
|
|
40449
40498
|
//#endregion
|
|
40450
40499
|
class EvaluationPlugin extends UIPlugin {
|
|
40451
|
-
config;
|
|
40452
40500
|
static getters = [
|
|
40453
40501
|
"evaluateFormula",
|
|
40454
40502
|
"getCorrespondingFormulaCell",
|
|
@@ -40459,15 +40507,13 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40459
40507
|
"getEvaluatedCells",
|
|
40460
40508
|
"getEvaluatedCellsInZone",
|
|
40461
40509
|
"getSpreadPositionsOf",
|
|
40510
|
+
"getArrayFormulaSpreadingOn",
|
|
40462
40511
|
];
|
|
40463
40512
|
shouldRebuildDependenciesGraph = true;
|
|
40464
40513
|
evaluator;
|
|
40465
|
-
compilationParams;
|
|
40466
40514
|
positionsToUpdate = [];
|
|
40467
40515
|
constructor(config) {
|
|
40468
40516
|
super(config);
|
|
40469
|
-
this.config = config;
|
|
40470
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40471
40517
|
this.evaluator = new Evaluator(config.custom, this.getters);
|
|
40472
40518
|
}
|
|
40473
40519
|
// ---------------------------------------------------------------------------
|
|
@@ -40492,10 +40538,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40492
40538
|
case "EVALUATE_CELLS":
|
|
40493
40539
|
this.evaluator.evaluateAllCells();
|
|
40494
40540
|
break;
|
|
40495
|
-
case "UPDATE_LOCALE":
|
|
40496
|
-
this.compilationParams = this.getCompilationParameters();
|
|
40497
|
-
this.evaluator.updateCompilationParameters();
|
|
40498
|
-
break;
|
|
40499
40541
|
}
|
|
40500
40542
|
}
|
|
40501
40543
|
finalize() {
|
|
@@ -40513,16 +40555,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40513
40555
|
// Getters
|
|
40514
40556
|
// ---------------------------------------------------------------------------
|
|
40515
40557
|
evaluateFormula(sheetId, formulaString) {
|
|
40516
|
-
|
|
40517
|
-
const ranges = [];
|
|
40518
|
-
for (let xc of compiledFormula.dependencies) {
|
|
40519
|
-
ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
40520
|
-
}
|
|
40521
|
-
const array = compiledFormula.execute(ranges, ...this.compilationParams);
|
|
40522
|
-
if (isMatrix(array)) {
|
|
40523
|
-
return array.map((col) => col.map((row) => row.value));
|
|
40524
|
-
}
|
|
40525
|
-
return array.value;
|
|
40558
|
+
return this.evaluator.evaluateFormula(sheetId, formulaString);
|
|
40526
40559
|
}
|
|
40527
40560
|
/**
|
|
40528
40561
|
* Return the value of each cell in the range as they are displayed in the grid.
|
|
@@ -40571,6 +40604,9 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40571
40604
|
getSpreadPositionsOf(position) {
|
|
40572
40605
|
return this.evaluator.getSpreadPositionsOf(position);
|
|
40573
40606
|
}
|
|
40607
|
+
getArrayFormulaSpreadingOn(position) {
|
|
40608
|
+
return this.evaluator.getArrayFormulaSpreadingOn(position);
|
|
40609
|
+
}
|
|
40574
40610
|
// ---------------------------------------------------------------------------
|
|
40575
40611
|
// Export
|
|
40576
40612
|
// ---------------------------------------------------------------------------
|
|
@@ -40614,7 +40650,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40614
40650
|
else if (cell && cell.content) {
|
|
40615
40651
|
return undefined;
|
|
40616
40652
|
}
|
|
40617
|
-
const spreadingFormulaPosition = this.
|
|
40653
|
+
const spreadingFormulaPosition = this.getArrayFormulaSpreadingOn(position);
|
|
40618
40654
|
if (spreadingFormulaPosition === undefined) {
|
|
40619
40655
|
return undefined;
|
|
40620
40656
|
}
|
|
@@ -40624,9 +40660,6 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
40624
40660
|
}
|
|
40625
40661
|
return undefined;
|
|
40626
40662
|
}
|
|
40627
|
-
getCompilationParameters() {
|
|
40628
|
-
return buildCompilationParameters(this.config.custom, this.getters, (position) => this.evaluator.getEvaluatedCell(position));
|
|
40629
|
-
}
|
|
40630
40663
|
}
|
|
40631
40664
|
function isBadExpression(tokens) {
|
|
40632
40665
|
try {
|
|
@@ -41767,19 +41800,21 @@ class AutofillPlugin extends UIPlugin {
|
|
|
41767
41800
|
let col = zone.left;
|
|
41768
41801
|
let row = zone.bottom;
|
|
41769
41802
|
if (col > 0) {
|
|
41770
|
-
let
|
|
41771
|
-
while (
|
|
41803
|
+
let leftPosition = { sheetId, col: col - 1, row };
|
|
41804
|
+
while (this.getters.getEvaluatedCell(leftPosition).type !== CellValueType.empty ||
|
|
41805
|
+
this.getters.getCell(leftPosition)?.content) {
|
|
41772
41806
|
row += 1;
|
|
41773
|
-
|
|
41807
|
+
leftPosition = { sheetId, col: col - 1, row };
|
|
41774
41808
|
}
|
|
41775
41809
|
}
|
|
41776
41810
|
if (row === zone.bottom) {
|
|
41777
41811
|
col = zone.right;
|
|
41778
41812
|
if (col <= this.getters.getNumberCols(sheetId)) {
|
|
41779
|
-
let
|
|
41780
|
-
while (
|
|
41813
|
+
let rightPosition = { sheetId, col: col + 1, row };
|
|
41814
|
+
while (this.getters.getEvaluatedCell(rightPosition).type !== CellValueType.empty ||
|
|
41815
|
+
this.getters.getCell(rightPosition)?.content) {
|
|
41781
41816
|
row += 1;
|
|
41782
|
-
|
|
41817
|
+
rightPosition = { sheetId, col: col + 1, row };
|
|
41783
41818
|
}
|
|
41784
41819
|
}
|
|
41785
41820
|
}
|
|
@@ -42771,6 +42806,7 @@ class Session extends EventBus {
|
|
|
42771
42806
|
isReplayingInitialRevisions = false;
|
|
42772
42807
|
processedRevisions = new Set();
|
|
42773
42808
|
uuidGenerator = new UuidGenerator();
|
|
42809
|
+
lastLocalOperation;
|
|
42774
42810
|
/**
|
|
42775
42811
|
* Manages the collaboration between multiple users on the same spreadsheet.
|
|
42776
42812
|
* It can forward local state changes to other users to ensure they all eventually
|
|
@@ -42803,6 +42839,11 @@ class Session extends EventBus {
|
|
|
42803
42839
|
return;
|
|
42804
42840
|
const revision = new Revision(this.uuidGenerator.uuidv4(), this.clientId, commands, rootCommand, changes, Date.now());
|
|
42805
42841
|
this.revisions.append(revision.id, revision);
|
|
42842
|
+
// REQUEST_REDO just repeats the last operation, the
|
|
42843
|
+
// last operation is still the same and should not change.
|
|
42844
|
+
if (rootCommand.type !== "REQUEST_REDO") {
|
|
42845
|
+
this.lastLocalOperation = revision;
|
|
42846
|
+
}
|
|
42806
42847
|
this.trigger("new-local-state-update", { id: revision.id });
|
|
42807
42848
|
this.sendUpdateMessage({
|
|
42808
42849
|
type: "REMOTE_REVISION",
|
|
@@ -42899,19 +42940,10 @@ class Session extends EventBus {
|
|
|
42899
42940
|
return this.pendingMessages.length === 0;
|
|
42900
42941
|
}
|
|
42901
42942
|
/**
|
|
42902
|
-
* Get the last local revision
|
|
42943
|
+
* Get the last local revision
|
|
42903
42944
|
* */
|
|
42904
|
-
getLastLocalNonEmptyRevision(
|
|
42905
|
-
|
|
42906
|
-
for (const rev of revisions) {
|
|
42907
|
-
if (rev.rootCommand === "SNAPSHOT")
|
|
42908
|
-
return undefined;
|
|
42909
|
-
if (!rev.rootCommand || rev.rootCommand === "REMOTE")
|
|
42910
|
-
continue;
|
|
42911
|
-
if (!ignoredRootCommands.includes(rev.rootCommand?.type) && rev.commands.length)
|
|
42912
|
-
return rev;
|
|
42913
|
-
}
|
|
42914
|
-
return undefined;
|
|
42945
|
+
getLastLocalNonEmptyRevision() {
|
|
42946
|
+
return this.lastLocalOperation;
|
|
42915
42947
|
}
|
|
42916
42948
|
_move(position) {
|
|
42917
42949
|
// this method is debounced and might be called after the client
|
|
@@ -42971,7 +43003,7 @@ class Session extends EventBus {
|
|
|
42971
43003
|
break;
|
|
42972
43004
|
case "REMOTE_REVISION":
|
|
42973
43005
|
const { clientId, commands, timestamp } = message;
|
|
42974
|
-
const revision = new Revision(message.nextRevisionId, clientId, commands,
|
|
43006
|
+
const revision = new Revision(message.nextRevisionId, clientId, commands, undefined, undefined, timestamp);
|
|
42975
43007
|
if (revision.clientId !== this.clientId) {
|
|
42976
43008
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
42977
43009
|
const pendingCommands = this.pendingMessages
|
|
@@ -42984,10 +43016,11 @@ class Session extends EventBus {
|
|
|
42984
43016
|
}
|
|
42985
43017
|
break;
|
|
42986
43018
|
case "SNAPSHOT_CREATED": {
|
|
42987
|
-
const revision = new Revision(message.nextRevisionId, "server", [],
|
|
43019
|
+
const revision = new Revision(message.nextRevisionId, "server", [], undefined, undefined, Date.now());
|
|
42988
43020
|
this.revisions.insert(revision.id, revision, message.serverRevisionId);
|
|
42989
43021
|
this.dropPendingHistoryMessages();
|
|
42990
43022
|
this.trigger("snapshot");
|
|
43023
|
+
this.lastLocalOperation = undefined;
|
|
42991
43024
|
break;
|
|
42992
43025
|
}
|
|
42993
43026
|
}
|
|
@@ -43325,11 +43358,26 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43325
43358
|
let cellsInRow = [];
|
|
43326
43359
|
for (let col of columnsIndex) {
|
|
43327
43360
|
const position = { col, row, sheetId };
|
|
43361
|
+
const spreader = getters.getArrayFormulaSpreadingOn(position);
|
|
43362
|
+
let cell = getters.getCell(position);
|
|
43363
|
+
const evaluatedCell = getters.getEvaluatedCell(position);
|
|
43364
|
+
if (spreader) {
|
|
43365
|
+
const isSpreaderCopied = rowsIndex.includes(spreader.row) && columnsIndex.includes(spreader.col);
|
|
43366
|
+
const content = isSpreaderCopied
|
|
43367
|
+
? ""
|
|
43368
|
+
: formatValue(evaluatedCell.value, { locale: getters.getLocale() });
|
|
43369
|
+
cell = {
|
|
43370
|
+
id: cell?.id || "",
|
|
43371
|
+
style: cell?.style,
|
|
43372
|
+
format: evaluatedCell.format,
|
|
43373
|
+
content,
|
|
43374
|
+
isFormula: false,
|
|
43375
|
+
};
|
|
43376
|
+
}
|
|
43328
43377
|
cellsInRow.push({
|
|
43329
|
-
cell
|
|
43330
|
-
style: getters.getCellComputedStyle(position),
|
|
43331
|
-
evaluatedCell: getters.getEvaluatedCell(position),
|
|
43378
|
+
cell,
|
|
43332
43379
|
border: getters.getCellBorder(position) || undefined,
|
|
43380
|
+
evaluatedCell,
|
|
43333
43381
|
position,
|
|
43334
43382
|
});
|
|
43335
43383
|
}
|
|
@@ -43451,13 +43499,6 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43451
43499
|
});
|
|
43452
43500
|
}
|
|
43453
43501
|
this.pasteCopiedTables(target);
|
|
43454
|
-
this.cells.forEach((row) => {
|
|
43455
|
-
row.forEach((c) => {
|
|
43456
|
-
if (c.cell) {
|
|
43457
|
-
c.cell = undefined;
|
|
43458
|
-
}
|
|
43459
|
-
});
|
|
43460
|
-
});
|
|
43461
43502
|
}
|
|
43462
43503
|
/**
|
|
43463
43504
|
* The clipped zone is copied as many times as it fits in the target.
|
|
@@ -43529,7 +43570,7 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43529
43570
|
clearClippedZones() {
|
|
43530
43571
|
for (const row of this.cells) {
|
|
43531
43572
|
for (const cell of row) {
|
|
43532
|
-
if (cell
|
|
43573
|
+
if (cell?.cell) {
|
|
43533
43574
|
this.dispatch("CLEAR_CELL", cell.position);
|
|
43534
43575
|
}
|
|
43535
43576
|
}
|
|
@@ -43555,6 +43596,9 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43555
43596
|
const rowCells = this.cells[r];
|
|
43556
43597
|
for (let c = 0; c < width; c++) {
|
|
43557
43598
|
const origin = rowCells[c];
|
|
43599
|
+
if (!origin) {
|
|
43600
|
+
continue;
|
|
43601
|
+
}
|
|
43558
43602
|
const position = { col: col + c, row: row + r, sheetId: sheetId };
|
|
43559
43603
|
// TODO: refactor this part. the "Paste merge" action is also executed with
|
|
43560
43604
|
// MOVE_RANGES in pasteFromCut. Adding a condition on the operation type here
|
|
@@ -43578,53 +43622,42 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43578
43622
|
pasteCell(origin, target, operation, clipboardOption) {
|
|
43579
43623
|
const { sheetId, col, row } = target;
|
|
43580
43624
|
const targetCell = this.getters.getEvaluatedCell(target);
|
|
43581
|
-
if (clipboardOption?.pasteOption
|
|
43582
|
-
const
|
|
43583
|
-
const
|
|
43584
|
-
|
|
43585
|
-
|
|
43586
|
-
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43587
|
-
left: targetBorders?.left || originBorders?.left,
|
|
43588
|
-
right: targetBorders?.right || originBorders?.right,
|
|
43589
|
-
};
|
|
43590
|
-
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43625
|
+
if (clipboardOption?.pasteOption === "onlyValue") {
|
|
43626
|
+
const locale = this.getters.getLocale();
|
|
43627
|
+
const content = formatValue(origin.evaluatedCell.value, { locale });
|
|
43628
|
+
this.dispatch("UPDATE_CELL", { ...target, content });
|
|
43629
|
+
return;
|
|
43591
43630
|
}
|
|
43592
|
-
|
|
43593
|
-
|
|
43594
|
-
|
|
43595
|
-
|
|
43596
|
-
|
|
43597
|
-
|
|
43598
|
-
|
|
43599
|
-
|
|
43600
|
-
|
|
43601
|
-
|
|
43602
|
-
|
|
43603
|
-
|
|
43604
|
-
|
|
43605
|
-
|
|
43606
|
-
}
|
|
43607
|
-
|
|
43608
|
-
|
|
43609
|
-
|
|
43610
|
-
|
|
43631
|
+
const targetBorders = this.getters.getCellBorder(target);
|
|
43632
|
+
const originBorders = origin.border;
|
|
43633
|
+
const border = {
|
|
43634
|
+
top: targetBorders?.top || originBorders?.top,
|
|
43635
|
+
bottom: targetBorders?.bottom || originBorders?.bottom,
|
|
43636
|
+
left: targetBorders?.left || originBorders?.left,
|
|
43637
|
+
right: targetBorders?.right || originBorders?.right,
|
|
43638
|
+
};
|
|
43639
|
+
this.dispatch("SET_BORDER", { sheetId, col, row, border });
|
|
43640
|
+
if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43641
|
+
this.dispatch("UPDATE_CELL", {
|
|
43642
|
+
...target,
|
|
43643
|
+
style: origin.cell?.style ?? null,
|
|
43644
|
+
format: origin.cell?.format ?? origin.evaluatedCell.format ?? targetCell.format,
|
|
43645
|
+
});
|
|
43646
|
+
return;
|
|
43647
|
+
}
|
|
43648
|
+
const content = origin.cell && origin.cell.isFormula && operation === "COPY"
|
|
43649
|
+
? this.getters.getTranslatedCellFormula(sheetId, col - origin.position.col, row - origin.position.row, origin.cell.compiledFormula)
|
|
43650
|
+
: origin.cell?.content;
|
|
43651
|
+
if (content !== "" || origin.cell?.format || origin.cell?.style) {
|
|
43611
43652
|
this.dispatch("UPDATE_CELL", {
|
|
43612
43653
|
...target,
|
|
43613
43654
|
content,
|
|
43614
|
-
style: origin.cell
|
|
43615
|
-
format: origin.cell
|
|
43655
|
+
style: origin.cell?.style || null,
|
|
43656
|
+
format: origin.cell?.format,
|
|
43616
43657
|
});
|
|
43617
43658
|
}
|
|
43618
43659
|
else if (targetCell) {
|
|
43619
|
-
|
|
43620
|
-
this.dispatch("UPDATE_CELL", { ...target, content: "" });
|
|
43621
|
-
}
|
|
43622
|
-
else if (clipboardOption?.pasteOption === "onlyFormat") {
|
|
43623
|
-
this.dispatch("UPDATE_CELL", { ...target, style: null, format: "" });
|
|
43624
|
-
}
|
|
43625
|
-
else {
|
|
43626
|
-
this.dispatch("CLEAR_CELL", target);
|
|
43627
|
-
}
|
|
43660
|
+
this.dispatch("CLEAR_CELL", target);
|
|
43628
43661
|
}
|
|
43629
43662
|
}
|
|
43630
43663
|
/**
|
|
@@ -43686,22 +43719,28 @@ class ClipboardCellsState extends ClipboardCellsAbstractState {
|
|
|
43686
43719
|
return (this.cells
|
|
43687
43720
|
.map((cells) => {
|
|
43688
43721
|
return cells
|
|
43689
|
-
.map((c) => this.getters.shouldShowFormulas() && c
|
|
43722
|
+
.map((c) => this.getters.shouldShowFormulas() && c?.cell?.isFormula
|
|
43690
43723
|
? c.cell?.content || ""
|
|
43691
|
-
: c
|
|
43724
|
+
: c?.evaluatedCell?.formattedValue || "")
|
|
43692
43725
|
.join("\t");
|
|
43693
43726
|
})
|
|
43694
43727
|
.join("\n") || "\t");
|
|
43695
43728
|
}
|
|
43696
43729
|
getHTMLContent() {
|
|
43697
43730
|
if (this.cells.length === 1 && this.cells[0].length === 1) {
|
|
43731
|
+
if (!this.cells[0][0]) {
|
|
43732
|
+
return "";
|
|
43733
|
+
}
|
|
43698
43734
|
return this.getters.getCellText(this.cells[0][0].position);
|
|
43699
43735
|
}
|
|
43700
43736
|
let htmlTable = '<table border="1" style="border-collapse:collapse">';
|
|
43701
43737
|
for (const row of this.cells) {
|
|
43702
43738
|
htmlTable += "<tr>";
|
|
43703
43739
|
for (const cell of row) {
|
|
43704
|
-
|
|
43740
|
+
if (!cell) {
|
|
43741
|
+
continue;
|
|
43742
|
+
}
|
|
43743
|
+
const cssStyle = cssPropertiesToCss(cellStyleToCss(this.getters.getCellComputedStyle(cell.position)));
|
|
43705
43744
|
const cellText = this.getters.getCellText(cell.position);
|
|
43706
43745
|
htmlTable += `<td style="${cssStyle}">` + xmlEscape(cellText) + "</td>";
|
|
43707
43746
|
}
|
|
@@ -45536,6 +45575,9 @@ class SelectionInputsManagerPlugin extends UIPlugin {
|
|
|
45536
45575
|
// Other
|
|
45537
45576
|
// ---------------------------------------------------------------------------
|
|
45538
45577
|
initInput(id, initialRanges, inputHasSingleRange = false) {
|
|
45578
|
+
if (this.inputs[id]) {
|
|
45579
|
+
this.unfocus();
|
|
45580
|
+
}
|
|
45539
45581
|
this.inputs[id] = new SelectionInputPlugin(this.config, initialRanges, inputHasSingleRange);
|
|
45540
45582
|
if (initialRanges.length === 0) {
|
|
45541
45583
|
const input = this.inputs[id];
|
|
@@ -46334,7 +46376,7 @@ class HistoryPlugin extends UIPlugin {
|
|
|
46334
46376
|
* Ignore standard undo/redo revisions (that are empty)
|
|
46335
46377
|
*/
|
|
46336
46378
|
getPossibleRevisionToRepeat() {
|
|
46337
|
-
return this.session.getLastLocalNonEmptyRevision(
|
|
46379
|
+
return this.session.getLastLocalNonEmptyRevision();
|
|
46338
46380
|
}
|
|
46339
46381
|
}
|
|
46340
46382
|
|
|
@@ -46831,11 +46873,14 @@ class ClipboardPlugin extends UIPlugin {
|
|
|
46831
46873
|
}
|
|
46832
46874
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
46833
46875
|
this.state.paste(cmd.target, { pasteOption, shouldPasteCF: true, selectTarget: true });
|
|
46876
|
+
if (this.state.operation === "CUT") {
|
|
46877
|
+
this.state = undefined;
|
|
46878
|
+
}
|
|
46834
46879
|
this.lastPasteState = this.state;
|
|
46835
46880
|
if (this.paintFormatStatus === "oneOff") {
|
|
46836
46881
|
this.paintFormatStatus = "inactive";
|
|
46837
|
-
this.status = "invisible";
|
|
46838
46882
|
}
|
|
46883
|
+
this.status = "invisible";
|
|
46839
46884
|
break;
|
|
46840
46885
|
case "COPY_PASTE_CELLS_ABOVE":
|
|
46841
46886
|
{
|
|
@@ -47116,6 +47161,10 @@ function setXcToReferenceType(xc, referenceType) {
|
|
|
47116
47161
|
return xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47117
47162
|
case "colrow":
|
|
47118
47163
|
indexOfNumber = xc.search(/[0-9]/);
|
|
47164
|
+
if (indexOfNumber === -1 || indexOfNumber === 0) {
|
|
47165
|
+
// no row number (eg. A) or no column (eg. 1)
|
|
47166
|
+
return "$" + xc;
|
|
47167
|
+
}
|
|
47119
47168
|
xc = xc.slice(0, indexOfNumber) + "$" + xc.slice(indexOfNumber);
|
|
47120
47169
|
return "$" + xc;
|
|
47121
47170
|
case "none":
|
|
@@ -47886,6 +47935,12 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
47886
47935
|
break;
|
|
47887
47936
|
case "HIDE_COLUMNS_ROWS":
|
|
47888
47937
|
case "UNHIDE_COLUMNS_ROWS":
|
|
47938
|
+
case "GROUP_HEADERS":
|
|
47939
|
+
case "UNGROUP_HEADERS":
|
|
47940
|
+
case "FOLD_HEADER_GROUP":
|
|
47941
|
+
case "UNFOLD_HEADER_GROUP":
|
|
47942
|
+
case "FOLD_ALL_HEADER_GROUPS":
|
|
47943
|
+
case "UNFOLD_ALL_HEADER_GROUPS":
|
|
47889
47944
|
this.updateHiddenRows();
|
|
47890
47945
|
break;
|
|
47891
47946
|
case "UPDATE_FILTER":
|
|
@@ -48587,7 +48642,7 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
48587
48642
|
sheetId: cmd.sheetId,
|
|
48588
48643
|
base: cmd.base,
|
|
48589
48644
|
quantity: thickness,
|
|
48590
|
-
position:
|
|
48645
|
+
position: cmd.position,
|
|
48591
48646
|
});
|
|
48592
48647
|
const isCol = cmd.dimension === "COL";
|
|
48593
48648
|
const start = cmd.elements[0];
|
|
@@ -48604,12 +48659,13 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
48604
48659
|
},
|
|
48605
48660
|
];
|
|
48606
48661
|
const state = new ClipboardCellsState(target, "CUT", this.getters, this.dispatch, this.selection);
|
|
48662
|
+
const base = isBasedBefore ? cmd.base : cmd.base + 1;
|
|
48607
48663
|
const pasteTarget = [
|
|
48608
48664
|
{
|
|
48609
|
-
left: isCol ?
|
|
48610
|
-
right: isCol ?
|
|
48611
|
-
top: !isCol ?
|
|
48612
|
-
bottom: !isCol ?
|
|
48665
|
+
left: isCol ? base : 0,
|
|
48666
|
+
right: isCol ? base + thickness - 1 : this.getters.getNumberCols(cmd.sheetId) - 1,
|
|
48667
|
+
top: !isCol ? base : 0,
|
|
48668
|
+
bottom: !isCol ? base + thickness - 1 : this.getters.getNumberRows(cmd.sheetId) - 1,
|
|
48613
48669
|
},
|
|
48614
48670
|
];
|
|
48615
48671
|
state.paste(pasteTarget, { selectTarget: true });
|
|
@@ -48644,6 +48700,11 @@ class GridSelectionPlugin extends UIPlugin {
|
|
|
48644
48700
|
doesElementsHaveCommonMerges(id, cmd.base - 1, cmd.base)) {
|
|
48645
48701
|
return "WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */;
|
|
48646
48702
|
}
|
|
48703
|
+
const headers = [cmd.base, ...cmd.elements];
|
|
48704
|
+
const maxHeaderValue = isCol ? this.getters.getNumberCols(id) : this.getters.getNumberRows(id);
|
|
48705
|
+
if (headers.some((h) => h < 0 || h >= maxHeaderValue)) {
|
|
48706
|
+
return "InvalidHeaderIndex" /* CommandResult.InvalidHeaderIndex */;
|
|
48707
|
+
}
|
|
48647
48708
|
return "Success" /* CommandResult.Success */;
|
|
48648
48709
|
}
|
|
48649
48710
|
//-------------------------------------------
|
|
@@ -49689,10 +49750,13 @@ class HeaderPositionsUIPlugin extends UIPlugin {
|
|
|
49689
49750
|
}
|
|
49690
49751
|
break;
|
|
49691
49752
|
case "UPDATE_CELL":
|
|
49692
|
-
if ("content" in cmd || "format" in cmd
|
|
49753
|
+
if ("content" in cmd || "format" in cmd) {
|
|
49693
49754
|
this.headerPositions = {};
|
|
49694
49755
|
this.isDirty = true;
|
|
49695
49756
|
}
|
|
49757
|
+
else {
|
|
49758
|
+
this.headerPositions[cmd.sheetId] = this.computeHeaderPositionsOfSheet(cmd.sheetId);
|
|
49759
|
+
}
|
|
49696
49760
|
break;
|
|
49697
49761
|
case "UPDATE_FILTER":
|
|
49698
49762
|
case "REMOVE_FILTER_TABLE":
|
|
@@ -51849,6 +51913,8 @@ css /* scss */ `
|
|
|
51849
51913
|
*:before,
|
|
51850
51914
|
*:after {
|
|
51851
51915
|
box-sizing: content-box;
|
|
51916
|
+
/** rtl not supported ATM */
|
|
51917
|
+
direction: ltr;
|
|
51852
51918
|
}
|
|
51853
51919
|
.o-separator {
|
|
51854
51920
|
border-bottom: ${MENU_SEPARATOR_BORDER_WIDTH}px solid ${SEPARATOR_COLOR};
|
|
@@ -55559,19 +55625,22 @@ class Model extends EventBus {
|
|
|
55559
55625
|
* Check if the given command is allowed by all the plugins and the history.
|
|
55560
55626
|
*/
|
|
55561
55627
|
checkDispatchAllowed(command) {
|
|
55562
|
-
|
|
55563
|
-
|
|
55628
|
+
const results = isCoreCommand(command)
|
|
55629
|
+
? this.checkDispatchAllowedCoreCommand(command)
|
|
55630
|
+
: this.checkDispatchAllowedLocalCommand(command);
|
|
55631
|
+
if (results.some((r) => r !== "Success" /* CommandResult.Success */)) {
|
|
55632
|
+
return new DispatchResult(results.flat());
|
|
55564
55633
|
}
|
|
55565
|
-
return
|
|
55634
|
+
return DispatchResult.Success;
|
|
55566
55635
|
}
|
|
55567
55636
|
checkDispatchAllowedCoreCommand(command) {
|
|
55568
55637
|
const results = this.corePlugins.map((handler) => handler.allowDispatch(command));
|
|
55569
55638
|
results.push(this.range.allowDispatch(command));
|
|
55570
|
-
return
|
|
55639
|
+
return results;
|
|
55571
55640
|
}
|
|
55572
55641
|
checkDispatchAllowedLocalCommand(command) {
|
|
55573
55642
|
const results = this.uiHandlers.map((handler) => handler.allowDispatch(command));
|
|
55574
|
-
return
|
|
55643
|
+
return results;
|
|
55575
55644
|
}
|
|
55576
55645
|
finalize() {
|
|
55577
55646
|
this.status = 3 /* Status.Finalizing */;
|
|
@@ -55883,6 +55952,6 @@ const constants = {
|
|
|
55883
55952
|
export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
|
|
55884
55953
|
|
|
55885
55954
|
|
|
55886
|
-
__info__.version = "17.0.
|
|
55887
|
-
__info__.date = "2023-
|
|
55888
|
-
__info__.hash = "
|
|
55955
|
+
__info__.version = "17.0.5";
|
|
55956
|
+
__info__.date = "2023-12-05T09:51:44.657Z";
|
|
55957
|
+
__info__.hash = "2480a5d";
|