@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
|
@@ -12593,6 +12593,18 @@
|
|
|
12593
12593
|
isExported: true,
|
|
12594
12594
|
};
|
|
12595
12595
|
// -----------------------------------------------------------------------------
|
|
12596
|
+
// FALSE
|
|
12597
|
+
// -----------------------------------------------------------------------------
|
|
12598
|
+
const FALSE = {
|
|
12599
|
+
description: _lt("Logical value `false`."),
|
|
12600
|
+
args: [],
|
|
12601
|
+
returns: ["BOOLEAN"],
|
|
12602
|
+
compute: function () {
|
|
12603
|
+
return false;
|
|
12604
|
+
},
|
|
12605
|
+
isExported: true,
|
|
12606
|
+
};
|
|
12607
|
+
// -----------------------------------------------------------------------------
|
|
12596
12608
|
// IF
|
|
12597
12609
|
// -----------------------------------------------------------------------------
|
|
12598
12610
|
const IF = {
|
|
@@ -12728,6 +12740,18 @@
|
|
|
12728
12740
|
isExported: true,
|
|
12729
12741
|
};
|
|
12730
12742
|
// -----------------------------------------------------------------------------
|
|
12743
|
+
// TRUE
|
|
12744
|
+
// -----------------------------------------------------------------------------
|
|
12745
|
+
const TRUE = {
|
|
12746
|
+
description: _lt("Logical value `true`."),
|
|
12747
|
+
args: [],
|
|
12748
|
+
returns: ["BOOLEAN"],
|
|
12749
|
+
compute: function () {
|
|
12750
|
+
return true;
|
|
12751
|
+
},
|
|
12752
|
+
isExported: true,
|
|
12753
|
+
};
|
|
12754
|
+
// -----------------------------------------------------------------------------
|
|
12731
12755
|
// XOR
|
|
12732
12756
|
// -----------------------------------------------------------------------------
|
|
12733
12757
|
const XOR = {
|
|
@@ -12754,12 +12778,14 @@
|
|
|
12754
12778
|
var logical = /*#__PURE__*/Object.freeze({
|
|
12755
12779
|
__proto__: null,
|
|
12756
12780
|
AND: AND,
|
|
12781
|
+
FALSE: FALSE,
|
|
12757
12782
|
IF: IF,
|
|
12758
12783
|
IFERROR: IFERROR,
|
|
12759
12784
|
IFNA: IFNA,
|
|
12760
12785
|
IFS: IFS,
|
|
12761
12786
|
NOT: NOT,
|
|
12762
12787
|
OR: OR,
|
|
12788
|
+
TRUE: TRUE,
|
|
12763
12789
|
XOR: XOR
|
|
12764
12790
|
});
|
|
12765
12791
|
|
|
@@ -13946,7 +13972,6 @@
|
|
|
13946
13972
|
* is useful for the composer, which needs to be able to work with incomplete
|
|
13947
13973
|
* formulas.
|
|
13948
13974
|
*/
|
|
13949
|
-
const functions$3 = functionRegistry.content;
|
|
13950
13975
|
const POSTFIX_UNARY_OPERATORS = ["%"];
|
|
13951
13976
|
const OPERATORS = "+,-,*,/,:,=,<>,>=,>,<=,<,^,&".split(",").concat(POSTFIX_UNARY_OPERATORS);
|
|
13952
13977
|
function tokenize(str, locale = DEFAULT_LOCALE) {
|
|
@@ -14077,17 +14102,11 @@
|
|
|
14077
14102
|
}
|
|
14078
14103
|
if (result.length) {
|
|
14079
14104
|
const value = result;
|
|
14080
|
-
const isFunction = value.toUpperCase() in functions$3;
|
|
14081
|
-
if (isFunction) {
|
|
14082
|
-
return { type: "FUNCTION", value };
|
|
14083
|
-
}
|
|
14084
14105
|
const isReference = rangeReference.test(value);
|
|
14085
14106
|
if (isReference) {
|
|
14086
14107
|
return { type: "REFERENCE", value };
|
|
14087
14108
|
}
|
|
14088
|
-
|
|
14089
|
-
return { type: "SYMBOL", value };
|
|
14090
|
-
}
|
|
14109
|
+
return { type: "SYMBOL", value };
|
|
14091
14110
|
}
|
|
14092
14111
|
return null;
|
|
14093
14112
|
}
|
|
@@ -14187,9 +14206,6 @@
|
|
|
14187
14206
|
return { type: "NUMBER", value: parseNumber(current.value, DEFAULT_LOCALE) };
|
|
14188
14207
|
case "STRING":
|
|
14189
14208
|
return { type: "STRING", value: removeStringQuotes(current.value) };
|
|
14190
|
-
case "FUNCTION":
|
|
14191
|
-
const args = parseFunctionArgs(tokens);
|
|
14192
|
-
return { type: "FUNCALL", value: current.value, args };
|
|
14193
14209
|
case "INVALID_REFERENCE":
|
|
14194
14210
|
throw new InvalidReferenceError();
|
|
14195
14211
|
case "REFERENCE":
|
|
@@ -14206,13 +14222,15 @@
|
|
|
14206
14222
|
value: current.value,
|
|
14207
14223
|
};
|
|
14208
14224
|
case "SYMBOL":
|
|
14209
|
-
|
|
14210
|
-
|
|
14225
|
+
const value = current.value;
|
|
14226
|
+
const nextToken = tokens[0];
|
|
14227
|
+
if (nextToken?.type === "LEFT_PAREN" && functionRegex.test(current.value)) {
|
|
14228
|
+
const args = parseFunctionArgs(tokens);
|
|
14229
|
+
return { type: "FUNCALL", value: value, args };
|
|
14211
14230
|
}
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14215
|
-
}
|
|
14231
|
+
const upperCaseValue = value.toUpperCase();
|
|
14232
|
+
if (upperCaseValue === "TRUE" || upperCaseValue === "FALSE") {
|
|
14233
|
+
return { type: "BOOLEAN", value: upperCaseValue === "TRUE" };
|
|
14216
14234
|
}
|
|
14217
14235
|
throw new BadExpressionError(_lt("Invalid formula"));
|
|
14218
14236
|
case "LEFT_PAREN":
|
|
@@ -14314,36 +14332,60 @@
|
|
|
14314
14332
|
* to nodes of a specific type.
|
|
14315
14333
|
* Useful if you want to convert some part of a formula.
|
|
14316
14334
|
*
|
|
14317
|
-
*
|
|
14318
|
-
* ```ts
|
|
14335
|
+
* @example
|
|
14319
14336
|
* convertAstNodes(ast, "FUNCALL", convertFormulaToExcel)
|
|
14320
14337
|
*
|
|
14321
14338
|
* function convertFormulaToExcel(ast: ASTFuncall) {
|
|
14322
14339
|
* // ...
|
|
14323
14340
|
* return modifiedAst
|
|
14324
14341
|
* }
|
|
14325
|
-
* ```
|
|
14326
14342
|
*/
|
|
14327
14343
|
function convertAstNodes(ast, type, fn) {
|
|
14328
|
-
|
|
14329
|
-
ast
|
|
14344
|
+
return mapAst(ast, (ast) => {
|
|
14345
|
+
if (ast.type === type) {
|
|
14346
|
+
return fn(ast);
|
|
14347
|
+
}
|
|
14348
|
+
return ast;
|
|
14349
|
+
});
|
|
14350
|
+
}
|
|
14351
|
+
function iterateAstNodes(ast) {
|
|
14352
|
+
return Array.from(astIterator(ast));
|
|
14353
|
+
}
|
|
14354
|
+
function* astIterator(ast) {
|
|
14355
|
+
yield ast;
|
|
14356
|
+
switch (ast.type) {
|
|
14357
|
+
case "FUNCALL":
|
|
14358
|
+
for (const arg of ast.args) {
|
|
14359
|
+
yield* astIterator(arg);
|
|
14360
|
+
}
|
|
14361
|
+
break;
|
|
14362
|
+
case "UNARY_OPERATION":
|
|
14363
|
+
yield* astIterator(ast.operand);
|
|
14364
|
+
break;
|
|
14365
|
+
case "BIN_OPERATION":
|
|
14366
|
+
yield* astIterator(ast.left);
|
|
14367
|
+
yield* astIterator(ast.right);
|
|
14368
|
+
break;
|
|
14330
14369
|
}
|
|
14370
|
+
}
|
|
14371
|
+
function mapAst(ast, fn) {
|
|
14372
|
+
ast = fn(ast);
|
|
14331
14373
|
switch (ast.type) {
|
|
14332
14374
|
case "FUNCALL":
|
|
14333
14375
|
return {
|
|
14334
14376
|
...ast,
|
|
14335
|
-
args: ast.args.map((child) =>
|
|
14377
|
+
args: ast.args.map((child) => mapAst(child, fn)),
|
|
14336
14378
|
};
|
|
14337
14379
|
case "UNARY_OPERATION":
|
|
14338
14380
|
return {
|
|
14339
14381
|
...ast,
|
|
14340
|
-
operand:
|
|
14382
|
+
operand: mapAst(ast.operand, fn),
|
|
14341
14383
|
};
|
|
14342
14384
|
case "BIN_OPERATION":
|
|
14343
14385
|
return {
|
|
14344
14386
|
...ast,
|
|
14345
|
-
right:
|
|
14346
|
-
left:
|
|
14387
|
+
right: mapAst(ast.right, fn),
|
|
14388
|
+
left: mapAst(ast.left, fn),
|
|
14347
14389
|
};
|
|
14348
14390
|
default:
|
|
14349
14391
|
return ast;
|
|
@@ -14613,6 +14655,9 @@
|
|
|
14613
14655
|
const { args } = ast;
|
|
14614
14656
|
const functionName = ast.value.toUpperCase();
|
|
14615
14657
|
const functionDefinition = functions$2[functionName];
|
|
14658
|
+
if (!functionDefinition) {
|
|
14659
|
+
throw new UnknownFunctionError(ast.value);
|
|
14660
|
+
}
|
|
14616
14661
|
assertEnoughArgs(ast);
|
|
14617
14662
|
const compiledArgs = [];
|
|
14618
14663
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -14871,7 +14916,7 @@
|
|
|
14871
14916
|
functionStarted = "";
|
|
14872
14917
|
}
|
|
14873
14918
|
switch (token.type) {
|
|
14874
|
-
case "
|
|
14919
|
+
case "SYMBOL":
|
|
14875
14920
|
functionStarted = token.value;
|
|
14876
14921
|
break;
|
|
14877
14922
|
case "LEFT_PAREN":
|
|
@@ -14908,6 +14953,17 @@
|
|
|
14908
14953
|
return mapParentFunction(mapParenthesis(enrichTokens(tokens)));
|
|
14909
14954
|
}
|
|
14910
14955
|
|
|
14956
|
+
const functions$1 = functionRegistry.content;
|
|
14957
|
+
function isExportableToExcel(tokens) {
|
|
14958
|
+
try {
|
|
14959
|
+
const nonExportableFunctions = iterateAstNodes(parseTokens(tokens)).filter((ast) => ast.type === "FUNCALL" && !functions$1[ast.value.toUpperCase()]?.isExported);
|
|
14960
|
+
return nonExportableFunctions.length === 0;
|
|
14961
|
+
}
|
|
14962
|
+
catch (error) {
|
|
14963
|
+
return false;
|
|
14964
|
+
}
|
|
14965
|
+
}
|
|
14966
|
+
|
|
14911
14967
|
function isValidLocale(locale) {
|
|
14912
14968
|
if (!(locale &&
|
|
14913
14969
|
typeof locale === "object" &&
|
|
@@ -17480,8 +17536,14 @@
|
|
|
17480
17536
|
id: "reset_size",
|
|
17481
17537
|
name: _lt("Reset size"),
|
|
17482
17538
|
sequence: 4,
|
|
17483
|
-
execute: () => {
|
|
17484
|
-
const
|
|
17539
|
+
execute: async () => {
|
|
17540
|
+
const imagePath = env.model.getters.getImagePath(figureId);
|
|
17541
|
+
const size = env.model.getters.getImageSize(figureId) ??
|
|
17542
|
+
(await env.imageProvider?.getImageOriginalSize(imagePath));
|
|
17543
|
+
if (!env.model.getters.getImageSize(figureId)) {
|
|
17544
|
+
const image = env.model.getters.getImage(figureId);
|
|
17545
|
+
image.size = size;
|
|
17546
|
+
}
|
|
17485
17547
|
const { height, width } = getMaxFigureSize(env.model.getters, size);
|
|
17486
17548
|
env.model.dispatch("UPDATE_FIGURE", {
|
|
17487
17549
|
sheetId: env.model.getters.getActiveSheetId(),
|
|
@@ -23534,7 +23596,7 @@
|
|
|
23534
23596
|
argToFocus: Number,
|
|
23535
23597
|
};
|
|
23536
23598
|
|
|
23537
|
-
const functions
|
|
23599
|
+
const functions = functionRegistry.content;
|
|
23538
23600
|
const ASSISTANT_WIDTH = 300;
|
|
23539
23601
|
const selectionIndicatorClass = "selector-flag";
|
|
23540
23602
|
const selectionIndicatorColor = "#a9a9a9";
|
|
@@ -23568,10 +23630,6 @@
|
|
|
23568
23630
|
padding-right: 3px;
|
|
23569
23631
|
outline: none;
|
|
23570
23632
|
|
|
23571
|
-
&.unfocusable {
|
|
23572
|
-
pointer-events: none;
|
|
23573
|
-
}
|
|
23574
|
-
|
|
23575
23633
|
p {
|
|
23576
23634
|
margin-bottom: 0px;
|
|
23577
23635
|
|
|
@@ -23819,7 +23877,10 @@
|
|
|
23819
23877
|
}
|
|
23820
23878
|
}
|
|
23821
23879
|
showAutocomplete(searchTerm) {
|
|
23822
|
-
|
|
23880
|
+
const searchTermUpperCase = searchTerm.toUpperCase();
|
|
23881
|
+
if (!this.env.model.getters.getCurrentContent().startsWith("=") ||
|
|
23882
|
+
searchTermUpperCase === "TRUE" ||
|
|
23883
|
+
searchTermUpperCase === "FALSE") {
|
|
23823
23884
|
return;
|
|
23824
23885
|
}
|
|
23825
23886
|
this.autoCompleteState.showProvider = true;
|
|
@@ -23937,7 +23998,6 @@
|
|
|
23937
23998
|
switch (token.type) {
|
|
23938
23999
|
case "OPERATOR":
|
|
23939
24000
|
case "NUMBER":
|
|
23940
|
-
case "FUNCTION":
|
|
23941
24001
|
case "ARG_SEPARATOR":
|
|
23942
24002
|
case "STRING":
|
|
23943
24003
|
result.push({ value: token.value, color: tokenColors[token.type] || "#000" });
|
|
@@ -23947,10 +24007,14 @@
|
|
|
23947
24007
|
result.push({ value: token.value, color: this.rangeColor(xc, sheetName) || "#000" });
|
|
23948
24008
|
break;
|
|
23949
24009
|
case "SYMBOL":
|
|
23950
|
-
|
|
23951
|
-
|
|
24010
|
+
const value = token.value;
|
|
24011
|
+
const upperCaseValue = value.toUpperCase();
|
|
24012
|
+
if (upperCaseValue === "TRUE" || upperCaseValue === "FALSE") {
|
|
23952
24013
|
result.push({ value: token.value, color: tokenColors.NUMBER });
|
|
23953
24014
|
}
|
|
24015
|
+
else if (upperCaseValue in functionRegistry.content) {
|
|
24016
|
+
result.push({ value: token.value, color: tokenColors.FUNCTION });
|
|
24017
|
+
}
|
|
23954
24018
|
else {
|
|
23955
24019
|
result.push({ value: token.value, color: "#000" });
|
|
23956
24020
|
}
|
|
@@ -24046,25 +24110,28 @@
|
|
|
24046
24110
|
this.autoCompleteState.showProvider = false;
|
|
24047
24111
|
this.functionDescriptionState.showDescription = false;
|
|
24048
24112
|
if (content.startsWith("=")) {
|
|
24049
|
-
const
|
|
24050
|
-
if (
|
|
24051
|
-
|
|
24052
|
-
|
|
24053
|
-
|
|
24054
|
-
|
|
24055
|
-
|
|
24056
|
-
|
|
24057
|
-
|
|
24058
|
-
|
|
24059
|
-
|
|
24060
|
-
|
|
24061
|
-
|
|
24062
|
-
|
|
24063
|
-
|
|
24064
|
-
|
|
24065
|
-
|
|
24066
|
-
|
|
24067
|
-
|
|
24113
|
+
const token = this.env.model.getters.getTokenAtCursor();
|
|
24114
|
+
if (!token) {
|
|
24115
|
+
return;
|
|
24116
|
+
}
|
|
24117
|
+
if (token.type === "SYMBOL") {
|
|
24118
|
+
// initialize Autocomplete Dropdown
|
|
24119
|
+
this.showAutocomplete(token.value);
|
|
24120
|
+
return;
|
|
24121
|
+
}
|
|
24122
|
+
const tokenContext = token.functionContext;
|
|
24123
|
+
const parentFunction = tokenContext?.parent.toUpperCase();
|
|
24124
|
+
if (tokenContext &&
|
|
24125
|
+
parentFunction &&
|
|
24126
|
+
parentFunction in functions &&
|
|
24127
|
+
token.type !== "UNKNOWN") {
|
|
24128
|
+
// initialize Formula Assistant
|
|
24129
|
+
const description = functions[parentFunction];
|
|
24130
|
+
const argPosition = tokenContext.argPosition;
|
|
24131
|
+
this.functionDescriptionState.functionName = parentFunction;
|
|
24132
|
+
this.functionDescriptionState.functionDescription = description;
|
|
24133
|
+
this.functionDescriptionState.argToFocus = description.getArgToFocus(argPosition + 1) - 1;
|
|
24134
|
+
this.functionDescriptionState.showDescription = true;
|
|
24068
24135
|
}
|
|
24069
24136
|
}
|
|
24070
24137
|
}
|
|
@@ -26764,7 +26831,12 @@
|
|
|
26764
26831
|
};
|
|
26765
26832
|
const RELATIONSHIP_NSR = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
26766
26833
|
const HEIGHT_FACTOR = 0.75; // 100px => 75 u
|
|
26767
|
-
|
|
26834
|
+
/**
|
|
26835
|
+
* Excel says its default column width is 8.43 characters (64px)
|
|
26836
|
+
* which makes WIDTH_FACTOR = 0.1317, but it doesn't work well
|
|
26837
|
+
* 0.143 is a value from dev's experiments.
|
|
26838
|
+
*/
|
|
26839
|
+
const WIDTH_FACTOR = 0.143;
|
|
26768
26840
|
/** unit : maximum number of characters a column can hold at the standard font size. What. */
|
|
26769
26841
|
const EXCEL_DEFAULT_COL_WIDTH = 8.43;
|
|
26770
26842
|
/** unit : points */
|
|
@@ -27281,7 +27353,7 @@
|
|
|
27281
27353
|
64: "000000",
|
|
27282
27354
|
65: "FFFFFF", // system background
|
|
27283
27355
|
};
|
|
27284
|
-
const
|
|
27356
|
+
const IMAGE_MIMETYPE_TO_EXTENSION_MAPPING = {
|
|
27285
27357
|
"image/avif": "avif",
|
|
27286
27358
|
"image/bmp": "bmp",
|
|
27287
27359
|
"image/gif": "gif",
|
|
@@ -27290,6 +27362,17 @@
|
|
|
27290
27362
|
"image/png": "png",
|
|
27291
27363
|
"image/tiff": "tiff",
|
|
27292
27364
|
"image/webp": "webp",
|
|
27365
|
+
};
|
|
27366
|
+
const IMAGE_EXTENSION_TO_MIMETYPE_MAPPING = {
|
|
27367
|
+
avif: "image/avif",
|
|
27368
|
+
bmp: "image/bmp",
|
|
27369
|
+
gif: "image/gif",
|
|
27370
|
+
ico: "image/vnd.microsoft.icon",
|
|
27371
|
+
jpeg: "image/jpeg",
|
|
27372
|
+
png: "image/png",
|
|
27373
|
+
tiff: "image/tiff",
|
|
27374
|
+
webp: "image/webp",
|
|
27375
|
+
jpg: "image/jpeg",
|
|
27293
27376
|
};
|
|
27294
27377
|
|
|
27295
27378
|
/**
|
|
@@ -28093,20 +28176,35 @@
|
|
|
28093
28176
|
convertEMUToDotValue(figure.anchors[0].rowOffset);
|
|
28094
28177
|
const y2 = getRowPosition(figure.anchors[1].row, sheetData) +
|
|
28095
28178
|
convertEMUToDotValue(figure.anchors[1].rowOffset);
|
|
28096
|
-
const
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
28100
|
-
|
|
28101
|
-
|
|
28102
|
-
|
|
28103
|
-
|
|
28104
|
-
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
|
|
28108
|
-
|
|
28109
|
-
|
|
28179
|
+
const figureData = { id, x: x1, y: y1 };
|
|
28180
|
+
if (isChartData(figure.data)) {
|
|
28181
|
+
return {
|
|
28182
|
+
...figureData,
|
|
28183
|
+
width: x2 - x1,
|
|
28184
|
+
height: y2 - y1,
|
|
28185
|
+
tag: "chart",
|
|
28186
|
+
data: convertChartData(figure.data),
|
|
28187
|
+
};
|
|
28188
|
+
}
|
|
28189
|
+
else if (isImageData(figure.data)) {
|
|
28190
|
+
return {
|
|
28191
|
+
...figureData,
|
|
28192
|
+
width: convertEMUToDotValue(figure.data.size.cx),
|
|
28193
|
+
height: convertEMUToDotValue(figure.data.size.cy),
|
|
28194
|
+
tag: "image",
|
|
28195
|
+
data: {
|
|
28196
|
+
path: figure.data.imageSrc,
|
|
28197
|
+
mimetype: figure.data.mimetype,
|
|
28198
|
+
},
|
|
28199
|
+
};
|
|
28200
|
+
}
|
|
28201
|
+
return undefined;
|
|
28202
|
+
}
|
|
28203
|
+
function isChartData(data) {
|
|
28204
|
+
return "dataSets" in data;
|
|
28205
|
+
}
|
|
28206
|
+
function isImageData(data) {
|
|
28207
|
+
return "imageSrc" in data;
|
|
28110
28208
|
}
|
|
28111
28209
|
function convertChartData(chartData) {
|
|
28112
28210
|
const dataSetsHaveTitle = chartData.dataSets[0].label !== undefined;
|
|
@@ -28813,9 +28911,13 @@
|
|
|
28813
28911
|
/**
|
|
28814
28912
|
* Get the list of all the XLSX files in the XLSX file structure
|
|
28815
28913
|
*/
|
|
28816
|
-
|
|
28817
|
-
const
|
|
28818
|
-
|
|
28914
|
+
getListOfXMLFiles() {
|
|
28915
|
+
const XMLFiles = Object.entries(this.xlsxFileStructure)
|
|
28916
|
+
.filter(([key]) => key !== "images")
|
|
28917
|
+
.map(([_, value]) => value)
|
|
28918
|
+
.flat()
|
|
28919
|
+
.filter(isDefined$1);
|
|
28920
|
+
return XMLFiles;
|
|
28819
28921
|
}
|
|
28820
28922
|
/**
|
|
28821
28923
|
* Return an array containing the return value of the given function applied to all the XML elements
|
|
@@ -28987,20 +29089,31 @@
|
|
|
28987
29089
|
return color;
|
|
28988
29090
|
}
|
|
28989
29091
|
/**
|
|
28990
|
-
* Returns the
|
|
29092
|
+
* Returns the xml file targeted by a relationship.
|
|
28991
29093
|
*/
|
|
28992
29094
|
getTargetXmlFile(relationship) {
|
|
28993
29095
|
if (!relationship)
|
|
28994
29096
|
throw new Error("Undefined target file");
|
|
28995
|
-
|
|
28996
|
-
target = target.replace("../", "");
|
|
28997
|
-
target = target.replace("./", "");
|
|
29097
|
+
const target = this.processRelationshipTargetName(relationship.target);
|
|
28998
29098
|
// Use "endsWith" because targets are relative paths, and we know the files by their absolute path.
|
|
28999
|
-
const f = this.
|
|
29099
|
+
const f = this.getListOfXMLFiles().find((f) => f.file.fileName.endsWith(target));
|
|
29000
29100
|
if (!f || !f.file)
|
|
29001
29101
|
throw new Error("Cannot find target file");
|
|
29002
29102
|
return f;
|
|
29003
29103
|
}
|
|
29104
|
+
/**
|
|
29105
|
+
* Returns the image parameters targeted by a relationship.
|
|
29106
|
+
*/
|
|
29107
|
+
getTargetImageFile(relationship) {
|
|
29108
|
+
if (!relationship)
|
|
29109
|
+
throw new Error("Undefined target file");
|
|
29110
|
+
const target = this.processRelationshipTargetName(relationship.target);
|
|
29111
|
+
// Use "endsWith" because targets are relative paths, and we know the files by their absolute path.
|
|
29112
|
+
const f = this.xlsxFileStructure.images.find((f) => f.fileName.endsWith(target));
|
|
29113
|
+
if (!f)
|
|
29114
|
+
throw new Error("Cannot find target file");
|
|
29115
|
+
return f;
|
|
29116
|
+
}
|
|
29004
29117
|
/**
|
|
29005
29118
|
* Wrapper of querySelector, but we'll remove the namespaces from the query if areNamespacesIgnored is true.
|
|
29006
29119
|
*
|
|
@@ -29047,6 +29160,10 @@
|
|
|
29047
29160
|
return clrScheme[colorId].value;
|
|
29048
29161
|
}
|
|
29049
29162
|
}
|
|
29163
|
+
/** Remove signs of relative path. */
|
|
29164
|
+
processRelationshipTargetName(targetName) {
|
|
29165
|
+
return targetName.replace(/\.+\//, "");
|
|
29166
|
+
}
|
|
29050
29167
|
}
|
|
29051
29168
|
|
|
29052
29169
|
/**
|
|
@@ -29276,15 +29393,16 @@
|
|
|
29276
29393
|
throw new Error("Only twoCellAnchor are supported for xlsx drawings.");
|
|
29277
29394
|
}
|
|
29278
29395
|
const chartElement = this.querySelector(figureElement, "c:chart");
|
|
29279
|
-
|
|
29280
|
-
|
|
29396
|
+
const imageElement = this.querySelector(figureElement, "a:blip");
|
|
29397
|
+
if (!chartElement && !imageElement) {
|
|
29398
|
+
throw new Error("Only chart and image figures are currently supported.");
|
|
29281
29399
|
}
|
|
29282
29400
|
return {
|
|
29283
29401
|
anchors: [
|
|
29284
29402
|
this.extractFigureAnchor("xdr:from", figureElement),
|
|
29285
29403
|
this.extractFigureAnchor("xdr:to", figureElement),
|
|
29286
29404
|
],
|
|
29287
|
-
data: this.extractChart(chartElement),
|
|
29405
|
+
data: chartElement ? this.extractChart(chartElement) : this.extractImage(figureElement),
|
|
29288
29406
|
};
|
|
29289
29407
|
});
|
|
29290
29408
|
}
|
|
@@ -29309,6 +29427,24 @@
|
|
|
29309
29427
|
}
|
|
29310
29428
|
return chartDefinition;
|
|
29311
29429
|
}
|
|
29430
|
+
extractImage(figureElement) {
|
|
29431
|
+
const imageElement = this.querySelector(figureElement, "a:blip");
|
|
29432
|
+
const imageId = this.extractAttr(imageElement, "r:embed", { required: true }).asString();
|
|
29433
|
+
const image = this.getTargetImageFile(this.relationships[imageId]);
|
|
29434
|
+
if (!image) {
|
|
29435
|
+
throw new Error("Unable to extract image");
|
|
29436
|
+
}
|
|
29437
|
+
const shapePropertyElement = this.querySelector(figureElement, "a:xfrm");
|
|
29438
|
+
const extension = image.fileName.split(".").at(-1);
|
|
29439
|
+
return {
|
|
29440
|
+
imageSrc: image.imageSrc,
|
|
29441
|
+
mimetype: extension ? IMAGE_EXTENSION_TO_MIMETYPE_MAPPING[extension] : undefined,
|
|
29442
|
+
size: {
|
|
29443
|
+
cx: this.extractChildAttr(shapePropertyElement, "a:ext", "cx", { required: true }).asNum(),
|
|
29444
|
+
cy: this.extractChildAttr(shapePropertyElement, "a:ext", "cy", { required: true }).asNum(),
|
|
29445
|
+
},
|
|
29446
|
+
};
|
|
29447
|
+
}
|
|
29312
29448
|
}
|
|
29313
29449
|
|
|
29314
29450
|
/**
|
|
@@ -29878,14 +30014,22 @@
|
|
|
29878
30014
|
class XlsxReader {
|
|
29879
30015
|
warningManager;
|
|
29880
30016
|
xmls;
|
|
30017
|
+
images;
|
|
29881
30018
|
constructor(files) {
|
|
29882
30019
|
this.warningManager = new XLSXImportWarningManager();
|
|
29883
30020
|
this.xmls = {};
|
|
30021
|
+
this.images = [];
|
|
29884
30022
|
for (let key of Object.keys(files)) {
|
|
29885
30023
|
// Random files can be in xlsx (like a bin file for printer settings)
|
|
29886
30024
|
if (key.endsWith(".xml") || key.endsWith(".rels")) {
|
|
29887
30025
|
this.xmls[key] = parseXML(new XMLString(files[key]));
|
|
29888
30026
|
}
|
|
30027
|
+
else if (key.includes("media/image")) {
|
|
30028
|
+
this.images.push({
|
|
30029
|
+
fileName: key,
|
|
30030
|
+
imageSrc: files[key]["imageSrc"],
|
|
30031
|
+
});
|
|
30032
|
+
}
|
|
29889
30033
|
}
|
|
29890
30034
|
}
|
|
29891
30035
|
convertXlsx() {
|
|
@@ -29938,6 +30082,7 @@
|
|
|
29938
30082
|
tables: getXLSXFilesOfType(CONTENT_TYPES.table, this.xmls),
|
|
29939
30083
|
pivots: getXLSXFilesOfType(CONTENT_TYPES.pivot, this.xmls),
|
|
29940
30084
|
externalLinks: getXLSXFilesOfType(CONTENT_TYPES.externalLink, this.xmls),
|
|
30085
|
+
images: this.images,
|
|
29941
30086
|
};
|
|
29942
30087
|
if (!xlsxFileStructure.workbook.rels) {
|
|
29943
30088
|
throw Error(_lt("Cannot find workbook relations file"));
|
|
@@ -33088,7 +33233,7 @@
|
|
|
33088
33233
|
handle(cmd) {
|
|
33089
33234
|
switch (cmd.type) {
|
|
33090
33235
|
case "CREATE_IMAGE":
|
|
33091
|
-
this.
|
|
33236
|
+
this.addImage(cmd.figureId, cmd.sheetId, cmd.position, cmd.size);
|
|
33092
33237
|
this.history.update("images", cmd.sheetId, cmd.figureId, cmd.definition);
|
|
33093
33238
|
this.syncedImages.add(cmd.definition.path);
|
|
33094
33239
|
break;
|
|
@@ -33152,7 +33297,7 @@
|
|
|
33152
33297
|
// ---------------------------------------------------------------------------
|
|
33153
33298
|
// Private
|
|
33154
33299
|
// ---------------------------------------------------------------------------
|
|
33155
|
-
|
|
33300
|
+
addImage(id, sheetId, position, size) {
|
|
33156
33301
|
const figure = {
|
|
33157
33302
|
id,
|
|
33158
33303
|
x: position.x,
|
|
@@ -35659,7 +35804,6 @@
|
|
|
35659
35804
|
}
|
|
35660
35805
|
}
|
|
35661
35806
|
|
|
35662
|
-
const functions = functionRegistry.content;
|
|
35663
35807
|
//#region
|
|
35664
35808
|
// ---------------------------------------------------------------------------
|
|
35665
35809
|
// INTRODUCTION
|
|
@@ -35881,9 +36025,7 @@
|
|
|
35881
36025
|
let isExported = true;
|
|
35882
36026
|
const formulaCell = this.getCorrespondingFormulaCell(position);
|
|
35883
36027
|
if (formulaCell) {
|
|
35884
|
-
isExported = formulaCell.compiledFormula.tokens
|
|
35885
|
-
.filter((tk) => tk.type === "FUNCTION")
|
|
35886
|
-
.every((tk) => functions[tk.value.toUpperCase()].isExported);
|
|
36028
|
+
isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
|
|
35887
36029
|
isFormula = isExported;
|
|
35888
36030
|
if (!isExported) {
|
|
35889
36031
|
newContent = value.toString();
|
|
@@ -44289,7 +44431,7 @@
|
|
|
44289
44431
|
async requestImage() {
|
|
44290
44432
|
const file = await this.getImageFromUser();
|
|
44291
44433
|
const path = await this.fileStore.upload(file);
|
|
44292
|
-
const size = await this.
|
|
44434
|
+
const size = await this.getImageOriginalSize(path);
|
|
44293
44435
|
return { path, size, mimetype: file.type };
|
|
44294
44436
|
}
|
|
44295
44437
|
getImageFromUser() {
|
|
@@ -44308,7 +44450,7 @@
|
|
|
44308
44450
|
input.click();
|
|
44309
44451
|
});
|
|
44310
44452
|
}
|
|
44311
|
-
|
|
44453
|
+
getImageOriginalSize(path) {
|
|
44312
44454
|
return new Promise((resolve, reject) => {
|
|
44313
44455
|
const image = new Image();
|
|
44314
44456
|
image.src = path;
|
|
@@ -45793,6 +45935,10 @@
|
|
|
45793
45935
|
top: 20%;
|
|
45794
45936
|
}
|
|
45795
45937
|
}
|
|
45938
|
+
|
|
45939
|
+
.user-select-text {
|
|
45940
|
+
user-select: text;
|
|
45941
|
+
}
|
|
45796
45942
|
`;
|
|
45797
45943
|
class TopBarComposer extends owl.Component {
|
|
45798
45944
|
static template = "o-spreadsheet-TopBarComposer";
|
|
@@ -48831,6 +48977,8 @@
|
|
|
48831
48977
|
["name", `Image ${imageId}`],
|
|
48832
48978
|
["title", "Image"],
|
|
48833
48979
|
];
|
|
48980
|
+
const cx = convertDotValueToEMU(figure.width);
|
|
48981
|
+
const cy = convertDotValueToEMU(figure.height);
|
|
48834
48982
|
return escapeXml /*xml*/ `
|
|
48835
48983
|
<xdr:twoCellAnchor editAs="oneCell">
|
|
48836
48984
|
<xdr:from>
|
|
@@ -48857,6 +49005,9 @@
|
|
|
48857
49005
|
</a:stretch>
|
|
48858
49006
|
</xdr:blipFill>
|
|
48859
49007
|
<xdr:spPr>
|
|
49008
|
+
<a:xfrm>
|
|
49009
|
+
<a:ext cx="${cx}" cy="${cy}" />
|
|
49010
|
+
</a:xfrm>
|
|
48860
49011
|
<a:prstGeom prst="rect">
|
|
48861
49012
|
<a:avLst/>
|
|
48862
49013
|
</a:prstGeom>
|
|
@@ -49376,7 +49527,7 @@
|
|
|
49376
49527
|
const mimeType = image.data.mimetype;
|
|
49377
49528
|
if (mimeType === undefined)
|
|
49378
49529
|
continue;
|
|
49379
|
-
const extension =
|
|
49530
|
+
const extension = IMAGE_MIMETYPE_TO_EXTENSION_MAPPING[mimeType];
|
|
49380
49531
|
// only support exporting images with mimetypes specified in the mapping
|
|
49381
49532
|
if (extension === undefined)
|
|
49382
49533
|
continue;
|
|
@@ -49512,7 +49663,7 @@
|
|
|
49512
49663
|
function createContentTypes(files) {
|
|
49513
49664
|
const overrideNodes = [];
|
|
49514
49665
|
// hard-code supported image mimetypes
|
|
49515
|
-
const imageDefaultNodes = Object.entries(
|
|
49666
|
+
const imageDefaultNodes = Object.entries(IMAGE_MIMETYPE_TO_EXTENSION_MAPPING).map(([mimetype, extension]) => createDefaultXMLElement(extension, mimetype));
|
|
49516
49667
|
for (const file of files) {
|
|
49517
49668
|
if ("contentType" in file && file.contentType) {
|
|
49518
49669
|
overrideNodes.push(createOverride("/" + file.path, CONTENT_TYPES[file.contentType]));
|
|
@@ -50142,6 +50293,7 @@
|
|
|
50142
50293
|
exports.invalidateCFEvaluationCommands = invalidateCFEvaluationCommands;
|
|
50143
50294
|
exports.invalidateDependenciesCommands = invalidateDependenciesCommands;
|
|
50144
50295
|
exports.invalidateEvaluationCommands = invalidateEvaluationCommands;
|
|
50296
|
+
exports.iterateAstNodes = iterateAstNodes;
|
|
50145
50297
|
exports.links = links;
|
|
50146
50298
|
exports.load = load;
|
|
50147
50299
|
exports.parse = parse;
|
|
@@ -50154,9 +50306,9 @@
|
|
|
50154
50306
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
50155
50307
|
|
|
50156
50308
|
|
|
50157
|
-
__info__.version = '16.4.0-alpha.
|
|
50158
|
-
__info__.date = '2023-
|
|
50159
|
-
__info__.hash = '
|
|
50309
|
+
__info__.version = '16.4.0-alpha.7';
|
|
50310
|
+
__info__.date = '2023-07-04T13:46:24.130Z';
|
|
50311
|
+
__info__.hash = 'b04cf78';
|
|
50160
50312
|
|
|
50161
50313
|
|
|
50162
50314
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|