ooxml-core 1.17.0 → 1.18.0
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/{PptxHandler-U6EFO73T.cjs → PptxHandler-4AHDZDA5.cjs} +2 -2
- package/dist/{PptxHandler-L3JPWOBN.mjs → PptxHandler-5X4VOWAO.mjs} +1 -1
- package/dist/{PptxHandler-K7GMS2ST.mjs → PptxHandler-X6AO6LKJ.mjs} +2 -2
- package/dist/{PresentationBuilder-OK526SZ4.mjs → PresentationBuilder-LRX55PXA.mjs} +2 -2
- package/dist/{PresentationBuilder-LUR6LGHU.cjs → PresentationBuilder-MJB4LIFS.cjs} +4 -4
- package/dist/{PresentationBuilder-XC3F3OPY.mjs → PresentationBuilder-UY3S4YE2.mjs} +1 -1
- package/dist/automation/index.cjs +4710 -3016
- package/dist/automation/index.mjs +4710 -3016
- package/dist/chart/data-label-text.d.ts +70 -0
- package/dist/chart/data-label-text.d.ts.map +1 -0
- package/dist/chart/formatting-nodes.d.ts +6 -0
- package/dist/chart/formatting-nodes.d.ts.map +1 -1
- package/dist/chart/index.cjs +690 -375
- package/dist/chart/index.d.ts +1 -0
- package/dist/chart/index.d.ts.map +1 -1
- package/dist/chart/index.mjs +687 -376
- package/dist/chart/read-formatting.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-bars.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-cartesian.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-labels.d.ts +42 -0
- package/dist/chart/render/chart-svg-labels.d.ts.map +1 -0
- package/dist/chart/render/chart-svg-radial.d.ts.map +1 -1
- package/dist/chart/render/chart-svg-xy.d.ts.map +1 -1
- package/dist/chart/render/chart-view-labels.d.ts +16 -0
- package/dist/chart/render/chart-view-labels.d.ts.map +1 -0
- package/dist/chart/render/chart-view.d.ts +3 -0
- package/dist/chart/render/chart-view.d.ts.map +1 -1
- package/dist/chart/render/summary-from-space.d.ts +2 -2
- package/dist/chart/render/summary-from-space.d.ts.map +1 -1
- package/dist/chart/render/summary-labels.d.ts +9 -0
- package/dist/chart/render/summary-labels.d.ts.map +1 -0
- package/dist/chart/render/summary.d.ts +23 -0
- package/dist/chart/render/summary.d.ts.map +1 -1
- package/dist/{chunk-IM5LFEA2.mjs → chunk-7NWQUCGX.mjs} +1 -1
- package/dist/{chunk-UFGJNXRG.mjs → chunk-I5ZE3VLI.mjs} +1 -1
- package/dist/{chunk-A7S2NYAU.mjs → chunk-LT7RCEHY.mjs} +1 -1
- package/dist/{chunk-HLZIALC5.mjs → chunk-U7IDT6VT.mjs} +1 -1
- package/dist/{chunk-YS43OMM3.mjs → chunk-Z5Y53IZD.mjs} +4 -4
- package/dist/docx/embedded.cjs +15 -0
- package/dist/docx/embedded.mjs +15 -0
- package/dist/docx/index.cjs +1261 -656
- package/dist/docx/index.mjs +1261 -656
- package/dist/docx/layout/index.cjs +1129 -539
- package/dist/docx/layout/index.mjs +1129 -539
- package/dist/docx/load/index.cjs +15 -0
- package/dist/docx/load/index.mjs +15 -0
- package/dist/docx/ui/index.cjs +1119 -529
- package/dist/docx/ui/index.mjs +1119 -529
- package/dist/index.cjs +757 -442
- package/dist/index.mjs +757 -442
- package/dist/pptx/automation/index.cjs +7 -0
- package/dist/pptx/automation/index.mjs +5 -5
- package/dist/pptx/cli/index.cjs +7 -0
- package/dist/pptx/cli/index.mjs +4 -4
- package/dist/pptx/converter/index.mjs +2 -2
- package/dist/pptx/editor/render/slide-operations.cjs +1 -1
- package/dist/pptx/editor/render/slide-operations.mjs +1 -1
- package/dist/pptx/index.cjs +7 -0
- package/dist/pptx/index.mjs +5 -5
- package/dist/teams/index.cjs +145 -49
- package/dist/teams/index.mjs +145 -49
- package/dist/visio/edit-chart-object-commands.d.ts +36 -0
- package/dist/visio/edit-chart-object-commands.d.ts.map +1 -0
- package/dist/visio/edit-chart-object.d.ts +7 -0
- package/dist/visio/edit-chart-object.d.ts.map +1 -0
- package/dist/visio/edit-commands.d.ts +2 -1
- package/dist/visio/edit-commands.d.ts.map +1 -1
- package/dist/visio/edit-foreign-frame.d.ts +8 -0
- package/dist/visio/edit-foreign-frame.d.ts.map +1 -0
- package/dist/visio/edit-metadata-commands.d.ts +7 -0
- package/dist/visio/edit-metadata-commands.d.ts.map +1 -1
- package/dist/visio/edit-picture.d.ts +8 -0
- package/dist/visio/edit-picture.d.ts.map +1 -1
- package/dist/visio/edit.d.ts.map +1 -1
- package/dist/visio/emf-bitmap.d.ts +8 -0
- package/dist/visio/emf-bitmap.d.ts.map +1 -0
- package/dist/visio/index.cjs +17093 -6136
- package/dist/visio/index.d.ts +2 -0
- package/dist/visio/index.d.ts.map +1 -1
- package/dist/visio/index.mjs +17091 -6137
- package/dist/visio/model.d.ts +18 -0
- package/dist/visio/model.d.ts.map +1 -1
- package/dist/visio/prepare-embedded.d.ts +10 -0
- package/dist/visio/prepare-embedded.d.ts.map +1 -0
- package/dist/visio/prepare-images.d.ts.map +1 -1
- package/dist/visio/shapes.d.ts.map +1 -1
- package/dist/visio/sheet.d.ts +2 -1
- package/dist/visio/sheet.d.ts.map +1 -1
- package/dist/visio/ui/edit-commands.d.ts.map +1 -1
- package/dist/visio/ui/index.cjs +33320 -22884
- package/dist/visio/ui/index.mjs +33318 -22884
- package/dist/visio/ui/insert.d.ts +11 -0
- package/dist/visio/ui/insert.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +1175 -564
- package/dist/xlsx/index.mjs +1175 -564
- package/dist/xlsx/load/index.cjs +136 -50
- package/dist/xlsx/load/index.mjs +136 -50
- package/dist/xlsx/model.d.ts +5 -0
- package/dist/xlsx/model.d.ts.map +1 -1
- package/dist/xlsx/read/load.d.ts.map +1 -1
- package/dist/xlsx/read/workbook-part.d.ts +2 -0
- package/dist/xlsx/read/workbook-part.d.ts.map +1 -1
- package/dist/xlsx/ui/dialogs/grid-chart.d.ts +22 -1
- package/dist/xlsx/ui/dialogs/grid-chart.d.ts.map +1 -1
- package/dist/xlsx/ui/index.cjs +16820 -4239
- package/dist/xlsx/ui/index.mjs +16810 -4237
- package/dist/xlsx/write/workbook-part.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/visio/edit-foreign-bitmap.d.ts +0 -7
- package/dist/visio/edit-foreign-bitmap.d.ts.map +0 -1
- /package/dist/{chunk-KU3SMBFU.mjs → chunk-C363NN2C.mjs} +0 -0
- /package/dist/{chunk-UWWS6VVJ.cjs → chunk-R4BCOQHB.cjs} +0 -0
|
@@ -57,8 +57,8 @@ function parseXml(xml, options = {}) {
|
|
|
57
57
|
let parsed;
|
|
58
58
|
try {
|
|
59
59
|
parsed = new DOMParser({
|
|
60
|
-
onError: (
|
|
61
|
-
if (
|
|
60
|
+
onError: (level2, message) => {
|
|
61
|
+
if (level2 !== "warning") parseError = message;
|
|
62
62
|
}
|
|
63
63
|
}).parseFromString(xml, "application/xml");
|
|
64
64
|
} catch (error) {
|
|
@@ -728,8 +728,8 @@ function resolveRunFormatting(run, context = {}) {
|
|
|
728
728
|
if (state) result[key] = true;
|
|
729
729
|
}
|
|
730
730
|
for (const key of OVERRIDE_KEYS) {
|
|
731
|
-
for (const
|
|
732
|
-
const value =
|
|
731
|
+
for (const level2 of levels) {
|
|
732
|
+
const value = level2[key];
|
|
733
733
|
if (value !== void 0) result[key] = value;
|
|
734
734
|
}
|
|
735
735
|
}
|
|
@@ -11339,6 +11339,287 @@ function groupRowsByCategory(rawCategories) {
|
|
|
11339
11339
|
return { uniqueCategories, rowIndexesByCategory };
|
|
11340
11340
|
}
|
|
11341
11341
|
|
|
11342
|
+
// chart/number-format-pattern.ts
|
|
11343
|
+
var NAMED_FORMAT_COLORS = {
|
|
11344
|
+
black: "#000000",
|
|
11345
|
+
blue: "#0000FF",
|
|
11346
|
+
cyan: "#00FFFF",
|
|
11347
|
+
green: "#00FF00",
|
|
11348
|
+
magenta: "#FF00FF",
|
|
11349
|
+
red: "#FF0000",
|
|
11350
|
+
white: "#FFFFFF",
|
|
11351
|
+
yellow: "#FFFF00"
|
|
11352
|
+
};
|
|
11353
|
+
var PLACEHOLDER = /[0#?]/u;
|
|
11354
|
+
function parsePattern(code) {
|
|
11355
|
+
let scale = 1;
|
|
11356
|
+
let scientific = false;
|
|
11357
|
+
let color;
|
|
11358
|
+
const chars = [];
|
|
11359
|
+
let inQuotes = false;
|
|
11360
|
+
for (let i = 0; i < code.length; i += 1) {
|
|
11361
|
+
const ch = code[i] ?? "";
|
|
11362
|
+
if (ch === '"') {
|
|
11363
|
+
inQuotes = !inQuotes;
|
|
11364
|
+
continue;
|
|
11365
|
+
}
|
|
11366
|
+
if (inQuotes) {
|
|
11367
|
+
chars.push({ ch, literal: true });
|
|
11368
|
+
continue;
|
|
11369
|
+
}
|
|
11370
|
+
if (ch === "\\" || ch === "*" || ch === "_") {
|
|
11371
|
+
const next = code[i + 1];
|
|
11372
|
+
i += 1;
|
|
11373
|
+
if (ch === "\\" && next !== void 0) {
|
|
11374
|
+
chars.push({ ch: next, literal: true });
|
|
11375
|
+
}
|
|
11376
|
+
continue;
|
|
11377
|
+
}
|
|
11378
|
+
if (ch === "%") {
|
|
11379
|
+
scale *= 100;
|
|
11380
|
+
chars.push({ ch, literal: true });
|
|
11381
|
+
continue;
|
|
11382
|
+
}
|
|
11383
|
+
if (ch === "E" && (code[i + 1] === "+" || code[i + 1] === "-")) {
|
|
11384
|
+
scientific = true;
|
|
11385
|
+
chars.push({ ch: "E", literal: false });
|
|
11386
|
+
i += 1;
|
|
11387
|
+
continue;
|
|
11388
|
+
}
|
|
11389
|
+
if (ch === "[") {
|
|
11390
|
+
const close = code.indexOf("]", i);
|
|
11391
|
+
const token = code.slice(i + 1, close === -1 ? code.length : close);
|
|
11392
|
+
const named3 = NAMED_FORMAT_COLORS[token.trim().toLowerCase()];
|
|
11393
|
+
if (named3 && color === void 0) {
|
|
11394
|
+
color = named3;
|
|
11395
|
+
}
|
|
11396
|
+
i = close === -1 ? code.length : close;
|
|
11397
|
+
continue;
|
|
11398
|
+
}
|
|
11399
|
+
chars.push({ ch, literal: false });
|
|
11400
|
+
}
|
|
11401
|
+
const firstDigit = chars.findIndex((c) => !c.literal && PLACEHOLDER.test(c.ch));
|
|
11402
|
+
if (firstDigit === -1) {
|
|
11403
|
+
return void 0;
|
|
11404
|
+
}
|
|
11405
|
+
let lastDigit = firstDigit;
|
|
11406
|
+
for (let i = chars.length - 1; i >= firstDigit; i -= 1) {
|
|
11407
|
+
const c = chars[i];
|
|
11408
|
+
if (c && !c.literal && (PLACEHOLDER.test(c.ch) || c.ch === "." || c.ch === "," || c.ch === "E")) {
|
|
11409
|
+
lastDigit = i;
|
|
11410
|
+
break;
|
|
11411
|
+
}
|
|
11412
|
+
}
|
|
11413
|
+
const numeric = chars.slice(firstDigit, lastDigit + 1);
|
|
11414
|
+
const prefix2 = chars.slice(0, firstDigit).map((c) => c.ch).join("");
|
|
11415
|
+
const suffix = chars.slice(lastDigit + 1).map((c) => c.ch).join("");
|
|
11416
|
+
let grouped = false;
|
|
11417
|
+
let intDigits = 0;
|
|
11418
|
+
let required = 0;
|
|
11419
|
+
let optional = 0;
|
|
11420
|
+
let afterPoint = false;
|
|
11421
|
+
let inExponent = false;
|
|
11422
|
+
for (let i = 0; i < numeric.length; i += 1) {
|
|
11423
|
+
const { ch, literal } = numeric[i] ?? { ch: "", literal: true };
|
|
11424
|
+
if (literal) {
|
|
11425
|
+
continue;
|
|
11426
|
+
}
|
|
11427
|
+
if (ch === "E") {
|
|
11428
|
+
inExponent = true;
|
|
11429
|
+
continue;
|
|
11430
|
+
}
|
|
11431
|
+
if (inExponent) {
|
|
11432
|
+
continue;
|
|
11433
|
+
}
|
|
11434
|
+
if (ch === ".") {
|
|
11435
|
+
afterPoint = true;
|
|
11436
|
+
continue;
|
|
11437
|
+
}
|
|
11438
|
+
if (ch === ",") {
|
|
11439
|
+
const next = numeric.slice(i + 1).find((c) => !c.literal);
|
|
11440
|
+
if (!next || next.ch === "." || !PLACEHOLDER.test(next.ch)) {
|
|
11441
|
+
scale /= 1e3;
|
|
11442
|
+
} else {
|
|
11443
|
+
grouped = true;
|
|
11444
|
+
}
|
|
11445
|
+
continue;
|
|
11446
|
+
}
|
|
11447
|
+
if (!PLACEHOLDER.test(ch)) {
|
|
11448
|
+
continue;
|
|
11449
|
+
}
|
|
11450
|
+
if (afterPoint) {
|
|
11451
|
+
if (ch === "0") {
|
|
11452
|
+
required += 1;
|
|
11453
|
+
} else {
|
|
11454
|
+
optional += 1;
|
|
11455
|
+
}
|
|
11456
|
+
} else if (ch === "0") {
|
|
11457
|
+
intDigits += 1;
|
|
11458
|
+
}
|
|
11459
|
+
}
|
|
11460
|
+
return {
|
|
11461
|
+
prefix: prefix2,
|
|
11462
|
+
suffix,
|
|
11463
|
+
intDigits,
|
|
11464
|
+
decimals: { required, optional },
|
|
11465
|
+
grouped,
|
|
11466
|
+
scale,
|
|
11467
|
+
scientific,
|
|
11468
|
+
color
|
|
11469
|
+
};
|
|
11470
|
+
}
|
|
11471
|
+
function group(intPart) {
|
|
11472
|
+
return intPart.replace(/\B(?=(\d{3})+(?!\d))/gu, ",");
|
|
11473
|
+
}
|
|
11474
|
+
function applyPattern(value, pattern, forcePositive) {
|
|
11475
|
+
const scaled = value * pattern.scale;
|
|
11476
|
+
const magnitude = forcePositive ? Math.abs(scaled) : scaled;
|
|
11477
|
+
if (pattern.scientific) {
|
|
11478
|
+
const digits = pattern.decimals.required + pattern.decimals.optional;
|
|
11479
|
+
const exponential = magnitude.toExponential(digits);
|
|
11480
|
+
const [mantissa = "", exponent = "0"] = exponential.split("e");
|
|
11481
|
+
const sign = exponent.startsWith("-") ? "-" : "+";
|
|
11482
|
+
const power = Math.abs(Number(exponent)).toString().padStart(2, "0");
|
|
11483
|
+
return `${pattern.prefix}${mantissa}E${sign}${power}${pattern.suffix}`;
|
|
11484
|
+
}
|
|
11485
|
+
const maxDecimals = pattern.decimals.required + pattern.decimals.optional;
|
|
11486
|
+
let body = magnitude.toFixed(maxDecimals);
|
|
11487
|
+
if (pattern.decimals.optional > 0) {
|
|
11488
|
+
body = body.replace(/(\.\d*?)0+$/u, "$1").replace(/\.$/u, "");
|
|
11489
|
+
const [, frac = ""] = body.split(".");
|
|
11490
|
+
if (frac.length < pattern.decimals.required) {
|
|
11491
|
+
body = Number(body).toFixed(pattern.decimals.required);
|
|
11492
|
+
}
|
|
11493
|
+
}
|
|
11494
|
+
const [rawIntPart = "", fracPart] = body.split(".");
|
|
11495
|
+
let intPart = rawIntPart;
|
|
11496
|
+
const hasMinusChar = intPart.startsWith("-");
|
|
11497
|
+
const negative = hasMinusChar && Number(body) !== 0;
|
|
11498
|
+
if (hasMinusChar) {
|
|
11499
|
+
intPart = intPart.slice(1);
|
|
11500
|
+
}
|
|
11501
|
+
if (intPart.length < pattern.intDigits) {
|
|
11502
|
+
intPart = intPart.padStart(pattern.intDigits, "0");
|
|
11503
|
+
}
|
|
11504
|
+
if (pattern.intDigits === 0 && intPart === "0" && fracPart !== void 0) {
|
|
11505
|
+
intPart = "";
|
|
11506
|
+
}
|
|
11507
|
+
if (pattern.grouped) {
|
|
11508
|
+
intPart = group(intPart);
|
|
11509
|
+
}
|
|
11510
|
+
const number = fracPart === void 0 ? intPart : `${intPart}.${fracPart}`;
|
|
11511
|
+
return `${negative ? "-" : ""}${pattern.prefix}${number}${pattern.suffix}`;
|
|
11512
|
+
}
|
|
11513
|
+
|
|
11514
|
+
// chart/number-format.ts
|
|
11515
|
+
var GENERAL = /* @__PURE__ */ new Set(["", "general", "@"]);
|
|
11516
|
+
function sections(code) {
|
|
11517
|
+
const out = [];
|
|
11518
|
+
let current = "";
|
|
11519
|
+
let inQuotes = false;
|
|
11520
|
+
for (let i = 0; i < code.length; i += 1) {
|
|
11521
|
+
const ch = code[i];
|
|
11522
|
+
if (ch === '"') {
|
|
11523
|
+
inQuotes = !inQuotes;
|
|
11524
|
+
current += ch;
|
|
11525
|
+
continue;
|
|
11526
|
+
}
|
|
11527
|
+
if (ch === "\\") {
|
|
11528
|
+
current += ch + (code[i + 1] ?? "");
|
|
11529
|
+
i += 1;
|
|
11530
|
+
continue;
|
|
11531
|
+
}
|
|
11532
|
+
if (ch === ";" && !inQuotes) {
|
|
11533
|
+
out.push(current);
|
|
11534
|
+
current = "";
|
|
11535
|
+
continue;
|
|
11536
|
+
}
|
|
11537
|
+
current += ch;
|
|
11538
|
+
}
|
|
11539
|
+
out.push(current);
|
|
11540
|
+
return out;
|
|
11541
|
+
}
|
|
11542
|
+
function sectionFor(value, parts) {
|
|
11543
|
+
if (parts.length === 1) {
|
|
11544
|
+
return { code: parts[0] ?? "", forcePositive: false };
|
|
11545
|
+
}
|
|
11546
|
+
if (value < 0 && parts[1] !== void 0) {
|
|
11547
|
+
return { code: parts[1] ?? "", forcePositive: true };
|
|
11548
|
+
}
|
|
11549
|
+
if (value === 0 && parts[2] !== void 0) {
|
|
11550
|
+
return { code: parts[2] ?? "", forcePositive: false };
|
|
11551
|
+
}
|
|
11552
|
+
return { code: parts[0] ?? "", forcePositive: false };
|
|
11553
|
+
}
|
|
11554
|
+
function formatChartNumberWithColor(value, formatCode) {
|
|
11555
|
+
if (!Number.isFinite(value)) {
|
|
11556
|
+
return void 0;
|
|
11557
|
+
}
|
|
11558
|
+
const code = (formatCode ?? "").trim();
|
|
11559
|
+
if (GENERAL.has(code.toLowerCase())) {
|
|
11560
|
+
return void 0;
|
|
11561
|
+
}
|
|
11562
|
+
if (/(?:^|[^\\"])(?:yy|mm?m|dd?|hh|ss)/iu.test(code) && !/[0#?]/u.test(code)) {
|
|
11563
|
+
return void 0;
|
|
11564
|
+
}
|
|
11565
|
+
const { code: section, forcePositive } = sectionFor(value, sections(code));
|
|
11566
|
+
const pattern = parsePattern(section);
|
|
11567
|
+
if (!pattern) {
|
|
11568
|
+
return void 0;
|
|
11569
|
+
}
|
|
11570
|
+
try {
|
|
11571
|
+
return { text: applyPattern(value, pattern, forcePositive), color: pattern.color };
|
|
11572
|
+
} catch {
|
|
11573
|
+
return void 0;
|
|
11574
|
+
}
|
|
11575
|
+
}
|
|
11576
|
+
|
|
11577
|
+
// chart/data-label-text.ts
|
|
11578
|
+
var DATA_LABEL_SEPARATOR = ", ";
|
|
11579
|
+
var DATA_LABEL_CATEGORY_PERCENT_SEPARATOR = "\n";
|
|
11580
|
+
var FLAG_KEYS = [
|
|
11581
|
+
"showValue",
|
|
11582
|
+
"showCategory",
|
|
11583
|
+
"showSeriesName",
|
|
11584
|
+
"showPercent",
|
|
11585
|
+
"showBubbleSize"
|
|
11586
|
+
];
|
|
11587
|
+
function resolveDataLabelFlags(levels) {
|
|
11588
|
+
const { point, series, chart } = levels;
|
|
11589
|
+
const picked = {};
|
|
11590
|
+
for (const key of FLAG_KEYS) picked[key] = point?.[key] ?? series?.[key] ?? chart?.[key];
|
|
11591
|
+
const anyDeclared = FLAG_KEYS.some((key) => picked[key] !== void 0);
|
|
11592
|
+
return {
|
|
11593
|
+
showValue: anyDeclared ? picked.showValue === true : levels.siblingOwnsLabels !== true,
|
|
11594
|
+
showCategory: picked.showCategory === true,
|
|
11595
|
+
showSeriesName: picked.showSeriesName === true,
|
|
11596
|
+
showPercent: picked.showPercent === true,
|
|
11597
|
+
showBubbleSize: picked.showBubbleSize === true,
|
|
11598
|
+
separator: point?.separator ?? series?.separator ?? chart?.separator ?? (picked.showCategory === true && picked.showPercent === true ? DATA_LABEL_CATEGORY_PERCENT_SEPARATOR : DATA_LABEL_SEPARATOR)
|
|
11599
|
+
};
|
|
11600
|
+
}
|
|
11601
|
+
function composeDataLabelText(input) {
|
|
11602
|
+
const { flags, value, numberFormat } = input;
|
|
11603
|
+
const parts = [];
|
|
11604
|
+
let valueColor;
|
|
11605
|
+
if (flags.showSeriesName && input.seriesName) parts.push(input.seriesName);
|
|
11606
|
+
if (flags.showCategory && input.category) parts.push(input.category);
|
|
11607
|
+
if (flags.showValue) {
|
|
11608
|
+
const formatted = formatChartNumberWithColor(value, numberFormat);
|
|
11609
|
+
parts.push(formatted?.text ?? (input.formatValue ?? String)(value, numberFormat));
|
|
11610
|
+
valueColor = formatted?.color;
|
|
11611
|
+
}
|
|
11612
|
+
if (flags.showPercent) {
|
|
11613
|
+
const base = input.percentBase;
|
|
11614
|
+
parts.push(base > 0 ? `${Math.round(Math.abs(value) / base * 100)}%` : "0%");
|
|
11615
|
+
}
|
|
11616
|
+
if (flags.showBubbleSize && input.bubbleSize !== void 0)
|
|
11617
|
+
parts.push((input.formatBubbleSize ?? String)(input.bubbleSize));
|
|
11618
|
+
const text2 = parts.join(flags.separator);
|
|
11619
|
+
if (text2.length === 0) return void 0;
|
|
11620
|
+
return { text: text2, color: parts.length === 1 && flags.showValue ? valueColor : void 0 };
|
|
11621
|
+
}
|
|
11622
|
+
|
|
11342
11623
|
// chart/bubble-radius.ts
|
|
11343
11624
|
function computeBubbleRadius(sizeVal, maxBubble, medianRadius, options) {
|
|
11344
11625
|
const scale = (options?.bubbleScale ?? 100) / 100;
|
|
@@ -11451,10 +11732,10 @@ function squarify(nodes, box) {
|
|
|
11451
11732
|
|
|
11452
11733
|
// chart/hierarchy.ts
|
|
11453
11734
|
function normalizeLevels(levels, pointCount) {
|
|
11454
|
-
return levels.map((
|
|
11735
|
+
return levels.map((level2) => {
|
|
11455
11736
|
let previous = "";
|
|
11456
11737
|
return Array.from({ length: pointCount }, (_, index) => {
|
|
11457
|
-
const label =
|
|
11738
|
+
const label = level2[index]?.trim() ?? "";
|
|
11458
11739
|
if (label) previous = label;
|
|
11459
11740
|
return label || previous;
|
|
11460
11741
|
});
|
|
@@ -11612,12 +11893,12 @@ function computeSunburstArcs(series, cx, cy, maxR) {
|
|
|
11612
11893
|
});
|
|
11613
11894
|
return out;
|
|
11614
11895
|
}
|
|
11615
|
-
function hierarchyKey(levels,
|
|
11616
|
-
return levels.slice(
|
|
11896
|
+
function hierarchyKey(levels, level2, index) {
|
|
11897
|
+
return levels.slice(level2).map((labels) => labels[index] ?? "").join("\0");
|
|
11617
11898
|
}
|
|
11618
11899
|
function computeHierarchicalSunburstArcs(categoryLevels, values, cx, cy, maxR) {
|
|
11619
|
-
const levels = categoryLevels.filter((
|
|
11620
|
-
const leafCount = Math.max(values.length, ...levels.map((
|
|
11900
|
+
const levels = categoryLevels.filter((level2) => level2.length > 0);
|
|
11901
|
+
const leafCount = Math.max(values.length, ...levels.map((level2) => level2.length), 0);
|
|
11621
11902
|
if (levels.length === 0 || leafCount === 0) return [];
|
|
11622
11903
|
const rawWeights = Array.from({ length: leafCount }, (_, index) => Math.abs(values[index] ?? 0));
|
|
11623
11904
|
const weights = rawWeights.some((value) => value !== 0) ? rawWeights : rawWeights.map(() => 1);
|
|
@@ -11628,15 +11909,15 @@ function computeHierarchicalSunburstArcs(categoryLevels, values, cx, cy, maxR) {
|
|
|
11628
11909
|
const rootLabels = levels[levels.length - 1] ?? [];
|
|
11629
11910
|
const rootColors = /* @__PURE__ */ new Map();
|
|
11630
11911
|
const out = [];
|
|
11631
|
-
for (let
|
|
11632
|
-
const ringIndex = levels.length - 1 -
|
|
11912
|
+
for (let level2 = levels.length - 1; level2 >= 0; level2--) {
|
|
11913
|
+
const ringIndex = levels.length - 1 - level2;
|
|
11633
11914
|
const innerRadius = ringWidth * (ringIndex + 0.5);
|
|
11634
11915
|
const outerRadius = ringWidth * (ringIndex + 1.5);
|
|
11635
11916
|
let start = 0;
|
|
11636
11917
|
while (start < leafCount) {
|
|
11637
|
-
const key = hierarchyKey(levels,
|
|
11918
|
+
const key = hierarchyKey(levels, level2, start);
|
|
11638
11919
|
let end = start + 1;
|
|
11639
|
-
while (end < leafCount && hierarchyKey(levels,
|
|
11920
|
+
while (end < leafCount && hierarchyKey(levels, level2, end) === key) end++;
|
|
11640
11921
|
const startAngle = -Math.PI / 2 + (prefix2[start] ?? 0) / total * Math.PI * 2;
|
|
11641
11922
|
const endAngle = -Math.PI / 2 + (prefix2[end] ?? 0) / total * Math.PI * 2;
|
|
11642
11923
|
const rootLabel = rootLabels[start] ?? "";
|
|
@@ -11646,8 +11927,8 @@ function computeHierarchicalSunburstArcs(categoryLevels, values, cx, cy, maxR) {
|
|
|
11646
11927
|
colorIndex: rootColors.get(rootLabel) ?? start,
|
|
11647
11928
|
opacity: Math.max(0.1, 0.9 - ringIndex * 0.1),
|
|
11648
11929
|
level: ringIndex,
|
|
11649
|
-
label: levels[
|
|
11650
|
-
...
|
|
11930
|
+
label: levels[level2]?.[start] ?? "",
|
|
11931
|
+
...level2 === 0 && end === start + 1 ? { pointIndex: start } : {},
|
|
11651
11932
|
...arcLabelPlacement(cx, cy, (innerRadius + outerRadius) / 2, startAngle, endAngle)
|
|
11652
11933
|
});
|
|
11653
11934
|
start = end;
|
|
@@ -11935,6 +12216,65 @@ function chartErrorBarAmount(options, values, displayIndex, sourceIndex, side) {
|
|
|
11935
12216
|
}
|
|
11936
12217
|
}
|
|
11937
12218
|
|
|
12219
|
+
// chart/pie-best-fit.ts
|
|
12220
|
+
var PX_PER_PT = 4 / 3;
|
|
12221
|
+
var BEST_FIT_RIM_INSET = 4 * PX_PER_PT;
|
|
12222
|
+
var BEST_FIT_EDGE_TOLERANCE = 1.5 * PX_PER_PT;
|
|
12223
|
+
var BEST_FIT_OUTSIDE_GAP = 2 * PX_PER_PT;
|
|
12224
|
+
function farCorner(x, y, w, h) {
|
|
12225
|
+
return Math.hypot(Math.abs(x) + w / 2, Math.abs(y) + h / 2);
|
|
12226
|
+
}
|
|
12227
|
+
function insideDistance(ux, uy, w, h, limit) {
|
|
12228
|
+
if (farCorner(0, 0, w, h) > limit) {
|
|
12229
|
+
return void 0;
|
|
12230
|
+
}
|
|
12231
|
+
let lo = 0;
|
|
12232
|
+
let hi = limit;
|
|
12233
|
+
for (let i = 0; i < 40; i++) {
|
|
12234
|
+
const mid = (lo + hi) / 2;
|
|
12235
|
+
if (farCorner(mid * ux, mid * uy, w, h) > limit) {
|
|
12236
|
+
hi = mid;
|
|
12237
|
+
} else {
|
|
12238
|
+
lo = mid;
|
|
12239
|
+
}
|
|
12240
|
+
}
|
|
12241
|
+
return lo;
|
|
12242
|
+
}
|
|
12243
|
+
function edgeOverhang(x, y, w, h, slice) {
|
|
12244
|
+
let worst = Number.NEGATIVE_INFINITY;
|
|
12245
|
+
const corners = [
|
|
12246
|
+
[-w / 2, -h / 2],
|
|
12247
|
+
[w / 2, -h / 2],
|
|
12248
|
+
[-w / 2, h / 2],
|
|
12249
|
+
[w / 2, h / 2]
|
|
12250
|
+
];
|
|
12251
|
+
for (const [dx, dy] of corners) {
|
|
12252
|
+
const px = x + dx;
|
|
12253
|
+
const py = y + dy;
|
|
12254
|
+
const fromStart = Math.cos(slice.startAngle) * py - Math.sin(slice.startAngle) * px;
|
|
12255
|
+
const fromEnd = Math.sin(slice.endAngle) * px - Math.cos(slice.endAngle) * py;
|
|
12256
|
+
worst = Math.max(worst, -fromStart, -fromEnd);
|
|
12257
|
+
}
|
|
12258
|
+
return worst;
|
|
12259
|
+
}
|
|
12260
|
+
function placeBestFitLabel(slice, w, h) {
|
|
12261
|
+
const mid = (slice.startAngle + slice.endAngle) / 2;
|
|
12262
|
+
const ux = Math.cos(mid);
|
|
12263
|
+
const uy = Math.sin(mid);
|
|
12264
|
+
const distance = insideDistance(ux, uy, w, h, slice.outerR - BEST_FIT_RIM_INSET);
|
|
12265
|
+
if (distance !== void 0) {
|
|
12266
|
+
const x = distance * ux;
|
|
12267
|
+
const y = distance * uy;
|
|
12268
|
+
const reflex = slice.endAngle - slice.startAngle >= Math.PI;
|
|
12269
|
+
if (reflex || edgeOverhang(x, y, w, h, slice) <= BEST_FIT_EDGE_TOLERANCE) {
|
|
12270
|
+
return { x: slice.cx + x, y: slice.cy + y, inside: true };
|
|
12271
|
+
}
|
|
12272
|
+
}
|
|
12273
|
+
const extent = Math.abs(ux) * w / 2 + Math.abs(uy) * h / 2;
|
|
12274
|
+
const outside = slice.outerR + BEST_FIT_OUTSIDE_GAP + extent;
|
|
12275
|
+
return { x: slice.cx + outside * ux, y: slice.cy + outside * uy, inside: false };
|
|
12276
|
+
}
|
|
12277
|
+
|
|
11938
12278
|
// chart/color-palettes.ts
|
|
11939
12279
|
var COLORFUL_VARIATIONS = [
|
|
11940
12280
|
{},
|
|
@@ -12288,6 +12628,41 @@ function summaryAnalysis(series) {
|
|
|
12288
12628
|
};
|
|
12289
12629
|
}
|
|
12290
12630
|
|
|
12631
|
+
// chart/render/summary-labels.ts
|
|
12632
|
+
function level(options, custom) {
|
|
12633
|
+
const out = {};
|
|
12634
|
+
if (options.deleted !== void 0) out.deleted = options.deleted;
|
|
12635
|
+
if (options.showValue !== void 0) out.showValue = options.showValue;
|
|
12636
|
+
if (options.showCategoryName !== void 0) out.showCategory = options.showCategoryName;
|
|
12637
|
+
if (options.showSeriesName !== void 0) out.showSeriesName = options.showSeriesName;
|
|
12638
|
+
if (options.showPercent !== void 0) out.showPercent = options.showPercent;
|
|
12639
|
+
if (options.showBubbleSize !== void 0) out.showBubbleSize = options.showBubbleSize;
|
|
12640
|
+
if (options.separator !== void 0) out.separator = options.separator;
|
|
12641
|
+
if (options.position) out.position = options.position;
|
|
12642
|
+
if (options.numberFormat?.formatCode) out.numberFormat = options.numberFormat.formatCode;
|
|
12643
|
+
if (custom?.text !== void 0) out.text = custom.text;
|
|
12644
|
+
return out;
|
|
12645
|
+
}
|
|
12646
|
+
function shows(levels, point) {
|
|
12647
|
+
const flags = resolveDataLabelFlags({ ...levels, ...point ? { point } : {} });
|
|
12648
|
+
return point?.text !== void 0 || Object.values(flags).some((value) => value === true);
|
|
12649
|
+
}
|
|
12650
|
+
function summaryDataLabels(series, group2) {
|
|
12651
|
+
const own2 = series.dataLabels;
|
|
12652
|
+
if (!own2 && !group2) return void 0;
|
|
12653
|
+
const out = {};
|
|
12654
|
+
if (group2) out.chart = level(group2);
|
|
12655
|
+
if (own2) out.series = level(own2);
|
|
12656
|
+
const points = {};
|
|
12657
|
+
for (const labels of [group2, own2])
|
|
12658
|
+
for (const label of labels?.labels ?? [])
|
|
12659
|
+
if (label.index !== void 0)
|
|
12660
|
+
points[label.index] = { ...points[label.index], ...level(label, label.tx) };
|
|
12661
|
+
if (Object.keys(points).length) out.points = points;
|
|
12662
|
+
if (!shows(out) && !Object.values(points).some((point) => shows(out, point))) return void 0;
|
|
12663
|
+
return out;
|
|
12664
|
+
}
|
|
12665
|
+
|
|
12291
12666
|
// chart/render/summary-from-space.ts
|
|
12292
12667
|
var solidColor = (fill) => fill?.kind === "solid" ? fill.color : void 0;
|
|
12293
12668
|
var isSolidFill = (fill) => fill?.kind === "solid" || fill?.kind === "unsupported" && fill.element === "solidFill";
|
|
@@ -12305,7 +12680,7 @@ var GROUP_TYPES = {
|
|
|
12305
12680
|
surface: "surface"
|
|
12306
12681
|
};
|
|
12307
12682
|
var GROUPINGS = /* @__PURE__ */ new Set(["clustered", "stacked", "percentStacked", "standard"]);
|
|
12308
|
-
function chartSummarySeries(source, chartType) {
|
|
12683
|
+
function chartSummarySeries(source, chartType, groupLabels) {
|
|
12309
12684
|
const categories = source.categories ?? source.xValues;
|
|
12310
12685
|
const values = source.values ?? source.yValues;
|
|
12311
12686
|
const numeric = (v) => typeof v === "number" ? v : v === "" ? null : Number.isFinite(Number(v)) ? Number(v) : null;
|
|
@@ -12313,6 +12688,7 @@ function chartSummarySeries(source, chartType) {
|
|
|
12313
12688
|
categories: chartSourceValues(categories),
|
|
12314
12689
|
values: chartSourceValues(values).map(numeric)
|
|
12315
12690
|
};
|
|
12691
|
+
if (values?.cache?.formatCode !== void 0) out.numberFormat = values.cache.formatCode;
|
|
12316
12692
|
if (source.bubbleSizes) {
|
|
12317
12693
|
out.bubbleSizes = chartSourceValues(source.bubbleSizes).map(numeric);
|
|
12318
12694
|
if (source.bubbleSizes.formula) out.bubbleSizesRef = source.bubbleSizes.formula;
|
|
@@ -12341,6 +12717,8 @@ function chartSummarySeries(source, chartType) {
|
|
|
12341
12717
|
}
|
|
12342
12718
|
if (Object.keys(points).length) out.pointColors = points;
|
|
12343
12719
|
if (Object.keys(pointFills).length) out.pointFills = pointFills;
|
|
12720
|
+
const dataLabels = summaryDataLabels(source, groupLabels);
|
|
12721
|
+
if (dataLabels) out.dataLabels = dataLabels;
|
|
12344
12722
|
Object.assign(out, summaryAnalysis(source));
|
|
12345
12723
|
return out;
|
|
12346
12724
|
}
|
|
@@ -12349,12 +12727,12 @@ function valueAxisId(chartSpace, axisIds) {
|
|
|
12349
12727
|
(id) => chartSpace.plotArea.axes.some((a) => a.id === id && a.kind === "val")
|
|
12350
12728
|
);
|
|
12351
12729
|
}
|
|
12352
|
-
function stockStyle(
|
|
12730
|
+
function stockStyle(group2) {
|
|
12353
12731
|
return {
|
|
12354
|
-
...
|
|
12355
|
-
...
|
|
12356
|
-
...
|
|
12357
|
-
...
|
|
12732
|
+
...group2.hiLowLinesSpPr ? { hiLowLines: group2.hiLowLinesSpPr } : {},
|
|
12733
|
+
...group2.upBars?.spPr ? { upBars: group2.upBars.spPr } : {},
|
|
12734
|
+
...group2.downBars?.spPr ? { downBars: group2.downBars.spPr } : {},
|
|
12735
|
+
...group2.upDownBarsGapWidth === void 0 ? {} : { gapWidth: group2.upDownBarsGapWidth }
|
|
12358
12736
|
};
|
|
12359
12737
|
}
|
|
12360
12738
|
function extraGroups(chartSpace, firstType) {
|
|
@@ -12362,31 +12740,33 @@ function extraGroups(chartSpace, firstType) {
|
|
|
12362
12740
|
if (!first3 || !["column", "line", "area"].includes(firstType)) return [];
|
|
12363
12741
|
const primary = valueAxisId(chartSpace, first3.axisIds);
|
|
12364
12742
|
const out = [];
|
|
12365
|
-
for (const
|
|
12366
|
-
const stockOverColumns =
|
|
12367
|
-
if (
|
|
12368
|
-
const type =
|
|
12743
|
+
for (const group2 of rest) {
|
|
12744
|
+
const stockOverColumns = group2.kind === "stock" && firstType === "column";
|
|
12745
|
+
if (group2.is3D || !(["bar", "line", "area"].includes(group2.kind) || stockOverColumns)) continue;
|
|
12746
|
+
const type = group2.kind === "bar" ? "column" : group2.kind;
|
|
12369
12747
|
const entry = {
|
|
12370
12748
|
chartType: type,
|
|
12371
|
-
series:
|
|
12372
|
-
secondary: valueAxisId(chartSpace,
|
|
12749
|
+
series: group2.series.map((source) => chartSummarySeries(source, type, group2.dataLabels)),
|
|
12750
|
+
secondary: valueAxisId(chartSpace, group2.axisIds) !== primary
|
|
12373
12751
|
};
|
|
12374
|
-
if (
|
|
12375
|
-
entry.grouping =
|
|
12376
|
-
if (type === "stock") entry.stock = stockStyle(
|
|
12752
|
+
if (group2.grouping && GROUPINGS.has(group2.grouping))
|
|
12753
|
+
entry.grouping = group2.grouping;
|
|
12754
|
+
if (type === "stock") entry.stock = stockStyle(group2);
|
|
12377
12755
|
if (type === "column") {
|
|
12378
|
-
if (
|
|
12379
|
-
if (
|
|
12756
|
+
if (group2.gapWidth !== void 0) entry.barGapWidth = group2.gapWidth;
|
|
12757
|
+
if (group2.overlap !== void 0) entry.barOverlap = group2.overlap;
|
|
12380
12758
|
}
|
|
12381
12759
|
if (entry.series.length) out.push(entry);
|
|
12382
12760
|
}
|
|
12383
12761
|
return out;
|
|
12384
12762
|
}
|
|
12385
12763
|
function chartSummaryFromSpace(chartSpace, extras = {}) {
|
|
12386
|
-
const
|
|
12387
|
-
let chartType =
|
|
12388
|
-
if (chartType === "bar" &&
|
|
12389
|
-
const series = (
|
|
12764
|
+
const group2 = chartSpace.plotArea.groups[0];
|
|
12765
|
+
let chartType = group2 ? GROUP_TYPES[group2.kind] : "column";
|
|
12766
|
+
if (chartType === "bar" && group2?.barDirection !== "bar") chartType = "column";
|
|
12767
|
+
const series = (group2?.series ?? []).map(
|
|
12768
|
+
(source) => chartSummarySeries(source, chartType, group2?.dataLabels)
|
|
12769
|
+
);
|
|
12390
12770
|
const summary = {
|
|
12391
12771
|
chartType,
|
|
12392
12772
|
series,
|
|
@@ -12394,22 +12774,22 @@ function chartSummaryFromSpace(chartSpace, extras = {}) {
|
|
|
12394
12774
|
};
|
|
12395
12775
|
const combined = extraGroups(chartSpace, chartType);
|
|
12396
12776
|
if (combined.length) summary.extraGroups = combined;
|
|
12397
|
-
if (chartType === "stock" &&
|
|
12398
|
-
if (chartType === "bubble" &&
|
|
12399
|
-
const sizeRepresents =
|
|
12777
|
+
if (chartType === "stock" && group2) summary.stock = stockStyle(group2);
|
|
12778
|
+
if (chartType === "bubble" && group2) {
|
|
12779
|
+
const sizeRepresents = group2.sizeRepresents === "w" ? "w" : "area";
|
|
12400
12780
|
summary.bubble = {
|
|
12401
12781
|
sizeRepresents,
|
|
12402
|
-
...
|
|
12403
|
-
showNegativeBubbles:
|
|
12782
|
+
...group2.bubbleScale === void 0 ? {} : { bubbleScale: group2.bubbleScale },
|
|
12783
|
+
showNegativeBubbles: group2.showNegativeBubbles === true
|
|
12404
12784
|
};
|
|
12405
12785
|
}
|
|
12406
|
-
const grouping =
|
|
12786
|
+
const grouping = group2?.grouping;
|
|
12407
12787
|
if (grouping && GROUPINGS.has(grouping))
|
|
12408
12788
|
summary.grouping = grouping;
|
|
12409
12789
|
if (chartType === "bar" || chartType === "column") {
|
|
12410
12790
|
for (const [value, field, fallback, min, max] of [
|
|
12411
|
-
[
|
|
12412
|
-
[
|
|
12791
|
+
[group2?.gapWidth, "barGapWidth", 150, 0, 500],
|
|
12792
|
+
[group2?.overlap, "barOverlap", 0, -100, 100]
|
|
12413
12793
|
]) {
|
|
12414
12794
|
const resolved = value ?? fallback;
|
|
12415
12795
|
if (Number.isInteger(resolved) && resolved >= min && resolved <= max)
|
|
@@ -12471,268 +12851,56 @@ function chartBarSpacing(chart) {
|
|
|
12471
12851
|
};
|
|
12472
12852
|
}
|
|
12473
12853
|
|
|
12474
|
-
// chart/render/
|
|
12475
|
-
|
|
12476
|
-
|
|
12477
|
-
|
|
12478
|
-
|
|
12479
|
-
|
|
12480
|
-
|
|
12481
|
-
|
|
12482
|
-
|
|
12483
|
-
|
|
12484
|
-
|
|
12485
|
-
|
|
12486
|
-
|
|
12487
|
-
|
|
12488
|
-
|
|
12489
|
-
|
|
12490
|
-
|
|
12491
|
-
|
|
12492
|
-
|
|
12493
|
-
|
|
12494
|
-
|
|
12495
|
-
|
|
12496
|
-
|
|
12497
|
-
|
|
12498
|
-
|
|
12499
|
-
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
|
|
12507
|
-
if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
|
|
12508
|
-
const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
|
|
12509
|
-
if (baseId) {
|
|
12510
|
-
const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
|
|
12511
|
-
const def = buildChartGradientDef(id, gradient, {
|
|
12512
|
-
width: Number(n(width)),
|
|
12513
|
-
height: Number(n(height)),
|
|
12514
|
-
shape: "rect"
|
|
12515
|
-
});
|
|
12516
|
-
out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
|
|
12517
|
-
color = `url(#${id})`;
|
|
12518
|
-
}
|
|
12519
|
-
}
|
|
12520
|
-
out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
|
|
12521
|
-
if (model.horizontal)
|
|
12522
|
-
out.push(
|
|
12523
|
-
rect2(Math.min(a, b), center + offset, Math.abs(b - a), barSize, color, s.shadowFilter)
|
|
12524
|
-
);
|
|
12525
|
-
else
|
|
12526
|
-
out.push(
|
|
12527
|
-
rect2(center + offset, Math.min(a, b), barSize, Math.abs(b - a), color, s.shadowFilter)
|
|
12528
|
-
);
|
|
12529
|
-
out.push("</g>");
|
|
12530
|
-
});
|
|
12531
|
-
});
|
|
12854
|
+
// chart/render/theme-palette.ts
|
|
12855
|
+
var THEME_SLOTS = [
|
|
12856
|
+
"lt1",
|
|
12857
|
+
"dk1",
|
|
12858
|
+
"lt2",
|
|
12859
|
+
"dk2",
|
|
12860
|
+
"accent1",
|
|
12861
|
+
"accent2",
|
|
12862
|
+
"accent3",
|
|
12863
|
+
"accent4",
|
|
12864
|
+
"accent5",
|
|
12865
|
+
"accent6",
|
|
12866
|
+
"hlink",
|
|
12867
|
+
"folHlink"
|
|
12868
|
+
];
|
|
12869
|
+
var DEFAULT_THEME_COLORS = [
|
|
12870
|
+
"FFFFFF",
|
|
12871
|
+
"000000",
|
|
12872
|
+
"E7E6E6",
|
|
12873
|
+
"44546A",
|
|
12874
|
+
"4472C4",
|
|
12875
|
+
"ED7D31",
|
|
12876
|
+
"A5A5A5",
|
|
12877
|
+
"FFC000",
|
|
12878
|
+
"5B9BD5",
|
|
12879
|
+
"70AD47",
|
|
12880
|
+
"0563C1",
|
|
12881
|
+
"954F72"
|
|
12882
|
+
];
|
|
12883
|
+
function themeColor(theme, index) {
|
|
12884
|
+
const hex = theme.colors[index] ?? DEFAULT_THEME_COLORS[index];
|
|
12885
|
+
return hex && parseArgbHex(hex) ? hex.replace(/^#/, "") : void 0;
|
|
12532
12886
|
}
|
|
12533
12887
|
|
|
12534
|
-
// chart/render/chart-
|
|
12535
|
-
|
|
12536
|
-
|
|
12537
|
-
|
|
12538
|
-
|
|
12539
|
-
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12544
|
-
|
|
12545
|
-
|
|
12546
|
-
};
|
|
12547
|
-
var CAP = 4;
|
|
12548
|
-
function strokeAttributes(stroke) {
|
|
12549
|
-
const pattern = stroke.dash ? DASHES[stroke.dash] : void 0;
|
|
12550
|
-
const dash = pattern ? ` stroke-dasharray="${pattern.map((step) => n(step * stroke.width)).join(" ")}"` : "";
|
|
12551
|
-
return `stroke="${esc(stroke.color)}" stroke-width="${n(stroke.width)}"${dash}`;
|
|
12552
|
-
}
|
|
12553
|
-
var segment = (x1, y1, x2, y2, stroke) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" ${stroke}/>`;
|
|
12554
|
-
function trendlines(series, si, xs, ys, plane, out) {
|
|
12555
|
-
for (const trendline of series.trendlines ?? []) {
|
|
12556
|
-
const fit2 = fitChartTrendline(trendline.fit, xs, ys);
|
|
12557
|
-
if (fit2.points.length < 2) continue;
|
|
12558
|
-
const points = fit2.points.map(({ x, y }) => plane(x, y).map(n).join(",")).join(" ");
|
|
12559
|
-
out.push(
|
|
12560
|
-
`<polyline points="${points}" fill="none" ${strokeAttributes(trendline.stroke)} data-chart-part="trendline" data-chart-series="${si}"/>`
|
|
12561
|
-
);
|
|
12562
|
-
}
|
|
12888
|
+
// chart/render/chart-colors.ts
|
|
12889
|
+
function chartColorScheme(theme) {
|
|
12890
|
+
const slots = Object.fromEntries(
|
|
12891
|
+
THEME_SLOTS.map((slot, index) => [slot, `#${themeColor(theme, index) ?? "000000"}`])
|
|
12892
|
+
);
|
|
12893
|
+
return {
|
|
12894
|
+
...slots,
|
|
12895
|
+
bg1: slots.lt1,
|
|
12896
|
+
tx1: slots.dk1,
|
|
12897
|
+
bg2: slots.lt2,
|
|
12898
|
+
tx2: slots.dk2
|
|
12899
|
+
};
|
|
12563
12900
|
}
|
|
12564
|
-
function
|
|
12565
|
-
const
|
|
12566
|
-
|
|
12567
|
-
if (bars2.barType !== side && bars2.barType !== "both") continue;
|
|
12568
|
-
const amount = chartErrorBarAmount(bars2.amount, values, at.displayIndex, at.sourceIndex, side);
|
|
12569
|
-
const sign = side === "plus" ? 1 : -1;
|
|
12570
|
-
const [x1, y1] = plane(at.x, at.y);
|
|
12571
|
-
const [x2, y2] = bars2.direction === "x" ? plane(at.x + sign * amount, at.y) : plane(at.x, at.y + sign * amount);
|
|
12572
|
-
out.push(segment(x1, y1, x2, y2, stroke));
|
|
12573
|
-
if (!bars2.endCap) continue;
|
|
12574
|
-
if (x1 === x2) out.push(segment(x2 - CAP, y2, x2 + CAP, y2, stroke));
|
|
12575
|
-
else out.push(segment(x2, y2 - CAP, x2, y2 + CAP, stroke));
|
|
12576
|
-
}
|
|
12577
|
-
}
|
|
12578
|
-
function plottedPoints(series, xOf) {
|
|
12579
|
-
return series.values.flatMap((y, index) => {
|
|
12580
|
-
const x = xOf(index);
|
|
12581
|
-
return y === null || x === null ? [] : [{ x, y, index }];
|
|
12582
|
-
});
|
|
12583
|
-
}
|
|
12584
|
-
function seriesAnalysis(series, si, xOf, plane, barPlane, categoryAxis, out) {
|
|
12585
|
-
const points = plottedPoints(series, xOf);
|
|
12586
|
-
const xs = points.map((p) => p.x);
|
|
12587
|
-
const ys = points.map((p) => p.y);
|
|
12588
|
-
trendlines(series, si, xs, ys, plane, out);
|
|
12589
|
-
for (const bars2 of series.errorBars ?? []) {
|
|
12590
|
-
if (categoryAxis && bars2.direction === "x") continue;
|
|
12591
|
-
const values = bars2.direction === "x" ? xs : ys;
|
|
12592
|
-
points.forEach(
|
|
12593
|
-
(p, displayIndex) => errorBar(bars2, { x: p.x, y: p.y, displayIndex, sourceIndex: p.index }, values, barPlane, out)
|
|
12594
|
-
);
|
|
12595
|
-
}
|
|
12596
|
-
}
|
|
12597
|
-
function categoryAnalysis(model, frame2, out) {
|
|
12598
|
-
if (model.grouping === "stacked" || model.grouping === "percentStacked") return;
|
|
12599
|
-
const plane = (x, y) => model.horizontal ? [frame2.value(y), frame2.band(x - 1)] : [frame2.band(x - 1), frame2.value(y)];
|
|
12600
|
-
const barred = model.type === "bar" || model.type === "column";
|
|
12601
|
-
const layout = barred ? barLayout(model, frame2) : void 0;
|
|
12602
|
-
model.series.forEach((series, si) => {
|
|
12603
|
-
if (!series.trendlines && !series.errorBars) return;
|
|
12604
|
-
const shift = layout ? layout.offset(si) + layout.barSize / 2 : 0;
|
|
12605
|
-
const barPlane = (x, y) => {
|
|
12606
|
-
const [px, py] = plane(x, y);
|
|
12607
|
-
return model.horizontal ? [px, py + shift] : [px + shift, py];
|
|
12608
|
-
};
|
|
12609
|
-
seriesAnalysis(series, si, (i) => i + 1, plane, barPlane, true, out);
|
|
12610
|
-
});
|
|
12611
|
-
}
|
|
12612
|
-
function scatterAnalysis(model, px, py, out) {
|
|
12613
|
-
const plane = (x, y) => [px(x), py(y)];
|
|
12614
|
-
model.series.forEach((series, si) => {
|
|
12615
|
-
if (!series.trendlines && !series.errorBars) return;
|
|
12616
|
-
seriesAnalysis(series, si, (i) => series.xValues?.[i] ?? null, plane, plane, false, out);
|
|
12617
|
-
});
|
|
12618
|
-
}
|
|
12619
|
-
|
|
12620
|
-
// chart/render/chart-scale.ts
|
|
12621
|
-
var clean = (n2) => Number(n2.toPrecision(12));
|
|
12622
|
-
function* units(raw) {
|
|
12623
|
-
let exp = Math.floor(Math.log10(raw)) - 1;
|
|
12624
|
-
for (; ; ) {
|
|
12625
|
-
const base = 10 ** exp;
|
|
12626
|
-
for (const m of [1, 2, 5]) yield clean(m * base);
|
|
12627
|
-
exp++;
|
|
12628
|
-
}
|
|
12629
|
-
}
|
|
12630
|
-
function niceScale(dataMin, dataMax, options = {}) {
|
|
12631
|
-
const maxIntervals = Math.max(1, options.maxIntervals ?? 10);
|
|
12632
|
-
let lo = Number.isFinite(dataMin) ? dataMin : 0;
|
|
12633
|
-
let hi = Number.isFinite(dataMax) ? dataMax : 0;
|
|
12634
|
-
if (lo > hi) [lo, hi] = [hi, lo];
|
|
12635
|
-
if (lo === hi) {
|
|
12636
|
-
if (lo === 0) hi = 1;
|
|
12637
|
-
else if (options.noZero) {
|
|
12638
|
-
const pad = Math.abs(lo) * 0.1 || 1;
|
|
12639
|
-
lo -= pad;
|
|
12640
|
-
hi += pad;
|
|
12641
|
-
} else if (lo > 0) lo = 0;
|
|
12642
|
-
else hi = 0;
|
|
12643
|
-
}
|
|
12644
|
-
let fixedLo = false;
|
|
12645
|
-
let fixedHi = false;
|
|
12646
|
-
if (!options.noZero) {
|
|
12647
|
-
if (lo >= 0 && hi - lo >= hi / 6) {
|
|
12648
|
-
lo = 0;
|
|
12649
|
-
fixedLo = true;
|
|
12650
|
-
} else if (hi <= 0 && hi - lo >= -lo / 6) {
|
|
12651
|
-
hi = 0;
|
|
12652
|
-
fixedHi = true;
|
|
12653
|
-
}
|
|
12654
|
-
}
|
|
12655
|
-
const range = hi - lo;
|
|
12656
|
-
const top = fixedHi ? hi : hi + range * 0.05;
|
|
12657
|
-
const bottom = fixedLo ? lo : lo - range * 0.05;
|
|
12658
|
-
for (const unit of units(range / maxIntervals)) {
|
|
12659
|
-
const min = fixedLo ? lo : Math.floor(clean(bottom / unit)) * unit;
|
|
12660
|
-
const max = fixedHi ? hi : Math.ceil(clean(top / unit)) * unit;
|
|
12661
|
-
const intervals = Math.round((max - min) / unit);
|
|
12662
|
-
if (intervals <= maxIntervals && intervals > 0) {
|
|
12663
|
-
const ticks = [];
|
|
12664
|
-
for (let i = 0; i <= intervals; i++) ticks.push(clean(min + i * unit));
|
|
12665
|
-
return { min: clean(min), max: clean(max), majorUnit: unit, ticks };
|
|
12666
|
-
}
|
|
12667
|
-
}
|
|
12668
|
-
return { min: lo, max: hi, majorUnit: range, ticks: [lo, hi] };
|
|
12669
|
-
}
|
|
12670
|
-
var PERCENT_SCALE = {
|
|
12671
|
-
min: 0,
|
|
12672
|
-
max: 1,
|
|
12673
|
-
majorUnit: 0.1,
|
|
12674
|
-
ticks: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
|
|
12675
|
-
};
|
|
12676
|
-
function formatAxisValue(value, percent = false) {
|
|
12677
|
-
if (percent) return `${clean(value * 100)}%`;
|
|
12678
|
-
const v = clean(value);
|
|
12679
|
-
if (Math.abs(v) >= 1e15 || v !== 0 && Math.abs(v) < 1e-6)
|
|
12680
|
-
return v.toExponential(2).replace("e+", "E+").replace("e-", "E-");
|
|
12681
|
-
const [int = "0", frac] = String(Math.abs(v)).split(".");
|
|
12682
|
-
const grouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
12683
|
-
return `${v < 0 ? "-" : ""}${grouped}${frac ? `.${frac}` : ""}`;
|
|
12684
|
-
}
|
|
12685
|
-
|
|
12686
|
-
// chart/render/theme-palette.ts
|
|
12687
|
-
var THEME_SLOTS = [
|
|
12688
|
-
"lt1",
|
|
12689
|
-
"dk1",
|
|
12690
|
-
"lt2",
|
|
12691
|
-
"dk2",
|
|
12692
|
-
"accent1",
|
|
12693
|
-
"accent2",
|
|
12694
|
-
"accent3",
|
|
12695
|
-
"accent4",
|
|
12696
|
-
"accent5",
|
|
12697
|
-
"accent6",
|
|
12698
|
-
"hlink",
|
|
12699
|
-
"folHlink"
|
|
12700
|
-
];
|
|
12701
|
-
var DEFAULT_THEME_COLORS = [
|
|
12702
|
-
"FFFFFF",
|
|
12703
|
-
"000000",
|
|
12704
|
-
"E7E6E6",
|
|
12705
|
-
"44546A",
|
|
12706
|
-
"4472C4",
|
|
12707
|
-
"ED7D31",
|
|
12708
|
-
"A5A5A5",
|
|
12709
|
-
"FFC000",
|
|
12710
|
-
"5B9BD5",
|
|
12711
|
-
"70AD47",
|
|
12712
|
-
"0563C1",
|
|
12713
|
-
"954F72"
|
|
12714
|
-
];
|
|
12715
|
-
function themeColor(theme, index) {
|
|
12716
|
-
const hex = theme.colors[index] ?? DEFAULT_THEME_COLORS[index];
|
|
12717
|
-
return hex && parseArgbHex(hex) ? hex.replace(/^#/, "") : void 0;
|
|
12718
|
-
}
|
|
12719
|
-
|
|
12720
|
-
// chart/render/chart-colors.ts
|
|
12721
|
-
function chartColorScheme(theme) {
|
|
12722
|
-
const slots = Object.fromEntries(
|
|
12723
|
-
THEME_SLOTS.map((slot, index) => [slot, `#${themeColor(theme, index) ?? "000000"}`])
|
|
12724
|
-
);
|
|
12725
|
-
return {
|
|
12726
|
-
...slots,
|
|
12727
|
-
bg1: slots.lt1,
|
|
12728
|
-
tx1: slots.dk1,
|
|
12729
|
-
bg2: slots.lt2,
|
|
12730
|
-
tx2: slots.dk2
|
|
12731
|
-
};
|
|
12732
|
-
}
|
|
12733
|
-
function autoSeriesColor(theme, index) {
|
|
12734
|
-
const i = Math.max(0, Math.floor(index));
|
|
12735
|
-
return chartPaletteSeriesColor(findChartColorPalette(10), i, i + 1, chartColorScheme(theme));
|
|
12901
|
+
function autoSeriesColor(theme, index) {
|
|
12902
|
+
const i = Math.max(0, Math.floor(index));
|
|
12903
|
+
return chartPaletteSeriesColor(findChartColorPalette(10), i, i + 1, chartColorScheme(theme));
|
|
12736
12904
|
}
|
|
12737
12905
|
|
|
12738
12906
|
// chart/text-inheritance.ts
|
|
@@ -12761,66 +12929,504 @@ function inheritChartText(part, entry, builtIn, root) {
|
|
|
12761
12929
|
const value = root[key] ?? builtIn?.[key];
|
|
12762
12930
|
if (value !== void 0) Object.assign(out, { [key]: value });
|
|
12763
12931
|
}
|
|
12764
|
-
if (part === "title" && root.fontSize !== void 0) out.fontSize = root.fontSize * 1.2;
|
|
12765
|
-
if (root.textEffectsXml !== void 0) out.textEffectsXml = root.textEffectsXml;
|
|
12766
|
-
return out;
|
|
12932
|
+
if (part === "title" && root.fontSize !== void 0) out.fontSize = root.fontSize * 1.2;
|
|
12933
|
+
if (root.textEffectsXml !== void 0) out.textEffectsXml = root.textEffectsXml;
|
|
12934
|
+
return out;
|
|
12935
|
+
}
|
|
12936
|
+
|
|
12937
|
+
// chart/render/chart-appearance.ts
|
|
12938
|
+
var chartPointsToPixels = (points) => points * EMU_PER_POINT / EMU_PER_PIXEL;
|
|
12939
|
+
function typeface(entry, theme) {
|
|
12940
|
+
const name = entry.typeface;
|
|
12941
|
+
if (name?.startsWith("+mj-")) return theme.majorFont;
|
|
12942
|
+
if (name?.startsWith("+mn-")) return theme.minorFont;
|
|
12943
|
+
return name ?? (entry.fontRef?.index === "major" ? theme.majorFont : entry.fontRef?.index === "minor" ? theme.minorFont : void 0);
|
|
12944
|
+
}
|
|
12945
|
+
function chartAppearance(chart, theme) {
|
|
12946
|
+
const defaults = builtInChartTextStyle(effectiveBuiltInChartStyle(chart.formatting));
|
|
12947
|
+
const entries = {};
|
|
12948
|
+
for (const part of CHART_STYLE_PARTS) {
|
|
12949
|
+
const base = chart.styleDefinition?.entries[part];
|
|
12950
|
+
const direct = chart.formatting?.entries[part];
|
|
12951
|
+
if (!defaults[part] && !base && !direct) continue;
|
|
12952
|
+
const entry = {
|
|
12953
|
+
...inheritChartText(
|
|
12954
|
+
part,
|
|
12955
|
+
{ ...defaults[part], ...base, sourceXml: base?.sourceXml ?? "" },
|
|
12956
|
+
defaults[part],
|
|
12957
|
+
chart.formatting?.textDefaults
|
|
12958
|
+
),
|
|
12959
|
+
...direct,
|
|
12960
|
+
sourceXml: direct?.sourceXml ?? base?.sourceXml ?? ""
|
|
12961
|
+
};
|
|
12962
|
+
if (base?.line || direct?.line) entry.line = { ...base?.line, ...direct?.line };
|
|
12963
|
+
entries[part] = entry;
|
|
12964
|
+
}
|
|
12965
|
+
const scheme = chartColorScheme(theme);
|
|
12966
|
+
const resolve = (color) => resolveDrawingColor(
|
|
12967
|
+
color,
|
|
12968
|
+
{ scheme: (name) => scheme[name] },
|
|
12969
|
+
{ hslRounding: "halfDown", transformOrder: "document" }
|
|
12970
|
+
);
|
|
12971
|
+
const out = resolveChartStyleDefinition(
|
|
12972
|
+
{ entries},
|
|
12973
|
+
(color) => drawingColorCss(resolve(color))
|
|
12974
|
+
) ?? {};
|
|
12975
|
+
for (const part of CHART_STYLE_PARTS) {
|
|
12976
|
+
const entry = entries[part];
|
|
12977
|
+
if (!entry) continue;
|
|
12978
|
+
const family = typeface(entry, theme);
|
|
12979
|
+
const shadow = resolveDrawingShadowXml(entry.textEffectsXml, {
|
|
12980
|
+
scheme: (name) => scheme[name]
|
|
12981
|
+
});
|
|
12982
|
+
if (shadow) (out[part] ??= {}).textShadow = shadow;
|
|
12983
|
+
if (family) (out[part] ??= {}).typeface = family;
|
|
12984
|
+
if (entry.axisVisible !== void 0) (out[part] ??= {}).axisVisible = entry.axisVisible;
|
|
12985
|
+
if (entry.labelsVisible !== void 0) (out[part] ??= {}).labelsVisible = entry.labelsVisible;
|
|
12986
|
+
if (entry.line?.widthEmu === 0) (out[part] ??= {}).lineWidth = 0;
|
|
12987
|
+
if (entry.fill?.kind === "gradient") {
|
|
12988
|
+
(out[part] ??= {}).gradient = resolveChartGradient(entry.fill, resolve);
|
|
12989
|
+
}
|
|
12990
|
+
}
|
|
12991
|
+
return out;
|
|
12992
|
+
}
|
|
12993
|
+
|
|
12994
|
+
// text/css-font-family.ts
|
|
12995
|
+
var FALLBACKS = {
|
|
12996
|
+
calibri: '"Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
12997
|
+
"calibri light": '"Calibri Light", "Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
12998
|
+
cambria: '"Cambria", "Caladea", Georgia, serif',
|
|
12999
|
+
arial: 'Arial, "Liberation Sans", Helvetica, sans-serif',
|
|
13000
|
+
"times new roman": '"Times New Roman", "Liberation Serif", Times, serif',
|
|
13001
|
+
"courier new": '"Courier New", "Liberation Mono", monospace',
|
|
13002
|
+
aptos: '"Aptos", "Calibri", "Carlito", "Segoe UI", sans-serif'
|
|
13003
|
+
};
|
|
13004
|
+
function cssFontFamily(name) {
|
|
13005
|
+
const known = FALLBACKS[name.toLowerCase()];
|
|
13006
|
+
if (known) return known;
|
|
13007
|
+
const quoted = `"${name.replace(/["\\]/g, "")}"`;
|
|
13008
|
+
return `${quoted}, "Calibri", "Carlito", "Segoe UI", sans-serif`;
|
|
13009
|
+
}
|
|
13010
|
+
|
|
13011
|
+
// chart/render/chart-svg-appearance.ts
|
|
13012
|
+
var nextPaintId = 0;
|
|
13013
|
+
function chartGradientPaint(model, width = 1024, height = 768) {
|
|
13014
|
+
const prefix2 = `xlsx-chart-${++nextPaintId}`;
|
|
13015
|
+
const appearance = { ...model.appearance };
|
|
13016
|
+
const defs = [];
|
|
13017
|
+
const shadowPaint = (shadow, suffix) => {
|
|
13018
|
+
const id = `${prefix2}-${suffix}`;
|
|
13019
|
+
const pad = Math.max(4, shadow.blur * 3 + Math.abs(shadow.dx) + Math.abs(shadow.dy));
|
|
13020
|
+
defs.push(
|
|
13021
|
+
`<filter id="${id}" filterUnits="userSpaceOnUse" x="${n(-pad)}" y="${n(-pad)}" width="${n(width + pad * 2)}" height="${n(height + pad * 2)}" color-interpolation-filters="sRGB">${svgDropShadowElement(shadow, { number: n, color: (value) => esc(value) })}</filter>`
|
|
13022
|
+
);
|
|
13023
|
+
return `url(#${id})`;
|
|
13024
|
+
};
|
|
13025
|
+
for (const [part, entry] of Object.entries(appearance)) {
|
|
13026
|
+
if (entry?.textShadow)
|
|
13027
|
+
appearance[part] = {
|
|
13028
|
+
...entry,
|
|
13029
|
+
textShadowFilter: shadowPaint(entry.textShadow, `${part}-text-shadow`)
|
|
13030
|
+
};
|
|
13031
|
+
}
|
|
13032
|
+
const paint2 = (gradient, suffix, bounds) => {
|
|
13033
|
+
const def = buildChartGradientDef(`${prefix2}-${suffix}`, gradient, bounds);
|
|
13034
|
+
defs.push(chartGradientMarkup(def));
|
|
13035
|
+
return `url(#${def.id})`;
|
|
13036
|
+
};
|
|
13037
|
+
for (const part of ["chartArea", "plotArea"]) {
|
|
13038
|
+
const entry = appearance[part];
|
|
13039
|
+
if (!entry?.gradient) continue;
|
|
13040
|
+
if (part === "plotArea" && ["circle", "shape"].includes(entry.gradient.path ?? "")) continue;
|
|
13041
|
+
appearance[part] = {
|
|
13042
|
+
...entry,
|
|
13043
|
+
fillColor: paint2(entry.gradient, part, { width, height, shape: "rect" })
|
|
13044
|
+
};
|
|
13045
|
+
}
|
|
13046
|
+
const series = model.series.map((source, index) => {
|
|
13047
|
+
const view = { ...source };
|
|
13048
|
+
if (source.shadow) view.shadowFilter = shadowPaint(source.shadow, `s${index}-shadow`);
|
|
13049
|
+
const bounds = model.type === "bar" || model.type === "column" ? { width: 1, height: 1, shape: "rect" } : void 0;
|
|
13050
|
+
if (source.gradient) view.color = paint2(source.gradient, `s${index}`, bounds);
|
|
13051
|
+
if (source.pointGradients) {
|
|
13052
|
+
view.pointColors = [...source.pointColors ?? []];
|
|
13053
|
+
for (const [key, gradient] of Object.entries(source.pointGradients))
|
|
13054
|
+
view.pointColors[Number(key)] = paint2(gradient, `s${index}-p${key}`, bounds);
|
|
13055
|
+
}
|
|
13056
|
+
return view;
|
|
13057
|
+
});
|
|
13058
|
+
return defs.length ? { model: { ...model, appearance, series }, defs: `<defs>${defs.join("")}</defs>` } : { model, defs: "" };
|
|
13059
|
+
}
|
|
13060
|
+
function chartTextAttributes(model, part, fallbackSize = FONT_SIZE) {
|
|
13061
|
+
const entry = model.appearance?.[part];
|
|
13062
|
+
return {
|
|
13063
|
+
size: entry?.fontSize === void 0 ? fallbackSize : chartPointsToPixels(entry.fontSize),
|
|
13064
|
+
...entry?.color === void 0 ? {} : { fill: entry.color },
|
|
13065
|
+
...entry?.bold === void 0 ? {} : { weight: entry.bold ? "bold" : "normal" },
|
|
13066
|
+
...entry?.italic === void 0 ? {} : { italic: entry.italic },
|
|
13067
|
+
...entry?.underline === void 0 ? {} : { underline: entry.underline },
|
|
13068
|
+
...entry?.typeface === void 0 ? {} : { family: cssFontFamily(entry.typeface) },
|
|
13069
|
+
...entry?.textShadowFilter === void 0 ? {} : { filter: entry.textShadowFilter }
|
|
13070
|
+
};
|
|
13071
|
+
}
|
|
13072
|
+
function chartStroke(model, part) {
|
|
13073
|
+
const entry = model.appearance?.[part];
|
|
13074
|
+
return {
|
|
13075
|
+
color: entry?.axisVisible === false ? "none" : entry?.lineColor ?? (part === "gridlineMajor" ? GRID_COLOR : AXIS_COLOR),
|
|
13076
|
+
width: entry?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry.lineWidth)
|
|
13077
|
+
};
|
|
13078
|
+
}
|
|
13079
|
+
function chartAreaRect(model, part, area) {
|
|
13080
|
+
if (area.w <= 0 || area.h <= 0) return "";
|
|
13081
|
+
const entry = model.appearance?.[part];
|
|
13082
|
+
let fill = entry?.fillColor ?? (part === "chartArea" ? "#FFFFFF" : "none");
|
|
13083
|
+
let defs = "";
|
|
13084
|
+
if (part !== "chartArea" && entry?.gradient && (part !== "plotArea" || ["circle", "shape"].includes(entry.gradient.path ?? ""))) {
|
|
13085
|
+
const def = buildChartGradientDef(`xlsx-chart-${++nextPaintId}-${part}`, entry.gradient, {
|
|
13086
|
+
width: area.w,
|
|
13087
|
+
height: area.h,
|
|
13088
|
+
shape: "rect"
|
|
13089
|
+
});
|
|
13090
|
+
defs = `<defs>${chartGradientMarkup(def)}</defs>`;
|
|
13091
|
+
fill = `url(#${def.id})`;
|
|
13092
|
+
}
|
|
13093
|
+
const stroke = entry?.lineColor ?? "none";
|
|
13094
|
+
if (fill === "none" && stroke === "none") return "";
|
|
13095
|
+
const width = entry?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry.lineWidth);
|
|
13096
|
+
return `${defs}<rect x="${n(area.x)}" y="${n(area.y)}" width="${n(area.w)}" height="${n(area.h)}" fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${n(width)}" data-chart-part="${part}"/>`;
|
|
13097
|
+
}
|
|
13098
|
+
|
|
13099
|
+
// chart/render/chart-svg-labels.ts
|
|
13100
|
+
var GAP = 3;
|
|
13101
|
+
var LINE = 1.2;
|
|
13102
|
+
var NAMED_COLORS = /^(black|blue|cyan|green|magenta|red|white|yellow)$/iu;
|
|
13103
|
+
function measure(model, label) {
|
|
13104
|
+
const attrs = chartTextAttributes(model, "dataLabel", 10);
|
|
13105
|
+
const size = attrs.size ?? 10;
|
|
13106
|
+
const lines = label.text.split("\n");
|
|
13107
|
+
return {
|
|
13108
|
+
lines,
|
|
13109
|
+
size,
|
|
13110
|
+
w: Math.max(...lines.map((l) => textWidth(l, size))),
|
|
13111
|
+
h: lines.length * size * LINE,
|
|
13112
|
+
attrs
|
|
13113
|
+
};
|
|
13114
|
+
}
|
|
13115
|
+
function draw(m, label, x, y, anchor, out) {
|
|
13116
|
+
const fill = label.color && NAMED_COLORS.test(label.color) ? label.color.toLowerCase() : void 0;
|
|
13117
|
+
m.lines.forEach((line3, k) => {
|
|
13118
|
+
const lineY = y - m.h / 2 + (k + 0.5) * m.size * LINE + m.size * 0.35;
|
|
13119
|
+
out.push(text(x, lineY, line3, { ...m.attrs, ...fill ? { fill } : {}, anchor }));
|
|
13120
|
+
});
|
|
13121
|
+
}
|
|
13122
|
+
function barLabels(model, marks, out) {
|
|
13123
|
+
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
13124
|
+
for (const mark of marks) {
|
|
13125
|
+
const label = mark.series.labels?.[mark.index];
|
|
13126
|
+
if (!label) continue;
|
|
13127
|
+
const m = measure(model, label);
|
|
13128
|
+
let position = label.position ?? (stacked ? "ctr" : "outEnd");
|
|
13129
|
+
if (stacked && position === "outEnd") position = "ctr";
|
|
13130
|
+
const cx = mark.x + mark.w / 2;
|
|
13131
|
+
const cy = mark.y + mark.h / 2;
|
|
13132
|
+
if (model.horizontal) {
|
|
13133
|
+
const end = mark.negative ? mark.x : mark.x + mark.w;
|
|
13134
|
+
const base = mark.negative ? mark.x + mark.w : mark.x;
|
|
13135
|
+
const dir2 = mark.negative ? -1 : 1;
|
|
13136
|
+
const side = (at, outward) => [
|
|
13137
|
+
at + (outward ? dir2 : -dir2) * GAP,
|
|
13138
|
+
(outward ? dir2 : -dir2) > 0 ? "start" : "end"
|
|
13139
|
+
];
|
|
13140
|
+
const [x, anchor] = position === "ctr" ? [cx, "middle"] : position === "inEnd" ? side(end, false) : position === "inBase" ? side(base, true) : side(end, true);
|
|
13141
|
+
draw(m, label, x, cy, anchor, out);
|
|
13142
|
+
continue;
|
|
13143
|
+
}
|
|
13144
|
+
const top = mark.negative ? mark.y + mark.h : mark.y;
|
|
13145
|
+
const bottom = mark.negative ? mark.y : mark.y + mark.h;
|
|
13146
|
+
const dir = mark.negative ? 1 : -1;
|
|
13147
|
+
const y = position === "ctr" ? cy : position === "inEnd" ? top - dir * (GAP + m.h / 2) : position === "inBase" ? bottom + dir * (GAP + m.h / 2) : top + dir * (GAP + m.h / 2);
|
|
13148
|
+
draw(m, label, cx, y, "middle", out);
|
|
13149
|
+
}
|
|
13150
|
+
}
|
|
13151
|
+
function pointLabels(model, marks, out) {
|
|
13152
|
+
for (const mark of marks) {
|
|
13153
|
+
const label = mark.series.labels?.[mark.index];
|
|
13154
|
+
if (!label) continue;
|
|
13155
|
+
const m = measure(model, label);
|
|
13156
|
+
const reach = mark.radius + GAP;
|
|
13157
|
+
switch (model.type === "area" ? "ctr" : label.position ?? "r") {
|
|
13158
|
+
case "ctr":
|
|
13159
|
+
draw(m, label, mark.x, mark.y, "middle", out);
|
|
13160
|
+
break;
|
|
13161
|
+
case "t":
|
|
13162
|
+
draw(m, label, mark.x, mark.y - reach - m.h / 2, "middle", out);
|
|
13163
|
+
break;
|
|
13164
|
+
case "b":
|
|
13165
|
+
draw(m, label, mark.x, mark.y + reach + m.h / 2, "middle", out);
|
|
13166
|
+
break;
|
|
13167
|
+
case "l":
|
|
13168
|
+
draw(m, label, mark.x - reach, mark.y, "end", out);
|
|
13169
|
+
break;
|
|
13170
|
+
default:
|
|
13171
|
+
draw(m, label, mark.x + reach, mark.y, "start", out);
|
|
13172
|
+
}
|
|
13173
|
+
}
|
|
13174
|
+
}
|
|
13175
|
+
function sliceLabels(model, marks, out) {
|
|
13176
|
+
for (const mark of marks) {
|
|
13177
|
+
const label = mark.series.labels?.[mark.index];
|
|
13178
|
+
if (!label) continue;
|
|
13179
|
+
const m = measure(model, label);
|
|
13180
|
+
const mid = (mark.start + mark.end) / 2;
|
|
13181
|
+
const ux = Math.sin(mid);
|
|
13182
|
+
const uy = -Math.cos(mid);
|
|
13183
|
+
const place2 = (radius) => [
|
|
13184
|
+
mark.cx + radius * ux,
|
|
13185
|
+
mark.cy + radius * uy
|
|
13186
|
+
];
|
|
13187
|
+
const position = model.type === "doughnut" ? "ctr" : label.position ?? "bestFit";
|
|
13188
|
+
let x;
|
|
13189
|
+
let y;
|
|
13190
|
+
if (position === "ctr") [x, y] = place2(mark.inner + (mark.outer - mark.inner) / 2);
|
|
13191
|
+
else if (position === "inEnd") {
|
|
13192
|
+
const extent = Math.abs(ux) * m.w / 2 + Math.abs(uy) * m.h / 2;
|
|
13193
|
+
[x, y] = place2(Math.max(0, mark.outer - GAP - extent));
|
|
13194
|
+
} else if (position === "outEnd") {
|
|
13195
|
+
const extent = Math.abs(ux) * m.w / 2 + Math.abs(uy) * m.h / 2;
|
|
13196
|
+
[x, y] = place2(mark.outer + GAP + extent);
|
|
13197
|
+
} else {
|
|
13198
|
+
const placed2 = placeBestFitLabel(
|
|
13199
|
+
{
|
|
13200
|
+
cx: mark.cx,
|
|
13201
|
+
cy: mark.cy,
|
|
13202
|
+
outerR: mark.outer,
|
|
13203
|
+
startAngle: mark.start - Math.PI / 2,
|
|
13204
|
+
endAngle: mark.end - Math.PI / 2
|
|
13205
|
+
},
|
|
13206
|
+
m.w,
|
|
13207
|
+
m.h
|
|
13208
|
+
);
|
|
13209
|
+
x = placed2.x;
|
|
13210
|
+
y = placed2.y;
|
|
13211
|
+
}
|
|
13212
|
+
draw(m, label, x, y, "middle", out);
|
|
13213
|
+
}
|
|
13214
|
+
}
|
|
13215
|
+
function hasOutsideLabels(model) {
|
|
13216
|
+
return model.series.some(
|
|
13217
|
+
(s) => s.labels?.some(
|
|
13218
|
+
(l) => l !== void 0 && ["bestFit", "outEnd"].includes(l.position ?? "bestFit")
|
|
13219
|
+
)
|
|
13220
|
+
);
|
|
13221
|
+
}
|
|
13222
|
+
|
|
13223
|
+
// chart/render/chart-svg-bars.ts
|
|
13224
|
+
function barLayout(model, frame2) {
|
|
13225
|
+
const count = Math.max(1, model.series.length);
|
|
13226
|
+
const geometry = clusteredBarGeometry(frame2.bandSize, count, chartBarSpacing(model));
|
|
13227
|
+
const barSize = geometry.singleBarWidth;
|
|
13228
|
+
const offset = (si) => model.horizontal ? geometry.clusterWidth / 2 - barSize - si * geometry.step : -geometry.clusterWidth / 2 + si * geometry.step;
|
|
13229
|
+
return { barSize, offset };
|
|
13230
|
+
}
|
|
13231
|
+
function bars(model, frame2, out, values) {
|
|
13232
|
+
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
13233
|
+
const { barSize, offset: barOffset } = barLayout(model, frame2);
|
|
13234
|
+
const base = frame2.value(0);
|
|
13235
|
+
const pos = new Array(model.categories.length).fill(0);
|
|
13236
|
+
const neg = new Array(model.categories.length).fill(0);
|
|
13237
|
+
const marks = [];
|
|
13238
|
+
model.series.forEach((s, si) => {
|
|
13239
|
+
values[si]?.forEach((v, i) => {
|
|
13240
|
+
if (v === null || i >= model.categories.length) return;
|
|
13241
|
+
let from = 0;
|
|
13242
|
+
let to = v;
|
|
13243
|
+
if (stacked) {
|
|
13244
|
+
const acc = v >= 0 ? pos : neg;
|
|
13245
|
+
from = acc[i] ?? 0;
|
|
13246
|
+
to = from + v;
|
|
13247
|
+
acc[i] = to;
|
|
13248
|
+
}
|
|
13249
|
+
const a = stacked ? frame2.value(from) : base;
|
|
13250
|
+
const b = frame2.value(to);
|
|
13251
|
+
const offset = barOffset(si);
|
|
13252
|
+
const center = frame2.band(i);
|
|
13253
|
+
const width = model.horizontal ? Math.abs(b - a) : barSize;
|
|
13254
|
+
const height = model.horizontal ? barSize : Math.abs(b - a);
|
|
13255
|
+
let color = s.pointColors?.[i] ?? s.color;
|
|
13256
|
+
const gradient = s.pointGradients?.[i] ?? (s.pointColors?.[i] === void 0 ? s.gradient : void 0);
|
|
13257
|
+
if (gradient && (gradient.path === "circle" || gradient.path === "shape")) {
|
|
13258
|
+
const baseId = color.match(/^url\(#(.+)\)$/)?.[1];
|
|
13259
|
+
if (baseId) {
|
|
13260
|
+
const id = baseId.replace(/(-s\d+(?:-p\d+)?)$/, `-mark${i}$1`);
|
|
13261
|
+
const def = buildChartGradientDef(id, gradient, {
|
|
13262
|
+
width: Number(n(width)),
|
|
13263
|
+
height: Number(n(height)),
|
|
13264
|
+
shape: "rect"
|
|
13265
|
+
});
|
|
13266
|
+
out.push(`<defs>${chartGradientMarkup(def)}</defs>`);
|
|
13267
|
+
color = `url(#${id})`;
|
|
13268
|
+
}
|
|
13269
|
+
}
|
|
13270
|
+
out.push(`<g data-chart-series="${si}" data-chart-point="${i}">`);
|
|
13271
|
+
const box = model.horizontal ? { x: Math.min(a, b), y: center + offset, w: Math.abs(b - a), h: barSize } : { x: center + offset, y: Math.min(a, b), w: barSize, h: Math.abs(b - a) };
|
|
13272
|
+
out.push(rect2(box.x, box.y, box.w, box.h, color, s.shadowFilter));
|
|
13273
|
+
out.push("</g>");
|
|
13274
|
+
marks.push({ series: s, index: i, ...box, negative: v < 0 });
|
|
13275
|
+
});
|
|
13276
|
+
});
|
|
13277
|
+
barLabels(model, marks, out);
|
|
13278
|
+
}
|
|
13279
|
+
|
|
13280
|
+
// chart/render/chart-svg-analysis.ts
|
|
13281
|
+
var DASHES = {
|
|
13282
|
+
dot: [1, 3],
|
|
13283
|
+
dash: [4, 3],
|
|
13284
|
+
lgDash: [8, 3],
|
|
13285
|
+
dashDot: [4, 3, 1, 3],
|
|
13286
|
+
lgDashDot: [8, 3, 1, 3],
|
|
13287
|
+
lgDashDotDot: [8, 3, 1, 3, 1, 3],
|
|
13288
|
+
sysDash: [3, 1],
|
|
13289
|
+
sysDot: [1, 1],
|
|
13290
|
+
sysDashDot: [3, 1, 1, 1],
|
|
13291
|
+
sysDashDotDot: [3, 1, 1, 1, 1, 1]
|
|
13292
|
+
};
|
|
13293
|
+
var CAP = 4;
|
|
13294
|
+
function strokeAttributes(stroke) {
|
|
13295
|
+
const pattern = stroke.dash ? DASHES[stroke.dash] : void 0;
|
|
13296
|
+
const dash = pattern ? ` stroke-dasharray="${pattern.map((step) => n(step * stroke.width)).join(" ")}"` : "";
|
|
13297
|
+
return `stroke="${esc(stroke.color)}" stroke-width="${n(stroke.width)}"${dash}`;
|
|
13298
|
+
}
|
|
13299
|
+
var segment = (x1, y1, x2, y2, stroke) => `<line x1="${n(x1)}" y1="${n(y1)}" x2="${n(x2)}" y2="${n(y2)}" ${stroke}/>`;
|
|
13300
|
+
function trendlines(series, si, xs, ys, plane, out) {
|
|
13301
|
+
for (const trendline of series.trendlines ?? []) {
|
|
13302
|
+
const fit2 = fitChartTrendline(trendline.fit, xs, ys);
|
|
13303
|
+
if (fit2.points.length < 2) continue;
|
|
13304
|
+
const points = fit2.points.map(({ x, y }) => plane(x, y).map(n).join(",")).join(" ");
|
|
13305
|
+
out.push(
|
|
13306
|
+
`<polyline points="${points}" fill="none" ${strokeAttributes(trendline.stroke)} data-chart-part="trendline" data-chart-series="${si}"/>`
|
|
13307
|
+
);
|
|
13308
|
+
}
|
|
13309
|
+
}
|
|
13310
|
+
function errorBar(bars2, at, values, plane, out) {
|
|
13311
|
+
const stroke = strokeAttributes(bars2.stroke);
|
|
13312
|
+
for (const side of ["plus", "minus"]) {
|
|
13313
|
+
if (bars2.barType !== side && bars2.barType !== "both") continue;
|
|
13314
|
+
const amount = chartErrorBarAmount(bars2.amount, values, at.displayIndex, at.sourceIndex, side);
|
|
13315
|
+
const sign = side === "plus" ? 1 : -1;
|
|
13316
|
+
const [x1, y1] = plane(at.x, at.y);
|
|
13317
|
+
const [x2, y2] = bars2.direction === "x" ? plane(at.x + sign * amount, at.y) : plane(at.x, at.y + sign * amount);
|
|
13318
|
+
out.push(segment(x1, y1, x2, y2, stroke));
|
|
13319
|
+
if (!bars2.endCap) continue;
|
|
13320
|
+
if (x1 === x2) out.push(segment(x2 - CAP, y2, x2 + CAP, y2, stroke));
|
|
13321
|
+
else out.push(segment(x2, y2 - CAP, x2, y2 + CAP, stroke));
|
|
13322
|
+
}
|
|
13323
|
+
}
|
|
13324
|
+
function plottedPoints(series, xOf) {
|
|
13325
|
+
return series.values.flatMap((y, index) => {
|
|
13326
|
+
const x = xOf(index);
|
|
13327
|
+
return y === null || x === null ? [] : [{ x, y, index }];
|
|
13328
|
+
});
|
|
13329
|
+
}
|
|
13330
|
+
function seriesAnalysis(series, si, xOf, plane, barPlane, categoryAxis, out) {
|
|
13331
|
+
const points = plottedPoints(series, xOf);
|
|
13332
|
+
const xs = points.map((p) => p.x);
|
|
13333
|
+
const ys = points.map((p) => p.y);
|
|
13334
|
+
trendlines(series, si, xs, ys, plane, out);
|
|
13335
|
+
for (const bars2 of series.errorBars ?? []) {
|
|
13336
|
+
if (categoryAxis && bars2.direction === "x") continue;
|
|
13337
|
+
const values = bars2.direction === "x" ? xs : ys;
|
|
13338
|
+
points.forEach(
|
|
13339
|
+
(p, displayIndex) => errorBar(bars2, { x: p.x, y: p.y, displayIndex, sourceIndex: p.index }, values, barPlane, out)
|
|
13340
|
+
);
|
|
13341
|
+
}
|
|
13342
|
+
}
|
|
13343
|
+
function categoryAnalysis(model, frame2, out) {
|
|
13344
|
+
if (model.grouping === "stacked" || model.grouping === "percentStacked") return;
|
|
13345
|
+
const plane = (x, y) => model.horizontal ? [frame2.value(y), frame2.band(x - 1)] : [frame2.band(x - 1), frame2.value(y)];
|
|
13346
|
+
const barred = model.type === "bar" || model.type === "column";
|
|
13347
|
+
const layout = barred ? barLayout(model, frame2) : void 0;
|
|
13348
|
+
model.series.forEach((series, si) => {
|
|
13349
|
+
if (!series.trendlines && !series.errorBars) return;
|
|
13350
|
+
const shift = layout ? layout.offset(si) + layout.barSize / 2 : 0;
|
|
13351
|
+
const barPlane = (x, y) => {
|
|
13352
|
+
const [px, py] = plane(x, y);
|
|
13353
|
+
return model.horizontal ? [px, py + shift] : [px + shift, py];
|
|
13354
|
+
};
|
|
13355
|
+
seriesAnalysis(series, si, (i) => i + 1, plane, barPlane, true, out);
|
|
13356
|
+
});
|
|
13357
|
+
}
|
|
13358
|
+
function scatterAnalysis(model, px, py, out) {
|
|
13359
|
+
const plane = (x, y) => [px(x), py(y)];
|
|
13360
|
+
model.series.forEach((series, si) => {
|
|
13361
|
+
if (!series.trendlines && !series.errorBars) return;
|
|
13362
|
+
seriesAnalysis(series, si, (i) => series.xValues?.[i] ?? null, plane, plane, false, out);
|
|
13363
|
+
});
|
|
12767
13364
|
}
|
|
12768
13365
|
|
|
12769
|
-
// chart/render/chart-
|
|
12770
|
-
var
|
|
12771
|
-
function
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
13366
|
+
// chart/render/chart-scale.ts
|
|
13367
|
+
var clean = (n2) => Number(n2.toPrecision(12));
|
|
13368
|
+
function* units(raw) {
|
|
13369
|
+
let exp = Math.floor(Math.log10(raw)) - 1;
|
|
13370
|
+
for (; ; ) {
|
|
13371
|
+
const base = 10 ** exp;
|
|
13372
|
+
for (const m of [1, 2, 5]) yield clean(m * base);
|
|
13373
|
+
exp++;
|
|
13374
|
+
}
|
|
12776
13375
|
}
|
|
12777
|
-
function
|
|
12778
|
-
const
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
if (
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
),
|
|
12791
|
-
...direct,
|
|
12792
|
-
sourceXml: direct?.sourceXml ?? base?.sourceXml ?? ""
|
|
12793
|
-
};
|
|
12794
|
-
if (base?.line || direct?.line) entry.line = { ...base?.line, ...direct?.line };
|
|
12795
|
-
entries[part] = entry;
|
|
13376
|
+
function niceScale(dataMin, dataMax, options = {}) {
|
|
13377
|
+
const maxIntervals = Math.max(1, options.maxIntervals ?? 10);
|
|
13378
|
+
let lo = Number.isFinite(dataMin) ? dataMin : 0;
|
|
13379
|
+
let hi = Number.isFinite(dataMax) ? dataMax : 0;
|
|
13380
|
+
if (lo > hi) [lo, hi] = [hi, lo];
|
|
13381
|
+
if (lo === hi) {
|
|
13382
|
+
if (lo === 0) hi = 1;
|
|
13383
|
+
else if (options.noZero) {
|
|
13384
|
+
const pad = Math.abs(lo) * 0.1 || 1;
|
|
13385
|
+
lo -= pad;
|
|
13386
|
+
hi += pad;
|
|
13387
|
+
} else if (lo > 0) lo = 0;
|
|
13388
|
+
else hi = 0;
|
|
12796
13389
|
}
|
|
12797
|
-
|
|
12798
|
-
|
|
12799
|
-
|
|
12800
|
-
|
|
12801
|
-
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
) ?? {};
|
|
12807
|
-
for (const part of CHART_STYLE_PARTS) {
|
|
12808
|
-
const entry = entries[part];
|
|
12809
|
-
if (!entry) continue;
|
|
12810
|
-
const family = typeface(entry, theme);
|
|
12811
|
-
const shadow = resolveDrawingShadowXml(entry.textEffectsXml, {
|
|
12812
|
-
scheme: (name) => scheme[name]
|
|
12813
|
-
});
|
|
12814
|
-
if (shadow) (out[part] ??= {}).textShadow = shadow;
|
|
12815
|
-
if (family) (out[part] ??= {}).typeface = family;
|
|
12816
|
-
if (entry.axisVisible !== void 0) (out[part] ??= {}).axisVisible = entry.axisVisible;
|
|
12817
|
-
if (entry.labelsVisible !== void 0) (out[part] ??= {}).labelsVisible = entry.labelsVisible;
|
|
12818
|
-
if (entry.line?.widthEmu === 0) (out[part] ??= {}).lineWidth = 0;
|
|
12819
|
-
if (entry.fill?.kind === "gradient") {
|
|
12820
|
-
(out[part] ??= {}).gradient = resolveChartGradient(entry.fill, resolve);
|
|
13390
|
+
let fixedLo = false;
|
|
13391
|
+
let fixedHi = false;
|
|
13392
|
+
if (!options.noZero) {
|
|
13393
|
+
if (lo >= 0 && hi - lo >= hi / 6) {
|
|
13394
|
+
lo = 0;
|
|
13395
|
+
fixedLo = true;
|
|
13396
|
+
} else if (hi <= 0 && hi - lo >= -lo / 6) {
|
|
13397
|
+
hi = 0;
|
|
13398
|
+
fixedHi = true;
|
|
12821
13399
|
}
|
|
12822
13400
|
}
|
|
12823
|
-
|
|
13401
|
+
const range = hi - lo;
|
|
13402
|
+
const top = fixedHi ? hi : hi + range * 0.05;
|
|
13403
|
+
const bottom = fixedLo ? lo : lo - range * 0.05;
|
|
13404
|
+
for (const unit of units(range / maxIntervals)) {
|
|
13405
|
+
const min = fixedLo ? lo : Math.floor(clean(bottom / unit)) * unit;
|
|
13406
|
+
const max = fixedHi ? hi : Math.ceil(clean(top / unit)) * unit;
|
|
13407
|
+
const intervals = Math.round((max - min) / unit);
|
|
13408
|
+
if (intervals <= maxIntervals && intervals > 0) {
|
|
13409
|
+
const ticks = [];
|
|
13410
|
+
for (let i = 0; i <= intervals; i++) ticks.push(clean(min + i * unit));
|
|
13411
|
+
return { min: clean(min), max: clean(max), majorUnit: unit, ticks };
|
|
13412
|
+
}
|
|
13413
|
+
}
|
|
13414
|
+
return { min: lo, max: hi, majorUnit: range, ticks: [lo, hi] };
|
|
13415
|
+
}
|
|
13416
|
+
var PERCENT_SCALE = {
|
|
13417
|
+
min: 0,
|
|
13418
|
+
max: 1,
|
|
13419
|
+
majorUnit: 0.1,
|
|
13420
|
+
ticks: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
|
|
13421
|
+
};
|
|
13422
|
+
function formatAxisValue(value, percent = false) {
|
|
13423
|
+
if (percent) return `${clean(value * 100)}%`;
|
|
13424
|
+
const v = clean(value);
|
|
13425
|
+
if (Math.abs(v) >= 1e15 || v !== 0 && Math.abs(v) < 1e-6)
|
|
13426
|
+
return v.toExponential(2).replace("e+", "E+").replace("e-", "E-");
|
|
13427
|
+
const [int = "0", frac] = String(Math.abs(v)).split(".");
|
|
13428
|
+
const grouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
13429
|
+
return `${v < 0 ? "-" : ""}${grouped}${frac ? `.${frac}` : ""}`;
|
|
12824
13430
|
}
|
|
12825
13431
|
|
|
12826
13432
|
// chart/render/chart-view-analysis.ts
|
|
@@ -13079,12 +13685,70 @@ function chartTitleText(chart, theme) {
|
|
|
13079
13685
|
};
|
|
13080
13686
|
}
|
|
13081
13687
|
|
|
13688
|
+
// chart/render/chart-view-labels.ts
|
|
13689
|
+
function labelsOf(source, view, categories, numberFormat) {
|
|
13690
|
+
const { chart, series, points } = source;
|
|
13691
|
+
if ((series?.deleted ?? chart?.deleted) === true) return void 0;
|
|
13692
|
+
const percentBase = view.values.reduce(
|
|
13693
|
+
(sum, v) => sum + (v === null ? 0 : Math.abs(v)),
|
|
13694
|
+
0
|
|
13695
|
+
);
|
|
13696
|
+
const out = [];
|
|
13697
|
+
let any = false;
|
|
13698
|
+
view.values.forEach((value, i) => {
|
|
13699
|
+
const point = points?.[i];
|
|
13700
|
+
if (value === null || point?.deleted === true) return;
|
|
13701
|
+
const position = point?.position ?? series?.position ?? chart?.position;
|
|
13702
|
+
const x = view.xValues?.[i];
|
|
13703
|
+
const category = x === void 0 || x === null ? categories[i] : formatAxisValue(x);
|
|
13704
|
+
let built;
|
|
13705
|
+
if (point?.text !== void 0) built = { text: point.text };
|
|
13706
|
+
else {
|
|
13707
|
+
const flags = resolveDataLabelFlags({
|
|
13708
|
+
...point ? { point } : {},
|
|
13709
|
+
...series ? { series } : {},
|
|
13710
|
+
...chart ? { chart } : {}
|
|
13711
|
+
});
|
|
13712
|
+
built = composeDataLabelText({
|
|
13713
|
+
flags,
|
|
13714
|
+
seriesName: view.name,
|
|
13715
|
+
category,
|
|
13716
|
+
value,
|
|
13717
|
+
numberFormat: point?.numberFormat ?? series?.numberFormat ?? chart?.numberFormat ?? numberFormat,
|
|
13718
|
+
percentBase,
|
|
13719
|
+
bubbleSize: view.sizes?.[i] ?? void 0,
|
|
13720
|
+
formatValue: (v) => formatAxisValue(v),
|
|
13721
|
+
formatBubbleSize: (size) => formatAxisValue(size)
|
|
13722
|
+
});
|
|
13723
|
+
}
|
|
13724
|
+
if (!built) return;
|
|
13725
|
+
any = true;
|
|
13726
|
+
out[i] = {
|
|
13727
|
+
text: built.text,
|
|
13728
|
+
...position ? { position } : {},
|
|
13729
|
+
...built.color ? { color: built.color } : {}
|
|
13730
|
+
};
|
|
13731
|
+
});
|
|
13732
|
+
return any ? out : void 0;
|
|
13733
|
+
}
|
|
13734
|
+
function applyDataLabels(model, sources, extra) {
|
|
13735
|
+
const apply = (source, view) => {
|
|
13736
|
+
if (!source?.dataLabels) return;
|
|
13737
|
+
const labels = labelsOf(source.dataLabels, view, model.categories, source.numberFormat);
|
|
13738
|
+
if (labels) view.labels = labels;
|
|
13739
|
+
};
|
|
13740
|
+
model.series.forEach((view, i) => apply(sources[i], view));
|
|
13741
|
+
model.extraGroups?.forEach(
|
|
13742
|
+
(group2, g) => group2.series.forEach((view, i) => apply(extra[g]?.series[i], view))
|
|
13743
|
+
);
|
|
13744
|
+
}
|
|
13745
|
+
|
|
13082
13746
|
// chart/render/chart-view-ex.ts
|
|
13083
13747
|
function groupsAxis(groups, categories) {
|
|
13084
13748
|
let min = Infinity;
|
|
13085
13749
|
let max = -Infinity;
|
|
13086
|
-
for (const
|
|
13087
|
-
const extent = valueExtent(
|
|
13750
|
+
for (const group2 of groups) {
|
|
13751
|
+
const extent = valueExtent(group2.type, group2.grouping, group2.series, categories);
|
|
13088
13752
|
min = Math.min(min, extent.min);
|
|
13089
13753
|
max = Math.max(max, extent.max);
|
|
13090
13754
|
}
|
|
@@ -13093,17 +13757,17 @@ function groupsAxis(groups, categories) {
|
|
|
13093
13757
|
function chartExtraView(chart, model, ctx, total, categoriesOf) {
|
|
13094
13758
|
let index = chart.series.length;
|
|
13095
13759
|
const groups = [];
|
|
13096
|
-
for (const
|
|
13097
|
-
const series =
|
|
13760
|
+
for (const group2 of chart.extraGroups ?? []) {
|
|
13761
|
+
const series = group2.series.map((s) => seriesView(ctx, s, index++, total, categoriesOf));
|
|
13098
13762
|
const view = {
|
|
13099
|
-
type:
|
|
13100
|
-
grouping:
|
|
13763
|
+
type: group2.chartType,
|
|
13764
|
+
grouping: group2.grouping ?? (group2.chartType === "column" ? "clustered" : "standard"),
|
|
13101
13765
|
series,
|
|
13102
|
-
secondary:
|
|
13766
|
+
secondary: group2.secondary
|
|
13103
13767
|
};
|
|
13104
|
-
if (
|
|
13105
|
-
if (
|
|
13106
|
-
if (
|
|
13768
|
+
if (group2.chartType === "stock") view.stock = stockView(group2.stock, ctx);
|
|
13769
|
+
if (group2.barGapWidth !== void 0) view.barGapWidth = group2.barGapWidth;
|
|
13770
|
+
if (group2.barOverlap !== void 0) view.barOverlap = group2.barOverlap;
|
|
13107
13771
|
groups.push(view);
|
|
13108
13772
|
}
|
|
13109
13773
|
if (!groups.length) return;
|
|
@@ -13120,8 +13784,8 @@ function chartExtraAxes(model) {
|
|
|
13120
13784
|
const own2 = valueExtent(model.type, model.grouping, model.series, count);
|
|
13121
13785
|
let min = own2.min;
|
|
13122
13786
|
let max = own2.max;
|
|
13123
|
-
for (const
|
|
13124
|
-
const extent = valueExtent(
|
|
13787
|
+
for (const group2 of shared) {
|
|
13788
|
+
const extent = valueExtent(group2.type, group2.grouping, group2.series, count);
|
|
13125
13789
|
min = Math.min(min, extent.min);
|
|
13126
13790
|
max = Math.max(max, extent.max);
|
|
13127
13791
|
}
|
|
@@ -13264,115 +13928,11 @@ function chartSummaryView(chart, theme, options = {}) {
|
|
|
13264
13928
|
chartExtraView(chart, model, ctx, total, collect);
|
|
13265
13929
|
if (type === "waterfall") waterfallView(chart, model, ctx);
|
|
13266
13930
|
else if (!byPoint) model.valueAxis = valueAxis(model);
|
|
13931
|
+
applyDataLabels(model, chart.series, extra);
|
|
13267
13932
|
chartExtraAxes(model);
|
|
13268
13933
|
return model;
|
|
13269
13934
|
}
|
|
13270
13935
|
|
|
13271
|
-
// text/css-font-family.ts
|
|
13272
|
-
var FALLBACKS = {
|
|
13273
|
-
calibri: '"Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
13274
|
-
"calibri light": '"Calibri Light", "Calibri", "Carlito", "Segoe UI", Arial, sans-serif',
|
|
13275
|
-
cambria: '"Cambria", "Caladea", Georgia, serif',
|
|
13276
|
-
arial: 'Arial, "Liberation Sans", Helvetica, sans-serif',
|
|
13277
|
-
"times new roman": '"Times New Roman", "Liberation Serif", Times, serif',
|
|
13278
|
-
"courier new": '"Courier New", "Liberation Mono", monospace',
|
|
13279
|
-
aptos: '"Aptos", "Calibri", "Carlito", "Segoe UI", sans-serif'
|
|
13280
|
-
};
|
|
13281
|
-
function cssFontFamily(name) {
|
|
13282
|
-
const known = FALLBACKS[name.toLowerCase()];
|
|
13283
|
-
if (known) return known;
|
|
13284
|
-
const quoted = `"${name.replace(/["\\]/g, "")}"`;
|
|
13285
|
-
return `${quoted}, "Calibri", "Carlito", "Segoe UI", sans-serif`;
|
|
13286
|
-
}
|
|
13287
|
-
|
|
13288
|
-
// chart/render/chart-svg-appearance.ts
|
|
13289
|
-
var nextPaintId = 0;
|
|
13290
|
-
function chartGradientPaint(model, width = 1024, height = 768) {
|
|
13291
|
-
const prefix2 = `xlsx-chart-${++nextPaintId}`;
|
|
13292
|
-
const appearance = { ...model.appearance };
|
|
13293
|
-
const defs = [];
|
|
13294
|
-
const shadowPaint = (shadow, suffix) => {
|
|
13295
|
-
const id = `${prefix2}-${suffix}`;
|
|
13296
|
-
const pad = Math.max(4, shadow.blur * 3 + Math.abs(shadow.dx) + Math.abs(shadow.dy));
|
|
13297
|
-
defs.push(
|
|
13298
|
-
`<filter id="${id}" filterUnits="userSpaceOnUse" x="${n(-pad)}" y="${n(-pad)}" width="${n(width + pad * 2)}" height="${n(height + pad * 2)}" color-interpolation-filters="sRGB">${svgDropShadowElement(shadow, { number: n, color: (value) => esc(value) })}</filter>`
|
|
13299
|
-
);
|
|
13300
|
-
return `url(#${id})`;
|
|
13301
|
-
};
|
|
13302
|
-
for (const [part, entry] of Object.entries(appearance)) {
|
|
13303
|
-
if (entry?.textShadow)
|
|
13304
|
-
appearance[part] = {
|
|
13305
|
-
...entry,
|
|
13306
|
-
textShadowFilter: shadowPaint(entry.textShadow, `${part}-text-shadow`)
|
|
13307
|
-
};
|
|
13308
|
-
}
|
|
13309
|
-
const paint2 = (gradient, suffix, bounds) => {
|
|
13310
|
-
const def = buildChartGradientDef(`${prefix2}-${suffix}`, gradient, bounds);
|
|
13311
|
-
defs.push(chartGradientMarkup(def));
|
|
13312
|
-
return `url(#${def.id})`;
|
|
13313
|
-
};
|
|
13314
|
-
for (const part of ["chartArea", "plotArea"]) {
|
|
13315
|
-
const entry = appearance[part];
|
|
13316
|
-
if (!entry?.gradient) continue;
|
|
13317
|
-
if (part === "plotArea" && ["circle", "shape"].includes(entry.gradient.path ?? "")) continue;
|
|
13318
|
-
appearance[part] = {
|
|
13319
|
-
...entry,
|
|
13320
|
-
fillColor: paint2(entry.gradient, part, { width, height, shape: "rect" })
|
|
13321
|
-
};
|
|
13322
|
-
}
|
|
13323
|
-
const series = model.series.map((source, index) => {
|
|
13324
|
-
const view = { ...source };
|
|
13325
|
-
if (source.shadow) view.shadowFilter = shadowPaint(source.shadow, `s${index}-shadow`);
|
|
13326
|
-
const bounds = model.type === "bar" || model.type === "column" ? { width: 1, height: 1, shape: "rect" } : void 0;
|
|
13327
|
-
if (source.gradient) view.color = paint2(source.gradient, `s${index}`, bounds);
|
|
13328
|
-
if (source.pointGradients) {
|
|
13329
|
-
view.pointColors = [...source.pointColors ?? []];
|
|
13330
|
-
for (const [key, gradient] of Object.entries(source.pointGradients))
|
|
13331
|
-
view.pointColors[Number(key)] = paint2(gradient, `s${index}-p${key}`, bounds);
|
|
13332
|
-
}
|
|
13333
|
-
return view;
|
|
13334
|
-
});
|
|
13335
|
-
return defs.length ? { model: { ...model, appearance, series }, defs: `<defs>${defs.join("")}</defs>` } : { model, defs: "" };
|
|
13336
|
-
}
|
|
13337
|
-
function chartTextAttributes(model, part, fallbackSize = FONT_SIZE) {
|
|
13338
|
-
const entry = model.appearance?.[part];
|
|
13339
|
-
return {
|
|
13340
|
-
size: entry?.fontSize === void 0 ? fallbackSize : chartPointsToPixels(entry.fontSize),
|
|
13341
|
-
...entry?.color === void 0 ? {} : { fill: entry.color },
|
|
13342
|
-
...entry?.bold === void 0 ? {} : { weight: entry.bold ? "bold" : "normal" },
|
|
13343
|
-
...entry?.italic === void 0 ? {} : { italic: entry.italic },
|
|
13344
|
-
...entry?.underline === void 0 ? {} : { underline: entry.underline },
|
|
13345
|
-
...entry?.typeface === void 0 ? {} : { family: cssFontFamily(entry.typeface) },
|
|
13346
|
-
...entry?.textShadowFilter === void 0 ? {} : { filter: entry.textShadowFilter }
|
|
13347
|
-
};
|
|
13348
|
-
}
|
|
13349
|
-
function chartStroke(model, part) {
|
|
13350
|
-
const entry = model.appearance?.[part];
|
|
13351
|
-
return {
|
|
13352
|
-
color: entry?.axisVisible === false ? "none" : entry?.lineColor ?? (part === "gridlineMajor" ? GRID_COLOR : AXIS_COLOR),
|
|
13353
|
-
width: entry?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry.lineWidth)
|
|
13354
|
-
};
|
|
13355
|
-
}
|
|
13356
|
-
function chartAreaRect(model, part, area) {
|
|
13357
|
-
if (area.w <= 0 || area.h <= 0) return "";
|
|
13358
|
-
const entry = model.appearance?.[part];
|
|
13359
|
-
let fill = entry?.fillColor ?? (part === "chartArea" ? "#FFFFFF" : "none");
|
|
13360
|
-
let defs = "";
|
|
13361
|
-
if (part !== "chartArea" && entry?.gradient && (part !== "plotArea" || ["circle", "shape"].includes(entry.gradient.path ?? ""))) {
|
|
13362
|
-
const def = buildChartGradientDef(`xlsx-chart-${++nextPaintId}-${part}`, entry.gradient, {
|
|
13363
|
-
width: area.w,
|
|
13364
|
-
height: area.h,
|
|
13365
|
-
shape: "rect"
|
|
13366
|
-
});
|
|
13367
|
-
defs = `<defs>${chartGradientMarkup(def)}</defs>`;
|
|
13368
|
-
fill = `url(#${def.id})`;
|
|
13369
|
-
}
|
|
13370
|
-
const stroke = entry?.lineColor ?? "none";
|
|
13371
|
-
if (fill === "none" && stroke === "none") return "";
|
|
13372
|
-
const width = entry?.lineWidth === void 0 ? 1 : chartPointsToPixels(entry.lineWidth);
|
|
13373
|
-
return `${defs}<rect x="${n(area.x)}" y="${n(area.y)}" width="${n(area.w)}" height="${n(area.h)}" fill="${esc(fill)}" stroke="${esc(stroke)}" stroke-width="${n(width)}" data-chart-part="${part}"/>`;
|
|
13374
|
-
}
|
|
13375
|
-
|
|
13376
13936
|
// chart/render/chart-svg-cartesian.ts
|
|
13377
13937
|
function cartesianAxes(model, area, out) {
|
|
13378
13938
|
const scale = model.valueAxis;
|
|
@@ -13491,6 +14051,7 @@ function linesAndAreas(model, frame2, out) {
|
|
|
13491
14051
|
const stacked = model.grouping === "stacked" || model.grouping === "percentStacked";
|
|
13492
14052
|
const acc = new Array(model.categories.length).fill(0);
|
|
13493
14053
|
const area = model.type === "area";
|
|
14054
|
+
const marks = [];
|
|
13494
14055
|
const layers = [];
|
|
13495
14056
|
model.series.forEach((s, si) => {
|
|
13496
14057
|
const points = [];
|
|
@@ -13505,6 +14066,13 @@ function linesAndAreas(model, frame2, out) {
|
|
|
13505
14066
|
const top = below2 + (v ?? 0);
|
|
13506
14067
|
if (stacked) acc[i] = top;
|
|
13507
14068
|
points.push([frame2.band(i), frame2.value(top)]);
|
|
14069
|
+
marks.push({
|
|
14070
|
+
series: s,
|
|
14071
|
+
index: i,
|
|
14072
|
+
x: frame2.band(i),
|
|
14073
|
+
y: frame2.value(top),
|
|
14074
|
+
radius: area ? 0 : 3
|
|
14075
|
+
});
|
|
13508
14076
|
lower.push([frame2.band(i), frame2.value(below2)]);
|
|
13509
14077
|
});
|
|
13510
14078
|
layers.push({
|
|
@@ -13537,6 +14105,7 @@ function linesAndAreas(model, frame2, out) {
|
|
|
13537
14105
|
if (!Number.isNaN(x))
|
|
13538
14106
|
out.push(`<circle cx="${n(x)}" cy="${n(y)}" r="2.5" fill="${color}"${filter}/>`);
|
|
13539
14107
|
}
|
|
14108
|
+
pointLabels(model, marks, out);
|
|
13540
14109
|
}
|
|
13541
14110
|
|
|
13542
14111
|
// chart/render/chart-svg-xy.ts
|
|
@@ -13606,6 +14175,7 @@ function scatter(model, area, out) {
|
|
|
13606
14175
|
line2(plot.x, plot.y + plot.h, plot.x + plot.w, plot.y + plot.h, xAxis.color, xAxis.width)
|
|
13607
14176
|
);
|
|
13608
14177
|
out.push(line2(plot.x, plot.y, plot.x, plot.y + plot.h, yAxis.color, yAxis.width));
|
|
14178
|
+
const marks = [];
|
|
13609
14179
|
for (const [si, s] of model.series.entries())
|
|
13610
14180
|
s.values.forEach((v, i) => {
|
|
13611
14181
|
const x = s.xValues?.[i] ?? null;
|
|
@@ -13614,14 +14184,17 @@ function scatter(model, area, out) {
|
|
|
13614
14184
|
const fill = s.pointColors?.[i] ?? s.color;
|
|
13615
14185
|
if (!bubble) {
|
|
13616
14186
|
out.push(`<circle cx="${n(px(x))}" cy="${n(py(v))}" r="3" fill="${fill}"${filter}/>`);
|
|
14187
|
+
marks.push({ series: s, index: i, x: px(x), y: py(v), radius: 3 });
|
|
13617
14188
|
return;
|
|
13618
14189
|
}
|
|
13619
14190
|
const r = radiusOf(s.sizes?.[i] ?? void 0);
|
|
13620
14191
|
if (r === void 0) return;
|
|
14192
|
+
marks.push({ series: s, index: i, x: px(x), y: py(v), radius: r });
|
|
13621
14193
|
out.push(
|
|
13622
14194
|
`<circle cx="${n(px(x))}" cy="${n(py(v))}" r="${n(r)}" fill="${fill}" fill-opacity="0.6" data-chart-series="${si}" data-chart-point="${i}"${filter}/>`
|
|
13623
14195
|
);
|
|
13624
14196
|
});
|
|
14197
|
+
pointLabels(model, marks, out);
|
|
13625
14198
|
scatterAnalysis(model, px, py, out);
|
|
13626
14199
|
}
|
|
13627
14200
|
|
|
@@ -13738,21 +14311,21 @@ function cartesianSvg(model, area) {
|
|
|
13738
14311
|
return out.join("");
|
|
13739
14312
|
}
|
|
13740
14313
|
const layers = [{ model, frame: frame2 }];
|
|
13741
|
-
for (const
|
|
14314
|
+
for (const group2 of model.extraGroups ?? []) {
|
|
13742
14315
|
const grouped = {
|
|
13743
14316
|
...model,
|
|
13744
|
-
type:
|
|
13745
|
-
grouping:
|
|
13746
|
-
series:
|
|
14317
|
+
type: group2.type,
|
|
14318
|
+
grouping: group2.grouping,
|
|
14319
|
+
series: group2.series,
|
|
13747
14320
|
horizontal: false
|
|
13748
14321
|
};
|
|
13749
|
-
if (
|
|
14322
|
+
if (group2.stock) grouped.stock = group2.stock;
|
|
13750
14323
|
else delete grouped.stock;
|
|
13751
|
-
if (
|
|
14324
|
+
if (group2.barGapWidth !== void 0) grouped.barGapWidth = group2.barGapWidth;
|
|
13752
14325
|
else delete grouped.barGapWidth;
|
|
13753
|
-
if (
|
|
14326
|
+
if (group2.barOverlap !== void 0) grouped.barOverlap = group2.barOverlap;
|
|
13754
14327
|
else delete grouped.barOverlap;
|
|
13755
|
-
const value =
|
|
14328
|
+
const value = group2.secondary && frame2.secondary ? frame2.secondary : frame2.value;
|
|
13756
14329
|
layers.push({ model: grouped, frame: { ...frame2, value } });
|
|
13757
14330
|
}
|
|
13758
14331
|
layers.map((layer, order) => ({ layer, order })).sort(
|
|
@@ -13786,7 +14359,9 @@ function pieSvg(model, area) {
|
|
|
13786
14359
|
const out = [chartAreaRect(model, "plotArea", area)];
|
|
13787
14360
|
const cx = area.x + area.w / 2;
|
|
13788
14361
|
const cy = area.y + area.h / 2;
|
|
13789
|
-
const
|
|
14362
|
+
const margin = hasOutsideLabels(model) ? Math.min(area.w, area.h) * 0.12 : 0;
|
|
14363
|
+
const radius = Math.max(1, Math.min(area.w, area.h) / 2 - 4 - margin);
|
|
14364
|
+
const slices = [];
|
|
13790
14365
|
const rings = model.type === "doughnut" ? model.series : model.series.slice(0, 1);
|
|
13791
14366
|
const hole = model.type === "doughnut" ? radius * 0.5 : 0;
|
|
13792
14367
|
const ringSize = (radius - hole) / Math.max(1, rings.length);
|
|
@@ -13803,9 +14378,20 @@ function pieSvg(model, area) {
|
|
|
13803
14378
|
out.push(
|
|
13804
14379
|
`<path d="${slicePath(cx, cy, outer, inner, angle, angle + sweep)}" fill="${color}" stroke="#FFFFFF" stroke-width="1"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
|
|
13805
14380
|
);
|
|
14381
|
+
slices.push({
|
|
14382
|
+
series: s,
|
|
14383
|
+
index: i,
|
|
14384
|
+
cx,
|
|
14385
|
+
cy,
|
|
14386
|
+
outer,
|
|
14387
|
+
inner,
|
|
14388
|
+
start: angle,
|
|
14389
|
+
end: angle + sweep
|
|
14390
|
+
});
|
|
13806
14391
|
angle += sweep;
|
|
13807
14392
|
});
|
|
13808
14393
|
});
|
|
14394
|
+
sliceLabels(model, slices, out);
|
|
13809
14395
|
return out.join("");
|
|
13810
14396
|
}
|
|
13811
14397
|
function radarSvg(model, area) {
|
|
@@ -13851,12 +14437,16 @@ function radarSvg(model, area) {
|
|
|
13851
14437
|
})
|
|
13852
14438
|
);
|
|
13853
14439
|
});
|
|
14440
|
+
const marks = [];
|
|
13854
14441
|
for (const s of model.series) {
|
|
13855
|
-
const
|
|
14442
|
+
const vertices = s.values.slice(0, count).map((v, i) => polar(cx, cy, r(v ?? scale.min), angle(i)));
|
|
14443
|
+
vertices.forEach(([x, y], i) => marks.push({ series: s, index: i, x, y, radius: 3 }));
|
|
14444
|
+
const points = vertices.map(([x, y]) => `${n(x)},${n(y)}`).join(" ");
|
|
13856
14445
|
out.push(
|
|
13857
14446
|
`<polygon points="${points}" fill="none" stroke="${s.color}" stroke-width="2"${s.shadowFilter ? ` filter="${s.shadowFilter}"` : ""}/>`
|
|
13858
14447
|
);
|
|
13859
14448
|
}
|
|
14449
|
+
pointLabels(model, marks, out);
|
|
13860
14450
|
return out.join("");
|
|
13861
14451
|
}
|
|
13862
14452
|
|
|
@@ -14108,17 +14698,17 @@ function automaticLegend(model, area, out, options, bounds) {
|
|
|
14108
14698
|
|
|
14109
14699
|
// text/wrap-styled-runs.ts
|
|
14110
14700
|
var graphemes = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
14111
|
-
function wrapStyledRuns(runs, maxWidth,
|
|
14701
|
+
function wrapStyledRuns(runs, maxWidth, measure2, options = {}) {
|
|
14112
14702
|
const groups = [];
|
|
14113
14703
|
for (const [source, run] of runs.entries()) {
|
|
14114
14704
|
for (const token of run.text.split(/(\r\n|[\r\n]|[ \t]+)/u).filter(Boolean)) {
|
|
14115
14705
|
const kind = /^[\r\n]+$/u.test(token) ? "break" : /^[ \t]+$/u.test(token) ? "space" : "word";
|
|
14116
|
-
let
|
|
14117
|
-
if (!
|
|
14118
|
-
|
|
14119
|
-
groups.push(
|
|
14706
|
+
let group2 = groups.at(-1);
|
|
14707
|
+
if (!group2 || group2.kind !== kind || kind === "break") {
|
|
14708
|
+
group2 = { kind, pieces: [] };
|
|
14709
|
+
groups.push(group2);
|
|
14120
14710
|
}
|
|
14121
|
-
if (kind !== "break")
|
|
14711
|
+
if (kind !== "break") group2.pieces.push({ run, source, text: token });
|
|
14122
14712
|
}
|
|
14123
14713
|
}
|
|
14124
14714
|
const merged = (left, right) => {
|
|
@@ -14131,7 +14721,7 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
|
|
|
14131
14721
|
return result2;
|
|
14132
14722
|
};
|
|
14133
14723
|
const width = (pieces) => pieces.reduce((sum, piece) => {
|
|
14134
|
-
const advance =
|
|
14724
|
+
const advance = measure2(piece.text, piece.run);
|
|
14135
14725
|
return sum + (Number.isFinite(advance) && advance >= 0 ? advance : 0);
|
|
14136
14726
|
}, 0);
|
|
14137
14727
|
const result = [];
|
|
@@ -14142,29 +14732,29 @@ function wrapStyledRuns(runs, maxWidth, measure, options = {}) {
|
|
|
14142
14732
|
line3 = [];
|
|
14143
14733
|
spaces = [];
|
|
14144
14734
|
};
|
|
14145
|
-
for (const
|
|
14146
|
-
if (
|
|
14735
|
+
for (const group2 of groups) {
|
|
14736
|
+
if (group2.kind === "break") {
|
|
14147
14737
|
flush();
|
|
14148
14738
|
continue;
|
|
14149
14739
|
}
|
|
14150
|
-
if (
|
|
14151
|
-
spaces =
|
|
14740
|
+
if (group2.kind === "space") {
|
|
14741
|
+
spaces = group2.pieces;
|
|
14152
14742
|
continue;
|
|
14153
14743
|
}
|
|
14154
14744
|
const separator = line3.length ? spaces : [];
|
|
14155
|
-
const wordWidth = width(
|
|
14156
|
-
if (line3.length && width(merged(line3, [...separator, ...
|
|
14745
|
+
const wordWidth = width(group2.pieces);
|
|
14746
|
+
if (line3.length && width(merged(line3, [...separator, ...group2.pieces])) > maxWidth) flush();
|
|
14157
14747
|
else line3 = merged(line3, separator);
|
|
14158
14748
|
spaces = [];
|
|
14159
14749
|
if (options.breakWords && wordWidth > maxWidth) {
|
|
14160
|
-
for (const piece of
|
|
14750
|
+
for (const piece of group2.pieces) {
|
|
14161
14751
|
for (const { segment: segment2 } of graphemes.segment(piece.text)) {
|
|
14162
14752
|
const next = { ...piece, text: segment2 };
|
|
14163
14753
|
if (line3.length && width(merged(line3, [next])) > maxWidth) flush();
|
|
14164
14754
|
line3 = merged(line3, [next]);
|
|
14165
14755
|
}
|
|
14166
14756
|
}
|
|
14167
|
-
} else line3 = merged(line3,
|
|
14757
|
+
} else line3 = merged(line3, group2.pieces);
|
|
14168
14758
|
}
|
|
14169
14759
|
flush();
|
|
14170
14760
|
return result;
|
|
@@ -14521,11 +15111,11 @@ function parseDirectParagraphProperties(props) {
|
|
|
14521
15111
|
|
|
14522
15112
|
// docx/numbering-parse.ts
|
|
14523
15113
|
var own = (map, key) => Object.prototype.hasOwnProperty.call(map, key) ? map[key] : void 0;
|
|
14524
|
-
function resolveNumberingLevel(catalog, numId,
|
|
15114
|
+
function resolveNumberingLevel(catalog, numId, level2) {
|
|
14525
15115
|
const num = own(catalog.nums, numId);
|
|
14526
15116
|
if (!num) return void 0;
|
|
14527
|
-
const override = num.levelOverrides?.[
|
|
14528
|
-
const sourceAbstract = own(catalog.abstractNums, num.abstractNumId)?.levels[
|
|
15117
|
+
const override = num.levelOverrides?.[level2];
|
|
15118
|
+
const sourceAbstract = own(catalog.abstractNums, num.abstractNumId)?.levels[level2];
|
|
14529
15119
|
const abstract = sourceAbstract?.startWasOmitted && sourceAbstract.start === 1 ? { ...sourceAbstract, start: 0 } : sourceAbstract;
|
|
14530
15120
|
let base = override?.lvl ?? abstract;
|
|
14531
15121
|
if (!base) return void 0;
|
|
@@ -14924,10 +15514,10 @@ function resolveParagraphNumbering(paragraph, styleCatalog, numberingCatalog) {
|
|
|
14924
15514
|
const inherited = resolveStyleNumbering(paragraph.style, styleCatalog);
|
|
14925
15515
|
if (!inherited || inherited.numId <= 0) return void 0;
|
|
14926
15516
|
if (numberingCatalog && paragraph.style && styleCatalog.styles[paragraph.style]) {
|
|
14927
|
-
for (let
|
|
14928
|
-
const definition = resolveNumberingLevel(numberingCatalog, String(inherited.numId),
|
|
15517
|
+
for (let level2 = 0; level2 < 9; level2++) {
|
|
15518
|
+
const definition = resolveNumberingLevel(numberingCatalog, String(inherited.numId), level2);
|
|
14929
15519
|
if (definition?.paragraphStyleId === paragraph.style)
|
|
14930
|
-
return { numId: inherited.numId, level };
|
|
15520
|
+
return { numId: inherited.numId, level: level2 };
|
|
14931
15521
|
}
|
|
14932
15522
|
}
|
|
14933
15523
|
return inherited;
|
|
@@ -14960,23 +15550,23 @@ var NumberingCounters = class {
|
|
|
14960
15550
|
return started;
|
|
14961
15551
|
}
|
|
14962
15552
|
/** Advances one level and resets deeper counters according to their resolved restart rules. */
|
|
14963
|
-
advance(numId,
|
|
15553
|
+
advance(numId, level2, def, catalog) {
|
|
14964
15554
|
const counts = this.forNum(numId);
|
|
14965
15555
|
const started = this.startedLevels(numId);
|
|
14966
|
-
const next = started.has(
|
|
14967
|
-
counts.set(
|
|
14968
|
-
started.add(
|
|
15556
|
+
const next = started.has(level2) ? (counts.get(level2) ?? def.start) + 1 : def.start;
|
|
15557
|
+
counts.set(level2, next);
|
|
15558
|
+
started.add(level2);
|
|
14969
15559
|
for (const deeper of [...started]) {
|
|
14970
|
-
if (deeper <=
|
|
15560
|
+
if (deeper <= level2) continue;
|
|
14971
15561
|
const deeperDef = resolveNumberingLevel(catalog, numId, deeper);
|
|
14972
15562
|
const restart = deeperDef?.lvlRestart;
|
|
14973
15563
|
if (restart === 0) continue;
|
|
14974
15564
|
const trigger = restart !== void 0 && restart > 0 && restart <= deeper ? restart - 1 : deeper - 1;
|
|
14975
|
-
if (
|
|
15565
|
+
if (level2 > trigger) continue;
|
|
14976
15566
|
counts.delete(deeper);
|
|
14977
15567
|
started.delete(deeper);
|
|
14978
15568
|
}
|
|
14979
|
-
for (let ancestor = 0; ancestor <
|
|
15569
|
+
for (let ancestor = 0; ancestor < level2; ancestor++) {
|
|
14980
15570
|
if (started.has(ancestor)) continue;
|
|
14981
15571
|
const ancestorDef = resolveNumberingLevel(catalog, numId, ancestor);
|
|
14982
15572
|
if (!ancestorDef) continue;
|
|
@@ -14986,14 +15576,14 @@ var NumberingCounters = class {
|
|
|
14986
15576
|
return next;
|
|
14987
15577
|
}
|
|
14988
15578
|
/** Current value for an ancestor placeholder, defaulting to its own start when never instantiated. */
|
|
14989
|
-
current(numId,
|
|
14990
|
-
return this.forNum(numId).get(
|
|
15579
|
+
current(numId, level2, start) {
|
|
15580
|
+
return this.forNum(numId).get(level2) ?? start;
|
|
14991
15581
|
}
|
|
14992
15582
|
};
|
|
14993
|
-
function substituteLvlText(lvlText, numId,
|
|
15583
|
+
function substituteLvlText(lvlText, numId, level2, catalog, counters, forceDecimal) {
|
|
14994
15584
|
return lvlText.replace(/%([1-9])/g, (match, digit) => {
|
|
14995
15585
|
const ancestorLevel = Number(digit) - 1;
|
|
14996
|
-
if (ancestorLevel >
|
|
15586
|
+
if (ancestorLevel > level2) return match;
|
|
14997
15587
|
const ancestorDef = resolveNumberingLevel(catalog, numId, ancestorLevel);
|
|
14998
15588
|
const start = ancestorDef?.start ?? 1;
|
|
14999
15589
|
const value = counters.current(numId, ancestorLevel, start);
|
|
@@ -15010,15 +15600,15 @@ function computeListLabels(model) {
|
|
|
15010
15600
|
const numbering = resolveParagraphNumbering(paragraph, model.paragraphStyles, catalog);
|
|
15011
15601
|
if (!numbering) continue;
|
|
15012
15602
|
const numId = String(numbering.numId);
|
|
15013
|
-
const
|
|
15014
|
-
const def = resolveNumberingLevel(catalog, numId,
|
|
15603
|
+
const level2 = Math.min(8, Math.max(0, numbering.level));
|
|
15604
|
+
const def = resolveNumberingLevel(catalog, numId, level2);
|
|
15015
15605
|
if (!def) continue;
|
|
15016
15606
|
if (def.numFmt === "none") continue;
|
|
15017
|
-
counters.advance(numId,
|
|
15018
|
-
const text2 = def.numFmt === "bullet" ? def.lvlText : substituteLvlText(def.lvlText, numId,
|
|
15607
|
+
counters.advance(numId, level2, def, catalog);
|
|
15608
|
+
const text2 = def.numFmt === "bullet" ? def.lvlText : substituteLvlText(def.lvlText, numId, level2, catalog, counters, Boolean(def.isLgl));
|
|
15019
15609
|
labels.set(paragraph.id, {
|
|
15020
15610
|
numId,
|
|
15021
|
-
level,
|
|
15611
|
+
level: level2,
|
|
15022
15612
|
text: text2,
|
|
15023
15613
|
suffix: def.suffix ?? "tab",
|
|
15024
15614
|
...definedProps({
|
|
@@ -15481,12 +16071,12 @@ function headerFooterSlotForPage(model, page, pageNumber) {
|
|
|
15481
16071
|
return page.pageInSection === 0 && section?.titlePage ? "first" : model.evenAndOddHeaders && pageNumber % 2 === 0 ? "even" : "default";
|
|
15482
16072
|
}
|
|
15483
16073
|
function headerFooterForPage(model, page, pageNumber, kind) {
|
|
15484
|
-
const
|
|
15485
|
-
const section =
|
|
16074
|
+
const sections2 = model.sections ?? [];
|
|
16075
|
+
const section = sections2[page.sectionIndex];
|
|
15486
16076
|
if (!section) return void 0;
|
|
15487
16077
|
const slot = headerFooterSlotForPage(model, page, pageNumber);
|
|
15488
16078
|
for (let index = page.sectionIndex; index >= 0; index--) {
|
|
15489
|
-
const content =
|
|
16079
|
+
const content = sections2[index]?.[kind]?.[slot];
|
|
15490
16080
|
if (content) return content;
|
|
15491
16081
|
}
|
|
15492
16082
|
return void 0;
|
|
@@ -17223,11 +17813,11 @@ function completedNoteStoryMinimum(row2, stories, pendingBlocks, available) {
|
|
|
17223
17813
|
for (const [index, cell] of row2.cells.entries()) {
|
|
17224
17814
|
const groups = /* @__PURE__ */ new Map();
|
|
17225
17815
|
for (const box of cell) {
|
|
17226
|
-
const
|
|
17227
|
-
if (
|
|
17228
|
-
const boxes = groups.get(
|
|
17816
|
+
const group2 = stories.get(box.blockId);
|
|
17817
|
+
if (group2 !== void 0) {
|
|
17818
|
+
const boxes = groups.get(group2) ?? [];
|
|
17229
17819
|
boxes.push(box);
|
|
17230
|
-
groups.set(
|
|
17820
|
+
groups.set(group2, boxes);
|
|
17231
17821
|
}
|
|
17232
17822
|
}
|
|
17233
17823
|
for (const boxes of groups.values()) {
|
|
@@ -17293,8 +17883,8 @@ var TableFootnotes = class {
|
|
|
17293
17883
|
for (const cell of row2.cells) {
|
|
17294
17884
|
for (const paragraph of cellParagraphs(cell))
|
|
17295
17885
|
if (paragraph.footnotes?.length) this.paragraphs.set(paragraph.id, paragraph);
|
|
17296
|
-
for (const [id,
|
|
17297
|
-
this.stories.set(id,
|
|
17886
|
+
for (const [id, group2] of (measured ? independentNoteStories(cell) : void 0) ?? []) {
|
|
17887
|
+
this.stories.set(id, group2);
|
|
17298
17888
|
}
|
|
17299
17889
|
}
|
|
17300
17890
|
}
|
|
@@ -17427,11 +18017,11 @@ var TableFootnotes = class {
|
|
|
17427
18017
|
for (const [index, cell] of row2.cells.entries()) {
|
|
17428
18018
|
const groups = /* @__PURE__ */ new Map();
|
|
17429
18019
|
for (const box of cell) {
|
|
17430
|
-
const
|
|
17431
|
-
if (
|
|
17432
|
-
const boxes = groups.get(
|
|
18020
|
+
const group2 = this.stories.get(box.blockId);
|
|
18021
|
+
if (group2 !== void 0) {
|
|
18022
|
+
const boxes = groups.get(group2) ?? [];
|
|
17433
18023
|
boxes.push(box);
|
|
17434
|
-
groups.set(
|
|
18024
|
+
groups.set(group2, boxes);
|
|
17435
18025
|
}
|
|
17436
18026
|
}
|
|
17437
18027
|
for (const boxes of groups.values()) {
|
|
@@ -19955,14 +20545,14 @@ function adaptDocumentModel(model, note = () => {
|
|
|
19955
20545
|
note2.blocks.filter((block) => block.type === "paragraph").map((paragraph) => adaptParagraph(paragraph))
|
|
19956
20546
|
])
|
|
19957
20547
|
) : void 0;
|
|
19958
|
-
const
|
|
20548
|
+
const sections2 = model.sections;
|
|
19959
20549
|
const modernFootnoteSeparator = model.compatibilityMode === 15;
|
|
19960
20550
|
const legacyFootnoteColumns = model.compatibilityMode === 12 || model.compatibilityMode === 14;
|
|
19961
20551
|
if (!modernFootnoteSeparator && !legacyFootnoteColumns && model.sections?.some((section) => section.footnoteColumns !== void 0))
|
|
19962
20552
|
reportOnce(
|
|
19963
20553
|
"Footnote column settings are preserved, but this compatibility mode has not been verified against native Word; Print Layout uses the existing page-wide fallback."
|
|
19964
20554
|
);
|
|
19965
|
-
if (!
|
|
20555
|
+
if (!sections2 || !sections2.length) {
|
|
19966
20556
|
return {
|
|
19967
20557
|
sections: [
|
|
19968
20558
|
{
|
|
@@ -19984,8 +20574,8 @@ function adaptDocumentModel(model, note = () => {
|
|
|
19984
20574
|
}
|
|
19985
20575
|
const indexById = new Map(model.blocks.map((block, index) => [block.id, index]));
|
|
19986
20576
|
let start = 0;
|
|
19987
|
-
const result =
|
|
19988
|
-
const last = index ===
|
|
20577
|
+
const result = sections2.map((section, index) => {
|
|
20578
|
+
const last = index === sections2.length - 1;
|
|
19989
20579
|
const endIndex = last ? blocks.length : (indexById.get(section.endsAtBlockId) ?? start - 1) + 1;
|
|
19990
20580
|
const end = Math.max(start, endIndex);
|
|
19991
20581
|
const slice = blocks.slice(start, end);
|