73 lines
3.1 KiB
JavaScript
73 lines
3.1 KiB
JavaScript
|
|
// Ad-hoc probe for one document: prints structure around a given block
|
||
|
|
// index, before and after a round-trip, plus the raw vMerge / numId picture
|
||
|
|
// from both packages. Structure only — no document text beyond short labels.
|
||
|
|
//
|
||
|
|
// node test/probe.mjs <file.docx> [blockIndex]
|
||
|
|
import { readFileSync, writeFileSync } from "node:fs";
|
||
|
|
import { loadAddonLibs, summarise } from "./harness.mjs";
|
||
|
|
|
||
|
|
const DocxEditor = loadAddonLibs();
|
||
|
|
const schema = DocxEditor.schema.build();
|
||
|
|
const file = process.argv[2];
|
||
|
|
const focus = process.argv[3] ? parseInt(process.argv[3], 10) : null;
|
||
|
|
const bytes = new Uint8Array(readFileSync(file));
|
||
|
|
|
||
|
|
const W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
||
|
|
|
||
|
|
async function numberingPicture(b, label) {
|
||
|
|
const zip = await DocxEditor.pkg.loadZip(b);
|
||
|
|
const doc = DocxEditor.pkg.parseXml(await zip.file("word/document.xml").async("string"));
|
||
|
|
const ps = doc.getElementsByTagNameNS(W, "p");
|
||
|
|
const seq = [];
|
||
|
|
for (let i = 0; i < ps.length; i++) {
|
||
|
|
const numPr = ps[i].getElementsByTagNameNS(W, "numPr")[0];
|
||
|
|
if (!numPr) { seq.push("."); continue; }
|
||
|
|
const numId = numPr.getElementsByTagNameNS(W, "numId")[0];
|
||
|
|
const ilvl = numPr.getElementsByTagNameNS(W, "ilvl")[0];
|
||
|
|
seq.push(`${numId ? numId.getAttributeNS(W, "val") : "?"}/${ilvl ? ilvl.getAttributeNS(W, "val") : "0"}`);
|
||
|
|
}
|
||
|
|
console.log(`${label} numbering (numId/level per paragraph, "." = not a list item):`);
|
||
|
|
console.log(" " + seq.join(" "));
|
||
|
|
|
||
|
|
const merges = [];
|
||
|
|
const rows = doc.getElementsByTagNameNS(W, "tr");
|
||
|
|
for (let r = 0; r < rows.length; r++) {
|
||
|
|
const cells = rows[r].getElementsByTagNameNS(W, "tc");
|
||
|
|
const marks = [];
|
||
|
|
for (let c = 0; c < cells.length; c++) {
|
||
|
|
const vm = cells[c].getElementsByTagNameNS(W, "vMerge")[0];
|
||
|
|
if (!vm) { marks.push("-"); continue; }
|
||
|
|
marks.push(vm.getAttributeNS(W, "val") === "restart" ? "R" : "c");
|
||
|
|
}
|
||
|
|
if (marks.includes("R") || marks.includes("c")) merges.push(`r${r}:${marks.join("")}`);
|
||
|
|
}
|
||
|
|
if (merges.length) console.log(`${label} vMerge: ${merges.slice(0, 20).join(" ")}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
const first = await DocxEditor.read.docxToDoc(bytes, schema);
|
||
|
|
const saved = await DocxEditor.write.docToDocx(first.doc, {
|
||
|
|
originalBytes: bytes, setup: first.setup, meta: first.meta,
|
||
|
|
});
|
||
|
|
const second = await DocxEditor.read.docxToDoc(saved.bytes, schema);
|
||
|
|
|
||
|
|
console.log(`blocks: ${first.doc.childCount} -> ${second.doc.childCount}`);
|
||
|
|
if (saved.warnings.length) console.log(`warnings: ${saved.warnings.join(" | ")}`);
|
||
|
|
console.log();
|
||
|
|
await numberingPicture(bytes, "original");
|
||
|
|
console.log();
|
||
|
|
await numberingPicture(saved.bytes, "saved ");
|
||
|
|
|
||
|
|
if (focus !== null) {
|
||
|
|
const outline = (doc, from) => {
|
||
|
|
const lines = [];
|
||
|
|
for (let i = from; i < Math.min(doc.childCount, from + 8); i++) {
|
||
|
|
const n = doc.child(i);
|
||
|
|
lines.push(` [${i}] ${n.type.name}${n.childCount ? ` (${n.childCount} kids)` : ""} ` +
|
||
|
|
JSON.stringify(n.textContent.slice(0, 40)));
|
||
|
|
}
|
||
|
|
return lines.join("\n");
|
||
|
|
};
|
||
|
|
console.log(`\nbefore, from [${focus}]:\n` + outline(first.doc, focus));
|
||
|
|
console.log(`\nafter, from [${focus}]:\n` + outline(second.doc, focus));
|
||
|
|
}
|