@odoo/o-spreadsheet 16.4.0-alpha.6 → 16.4.0-alpha.7
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.js +249 -97
- package/dist/o-spreadsheet.d.ts +27 -27
- package/dist/o-spreadsheet.esm.js +249 -98
- package/dist/o-spreadsheet.iife.js +249 -97
- package/dist/o-spreadsheet.iife.min.js +248 -245
- package/package.json +1 -1
|
@@ -12596,6 +12596,18 @@ const AND = {
|
|
|
12596
12596
|
isExported: true,
|
|
12597
12597
|
};
|
|
12598
12598
|
// -----------------------------------------------------------------------------
|
|
12599
|
+
// FALSE
|
|
12600
|
+
// -----------------------------------------------------------------------------
|
|
12601
|
+
const FALSE = {
|
|
12602
|
+
description: _lt("Logical value `false`."),
|
|
12603
|
+
args: [],
|
|
12604
|
+
returns: ["BOOLEAN"],
|
|
12605
|
+
compute: function () {
|
|
12606
|
+
return false;
|
|
12607
|
+
},
|
|
12608
|
+
isExported: true,
|
|
12609
|
+
};
|
|
12610
|
+
// -----------------------------------------------------------------------------
|
|
12599
12611
|
// IF
|
|
12600
12612
|
// -----------------------------------------------------------------------------
|
|
12601
12613
|
const IF = {
|
|
@@ -12731,6 +12743,18 @@ const OR = {
|
|
|
12731
12743
|
isExported: true,
|
|
12732
12744
|
};
|
|
12733
12745
|
// -----------------------------------------------------------------------------
|
|
12746
|
+
// TRUE
|
|
12747
|
+
// -----------------------------------------------------------------------------
|
|
12748
|
+
const TRUE = {
|
|
12749
|
+
description: _lt("Logical value `true`."),
|
|
12750
|
+
args: [],
|
|
12751
|
+
returns: ["BOOLEAN"],
|
|
12752
|
+
compute: function () {
|
|
12753
|
+
return true;
|
|
12754
|
+
},
|
|
12755
|
+
isExported: true,
|
|
12756
|
+
};
|
|
12757
|
+
// -----------------------------------------------------------------------------
|
|
12734
12758
|
// XOR
|
|
12735
12759
|
// -----------------------------------------------------------------------------
|
|
12736
12760
|
const XOR = {
|
|
@@ -12757,12 +12781,14 @@ const XOR = {
|
|
|
12757
12781
|
var logical = /*#__PURE__*/Object.freeze({
|
|
12758
12782
|
__proto__: null,
|
|
12759
12783
|
AND: AND,
|
|
12784
|
+
FALSE: FALSE,
|
|
12760
12785
|
IF: IF,
|
|
12761
12786
|
IFERROR: IFERROR,
|
|
12762
12787
|
IFNA: IFNA,
|
|
12763
12788
|
IFS: IFS,
|
|
12764
12789
|
NOT: NOT,
|
|
12765
12790
|
OR: OR,
|
|
12791
|
+
TRUE: TRUE,
|
|
12766
12792
|
XOR: XOR
|
|
12767
12793
|
});
|
|
12768
12794
|
|
|
@@ -13949,7 +13975,6 @@ function indentCode(code) {
|
|
|
13949
13975
|
* is useful for the composer, which needs to be able to work with incomplete
|
|
13950
13976
|
* formulas.
|
|
13951
13977
|
*/
|
|
13952
|
-
const functions$3 = functionRegistry.content;
|
|
13953
13978
|
const POSTFIX_UNARY_OPERATORS = ["%"];
|
|
13954
13979
|
const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
|
|
13955
13980
|
function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
@@ -14080,17 +14105,11 @@ function tokenizeSymbol(chars) {
|
|
|
14080
14105
|
}
|
|
14081
14106
|
if (result.length) {
|
|
14082
14107
|
const value = result;
|
|
14083
|
-
const isFunction = value.toUpperCase() in functions$3;
|
|
14084
|
-
if (isFunction) {
|
|
14085
|
-
return { type: "FUNCTION", value };
|
|
14086
|
-
}
|
|
14087
14108
|
const isReference = rangeReference.test(value);
|
|
14088
14109
|
if (isReference) {
|
|
14089
14110
|
return { type: "REFERENCE", value };
|
|
14090
14111
|
}
|
|
14091
|
-
|
|
14092
|
-
return { type: "SYMBOL", value };
|
|
14093
|
-
}
|
|
14112
|
+
return { type: "SYMBOL", value };
|
|
14094
14113
|
}
|
|
14095
14114
|
return null;
|
|
14096
14115
|
}
|
|
@@ -14190,9 +14209,6 @@ function parseOperand(tokens) {
|
|
|
14190
14209
|
return { type: "NUMBER", value: parseNumber(current.value, DEFAULT_LOCALE) };
|
|
14191
14210
|
case "STRING":
|
|
14192
14211
|
return { type: "STRING", value: removeStringQuotes(current.value) };
|
|
14193
|
-
case "FUNCTION":
|
|
14194
|
-
const args = parseFunctionArgs(tokens);
|
|
14195
|
-
return { type: "FUNCALL", value: current.value, args };
|
|
14196
14212
|
case "INVALID_REFERENCE":
|
|
14197
14213
|
throw new InvalidReferenceError();
|
|
14198
14214
|
case "REFERENCE":
|
|
@@ -14209,13 +14225,15 @@ function parseOperand(tokens) {
|
|
|
14209
14225
|
value: current.value,
|
|
14210
14226
|
};
|
|
14211
14227
|
case "SYMBOL":
|
|
14212
|
-
|
|
14213
|
-
|
|
14228
|
+
const value = current.value;
|
|
14229
|
+
const nextToken = tokens[0];
|
|
14230
|
+
if (nextToken?.type === "LEFT_PAREN" && functionRegex.test(current.value)) {
|
|
14231
|
+
const args = parseFunctionArgs(tokens);
|
|
14232
|
+
return { type: "FUNCALL", value: value, args };
|
|
14214
14233
|
}
|
|
14215
|
-
|
|
14216
|
-
|
|
14217
|
-
|
|
14218
|
-
}
|
|
14234
|
+
const upperCaseValue = value.toUpperCase();
|
|
14235
|
+
if (upperCaseValue === "TRUE" || upperCaseValue === "FALSE") {
|
|
14236
|
+
return { type: "BOOLEAN", value: upperCaseValue === "TRUE" };
|
|
14219
14237
|
}
|
|
14220
14238
|
throw new BadExpressionError(_lt("Invalid formula"));
|
|
14221
14239
|
case "LEFT_PAREN":
|
|
@@ -14317,36 +14335,60 @@ function parseTokens(tokens) {
|
|
|
14317
14335
|
* to nodes of a specific type.
|
|
14318
14336
|
* Useful if you want to convert some part of a formula.
|
|
14319
14337
|
*
|
|
14320
|
-
*
|
|
14321
|
-
* ```ts
|
|
14338
|
+
* @example
|
|
14322
14339
|
* convertAstNodes(ast, "FUNCALL", convertFormulaToExcel)
|
|
14323
14340
|
*
|
|
14324
14341
|
* function convertFormulaToExcel(ast: ASTFuncall) {
|
|
14325
14342
|
* // ...
|
|
14326
14343
|
* return modifiedAst
|
|
14327
14344
|
* }
|
|
14328
|
-
* ```
|
|
14329
14345
|
*/
|
|
14330
14346
|
function convertAstNodes(ast, type, fn) {
|
|
14331
|
-
|
|
14332
|
-
ast
|
|
14347
|
+
return mapAst(ast, (ast) => {
|
|
14348
|
+
if (ast.type === type) {
|
|
14349
|
+
return fn(ast);
|
|
14350
|
+
}
|
|
14351
|
+
return ast;
|
|
14352
|
+
});
|
|
14353
|
+
}
|
|
14354
|
+
function iterateAstNodes(ast) {
|
|
14355
|
+
return Array.from(astIterator(ast));
|
|
14356
|
+
}
|
|
14357
|
+
function* astIterator(ast) {
|
|
14358
|
+
yield ast;
|
|
14359
|
+
switch (ast.type) {
|
|
14360
|
+
case "FUNCALL":
|
|
14361
|
+
for (const arg of ast.args) {
|
|
14362
|
+
yield* astIterator(arg);
|
|
14363
|
+
}
|
|
14364
|
+
break;
|
|
14365
|
+
case "UNARY_OPERATION":
|
|
14366
|
+
yield* astIterator(ast.operand);
|
|
14367
|
+
break;
|
|
14368
|
+
case "BIN_OPERATION":
|
|
14369
|
+
yield* astIterator(ast.left);
|
|
14370
|
+
yield* astIterator(ast.right);
|
|
14371
|
+
break;
|
|
14333
14372
|
}
|
|
14373
|
+
}
|
|
14374
|
+
function mapAst(ast, fn) {
|
|
14375
|
+
ast = fn(ast);
|
|
14334
14376
|
switch (ast.type) {
|
|
14335
14377
|
case "FUNCALL":
|
|
14336
14378
|
return {
|
|
14337
14379
|
...ast,
|
|
14338
|
-
args: ast.args.map((child) =>
|
|
14380
|
+
args: ast.args.map((child) => mapAst(child, fn)),
|
|
14339
14381
|
};
|
|
14340
14382
|
case "UNARY_OPERATION":
|
|
14341
14383
|
return {
|
|
14342
14384
|
...ast,
|
|
14343
|
-
operand:
|
|
14385
|
+
operand: mapAst(ast.operand, fn),
|
|
14344
14386
|
};
|
|
14345
14387
|
case "BIN_OPERATION":
|
|
14346
14388
|
return {
|
|
14347
14389
|
...ast,
|
|
14348
|
-
right:
|
|
14349
|
-
left:
|
|
14390
|
+
right: mapAst(ast.right, fn),
|
|
14391
|
+
left: mapAst(ast.left, fn),
|
|
14350
14392
|
};
|
|
14351
14393
|
default:
|
|
14352
14394
|
return ast;
|
|
@@ -14616,6 +14658,9 @@ function compile(formula) {
|
|
|
14616
14658
|
const { args } = ast;
|
|
14617
14659
|
const functionName = ast.value.toUpperCase();
|
|
14618
14660
|
const functionDefinition = functions$2[functionName];
|
|
14661
|
+
if (!functionDefinition) {
|
|
14662
|
+
throw new UnknownFunctionError(ast.value);
|
|
14663
|
+
}
|
|
14619
14664
|
assertEnoughArgs(ast);
|
|
14620
14665
|
const compiledArgs = [];
|
|
14621
14666
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -14874,7 +14919,7 @@ function mapParentFunction(tokens) {
|
|
|
14874
14919
|
functionStarted = "";
|
|
14875
14920
|
}
|
|
14876
14921
|
switch (token.type) {
|
|
14877
|
-
case "
|
|
14922
|
+
case "SYMBOL":
|
|
14878
14923
|
functionStarted = token.value;
|
|
14879
14924
|
break;
|
|
14880
14925
|
case "LEFT_PAREN":
|
|
@@ -14911,6 +14956,17 @@ function composerTokenize(formula, locale) {
|
|
|
14911
14956
|
return mapParentFunction(mapParenthesis(enrichTokens(tokens)));
|
|
14912
14957
|
}
|
|
14913
14958
|
|
|
14959
|
+
const functions$1 = functionRegistry.content;
|
|
14960
|
+
function isExportableToExcel(tokens) {
|
|
14961
|
+
try {
|
|
14962
|
+
const nonExportableFunctions = iterateAstNodes(parseTokens(tokens)).filter((ast) => ast.type === "FUNCALL" && !functions$1[ast.value.toUpperCase()]?.isExported);
|
|
14963
|
+
return nonExportableFunctions.length === 0;
|
|
14964
|
+
}
|
|
14965
|
+
catch (error) {
|
|
14966
|
+
return false;
|
|
14967
|
+
}
|
|
14968
|
+
}
|
|
14969
|
+
|
|
14914
14970
|
function isValidLocale(locale) {
|
|
14915
14971
|
if (!(locale &&
|
|
14916
14972
|
typeof locale === "object" &&
|
|
@@ -17483,8 +17539,14 @@ function getImageMenuRegistry(figureId, onFigureDeleted, env) {
|
|
|
17483
17539
|
id: "reset_size",
|
|
17484
17540
|
name: _lt("Reset size"),
|
|
17485
17541
|
sequence: 4,
|
|
17486
|
-
execute: () => {
|
|
17487
|
-
const
|
|
17542
|
+
execute: async () => {
|
|
17543
|
+
const imagePath = env.model.getters.getImagePath(figureId);
|
|
17544
|
+
const size = env.model.getters.getImageSize(figureId) ??
|
|
17545
|
+
(await env.imageProvider?.getImageOriginalSize(imagePath));
|
|
17546
|
+
if (!env.model.getters.getImageSize(figureId)) {
|
|
17547
|
+
const image = env.model.getters.getImage(figureId);
|
|
17548
|
+
image.size = size;
|
|
17549
|
+
}
|
|
17488
17550
|
const { height, width } = getMaxFigureSize(env.model.getters, size);
|
|
17489
17551
|
env.model.dispatch("UPDATE_FIGURE", {
|
|
17490
17552
|
sheetId: env.model.getters.getActiveSheetId(),
|
|
@@ -23537,7 +23599,7 @@ FunctionDescriptionProvider.props = {
|
|
|
23537
23599
|
argToFocus: Number,
|
|
23538
23600
|
};
|
|
23539
23601
|
|
|
23540
|
-
const functions
|
|
23602
|
+
const functions = functionRegistry.content;
|
|
23541
23603
|
const ASSISTANT_WIDTH = 300;
|
|
23542
23604
|
const selectionIndicatorClass = "selector-flag";
|
|
23543
23605
|
const selectionIndicatorColor = "#a9a9a9";
|
|
@@ -23571,10 +23633,6 @@ css /* scss */ `
|
|
|
23571
23633
|
padding-right: 3px;
|
|
23572
23634
|
outline: none;
|
|
23573
23635
|
|
|
23574
|
-
&.unfocusable {
|
|
23575
|
-
pointer-events: none;
|
|
23576
|
-
}
|
|
23577
|
-
|
|
23578
23636
|
p {
|
|
23579
23637
|
margin-bottom: 0px;
|
|
23580
23638
|
|
|
@@ -23822,7 +23880,10 @@ class Composer extends owl.Component {
|
|
|
23822
23880
|
}
|
|
23823
23881
|
}
|
|
23824
23882
|
showAutocomplete(searchTerm) {
|
|
23825
|
-
|
|
23883
|
+
const searchTermUpperCase = searchTerm.toUpperCase();
|
|
23884
|
+
if (!this.env.model.getters.getCurrentContent().startsWith("=") ||
|
|
23885
|
+
searchTermUpperCase === "TRUE" ||
|
|
23886
|
+
searchTermUpperCase === "FALSE") {
|
|
23826
23887
|
return;
|
|
23827
23888
|
}
|
|
23828
23889
|
this.autoCompleteState.showProvider = true;
|
|
@@ -23940,7 +24001,6 @@ class Composer extends owl.Component {
|
|
|
23940
24001
|
switch (token.type) {
|
|
23941
24002
|
case "OPERATOR":
|
|
23942
24003
|
case "NUMBER":
|
|
23943
|
-
case "FUNCTION":
|
|
23944
24004
|
case "ARG_SEPARATOR":
|
|
23945
24005
|
case "STRING":
|
|
23946
24006
|
result.push({ value: token.value, color: tokenColors[token.type] || "#000" });
|
|
@@ -23950,10 +24010,14 @@ class Composer extends owl.Component {
|
|
|
23950
24010
|
result.push({ value: token.value, color: this.rangeColor(xc, sheetName) || "#000" });
|
|
23951
24011
|
break;
|
|
23952
24012
|
case "SYMBOL":
|
|
23953
|
-
|
|
23954
|
-
|
|
24013
|
+
const value = token.value;
|
|
24014
|
+
const upperCaseValue = value.toUpperCase();
|
|
24015
|
+
if (upperCaseValue === "TRUE" || upperCaseValue === "FALSE") {
|
|
23955
24016
|
result.push({ value: token.value, color: tokenColors.NUMBER });
|
|
23956
24017
|
}
|
|
24018
|
+
else if (upperCaseValue in functionRegistry.content) {
|
|
24019
|
+
result.push({ value: token.value, color: tokenColors.FUNCTION });
|
|
24020
|
+
}
|
|
23957
24021
|
else {
|
|
23958
24022
|
result.push({ value: token.value, color: "#000" });
|
|
23959
24023
|
}
|
|
@@ -24049,25 +24113,28 @@ class Composer extends owl.Component {
|
|
|
24049
24113
|
this.autoCompleteState.showProvider = false;
|
|
24050
24114
|
this.functionDescriptionState.showDescription = false;
|
|
24051
24115
|
if (content.startsWith("=")) {
|
|
24052
|
-
const
|
|
24053
|
-
if (
|
|
24054
|
-
|
|
24055
|
-
|
|
24056
|
-
|
|
24057
|
-
|
|
24058
|
-
|
|
24059
|
-
|
|
24060
|
-
|
|
24061
|
-
|
|
24062
|
-
|
|
24063
|
-
|
|
24064
|
-
|
|
24065
|
-
|
|
24066
|
-
|
|
24067
|
-
|
|
24068
|
-
|
|
24069
|
-
|
|
24070
|
-
|
|
24116
|
+
const token = this.env.model.getters.getTokenAtCursor();
|
|
24117
|
+
if (!token) {
|
|
24118
|
+
return;
|
|
24119
|
+
}
|
|
24120
|
+
if (token.type === "SYMBOL") {
|
|
24121
|
+
// initialize Autocomplete Dropdown
|
|
24122
|
+
this.showAutocomplete(token.value);
|
|
24123
|
+
return;
|
|
24124
|
+
}
|
|
24125
|
+
const tokenContext = token.functionContext;
|
|
24126
|
+
const parentFunction = tokenContext?.parent.toUpperCase();
|
|
24127
|
+
if (tokenContext &&
|
|
24128
|
+
parentFunction &&
|
|
24129
|
+
parentFunction in functions &&
|
|
24130
|
+
token.type !== "UNKNOWN") {
|
|
24131
|
+
// initialize Formula Assistant
|
|
24132
|
+
const description = functions[parentFunction];
|
|
24133
|
+
const argPosition = tokenContext.argPosition;
|
|
24134
|
+
this.functionDescriptionState.functionName = parentFunction;
|
|
24135
|
+
this.functionDescriptionState.functionDescription = description;
|
|
24136
|
+
this.functionDescriptionState.argToFocus = description.getArgToFocus(argPosition + 1) - 1;
|
|
24137
|
+
this.functionDescriptionState.showDescription = true;
|
|
24071
24138
|
}
|
|
24072
24139
|
}
|
|
24073
24140
|
}
|
|
@@ -26767,7 +26834,12 @@ const XLSX_RELATION_TYPE = {
|
|
|
26767
26834
|
};
|
|
26768
26835
|
const RELATIONSHIP_NSR = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
26769
26836
|
const HEIGHT_FACTOR = 0.75; // 100px => 75 u
|
|
26770
|
-
|
|
26837
|
+
/**
|
|
26838
|
+
* Excel says its default column width is 8.43 characters (64px)
|
|
26839
|
+
* which makes WIDTH_FACTOR = 0.1317, but it doesn't work well
|
|
26840
|
+
* 0.143 is a value from dev's experiments.
|
|
26841
|
+
*/
|
|
26842
|
+
const WIDTH_FACTOR = 0.143;
|
|
26771
26843
|
/** unit : maximum number of characters a column can hold at the standard font size. What. */
|
|
26772
26844
|
const EXCEL_DEFAULT_COL_WIDTH = 8.43;
|
|
26773
26845
|
/** unit : points */
|
|
@@ -27284,7 +27356,7 @@ const XLSX_INDEXED_COLORS = {
|
|
|
27284
27356
|
64: "000000",
|
|
27285
27357
|
65: "FFFFFF", // system background
|
|
27286
27358
|
};
|
|
27287
|
-
const
|
|
27359
|
+
const IMAGE_MIMETYPE_TO_EXTENSION_MAPPING = {
|
|
27288
27360
|
"image/avif": "avif",
|
|
27289
27361
|
"image/bmp": "bmp",
|
|
27290
27362
|
"image/gif": "gif",
|
|
@@ -27293,6 +27365,17 @@ const IMAGE_MIMETYPE_EXTENSION_MAPPING = {
|
|
|
27293
27365
|
"image/png": "png",
|
|
27294
27366
|
"image/tiff": "tiff",
|
|
27295
27367
|
"image/webp": "webp",
|
|
27368
|
+
};
|
|
27369
|
+
const IMAGE_EXTENSION_TO_MIMETYPE_MAPPING = {
|
|
27370
|
+
avif: "image/avif",
|
|
27371
|
+
bmp: "image/bmp",
|
|
27372
|
+
gif: "image/gif",
|
|
27373
|
+
ico: "image/vnd.microsoft.icon",
|
|
27374
|
+
jpeg: "image/jpeg",
|
|
27375
|
+
png: "image/png",
|
|
27376
|
+
tiff: "image/tiff",
|
|
27377
|
+
webp: "image/webp",
|
|
27378
|
+
jpg: "image/jpeg",
|
|
27296
27379
|
};
|
|
27297
27380
|
|
|
27298
27381
|
/**
|
|
@@ -28096,20 +28179,35 @@ function convertFigure(figure, id, sheetData) {
|
|
|
28096
28179
|
convertEMUToDotValue(figure.anchors[0].rowOffset);
|
|
28097
28180
|
const y2 = getRowPosition(figure.anchors[1].row, sheetData) +
|
|
28098
28181
|
convertEMUToDotValue(figure.anchors[1].rowOffset);
|
|
28099
|
-
const
|
|
28100
|
-
|
|
28101
|
-
|
|
28102
|
-
|
|
28103
|
-
|
|
28104
|
-
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
|
|
28108
|
-
|
|
28109
|
-
|
|
28110
|
-
|
|
28111
|
-
|
|
28112
|
-
|
|
28182
|
+
const figureData = { id, x: x1, y: y1 };
|
|
28183
|
+
if (isChartData(figure.data)) {
|
|
28184
|
+
return {
|
|
28185
|
+
...figureData,
|
|
28186
|
+
width: x2 - x1,
|
|
28187
|
+
height: y2 - y1,
|
|
28188
|
+
tag: "chart",
|
|
28189
|
+
data: convertChartData(figure.data),
|
|
28190
|
+
};
|
|
28191
|
+
}
|
|
28192
|
+
else if (isImageData(figure.data)) {
|
|
28193
|
+
return {
|
|
28194
|
+
...figureData,
|
|
28195
|
+
width: convertEMUToDotValue(figure.data.size.cx),
|
|
28196
|
+
height: convertEMUToDotValue(figure.data.size.cy),
|
|
28197
|
+
tag: "image",
|
|
28198
|
+
data: {
|
|
28199
|
+
path: figure.data.imageSrc,
|
|
28200
|
+
mimetype: figure.data.mimetype,
|
|
28201
|
+
},
|
|
28202
|
+
};
|
|
28203
|
+
}
|
|
28204
|
+
return undefined;
|
|
28205
|
+
}
|
|
28206
|
+
function isChartData(data) {
|
|
28207
|
+
return "dataSets" in data;
|
|
28208
|
+
}
|
|
28209
|
+
function isImageData(data) {
|
|
28210
|
+
return "imageSrc" in data;
|
|
28113
28211
|
}
|
|
28114
28212
|
function convertChartData(chartData) {
|
|
28115
28213
|
const dataSetsHaveTitle = chartData.dataSets[0].label !== undefined;
|
|
@@ -28816,9 +28914,13 @@ class XlsxBaseExtractor {
|
|
|
28816
28914
|
/**
|
|
28817
28915
|
* Get the list of all the XLSX files in the XLSX file structure
|
|
28818
28916
|
*/
|
|
28819
|
-
|
|
28820
|
-
const
|
|
28821
|
-
|
|
28917
|
+
getListOfXMLFiles() {
|
|
28918
|
+
const XMLFiles = Object.entries(this.xlsxFileStructure)
|
|
28919
|
+
.filter(([key]) => key !== "images")
|
|
28920
|
+
.map(([_, value]) => value)
|
|
28921
|
+
.flat()
|
|
28922
|
+
.filter(isDefined$1);
|
|
28923
|
+
return XMLFiles;
|
|
28822
28924
|
}
|
|
28823
28925
|
/**
|
|
28824
28926
|
* Return an array containing the return value of the given function applied to all the XML elements
|
|
@@ -28990,20 +29092,31 @@ class XlsxBaseExtractor {
|
|
|
28990
29092
|
return color;
|
|
28991
29093
|
}
|
|
28992
29094
|
/**
|
|
28993
|
-
* Returns the
|
|
29095
|
+
* Returns the xml file targeted by a relationship.
|
|
28994
29096
|
*/
|
|
28995
29097
|
getTargetXmlFile(relationship) {
|
|
28996
29098
|
if (!relationship)
|
|
28997
29099
|
throw new Error("Undefined target file");
|
|
28998
|
-
|
|
28999
|
-
target = target.replace("../", "");
|
|
29000
|
-
target = target.replace("./", "");
|
|
29100
|
+
const target = this.processRelationshipTargetName(relationship.target);
|
|
29001
29101
|
// Use "endsWith" because targets are relative paths, and we know the files by their absolute path.
|
|
29002
|
-
const f = this.
|
|
29102
|
+
const f = this.getListOfXMLFiles().find((f) => f.file.fileName.endsWith(target));
|
|
29003
29103
|
if (!f || !f.file)
|
|
29004
29104
|
throw new Error("Cannot find target file");
|
|
29005
29105
|
return f;
|
|
29006
29106
|
}
|
|
29107
|
+
/**
|
|
29108
|
+
* Returns the image parameters targeted by a relationship.
|
|
29109
|
+
*/
|
|
29110
|
+
getTargetImageFile(relationship) {
|
|
29111
|
+
if (!relationship)
|
|
29112
|
+
throw new Error("Undefined target file");
|
|
29113
|
+
const target = this.processRelationshipTargetName(relationship.target);
|
|
29114
|
+
// Use "endsWith" because targets are relative paths, and we know the files by their absolute path.
|
|
29115
|
+
const f = this.xlsxFileStructure.images.find((f) => f.fileName.endsWith(target));
|
|
29116
|
+
if (!f)
|
|
29117
|
+
throw new Error("Cannot find target file");
|
|
29118
|
+
return f;
|
|
29119
|
+
}
|
|
29007
29120
|
/**
|
|
29008
29121
|
* Wrapper of querySelector, but we'll remove the namespaces from the query if areNamespacesIgnored is true.
|
|
29009
29122
|
*
|
|
@@ -29050,6 +29163,10 @@ class XlsxBaseExtractor {
|
|
|
29050
29163
|
return clrScheme[colorId].value;
|
|
29051
29164
|
}
|
|
29052
29165
|
}
|
|
29166
|
+
/** Remove signs of relative path. */
|
|
29167
|
+
processRelationshipTargetName(targetName) {
|
|
29168
|
+
return targetName.replace(/\.+\//, "");
|
|
29169
|
+
}
|
|
29053
29170
|
}
|
|
29054
29171
|
|
|
29055
29172
|
/**
|
|
@@ -29279,15 +29396,16 @@ class XlsxFigureExtractor extends XlsxBaseExtractor {
|
|
|
29279
29396
|
throw new Error("Only twoCellAnchor are supported for xlsx drawings.");
|
|
29280
29397
|
}
|
|
29281
29398
|
const chartElement = this.querySelector(figureElement, "c:chart");
|
|
29282
|
-
|
|
29283
|
-
|
|
29399
|
+
const imageElement = this.querySelector(figureElement, "a:blip");
|
|
29400
|
+
if (!chartElement && !imageElement) {
|
|
29401
|
+
throw new Error("Only chart and image figures are currently supported.");
|
|
29284
29402
|
}
|
|
29285
29403
|
return {
|
|
29286
29404
|
anchors: [
|
|
29287
29405
|
this.extractFigureAnchor("xdr:from", figureElement),
|
|
29288
29406
|
this.extractFigureAnchor("xdr:to", figureElement),
|
|
29289
29407
|
],
|
|
29290
|
-
data: this.extractChart(chartElement),
|
|
29408
|
+
data: chartElement ? this.extractChart(chartElement) : this.extractImage(figureElement),
|
|
29291
29409
|
};
|
|
29292
29410
|
});
|
|
29293
29411
|
}
|
|
@@ -29312,6 +29430,24 @@ class XlsxFigureExtractor extends XlsxBaseExtractor {
|
|
|
29312
29430
|
}
|
|
29313
29431
|
return chartDefinition;
|
|
29314
29432
|
}
|
|
29433
|
+
extractImage(figureElement) {
|
|
29434
|
+
const imageElement = this.querySelector(figureElement, "a:blip");
|
|
29435
|
+
const imageId = this.extractAttr(imageElement, "r:embed", { required: true }).asString();
|
|
29436
|
+
const image = this.getTargetImageFile(this.relationships[imageId]);
|
|
29437
|
+
if (!image) {
|
|
29438
|
+
throw new Error("Unable to extract image");
|
|
29439
|
+
}
|
|
29440
|
+
const shapePropertyElement = this.querySelector(figureElement, "a:xfrm");
|
|
29441
|
+
const extension = image.fileName.split(".").at(-1);
|
|
29442
|
+
return {
|
|
29443
|
+
imageSrc: image.imageSrc,
|
|
29444
|
+
mimetype: extension ? IMAGE_EXTENSION_TO_MIMETYPE_MAPPING[extension] : undefined,
|
|
29445
|
+
size: {
|
|
29446
|
+
cx: this.extractChildAttr(shapePropertyElement, "a:ext", "cx", { required: true }).asNum(),
|
|
29447
|
+
cy: this.extractChildAttr(shapePropertyElement, "a:ext", "cy", { required: true }).asNum(),
|
|
29448
|
+
},
|
|
29449
|
+
};
|
|
29450
|
+
}
|
|
29315
29451
|
}
|
|
29316
29452
|
|
|
29317
29453
|
/**
|
|
@@ -29881,14 +30017,22 @@ const EXCEL_IMPORT_VERSION = 12;
|
|
|
29881
30017
|
class XlsxReader {
|
|
29882
30018
|
warningManager;
|
|
29883
30019
|
xmls;
|
|
30020
|
+
images;
|
|
29884
30021
|
constructor(files) {
|
|
29885
30022
|
this.warningManager = new XLSXImportWarningManager();
|
|
29886
30023
|
this.xmls = {};
|
|
30024
|
+
this.images = [];
|
|
29887
30025
|
for (let key of Object.keys(files)) {
|
|
29888
30026
|
// Random files can be in xlsx (like a bin file for printer settings)
|
|
29889
30027
|
if (key.endsWith(".xml") || key.endsWith(".rels")) {
|
|
29890
30028
|
this.xmls[key] = parseXML(new XMLString(files[key]));
|
|
29891
30029
|
}
|
|
30030
|
+
else if (key.includes("media/image")) {
|
|
30031
|
+
this.images.push({
|
|
30032
|
+
fileName: key,
|
|
30033
|
+
imageSrc: files[key]["imageSrc"],
|
|
30034
|
+
});
|
|
30035
|
+
}
|
|
29892
30036
|
}
|
|
29893
30037
|
}
|
|
29894
30038
|
convertXlsx() {
|
|
@@ -29941,6 +30085,7 @@ class XlsxReader {
|
|
|
29941
30085
|
tables: getXLSXFilesOfType(CONTENT_TYPES.table, this.xmls),
|
|
29942
30086
|
pivots: getXLSXFilesOfType(CONTENT_TYPES.pivot, this.xmls),
|
|
29943
30087
|
externalLinks: getXLSXFilesOfType(CONTENT_TYPES.externalLink, this.xmls),
|
|
30088
|
+
images: this.images,
|
|
29944
30089
|
};
|
|
29945
30090
|
if (!xlsxFileStructure.workbook.rels) {
|
|
29946
30091
|
throw Error(_lt("Cannot find workbook relations file"));
|
|
@@ -33091,7 +33236,7 @@ class ImagePlugin extends CorePlugin {
|
|
|
33091
33236
|
handle(cmd) {
|
|
33092
33237
|
switch (cmd.type) {
|
|
33093
33238
|
case "CREATE_IMAGE":
|
|
33094
|
-
this.
|
|
33239
|
+
this.addImage(cmd.figureId, cmd.sheetId, cmd.position, cmd.size);
|
|
33095
33240
|
this.history.update("images", cmd.sheetId, cmd.figureId, cmd.definition);
|
|
33096
33241
|
this.syncedImages.add(cmd.definition.path);
|
|
33097
33242
|
break;
|
|
@@ -33155,7 +33300,7 @@ class ImagePlugin extends CorePlugin {
|
|
|
33155
33300
|
// ---------------------------------------------------------------------------
|
|
33156
33301
|
// Private
|
|
33157
33302
|
// ---------------------------------------------------------------------------
|
|
33158
|
-
|
|
33303
|
+
addImage(id, sheetId, position, size) {
|
|
33159
33304
|
const figure = {
|
|
33160
33305
|
id,
|
|
33161
33306
|
x: position.x,
|
|
@@ -35662,7 +35807,6 @@ class PositionBitsEncoder {
|
|
|
35662
35807
|
}
|
|
35663
35808
|
}
|
|
35664
35809
|
|
|
35665
|
-
const functions = functionRegistry.content;
|
|
35666
35810
|
//#region
|
|
35667
35811
|
// ---------------------------------------------------------------------------
|
|
35668
35812
|
// INTRODUCTION
|
|
@@ -35884,9 +36028,7 @@ class EvaluationPlugin extends UIPlugin {
|
|
|
35884
36028
|
let isExported = true;
|
|
35885
36029
|
const formulaCell = this.getCorrespondingFormulaCell(position);
|
|
35886
36030
|
if (formulaCell) {
|
|
35887
|
-
isExported = formulaCell.compiledFormula.tokens
|
|
35888
|
-
.filter((tk) => tk.type === "FUNCTION")
|
|
35889
|
-
.every((tk) => functions[tk.value.toUpperCase()].isExported);
|
|
36031
|
+
isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
|
|
35890
36032
|
isFormula = isExported;
|
|
35891
36033
|
if (!isExported) {
|
|
35892
36034
|
newContent = value.toString();
|
|
@@ -44292,7 +44434,7 @@ class ImageProvider {
|
|
|
44292
44434
|
async requestImage() {
|
|
44293
44435
|
const file = await this.getImageFromUser();
|
|
44294
44436
|
const path = await this.fileStore.upload(file);
|
|
44295
|
-
const size = await this.
|
|
44437
|
+
const size = await this.getImageOriginalSize(path);
|
|
44296
44438
|
return { path, size, mimetype: file.type };
|
|
44297
44439
|
}
|
|
44298
44440
|
getImageFromUser() {
|
|
@@ -44311,7 +44453,7 @@ class ImageProvider {
|
|
|
44311
44453
|
input.click();
|
|
44312
44454
|
});
|
|
44313
44455
|
}
|
|
44314
|
-
|
|
44456
|
+
getImageOriginalSize(path) {
|
|
44315
44457
|
return new Promise((resolve, reject) => {
|
|
44316
44458
|
const image = new Image();
|
|
44317
44459
|
image.src = path;
|
|
@@ -45796,6 +45938,10 @@ css /* scss */ `
|
|
|
45796
45938
|
top: 20%;
|
|
45797
45939
|
}
|
|
45798
45940
|
}
|
|
45941
|
+
|
|
45942
|
+
.user-select-text {
|
|
45943
|
+
user-select: text;
|
|
45944
|
+
}
|
|
45799
45945
|
`;
|
|
45800
45946
|
class TopBarComposer extends owl.Component {
|
|
45801
45947
|
static template = "o-spreadsheet-TopBarComposer";
|
|
@@ -48834,6 +48980,8 @@ function createImageDrawing(figure, sheet, imageRelId) {
|
|
|
48834
48980
|
["name", `Image ${imageId}`],
|
|
48835
48981
|
["title", "Image"],
|
|
48836
48982
|
];
|
|
48983
|
+
const cx = convertDotValueToEMU(figure.width);
|
|
48984
|
+
const cy = convertDotValueToEMU(figure.height);
|
|
48837
48985
|
return escapeXml /*xml*/ `
|
|
48838
48986
|
<xdr:twoCellAnchor editAs="oneCell">
|
|
48839
48987
|
<xdr:from>
|
|
@@ -48860,6 +49008,9 @@ function createImageDrawing(figure, sheet, imageRelId) {
|
|
|
48860
49008
|
</a:stretch>
|
|
48861
49009
|
</xdr:blipFill>
|
|
48862
49010
|
<xdr:spPr>
|
|
49011
|
+
<a:xfrm>
|
|
49012
|
+
<a:ext cx="${cx}" cy="${cy}" />
|
|
49013
|
+
</a:xfrm>
|
|
48863
49014
|
<a:prstGeom prst="rect">
|
|
48864
49015
|
<a:avLst/>
|
|
48865
49016
|
</a:prstGeom>
|
|
@@ -49379,7 +49530,7 @@ function createWorksheets(data, construct) {
|
|
|
49379
49530
|
const mimeType = image.data.mimetype;
|
|
49380
49531
|
if (mimeType === undefined)
|
|
49381
49532
|
continue;
|
|
49382
|
-
const extension =
|
|
49533
|
+
const extension = IMAGE_MIMETYPE_TO_EXTENSION_MAPPING[mimeType];
|
|
49383
49534
|
// only support exporting images with mimetypes specified in the mapping
|
|
49384
49535
|
if (extension === undefined)
|
|
49385
49536
|
continue;
|
|
@@ -49515,7 +49666,7 @@ function createRelsFiles(relsFiles) {
|
|
|
49515
49666
|
function createContentTypes(files) {
|
|
49516
49667
|
const overrideNodes = [];
|
|
49517
49668
|
// hard-code supported image mimetypes
|
|
49518
|
-
const imageDefaultNodes = Object.entries(
|
|
49669
|
+
const imageDefaultNodes = Object.entries(IMAGE_MIMETYPE_TO_EXTENSION_MAPPING).map(([mimetype, extension]) => createDefaultXMLElement(extension, mimetype));
|
|
49519
49670
|
for (const file of files) {
|
|
49520
49671
|
if ("contentType" in file && file.contentType) {
|
|
49521
49672
|
overrideNodes.push(createOverride("/" + file.path, CONTENT_TYPES[file.contentType]));
|
|
@@ -50145,6 +50296,7 @@ exports.helpers = helpers;
|
|
|
50145
50296
|
exports.invalidateCFEvaluationCommands = invalidateCFEvaluationCommands;
|
|
50146
50297
|
exports.invalidateDependenciesCommands = invalidateDependenciesCommands;
|
|
50147
50298
|
exports.invalidateEvaluationCommands = invalidateEvaluationCommands;
|
|
50299
|
+
exports.iterateAstNodes = iterateAstNodes;
|
|
50148
50300
|
exports.links = links;
|
|
50149
50301
|
exports.load = load;
|
|
50150
50302
|
exports.parse = parse;
|
|
@@ -50155,6 +50307,6 @@ exports.setTranslationMethod = setTranslationMethod;
|
|
|
50155
50307
|
exports.tokenize = tokenize;
|
|
50156
50308
|
|
|
50157
50309
|
|
|
50158
|
-
__info__.version = '16.4.0-alpha.
|
|
50159
|
-
__info__.date = '2023-
|
|
50160
|
-
__info__.hash = '
|
|
50310
|
+
__info__.version = '16.4.0-alpha.7';
|
|
50311
|
+
__info__.date = '2023-07-04T13:46:24.130Z';
|
|
50312
|
+
__info__.hash = 'b04cf78';
|