@odoo/o-spreadsheet 19.3.16 → 19.3.18
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.
- package/dist/o_spreadsheet.cjs +89 -45
- package/dist/o_spreadsheet.css +11 -3
- package/dist/o_spreadsheet.esm.js +89 -45
- package/dist/o_spreadsheet.iife.js +89 -45
- package/dist/o_spreadsheet.min.iife.js +260 -260
- package/dist/o_spreadsheet.xml +3 -3
- package/dist/types/collaborative/session.d.ts +3 -1
- package/dist/types/functions/helpers.d.ts +4 -0
- package/dist/types/functions/module_operators.d.ts +1 -1
- package/dist/types/functions/module_text.d.ts +11 -11
- package/dist/types/functions/module_web.d.ts +1 -1
- package/dist/types/plugins/core/squisher.d.ts +3 -0
- package/dist/types/types/collaborative/transport_service.d.ts +1 -0
- package/package.json +1 -1
package/dist/o_spreadsheet.cjs
CHANGED
|
@@ -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 19.3.
|
|
6
|
-
* @date 2026-08-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.3.18
|
|
6
|
+
* @date 2026-08-29T09:16:28.272Z
|
|
7
|
+
* @hash 1f4b1ae
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
@@ -4070,6 +4070,18 @@ function toString(data) {
|
|
|
4070
4070
|
default: return "";
|
|
4071
4071
|
}
|
|
4072
4072
|
}
|
|
4073
|
+
/**
|
|
4074
|
+
* Only converts the decimal separator, ignore number format such as % or dates
|
|
4075
|
+
*/
|
|
4076
|
+
function toLocaleString(data, locale) {
|
|
4077
|
+
const value = toValue(data);
|
|
4078
|
+
switch (typeof value) {
|
|
4079
|
+
case "string": return value;
|
|
4080
|
+
case "number": return value.toString().replace(".", locale.decimalSeparator);
|
|
4081
|
+
case "boolean": return value ? "TRUE" : "FALSE";
|
|
4082
|
+
default: return "";
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4073
4085
|
/** Normalize string by setting it to lowercase and replacing accent letters with plain letters */
|
|
4074
4086
|
const normalizeString = memoize(function normalizeString(str) {
|
|
4075
4087
|
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
@@ -10474,6 +10486,7 @@ function getRadarChartDatasets(definition, args) {
|
|
|
10474
10486
|
hidden,
|
|
10475
10487
|
borderColor,
|
|
10476
10488
|
backgroundColor: borderColor,
|
|
10489
|
+
pointBackgroundColor: borderColor,
|
|
10477
10490
|
pointRadius: definition.hideDataMarkers ? 0 : 3
|
|
10478
10491
|
};
|
|
10479
10492
|
if (fill) {
|
|
@@ -29088,12 +29101,13 @@ var FilterMenu = class extends _odoo_owl.Component {
|
|
|
29088
29101
|
}
|
|
29089
29102
|
sortFilterZone(sortDirection) {
|
|
29090
29103
|
const filterPosition = this.props.filterPosition;
|
|
29091
|
-
const
|
|
29104
|
+
const table = this.table;
|
|
29105
|
+
const tableZone = table?.range.zone;
|
|
29092
29106
|
if (!filterPosition || !tableZone || tableZone.top === tableZone.bottom) return;
|
|
29093
29107
|
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
29094
29108
|
const contentZone = {
|
|
29095
29109
|
...tableZone,
|
|
29096
|
-
top: tableZone.top +
|
|
29110
|
+
top: tableZone.top + table.config.numberOfHeaders
|
|
29097
29111
|
};
|
|
29098
29112
|
const sortAnchor = {
|
|
29099
29113
|
col: filterPosition.col,
|
|
@@ -49826,6 +49840,7 @@ var Squisher = class {
|
|
|
49826
49840
|
baseFormulaWasTransformed = false;
|
|
49827
49841
|
rangeToStringOptions = { doNotSimplifyRange: true };
|
|
49828
49842
|
baseNumber = void 0;
|
|
49843
|
+
baseNumberFormat = void 0;
|
|
49829
49844
|
constructor(getters) {
|
|
49830
49845
|
this.getters = getters;
|
|
49831
49846
|
}
|
|
@@ -49860,6 +49875,11 @@ var Squisher = class {
|
|
|
49860
49875
|
this.baseFormulaWasTransformed = false;
|
|
49861
49876
|
}
|
|
49862
49877
|
}
|
|
49878
|
+
/** Reset the base number literal chain, so the next literal number cannot be squished as an offset of it */
|
|
49879
|
+
resetBaseNumber() {
|
|
49880
|
+
this.baseNumber = void 0;
|
|
49881
|
+
this.baseNumberFormat = void 0;
|
|
49882
|
+
}
|
|
49863
49883
|
/**
|
|
49864
49884
|
* Takes a cell and squish their formulas against the previous one (in the previous call).
|
|
49865
49885
|
* We should call this method for each cell in the sheet, in order from top to bottom, then from left to right (all cells of a columns, for each columns left to right).
|
|
@@ -49898,8 +49918,9 @@ var Squisher = class {
|
|
|
49898
49918
|
if (typeof cell.parsedValue === "number" && cell.parsedValue % 1 === 0) {
|
|
49899
49919
|
this.resetBaseFormula();
|
|
49900
49920
|
const numberValue = cell.parsedValue;
|
|
49901
|
-
if (this.baseNumber === void 0) {
|
|
49921
|
+
if (this.baseNumber === void 0 || cell.format !== this.baseNumberFormat) {
|
|
49902
49922
|
this.baseNumber = numberValue;
|
|
49923
|
+
this.baseNumberFormat = cell.format;
|
|
49903
49924
|
return cell.content;
|
|
49904
49925
|
}
|
|
49905
49926
|
const numberOffset = numberValue - this.baseNumber;
|
|
@@ -49910,7 +49931,7 @@ var Squisher = class {
|
|
|
49910
49931
|
}
|
|
49911
49932
|
}
|
|
49912
49933
|
this.resetBaseFormula();
|
|
49913
|
-
this.
|
|
49934
|
+
this.resetBaseNumber();
|
|
49914
49935
|
return cell.content;
|
|
49915
49936
|
}
|
|
49916
49937
|
squishCommand(command) {
|
|
@@ -49919,6 +49940,8 @@ var Squisher = class {
|
|
|
49919
49940
|
const squished = this.squish(cell, command.sheetId);
|
|
49920
49941
|
return typeof squished === "string" ? command.content : squished;
|
|
49921
49942
|
}
|
|
49943
|
+
this.resetBaseFormula();
|
|
49944
|
+
this.resetBaseNumber();
|
|
49922
49945
|
return command.content;
|
|
49923
49946
|
}
|
|
49924
49947
|
/**
|
|
@@ -50072,8 +50095,10 @@ var Unsquisher = class {
|
|
|
50072
50095
|
continue;
|
|
50073
50096
|
}
|
|
50074
50097
|
const current = command.content;
|
|
50075
|
-
if (current === void 0 || current === null || current === "")
|
|
50076
|
-
|
|
50098
|
+
if (current === void 0 || current === null || current === "") {
|
|
50099
|
+
this.rebase();
|
|
50100
|
+
strategy = "NOT_A_FORMULA";
|
|
50101
|
+
} else strategy = this.chooseStrategy(current, strategy, command.sheetId, getters);
|
|
50077
50102
|
let targetPositions;
|
|
50078
50103
|
if (command.type === "SQUISHED_UPDATE_CELL" && "targetRange" in command) {
|
|
50079
50104
|
const [start, end] = command.targetRange.split(":");
|
|
@@ -50118,8 +50143,11 @@ var Unsquisher = class {
|
|
|
50118
50143
|
let strategy;
|
|
50119
50144
|
for (const { key } of keys) {
|
|
50120
50145
|
const current = squished[key];
|
|
50121
|
-
if (current === void 0 || current === null || current === "")
|
|
50122
|
-
|
|
50146
|
+
if (current === void 0 || current === null || current === "") {
|
|
50147
|
+
this.rebase();
|
|
50148
|
+
strategy = void 0;
|
|
50149
|
+
continue;
|
|
50150
|
+
} else strategy = this.chooseStrategy(current, strategy, sheetId, getters);
|
|
50123
50151
|
const parts = key.split(":");
|
|
50124
50152
|
const targetPositions = parts.length === 1 ? expandXc(key) : expandRange(parts[0], parts[1]);
|
|
50125
50153
|
yield* this.applyStrategy(strategy, targetPositions, current, sheetId, getters);
|
|
@@ -50165,6 +50193,9 @@ var Unsquisher = class {
|
|
|
50165
50193
|
case "FIRST_OFFSET":
|
|
50166
50194
|
strategy = "COMBINE_OFFSET";
|
|
50167
50195
|
break;
|
|
50196
|
+
case "COMBINE_OFFSET":
|
|
50197
|
+
case "OFFSET_NUMBER": break;
|
|
50198
|
+
default: throw new Error(`Cannot unsquish an offset without a preceding base cell: ${strategy}`);
|
|
50168
50199
|
}
|
|
50169
50200
|
}
|
|
50170
50201
|
return strategy;
|
|
@@ -60947,6 +60978,7 @@ var Session = class extends EventBus {
|
|
|
60947
60978
|
transportService;
|
|
60948
60979
|
serverRevisionId;
|
|
60949
60980
|
commandSquisher;
|
|
60981
|
+
shouldVerifySquish;
|
|
60950
60982
|
/**
|
|
60951
60983
|
* Positions of the others client.
|
|
60952
60984
|
*/
|
|
@@ -60981,13 +61013,15 @@ var Session = class extends EventBus {
|
|
|
60981
61013
|
* between all connected clients
|
|
60982
61014
|
* @param serverRevisionId
|
|
60983
61015
|
* @param commandSquisher used to squish and unsquish commands to reduce the size of messages sent to the server
|
|
61016
|
+
* @param shouldVerifySquish either the commands should be unsquished and verified before being sent to the server
|
|
60984
61017
|
*/
|
|
60985
|
-
constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher) {
|
|
61018
|
+
constructor(revisions, transportService, serverRevisionId = DEFAULT_REVISION_ID, commandSquisher, shouldVerifySquish = true) {
|
|
60986
61019
|
super();
|
|
60987
61020
|
this.revisions = revisions;
|
|
60988
61021
|
this.transportService = transportService;
|
|
60989
61022
|
this.serverRevisionId = serverRevisionId;
|
|
60990
61023
|
this.commandSquisher = commandSquisher;
|
|
61024
|
+
this.shouldVerifySquish = shouldVerifySquish;
|
|
60991
61025
|
}
|
|
60992
61026
|
canApplyOptimisticUpdate() {
|
|
60993
61027
|
return !this.waitingUndoRedoAck;
|
|
@@ -61243,10 +61277,20 @@ var Session = class extends EventBus {
|
|
|
61243
61277
|
this.revisions.rebase(revision.id);
|
|
61244
61278
|
revision = this.revisions.get(message.nextRevisionId);
|
|
61245
61279
|
}
|
|
61246
|
-
|
|
61280
|
+
const squishedCommands = this.commandSquisher.squish(revision.commands);
|
|
61281
|
+
if (!squishedCommands.some((x) => x.type === "SQUISHED_UPDATE_CELL")) message = {
|
|
61247
61282
|
...message,
|
|
61248
61283
|
commands: revision.commands
|
|
61249
61284
|
};
|
|
61285
|
+
else if (this.shouldVerifySquish && !deepEquals(revision.commands, this.commandSquisher.unsquish(squishedCommands))) message = {
|
|
61286
|
+
...message,
|
|
61287
|
+
commands: revision.commands,
|
|
61288
|
+
squishedFailed: true
|
|
61289
|
+
};
|
|
61290
|
+
else message = {
|
|
61291
|
+
...message,
|
|
61292
|
+
commands: squishedCommands
|
|
61293
|
+
};
|
|
61250
61294
|
}
|
|
61251
61295
|
if (this.isReplayingInitialRevisions) throw new Error(`Trying to send a new revision while replaying initial revision. This can lead to endless dispatches every time the spreadsheet is open.
|
|
61252
61296
|
${JSON.stringify(message)}`);
|
|
@@ -77399,7 +77443,7 @@ const ARRAYTOTEXT = {
|
|
|
77399
77443
|
else if (_format === 0) {
|
|
77400
77444
|
const rowSeparator = this.locale.decimalSeparator === "," ? "/" : ",";
|
|
77401
77445
|
return transposeMatrix(_array).flatMap((row) => row.map((value) => {
|
|
77402
|
-
return isEvaluationError(value.value) ? value.value :
|
|
77446
|
+
return isEvaluationError(value.value) ? value.value : toLocaleString(value, this.locale);
|
|
77403
77447
|
})).join(rowSeparator);
|
|
77404
77448
|
} else return new EvaluationError(_t("Format must be 0 or 1"));
|
|
77405
77449
|
},
|
|
@@ -83160,7 +83204,7 @@ const CONCAT = {
|
|
|
83160
83204
|
description: _t("Concatenation of two values."),
|
|
83161
83205
|
args: [arg("value1 (string)", _t("The value to which value2 will be appended.")), arg("value2 (string)", _t("The value to append to value1."))],
|
|
83162
83206
|
compute: function(value1, value2) {
|
|
83163
|
-
return
|
|
83207
|
+
return toLocaleString(value1, this.locale) + toLocaleString(value2, this.locale);
|
|
83164
83208
|
},
|
|
83165
83209
|
isExported: true
|
|
83166
83210
|
};
|
|
@@ -84025,7 +84069,7 @@ const CLEAN = {
|
|
|
84025
84069
|
description: _t("Remove non-printable characters from a piece of text."),
|
|
84026
84070
|
args: [arg("text (string)", _t("The text whose non-printable characters are to be removed."))],
|
|
84027
84071
|
compute: function(text) {
|
|
84028
|
-
const _text =
|
|
84072
|
+
const _text = toLocaleString(text, this.locale);
|
|
84029
84073
|
let cleanedStr = "";
|
|
84030
84074
|
for (const char of _text) if (char && char.charCodeAt(0) > 31) cleanedStr += char;
|
|
84031
84075
|
return cleanedStr;
|
|
@@ -84036,7 +84080,7 @@ const CONCATENATE = {
|
|
|
84036
84080
|
description: _t("Appends strings to one another."),
|
|
84037
84081
|
args: [arg("string (string, range<string>, repeating)", _t("String to append in sequence."))],
|
|
84038
84082
|
compute: function(...datas) {
|
|
84039
|
-
return reduceAny(datas, (acc, a) => acc +
|
|
84083
|
+
return reduceAny(datas, (acc, a) => acc + toLocaleString(a, this.locale), "");
|
|
84040
84084
|
},
|
|
84041
84085
|
isExported: true
|
|
84042
84086
|
};
|
|
@@ -84044,7 +84088,7 @@ const EXACT = {
|
|
|
84044
84088
|
description: _t("Tests whether two strings are identical."),
|
|
84045
84089
|
args: [arg("string1 (string)", _t("The first string to compare.")), arg("string2 (string)", _t("The second string to compare."))],
|
|
84046
84090
|
compute: function(string1, string2) {
|
|
84047
|
-
return
|
|
84091
|
+
return toLocaleString(string1, this.locale) === toLocaleString(string2, this.locale);
|
|
84048
84092
|
},
|
|
84049
84093
|
isExported: true
|
|
84050
84094
|
};
|
|
@@ -84056,8 +84100,8 @@ const FIND = {
|
|
|
84056
84100
|
arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
|
|
84057
84101
|
],
|
|
84058
84102
|
compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
|
|
84059
|
-
const _searchFor =
|
|
84060
|
-
const _textToSearch =
|
|
84103
|
+
const _searchFor = toLocaleString(searchFor, this.locale);
|
|
84104
|
+
const _textToSearch = toLocaleString(textToSearch, this.locale);
|
|
84061
84105
|
const _startingAt = toNumber(startingAt, this.locale);
|
|
84062
84106
|
if (_textToSearch === "") return new EvaluationError(_t("The text_to_search must be non-empty."));
|
|
84063
84107
|
if (_startingAt < 1) return new EvaluationError(_t("The starting_at (%s) must be greater than or equal to 1.", _startingAt));
|
|
@@ -84094,8 +84138,8 @@ const JOIN = {
|
|
|
84094
84138
|
description: _t("Concatenates elements of arrays with delimiter."),
|
|
84095
84139
|
args: [arg("delimiter (string)", _t("The character or string to place between each concatenated value.")), arg("value_or_array (string, range<string>, repeating)", _t("Value to be appended using delimiter."))],
|
|
84096
84140
|
compute: function(delimiter, ...valuesOrArrays) {
|
|
84097
|
-
const _delimiter =
|
|
84098
|
-
return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") +
|
|
84141
|
+
const _delimiter = toLocaleString(delimiter, this.locale);
|
|
84142
|
+
return reduceAny(valuesOrArrays, (acc, a) => (acc ? acc + _delimiter : "") + toLocaleString(a, this.locale), "");
|
|
84099
84143
|
}
|
|
84100
84144
|
};
|
|
84101
84145
|
const LEFT = {
|
|
@@ -84104,7 +84148,7 @@ const LEFT = {
|
|
|
84104
84148
|
compute: function(text, ...args) {
|
|
84105
84149
|
const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
|
|
84106
84150
|
if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
|
|
84107
|
-
return
|
|
84151
|
+
return toLocaleString(text, this.locale).substring(0, _numberOfCharacters);
|
|
84108
84152
|
},
|
|
84109
84153
|
isExported: true
|
|
84110
84154
|
};
|
|
@@ -84112,7 +84156,7 @@ const LEN = {
|
|
|
84112
84156
|
description: _t("Length of a string."),
|
|
84113
84157
|
args: [arg("text (string)", _t("The string whose length will be returned."))],
|
|
84114
84158
|
compute: function(text) {
|
|
84115
|
-
return
|
|
84159
|
+
return toLocaleString(text, this.locale).length;
|
|
84116
84160
|
},
|
|
84117
84161
|
isExported: true
|
|
84118
84162
|
};
|
|
@@ -84120,7 +84164,7 @@ const LOWER = {
|
|
|
84120
84164
|
description: _t("Converts a specified string to lowercase."),
|
|
84121
84165
|
args: [arg("text (string)", _t("The string to convert to lowercase."))],
|
|
84122
84166
|
compute: function(text) {
|
|
84123
|
-
return
|
|
84167
|
+
return toLocaleString(text, this.locale).toLowerCase();
|
|
84124
84168
|
},
|
|
84125
84169
|
isExported: true
|
|
84126
84170
|
};
|
|
@@ -84132,7 +84176,7 @@ const MID = {
|
|
|
84132
84176
|
arg("extract_length (number)", _t("The length of the segment to extract."))
|
|
84133
84177
|
],
|
|
84134
84178
|
compute: function(text, starting_at, extract_length) {
|
|
84135
|
-
const _text =
|
|
84179
|
+
const _text = toLocaleString(text, this.locale);
|
|
84136
84180
|
const _starting_at = toNumber(starting_at, this.locale);
|
|
84137
84181
|
const _extract_length = toNumber(extract_length, this.locale);
|
|
84138
84182
|
if (_starting_at < 1) return new EvaluationError(_t("The starting_at argument (%s) must be positive greater than one.", _starting_at.toString()));
|
|
@@ -84145,7 +84189,7 @@ const PROPER = {
|
|
|
84145
84189
|
description: _t("Capitalizes each word in a specified string."),
|
|
84146
84190
|
args: [arg("text_to_capitalize (string)", _t("The text which will be returned with the first letter of each word in uppercase and all other letters in lowercase."))],
|
|
84147
84191
|
compute: function(text) {
|
|
84148
|
-
return
|
|
84192
|
+
return toLocaleString(text, this.locale).replace(wordRegex, (word) => {
|
|
84149
84193
|
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
84150
84194
|
});
|
|
84151
84195
|
},
|
|
@@ -84293,9 +84337,9 @@ const REPLACE = {
|
|
|
84293
84337
|
compute: function(text, position, length, newText) {
|
|
84294
84338
|
const _position = toNumber(position, this.locale);
|
|
84295
84339
|
if (_position < 1) return new EvaluationError(_t("The position (%s) must be greater than or equal to 1.", _position));
|
|
84296
|
-
const _text =
|
|
84340
|
+
const _text = toLocaleString(text, this.locale);
|
|
84297
84341
|
const _length = toNumber(length, this.locale);
|
|
84298
|
-
const _newText =
|
|
84342
|
+
const _newText = toLocaleString(newText, this.locale);
|
|
84299
84343
|
return _text.substring(0, _position - 1) + _newText + _text.substring(_position - 1 + _length);
|
|
84300
84344
|
},
|
|
84301
84345
|
isExported: true
|
|
@@ -84306,7 +84350,7 @@ const RIGHT = {
|
|
|
84306
84350
|
compute: function(text, ...args) {
|
|
84307
84351
|
const _numberOfCharacters = args.length ? toNumber(args[0], this.locale) : 1;
|
|
84308
84352
|
if (_numberOfCharacters < 0) return new EvaluationError(_t("The number_of_characters (%s) must be positive or null.", _numberOfCharacters));
|
|
84309
|
-
const _text =
|
|
84353
|
+
const _text = toLocaleString(text, this.locale);
|
|
84310
84354
|
const stringLength = _text.length;
|
|
84311
84355
|
return _text.substring(stringLength - _numberOfCharacters, stringLength);
|
|
84312
84356
|
},
|
|
@@ -84320,8 +84364,8 @@ const SEARCH = {
|
|
|
84320
84364
|
arg(`starting_at (number, default=${DEFAULT_STARTING_AT})`, _t("The character within text_to_search at which to start the search."))
|
|
84321
84365
|
],
|
|
84322
84366
|
compute: function(searchFor, textToSearch, startingAt = { value: DEFAULT_STARTING_AT }) {
|
|
84323
|
-
const _searchFor =
|
|
84324
|
-
const _textToSearch =
|
|
84367
|
+
const _searchFor = toLocaleString(searchFor, this.locale).toLowerCase();
|
|
84368
|
+
const _textToSearch = toLocaleString(textToSearch, this.locale).toLowerCase();
|
|
84325
84369
|
const _startingAt = toNumber(startingAt, this.locale);
|
|
84326
84370
|
if (_textToSearch === "") return {
|
|
84327
84371
|
value: CellErrorType.GenericError,
|
|
@@ -84351,8 +84395,8 @@ const SPLIT = {
|
|
|
84351
84395
|
arg(`remove_empty_text (boolean, default=${SPLIT_DEFAULT_REMOVE_EMPTY_TEXT})`, _t("Whether or not to remove empty text messages from the split results. The default behavior is to treat consecutive delimiters as one (if TRUE). If FALSE, empty cells values are added between consecutive delimiters."))
|
|
84352
84396
|
],
|
|
84353
84397
|
compute: function(text, delimiter, splitByEach = { value: SPLIT_DEFAULT_SPLIT_BY_EACH }, removeEmptyText = { value: SPLIT_DEFAULT_REMOVE_EMPTY_TEXT }) {
|
|
84354
|
-
const _text =
|
|
84355
|
-
const _delimiter = escapeRegExp(
|
|
84398
|
+
const _text = toLocaleString(text, this.locale);
|
|
84399
|
+
const _delimiter = escapeRegExp(toLocaleString(delimiter, this.locale));
|
|
84356
84400
|
const _splitByEach = toBoolean(splitByEach);
|
|
84357
84401
|
const _removeEmptyText = toBoolean(removeEmptyText);
|
|
84358
84402
|
if (_delimiter.length <= 0) return new EvaluationError(_t("The delimiter (%s) must be not be empty.", _delimiter));
|
|
@@ -84374,10 +84418,10 @@ const SUBSTITUTE = {
|
|
|
84374
84418
|
compute: function(textToSearch, searchFor, replaceWith, occurrenceNumber) {
|
|
84375
84419
|
const _occurrenceNumber = toNumber(occurrenceNumber, this.locale);
|
|
84376
84420
|
if (_occurrenceNumber < 0) return new EvaluationError(_t("The occurrenceNumber (%s) must be positive or null.", _occurrenceNumber));
|
|
84377
|
-
const _textToSearch =
|
|
84378
|
-
const _searchFor =
|
|
84421
|
+
const _textToSearch = toLocaleString(textToSearch, this.locale);
|
|
84422
|
+
const _searchFor = toLocaleString(searchFor, this.locale);
|
|
84379
84423
|
if (_searchFor === "") return _textToSearch;
|
|
84380
|
-
const _replaceWith =
|
|
84424
|
+
const _replaceWith = toLocaleString(replaceWith, this.locale);
|
|
84381
84425
|
const reg = new RegExp(escapeRegExp(_searchFor), "g");
|
|
84382
84426
|
if (_occurrenceNumber === 0) return _textToSearch.replace(reg, _replaceWith);
|
|
84383
84427
|
let n = 0;
|
|
@@ -84400,10 +84444,10 @@ const TEXTJOIN = {
|
|
|
84400
84444
|
arg("texts (string, range<string>, repeating)", _t("Text item to join."))
|
|
84401
84445
|
],
|
|
84402
84446
|
compute: function(delimiter, ignoreEmpty = { value: TEXTJOIN_DEFAULT_IGNORE_EMPTY }, ...textsOrArrays) {
|
|
84403
|
-
const _delimiter =
|
|
84447
|
+
const _delimiter = toLocaleString(delimiter, this.locale);
|
|
84404
84448
|
const _ignoreEmpty = toBoolean(ignoreEmpty);
|
|
84405
84449
|
let n = 0;
|
|
84406
|
-
return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty &&
|
|
84450
|
+
return reduceAny(textsOrArrays, (acc, a) => !(_ignoreEmpty && toLocaleString(a, this.locale) === "") ? (n++ ? acc + _delimiter : "") + toLocaleString(a, this.locale) : acc, "");
|
|
84407
84451
|
},
|
|
84408
84452
|
isExported: true
|
|
84409
84453
|
};
|
|
@@ -84456,7 +84500,7 @@ const TRIM = {
|
|
|
84456
84500
|
description: _t("Removes space characters."),
|
|
84457
84501
|
args: [arg("text (string)", _t("The text or reference to a cell containing text to be trimmed."))],
|
|
84458
84502
|
compute: function(text) {
|
|
84459
|
-
return trimContent(
|
|
84503
|
+
return trimContent(toLocaleString(text, this.locale));
|
|
84460
84504
|
},
|
|
84461
84505
|
isExported: true
|
|
84462
84506
|
};
|
|
@@ -84464,7 +84508,7 @@ const UPPER = {
|
|
|
84464
84508
|
description: _t("Converts a specified string to uppercase."),
|
|
84465
84509
|
args: [arg("text (string)", _t("The string to convert to uppercase."))],
|
|
84466
84510
|
compute: function(text) {
|
|
84467
|
-
return
|
|
84511
|
+
return toLocaleString(text, this.locale).toUpperCase();
|
|
84468
84512
|
},
|
|
84469
84513
|
isExported: true
|
|
84470
84514
|
};
|
|
@@ -84561,7 +84605,7 @@ const HYPERLINK = {
|
|
|
84561
84605
|
args: [arg("url (string)", _t("The full URL of the link enclosed in quotation marks.")), arg("link_label (string, optional)", _t("The text to display in the cell, enclosed in quotation marks."))],
|
|
84562
84606
|
compute: function(url, linkLabel) {
|
|
84563
84607
|
const processedUrl = toString(url).trim();
|
|
84564
|
-
const processedLabel =
|
|
84608
|
+
const processedLabel = toLocaleString(linkLabel, this.locale) || processedUrl;
|
|
84565
84609
|
if (processedUrl === "") return processedLabel;
|
|
84566
84610
|
return markdownLink(processedLabel, processedUrl);
|
|
84567
84611
|
},
|
|
@@ -84958,6 +85002,6 @@ exports.stores = stores;
|
|
|
84958
85002
|
exports.tokenColors = tokenColors;
|
|
84959
85003
|
exports.tokenize = tokenize;
|
|
84960
85004
|
|
|
84961
|
-
__info__.version = "19.3.
|
|
84962
|
-
__info__.date = "2026-08-
|
|
84963
|
-
__info__.hash = "
|
|
85005
|
+
__info__.version = "19.3.18";
|
|
85006
|
+
__info__.date = "2026-08-29T09:16:28.272Z";
|
|
85007
|
+
__info__.hash = "1f4b1ae";
|
package/dist/o_spreadsheet.css
CHANGED
|
@@ -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 19.3.
|
|
6
|
-
* @date 2026-08-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.3.18
|
|
6
|
+
* @date 2026-08-29T09:16:30.020Z
|
|
7
|
+
* @hash 1f4b1ae
|
|
8
8
|
*/
|
|
9
9
|
:root {
|
|
10
10
|
--os-gray-100: light-dark(#f9fafb, #1b1d26);
|
|
@@ -300,6 +300,7 @@
|
|
|
300
300
|
.os-input {
|
|
301
301
|
border-width: 0 0 1px 0;
|
|
302
302
|
border-color: transparent;
|
|
303
|
+
border-style: solid;
|
|
303
304
|
outline: none;
|
|
304
305
|
text-overflow: ellipsis;
|
|
305
306
|
color: var(--os-text-body);
|
|
@@ -630,6 +631,7 @@
|
|
|
630
631
|
width: 100%;
|
|
631
632
|
outline: none;
|
|
632
633
|
border-color: var(--os-border-color);
|
|
634
|
+
border-style: solid;
|
|
633
635
|
color: var(--os-gray-900);
|
|
634
636
|
|
|
635
637
|
&::placeholder {
|
|
@@ -1478,6 +1480,12 @@
|
|
|
1478
1480
|
background-color: var(--os-action-color);
|
|
1479
1481
|
border-color: var(--os-action-color) !important;
|
|
1480
1482
|
}
|
|
1483
|
+
|
|
1484
|
+
&:focus {
|
|
1485
|
+
outline: none;
|
|
1486
|
+
box-shadow: 0 0 0 0.25rem rgba(113, 75, 103, 0.25);
|
|
1487
|
+
border-color: var(--os-action-color);
|
|
1488
|
+
}
|
|
1481
1489
|
}
|
|
1482
1490
|
}
|
|
1483
1491
|
}
|