@odoo/o-spreadsheet 17.2.14 → 17.2.16
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 +233 -191
- package/dist/o-spreadsheet.d.ts +6 -3
- package/dist/o-spreadsheet.esm.js +233 -191
- package/dist/o-spreadsheet.iife.js +233 -191
- package/dist/o-spreadsheet.iife.min.js +6 -6
- package/dist/o_spreadsheet.xml +4 -4
- package/package.json +1 -1
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.2.
|
|
7
|
-
* @date 2024-07-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.2.16
|
|
7
|
+
* @date 2024-07-11T06:38:53.101Z
|
|
8
|
+
* @hash 9f20685
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
@@ -577,7 +577,7 @@ function getAddHeaderStartIndex(position, base) {
|
|
|
577
577
|
/**
|
|
578
578
|
* Compares two objects.
|
|
579
579
|
*/
|
|
580
|
-
function deepEquals(o1, o2
|
|
580
|
+
function deepEquals(o1, o2) {
|
|
581
581
|
if (o1 === o2)
|
|
582
582
|
return true;
|
|
583
583
|
if ((o1 && !o2) || (o2 && !o1))
|
|
@@ -593,17 +593,13 @@ function deepEquals(o1, o2, ignoreFunctions) {
|
|
|
593
593
|
}
|
|
594
594
|
}
|
|
595
595
|
for (const key in o1) {
|
|
596
|
-
|
|
597
|
-
if (typeOfO1Key !== typeof o2[key])
|
|
596
|
+
if (typeof o1[key] !== typeof o2[key])
|
|
598
597
|
return false;
|
|
599
|
-
if (
|
|
600
|
-
if (!deepEquals(o1[key], o2[key]
|
|
598
|
+
if (typeof o1[key] === "object") {
|
|
599
|
+
if (!deepEquals(o1[key], o2[key]))
|
|
601
600
|
return false;
|
|
602
601
|
}
|
|
603
602
|
else {
|
|
604
|
-
if (ignoreFunctions && typeOfO1Key === "function") {
|
|
605
|
-
continue;
|
|
606
|
-
}
|
|
607
603
|
if (o1[key] !== o2[key])
|
|
608
604
|
return false;
|
|
609
605
|
}
|
|
@@ -1752,7 +1748,7 @@ const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSepa
|
|
|
1752
1748
|
});
|
|
1753
1749
|
const getNumberRegex = memoize(function getNumberRegex(locale) {
|
|
1754
1750
|
const decimalSeparator = escapeRegExp(locale.decimalSeparator);
|
|
1755
|
-
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
|
|
1751
|
+
const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
|
|
1756
1752
|
const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
|
|
1757
1753
|
const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
|
|
1758
1754
|
const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
|
|
@@ -1779,7 +1775,7 @@ function isNumber(value, locale) {
|
|
|
1779
1775
|
return getNumberRegex(locale).test(value.trim());
|
|
1780
1776
|
}
|
|
1781
1777
|
const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
|
|
1782
|
-
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
|
|
1778
|
+
return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
|
|
1783
1779
|
});
|
|
1784
1780
|
/**
|
|
1785
1781
|
* Convert a string into a number. It assumes that the string actually represents
|
|
@@ -2648,6 +2644,9 @@ function getPredicate(descr, locale) {
|
|
|
2648
2644
|
* If the character is a special regular expression character, it is escaped with "\\".
|
|
2649
2645
|
*/
|
|
2650
2646
|
const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
|
|
2647
|
+
if (operand === "*") {
|
|
2648
|
+
return /.+/;
|
|
2649
|
+
}
|
|
2651
2650
|
let exp = "";
|
|
2652
2651
|
let predecessor = "";
|
|
2653
2652
|
for (let char of operand) {
|
|
@@ -2671,9 +2670,9 @@ const wildcardToRegExp = memoize(function wildcardToRegExp(operand) {
|
|
|
2671
2670
|
}
|
|
2672
2671
|
return new RegExp("^" + exp + "$", "i");
|
|
2673
2672
|
});
|
|
2674
|
-
function evaluatePredicate(value, criterion) {
|
|
2673
|
+
function evaluatePredicate(value = "", criterion) {
|
|
2675
2674
|
const { operator, operand } = criterion;
|
|
2676
|
-
if (
|
|
2675
|
+
if (operand === undefined || value === null || operand === null) {
|
|
2677
2676
|
return false;
|
|
2678
2677
|
}
|
|
2679
2678
|
if (typeof operand === "number" && operator === "=") {
|
|
@@ -5359,19 +5358,22 @@ class TokenizingChars {
|
|
|
5359
5358
|
}
|
|
5360
5359
|
|
|
5361
5360
|
function isValidLocale(locale) {
|
|
5362
|
-
if (!
|
|
5363
|
-
typeof locale
|
|
5364
|
-
typeof locale.
|
|
5365
|
-
typeof locale.code === "string" &&
|
|
5366
|
-
typeof locale.thousandsSeparator === "string" &&
|
|
5367
|
-
typeof locale.decimalSeparator === "string" &&
|
|
5368
|
-
typeof locale.dateFormat === "string" &&
|
|
5369
|
-
typeof locale.timeFormat === "string" &&
|
|
5370
|
-
typeof locale.formulaArgSeparator === "string")) {
|
|
5361
|
+
if (!locale ||
|
|
5362
|
+
typeof locale !== "object" ||
|
|
5363
|
+
!(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
|
|
5371
5364
|
return false;
|
|
5372
5365
|
}
|
|
5373
|
-
|
|
5374
|
-
|
|
5366
|
+
for (const property of [
|
|
5367
|
+
"code",
|
|
5368
|
+
"name",
|
|
5369
|
+
"decimalSeparator",
|
|
5370
|
+
"dateFormat",
|
|
5371
|
+
"timeFormat",
|
|
5372
|
+
"formulaArgSeparator",
|
|
5373
|
+
]) {
|
|
5374
|
+
if (!locale[property] || typeof locale[property] !== "string") {
|
|
5375
|
+
return false;
|
|
5376
|
+
}
|
|
5375
5377
|
}
|
|
5376
5378
|
if (locale.formulaArgSeparator === locale.decimalSeparator) {
|
|
5377
5379
|
return false;
|
|
@@ -5469,7 +5471,10 @@ function canonicalizeNumberLiteral(content, locale) {
|
|
|
5469
5471
|
if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
|
|
5470
5472
|
return content;
|
|
5471
5473
|
}
|
|
5472
|
-
|
|
5474
|
+
if (locale.thousandsSeparator) {
|
|
5475
|
+
content = content.replaceAll(locale.thousandsSeparator, "");
|
|
5476
|
+
}
|
|
5477
|
+
return content.replace(locale.decimalSeparator, ".");
|
|
5473
5478
|
}
|
|
5474
5479
|
/**
|
|
5475
5480
|
* Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
|
|
@@ -6453,6 +6458,146 @@ function transformRangeData(range, executed) {
|
|
|
6453
6458
|
return undefined;
|
|
6454
6459
|
}
|
|
6455
6460
|
|
|
6461
|
+
var State;
|
|
6462
|
+
(function (State) {
|
|
6463
|
+
/**
|
|
6464
|
+
* Initial state.
|
|
6465
|
+
* Expecting any reference for the left part of a range
|
|
6466
|
+
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
6467
|
+
*/
|
|
6468
|
+
State[State["LeftRef"] = 0] = "LeftRef";
|
|
6469
|
+
/**
|
|
6470
|
+
* Expecting any reference for the right part of a range
|
|
6471
|
+
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
6472
|
+
*/
|
|
6473
|
+
State[State["RightRef"] = 1] = "RightRef";
|
|
6474
|
+
/**
|
|
6475
|
+
* Expecting the separator without any constraint on the right part
|
|
6476
|
+
*/
|
|
6477
|
+
State[State["Separator"] = 2] = "Separator";
|
|
6478
|
+
/**
|
|
6479
|
+
* Expecting the separator for a full column range
|
|
6480
|
+
*/
|
|
6481
|
+
State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
|
|
6482
|
+
/**
|
|
6483
|
+
* Expecting the separator for a full row range
|
|
6484
|
+
*/
|
|
6485
|
+
State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
|
|
6486
|
+
/**
|
|
6487
|
+
* Expecting the right part of a full column range
|
|
6488
|
+
* e.g. "1", "A1"
|
|
6489
|
+
*/
|
|
6490
|
+
State[State["RightColumnRef"] = 5] = "RightColumnRef";
|
|
6491
|
+
/**
|
|
6492
|
+
* Expecting the right part of a full row range
|
|
6493
|
+
* e.g. "A", "A1"
|
|
6494
|
+
*/
|
|
6495
|
+
State[State["RightRowRef"] = 6] = "RightRowRef";
|
|
6496
|
+
/**
|
|
6497
|
+
* Final state. A range has been matched
|
|
6498
|
+
*/
|
|
6499
|
+
State[State["Found"] = 7] = "Found";
|
|
6500
|
+
})(State || (State = {}));
|
|
6501
|
+
const goTo = (state, guard = () => true) => [
|
|
6502
|
+
{
|
|
6503
|
+
goTo: state,
|
|
6504
|
+
guard,
|
|
6505
|
+
},
|
|
6506
|
+
];
|
|
6507
|
+
const goToMulti = (state, guard = () => true) => ({
|
|
6508
|
+
goTo: state,
|
|
6509
|
+
guard,
|
|
6510
|
+
});
|
|
6511
|
+
const machine = {
|
|
6512
|
+
[State.LeftRef]: {
|
|
6513
|
+
REFERENCE: goTo(State.Separator),
|
|
6514
|
+
NUMBER: goTo(State.FullRowSeparator),
|
|
6515
|
+
SYMBOL: [
|
|
6516
|
+
goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
|
|
6517
|
+
goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
|
|
6518
|
+
],
|
|
6519
|
+
},
|
|
6520
|
+
[State.FullColumnSeparator]: {
|
|
6521
|
+
SPACE: goTo(State.FullColumnSeparator),
|
|
6522
|
+
OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
|
|
6523
|
+
},
|
|
6524
|
+
[State.FullRowSeparator]: {
|
|
6525
|
+
SPACE: goTo(State.FullRowSeparator),
|
|
6526
|
+
OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
|
|
6527
|
+
},
|
|
6528
|
+
[State.Separator]: {
|
|
6529
|
+
SPACE: goTo(State.Separator),
|
|
6530
|
+
OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
|
|
6531
|
+
},
|
|
6532
|
+
[State.RightRef]: {
|
|
6533
|
+
SPACE: goTo(State.RightRef),
|
|
6534
|
+
NUMBER: goTo(State.Found),
|
|
6535
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
6536
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
6537
|
+
},
|
|
6538
|
+
[State.RightColumnRef]: {
|
|
6539
|
+
SPACE: goTo(State.RightColumnRef),
|
|
6540
|
+
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
6541
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
6542
|
+
},
|
|
6543
|
+
[State.RightRowRef]: {
|
|
6544
|
+
SPACE: goTo(State.RightRowRef),
|
|
6545
|
+
NUMBER: goTo(State.Found),
|
|
6546
|
+
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
6547
|
+
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
6548
|
+
},
|
|
6549
|
+
[State.Found]: {},
|
|
6550
|
+
};
|
|
6551
|
+
/**
|
|
6552
|
+
* Check if the list of tokens starts with a sequence of tokens representing
|
|
6553
|
+
* a range.
|
|
6554
|
+
* If a range is found, the sequence is removed from the list and is returned
|
|
6555
|
+
* as a single token.
|
|
6556
|
+
*/
|
|
6557
|
+
function matchReference(tokens) {
|
|
6558
|
+
let head = 0;
|
|
6559
|
+
let transitions = machine[State.LeftRef];
|
|
6560
|
+
let matchedTokens = "";
|
|
6561
|
+
while (transitions !== undefined) {
|
|
6562
|
+
const token = tokens[head++];
|
|
6563
|
+
if (!token) {
|
|
6564
|
+
return null;
|
|
6565
|
+
}
|
|
6566
|
+
const transition = transitions[token.type]?.find((transition) => transition.guard(token));
|
|
6567
|
+
const nextState = transition ? transition.goTo : undefined;
|
|
6568
|
+
switch (nextState) {
|
|
6569
|
+
case undefined:
|
|
6570
|
+
return null;
|
|
6571
|
+
case State.Found:
|
|
6572
|
+
matchedTokens += token.value;
|
|
6573
|
+
tokens.splice(0, head);
|
|
6574
|
+
return {
|
|
6575
|
+
type: "REFERENCE",
|
|
6576
|
+
value: matchedTokens,
|
|
6577
|
+
};
|
|
6578
|
+
default:
|
|
6579
|
+
transitions = machine[nextState];
|
|
6580
|
+
matchedTokens += token.value;
|
|
6581
|
+
break;
|
|
6582
|
+
}
|
|
6583
|
+
}
|
|
6584
|
+
return null;
|
|
6585
|
+
}
|
|
6586
|
+
/**
|
|
6587
|
+
* Take the result of the tokenizer and transform it to be usable in the
|
|
6588
|
+
* manipulations of range
|
|
6589
|
+
*
|
|
6590
|
+
* @param formula
|
|
6591
|
+
*/
|
|
6592
|
+
function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
|
|
6593
|
+
const tokens = tokenize(formula, locale);
|
|
6594
|
+
const result = [];
|
|
6595
|
+
while (tokens.length) {
|
|
6596
|
+
result.push(matchReference(tokens) || tokens.shift());
|
|
6597
|
+
}
|
|
6598
|
+
return result;
|
|
6599
|
+
}
|
|
6600
|
+
|
|
6456
6601
|
const functionRegex = /[a-zA-Z0-9\_]+(\.[a-zA-Z0-9\_]+)*/;
|
|
6457
6602
|
const UNARY_OPERATORS_PREFIX = ["-", "+"];
|
|
6458
6603
|
const UNARY_OPERATORS_POSTFIX = ["%"];
|
|
@@ -6601,7 +6746,7 @@ function parseExpression(tokens, parent_priority = 0) {
|
|
|
6601
6746
|
* Parse an expression (as a string) into an AST.
|
|
6602
6747
|
*/
|
|
6603
6748
|
function parse(str) {
|
|
6604
|
-
return parseTokens(
|
|
6749
|
+
return parseTokens(rangeTokenize(str));
|
|
6605
6750
|
}
|
|
6606
6751
|
function parseTokens(tokens) {
|
|
6607
6752
|
tokens = tokens.filter((x) => x.type !== "SPACE");
|
|
@@ -6737,146 +6882,6 @@ function rightOperandToFormula(operationAST) {
|
|
|
6737
6882
|
return needParenthesis ? `(${astToFormula(rightOperation)})` : astToFormula(rightOperation);
|
|
6738
6883
|
}
|
|
6739
6884
|
|
|
6740
|
-
var State;
|
|
6741
|
-
(function (State) {
|
|
6742
|
-
/**
|
|
6743
|
-
* Initial state.
|
|
6744
|
-
* Expecting any reference for the left part of a range
|
|
6745
|
-
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
6746
|
-
*/
|
|
6747
|
-
State[State["LeftRef"] = 0] = "LeftRef";
|
|
6748
|
-
/**
|
|
6749
|
-
* Expecting any reference for the right part of a range
|
|
6750
|
-
* e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
|
|
6751
|
-
*/
|
|
6752
|
-
State[State["RightRef"] = 1] = "RightRef";
|
|
6753
|
-
/**
|
|
6754
|
-
* Expecting the separator without any constraint on the right part
|
|
6755
|
-
*/
|
|
6756
|
-
State[State["Separator"] = 2] = "Separator";
|
|
6757
|
-
/**
|
|
6758
|
-
* Expecting the separator for a full column range
|
|
6759
|
-
*/
|
|
6760
|
-
State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
|
|
6761
|
-
/**
|
|
6762
|
-
* Expecting the separator for a full row range
|
|
6763
|
-
*/
|
|
6764
|
-
State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
|
|
6765
|
-
/**
|
|
6766
|
-
* Expecting the right part of a full column range
|
|
6767
|
-
* e.g. "1", "A1"
|
|
6768
|
-
*/
|
|
6769
|
-
State[State["RightColumnRef"] = 5] = "RightColumnRef";
|
|
6770
|
-
/**
|
|
6771
|
-
* Expecting the right part of a full row range
|
|
6772
|
-
* e.g. "A", "A1"
|
|
6773
|
-
*/
|
|
6774
|
-
State[State["RightRowRef"] = 6] = "RightRowRef";
|
|
6775
|
-
/**
|
|
6776
|
-
* Final state. A range has been matched
|
|
6777
|
-
*/
|
|
6778
|
-
State[State["Found"] = 7] = "Found";
|
|
6779
|
-
})(State || (State = {}));
|
|
6780
|
-
const goTo = (state, guard = () => true) => [
|
|
6781
|
-
{
|
|
6782
|
-
goTo: state,
|
|
6783
|
-
guard,
|
|
6784
|
-
},
|
|
6785
|
-
];
|
|
6786
|
-
const goToMulti = (state, guard = () => true) => ({
|
|
6787
|
-
goTo: state,
|
|
6788
|
-
guard,
|
|
6789
|
-
});
|
|
6790
|
-
const machine = {
|
|
6791
|
-
[State.LeftRef]: {
|
|
6792
|
-
REFERENCE: goTo(State.Separator),
|
|
6793
|
-
NUMBER: goTo(State.FullRowSeparator),
|
|
6794
|
-
SYMBOL: [
|
|
6795
|
-
goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
|
|
6796
|
-
goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
|
|
6797
|
-
],
|
|
6798
|
-
},
|
|
6799
|
-
[State.FullColumnSeparator]: {
|
|
6800
|
-
SPACE: goTo(State.FullColumnSeparator),
|
|
6801
|
-
OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
|
|
6802
|
-
},
|
|
6803
|
-
[State.FullRowSeparator]: {
|
|
6804
|
-
SPACE: goTo(State.FullRowSeparator),
|
|
6805
|
-
OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
|
|
6806
|
-
},
|
|
6807
|
-
[State.Separator]: {
|
|
6808
|
-
SPACE: goTo(State.Separator),
|
|
6809
|
-
OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
|
|
6810
|
-
},
|
|
6811
|
-
[State.RightRef]: {
|
|
6812
|
-
SPACE: goTo(State.RightRef),
|
|
6813
|
-
NUMBER: goTo(State.Found),
|
|
6814
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
6815
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
|
|
6816
|
-
},
|
|
6817
|
-
[State.RightColumnRef]: {
|
|
6818
|
-
SPACE: goTo(State.RightColumnRef),
|
|
6819
|
-
SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
|
|
6820
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
6821
|
-
},
|
|
6822
|
-
[State.RightRowRef]: {
|
|
6823
|
-
SPACE: goTo(State.RightRowRef),
|
|
6824
|
-
NUMBER: goTo(State.Found),
|
|
6825
|
-
REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
|
|
6826
|
-
SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
|
|
6827
|
-
},
|
|
6828
|
-
[State.Found]: {},
|
|
6829
|
-
};
|
|
6830
|
-
/**
|
|
6831
|
-
* Check if the list of tokens starts with a sequence of tokens representing
|
|
6832
|
-
* a range.
|
|
6833
|
-
* If a range is found, the sequence is removed from the list and is returned
|
|
6834
|
-
* as a single token.
|
|
6835
|
-
*/
|
|
6836
|
-
function matchReference(tokens) {
|
|
6837
|
-
let head = 0;
|
|
6838
|
-
let transitions = machine[State.LeftRef];
|
|
6839
|
-
let matchedTokens = "";
|
|
6840
|
-
while (transitions !== undefined) {
|
|
6841
|
-
const token = tokens[head++];
|
|
6842
|
-
if (!token) {
|
|
6843
|
-
return null;
|
|
6844
|
-
}
|
|
6845
|
-
const transition = transitions[token.type]?.find((transition) => transition.guard(token));
|
|
6846
|
-
const nextState = transition ? transition.goTo : undefined;
|
|
6847
|
-
switch (nextState) {
|
|
6848
|
-
case undefined:
|
|
6849
|
-
return null;
|
|
6850
|
-
case State.Found:
|
|
6851
|
-
matchedTokens += token.value;
|
|
6852
|
-
tokens.splice(0, head);
|
|
6853
|
-
return {
|
|
6854
|
-
type: "REFERENCE",
|
|
6855
|
-
value: matchedTokens,
|
|
6856
|
-
};
|
|
6857
|
-
default:
|
|
6858
|
-
transitions = machine[nextState];
|
|
6859
|
-
matchedTokens += token.value;
|
|
6860
|
-
break;
|
|
6861
|
-
}
|
|
6862
|
-
}
|
|
6863
|
-
return null;
|
|
6864
|
-
}
|
|
6865
|
-
/**
|
|
6866
|
-
* Take the result of the tokenizer and transform it to be usable in the
|
|
6867
|
-
* manipulations of range
|
|
6868
|
-
*
|
|
6869
|
-
* @param formula
|
|
6870
|
-
*/
|
|
6871
|
-
function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
|
|
6872
|
-
const tokens = tokenize(formula, locale);
|
|
6873
|
-
const result = [];
|
|
6874
|
-
while (tokens.length) {
|
|
6875
|
-
result.push(matchReference(tokens) || tokens.shift());
|
|
6876
|
-
}
|
|
6877
|
-
return result;
|
|
6878
|
-
}
|
|
6879
|
-
|
|
6880
6885
|
/**
|
|
6881
6886
|
* Add the following information on tokens:
|
|
6882
6887
|
* - length
|
|
@@ -9200,7 +9205,6 @@ class ChartJsComponent extends owl.Component {
|
|
|
9200
9205
|
};
|
|
9201
9206
|
canvas = owl.useRef("graphContainer");
|
|
9202
9207
|
chart;
|
|
9203
|
-
currentRuntime;
|
|
9204
9208
|
get background() {
|
|
9205
9209
|
return this.chartRuntime.background;
|
|
9206
9210
|
}
|
|
@@ -9217,18 +9221,11 @@ class ChartJsComponent extends owl.Component {
|
|
|
9217
9221
|
setup() {
|
|
9218
9222
|
owl.onMounted(() => {
|
|
9219
9223
|
const runtime = this.chartRuntime;
|
|
9220
|
-
this.currentRuntime = runtime;
|
|
9221
9224
|
// Note: chartJS modify the runtime in place, so it's important to give it a copy
|
|
9222
9225
|
this.createChart(deepCopy(runtime.chartJsConfig));
|
|
9223
9226
|
});
|
|
9224
9227
|
owl.onWillUnmount(() => this.chart?.destroy());
|
|
9225
|
-
owl.useEffect(() =>
|
|
9226
|
-
const runtime = this.chartRuntime;
|
|
9227
|
-
if (!deepEquals(runtime, this.currentRuntime, "ignoreFunctions")) {
|
|
9228
|
-
this.currentRuntime = runtime;
|
|
9229
|
-
this.updateChartJs(deepCopy(runtime));
|
|
9230
|
-
}
|
|
9231
|
-
});
|
|
9228
|
+
owl.useEffect(() => this.updateChartJs(deepCopy(this.chartRuntime)), () => [this.chartRuntime]);
|
|
9232
9229
|
}
|
|
9233
9230
|
createChart(chartData) {
|
|
9234
9231
|
const canvas = this.canvas.el;
|
|
@@ -19630,7 +19627,7 @@ function truncateLabel(label) {
|
|
|
19630
19627
|
/**
|
|
19631
19628
|
* Get a default chart js configuration
|
|
19632
19629
|
*/
|
|
19633
|
-
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
|
|
19630
|
+
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels = true }) {
|
|
19634
19631
|
const options = {
|
|
19635
19632
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
19636
19633
|
responsive: true,
|
|
@@ -20548,10 +20545,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
20548
20545
|
const cumulative = "cumulative" in chart ? chart.cumulative : false;
|
|
20549
20546
|
const colors = new ChartColors();
|
|
20550
20547
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
20551
|
-
if (["linear", "time"].includes(axisType)) {
|
|
20552
|
-
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
20553
|
-
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
20554
|
-
}
|
|
20555
20548
|
const color = colors.next();
|
|
20556
20549
|
let backgroundRGBA = colorToRGBA(color);
|
|
20557
20550
|
if (stacked) {
|
|
@@ -20567,6 +20560,10 @@ function createLineOrScatterChartRuntime(chart, getters) {
|
|
|
20567
20560
|
return value;
|
|
20568
20561
|
});
|
|
20569
20562
|
}
|
|
20563
|
+
if (["linear", "time"].includes(axisType)) {
|
|
20564
|
+
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
20565
|
+
data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
|
|
20566
|
+
}
|
|
20570
20567
|
const backgroundColor = rgbaToHex(backgroundRGBA);
|
|
20571
20568
|
const dataset = {
|
|
20572
20569
|
label,
|
|
@@ -30424,7 +30421,13 @@ class SettingsPanel extends owl.Component {
|
|
|
30424
30421
|
}
|
|
30425
30422
|
async loadLocales() {
|
|
30426
30423
|
this.loadedLocales = (await this.env.loadLocales())
|
|
30427
|
-
.filter(
|
|
30424
|
+
.filter((locale) => {
|
|
30425
|
+
const isValid = isValidLocale(locale);
|
|
30426
|
+
if (!isValid) {
|
|
30427
|
+
console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
|
|
30428
|
+
}
|
|
30429
|
+
return isValid;
|
|
30430
|
+
})
|
|
30428
30431
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
30429
30432
|
}
|
|
30430
30433
|
get numberFormatPreview() {
|
|
@@ -36232,6 +36235,7 @@ class Grid extends owl.Component {
|
|
|
36232
36235
|
return;
|
|
36233
36236
|
}
|
|
36234
36237
|
if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
|
|
36238
|
+
ev.preventDefault();
|
|
36235
36239
|
const content = clipboardData.getData(ClipboardMIMEType.PlainText);
|
|
36236
36240
|
const target = this.env.model.getters.getSelectedZones();
|
|
36237
36241
|
const clipboardString = this.env.model.getters.getClipboardTextContent();
|
|
@@ -40808,6 +40812,21 @@ class BordersPlugin extends CorePlugin {
|
|
|
40808
40812
|
return [];
|
|
40809
40813
|
return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
|
|
40810
40814
|
}
|
|
40815
|
+
/**
|
|
40816
|
+
* Get all the rows which contains at least a border
|
|
40817
|
+
*/
|
|
40818
|
+
getRowsWithBorders(sheetId) {
|
|
40819
|
+
const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
|
|
40820
|
+
if (!sheetBorders)
|
|
40821
|
+
return [];
|
|
40822
|
+
const rowsWithBorders = new Set();
|
|
40823
|
+
for (const rowBorders of sheetBorders) {
|
|
40824
|
+
for (const rowBorder in rowBorders) {
|
|
40825
|
+
rowsWithBorders.add(parseInt(rowBorder, 10));
|
|
40826
|
+
}
|
|
40827
|
+
}
|
|
40828
|
+
return Array.from(rowsWithBorders);
|
|
40829
|
+
}
|
|
40811
40830
|
/**
|
|
40812
40831
|
* Get the range of all the rows in the sheet
|
|
40813
40832
|
*/
|
|
@@ -40857,7 +40876,7 @@ class BordersPlugin extends CorePlugin {
|
|
|
40857
40876
|
destructive: false,
|
|
40858
40877
|
});
|
|
40859
40878
|
}
|
|
40860
|
-
this.
|
|
40879
|
+
this.getRowsWithBorders(sheetId)
|
|
40861
40880
|
.filter((row) => row >= start)
|
|
40862
40881
|
.sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
|
|
40863
40882
|
.forEach((row) => {
|
|
@@ -47480,7 +47499,7 @@ class PositionSet {
|
|
|
47480
47499
|
return this.sheets[position.sheetId].getValue(position) === 1;
|
|
47481
47500
|
}
|
|
47482
47501
|
clear() {
|
|
47483
|
-
const insertions = this
|
|
47502
|
+
const insertions = [...this];
|
|
47484
47503
|
this.insertions = [];
|
|
47485
47504
|
for (const sheetId in this.sheets) {
|
|
47486
47505
|
this.sheets[sheetId].clear();
|
|
@@ -47798,6 +47817,7 @@ class Evaluator {
|
|
|
47798
47817
|
}
|
|
47799
47818
|
finally {
|
|
47800
47819
|
this.cellsBeingComputed.delete(cellId);
|
|
47820
|
+
this.nextPositionsToUpdate.delete(position);
|
|
47801
47821
|
}
|
|
47802
47822
|
}
|
|
47803
47823
|
computeAndSave(position) {
|
|
@@ -47822,8 +47842,33 @@ class Evaluator {
|
|
|
47822
47842
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
47823
47843
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
47824
47844
|
this.spreadValues(formulaPosition, formulaReturn));
|
|
47845
|
+
this.invalidatePositionsDependingOnSpread(formulaPosition, nbColumns, nbRows);
|
|
47825
47846
|
return createEvaluatedCell(nullValueToZeroValue(formulaReturn[0][0]), this.getters.getLocale(), cellData);
|
|
47826
47847
|
}
|
|
47848
|
+
invalidatePositionsDependingOnSpread(arrayFormulaPosition, nbColumns, nbRows) {
|
|
47849
|
+
// the result matrix is split in 2 zones to exclude the array formula position
|
|
47850
|
+
const top = arrayFormulaPosition.row;
|
|
47851
|
+
const left = arrayFormulaPosition.col;
|
|
47852
|
+
const bottom = top + nbRows - 1;
|
|
47853
|
+
const leftColumnZone = {
|
|
47854
|
+
top: top + 1,
|
|
47855
|
+
bottom,
|
|
47856
|
+
left,
|
|
47857
|
+
right: left,
|
|
47858
|
+
};
|
|
47859
|
+
const rightPartZone = {
|
|
47860
|
+
top,
|
|
47861
|
+
bottom,
|
|
47862
|
+
left: left + 1,
|
|
47863
|
+
right: left + nbColumns - 1,
|
|
47864
|
+
};
|
|
47865
|
+
const sheetId = arrayFormulaPosition.sheetId;
|
|
47866
|
+
const invalidatedPositions = this.formulaDependencies().getCellsDependingOn([
|
|
47867
|
+
{ sheetId, zone: rightPartZone },
|
|
47868
|
+
{ sheetId, zone: leftColumnZone },
|
|
47869
|
+
]);
|
|
47870
|
+
this.nextPositionsToUpdate.addMany(invalidatedPositions);
|
|
47871
|
+
}
|
|
47827
47872
|
assertSheetHasEnoughSpaceToSpreadFormulaResult({ sheetId, col, row }, matrixResult) {
|
|
47828
47873
|
const numberOfCols = this.getters.getNumberCols(sheetId);
|
|
47829
47874
|
const numberOfRows = this.getters.getNumberRows(sheetId);
|
|
@@ -47866,9 +47911,6 @@ class Evaluator {
|
|
|
47866
47911
|
const cell = this.getters.getCell(position);
|
|
47867
47912
|
const evaluatedCell = createEvaluatedCell(nullValueToZeroValue(matrixResult[i][j]), this.getters.getLocale(), cell);
|
|
47868
47913
|
this.evaluatedCells.set(position, evaluatedCell);
|
|
47869
|
-
// check if formula dependencies present in the spread zone
|
|
47870
|
-
// if so, they need to be recomputed
|
|
47871
|
-
this.nextPositionsToUpdate.addMany(this.getCellsDependingOn([position]));
|
|
47872
47914
|
};
|
|
47873
47915
|
}
|
|
47874
47916
|
invalidateSpreading(position) {
|
|
@@ -60841,6 +60883,6 @@ exports.tokenColors = tokenColors;
|
|
|
60841
60883
|
exports.tokenize = tokenize;
|
|
60842
60884
|
|
|
60843
60885
|
|
|
60844
|
-
__info__.version = "17.2.
|
|
60845
|
-
__info__.date = "2024-07-
|
|
60846
|
-
__info__.hash = "
|
|
60886
|
+
__info__.version = "17.2.16";
|
|
60887
|
+
__info__.date = "2024-07-11T06:38:53.101Z";
|
|
60888
|
+
__info__.hash = "9f20685";
|
package/dist/o-spreadsheet.d.ts
CHANGED
|
@@ -1545,7 +1545,7 @@ type LocaleCode = string & Alias;
|
|
|
1545
1545
|
interface Locale {
|
|
1546
1546
|
name: string;
|
|
1547
1547
|
code: LocaleCode;
|
|
1548
|
-
thousandsSeparator
|
|
1548
|
+
thousandsSeparator?: string;
|
|
1549
1549
|
decimalSeparator: string;
|
|
1550
1550
|
dateFormat: string;
|
|
1551
1551
|
timeFormat: string;
|
|
@@ -2276,6 +2276,10 @@ declare class BordersPlugin extends CorePlugin<BordersPluginState> implements Bo
|
|
|
2276
2276
|
* Get all the columns which contains at least a border
|
|
2277
2277
|
*/
|
|
2278
2278
|
private getColumnsWithBorders;
|
|
2279
|
+
/**
|
|
2280
|
+
* Get all the rows which contains at least a border
|
|
2281
|
+
*/
|
|
2282
|
+
private getRowsWithBorders;
|
|
2279
2283
|
/**
|
|
2280
2284
|
* Get the range of all the rows in the sheet
|
|
2281
2285
|
*/
|
|
@@ -4941,7 +4945,7 @@ declare function lazy<T>(fn: (() => T) | T): Lazy<T>;
|
|
|
4941
4945
|
/**
|
|
4942
4946
|
* Compares two objects.
|
|
4943
4947
|
*/
|
|
4944
|
-
declare function deepEquals(o1: any, o2: any
|
|
4948
|
+
declare function deepEquals(o1: any, o2: any): boolean;
|
|
4945
4949
|
|
|
4946
4950
|
interface ConstructorArgs {
|
|
4947
4951
|
readonly zone: Readonly<Zone | UnboundedZone>;
|
|
@@ -6866,7 +6870,6 @@ declare class ChartJsComponent extends Component<Props$y, SpreadsheetChildEnv> {
|
|
|
6866
6870
|
};
|
|
6867
6871
|
private canvas;
|
|
6868
6872
|
private chart?;
|
|
6869
|
-
private currentRuntime;
|
|
6870
6873
|
get background(): string;
|
|
6871
6874
|
get canvasStyle(): string;
|
|
6872
6875
|
get chartRuntime(): ChartJSRuntime;
|