@odoo/o-spreadsheet 15.2.9 → 15.2.11

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.
@@ -2965,6 +2965,36 @@ function lazy(fn) {
2965
2965
  };
2966
2966
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
2967
2967
  return lazyValue;
2968
+ }
2969
+ /**
2970
+ * Compares two objects.
2971
+ */
2972
+ function deepEquals(o1, o2) {
2973
+ if (o1 === o2)
2974
+ return true;
2975
+ if ((o1 && !o2) || (o2 && !o1))
2976
+ return false;
2977
+ if (typeof o1 !== typeof o2)
2978
+ return false;
2979
+ if (typeof o1 !== "object")
2980
+ return o1 === o2;
2981
+ // Objects can have different keys if the values are undefined
2982
+ const keys = new Set();
2983
+ Object.keys(o1).forEach((key) => keys.add(key));
2984
+ Object.keys(o2).forEach((key) => keys.add(key));
2985
+ for (let key of keys) {
2986
+ if (typeof o1[key] !== typeof o1[key])
2987
+ return false;
2988
+ if (typeof o1[key] === "object") {
2989
+ if (!deepEquals(o1[key], o2[key]))
2990
+ return false;
2991
+ }
2992
+ else {
2993
+ if (o1[key] !== o2[key])
2994
+ return false;
2995
+ }
2996
+ }
2997
+ return true;
2968
2998
  }
2969
2999
 
2970
3000
  function createDefaultCols(colNumber) {
@@ -19201,6 +19231,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19201
19231
  // stores the computed styles in the format of computedStyles.sheetName[col][row] = Style
19202
19232
  this.computedStyles = {};
19203
19233
  this.computedIcons = {};
19234
+ this.uuidGenerator = new UuidGenerator();
19204
19235
  /**
19205
19236
  * Execute the predicate to know if a conditional formatting rule should be applied to a cell
19206
19237
  */
@@ -19529,6 +19560,10 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19529
19560
  }
19530
19561
  currentRanges = currentRanges.concat(toAdd);
19531
19562
  const newRange = recomputeZones(currentRanges, toRemove);
19563
+ if (newRange.length === 0) {
19564
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
19565
+ return;
19566
+ }
19532
19567
  this.dispatch("ADD_CONDITIONAL_FORMAT", {
19533
19568
  cf: {
19534
19569
  id: cf.id,
@@ -19554,13 +19589,20 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19554
19589
  this.adaptRules(origin.sheetId, cf, [xc], toRemoveRange);
19555
19590
  }
19556
19591
  else {
19557
- this.adaptRules(target.sheetId, cf, [xc], []);
19558
19592
  this.adaptRules(origin.sheetId, cf, [], toRemoveRange);
19593
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
19594
+ this.adaptRules(target.sheetId, cfToCopyTo, [xc], []);
19559
19595
  }
19560
19596
  }
19561
19597
  }
19562
19598
  }
19563
19599
  }
19600
+ getCFToCopyTo(targetSheetId, originCF) {
19601
+ const cfInTarget = this.getters
19602
+ .getConditionalFormats(targetSheetId)
19603
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
19604
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
19605
+ }
19564
19606
  }
19565
19607
  EvaluationConditionalFormatPlugin.getters = ["getConditionalStyle", "getConditionalIcon"];
19566
19608
  EvaluationConditionalFormatPlugin.modes = ["normal"];
@@ -24241,12 +24283,15 @@ function createXMLFile(doc, path, contentType) {
24241
24283
  };
24242
24284
  }
24243
24285
  function xmlEscape(str) {
24244
- return String(str)
24286
+ return (String(str)
24245
24287
  .replace(/\&/g, "&")
24246
24288
  .replace(/\</g, "&lt;")
24247
24289
  .replace(/\>/g, "&gt;")
24248
24290
  .replace(/\"/g, "&quot;")
24249
- .replace(/\'/g, "&apos;");
24291
+ .replace(/\'/g, "&apos;")
24292
+ // Delete all ASCII control characters except for TAB (\x09), LF (\x0A) and CR (\x0D)
24293
+ // They are not valid at all in XML 1.0 (even escaped)
24294
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, ""));
24250
24295
  }
24251
24296
  function formatAttributes(attrs) {
24252
24297
  return new XMLString(attrs.map(([key, val]) => `${key}="${xmlEscape(val)}"`).join(" "));
@@ -31340,6 +31385,6 @@ exports.registries = registries;
31340
31385
  exports.setTranslationMethod = setTranslationMethod;
31341
31386
 
31342
31387
 
31343
- __info__.version = '15.2.9';
31344
- __info__.date = '2023-06-12T13:42:56.116Z';
31345
- __info__.hash = 'e4aee80';
31388
+ __info__.version = '15.2.11';
31389
+ __info__.date = '2023-10-19T14:17:12.583Z';
31390
+ __info__.hash = 'e13740a';
@@ -2988,6 +2988,7 @@ declare class EvaluationConditionalFormatPlugin extends UIPlugin {
2988
2988
  private isStale;
2989
2989
  private computedStyles;
2990
2990
  private computedIcons;
2991
+ private uuidGenerator;
2991
2992
  handle(cmd: Command): void;
2992
2993
  finalize(): void;
2993
2994
  /**
@@ -3022,6 +3023,7 @@ declare class EvaluationConditionalFormatPlugin extends UIPlugin {
3022
3023
  */
3023
3024
  private adaptRules;
3024
3025
  private pasteCf;
3026
+ private getCFToCopyTo;
3025
3027
  }
3026
3028
 
3027
3029
  /**
@@ -2942,6 +2942,36 @@ function lazy(fn) {
2942
2942
  };
2943
2943
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
2944
2944
  return lazyValue;
2945
+ }
2946
+ /**
2947
+ * Compares two objects.
2948
+ */
2949
+ function deepEquals(o1, o2) {
2950
+ if (o1 === o2)
2951
+ return true;
2952
+ if ((o1 && !o2) || (o2 && !o1))
2953
+ return false;
2954
+ if (typeof o1 !== typeof o2)
2955
+ return false;
2956
+ if (typeof o1 !== "object")
2957
+ return o1 === o2;
2958
+ // Objects can have different keys if the values are undefined
2959
+ const keys = new Set();
2960
+ Object.keys(o1).forEach((key) => keys.add(key));
2961
+ Object.keys(o2).forEach((key) => keys.add(key));
2962
+ for (let key of keys) {
2963
+ if (typeof o1[key] !== typeof o1[key])
2964
+ return false;
2965
+ if (typeof o1[key] === "object") {
2966
+ if (!deepEquals(o1[key], o2[key]))
2967
+ return false;
2968
+ }
2969
+ else {
2970
+ if (o1[key] !== o2[key])
2971
+ return false;
2972
+ }
2973
+ }
2974
+ return true;
2945
2975
  }
2946
2976
 
2947
2977
  function createDefaultCols(colNumber) {
@@ -19178,6 +19208,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19178
19208
  // stores the computed styles in the format of computedStyles.sheetName[col][row] = Style
19179
19209
  this.computedStyles = {};
19180
19210
  this.computedIcons = {};
19211
+ this.uuidGenerator = new UuidGenerator();
19181
19212
  /**
19182
19213
  * Execute the predicate to know if a conditional formatting rule should be applied to a cell
19183
19214
  */
@@ -19506,6 +19537,10 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19506
19537
  }
19507
19538
  currentRanges = currentRanges.concat(toAdd);
19508
19539
  const newRange = recomputeZones(currentRanges, toRemove);
19540
+ if (newRange.length === 0) {
19541
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
19542
+ return;
19543
+ }
19509
19544
  this.dispatch("ADD_CONDITIONAL_FORMAT", {
19510
19545
  cf: {
19511
19546
  id: cf.id,
@@ -19531,13 +19566,20 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19531
19566
  this.adaptRules(origin.sheetId, cf, [xc], toRemoveRange);
19532
19567
  }
19533
19568
  else {
19534
- this.adaptRules(target.sheetId, cf, [xc], []);
19535
19569
  this.adaptRules(origin.sheetId, cf, [], toRemoveRange);
19570
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
19571
+ this.adaptRules(target.sheetId, cfToCopyTo, [xc], []);
19536
19572
  }
19537
19573
  }
19538
19574
  }
19539
19575
  }
19540
19576
  }
19577
+ getCFToCopyTo(targetSheetId, originCF) {
19578
+ const cfInTarget = this.getters
19579
+ .getConditionalFormats(targetSheetId)
19580
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
19581
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
19582
+ }
19541
19583
  }
19542
19584
  EvaluationConditionalFormatPlugin.getters = ["getConditionalStyle", "getConditionalIcon"];
19543
19585
  EvaluationConditionalFormatPlugin.modes = ["normal"];
@@ -24218,12 +24260,15 @@ function createXMLFile(doc, path, contentType) {
24218
24260
  };
24219
24261
  }
24220
24262
  function xmlEscape(str) {
24221
- return String(str)
24263
+ return (String(str)
24222
24264
  .replace(/\&/g, "&amp;")
24223
24265
  .replace(/\</g, "&lt;")
24224
24266
  .replace(/\>/g, "&gt;")
24225
24267
  .replace(/\"/g, "&quot;")
24226
- .replace(/\'/g, "&apos;");
24268
+ .replace(/\'/g, "&apos;")
24269
+ // Delete all ASCII control characters except for TAB (\x09), LF (\x0A) and CR (\x0D)
24270
+ // They are not valid at all in XML 1.0 (even escaped)
24271
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, ""));
24227
24272
  }
24228
24273
  function formatAttributes(attrs) {
24229
24274
  return new XMLString(attrs.map(([key, val]) => `${key}="${xmlEscape(val)}"`).join(" "));
@@ -31294,6 +31339,6 @@ const helpers = {
31294
31339
  export { CommandResult, CorePlugin, DATETIME_FORMAT, DataSource, DispatchResult, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, DEBUG as __DEBUG__, __info__, astToFormula, cellTypes, compile, convertAstNodes, coreTypes, functionCache, helpers, invalidateEvaluationCommands, parse, readonlyAllowedCommands, registries, setTranslationMethod };
31295
31340
 
31296
31341
 
31297
- __info__.version = '15.2.9';
31298
- __info__.date = '2023-06-12T13:42:56.116Z';
31299
- __info__.hash = 'e4aee80';
31342
+ __info__.version = '15.2.11';
31343
+ __info__.date = '2023-10-19T14:17:12.583Z';
31344
+ __info__.hash = 'e13740a';
@@ -2962,6 +2962,36 @@
2962
2962
  };
2963
2963
  lazyValue.map = (callback) => lazy(() => callback(lazyValue()));
2964
2964
  return lazyValue;
2965
+ }
2966
+ /**
2967
+ * Compares two objects.
2968
+ */
2969
+ function deepEquals(o1, o2) {
2970
+ if (o1 === o2)
2971
+ return true;
2972
+ if ((o1 && !o2) || (o2 && !o1))
2973
+ return false;
2974
+ if (typeof o1 !== typeof o2)
2975
+ return false;
2976
+ if (typeof o1 !== "object")
2977
+ return o1 === o2;
2978
+ // Objects can have different keys if the values are undefined
2979
+ const keys = new Set();
2980
+ Object.keys(o1).forEach((key) => keys.add(key));
2981
+ Object.keys(o2).forEach((key) => keys.add(key));
2982
+ for (let key of keys) {
2983
+ if (typeof o1[key] !== typeof o1[key])
2984
+ return false;
2985
+ if (typeof o1[key] === "object") {
2986
+ if (!deepEquals(o1[key], o2[key]))
2987
+ return false;
2988
+ }
2989
+ else {
2990
+ if (o1[key] !== o2[key])
2991
+ return false;
2992
+ }
2993
+ }
2994
+ return true;
2965
2995
  }
2966
2996
 
2967
2997
  function createDefaultCols(colNumber) {
@@ -19198,6 +19228,7 @@
19198
19228
  // stores the computed styles in the format of computedStyles.sheetName[col][row] = Style
19199
19229
  this.computedStyles = {};
19200
19230
  this.computedIcons = {};
19231
+ this.uuidGenerator = new UuidGenerator();
19201
19232
  /**
19202
19233
  * Execute the predicate to know if a conditional formatting rule should be applied to a cell
19203
19234
  */
@@ -19526,6 +19557,10 @@
19526
19557
  }
19527
19558
  currentRanges = currentRanges.concat(toAdd);
19528
19559
  const newRange = recomputeZones(currentRanges, toRemove);
19560
+ if (newRange.length === 0) {
19561
+ this.dispatch("REMOVE_CONDITIONAL_FORMAT", { id: cf.id, sheetId });
19562
+ return;
19563
+ }
19529
19564
  this.dispatch("ADD_CONDITIONAL_FORMAT", {
19530
19565
  cf: {
19531
19566
  id: cf.id,
@@ -19551,13 +19586,20 @@
19551
19586
  this.adaptRules(origin.sheetId, cf, [xc], toRemoveRange);
19552
19587
  }
19553
19588
  else {
19554
- this.adaptRules(target.sheetId, cf, [xc], []);
19555
19589
  this.adaptRules(origin.sheetId, cf, [], toRemoveRange);
19590
+ const cfToCopyTo = this.getCFToCopyTo(target.sheetId, cf);
19591
+ this.adaptRules(target.sheetId, cfToCopyTo, [xc], []);
19556
19592
  }
19557
19593
  }
19558
19594
  }
19559
19595
  }
19560
19596
  }
19597
+ getCFToCopyTo(targetSheetId, originCF) {
19598
+ const cfInTarget = this.getters
19599
+ .getConditionalFormats(targetSheetId)
19600
+ .find((cf) => cf.stopIfTrue === originCF.stopIfTrue && deepEquals(cf.rule, originCF.rule));
19601
+ return cfInTarget ? cfInTarget : { ...originCF, id: this.uuidGenerator.uuidv4(), ranges: [] };
19602
+ }
19561
19603
  }
19562
19604
  EvaluationConditionalFormatPlugin.getters = ["getConditionalStyle", "getConditionalIcon"];
19563
19605
  EvaluationConditionalFormatPlugin.modes = ["normal"];
@@ -24238,12 +24280,15 @@
24238
24280
  };
24239
24281
  }
24240
24282
  function xmlEscape(str) {
24241
- return String(str)
24283
+ return (String(str)
24242
24284
  .replace(/\&/g, "&amp;")
24243
24285
  .replace(/\</g, "&lt;")
24244
24286
  .replace(/\>/g, "&gt;")
24245
24287
  .replace(/\"/g, "&quot;")
24246
- .replace(/\'/g, "&apos;");
24288
+ .replace(/\'/g, "&apos;")
24289
+ // Delete all ASCII control characters except for TAB (\x09), LF (\x0A) and CR (\x0D)
24290
+ // They are not valid at all in XML 1.0 (even escaped)
24291
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, ""));
24247
24292
  }
24248
24293
  function formatAttributes(attrs) {
24249
24294
  return new XMLString(attrs.map(([key, val]) => `${key}="${xmlEscape(val)}"`).join(" "));
@@ -31339,9 +31384,9 @@
31339
31384
  Object.defineProperty(exports, '__esModule', { value: true });
31340
31385
 
31341
31386
 
31342
- __info__.version = '15.2.9';
31343
- __info__.date = '2023-06-12T13:42:56.116Z';
31344
- __info__.hash = 'e4aee80';
31387
+ __info__.version = '15.2.11';
31388
+ __info__.date = '2023-10-19T14:17:12.583Z';
31389
+ __info__.hash = 'e13740a';
31345
31390
 
31346
31391
 
31347
31392
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);