@odoo/o-spreadsheet 17.2.14 → 17.2.15

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.
@@ -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.14
7
- * @date 2024-07-02T10:35:53.850Z
8
- * @hash fb0d979
6
+ * @version 17.2.15
7
+ * @date 2024-07-08T05:41:55.356Z
8
+ * @hash acfb3e7
9
9
  */
10
10
 
11
11
  (function (exports, owl) {
@@ -1751,7 +1751,7 @@
1751
1751
  });
1752
1752
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1753
1753
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
1754
- const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
1754
+ const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
1755
1755
  const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1756
1756
  const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1757
1757
  const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
@@ -1778,7 +1778,7 @@
1778
1778
  return getNumberRegex(locale).test(value.trim());
1779
1779
  }
1780
1780
  const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
1781
- return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
1781
+ return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
1782
1782
  });
1783
1783
  /**
1784
1784
  * Convert a string into a number. It assumes that the string actually represents
@@ -5358,19 +5358,22 @@
5358
5358
  }
5359
5359
 
5360
5360
  function isValidLocale(locale) {
5361
- if (!(locale &&
5362
- typeof locale === "object" &&
5363
- typeof locale.name === "string" &&
5364
- typeof locale.code === "string" &&
5365
- typeof locale.thousandsSeparator === "string" &&
5366
- typeof locale.decimalSeparator === "string" &&
5367
- typeof locale.dateFormat === "string" &&
5368
- typeof locale.timeFormat === "string" &&
5369
- typeof locale.formulaArgSeparator === "string")) {
5361
+ if (!locale ||
5362
+ typeof locale !== "object" ||
5363
+ !(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
5370
5364
  return false;
5371
5365
  }
5372
- if (!Object.values(locale).every((v) => v)) {
5373
- return false;
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
+ }
5374
5377
  }
5375
5378
  if (locale.formulaArgSeparator === locale.decimalSeparator) {
5376
5379
  return false;
@@ -5468,7 +5471,10 @@
5468
5471
  if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
5469
5472
  return content;
5470
5473
  }
5471
- return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
5474
+ if (locale.thousandsSeparator) {
5475
+ content = content.replaceAll(locale.thousandsSeparator, "");
5476
+ }
5477
+ return content.replace(locale.decimalSeparator, ".");
5472
5478
  }
5473
5479
  /**
5474
5480
  * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
@@ -6452,6 +6458,146 @@
6452
6458
  return undefined;
6453
6459
  }
6454
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
+
6455
6601
  const functionRegex = /[a-zA-Z0-9\_]+(\.[a-zA-Z0-9\_]+)*/;
6456
6602
  const UNARY_OPERATORS_PREFIX = ["-", "+"];
6457
6603
  const UNARY_OPERATORS_POSTFIX = ["%"];
@@ -6600,7 +6746,7 @@
6600
6746
  * Parse an expression (as a string) into an AST.
6601
6747
  */
6602
6748
  function parse(str) {
6603
- return parseTokens(tokenize(str));
6749
+ return parseTokens(rangeTokenize(str));
6604
6750
  }
6605
6751
  function parseTokens(tokens) {
6606
6752
  tokens = tokens.filter((x) => x.type !== "SPACE");
@@ -6736,146 +6882,6 @@
6736
6882
  return needParenthesis ? `(${astToFormula(rightOperation)})` : astToFormula(rightOperation);
6737
6883
  }
6738
6884
 
6739
- var State;
6740
- (function (State) {
6741
- /**
6742
- * Initial state.
6743
- * Expecting any reference for the left part of a range
6744
- * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
6745
- */
6746
- State[State["LeftRef"] = 0] = "LeftRef";
6747
- /**
6748
- * Expecting any reference for the right part of a range
6749
- * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
6750
- */
6751
- State[State["RightRef"] = 1] = "RightRef";
6752
- /**
6753
- * Expecting the separator without any constraint on the right part
6754
- */
6755
- State[State["Separator"] = 2] = "Separator";
6756
- /**
6757
- * Expecting the separator for a full column range
6758
- */
6759
- State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
6760
- /**
6761
- * Expecting the separator for a full row range
6762
- */
6763
- State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
6764
- /**
6765
- * Expecting the right part of a full column range
6766
- * e.g. "1", "A1"
6767
- */
6768
- State[State["RightColumnRef"] = 5] = "RightColumnRef";
6769
- /**
6770
- * Expecting the right part of a full row range
6771
- * e.g. "A", "A1"
6772
- */
6773
- State[State["RightRowRef"] = 6] = "RightRowRef";
6774
- /**
6775
- * Final state. A range has been matched
6776
- */
6777
- State[State["Found"] = 7] = "Found";
6778
- })(State || (State = {}));
6779
- const goTo = (state, guard = () => true) => [
6780
- {
6781
- goTo: state,
6782
- guard,
6783
- },
6784
- ];
6785
- const goToMulti = (state, guard = () => true) => ({
6786
- goTo: state,
6787
- guard,
6788
- });
6789
- const machine = {
6790
- [State.LeftRef]: {
6791
- REFERENCE: goTo(State.Separator),
6792
- NUMBER: goTo(State.FullRowSeparator),
6793
- SYMBOL: [
6794
- goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
6795
- goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
6796
- ],
6797
- },
6798
- [State.FullColumnSeparator]: {
6799
- SPACE: goTo(State.FullColumnSeparator),
6800
- OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
6801
- },
6802
- [State.FullRowSeparator]: {
6803
- SPACE: goTo(State.FullRowSeparator),
6804
- OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
6805
- },
6806
- [State.Separator]: {
6807
- SPACE: goTo(State.Separator),
6808
- OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
6809
- },
6810
- [State.RightRef]: {
6811
- SPACE: goTo(State.RightRef),
6812
- NUMBER: goTo(State.Found),
6813
- REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
6814
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
6815
- },
6816
- [State.RightColumnRef]: {
6817
- SPACE: goTo(State.RightColumnRef),
6818
- SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
6819
- REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
6820
- },
6821
- [State.RightRowRef]: {
6822
- SPACE: goTo(State.RightRowRef),
6823
- NUMBER: goTo(State.Found),
6824
- REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
6825
- SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
6826
- },
6827
- [State.Found]: {},
6828
- };
6829
- /**
6830
- * Check if the list of tokens starts with a sequence of tokens representing
6831
- * a range.
6832
- * If a range is found, the sequence is removed from the list and is returned
6833
- * as a single token.
6834
- */
6835
- function matchReference(tokens) {
6836
- let head = 0;
6837
- let transitions = machine[State.LeftRef];
6838
- let matchedTokens = "";
6839
- while (transitions !== undefined) {
6840
- const token = tokens[head++];
6841
- if (!token) {
6842
- return null;
6843
- }
6844
- const transition = transitions[token.type]?.find((transition) => transition.guard(token));
6845
- const nextState = transition ? transition.goTo : undefined;
6846
- switch (nextState) {
6847
- case undefined:
6848
- return null;
6849
- case State.Found:
6850
- matchedTokens += token.value;
6851
- tokens.splice(0, head);
6852
- return {
6853
- type: "REFERENCE",
6854
- value: matchedTokens,
6855
- };
6856
- default:
6857
- transitions = machine[nextState];
6858
- matchedTokens += token.value;
6859
- break;
6860
- }
6861
- }
6862
- return null;
6863
- }
6864
- /**
6865
- * Take the result of the tokenizer and transform it to be usable in the
6866
- * manipulations of range
6867
- *
6868
- * @param formula
6869
- */
6870
- function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
6871
- const tokens = tokenize(formula, locale);
6872
- const result = [];
6873
- while (tokens.length) {
6874
- result.push(matchReference(tokens) || tokens.shift());
6875
- }
6876
- return result;
6877
- }
6878
-
6879
6885
  /**
6880
6886
  * Add the following information on tokens:
6881
6887
  * - length
@@ -20547,10 +20553,6 @@ stores.inject(MyMetaStore, storeInstance);
20547
20553
  const cumulative = "cumulative" in chart ? chart.cumulative : false;
20548
20554
  const colors = new ChartColors();
20549
20555
  for (let [index, { label, data }] of dataSetsValues.entries()) {
20550
- if (["linear", "time"].includes(axisType)) {
20551
- // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
20552
- data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
20553
- }
20554
20556
  const color = colors.next();
20555
20557
  let backgroundRGBA = colorToRGBA(color);
20556
20558
  if (stacked) {
@@ -20566,6 +20568,10 @@ stores.inject(MyMetaStore, storeInstance);
20566
20568
  return value;
20567
20569
  });
20568
20570
  }
20571
+ if (["linear", "time"].includes(axisType)) {
20572
+ // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
20573
+ data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
20574
+ }
20569
20575
  const backgroundColor = rgbaToHex(backgroundRGBA);
20570
20576
  const dataset = {
20571
20577
  label,
@@ -30423,7 +30429,13 @@ stores.inject(MyMetaStore, storeInstance);
30423
30429
  }
30424
30430
  async loadLocales() {
30425
30431
  this.loadedLocales = (await this.env.loadLocales())
30426
- .filter(isValidLocale)
30432
+ .filter((locale) => {
30433
+ const isValid = isValidLocale(locale);
30434
+ if (!isValid) {
30435
+ console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
30436
+ }
30437
+ return isValid;
30438
+ })
30427
30439
  .sort((a, b) => a.name.localeCompare(b.name));
30428
30440
  }
30429
30441
  get numberFormatPreview() {
@@ -36231,6 +36243,7 @@ stores.inject(MyMetaStore, storeInstance);
36231
36243
  return;
36232
36244
  }
36233
36245
  if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
36246
+ ev.preventDefault();
36234
36247
  const content = clipboardData.getData(ClipboardMIMEType.PlainText);
36235
36248
  const target = this.env.model.getters.getSelectedZones();
36236
36249
  const clipboardString = this.env.model.getters.getClipboardTextContent();
@@ -40807,6 +40820,21 @@ stores.inject(MyMetaStore, storeInstance);
40807
40820
  return [];
40808
40821
  return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
40809
40822
  }
40823
+ /**
40824
+ * Get all the rows which contains at least a border
40825
+ */
40826
+ getRowsWithBorders(sheetId) {
40827
+ const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
40828
+ if (!sheetBorders)
40829
+ return [];
40830
+ const rowsWithBorders = new Set();
40831
+ for (const rowBorders of sheetBorders) {
40832
+ for (const rowBorder in rowBorders) {
40833
+ rowsWithBorders.add(parseInt(rowBorder, 10));
40834
+ }
40835
+ }
40836
+ return Array.from(rowsWithBorders);
40837
+ }
40810
40838
  /**
40811
40839
  * Get the range of all the rows in the sheet
40812
40840
  */
@@ -40856,7 +40884,7 @@ stores.inject(MyMetaStore, storeInstance);
40856
40884
  destructive: false,
40857
40885
  });
40858
40886
  }
40859
- this.getRowsRange(sheetId)
40887
+ this.getRowsWithBorders(sheetId)
40860
40888
  .filter((row) => row >= start)
40861
40889
  .sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
40862
40890
  .forEach((row) => {
@@ -60840,9 +60868,9 @@ stores.inject(MyMetaStore, storeInstance);
60840
60868
  exports.tokenize = tokenize;
60841
60869
 
60842
60870
 
60843
- __info__.version = "17.2.14";
60844
- __info__.date = "2024-07-02T10:35:53.850Z";
60845
- __info__.hash = "fb0d979";
60871
+ __info__.version = "17.2.15";
60872
+ __info__.date = "2024-07-08T05:41:55.356Z";
60873
+ __info__.hash = "acfb3e7";
60846
60874
 
60847
60875
 
60848
60876
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);