@odoo/o-spreadsheet 16.0.65 → 16.0.67

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.
@@ -6956,7 +6956,7 @@ function transformZone(zone, executed) {
6956
6956
  if (executed.type === "ADD_COLUMNS_ROWS") {
6957
6957
  return expandZoneOnInsertion(zone, executed.dimension === "COL" ? "left" : "top", executed.base, executed.position, executed.quantity);
6958
6958
  }
6959
- return { ...zone };
6959
+ return zone;
6960
6960
  }
6961
6961
 
6962
6962
  /**
@@ -7386,7 +7386,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
7386
7386
  }
7387
7387
  }
7388
7388
  else if (dataSets.length === 1) {
7389
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
7389
+ const dataLength = getData(getters, dataSets[0]).length;
7390
+ for (let i = 0; i < dataLength; i++) {
7390
7391
  labels.formattedValues.push("");
7391
7392
  labels.values.push("");
7392
7393
  }
@@ -18418,7 +18419,13 @@ function tokenizeString(chars) {
18418
18419
  }
18419
18420
  return null;
18420
18421
  }
18421
- const separatorRegexp = /\w|\.|!|\$/;
18422
+ /**
18423
+ - \p{L} is for any letter (from any language)
18424
+ - \p{N} is for any number
18425
+ - the u flag at the end is for unicode, which enables the `\p{...}` syntax
18426
+ */
18427
+ const unicodeSymbolCharRegexp = /\p{L}|\p{N}|_|\.|!|\$/u;
18428
+ const SYMBOL_CHARS = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.!$");
18422
18429
  /**
18423
18430
  * A "Symbol" is just basically any word-like element that can appear in a
18424
18431
  * formula, which is not a string. So:
@@ -18458,7 +18465,7 @@ function tokenizeSymbol(chars) {
18458
18465
  };
18459
18466
  }
18460
18467
  }
18461
- while (chars[0] && chars[0].match(separatorRegexp)) {
18468
+ while (chars[0] && (SYMBOL_CHARS.has(chars[0]) || chars[0].match(unicodeSymbolCharRegexp))) {
18462
18469
  result += chars.shift();
18463
18470
  }
18464
18471
  if (result.length) {
@@ -23731,9 +23738,9 @@ const XLSX_CHART_TYPES = [
23731
23738
  /** In XLSX color format (no #) */
23732
23739
  const AUTO_COLOR = "000000";
23733
23740
  const XLSX_ICONSET_MAP = {
23734
- arrow: "3Arrows",
23741
+ arrows: "3Arrows",
23735
23742
  smiley: "3Symbols",
23736
- dot: "3TrafficLights1",
23743
+ dots: "3TrafficLights1",
23737
23744
  };
23738
23745
  const NAMESPACE = {
23739
23746
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -24122,6 +24129,7 @@ const ICON_SET_CONVERSION_MAP = {
24122
24129
  };
24123
24130
  /** Map between legend position in XLSX file and human readable position */
24124
24131
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
24132
+ none: "none",
24125
24133
  b: "bottom",
24126
24134
  t: "top",
24127
24135
  l: "left",
@@ -26299,7 +26307,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26299
26307
  ? "right"
26300
26308
  : "left",
26301
26309
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
26302
- default: "b",
26310
+ default: "none",
26303
26311
  }).asString()],
26304
26312
  stacked: barChartGrouping === "stacked",
26305
26313
  fontColor: "000000",
@@ -36214,10 +36222,8 @@ function mergeTransformation(cmd, executed) {
36214
36222
  }
36215
36223
  const target = [];
36216
36224
  for (const zone1 of cmd.target) {
36217
- for (const zone2 of executed.target) {
36218
- if (!overlap(zone1, zone2)) {
36219
- target.push({ ...zone1 });
36220
- }
36225
+ if (executed.target.every((zone2) => !overlap(zone1, zone2))) {
36226
+ target.push(zone1);
36221
36227
  }
36222
36228
  }
36223
36229
  if (target.length) {
@@ -42464,10 +42470,14 @@ function addIconSetRule(cf, rule) {
42464
42470
  continue;
42465
42471
  }
42466
42472
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
42473
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
42474
+ if (isIconSetReversed(rule.icons)) {
42475
+ iconSetAttrs.push(["reverse", "1"]);
42476
+ }
42467
42477
  conditionalFormats.push(escapeXml /*xml*/ `
42468
42478
  <conditionalFormatting sqref="${range}">
42469
42479
  <cfRule ${formatAttributes(ruleAttributes)}>
42470
- <iconSet iconSet="${getIconSet(rule.icons)}">
42480
+ <iconSet ${formatAttributes(iconSetAttrs)}>
42471
42481
  ${joinXmlNodes(cfValueObjectNodes)}
42472
42482
  </iconSet>
42473
42483
  </cfRule>
@@ -42485,9 +42495,21 @@ function commonCfAttributes(cf) {
42485
42495
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
42486
42496
  ];
42487
42497
  }
42498
+ function isIconSetReversed(iconSet) {
42499
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
42500
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
42501
+ }
42488
42502
  function getIconSet(iconSet) {
42489
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
42490
- "dots"];
42503
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
42504
+ }
42505
+ /**
42506
+ * Partial detection based on "upper" point only.
42507
+ * We support any arbitrary icon in the set, while excel doesn't allow
42508
+ * mixing icons from different types.
42509
+ */
42510
+ function detectIconsType(iconSet) {
42511
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
42512
+ return type;
42491
42513
  }
42492
42514
  function thresholdAttributes(threshold, position) {
42493
42515
  const type = getExcelThresholdType(threshold.type, position);
@@ -43760,6 +43782,6 @@ exports.setTranslationMethod = setTranslationMethod;
43760
43782
  exports.tokenize = tokenize;
43761
43783
 
43762
43784
 
43763
- __info__.version = '16.0.65';
43764
- __info__.date = '2025-03-19T08:14:11.320Z';
43765
- __info__.hash = '4e495e9';
43785
+ __info__.version = '16.0.67';
43786
+ __info__.date = '2025-04-18T16:22:13.893Z';
43787
+ __info__.hash = 'efeeb27';
@@ -6952,7 +6952,7 @@ function transformZone(zone, executed) {
6952
6952
  if (executed.type === "ADD_COLUMNS_ROWS") {
6953
6953
  return expandZoneOnInsertion(zone, executed.dimension === "COL" ? "left" : "top", executed.base, executed.position, executed.quantity);
6954
6954
  }
6955
- return { ...zone };
6955
+ return zone;
6956
6956
  }
6957
6957
 
6958
6958
  /**
@@ -7382,7 +7382,8 @@ function getChartLabelValues(getters, dataSets, labelRange) {
7382
7382
  }
7383
7383
  }
7384
7384
  else if (dataSets.length === 1) {
7385
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
7385
+ const dataLength = getData(getters, dataSets[0]).length;
7386
+ for (let i = 0; i < dataLength; i++) {
7386
7387
  labels.formattedValues.push("");
7387
7388
  labels.values.push("");
7388
7389
  }
@@ -18414,7 +18415,13 @@ function tokenizeString(chars) {
18414
18415
  }
18415
18416
  return null;
18416
18417
  }
18417
- const separatorRegexp = /\w|\.|!|\$/;
18418
+ /**
18419
+ - \p{L} is for any letter (from any language)
18420
+ - \p{N} is for any number
18421
+ - the u flag at the end is for unicode, which enables the `\p{...}` syntax
18422
+ */
18423
+ const unicodeSymbolCharRegexp = /\p{L}|\p{N}|_|\.|!|\$/u;
18424
+ const SYMBOL_CHARS = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.!$");
18418
18425
  /**
18419
18426
  * A "Symbol" is just basically any word-like element that can appear in a
18420
18427
  * formula, which is not a string. So:
@@ -18454,7 +18461,7 @@ function tokenizeSymbol(chars) {
18454
18461
  };
18455
18462
  }
18456
18463
  }
18457
- while (chars[0] && chars[0].match(separatorRegexp)) {
18464
+ while (chars[0] && (SYMBOL_CHARS.has(chars[0]) || chars[0].match(unicodeSymbolCharRegexp))) {
18458
18465
  result += chars.shift();
18459
18466
  }
18460
18467
  if (result.length) {
@@ -23727,9 +23734,9 @@ const XLSX_CHART_TYPES = [
23727
23734
  /** In XLSX color format (no #) */
23728
23735
  const AUTO_COLOR = "000000";
23729
23736
  const XLSX_ICONSET_MAP = {
23730
- arrow: "3Arrows",
23737
+ arrows: "3Arrows",
23731
23738
  smiley: "3Symbols",
23732
- dot: "3TrafficLights1",
23739
+ dots: "3TrafficLights1",
23733
23740
  };
23734
23741
  const NAMESPACE = {
23735
23742
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -24118,6 +24125,7 @@ const ICON_SET_CONVERSION_MAP = {
24118
24125
  };
24119
24126
  /** Map between legend position in XLSX file and human readable position */
24120
24127
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
24128
+ none: "none",
24121
24129
  b: "bottom",
24122
24130
  t: "top",
24123
24131
  l: "left",
@@ -26295,7 +26303,7 @@ class XlsxChartExtractor extends XlsxBaseExtractor {
26295
26303
  ? "right"
26296
26304
  : "left",
26297
26305
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
26298
- default: "b",
26306
+ default: "none",
26299
26307
  }).asString()],
26300
26308
  stacked: barChartGrouping === "stacked",
26301
26309
  fontColor: "000000",
@@ -36210,10 +36218,8 @@ function mergeTransformation(cmd, executed) {
36210
36218
  }
36211
36219
  const target = [];
36212
36220
  for (const zone1 of cmd.target) {
36213
- for (const zone2 of executed.target) {
36214
- if (!overlap(zone1, zone2)) {
36215
- target.push({ ...zone1 });
36216
- }
36221
+ if (executed.target.every((zone2) => !overlap(zone1, zone2))) {
36222
+ target.push(zone1);
36217
36223
  }
36218
36224
  }
36219
36225
  if (target.length) {
@@ -42460,10 +42466,14 @@ function addIconSetRule(cf, rule) {
42460
42466
  continue;
42461
42467
  }
42462
42468
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
42469
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
42470
+ if (isIconSetReversed(rule.icons)) {
42471
+ iconSetAttrs.push(["reverse", "1"]);
42472
+ }
42463
42473
  conditionalFormats.push(escapeXml /*xml*/ `
42464
42474
  <conditionalFormatting sqref="${range}">
42465
42475
  <cfRule ${formatAttributes(ruleAttributes)}>
42466
- <iconSet iconSet="${getIconSet(rule.icons)}">
42476
+ <iconSet ${formatAttributes(iconSetAttrs)}>
42467
42477
  ${joinXmlNodes(cfValueObjectNodes)}
42468
42478
  </iconSet>
42469
42479
  </cfRule>
@@ -42481,9 +42491,21 @@ function commonCfAttributes(cf) {
42481
42491
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
42482
42492
  ];
42483
42493
  }
42494
+ function isIconSetReversed(iconSet) {
42495
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
42496
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
42497
+ }
42484
42498
  function getIconSet(iconSet) {
42485
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
42486
- "dots"];
42499
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
42500
+ }
42501
+ /**
42502
+ * Partial detection based on "upper" point only.
42503
+ * We support any arbitrary icon in the set, while excel doesn't allow
42504
+ * mixing icons from different types.
42505
+ */
42506
+ function detectIconsType(iconSet) {
42507
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
42508
+ return type;
42487
42509
  }
42488
42510
  function thresholdAttributes(threshold, position) {
42489
42511
  const type = getExcelThresholdType(threshold.type, position);
@@ -43728,6 +43750,6 @@ function addFunction(functionName, functionDescription) {
43728
43750
  export { AbstractChart, CommandResult, CorePlugin, DATETIME_FORMAT, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, cellTypes, compile, components, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, invalidateEvaluationCommands, load, parse, readonlyAllowedCommands, registries, setTranslationMethod, tokenize };
43729
43751
 
43730
43752
 
43731
- __info__.version = '16.0.65';
43732
- __info__.date = '2025-03-19T08:14:11.320Z';
43733
- __info__.hash = '4e495e9';
43753
+ __info__.version = '16.0.67';
43754
+ __info__.date = '2025-04-18T16:22:13.893Z';
43755
+ __info__.hash = 'efeeb27';
@@ -6953,7 +6953,7 @@
6953
6953
  if (executed.type === "ADD_COLUMNS_ROWS") {
6954
6954
  return expandZoneOnInsertion(zone, executed.dimension === "COL" ? "left" : "top", executed.base, executed.position, executed.quantity);
6955
6955
  }
6956
- return { ...zone };
6956
+ return zone;
6957
6957
  }
6958
6958
 
6959
6959
  /**
@@ -7383,7 +7383,8 @@
7383
7383
  }
7384
7384
  }
7385
7385
  else if (dataSets.length === 1) {
7386
- for (let i = 0; i < getData(getters, dataSets[0]).length; i++) {
7386
+ const dataLength = getData(getters, dataSets[0]).length;
7387
+ for (let i = 0; i < dataLength; i++) {
7387
7388
  labels.formattedValues.push("");
7388
7389
  labels.values.push("");
7389
7390
  }
@@ -18415,7 +18416,13 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
18415
18416
  }
18416
18417
  return null;
18417
18418
  }
18418
- const separatorRegexp = /\w|\.|!|\$/;
18419
+ /**
18420
+ - \p{L} is for any letter (from any language)
18421
+ - \p{N} is for any number
18422
+ - the u flag at the end is for unicode, which enables the `\p{...}` syntax
18423
+ */
18424
+ const unicodeSymbolCharRegexp = /\p{L}|\p{N}|_|\.|!|\$/u;
18425
+ const SYMBOL_CHARS = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.!$");
18419
18426
  /**
18420
18427
  * A "Symbol" is just basically any word-like element that can appear in a
18421
18428
  * formula, which is not a string. So:
@@ -18455,7 +18462,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
18455
18462
  };
18456
18463
  }
18457
18464
  }
18458
- while (chars[0] && chars[0].match(separatorRegexp)) {
18465
+ while (chars[0] && (SYMBOL_CHARS.has(chars[0]) || chars[0].match(unicodeSymbolCharRegexp))) {
18459
18466
  result += chars.shift();
18460
18467
  }
18461
18468
  if (result.length) {
@@ -23728,9 +23735,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
23728
23735
  /** In XLSX color format (no #) */
23729
23736
  const AUTO_COLOR = "000000";
23730
23737
  const XLSX_ICONSET_MAP = {
23731
- arrow: "3Arrows",
23738
+ arrows: "3Arrows",
23732
23739
  smiley: "3Symbols",
23733
- dot: "3TrafficLights1",
23740
+ dots: "3TrafficLights1",
23734
23741
  };
23735
23742
  const NAMESPACE = {
23736
23743
  styleSheet: "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
@@ -24119,6 +24126,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
24119
24126
  };
24120
24127
  /** Map between legend position in XLSX file and human readable position */
24121
24128
  const DRAWING_LEGEND_POSITION_CONVERSION_MAP = {
24129
+ none: "none",
24122
24130
  b: "bottom",
24123
24131
  t: "top",
24124
24132
  l: "left",
@@ -26296,7 +26304,7 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
26296
26304
  ? "right"
26297
26305
  : "left",
26298
26306
  legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
26299
- default: "b",
26307
+ default: "none",
26300
26308
  }).asString()],
26301
26309
  stacked: barChartGrouping === "stacked",
26302
26310
  fontColor: "000000",
@@ -36211,10 +36219,8 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
36211
36219
  }
36212
36220
  const target = [];
36213
36221
  for (const zone1 of cmd.target) {
36214
- for (const zone2 of executed.target) {
36215
- if (!overlap(zone1, zone2)) {
36216
- target.push({ ...zone1 });
36217
- }
36222
+ if (executed.target.every((zone2) => !overlap(zone1, zone2))) {
36223
+ target.push(zone1);
36218
36224
  }
36219
36225
  }
36220
36226
  if (target.length) {
@@ -42461,10 +42467,14 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42461
42467
  continue;
42462
42468
  }
42463
42469
  const cfValueObjectNodes = cfValueObject.map((attrs) => escapeXml /*xml*/ `<cfvo ${formatAttributes(attrs)} />`);
42470
+ const iconSetAttrs = [["iconSet", getIconSet(rule.icons)]];
42471
+ if (isIconSetReversed(rule.icons)) {
42472
+ iconSetAttrs.push(["reverse", "1"]);
42473
+ }
42464
42474
  conditionalFormats.push(escapeXml /*xml*/ `
42465
42475
  <conditionalFormatting sqref="${range}">
42466
42476
  <cfRule ${formatAttributes(ruleAttributes)}>
42467
- <iconSet iconSet="${getIconSet(rule.icons)}">
42477
+ <iconSet ${formatAttributes(iconSetAttrs)}>
42468
42478
  ${joinXmlNodes(cfValueObjectNodes)}
42469
42479
  </iconSet>
42470
42480
  </cfRule>
@@ -42482,9 +42492,21 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
42482
42492
  ["stopIfTrue", cf.stopIfTrue ? 1 : 0],
42483
42493
  ];
42484
42494
  }
42495
+ function isIconSetReversed(iconSet) {
42496
+ const defaultIconSet = ICON_SETS[detectIconsType(iconSet)];
42497
+ return iconSet.upper === defaultIconSet.bad && iconSet.lower === defaultIconSet.good;
42498
+ }
42485
42499
  function getIconSet(iconSet) {
42486
- return XLSX_ICONSET_MAP[Object.keys(XLSX_ICONSET_MAP).find((key) => iconSet.upper.toLowerCase().startsWith(key)) ||
42487
- "dots"];
42500
+ return XLSX_ICONSET_MAP[detectIconsType(iconSet)];
42501
+ }
42502
+ /**
42503
+ * Partial detection based on "upper" point only.
42504
+ * We support any arbitrary icon in the set, while excel doesn't allow
42505
+ * mixing icons from different types.
42506
+ */
42507
+ function detectIconsType(iconSet) {
42508
+ const type = Object.keys(ICON_SETS).find((type) => Object.values(ICON_SETS[type]).includes(iconSet.upper)) || "dots";
42509
+ return type;
42488
42510
  }
42489
42511
  function thresholdAttributes(threshold, position) {
42490
42512
  const type = getExcelThresholdType(threshold.type, position);
@@ -43759,9 +43781,9 @@ day_count_convention (number, default=${DEFAULT_DAY_COUNT_CONVENTION} ) ${_lt("A
43759
43781
  Object.defineProperty(exports, '__esModule', { value: true });
43760
43782
 
43761
43783
 
43762
- __info__.version = '16.0.65';
43763
- __info__.date = '2025-03-19T08:14:11.320Z';
43764
- __info__.hash = '4e495e9';
43784
+ __info__.version = '16.0.67';
43785
+ __info__.date = '2025-04-18T16:22:13.893Z';
43786
+ __info__.hash = 'efeeb27';
43765
43787
 
43766
43788
 
43767
43789
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);