Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
282c4d6
test(ooxml.js): cover isCompactXmlNode's full type-code truth table d…
Mearman Sep 14, 2026
b52c593
refactor(ooxml.js): drop comments' redundant presence guards before a…
Mearman Sep 14, 2026
a850fb7
test(ooxml.js): close comments.ts's relationship-type, local-name, an…
Mearman Sep 14, 2026
f0c48fd
test(ooxml.js): distinguish extentAlong's true earliest start from it…
Mearman Sep 14, 2026
b027bcf
refactor(ooxml.js): drop constructs.ts's three redundant guards
Mearman Sep 14, 2026
0bee000
test(ooxml.js): close constructs.ts's paragraph-index, checkbox, and …
Mearman Sep 14, 2026
bd6c611
fix(ooxml.js): pin isBlockScopedHalf's own leading/trailing boundary …
Mearman Sep 14, 2026
2896328
refactor(ooxml.js): drop drawings.ts's redundant column/row validity …
Mearman Sep 14, 2026
0c5d24b
refactor(ooxml.js): drop drawings.ts's remaining redundant NaN-fallba…
Mearman Sep 14, 2026
aa6df62
test(ooxml.js): cover SheetGridGeometry's column/row lookups and edit…
Mearman Sep 15, 2026
445e43c
test(ooxml.js): close drawings.ts's remaining chart-frame and marker …
Mearman Sep 15, 2026
a8de250
test(ooxml.js): add direct structural coverage for buildDrawing and f…
Mearman Sep 15, 2026
2f70f98
test(ooxml.js): close content.ts's row/column, span, and residue muta…
Mearman Sep 16, 2026
76fa96a
test(ooxml.js): reach content.ts's genuine mutation ceiling
Mearman Sep 16, 2026
7beba7a
test(ooxml.js): close styles.ts's decoration key-presence and
Mearman Sep 16, 2026
ce0379f
test(ooxml.js): reach styles.ts's genuine mutation ceiling
Mearman Sep 16, 2026
7027a42
test(ooxml.js): fix two border-signature tests that could not
Mearman Sep 16, 2026
9c779c7
test(ooxml.js): cover borderToXlsxStyle's double/dotted tokens
Mearman Sep 16, 2026
c12cddb
test(ooxml.js): add drawings-write.ts's own direct unit suite
Mearman Sep 16, 2026
ea6730e
test(ooxml.js): fix drawings-write test coverage attribution
Mearman Sep 16, 2026
430e4a4
test(ooxml.js): close drawings-write's remaining chart-counter and sp…
Mearman Sep 16, 2026
241f8e6
test(ooxml.js): add conditional-format.ts's own direct unit suite
Mearman Sep 16, 2026
2ad1b6e
test(ooxml.js): close conditional-format's operator, boundary, and re…
Mearman Sep 16, 2026
0b60dfc
test(ooxml.js): cover pptx read's slide-size fallback, alignment, and…
Mearman Sep 16, 2026
31838ab
docs(ooxml.js): raise the mutation break threshold to the
Mearman Sep 16, 2026
c8191e5
test(ooxml.js): cover build.ts's exact package-scaffolding output
Mearman Sep 16, 2026
2a01e63
test(ooxml.js): cover build.ts's styles-part and docProps output exactly
Mearman Sep 16, 2026
bc9fa5c
test(ooxml.js): cover build.ts's dimension, cols, row/cell assembly, …
Mearman Sep 16, 2026
e0726be
test(ooxml.js): cover build.ts's page margins, page setup, and manual…
Mearman Sep 16, 2026
14dfb9a
test(ooxml.js): cover build.ts's per-sheet table filtering and relati…
Mearman Sep 16, 2026
ed7cca9
test(ooxml.js): assert the derived Print_Area definedName's own text …
Mearman Sep 16, 2026
646213c
docs(ooxml.js): record build.ts's re-measured mutation score and a St…
Mearman Sep 16, 2026
745cc14
test(ooxml.js): fix build.test.ts's own type errors under Node typecheck
Mearman Sep 16, 2026
bba66d4
test(ooxml.js): cover docx write.ts's table, link, and scaffolding XM…
Mearman Sep 16, 2026
aace335
docs(ooxml.js): record docx write.ts's re-measured mutation score
Mearman Sep 16, 2026
9757cfa
test(ooxml.js): cover docx read.ts's page geometry, toggles, and fiel…
Mearman Sep 16, 2026
1bb2650
test(ooxml.js): cover docx read.ts's split-run reindexing and border-…
Mearman Sep 16, 2026
01d100e
docs(ooxml.js): record docx read.ts's re-measured mutation score
Mearman Sep 16, 2026
4ef7c94
refactor(ooxml.js): drop docx read.ts's provably-redundant guards
Mearman Sep 16, 2026
f161967
test(ooxml.js): cover docx read.ts's construct tie-breaks, header joi…
Mearman Sep 16, 2026
83fe09a
refactor(ooxml.js): remove docx read.ts's behaviourally-dead guard ex…
Mearman Sep 16, 2026
70b9f91
test(ooxml.js): cover docx read.ts's run-walk guards, tracked-change …
Mearman Sep 16, 2026
97f2ae2
refactor(ooxml.js): read docx marker halves' @w:name unconditionally
Mearman Sep 16, 2026
8605bc7
docs(ooxml.js): record docx read.ts's protocol-verified 99.40% mutati…
Mearman Sep 16, 2026
d983d25
test(ooxml.js): assert docx write.ts's optional part emission and lin…
Mearman Sep 16, 2026
8b0f7dc
refactor(ooxml.js): drop docx write.ts's links-empty early return
Mearman Sep 16, 2026
6a288ca
test(ooxml.js): assert docx write.ts's run content, styles, notes, an…
Mearman Sep 16, 2026
933f665
docs(ooxml.js): record docx write.ts's re-measured 83.95% mutation score
Mearman Sep 16, 2026
be3d218
refactor(ooxml.js): drop docx write.ts's stale index-space link-overl…
Mearman Sep 16, 2026
cfc6bd7
test(ooxml.js): cover docx write.ts's boundary shapes, media, and exa…
Mearman Sep 16, 2026
df8e926
test(ooxml.js): assert xlsx build's workbook, dimension, merges, and …
Mearman Sep 16, 2026
0088647
test(ooxml.js): cover docx write.ts's cross-part sharing, minting ord…
Mearman Sep 16, 2026
0217d20
test(ooxml.js): assert xlsx build's carried-name and derived print-na…
Mearman Sep 16, 2026
e2d9296
refactor(ooxml.js): spell the trailing-run hyperlink exclusion once i…
Mearman Sep 16, 2026
a8f3065
test(ooxml.js): pin docx write.ts's lifted-image run alignment and no…
Mearman Sep 16, 2026
019a47a
docs(ooxml.js): record docx write.ts's protocol-verified 99.45% mutat…
Mearman Sep 16, 2026
930228d
refactor(ooxml.js): drop xlsx build's dead print-titles presence guard
Mearman Sep 16, 2026
4e6a807
test(ooxml.js): assert xlsx build's part roots, scope-keyed suppressi…
Mearman Sep 16, 2026
f2b02b3
refactor(ooxml.js): drop xlsx build's dead worksheet-extras fallbacks
Mearman Sep 16, 2026
4bdf7b5
test(ooxml.js): cover xlsx build's bottom-aligned default and exact m…
Mearman Sep 16, 2026
b1b779f
docs(ooxml.js): record xlsx build.ts's triaged 87.66% floor and its v…
Mearman Sep 16, 2026
c0be1c9
fix(ooxml.js): match the docx write tests' fixtures to the content sc…
Mearman Sep 20, 2026
9d29da4
chore(ooxml.js): raise the mutation break threshold to 95
Mearman Sep 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 155 additions & 1 deletion packages/ooxml.js/src/compact.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, it } from "vitest";
import {
CompactXmlNodeSchema,
decodeCompactPackage,
decodePackage,
encodeCompactPackage,
Expand All @@ -8,7 +9,7 @@ import {
toCompact,
zipPackage,
} from "./index";
import type { Package, XmlElement } from "./index";
import type { CompactPackage, Package, XmlElement } from "./index";

function enc(s: string): Uint8Array<ArrayBuffer> {
return new TextEncoder().encode(s);
Expand Down Expand Up @@ -179,6 +180,109 @@ describe("compact size", () => {
});
});

describe("isCompactXmlNode (via CompactXmlNodeSchema)", () => {
it("rejects a non-array value", () => {
expect(CompactXmlNodeSchema.safeParse("nope").success).toBe(false);
expect(CompactXmlNodeSchema.safeParse({ 0: 1, 1: 0 }).success).toBe(false);
});

it("accepts a text/cdata/comment node ([1|2|3, number])", () => {
expect(CompactXmlNodeSchema.safeParse([1, 0]).success).toBe(true);
expect(CompactXmlNodeSchema.safeParse([2, 0]).success).toBe(true);
expect(CompactXmlNodeSchema.safeParse([3, 0]).success).toBe(true);
});

it("rejects a text/cdata/comment node with the wrong tuple length", () => {
expect(CompactXmlNodeSchema.safeParse([1, 0, 0]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([2, 0, 0]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([3, 0, 0]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([1]).success).toBe(false);
});

it("rejects a text/cdata/comment node whose value slot is not a number", () => {
expect(CompactXmlNodeSchema.safeParse([1, "x"]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([2, "x"]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([3, "x"]).success).toBe(false);
});

it("accepts a declaration node ([4, attrPairs])", () => {
expect(CompactXmlNodeSchema.safeParse([4, [0, 1]]).success).toBe(true);
expect(CompactXmlNodeSchema.safeParse([4, []]).success).toBe(true);
});

it("rejects a declaration node with the wrong tuple length", () => {
expect(CompactXmlNodeSchema.safeParse([4, [0, 1], 9]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([4]).success).toBe(false);
});

it("rejects a declaration node whose attr pairs are not a valid CompactAttrPairs", () => {
expect(CompactXmlNodeSchema.safeParse([4, "not-an-array"]).success).toBe(
false,
);
expect(CompactXmlNodeSchema.safeParse([4, [0, "x"]]).success).toBe(false);
});

it("accepts a pi node ([5, number, number])", () => {
expect(CompactXmlNodeSchema.safeParse([5, 0, 1]).success).toBe(true);
});

it("rejects a pi node with the wrong tuple length", () => {
expect(CompactXmlNodeSchema.safeParse([5, 0]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([5, 0, 1, 2]).success).toBe(false);
});

it("rejects a pi node whose target or content slot is not a number", () => {
expect(CompactXmlNodeSchema.safeParse([5, "x", 1]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([5, 0, "x"]).success).toBe(false);
});

it("accepts an element node ([0, tag, attrPairs, children])", () => {
expect(CompactXmlNodeSchema.safeParse([0, 0, [], []]).success).toBe(true);
expect(
CompactXmlNodeSchema.safeParse([0, 0, [1, 2], [[1, 0]]]).success,
).toBe(true);
});

it("rejects an element node with the wrong tuple length", () => {
expect(CompactXmlNodeSchema.safeParse([0, 0, [], [], 9]).success).toBe(
false,
);
expect(CompactXmlNodeSchema.safeParse([0, 0, []]).success).toBe(false);
});

it("rejects an element node whose tag slot is not a number", () => {
expect(CompactXmlNodeSchema.safeParse([0, "x", [], []]).success).toBe(
false,
);
});

it("rejects an element node whose attr pairs are not a valid CompactAttrPairs", () => {
expect(
CompactXmlNodeSchema.safeParse([0, 0, "not-an-array", []]).success,
).toBe(false);
expect(CompactXmlNodeSchema.safeParse([0, 0, [0, "x"], []]).success).toBe(
false,
);
});

it("rejects an element node whose children slot is not an array", () => {
expect(
CompactXmlNodeSchema.safeParse([0, 0, [], "not-an-array"]).success,
).toBe(false);
});

it("rejects an element node whose children are not all valid compact nodes", () => {
expect(
CompactXmlNodeSchema.safeParse([0, 0, [], [["not-a-node"]]]).success,
).toBe(false);
});

it("rejects an unrecognised leading type code, even one that happens to satisfy the element-shape checks", () => {
expect(CompactXmlNodeSchema.safeParse([9]).success).toBe(false);
expect(CompactXmlNodeSchema.safeParse([9, 0, [], []]).success).toBe(false);
});
});

describe("compact adversarial cases", () => {
it("round-trips an empty Package", () => {
const pkg: Package = { parts: {} };
Expand Down Expand Up @@ -217,6 +321,56 @@ describe("compact adversarial cases", () => {
expect(fromCompact(toCompact(pkg))).toEqual(pkg);
});

it("round-trips a cdata node", () => {
const pkg: Package = {
parts: {
"word/document.xml": {
kind: "xml",
nodes: [{ type: "cdata", value: "<raw> & unescaped" }],
},
},
};
expect(fromCompact(toCompact(pkg))).toEqual(pkg);
});

it("round-trips a processing-instruction node", () => {
const pkg: Package = {
parts: {
"word/document.xml": {
kind: "xml",
nodes: [
{
type: "pi",
target: "mso-application",
content: 'progid="Word.Document"',
},
],
},
},
};
expect(fromCompact(toCompact(pkg))).toEqual(pkg);
});

it("throws with the out-of-range string index when a string-table lookup fails", () => {
const cpkg: CompactPackage = {
s: [],
p: { "word/document.xml": [[1, 5]] },
};
expect(() => fromCompact(cpkg)).toThrow(
"fromCompact: string table index 5 is out of range",
);
});

it("throws when an attribute index-pairs array has odd length", () => {
const cpkg: CompactPackage = {
s: ["name-only"],
p: { "word/document.xml": [[4, [0]]] },
};
expect(() => fromCompact(cpkg)).toThrow(
"fromCompact: attribute index pairs array has odd length",
);
});

it("round-trips a large base64 binary part as a single interned string", () => {
const largeBase64 = Buffer.from(new Uint8Array(64 * 1024).fill(7)).toString(
"base64",
Expand Down
Loading
Loading