ooxml-core 0.21.2 → 0.22.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/README.md +3 -4
- package/dist/automation/index.cjs +34 -13
- package/dist/automation/index.mjs +34 -13
- package/dist/chart/index.cjs +242 -0
- package/dist/chart/index.d.ts +5 -0
- package/dist/chart/index.d.ts.map +1 -1
- package/dist/chart/index.mjs +227 -1
- package/dist/chart/pie-best-fit.d.ts +51 -0
- package/dist/chart/pie-best-fit.d.ts.map +1 -0
- package/dist/chart/pie-label-collision.d.ts +48 -0
- package/dist/chart/pie-label-collision.d.ts.map +1 -0
- package/dist/chart/radar-geometry.d.ts +19 -0
- package/dist/chart/radar-geometry.d.ts.map +1 -0
- package/dist/chart/treemap-squarify.d.ts +31 -0
- package/dist/chart/treemap-squarify.d.ts.map +1 -0
- package/dist/chart/trendline-equation.d.ts +39 -0
- package/dist/chart/trendline-equation.d.ts.map +1 -0
- package/dist/collab/index.cjs +6 -1
- package/dist/collab/index.mjs +6 -1
- package/dist/color/contrast.d.ts +18 -0
- package/dist/color/contrast.d.ts.map +1 -0
- package/dist/color/index.cjs +33 -0
- package/dist/color/index.d.ts +2 -0
- package/dist/color/index.d.ts.map +1 -1
- package/dist/color/index.mjs +31 -1
- package/dist/color/unit-rgb.d.ts +21 -0
- package/dist/color/unit-rgb.d.ts.map +1 -0
- package/dist/docx/embedded.cjs +1 -1
- package/dist/docx/embedded.mjs +1 -1
- package/dist/docx/index.cjs +1 -1
- package/dist/docx/index.mjs +1 -1
- package/dist/docx/load/index.cjs +1 -1
- package/dist/docx/load/index.mjs +1 -1
- package/dist/geometry/align-distribute.d.ts +145 -0
- package/dist/geometry/align-distribute.d.ts.map +1 -0
- package/dist/geometry/index.cjs +318 -0
- package/dist/geometry/index.d.ts +2 -0
- package/dist/geometry/index.d.ts.map +1 -1
- package/dist/geometry/index.mjs +307 -1
- package/dist/geometry/snap-guides.d.ts +125 -0
- package/dist/geometry/snap-guides.d.ts.map +1 -0
- package/dist/index.cjs +665 -0
- package/dist/index.mjs +665 -0
- package/dist/pptx/automation/index.cjs +24 -1
- package/dist/pptx/automation/index.d.ts +3 -3
- package/dist/pptx/automation/index.mjs +24 -1
- package/dist/pptx/chunks/{index-JaNVJ6Tf.d.ts → index-D2y7ehZ5.d.ts} +3 -3
- package/dist/pptx/chunks/{index-JaNVJ6Tf.d.ts.map → index-D2y7ehZ5.d.ts.map} +1 -1
- package/dist/pptx/chunks/{index-DHdHU9Qr.d.ts → index-ucqKcqvI.d.ts} +10 -2
- package/dist/pptx/chunks/{index-DHdHU9Qr.d.ts.map → index-ucqKcqvI.d.ts.map} +1 -1
- package/dist/pptx/chunks/{text-operations-DUEhSW5Z.d.ts → text-operations-CR3pUJi-.d.ts} +14 -2
- package/dist/pptx/chunks/text-operations-CR3pUJi-.d.ts.map +1 -0
- package/dist/pptx/cli/index.cjs +23 -0
- package/dist/pptx/cli/index.d.ts +1 -1
- package/dist/pptx/cli/index.mjs +23 -0
- package/dist/pptx/converter/index.d.ts +1 -1
- package/dist/pptx/index.cjs +33 -3
- package/dist/pptx/index.d.ts +3 -3
- package/dist/pptx/index.mjs +33 -3
- package/dist/teams/index.cjs +7 -2
- package/dist/teams/index.mjs +7 -2
- package/dist/text/decimal-tab.d.ts +24 -0
- package/dist/text/decimal-tab.d.ts.map +1 -0
- package/dist/text/index.cjs +72 -0
- package/dist/text/index.d.ts +2 -0
- package/dist/text/index.d.ts.map +1 -1
- package/dist/text/index.mjs +68 -1
- package/dist/text/tab-leader.d.ts +36 -0
- package/dist/text/tab-leader.d.ts.map +1 -0
- package/dist/xlsx/edit/charts.d.ts.map +1 -1
- package/dist/xlsx/edit/clipboard-html-parse.d.ts.map +1 -1
- package/dist/xlsx/index.cjs +33 -12
- package/dist/xlsx/index.mjs +33 -12
- package/dist/xlsx/ui/grid/cell-paint.d.ts.map +1 -1
- package/dist/xlsx/ui/index.cjs +37 -16
- package/dist/xlsx/ui/index.mjs +37 -16
- package/package.json +2 -2
- package/dist/pptx/chunks/text-operations-DUEhSW5Z.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
**Read, edit, validate and write Office Open XML documents in TypeScript.**
|
|
10
10
|
One package, one XML model, every format: Word, PowerPoint, Excel and the shared building blocks beneath them. Visio VSDX parsing and bounded editing are available through `ooxml-core/visio`.
|
|
11
11
|
|
|
12
|
-
[](LICENSE)
|
|
13
12
|
[](https://github.com/ChristopherVR/ooxml/actions/workflows/ci.yml)
|
|
14
13
|
[](CODE_OF_CONDUCT.md)
|
|
15
14
|
|
|
@@ -17,7 +16,7 @@ One package, one XML model, every format: Word, PowerPoint, Excel and the shared
|
|
|
17
16
|
[**Packages and areas**](#features-and-api-one-package-many-areas) ·
|
|
18
17
|
[**Install**](#install) ·
|
|
19
18
|
[**Examples**](#quick-start) ·
|
|
20
|
-
[**Contributing**](CONTRIBUTING.md)
|
|
19
|
+
[**Contributing**](../../CONTRIBUTING.md)
|
|
21
20
|
|
|
22
21
|
</div>
|
|
23
22
|
|
|
@@ -63,7 +62,7 @@ The `chart` subpath provides shared chart data calculations (regression, quartil
|
|
|
63
62
|
blank values and stacked series). The `text` subpath provides script-category
|
|
64
63
|
segmentation primitives. These areas are DOM-free and do not import a product model.
|
|
65
64
|
SVG curve flattening is available from `geometry`. See the
|
|
66
|
-
[PowerPoint reuse audit](docs/pptx-shared-logic-audit.md) for extraction evidence
|
|
65
|
+
[PowerPoint reuse audit](../../docs/pptx-shared-logic-audit.md) for extraction evidence
|
|
67
66
|
and remaining candidates.
|
|
68
67
|
|
|
69
68
|
## Install
|
|
@@ -110,7 +109,7 @@ const part = resolvePartPath('word/document.xml', rels.get('rId5')!.target);
|
|
|
110
109
|
|
|
111
110
|
## Contributing and roadmap
|
|
112
111
|
|
|
113
|
-
`ooxml-core` is developed in the [ChristopherVR/ooxml](https://github.com/ChristopherVR/ooxml) repository, which also holds [`ooxml-ui`](https://www.npmjs.com/package/ooxml-ui), the MCP servers and the Word, Excel, Visio and OpenTeams viewers. Its README covers the repository layout, the development workflow and releases, and the [roadmap](https://github.com/ChristopherVR/ooxml/blob/main/docs/roadmap.md) says what comes next; the working agreements are in [AGENTS.md](AGENTS.md) and [CONTRIBUTING.md](CONTRIBUTING.md), and [PROVENANCE.md](PROVENANCE.md) records where each module came from.
|
|
112
|
+
`ooxml-core` is developed in the [ChristopherVR/ooxml](https://github.com/ChristopherVR/ooxml) repository, which also holds [`ooxml-ui`](https://www.npmjs.com/package/ooxml-ui), the MCP servers and the Word, Excel, Visio and OpenTeams viewers. Its README covers the repository layout, the development workflow and releases, and the [roadmap](https://github.com/ChristopherVR/ooxml/blob/main/docs/roadmap.md) says what comes next; the working agreements are in [AGENTS.md](../../AGENTS.md) and [CONTRIBUTING.md](../../CONTRIBUTING.md), and [PROVENANCE.md](../../PROVENANCE.md) records where each module came from.
|
|
114
113
|
|
|
115
114
|
## License
|
|
116
115
|
|
|
@@ -1404,7 +1404,7 @@ async function applyCoreProperties(zip, next, prior) {
|
|
|
1404
1404
|
await ensureContentTypeOverride(zip, CORE_PATH, CORE_TYPE);
|
|
1405
1405
|
const rels = zip.file("_rels/.rels");
|
|
1406
1406
|
const relsXml = await rels?.async("string") ?? '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
|
|
1407
|
-
if (!relsXml.includes(CORE_REL)) {
|
|
1407
|
+
if (!relsXml.includes(`Type="${CORE_REL}"`)) {
|
|
1408
1408
|
const ids = [...relsXml.matchAll(/Id="rId(\d+)"/g)].map((match2) => Number(match2[1]));
|
|
1409
1409
|
const id = `rId${Math.max(0, ...ids) + 1}`;
|
|
1410
1410
|
zip.file(
|
|
@@ -25586,7 +25586,7 @@ async function saveXlsx(workbook) {
|
|
|
25586
25586
|
|
|
25587
25587
|
// xlsx/edit/context.ts
|
|
25588
25588
|
function sheetAt(workbook, index2) {
|
|
25589
|
-
const sheet = workbook.sheets[index2];
|
|
25589
|
+
const sheet = Number.isInteger(index2) ? workbook.sheets[index2] : void 0;
|
|
25590
25590
|
if (!sheet) throw new RangeError(`No sheet at index ${index2}`);
|
|
25591
25591
|
return sheet;
|
|
25592
25592
|
}
|
|
@@ -26786,9 +26786,27 @@ function stylePatchFromCss(css, inner2) {
|
|
|
26786
26786
|
if (numFmt) patch.numFmt = decodeNumberFormat(numFmt);
|
|
26787
26787
|
return patch;
|
|
26788
26788
|
}
|
|
26789
|
+
function stripTags(markup) {
|
|
26790
|
+
let previous;
|
|
26791
|
+
let text = markup;
|
|
26792
|
+
do {
|
|
26793
|
+
previous = text;
|
|
26794
|
+
text = text.replace(/<!--[\s\S]*?-->/g, "").replace(/<[^<>]*>/g, "");
|
|
26795
|
+
} while (text !== previous);
|
|
26796
|
+
return removeAll(text, ["<!--", "-->"]);
|
|
26797
|
+
}
|
|
26798
|
+
function removeAll(text, tokens2) {
|
|
26799
|
+
let current = text;
|
|
26800
|
+
let previous;
|
|
26801
|
+
do {
|
|
26802
|
+
previous = current;
|
|
26803
|
+
for (const token of tokens2) current = current.split(token).join("");
|
|
26804
|
+
} while (current !== previous);
|
|
26805
|
+
return current;
|
|
26806
|
+
}
|
|
26789
26807
|
function cellText(inner2) {
|
|
26790
26808
|
return decodeEntities(
|
|
26791
|
-
inner2.replace(
|
|
26809
|
+
stripTags(inner2.replace(/<br\s*\/?>/gi, "\0")).replace(/\s+/g, " ").replace(/ ?\u0000 ?/g, "\n")
|
|
26792
26810
|
).replace(/ /g, " ").trim();
|
|
26793
26811
|
}
|
|
26794
26812
|
function parseHtmlTable(html, base) {
|
|
@@ -26796,7 +26814,9 @@ function parseHtmlTable(html, base) {
|
|
|
26796
26814
|
if (table2 === void 0) return void 0;
|
|
26797
26815
|
const classes = /* @__PURE__ */ new Map();
|
|
26798
26816
|
for (const block of html.matchAll(/<style\b[^>]*>([\s\S]*?)<\/style>/gi))
|
|
26799
|
-
for (const rule2 of (block[1] ?? ""
|
|
26817
|
+
for (const rule2 of removeAll(block[1] ?? "", ["<!--", "-->"]).matchAll(
|
|
26818
|
+
/\.([\w-]+)\s*\{([^}]*)\}/g
|
|
26819
|
+
))
|
|
26800
26820
|
classes.set(rule2[1] ?? "", rule2[2] ?? "");
|
|
26801
26821
|
const grid = [];
|
|
26802
26822
|
const taken = /* @__PURE__ */ new Set();
|
|
@@ -27585,7 +27605,7 @@ function setAutoFilter(ctx, s, range) {
|
|
|
27585
27605
|
const old = sheet.autoFilter;
|
|
27586
27606
|
if (old) applyFilter(ctx, sheet, { range: old.range });
|
|
27587
27607
|
if (r) sheet.autoFilter = { range: r };
|
|
27588
|
-
else
|
|
27608
|
+
else Reflect.deleteProperty(sheet, "autoFilter");
|
|
27589
27609
|
},
|
|
27590
27610
|
{ sheet: s, structural: true }
|
|
27591
27611
|
);
|
|
@@ -28647,9 +28667,10 @@ function updateChart(ctx, s, index2, patch) {
|
|
|
28647
28667
|
() => {
|
|
28648
28668
|
const live = sheet.drawings[index2];
|
|
28649
28669
|
for (const [key2, value] of Object.entries(structuredClone(patch))) {
|
|
28650
|
-
if (key2 === "kind" || key2 === "partName") continue;
|
|
28651
|
-
if (
|
|
28652
|
-
|
|
28670
|
+
if (key2 === "kind" || key2 === "partName" || key2 === "__proto__") continue;
|
|
28671
|
+
if (key2 === "constructor" || key2 === "prototype") continue;
|
|
28672
|
+
if (value === void 0) Reflect.deleteProperty(live, key2);
|
|
28673
|
+
else Reflect.set(live, key2, value);
|
|
28653
28674
|
}
|
|
28654
28675
|
},
|
|
28655
28676
|
{ sheet: s }
|
|
@@ -29158,7 +29179,7 @@ function setDefaultColumnWidth(ctx, s, width) {
|
|
|
29158
29179
|
"format",
|
|
29159
29180
|
[{ kind: "sheet", sheet: s }],
|
|
29160
29181
|
() => {
|
|
29161
|
-
if (width === void 0)
|
|
29182
|
+
if (width === void 0) Reflect.deleteProperty(sheet, "defaultColWidth");
|
|
29162
29183
|
else sheet.defaultColWidth = width;
|
|
29163
29184
|
},
|
|
29164
29185
|
{ sheet: s, structural: true }
|
|
@@ -29180,7 +29201,7 @@ function setPageSetup(ctx, s, patch) {
|
|
|
29180
29201
|
() => {
|
|
29181
29202
|
const next = compact2({ ...sheet.pageSetup, ...structuredClone(patch) });
|
|
29182
29203
|
if (Object.keys(next).length) sheet.pageSetup = next;
|
|
29183
|
-
else
|
|
29204
|
+
else Reflect.deleteProperty(sheet, "pageSetup");
|
|
29184
29205
|
},
|
|
29185
29206
|
{ sheet: s }
|
|
29186
29207
|
);
|
|
@@ -29196,7 +29217,7 @@ function setPrintOptions(ctx, s, patch) {
|
|
|
29196
29217
|
for (const key2 of Object.keys(next))
|
|
29197
29218
|
if (!next[key2]) delete next[key2];
|
|
29198
29219
|
if (Object.keys(next).length) sheet.printOptions = next;
|
|
29199
|
-
else
|
|
29220
|
+
else Reflect.deleteProperty(sheet, "printOptions");
|
|
29200
29221
|
sheet.preserved.delete("printOptions");
|
|
29201
29222
|
},
|
|
29202
29223
|
{ sheet: s }
|
|
@@ -29802,7 +29823,7 @@ function setSheetProtection(ctx, s, protection2, password) {
|
|
|
29802
29823
|
[{ kind: "sheet", sheet: s }],
|
|
29803
29824
|
() => {
|
|
29804
29825
|
if (!protection2) {
|
|
29805
|
-
|
|
29826
|
+
Reflect.deleteProperty(sheet, "protection");
|
|
29806
29827
|
return;
|
|
29807
29828
|
}
|
|
29808
29829
|
const next = structuredClone(protection2);
|
|
@@ -30774,7 +30795,7 @@ function setTabColor(ctx, index2, color2) {
|
|
|
30774
30795
|
[{ kind: "sheet", sheet: index2 }],
|
|
30775
30796
|
() => {
|
|
30776
30797
|
if (color2) sheet.tabColor = { ...color2 };
|
|
30777
|
-
else
|
|
30798
|
+
else Reflect.deleteProperty(sheet, "tabColor");
|
|
30778
30799
|
},
|
|
30779
30800
|
{ sheet: index2 }
|
|
30780
30801
|
);
|
|
@@ -1398,7 +1398,7 @@ async function applyCoreProperties(zip, next, prior) {
|
|
|
1398
1398
|
await ensureContentTypeOverride(zip, CORE_PATH, CORE_TYPE);
|
|
1399
1399
|
const rels = zip.file("_rels/.rels");
|
|
1400
1400
|
const relsXml = await rels?.async("string") ?? '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"></Relationships>';
|
|
1401
|
-
if (!relsXml.includes(CORE_REL)) {
|
|
1401
|
+
if (!relsXml.includes(`Type="${CORE_REL}"`)) {
|
|
1402
1402
|
const ids = [...relsXml.matchAll(/Id="rId(\d+)"/g)].map((match2) => Number(match2[1]));
|
|
1403
1403
|
const id = `rId${Math.max(0, ...ids) + 1}`;
|
|
1404
1404
|
zip.file(
|
|
@@ -25580,7 +25580,7 @@ async function saveXlsx(workbook) {
|
|
|
25580
25580
|
|
|
25581
25581
|
// xlsx/edit/context.ts
|
|
25582
25582
|
function sheetAt(workbook, index2) {
|
|
25583
|
-
const sheet = workbook.sheets[index2];
|
|
25583
|
+
const sheet = Number.isInteger(index2) ? workbook.sheets[index2] : void 0;
|
|
25584
25584
|
if (!sheet) throw new RangeError(`No sheet at index ${index2}`);
|
|
25585
25585
|
return sheet;
|
|
25586
25586
|
}
|
|
@@ -26780,9 +26780,27 @@ function stylePatchFromCss(css, inner2) {
|
|
|
26780
26780
|
if (numFmt) patch.numFmt = decodeNumberFormat(numFmt);
|
|
26781
26781
|
return patch;
|
|
26782
26782
|
}
|
|
26783
|
+
function stripTags(markup) {
|
|
26784
|
+
let previous;
|
|
26785
|
+
let text = markup;
|
|
26786
|
+
do {
|
|
26787
|
+
previous = text;
|
|
26788
|
+
text = text.replace(/<!--[\s\S]*?-->/g, "").replace(/<[^<>]*>/g, "");
|
|
26789
|
+
} while (text !== previous);
|
|
26790
|
+
return removeAll(text, ["<!--", "-->"]);
|
|
26791
|
+
}
|
|
26792
|
+
function removeAll(text, tokens2) {
|
|
26793
|
+
let current = text;
|
|
26794
|
+
let previous;
|
|
26795
|
+
do {
|
|
26796
|
+
previous = current;
|
|
26797
|
+
for (const token of tokens2) current = current.split(token).join("");
|
|
26798
|
+
} while (current !== previous);
|
|
26799
|
+
return current;
|
|
26800
|
+
}
|
|
26783
26801
|
function cellText(inner2) {
|
|
26784
26802
|
return decodeEntities(
|
|
26785
|
-
inner2.replace(
|
|
26803
|
+
stripTags(inner2.replace(/<br\s*\/?>/gi, "\0")).replace(/\s+/g, " ").replace(/ ?\u0000 ?/g, "\n")
|
|
26786
26804
|
).replace(/ /g, " ").trim();
|
|
26787
26805
|
}
|
|
26788
26806
|
function parseHtmlTable(html, base) {
|
|
@@ -26790,7 +26808,9 @@ function parseHtmlTable(html, base) {
|
|
|
26790
26808
|
if (table2 === void 0) return void 0;
|
|
26791
26809
|
const classes = /* @__PURE__ */ new Map();
|
|
26792
26810
|
for (const block of html.matchAll(/<style\b[^>]*>([\s\S]*?)<\/style>/gi))
|
|
26793
|
-
for (const rule2 of (block[1] ?? ""
|
|
26811
|
+
for (const rule2 of removeAll(block[1] ?? "", ["<!--", "-->"]).matchAll(
|
|
26812
|
+
/\.([\w-]+)\s*\{([^}]*)\}/g
|
|
26813
|
+
))
|
|
26794
26814
|
classes.set(rule2[1] ?? "", rule2[2] ?? "");
|
|
26795
26815
|
const grid = [];
|
|
26796
26816
|
const taken = /* @__PURE__ */ new Set();
|
|
@@ -27579,7 +27599,7 @@ function setAutoFilter(ctx, s, range) {
|
|
|
27579
27599
|
const old = sheet.autoFilter;
|
|
27580
27600
|
if (old) applyFilter(ctx, sheet, { range: old.range });
|
|
27581
27601
|
if (r) sheet.autoFilter = { range: r };
|
|
27582
|
-
else
|
|
27602
|
+
else Reflect.deleteProperty(sheet, "autoFilter");
|
|
27583
27603
|
},
|
|
27584
27604
|
{ sheet: s, structural: true }
|
|
27585
27605
|
);
|
|
@@ -28641,9 +28661,10 @@ function updateChart(ctx, s, index2, patch) {
|
|
|
28641
28661
|
() => {
|
|
28642
28662
|
const live = sheet.drawings[index2];
|
|
28643
28663
|
for (const [key2, value] of Object.entries(structuredClone(patch))) {
|
|
28644
|
-
if (key2 === "kind" || key2 === "partName") continue;
|
|
28645
|
-
if (
|
|
28646
|
-
|
|
28664
|
+
if (key2 === "kind" || key2 === "partName" || key2 === "__proto__") continue;
|
|
28665
|
+
if (key2 === "constructor" || key2 === "prototype") continue;
|
|
28666
|
+
if (value === void 0) Reflect.deleteProperty(live, key2);
|
|
28667
|
+
else Reflect.set(live, key2, value);
|
|
28647
28668
|
}
|
|
28648
28669
|
},
|
|
28649
28670
|
{ sheet: s }
|
|
@@ -29152,7 +29173,7 @@ function setDefaultColumnWidth(ctx, s, width) {
|
|
|
29152
29173
|
"format",
|
|
29153
29174
|
[{ kind: "sheet", sheet: s }],
|
|
29154
29175
|
() => {
|
|
29155
|
-
if (width === void 0)
|
|
29176
|
+
if (width === void 0) Reflect.deleteProperty(sheet, "defaultColWidth");
|
|
29156
29177
|
else sheet.defaultColWidth = width;
|
|
29157
29178
|
},
|
|
29158
29179
|
{ sheet: s, structural: true }
|
|
@@ -29174,7 +29195,7 @@ function setPageSetup(ctx, s, patch) {
|
|
|
29174
29195
|
() => {
|
|
29175
29196
|
const next = compact2({ ...sheet.pageSetup, ...structuredClone(patch) });
|
|
29176
29197
|
if (Object.keys(next).length) sheet.pageSetup = next;
|
|
29177
|
-
else
|
|
29198
|
+
else Reflect.deleteProperty(sheet, "pageSetup");
|
|
29178
29199
|
},
|
|
29179
29200
|
{ sheet: s }
|
|
29180
29201
|
);
|
|
@@ -29190,7 +29211,7 @@ function setPrintOptions(ctx, s, patch) {
|
|
|
29190
29211
|
for (const key2 of Object.keys(next))
|
|
29191
29212
|
if (!next[key2]) delete next[key2];
|
|
29192
29213
|
if (Object.keys(next).length) sheet.printOptions = next;
|
|
29193
|
-
else
|
|
29214
|
+
else Reflect.deleteProperty(sheet, "printOptions");
|
|
29194
29215
|
sheet.preserved.delete("printOptions");
|
|
29195
29216
|
},
|
|
29196
29217
|
{ sheet: s }
|
|
@@ -29796,7 +29817,7 @@ function setSheetProtection(ctx, s, protection2, password) {
|
|
|
29796
29817
|
[{ kind: "sheet", sheet: s }],
|
|
29797
29818
|
() => {
|
|
29798
29819
|
if (!protection2) {
|
|
29799
|
-
|
|
29820
|
+
Reflect.deleteProperty(sheet, "protection");
|
|
29800
29821
|
return;
|
|
29801
29822
|
}
|
|
29802
29823
|
const next = structuredClone(protection2);
|
|
@@ -30768,7 +30789,7 @@ function setTabColor(ctx, index2, color2) {
|
|
|
30768
30789
|
[{ kind: "sheet", sheet: index2 }],
|
|
30769
30790
|
() => {
|
|
30770
30791
|
if (color2) sheet.tabColor = { ...color2 };
|
|
30771
|
-
else
|
|
30792
|
+
else Reflect.deleteProperty(sheet, "tabColor");
|
|
30772
30793
|
},
|
|
30773
30794
|
{ sheet: index2 }
|
|
30774
30795
|
);
|
package/dist/chart/index.cjs
CHANGED
|
@@ -380,17 +380,259 @@ function aggregateByCategory(values, rawCategories) {
|
|
|
380
380
|
});
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
+
// chart/treemap-squarify.ts
|
|
384
|
+
function worstAspectRatio(areas, side) {
|
|
385
|
+
const sum = areas.reduce((total, area) => total + area, 0);
|
|
386
|
+
const max = Math.max(...areas);
|
|
387
|
+
const min = Math.min(...areas);
|
|
388
|
+
const sideSq = side * side;
|
|
389
|
+
const sumSq = sum * sum;
|
|
390
|
+
return Math.max(sideSq * max / sumSq, sumSq / (sideSq * min));
|
|
391
|
+
}
|
|
392
|
+
function squarify(nodes, box) {
|
|
393
|
+
const sorted = [...nodes].sort((a, b) => b.weight - a.weight);
|
|
394
|
+
const total = sorted.reduce((sum, node) => sum + node.weight, 0);
|
|
395
|
+
const scale = total > 0 ? box.w * box.h / total : box.w * box.h / sorted.length;
|
|
396
|
+
const items = sorted.map((node) => ({ node, area: (total > 0 ? node.weight : 1) * scale }));
|
|
397
|
+
const result = [];
|
|
398
|
+
let rect = { ...box };
|
|
399
|
+
let remaining = items;
|
|
400
|
+
for (let first = remaining[0]; first !== void 0; first = remaining[0]) {
|
|
401
|
+
const side = Math.min(rect.w, rect.h);
|
|
402
|
+
let row = [first];
|
|
403
|
+
let rowAreas = [first.area];
|
|
404
|
+
let worst = worstAspectRatio(rowAreas, side);
|
|
405
|
+
let cursor = 1;
|
|
406
|
+
for (let next = remaining[cursor]; next !== void 0; next = remaining[cursor]) {
|
|
407
|
+
const candidateAreas = [...rowAreas, next.area];
|
|
408
|
+
const candidateWorst = worstAspectRatio(candidateAreas, side);
|
|
409
|
+
if (candidateWorst > worst) {
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
row = [...row, next];
|
|
413
|
+
rowAreas = candidateAreas;
|
|
414
|
+
worst = candidateWorst;
|
|
415
|
+
cursor++;
|
|
416
|
+
}
|
|
417
|
+
const rowTotalArea = rowAreas.reduce((sum, area) => sum + area, 0);
|
|
418
|
+
const thickness = side > 0 ? rowTotalArea / side : 0;
|
|
419
|
+
const layoutVertically = rect.w >= rect.h;
|
|
420
|
+
let offset = layoutVertically ? rect.y : rect.x;
|
|
421
|
+
for (const item of row) {
|
|
422
|
+
const length = thickness > 0 ? item.area / thickness : 0;
|
|
423
|
+
if (layoutVertically) {
|
|
424
|
+
result.push([item.node, { x: rect.x, y: offset, w: thickness, h: length }]);
|
|
425
|
+
} else {
|
|
426
|
+
result.push([item.node, { x: offset, y: rect.y, w: length, h: thickness }]);
|
|
427
|
+
}
|
|
428
|
+
offset += length;
|
|
429
|
+
}
|
|
430
|
+
rect = layoutVertically ? { ...rect, x: rect.x + thickness, w: rect.w - thickness } : { ...rect, y: rect.y + thickness, h: rect.h - thickness };
|
|
431
|
+
remaining = remaining.slice(row.length);
|
|
432
|
+
}
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// chart/trendline-equation.ts
|
|
437
|
+
var SIGNIFICANT_DIGITS = 4;
|
|
438
|
+
function formatTrendlineCoefficient(value) {
|
|
439
|
+
if (!Number.isFinite(value) || value === 0) {
|
|
440
|
+
return "0";
|
|
441
|
+
}
|
|
442
|
+
const rounded = Number(value.toPrecision(SIGNIFICANT_DIGITS));
|
|
443
|
+
return rounded === 0 ? "0" : String(rounded);
|
|
444
|
+
}
|
|
445
|
+
function signedTerm(value) {
|
|
446
|
+
return { sign: value < 0 ? "-" : "+", abs: formatTrendlineCoefficient(Math.abs(value)) };
|
|
447
|
+
}
|
|
448
|
+
function formatLinearEquation(slope, intercept) {
|
|
449
|
+
const { sign, abs } = signedTerm(intercept);
|
|
450
|
+
return `y = ${formatTrendlineCoefficient(slope)}x ${sign} ${abs}`;
|
|
451
|
+
}
|
|
452
|
+
function formatExponentialEquation(a, b) {
|
|
453
|
+
return `y = ${formatTrendlineCoefficient(a)} e^(${formatTrendlineCoefficient(b)}x)`;
|
|
454
|
+
}
|
|
455
|
+
function formatLogarithmicEquation(slope, intercept) {
|
|
456
|
+
const { sign, abs } = signedTerm(intercept);
|
|
457
|
+
return `y = ${formatTrendlineCoefficient(slope)}ln(x) ${sign} ${abs}`;
|
|
458
|
+
}
|
|
459
|
+
function formatPowerEquation(a, b) {
|
|
460
|
+
return `y = ${formatTrendlineCoefficient(a)}x^${formatTrendlineCoefficient(b)}`;
|
|
461
|
+
}
|
|
462
|
+
function formatPolynomialEquation(coeffsAscending) {
|
|
463
|
+
const order = coeffsAscending.length - 1;
|
|
464
|
+
let out = "y = ";
|
|
465
|
+
for (let power = order; power >= 0; power--) {
|
|
466
|
+
const coeff = coeffsAscending[power] ?? 0;
|
|
467
|
+
const { sign, abs } = signedTerm(coeff);
|
|
468
|
+
const variable = power === 0 ? "" : power === 1 ? "x" : `x^${power}`;
|
|
469
|
+
out += power === order ? `${sign === "-" ? "-" : ""}${abs}${variable}` : ` ${sign} ${abs}${variable}`;
|
|
470
|
+
}
|
|
471
|
+
return out;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// chart/radar-geometry.ts
|
|
475
|
+
function radarAngle(index, catCount) {
|
|
476
|
+
const n = Math.max(catCount, 1);
|
|
477
|
+
return Math.PI * 2 * index / n - Math.PI / 2;
|
|
478
|
+
}
|
|
479
|
+
function computeRadarPoints(values, maxVal, radius, cx, cy, catCount) {
|
|
480
|
+
const denom = maxVal > 0 ? maxVal : 1;
|
|
481
|
+
return values.slice(0, Math.max(catCount, 1)).map((val, i) => {
|
|
482
|
+
const angle = radarAngle(i, catCount), r = Math.abs(val) / denom * radius;
|
|
483
|
+
return { x: cx + r * Math.cos(angle), y: cy + r * Math.sin(angle) };
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
function radarRingPoints(cx, cy, rr, catCount) {
|
|
487
|
+
const n = Math.max(catCount, 1);
|
|
488
|
+
return Array.from({ length: n }, (_, i) => {
|
|
489
|
+
const angle = radarAngle(i, n);
|
|
490
|
+
return `${(cx + rr * Math.cos(angle)).toFixed(2)},${(cy + rr * Math.sin(angle)).toFixed(2)}`;
|
|
491
|
+
}).join(" ");
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// chart/pie-best-fit.ts
|
|
495
|
+
var PX_PER_PT = 4 / 3;
|
|
496
|
+
var BEST_FIT_RIM_INSET = 4 * PX_PER_PT;
|
|
497
|
+
var BEST_FIT_EDGE_TOLERANCE = 1.5 * PX_PER_PT;
|
|
498
|
+
var BEST_FIT_OUTSIDE_GAP = 2 * PX_PER_PT;
|
|
499
|
+
function farCorner(x, y, w, h) {
|
|
500
|
+
return Math.hypot(Math.abs(x) + w / 2, Math.abs(y) + h / 2);
|
|
501
|
+
}
|
|
502
|
+
function insideDistance(ux, uy, w, h, limit) {
|
|
503
|
+
if (farCorner(0, 0, w, h) > limit) {
|
|
504
|
+
return void 0;
|
|
505
|
+
}
|
|
506
|
+
let lo = 0;
|
|
507
|
+
let hi = limit;
|
|
508
|
+
for (let i = 0; i < 40; i++) {
|
|
509
|
+
const mid = (lo + hi) / 2;
|
|
510
|
+
if (farCorner(mid * ux, mid * uy, w, h) > limit) {
|
|
511
|
+
hi = mid;
|
|
512
|
+
} else {
|
|
513
|
+
lo = mid;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return lo;
|
|
517
|
+
}
|
|
518
|
+
function edgeOverhang(x, y, w, h, slice) {
|
|
519
|
+
let worst = Number.NEGATIVE_INFINITY;
|
|
520
|
+
const corners = [
|
|
521
|
+
[-w / 2, -h / 2],
|
|
522
|
+
[w / 2, -h / 2],
|
|
523
|
+
[-w / 2, h / 2],
|
|
524
|
+
[w / 2, h / 2]
|
|
525
|
+
];
|
|
526
|
+
for (const [dx, dy] of corners) {
|
|
527
|
+
const px = x + dx;
|
|
528
|
+
const py = y + dy;
|
|
529
|
+
const fromStart = Math.cos(slice.startAngle) * py - Math.sin(slice.startAngle) * px;
|
|
530
|
+
const fromEnd = Math.sin(slice.endAngle) * px - Math.cos(slice.endAngle) * py;
|
|
531
|
+
worst = Math.max(worst, -fromStart, -fromEnd);
|
|
532
|
+
}
|
|
533
|
+
return worst;
|
|
534
|
+
}
|
|
535
|
+
function placeBestFitLabel(slice, w, h) {
|
|
536
|
+
const mid = (slice.startAngle + slice.endAngle) / 2;
|
|
537
|
+
const ux = Math.cos(mid);
|
|
538
|
+
const uy = Math.sin(mid);
|
|
539
|
+
const distance = insideDistance(ux, uy, w, h, slice.outerR - BEST_FIT_RIM_INSET);
|
|
540
|
+
if (distance !== void 0) {
|
|
541
|
+
const x = distance * ux;
|
|
542
|
+
const y = distance * uy;
|
|
543
|
+
const reflex = slice.endAngle - slice.startAngle >= Math.PI;
|
|
544
|
+
if (reflex || edgeOverhang(x, y, w, h, slice) <= BEST_FIT_EDGE_TOLERANCE) {
|
|
545
|
+
return { x: slice.cx + x, y: slice.cy + y, inside: true };
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
const extent = Math.abs(ux) * w / 2 + Math.abs(uy) * h / 2;
|
|
549
|
+
const outside = slice.outerR + BEST_FIT_OUTSIDE_GAP + extent;
|
|
550
|
+
return { x: slice.cx + outside * ux, y: slice.cy + outside * uy, inside: false };
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// chart/pie-label-collision.ts
|
|
554
|
+
var LABEL_COLLISION_GAP = 2;
|
|
555
|
+
function boxDistanceToCentre(box, y, disc) {
|
|
556
|
+
const nearestX = Math.max(box.x - box.w / 2, Math.min(disc.cx, box.x + box.w / 2));
|
|
557
|
+
const nearestY = Math.max(y - box.h / 2, Math.min(disc.cy, y + box.h / 2));
|
|
558
|
+
return Math.hypot(nearestX - disc.cx, nearestY - disc.cy);
|
|
559
|
+
}
|
|
560
|
+
function clearOfDisc(box, y, disc) {
|
|
561
|
+
if (boxDistanceToCentre(box, y, disc) >= disc.r) {
|
|
562
|
+
return 0;
|
|
563
|
+
}
|
|
564
|
+
const sign = box.x >= disc.cx ? 1 : -1;
|
|
565
|
+
let dx = 0;
|
|
566
|
+
while (dx < disc.r * 2 && boxDistanceToCentre({ ...box, x: box.x + sign * dx }, y, disc) < disc.r) {
|
|
567
|
+
dx += 1;
|
|
568
|
+
}
|
|
569
|
+
return sign * dx;
|
|
570
|
+
}
|
|
571
|
+
function overlapsX(a, b) {
|
|
572
|
+
return Math.abs(a.x - b.x) < (a.w + b.w) / 2;
|
|
573
|
+
}
|
|
574
|
+
function sweepSide(boxes, minY, maxY) {
|
|
575
|
+
const sorted = [...boxes].sort((a, b) => a.y - b.y || a.id - b.id);
|
|
576
|
+
const ys = sorted.map((box) => box.y);
|
|
577
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
578
|
+
const prev = sorted[i - 1];
|
|
579
|
+
const box = sorted[i];
|
|
580
|
+
if (overlapsX(prev, box)) {
|
|
581
|
+
ys[i] = Math.max(ys[i], ys[i - 1] + (prev.h + box.h) / 2 + LABEL_COLLISION_GAP);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
for (let i = sorted.length - 1; i >= 0; i--) {
|
|
585
|
+
const box = sorted[i];
|
|
586
|
+
const limit = i === sorted.length - 1 ? maxY - box.h / 2 : ys[i + 1] - (box.h + sorted[i + 1].h) / 2 - LABEL_COLLISION_GAP;
|
|
587
|
+
if (ys[i] > limit) {
|
|
588
|
+
ys[i] = Math.max(limit, minY + box.h / 2);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return new Map(sorted.map((box, i) => [box.id, ys[i]]));
|
|
592
|
+
}
|
|
593
|
+
function nudgeOutsideLabels(boxes, disc, minY, maxY) {
|
|
594
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
595
|
+
for (const side of [
|
|
596
|
+
boxes.filter((box) => box.x >= disc.cx),
|
|
597
|
+
boxes.filter((box) => box.x < disc.cx)
|
|
598
|
+
]) {
|
|
599
|
+
for (const [id, y] of sweepSide(side, minY, maxY)) {
|
|
600
|
+
resolved.set(id, y);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return boxes.map((box) => {
|
|
604
|
+
const y = resolved.get(box.id) ?? box.y;
|
|
605
|
+
return { id: box.id, dx: y === box.y ? 0 : clearOfDisc(box, y, disc), dy: y - box.y };
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
exports.BEST_FIT_EDGE_TOLERANCE = BEST_FIT_EDGE_TOLERANCE;
|
|
610
|
+
exports.BEST_FIT_OUTSIDE_GAP = BEST_FIT_OUTSIDE_GAP;
|
|
611
|
+
exports.BEST_FIT_RIM_INSET = BEST_FIT_RIM_INSET;
|
|
612
|
+
exports.LABEL_COLLISION_GAP = LABEL_COLLISION_GAP;
|
|
383
613
|
exports.aggregateByCategory = aggregateByCategory;
|
|
384
614
|
exports.axisTargetIntervals = axisTargetIntervals;
|
|
385
615
|
exports.computeBoxStats = computeBoxStats;
|
|
386
616
|
exports.computeHistogramBins = computeHistogramBins;
|
|
387
617
|
exports.computeLinearRegression = computeLinearRegression;
|
|
388
618
|
exports.computeRSquared = computeRSquared;
|
|
619
|
+
exports.computeRadarPoints = computeRadarPoints;
|
|
389
620
|
exports.computeStackedSeriesPlots = computeStackedSeriesPlots;
|
|
390
621
|
exports.fitPolynomial = fitPolynomial;
|
|
622
|
+
exports.formatExponentialEquation = formatExponentialEquation;
|
|
623
|
+
exports.formatLinearEquation = formatLinearEquation;
|
|
624
|
+
exports.formatLogarithmicEquation = formatLogarithmicEquation;
|
|
625
|
+
exports.formatPolynomialEquation = formatPolynomialEquation;
|
|
626
|
+
exports.formatPowerEquation = formatPowerEquation;
|
|
627
|
+
exports.formatTrendlineCoefficient = formatTrendlineCoefficient;
|
|
391
628
|
exports.groupRowsByCategory = groupRowsByCategory;
|
|
392
629
|
exports.niceAxisStep = niceAxisStep;
|
|
393
630
|
exports.niceValueAxisBounds = niceValueAxisBounds;
|
|
631
|
+
exports.nudgeOutsideLabels = nudgeOutsideLabels;
|
|
632
|
+
exports.placeBestFitLabel = placeBestFitLabel;
|
|
633
|
+
exports.radarAngle = radarAngle;
|
|
634
|
+
exports.radarRingPoints = radarRingPoints;
|
|
394
635
|
exports.resolveBlankDisplay = resolveBlankDisplay;
|
|
395
636
|
exports.scottBinCount = scottBinCount;
|
|
637
|
+
exports.squarify = squarify;
|
|
396
638
|
exports.visibleRuns = visibleRuns;
|
package/dist/chart/index.d.ts
CHANGED
|
@@ -5,4 +5,9 @@ export * from './blank-display.js';
|
|
|
5
5
|
export * from './stacked-series.js';
|
|
6
6
|
export * from './axis-nice.js';
|
|
7
7
|
export * from './histogram-binning.js';
|
|
8
|
+
export * from './treemap-squarify.js';
|
|
9
|
+
export * from './trendline-equation.js';
|
|
10
|
+
export * from './radar-geometry.js';
|
|
11
|
+
export * from './pie-best-fit.js';
|
|
12
|
+
export * from './pie-label-collision.js';
|
|
8
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../chart/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../chart/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC"}
|