@odoo/o-spreadsheet 17.0.84 → 17.0.85

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.
@@ -2,9 +2,9 @@
2
2
  /**
3
3
  * This file is generated by o-spreadsheet build tools. Do not edit it.
4
4
  * @see https://github.com/odoo/o-spreadsheet
5
- * @version 17.0.84
6
- * @date 2026-01-14T09:59:26.542Z
7
- * @hash ae64224
5
+ * @version 17.0.85
6
+ * @date 2026-01-21T11:02:43.920Z
7
+ * @hash 0343060
8
8
  */
9
9
 
10
10
  import { Component, useRef, onMounted, useEffect, onWillPatch, useState, onWillUpdateProps, onPatched, useComponent, useExternalListener, onWillUnmount, onWillStart, xml, useChildSubEnv, useSubEnv, markRaw } from '@odoo/owl';
@@ -4555,17 +4555,318 @@ function isSheetNameEqual(name1, name2) {
4555
4555
  getUnquotedSheetName(name2.trim().toUpperCase()));
4556
4556
  }
4557
4557
 
4558
+ /**
4559
+ * Registry
4560
+ *
4561
+ * The Registry class is basically just a mapping from a string key to an object.
4562
+ * It is really not much more than an object. It is however useful for the
4563
+ * following reasons:
4564
+ *
4565
+ * 1. it let us react and execute code when someone add something to the registry
4566
+ * (for example, the FunctionRegistry subclass this for this purpose)
4567
+ * 2. it throws an error when the get operation fails
4568
+ * 3. it provides a chained API to add items to the registry.
4569
+ */
4570
+ class Registry {
4571
+ content = {};
4572
+ /**
4573
+ * Add an item to the registry
4574
+ *
4575
+ * Note that this also returns the registry, so another add method call can
4576
+ * be chained
4577
+ */
4578
+ add(key, value) {
4579
+ this.content[key] = value;
4580
+ return this;
4581
+ }
4582
+ /**
4583
+ * Get an item from the registry
4584
+ */
4585
+ get(key) {
4586
+ /**
4587
+ * Note: key in {} is ~12 times slower than {}[key].
4588
+ * So, we check the absence of key only when the direct access returns
4589
+ * a falsy value. It's done to ensure that the registry can contains falsy values
4590
+ */
4591
+ const content = this.content[key];
4592
+ if (!content) {
4593
+ if (!(key in this.content)) {
4594
+ throw new Error(`Cannot find ${key} in this registry!`);
4595
+ }
4596
+ }
4597
+ return content;
4598
+ }
4599
+ /**
4600
+ * Check if the key is already in the registry
4601
+ */
4602
+ contains(key) {
4603
+ return key in this.content;
4604
+ }
4605
+ /**
4606
+ * Get a list of all elements in the registry
4607
+ */
4608
+ getAll() {
4609
+ return Object.values(this.content);
4610
+ }
4611
+ /**
4612
+ * Get a list of all keys in the registry
4613
+ */
4614
+ getKeys() {
4615
+ return Object.keys(this.content);
4616
+ }
4617
+ /**
4618
+ * Remove an item from the registry
4619
+ */
4620
+ remove(key) {
4621
+ delete this.content[key];
4622
+ }
4623
+ }
4624
+
4625
+ /**
4626
+ * Add the `https` prefix to the url if it's missing
4627
+ */
4628
+ function withHttps(url) {
4629
+ return !/^https?:\/\//i.test(url) ? `https://${url}` : url;
4630
+ }
4631
+ const urlRegistry = new Registry();
4632
+ function createWebLink(url, label) {
4633
+ url = withHttps(url);
4634
+ return {
4635
+ url,
4636
+ label: label || url,
4637
+ isExternal: true,
4638
+ isUrlEditable: true,
4639
+ };
4640
+ }
4641
+ urlRegistry.add("sheet_URL", {
4642
+ match: (url) => isSheetUrl(url),
4643
+ createLink: (url, label) => {
4644
+ return {
4645
+ label,
4646
+ url,
4647
+ isExternal: false,
4648
+ isUrlEditable: false,
4649
+ };
4650
+ },
4651
+ urlRepresentation(url, getters) {
4652
+ const sheetId = parseSheetUrl(url);
4653
+ return getters.tryGetSheetName(sheetId) || _t("Invalid sheet");
4654
+ },
4655
+ open(url, env) {
4656
+ const sheetId = parseSheetUrl(url);
4657
+ env.model.dispatch("ACTIVATE_SHEET", {
4658
+ sheetIdFrom: env.model.getters.getActiveSheetId(),
4659
+ sheetIdTo: sheetId,
4660
+ });
4661
+ },
4662
+ sequence: 0,
4663
+ });
4664
+ const WebUrlSpec = {
4665
+ createLink: createWebLink,
4666
+ match: (url) => isWebLink(url),
4667
+ open: (url) => window.open(url, "_blank"),
4668
+ urlRepresentation: (url) => url,
4669
+ sequence: 0,
4670
+ };
4671
+ function findMatchingSpec(url) {
4672
+ return (urlRegistry
4673
+ .getAll()
4674
+ .sort((a, b) => a.sequence - b.sequence)
4675
+ .find((urlType) => urlType.match(url)) || WebUrlSpec);
4676
+ }
4677
+ function urlRepresentation(link, getters) {
4678
+ return findMatchingSpec(link.url).urlRepresentation(link.url, getters);
4679
+ }
4680
+ function openLink(link, env) {
4681
+ findMatchingSpec(link.url).open(link.url, env);
4682
+ }
4683
+ function detectLink(value) {
4684
+ if (typeof value !== "string") {
4685
+ return undefined;
4686
+ }
4687
+ if (isMarkdownLink(value)) {
4688
+ const { label, url } = parseMarkdownLink(value);
4689
+ return findMatchingSpec(url).createLink(url, label);
4690
+ }
4691
+ else if (isWebLink(value)) {
4692
+ return createWebLink(value);
4693
+ }
4694
+ return undefined;
4695
+ }
4696
+
4697
+ function evaluateLiteral(content, localeFormat) {
4698
+ return createEvaluatedCell(parseLiteral(content || "", localeFormat.locale), localeFormat);
4699
+ }
4700
+ function parseLiteral(content, locale) {
4701
+ if (content.startsWith("=")) {
4702
+ throw new Error(`Cannot parse "${content}" because it's not a literal value. It's a formula`);
4703
+ }
4704
+ if (isNumber(content, DEFAULT_LOCALE)) {
4705
+ return toNumber(content, DEFAULT_LOCALE);
4706
+ }
4707
+ else if (isDateTime(content, locale)) {
4708
+ return toNumber(content, locale);
4709
+ }
4710
+ else if (isBoolean(content)) {
4711
+ return content.toUpperCase() === "TRUE" ? true : false;
4712
+ }
4713
+ return content;
4714
+ }
4715
+ function createEvaluatedCell(value, localeFormat) {
4716
+ const link = detectLink(value);
4717
+ if (link) {
4718
+ return {
4719
+ ..._createEvaluatedCell(parseLiteral(link.label, localeFormat.locale), {
4720
+ format: localeFormat.format ||
4721
+ detectDateFormat(link.label, localeFormat.locale) ||
4722
+ detectNumberFormat(link.label),
4723
+ locale: localeFormat.locale,
4724
+ }),
4725
+ link,
4726
+ };
4727
+ }
4728
+ return _createEvaluatedCell(value, localeFormat);
4729
+ }
4730
+ function _createEvaluatedCell(value, localeFormat) {
4731
+ try {
4732
+ for (const builder of builders) {
4733
+ const evaluateCell = builder(value, localeFormat);
4734
+ if (evaluateCell) {
4735
+ return evaluateCell;
4736
+ }
4737
+ }
4738
+ return textCell((value || "").toString(), localeFormat);
4739
+ }
4740
+ catch (error) {
4741
+ return errorCell(new EvaluationError(CellErrorType.GenericError, error.message || DEFAULT_ERROR_MESSAGE));
4742
+ }
4743
+ }
4744
+ function textCell(value, localeFormat) {
4745
+ return {
4746
+ type: CellValueType.text,
4747
+ value,
4748
+ format: localeFormat.format,
4749
+ isAutoSummable: true,
4750
+ defaultAlign: "left",
4751
+ formattedValue: formatValue(value, localeFormat),
4752
+ };
4753
+ }
4754
+ function numberCell(value, localeFormat) {
4755
+ return {
4756
+ type: CellValueType.number,
4757
+ value: value || 0, // necessary to avoid "-0" and NaN values,
4758
+ format: localeFormat.format,
4759
+ isAutoSummable: true,
4760
+ defaultAlign: "right",
4761
+ formattedValue: formatValue(value, localeFormat),
4762
+ };
4763
+ }
4764
+ const EMPTY_EVALUATED_CELL = {
4765
+ type: CellValueType.empty,
4766
+ value: "",
4767
+ format: undefined,
4768
+ isAutoSummable: true,
4769
+ defaultAlign: "left",
4770
+ formattedValue: "",
4771
+ };
4772
+ function emptyCell(localeFormat) {
4773
+ if (localeFormat.format === undefined) {
4774
+ // share the same object to save memory
4775
+ return EMPTY_EVALUATED_CELL;
4776
+ }
4777
+ return {
4778
+ type: CellValueType.empty,
4779
+ value: "",
4780
+ format: localeFormat.format,
4781
+ isAutoSummable: true,
4782
+ defaultAlign: "left",
4783
+ formattedValue: "",
4784
+ };
4785
+ }
4786
+ function dateTimeCell(value, localeFormat) {
4787
+ const formattedValue = formatValue(value, localeFormat);
4788
+ return {
4789
+ type: CellValueType.number,
4790
+ value,
4791
+ format: localeFormat.format,
4792
+ isAutoSummable: false,
4793
+ defaultAlign: "right",
4794
+ formattedValue,
4795
+ };
4796
+ }
4797
+ function booleanCell(value, localeFormat) {
4798
+ const formattedValue = value ? "TRUE" : "FALSE";
4799
+ return {
4800
+ type: CellValueType.boolean,
4801
+ value,
4802
+ format: localeFormat.format,
4803
+ isAutoSummable: false,
4804
+ defaultAlign: "center",
4805
+ formattedValue,
4806
+ };
4807
+ }
4808
+ function errorCell(error) {
4809
+ return {
4810
+ type: CellValueType.error,
4811
+ value: error.errorType,
4812
+ error,
4813
+ isAutoSummable: false,
4814
+ defaultAlign: "center",
4815
+ formattedValue: error.errorType,
4816
+ };
4817
+ }
4818
+ const builders = [
4819
+ function createEmpty(value, localeFormat) {
4820
+ if (value === "") {
4821
+ return emptyCell(localeFormat);
4822
+ }
4823
+ return undefined;
4824
+ },
4825
+ function createDateTime(value, localeFormat) {
4826
+ if (!!localeFormat.format &&
4827
+ typeof value === "number" &&
4828
+ isDateTimeFormat(localeFormat.format)) {
4829
+ return dateTimeCell(value, localeFormat);
4830
+ }
4831
+ return undefined;
4832
+ },
4833
+ function createNumber(value, localeFormat) {
4834
+ if (typeof value === "number") {
4835
+ return numberCell(value, localeFormat);
4836
+ }
4837
+ else if (value === null) {
4838
+ return numberCell(0, localeFormat);
4839
+ }
4840
+ return undefined;
4841
+ },
4842
+ function createBoolean(value, localeFormat) {
4843
+ if (typeof value === "boolean") {
4844
+ return booleanCell(value, localeFormat);
4845
+ }
4846
+ return undefined;
4847
+ },
4848
+ ];
4849
+
4558
4850
  function computeTextLinesHeight(textLineHeight, numberOfLines = 1) {
4559
4851
  return numberOfLines * (textLineHeight + MIN_CELL_TEXT_MARGIN) - MIN_CELL_TEXT_MARGIN;
4560
4852
  }
4561
4853
  /**
4562
4854
  * Get the default height of the cell given its style.
4563
4855
  */
4564
- function getDefaultCellHeight(ctx, cell, colSize) {
4856
+ function getDefaultCellHeight(ctx, cell, locale, colSize) {
4565
4857
  if (!cell || (!cell.isFormula && !cell.content)) {
4566
4858
  return DEFAULT_CELL_HEIGHT;
4567
4859
  }
4568
- const content = cell.isFormula ? "" : cell.content;
4860
+ let content = "";
4861
+ try {
4862
+ if (!cell.isFormula) {
4863
+ const localeFormat = { format: cell.format, locale };
4864
+ content = formatValue(parseLiteral(cell.content, locale), localeFormat);
4865
+ }
4866
+ }
4867
+ catch {
4868
+ content = CellErrorType.GenericError;
4869
+ }
4569
4870
  return getCellContentHeight(ctx, content, cell.style, colSize);
4570
4871
  }
4571
4872
  function getCellContentHeight(ctx, content, style, colSize) {
@@ -4869,7 +5170,8 @@ function createAction(item) {
4869
5170
  return children
4870
5171
  .map((child) => (typeof child === "function" ? child(env) : child))
4871
5172
  .flat()
4872
- .map(createAction);
5173
+ .map(createAction)
5174
+ .sort((a, b) => a.sequence - b.sequence);
4873
5175
  }
4874
5176
  : () => [],
4875
5177
  isReadonlyAllowed: item.isReadonlyAllowed || false,
@@ -5830,298 +6132,6 @@ ScorecardChart.props = {
5830
6132
  figure: Object,
5831
6133
  };
5832
6134
 
5833
- /**
5834
- * Registry
5835
- *
5836
- * The Registry class is basically just a mapping from a string key to an object.
5837
- * It is really not much more than an object. It is however useful for the
5838
- * following reasons:
5839
- *
5840
- * 1. it let us react and execute code when someone add something to the registry
5841
- * (for example, the FunctionRegistry subclass this for this purpose)
5842
- * 2. it throws an error when the get operation fails
5843
- * 3. it provides a chained API to add items to the registry.
5844
- */
5845
- class Registry {
5846
- content = {};
5847
- /**
5848
- * Add an item to the registry
5849
- *
5850
- * Note that this also returns the registry, so another add method call can
5851
- * be chained
5852
- */
5853
- add(key, value) {
5854
- this.content[key] = value;
5855
- return this;
5856
- }
5857
- /**
5858
- * Get an item from the registry
5859
- */
5860
- get(key) {
5861
- /**
5862
- * Note: key in {} is ~12 times slower than {}[key].
5863
- * So, we check the absence of key only when the direct access returns
5864
- * a falsy value. It's done to ensure that the registry can contains falsy values
5865
- */
5866
- const content = this.content[key];
5867
- if (!content) {
5868
- if (!(key in this.content)) {
5869
- throw new Error(`Cannot find ${key} in this registry!`);
5870
- }
5871
- }
5872
- return content;
5873
- }
5874
- /**
5875
- * Check if the key is already in the registry
5876
- */
5877
- contains(key) {
5878
- return key in this.content;
5879
- }
5880
- /**
5881
- * Get a list of all elements in the registry
5882
- */
5883
- getAll() {
5884
- return Object.values(this.content);
5885
- }
5886
- /**
5887
- * Get a list of all keys in the registry
5888
- */
5889
- getKeys() {
5890
- return Object.keys(this.content);
5891
- }
5892
- /**
5893
- * Remove an item from the registry
5894
- */
5895
- remove(key) {
5896
- delete this.content[key];
5897
- }
5898
- }
5899
-
5900
- /**
5901
- * Add the `https` prefix to the url if it's missing
5902
- */
5903
- function withHttps(url) {
5904
- return !/^https?:\/\//i.test(url) ? `https://${url}` : url;
5905
- }
5906
- const urlRegistry = new Registry();
5907
- function createWebLink(url, label) {
5908
- url = withHttps(url);
5909
- return {
5910
- url,
5911
- label: label || url,
5912
- isExternal: true,
5913
- isUrlEditable: true,
5914
- };
5915
- }
5916
- urlRegistry.add("sheet_URL", {
5917
- match: (url) => isSheetUrl(url),
5918
- createLink: (url, label) => {
5919
- return {
5920
- label,
5921
- url,
5922
- isExternal: false,
5923
- isUrlEditable: false,
5924
- };
5925
- },
5926
- urlRepresentation(url, getters) {
5927
- const sheetId = parseSheetUrl(url);
5928
- return getters.tryGetSheetName(sheetId) || _t("Invalid sheet");
5929
- },
5930
- open(url, env) {
5931
- const sheetId = parseSheetUrl(url);
5932
- env.model.dispatch("ACTIVATE_SHEET", {
5933
- sheetIdFrom: env.model.getters.getActiveSheetId(),
5934
- sheetIdTo: sheetId,
5935
- });
5936
- },
5937
- sequence: 0,
5938
- });
5939
- const WebUrlSpec = {
5940
- createLink: createWebLink,
5941
- match: (url) => isWebLink(url),
5942
- open: (url) => window.open(url, "_blank"),
5943
- urlRepresentation: (url) => url,
5944
- sequence: 0,
5945
- };
5946
- function findMatchingSpec(url) {
5947
- return (urlRegistry
5948
- .getAll()
5949
- .sort((a, b) => a.sequence - b.sequence)
5950
- .find((urlType) => urlType.match(url)) || WebUrlSpec);
5951
- }
5952
- function urlRepresentation(link, getters) {
5953
- return findMatchingSpec(link.url).urlRepresentation(link.url, getters);
5954
- }
5955
- function openLink(link, env) {
5956
- findMatchingSpec(link.url).open(link.url, env);
5957
- }
5958
- function detectLink(value) {
5959
- if (typeof value !== "string") {
5960
- return undefined;
5961
- }
5962
- if (isMarkdownLink(value)) {
5963
- const { label, url } = parseMarkdownLink(value);
5964
- return findMatchingSpec(url).createLink(url, label);
5965
- }
5966
- else if (isWebLink(value)) {
5967
- return createWebLink(value);
5968
- }
5969
- return undefined;
5970
- }
5971
-
5972
- function evaluateLiteral(content, localeFormat) {
5973
- return createEvaluatedCell(parseLiteral(content || "", localeFormat.locale), localeFormat);
5974
- }
5975
- function parseLiteral(content, locale) {
5976
- if (content.startsWith("=")) {
5977
- throw new Error(`Cannot parse "${content}" because it's not a literal value. It's a formula`);
5978
- }
5979
- if (isNumber(content, DEFAULT_LOCALE)) {
5980
- return toNumber(content, DEFAULT_LOCALE);
5981
- }
5982
- else if (isDateTime(content, locale)) {
5983
- return toNumber(content, locale);
5984
- }
5985
- else if (isBoolean(content)) {
5986
- return content.toUpperCase() === "TRUE" ? true : false;
5987
- }
5988
- return content;
5989
- }
5990
- function createEvaluatedCell(value, localeFormat) {
5991
- const link = detectLink(value);
5992
- if (link) {
5993
- return {
5994
- ..._createEvaluatedCell(parseLiteral(link.label, localeFormat.locale), {
5995
- format: localeFormat.format ||
5996
- detectDateFormat(link.label, localeFormat.locale) ||
5997
- detectNumberFormat(link.label),
5998
- locale: localeFormat.locale,
5999
- }),
6000
- link,
6001
- };
6002
- }
6003
- return _createEvaluatedCell(value, localeFormat);
6004
- }
6005
- function _createEvaluatedCell(value, localeFormat) {
6006
- try {
6007
- for (const builder of builders) {
6008
- const evaluateCell = builder(value, localeFormat);
6009
- if (evaluateCell) {
6010
- return evaluateCell;
6011
- }
6012
- }
6013
- return textCell((value || "").toString(), localeFormat);
6014
- }
6015
- catch (error) {
6016
- return errorCell(new EvaluationError(CellErrorType.GenericError, error.message || DEFAULT_ERROR_MESSAGE));
6017
- }
6018
- }
6019
- function textCell(value, localeFormat) {
6020
- return {
6021
- type: CellValueType.text,
6022
- value,
6023
- format: localeFormat.format,
6024
- isAutoSummable: true,
6025
- defaultAlign: "left",
6026
- formattedValue: formatValue(value, localeFormat),
6027
- };
6028
- }
6029
- function numberCell(value, localeFormat) {
6030
- return {
6031
- type: CellValueType.number,
6032
- value: value || 0, // necessary to avoid "-0" and NaN values,
6033
- format: localeFormat.format,
6034
- isAutoSummable: true,
6035
- defaultAlign: "right",
6036
- formattedValue: formatValue(value, localeFormat),
6037
- };
6038
- }
6039
- const EMPTY_EVALUATED_CELL = {
6040
- type: CellValueType.empty,
6041
- value: "",
6042
- format: undefined,
6043
- isAutoSummable: true,
6044
- defaultAlign: "left",
6045
- formattedValue: "",
6046
- };
6047
- function emptyCell(localeFormat) {
6048
- if (localeFormat.format === undefined) {
6049
- // share the same object to save memory
6050
- return EMPTY_EVALUATED_CELL;
6051
- }
6052
- return {
6053
- type: CellValueType.empty,
6054
- value: "",
6055
- format: localeFormat.format,
6056
- isAutoSummable: true,
6057
- defaultAlign: "left",
6058
- formattedValue: "",
6059
- };
6060
- }
6061
- function dateTimeCell(value, localeFormat) {
6062
- const formattedValue = formatValue(value, localeFormat);
6063
- return {
6064
- type: CellValueType.number,
6065
- value,
6066
- format: localeFormat.format,
6067
- isAutoSummable: false,
6068
- defaultAlign: "right",
6069
- formattedValue,
6070
- };
6071
- }
6072
- function booleanCell(value, localeFormat) {
6073
- const formattedValue = value ? "TRUE" : "FALSE";
6074
- return {
6075
- type: CellValueType.boolean,
6076
- value,
6077
- format: localeFormat.format,
6078
- isAutoSummable: false,
6079
- defaultAlign: "center",
6080
- formattedValue,
6081
- };
6082
- }
6083
- function errorCell(error) {
6084
- return {
6085
- type: CellValueType.error,
6086
- value: error.errorType,
6087
- error,
6088
- isAutoSummable: false,
6089
- defaultAlign: "center",
6090
- formattedValue: error.errorType,
6091
- };
6092
- }
6093
- const builders = [
6094
- function createEmpty(value, localeFormat) {
6095
- if (value === "") {
6096
- return emptyCell(localeFormat);
6097
- }
6098
- return undefined;
6099
- },
6100
- function createDateTime(value, localeFormat) {
6101
- if (!!localeFormat.format &&
6102
- typeof value === "number" &&
6103
- isDateTimeFormat(localeFormat.format)) {
6104
- return dateTimeCell(value, localeFormat);
6105
- }
6106
- return undefined;
6107
- },
6108
- function createNumber(value, localeFormat) {
6109
- if (typeof value === "number") {
6110
- return numberCell(value, localeFormat);
6111
- }
6112
- else if (value === null) {
6113
- return numberCell(0, localeFormat);
6114
- }
6115
- return undefined;
6116
- },
6117
- function createBoolean(value, localeFormat) {
6118
- if (typeof value === "boolean") {
6119
- return booleanCell(value, localeFormat);
6120
- }
6121
- return undefined;
6122
- },
6123
- ];
6124
-
6125
6135
  /**
6126
6136
  * An AutofillModifierImplementation is used to describe how to handle a
6127
6137
  * AutofillModifier.
@@ -43583,6 +43593,7 @@ class HeaderSizeUIPlugin extends UIPlugin {
43583
43593
  handle(cmd) {
43584
43594
  switch (cmd.type) {
43585
43595
  case "START":
43596
+ case "UPDATE_LOCALE":
43586
43597
  for (const sheetId of this.getters.getSheetIds()) {
43587
43598
  this.initializeSheet(sheetId);
43588
43599
  }
@@ -43688,7 +43699,7 @@ class HeaderSizeUIPlugin extends UIPlugin {
43688
43699
  }
43689
43700
  const cell = this.getters.getCell(position);
43690
43701
  const colSize = this.getters.getColSize(position.sheetId, position.col);
43691
- return getDefaultCellHeight(this.ctx, cell, colSize);
43702
+ return getDefaultCellHeight(this.ctx, cell, this.getters.getLocale(), colSize);
43692
43703
  }
43693
43704
  isInMultiRowMerge(position) {
43694
43705
  const merge = this.getters.getMerge(position);
@@ -58512,6 +58523,6 @@ const constants = {
58512
58523
  export { AbstractChart, CommandResult, CorePlugin, DispatchResult, EvaluationError, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, __info__, addFunction, astToFormula, compile, compileTokens, components, constants, convertAstNodes, coreTypes, findCellInNewZone, functionCache, helpers, hooks, invalidateCFEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, tokenize };
58513
58524
 
58514
58525
 
58515
- __info__.version = "17.0.84";
58516
- __info__.date = "2026-01-14T09:59:26.542Z";
58517
- __info__.hash = "ae64224";
58526
+ __info__.version = "17.0.85";
58527
+ __info__.date = "2026-01-21T11:02:43.920Z";
58528
+ __info__.hash = "0343060";