@odoo/o-spreadsheet 17.2.13 → 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.13
7
- * @date 2024-07-02T09:03:00.731Z
8
- * @hash fac2351
6
+ * @version 17.2.15
7
+ * @date 2024-07-08T05:41:55.356Z
8
+ * @hash acfb3e7
9
9
  */
10
10
 
11
11
  'use strict';
@@ -1752,7 +1752,7 @@ const getFormulaNumberRegex = memoize(function getFormulaNumberRegex(decimalSepa
1752
1752
  });
1753
1753
  const getNumberRegex = memoize(function getNumberRegex(locale) {
1754
1754
  const decimalSeparator = escapeRegExp(locale.decimalSeparator);
1755
- const thousandsSeparator = escapeRegExp(locale.thousandsSeparator);
1755
+ const thousandsSeparator = escapeRegExp(locale.thousandsSeparator || "");
1756
1756
  const pIntegerAndDecimals = `(\\d+(${thousandsSeparator}\\d{3,})*(${decimalSeparator}\\d*)?)`; // pattern that match integer number with or without decimal digits
1757
1757
  const pOnlyDecimals = `(${decimalSeparator}\\d+)`; // pattern that match only expression with decimal digits
1758
1758
  const pScientificFormat = "(e(\\+|-)?\\d+)?"; // pattern that match scientific format between zero and one time (should be placed before pPercentFormat)
@@ -1779,7 +1779,7 @@ function isNumber(value, locale) {
1779
1779
  return getNumberRegex(locale).test(value.trim());
1780
1780
  }
1781
1781
  const getInvaluableSymbolsRegexp = memoize(function getInvaluableSymbolsRegexp(locale) {
1782
- return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator)}]`, "g");
1782
+ return new RegExp(`[\$€${escapeRegExp(locale.thousandsSeparator || "")}]`, "g");
1783
1783
  });
1784
1784
  /**
1785
1785
  * Convert a string into a number. It assumes that the string actually represents
@@ -5359,19 +5359,22 @@ class TokenizingChars {
5359
5359
  }
5360
5360
 
5361
5361
  function isValidLocale(locale) {
5362
- if (!(locale &&
5363
- typeof locale === "object" &&
5364
- typeof locale.name === "string" &&
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")) {
5362
+ if (!locale ||
5363
+ typeof locale !== "object" ||
5364
+ !(!locale.thousandsSeparator || typeof locale.thousandsSeparator === "string")) {
5371
5365
  return false;
5372
5366
  }
5373
- if (!Object.values(locale).every((v) => v)) {
5374
- return false;
5367
+ for (const property of [
5368
+ "code",
5369
+ "name",
5370
+ "decimalSeparator",
5371
+ "dateFormat",
5372
+ "timeFormat",
5373
+ "formulaArgSeparator",
5374
+ ]) {
5375
+ if (!locale[property] || typeof locale[property] !== "string") {
5376
+ return false;
5377
+ }
5375
5378
  }
5376
5379
  if (locale.formulaArgSeparator === locale.decimalSeparator) {
5377
5380
  return false;
@@ -5469,7 +5472,10 @@ function canonicalizeNumberLiteral(content, locale) {
5469
5472
  if (locale.decimalSeparator === "." || !isNumber(content, locale)) {
5470
5473
  return content;
5471
5474
  }
5472
- return content.replace(locale.thousandsSeparator, "").replace(locale.decimalSeparator, ".");
5475
+ if (locale.thousandsSeparator) {
5476
+ content = content.replaceAll(locale.thousandsSeparator, "");
5477
+ }
5478
+ return content.replace(locale.decimalSeparator, ".");
5473
5479
  }
5474
5480
  /**
5475
5481
  * Change a content string from the given locale to its canonical form (en_US locale). Also convert date string.
@@ -6453,6 +6459,146 @@ function transformRangeData(range, executed) {
6453
6459
  return undefined;
6454
6460
  }
6455
6461
 
6462
+ var State;
6463
+ (function (State) {
6464
+ /**
6465
+ * Initial state.
6466
+ * Expecting any reference for the left part of a range
6467
+ * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
6468
+ */
6469
+ State[State["LeftRef"] = 0] = "LeftRef";
6470
+ /**
6471
+ * Expecting any reference for the right part of a range
6472
+ * e.g. "A1", "1", "A", "Sheet1!A1", "Sheet1!A"
6473
+ */
6474
+ State[State["RightRef"] = 1] = "RightRef";
6475
+ /**
6476
+ * Expecting the separator without any constraint on the right part
6477
+ */
6478
+ State[State["Separator"] = 2] = "Separator";
6479
+ /**
6480
+ * Expecting the separator for a full column range
6481
+ */
6482
+ State[State["FullColumnSeparator"] = 3] = "FullColumnSeparator";
6483
+ /**
6484
+ * Expecting the separator for a full row range
6485
+ */
6486
+ State[State["FullRowSeparator"] = 4] = "FullRowSeparator";
6487
+ /**
6488
+ * Expecting the right part of a full column range
6489
+ * e.g. "1", "A1"
6490
+ */
6491
+ State[State["RightColumnRef"] = 5] = "RightColumnRef";
6492
+ /**
6493
+ * Expecting the right part of a full row range
6494
+ * e.g. "A", "A1"
6495
+ */
6496
+ State[State["RightRowRef"] = 6] = "RightRowRef";
6497
+ /**
6498
+ * Final state. A range has been matched
6499
+ */
6500
+ State[State["Found"] = 7] = "Found";
6501
+ })(State || (State = {}));
6502
+ const goTo = (state, guard = () => true) => [
6503
+ {
6504
+ goTo: state,
6505
+ guard,
6506
+ },
6507
+ ];
6508
+ const goToMulti = (state, guard = () => true) => ({
6509
+ goTo: state,
6510
+ guard,
6511
+ });
6512
+ const machine = {
6513
+ [State.LeftRef]: {
6514
+ REFERENCE: goTo(State.Separator),
6515
+ NUMBER: goTo(State.FullRowSeparator),
6516
+ SYMBOL: [
6517
+ goToMulti(State.FullColumnSeparator, (token) => isColReference(token.value)),
6518
+ goToMulti(State.FullRowSeparator, (token) => isRowReference(token.value)),
6519
+ ],
6520
+ },
6521
+ [State.FullColumnSeparator]: {
6522
+ SPACE: goTo(State.FullColumnSeparator),
6523
+ OPERATOR: goTo(State.RightColumnRef, (token) => token.value === ":"),
6524
+ },
6525
+ [State.FullRowSeparator]: {
6526
+ SPACE: goTo(State.FullRowSeparator),
6527
+ OPERATOR: goTo(State.RightRowRef, (token) => token.value === ":"),
6528
+ },
6529
+ [State.Separator]: {
6530
+ SPACE: goTo(State.Separator),
6531
+ OPERATOR: goTo(State.RightRef, (token) => token.value === ":"),
6532
+ },
6533
+ [State.RightRef]: {
6534
+ SPACE: goTo(State.RightRef),
6535
+ NUMBER: goTo(State.Found),
6536
+ REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
6537
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value) || isRowHeader(token.value)),
6538
+ },
6539
+ [State.RightColumnRef]: {
6540
+ SPACE: goTo(State.RightColumnRef),
6541
+ SYMBOL: goTo(State.Found, (token) => isColHeader(token.value)),
6542
+ REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
6543
+ },
6544
+ [State.RightRowRef]: {
6545
+ SPACE: goTo(State.RightRowRef),
6546
+ NUMBER: goTo(State.Found),
6547
+ REFERENCE: goTo(State.Found, (token) => isSingleCellReference(token.value)),
6548
+ SYMBOL: goTo(State.Found, (token) => isRowHeader(token.value)),
6549
+ },
6550
+ [State.Found]: {},
6551
+ };
6552
+ /**
6553
+ * Check if the list of tokens starts with a sequence of tokens representing
6554
+ * a range.
6555
+ * If a range is found, the sequence is removed from the list and is returned
6556
+ * as a single token.
6557
+ */
6558
+ function matchReference(tokens) {
6559
+ let head = 0;
6560
+ let transitions = machine[State.LeftRef];
6561
+ let matchedTokens = "";
6562
+ while (transitions !== undefined) {
6563
+ const token = tokens[head++];
6564
+ if (!token) {
6565
+ return null;
6566
+ }
6567
+ const transition = transitions[token.type]?.find((transition) => transition.guard(token));
6568
+ const nextState = transition ? transition.goTo : undefined;
6569
+ switch (nextState) {
6570
+ case undefined:
6571
+ return null;
6572
+ case State.Found:
6573
+ matchedTokens += token.value;
6574
+ tokens.splice(0, head);
6575
+ return {
6576
+ type: "REFERENCE",
6577
+ value: matchedTokens,
6578
+ };
6579
+ default:
6580
+ transitions = machine[nextState];
6581
+ matchedTokens += token.value;
6582
+ break;
6583
+ }
6584
+ }
6585
+ return null;
6586
+ }
6587
+ /**
6588
+ * Take the result of the tokenizer and transform it to be usable in the
6589
+ * manipulations of range
6590
+ *
6591
+ * @param formula
6592
+ */
6593
+ function rangeTokenize(formula, locale = DEFAULT_LOCALE) {
6594
+ const tokens = tokenize(formula, locale);
6595
+ const result = [];
6596
+ while (tokens.length) {
6597
+ result.push(matchReference(tokens) || tokens.shift());
6598
+ }
6599
+ return result;
6600
+ }
6601
+
6456
6602
  const functionRegex = /[a-zA-Z0-9\_]+(\.[a-zA-Z0-9\_]+)*/;
6457
6603
  const UNARY_OPERATORS_PREFIX = ["-", "+"];
6458
6604
  const UNARY_OPERATORS_POSTFIX = ["%"];
@@ -6601,7 +6747,7 @@ function parseExpression(tokens, parent_priority = 0) {
6601
6747
  * Parse an expression (as a string) into an AST.
6602
6748
  */
6603
6749
  function parse(str) {
6604
- return parseTokens(tokenize(str));
6750
+ return parseTokens(rangeTokenize(str));
6605
6751
  }
6606
6752
  function parseTokens(tokens) {
6607
6753
  tokens = tokens.filter((x) => x.type !== "SPACE");
@@ -6737,146 +6883,6 @@ function rightOperandToFormula(operationAST) {
6737
6883
  return needParenthesis ? `(${astToFormula(rightOperation)})` : astToFormula(rightOperation);
6738
6884
  }
6739
6885
 
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
6886
  /**
6881
6887
  * Add the following information on tokens:
6882
6888
  * - length
@@ -20548,10 +20554,6 @@ function createLineOrScatterChartRuntime(chart, getters) {
20548
20554
  const cumulative = "cumulative" in chart ? chart.cumulative : false;
20549
20555
  const colors = new ChartColors();
20550
20556
  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
20557
  const color = colors.next();
20556
20558
  let backgroundRGBA = colorToRGBA(color);
20557
20559
  if (stacked) {
@@ -20567,6 +20569,10 @@ function createLineOrScatterChartRuntime(chart, getters) {
20567
20569
  return value;
20568
20570
  });
20569
20571
  }
20572
+ if (["linear", "time"].includes(axisType)) {
20573
+ // Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
20574
+ data = data.map((y, index) => ({ x: labels[index] || undefined, y }));
20575
+ }
20570
20576
  const backgroundColor = rgbaToHex(backgroundRGBA);
20571
20577
  const dataset = {
20572
20578
  label,
@@ -30424,7 +30430,13 @@ class SettingsPanel extends owl.Component {
30424
30430
  }
30425
30431
  async loadLocales() {
30426
30432
  this.loadedLocales = (await this.env.loadLocales())
30427
- .filter(isValidLocale)
30433
+ .filter((locale) => {
30434
+ const isValid = isValidLocale(locale);
30435
+ if (!isValid) {
30436
+ console.warn(`Invalid locale: ${locale["code"]} ${locale}`);
30437
+ }
30438
+ return isValid;
30439
+ })
30428
30440
  .sort((a, b) => a.name.localeCompare(b.name));
30429
30441
  }
30430
30442
  get numberFormatPreview() {
@@ -36232,6 +36244,7 @@ class Grid extends owl.Component {
36232
36244
  return;
36233
36245
  }
36234
36246
  if (clipboardData.types.indexOf(ClipboardMIMEType.PlainText) > -1) {
36247
+ ev.preventDefault();
36235
36248
  const content = clipboardData.getData(ClipboardMIMEType.PlainText);
36236
36249
  const target = this.env.model.getters.getSelectedZones();
36237
36250
  const clipboardString = this.env.model.getters.getClipboardTextContent();
@@ -36493,6 +36506,8 @@ const NON_RETROCOMPATIBLE_FUNCTIONS = [
36493
36506
  "BITOR",
36494
36507
  "BITRSHIFT",
36495
36508
  "BITXOR",
36509
+ "BYCOL",
36510
+ "BYROW",
36496
36511
  "CEILING.MATH",
36497
36512
  "CEILING.PRECISE",
36498
36513
  "CHISQ.DIST",
@@ -36500,6 +36515,8 @@ const NON_RETROCOMPATIBLE_FUNCTIONS = [
36500
36515
  "CHISQ.INV",
36501
36516
  "CHISQ.INV.RT",
36502
36517
  "CHISQ.TEST",
36518
+ "CHOOSECOLS",
36519
+ "CHOOSEROWS",
36503
36520
  "COMBINA",
36504
36521
  "CONCAT",
36505
36522
  "CONFIDENCE.NORM",
@@ -36512,14 +36529,17 @@ const NON_RETROCOMPATIBLE_FUNCTIONS = [
36512
36529
  "CSCH",
36513
36530
  "DAYS",
36514
36531
  "DECIMAL",
36532
+ "DROP",
36515
36533
  "ERF.PRECISE",
36516
36534
  "ERFC.PRECISE",
36535
+ "EXPAND",
36517
36536
  "EXPON.DIST",
36518
36537
  "F.DIST",
36519
36538
  "F.DIST.RT",
36520
36539
  "F.INV",
36521
36540
  "F.INV.RT",
36522
36541
  "F.TEST",
36542
+ "FIELDVALUE",
36523
36543
  "FILTERXML",
36524
36544
  "FLOOR.MATH",
36525
36545
  "FLOOR.PRECISE",
@@ -36534,6 +36554,7 @@ const NON_RETROCOMPATIBLE_FUNCTIONS = [
36534
36554
  "GAMMA.INV",
36535
36555
  "GAMMALN.PRECISE",
36536
36556
  "GAUSS",
36557
+ "HSTACK",
36537
36558
  "HYPGEOM.DIST",
36538
36559
  "IFNA",
36539
36560
  "IFS",
@@ -36546,9 +36567,14 @@ const NON_RETROCOMPATIBLE_FUNCTIONS = [
36546
36567
  "IMSINH",
36547
36568
  "IMTAN",
36548
36569
  "ISFORMULA",
36570
+ "ISOMITTED",
36549
36571
  "ISOWEEKNUM",
36572
+ "LAMBDA",
36573
+ "LET",
36550
36574
  "LOGNORM.DIST",
36551
36575
  "LOGNORM.INV",
36576
+ "MAKEARRAY",
36577
+ "MAP",
36552
36578
  "MAXIFS",
36553
36579
  "MINIFS",
36554
36580
  "MODE.MULT",
@@ -36568,17 +36594,26 @@ const NON_RETROCOMPATIBLE_FUNCTIONS = [
36568
36594
  "PERMUTATIONA",
36569
36595
  "PHI",
36570
36596
  "POISSON.DIST",
36597
+ "PQSOURCE",
36598
+ "PYTHON_STR",
36599
+ "PYTHON_TYPE",
36600
+ "PYTHON_TYPENAME",
36571
36601
  "QUARTILE.EXC",
36572
36602
  "QUARTILE.INC",
36573
36603
  "QUERYSTRING",
36604
+ "RANDARRAY",
36574
36605
  "RANK.AVG",
36575
36606
  "RANK.EQ",
36607
+ "REDUCE",
36576
36608
  "RRI",
36609
+ "SCAN",
36577
36610
  "SEC",
36578
36611
  "SECH",
36612
+ "SEQUENCE",
36579
36613
  "SHEET",
36580
36614
  "SHEETS",
36581
36615
  "SKEW.P",
36616
+ "SORTBY",
36582
36617
  "STDEV.P",
36583
36618
  "STDEV.S",
36584
36619
  "SWITCH",
@@ -36588,13 +36623,24 @@ const NON_RETROCOMPATIBLE_FUNCTIONS = [
36588
36623
  "T.INV",
36589
36624
  "T.INV.2T",
36590
36625
  "T.TEST",
36626
+ "TAKE",
36627
+ "TEXTAFTER",
36628
+ "TEXTBEFORE",
36591
36629
  "TEXTJOIN",
36630
+ "TEXTSPLIT",
36631
+ "TOCOL",
36632
+ "TOROW",
36592
36633
  "UNICHAR",
36593
36634
  "UNICODE",
36635
+ "UNIQUE",
36594
36636
  "VAR.P",
36595
36637
  "VAR.S",
36638
+ "VSTACK",
36596
36639
  "WEBSERVICE",
36597
36640
  "WEIBULL.DIST",
36641
+ "WRAPCOLS",
36642
+ "WRAPROWS",
36643
+ "XLOOKUP",
36598
36644
  "XOR",
36599
36645
  "Z.TEST",
36600
36646
  ];
@@ -40775,6 +40821,21 @@ class BordersPlugin extends CorePlugin {
40775
40821
  return [];
40776
40822
  return Object.keys(sheetBorders).map((index) => parseInt(index, 10));
40777
40823
  }
40824
+ /**
40825
+ * Get all the rows which contains at least a border
40826
+ */
40827
+ getRowsWithBorders(sheetId) {
40828
+ const sheetBorders = this.borders[sheetId]?.filter(isDefined$1);
40829
+ if (!sheetBorders)
40830
+ return [];
40831
+ const rowsWithBorders = new Set();
40832
+ for (const rowBorders of sheetBorders) {
40833
+ for (const rowBorder in rowBorders) {
40834
+ rowsWithBorders.add(parseInt(rowBorder, 10));
40835
+ }
40836
+ }
40837
+ return Array.from(rowsWithBorders);
40838
+ }
40778
40839
  /**
40779
40840
  * Get the range of all the rows in the sheet
40780
40841
  */
@@ -40824,7 +40885,7 @@ class BordersPlugin extends CorePlugin {
40824
40885
  destructive: false,
40825
40886
  });
40826
40887
  }
40827
- this.getRowsRange(sheetId)
40888
+ this.getRowsWithBorders(sheetId)
40828
40889
  .filter((row) => row >= start)
40829
40890
  .sort((a, b) => (delta < 0 ? a - b : b - a)) // start by the end when moving up
40830
40891
  .forEach((row) => {
@@ -60808,6 +60869,6 @@ exports.tokenColors = tokenColors;
60808
60869
  exports.tokenize = tokenize;
60809
60870
 
60810
60871
 
60811
- __info__.version = "17.2.13";
60812
- __info__.date = "2024-07-02T09:03:00.731Z";
60813
- __info__.hash = "fac2351";
60872
+ __info__.version = "17.2.15";
60873
+ __info__.date = "2024-07-08T05:41:55.356Z";
60874
+ __info__.hash = "acfb3e7";
@@ -1545,7 +1545,7 @@ type LocaleCode = string & Alias;
1545
1545
  interface Locale {
1546
1546
  name: string;
1547
1547
  code: LocaleCode;
1548
- thousandsSeparator: string;
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
  */