bun-docx 0.13.0 → 0.14.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 +13 -5
- package/dist/index.js +1258 -690
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16632,6 +16632,7 @@ var init_jsx = __esm(() => {
|
|
|
16632
16632
|
"rFonts",
|
|
16633
16633
|
"br",
|
|
16634
16634
|
"tab",
|
|
16635
|
+
"tabs",
|
|
16635
16636
|
"drawing",
|
|
16636
16637
|
"sectPr",
|
|
16637
16638
|
"sectPrChange",
|
|
@@ -21616,6 +21617,15 @@ function applyParagraphProperties(document2, paragraph, paragraphProperties) {
|
|
|
21616
21617
|
paragraph.alignment = value;
|
|
21617
21618
|
}
|
|
21618
21619
|
}
|
|
21620
|
+
const tabsNode = paragraphProperties.findChild("w:tabs");
|
|
21621
|
+
if (tabsNode) {
|
|
21622
|
+
const stops = tabsNode.findChildren("w:tab").map((tab) => ({
|
|
21623
|
+
align: tab.getAttribute("w:val") ?? "left",
|
|
21624
|
+
pos: Number(tab.getAttribute("w:pos") ?? "0")
|
|
21625
|
+
})).filter((stop) => Number.isFinite(stop.pos));
|
|
21626
|
+
if (stops.length > 0)
|
|
21627
|
+
paragraph.tabStops = stops;
|
|
21628
|
+
}
|
|
21619
21629
|
const numberingProperties = paragraphProperties.findChild("w:numPr");
|
|
21620
21630
|
if (numberingProperties) {
|
|
21621
21631
|
const indentLevel = numberingProperties.findChild("w:ilvl");
|
|
@@ -34067,6 +34077,7 @@ function Paragraph({
|
|
|
34067
34077
|
alignment,
|
|
34068
34078
|
list,
|
|
34069
34079
|
taskState,
|
|
34080
|
+
tabs,
|
|
34070
34081
|
text: text2,
|
|
34071
34082
|
runs,
|
|
34072
34083
|
...formatting
|
|
@@ -34075,7 +34086,7 @@ function Paragraph({
|
|
|
34075
34086
|
return /* @__PURE__ */ jsxDEV(w.p, {
|
|
34076
34087
|
children: [
|
|
34077
34088
|
/* @__PURE__ */ jsxDEV(ParagraphProperties, {
|
|
34078
|
-
options: { style, alignment, list }
|
|
34089
|
+
options: { style, alignment, list, tabs }
|
|
34079
34090
|
}, undefined, false, undefined, this),
|
|
34080
34091
|
taskState && /* @__PURE__ */ jsxDEV(TaskCheckbox, {
|
|
34081
34092
|
checked: taskState === "checked"
|
|
@@ -34131,13 +34142,26 @@ function RunElement({ run }) {
|
|
|
34131
34142
|
return null;
|
|
34132
34143
|
}
|
|
34133
34144
|
function applyParagraphOptionsInPlace(rebuilt, options) {
|
|
34134
|
-
if (!options.style && !options.alignment)
|
|
34145
|
+
if (!options.style && !options.alignment && !options.tabs)
|
|
34135
34146
|
return;
|
|
34136
34147
|
let pPr = rebuilt.find((child2) => child2.tag === "w:pPr");
|
|
34137
34148
|
if (!pPr) {
|
|
34138
34149
|
pPr = new XmlNode2("w:pPr");
|
|
34139
34150
|
rebuilt.unshift(pPr);
|
|
34140
34151
|
}
|
|
34152
|
+
if (options.tabs) {
|
|
34153
|
+
pPr.children = pPr.children.filter((child2) => child2.tag !== "w:tabs");
|
|
34154
|
+
if (options.tabs.length > 0) {
|
|
34155
|
+
const tabsNode = new XmlNode2("w:tabs");
|
|
34156
|
+
for (const stop of options.tabs) {
|
|
34157
|
+
tabsNode.children.push(new XmlNode2("w:tab", {
|
|
34158
|
+
"w:val": stop.align,
|
|
34159
|
+
"w:pos": String(Math.round(stop.pos))
|
|
34160
|
+
}));
|
|
34161
|
+
}
|
|
34162
|
+
insertPprChildInOrder(pPr, tabsNode);
|
|
34163
|
+
}
|
|
34164
|
+
}
|
|
34141
34165
|
if (options.style) {
|
|
34142
34166
|
const existingStyle = pPr.findChild("w:pStyle");
|
|
34143
34167
|
if (existingStyle) {
|
|
@@ -34244,7 +34268,8 @@ function RunProperties({ run }) {
|
|
|
34244
34268
|
function ParagraphProperties({
|
|
34245
34269
|
options
|
|
34246
34270
|
}) {
|
|
34247
|
-
|
|
34271
|
+
const hasTabs = options.tabs !== undefined && options.tabs.length > 0;
|
|
34272
|
+
if (!options.style && !options.alignment && !options.list && !hasTabs)
|
|
34248
34273
|
return null;
|
|
34249
34274
|
return /* @__PURE__ */ jsxDEV(w.pPr, {
|
|
34250
34275
|
children: [
|
|
@@ -34261,6 +34286,12 @@ function ParagraphProperties({
|
|
|
34261
34286
|
}, undefined, false, undefined, this)
|
|
34262
34287
|
]
|
|
34263
34288
|
}, undefined, true, undefined, this),
|
|
34289
|
+
hasTabs && /* @__PURE__ */ jsxDEV(w.tabs, {
|
|
34290
|
+
children: options.tabs?.map((stop) => /* @__PURE__ */ jsxDEV(w.tab, {
|
|
34291
|
+
"w-val": stop.align,
|
|
34292
|
+
"w-pos": String(Math.round(stop.pos))
|
|
34293
|
+
}, undefined, false, undefined, this))
|
|
34294
|
+
}, undefined, false, undefined, this),
|
|
34264
34295
|
options.alignment && /* @__PURE__ */ jsxDEV(w.jc, {
|
|
34265
34296
|
"w-val": options.alignment
|
|
34266
34297
|
}, undefined, false, undefined, this)
|
|
@@ -49400,7 +49431,7 @@ function collectRunText(run) {
|
|
|
49400
49431
|
function tokenize(text2) {
|
|
49401
49432
|
if (text2.length === 0)
|
|
49402
49433
|
return [];
|
|
49403
|
-
return text2.match(/\S+|\
|
|
49434
|
+
return text2.match(/\S+|\t+|[^\S\t]+/g) ?? [];
|
|
49404
49435
|
}
|
|
49405
49436
|
function diffTokens(oldTokens, newTokens) {
|
|
49406
49437
|
const m2 = oldTokens.length;
|
|
@@ -49461,6 +49492,10 @@ function demoteOrphanWhitespaceKeeps(ops) {
|
|
|
49461
49492
|
out.push(op2);
|
|
49462
49493
|
continue;
|
|
49463
49494
|
}
|
|
49495
|
+
if (op2.old.text.includes("\t")) {
|
|
49496
|
+
out.push(op2);
|
|
49497
|
+
continue;
|
|
49498
|
+
}
|
|
49464
49499
|
const prev = ops[index - 1];
|
|
49465
49500
|
const next = ops[index + 1];
|
|
49466
49501
|
const prevIsEdit = prev !== undefined && prev.kind !== "keep";
|
|
@@ -49549,25 +49584,45 @@ function inheritedRprForInsert(ops, index, fallbackRpr) {
|
|
|
49549
49584
|
break;
|
|
49550
49585
|
groupEnd++;
|
|
49551
49586
|
}
|
|
49552
|
-
const
|
|
49553
|
-
|
|
49554
|
-
|
|
49587
|
+
const targetText = (() => {
|
|
49588
|
+
const op2 = ops[index];
|
|
49589
|
+
return op2 && op2.kind === "insert" ? op2.text : "";
|
|
49590
|
+
})();
|
|
49591
|
+
const targetIsWord = !isWhitespaceOnly(targetText);
|
|
49592
|
+
const allDeletes = [];
|
|
49593
|
+
const wordDeletes = [];
|
|
49594
|
+
let allInsertOrdinal = 0;
|
|
49595
|
+
let wordInsertOrdinal = 0;
|
|
49596
|
+
let myAllOrdinal = -1;
|
|
49597
|
+
let myWordOrdinal = -1;
|
|
49555
49598
|
for (let cursor = groupStart;cursor <= groupEnd; cursor++) {
|
|
49556
49599
|
const op2 = ops[cursor];
|
|
49557
49600
|
if (!op2)
|
|
49558
49601
|
continue;
|
|
49559
49602
|
if (op2.kind === "delete") {
|
|
49560
|
-
|
|
49603
|
+
allDeletes.push(op2.old.rPr);
|
|
49604
|
+
if (!isWhitespaceOnly(op2.old.text))
|
|
49605
|
+
wordDeletes.push(op2.old.rPr);
|
|
49561
49606
|
continue;
|
|
49562
49607
|
}
|
|
49563
49608
|
if (op2.kind === "insert") {
|
|
49564
|
-
|
|
49565
|
-
|
|
49566
|
-
|
|
49609
|
+
const isWord = !isWhitespaceOnly(op2.text);
|
|
49610
|
+
if (cursor === index) {
|
|
49611
|
+
myAllOrdinal = allInsertOrdinal;
|
|
49612
|
+
myWordOrdinal = isWord ? wordInsertOrdinal : -1;
|
|
49613
|
+
}
|
|
49614
|
+
allInsertOrdinal++;
|
|
49615
|
+
if (isWord)
|
|
49616
|
+
wordInsertOrdinal++;
|
|
49567
49617
|
}
|
|
49568
49618
|
}
|
|
49569
|
-
if (
|
|
49570
|
-
const paired =
|
|
49619
|
+
if (targetIsWord && wordDeletes.length > 0 && myWordOrdinal >= 0) {
|
|
49620
|
+
const paired = myWordOrdinal < wordDeletes.length ? wordDeletes[myWordOrdinal] : wordDeletes[wordDeletes.length - 1];
|
|
49621
|
+
if (paired !== undefined)
|
|
49622
|
+
return paired;
|
|
49623
|
+
}
|
|
49624
|
+
if (!targetIsWord && allDeletes.length > 0 && myAllOrdinal >= 0) {
|
|
49625
|
+
const paired = myAllOrdinal < allDeletes.length ? allDeletes[myAllOrdinal] : allDeletes[allDeletes.length - 1];
|
|
49571
49626
|
if (paired !== undefined)
|
|
49572
49627
|
return paired;
|
|
49573
49628
|
}
|
|
@@ -49964,6 +50019,14 @@ class Edit {
|
|
|
49964
50019
|
}
|
|
49965
50020
|
return anchorTarget ?? blockRef.node;
|
|
49966
50021
|
}
|
|
50022
|
+
paragraphProperties(blockRef, options) {
|
|
50023
|
+
if (blockRef.node.tag !== "w:p") {
|
|
50024
|
+
throw new EditError("USAGE", "--style/--alignment alone restyle a paragraph; this locator is not a paragraph.");
|
|
50025
|
+
}
|
|
50026
|
+
this.document.ensureStyles().ensureReferencedStyle(options.style);
|
|
50027
|
+
applyParagraphOptionsInPlace(blockRef.node.children, options);
|
|
50028
|
+
return blockRef.node;
|
|
50029
|
+
}
|
|
49967
50030
|
span(blockRef, span, replacement, opts = {}) {
|
|
49968
50031
|
if (blockRef.node.tag !== "w:p") {
|
|
49969
50032
|
throw new EditError("USAGE", "A character-span locator (pN:S-E) edits text inside a paragraph; this locator does not resolve to a paragraph.");
|
|
@@ -80368,16 +80431,20 @@ async function respond(payload) {
|
|
|
80368
80431
|
function setVerboseAck(verbose) {
|
|
80369
80432
|
verboseAck = verbose;
|
|
80370
80433
|
}
|
|
80371
|
-
async function respondAck(payload) {
|
|
80434
|
+
async function respondAck(payload, layoutHint) {
|
|
80372
80435
|
if (verboseAck) {
|
|
80373
80436
|
await respond(payload);
|
|
80374
80437
|
return;
|
|
80375
80438
|
}
|
|
80376
|
-
const
|
|
80377
|
-
if (
|
|
80378
|
-
await writeStdout(`${
|
|
80439
|
+
const parts = [summarizeAck(payload), layoutHint].filter((part) => Boolean(part));
|
|
80440
|
+
if (parts.length > 0)
|
|
80441
|
+
await writeStdout(`${parts.join(`
|
|
80442
|
+
`)}
|
|
80379
80443
|
`);
|
|
80380
80444
|
}
|
|
80445
|
+
function renderVerifyHint(path2) {
|
|
80446
|
+
return `\u21B3 layout changed \u2014 verify it renders right: docx render ${path2} --out pages/ (read shows text/structure, NOT page layout: columns, wraps, image sizing)`;
|
|
80447
|
+
}
|
|
80381
80448
|
function summarizeAck(payload) {
|
|
80382
80449
|
if (!payload || typeof payload !== "object")
|
|
80383
80450
|
return null;
|
|
@@ -80425,13 +80492,16 @@ function ackTarget(ack) {
|
|
|
80425
80492
|
return str(ack.path);
|
|
80426
80493
|
return null;
|
|
80427
80494
|
}
|
|
80428
|
-
async function respondMinted(locators, verbosePayload) {
|
|
80495
|
+
async function respondMinted(locators, verbosePayload, layoutHint) {
|
|
80429
80496
|
if (verboseAck) {
|
|
80430
80497
|
await respond(verbosePayload);
|
|
80431
80498
|
return;
|
|
80432
80499
|
}
|
|
80433
|
-
|
|
80434
|
-
|
|
80500
|
+
const parts = [...locators];
|
|
80501
|
+
if (layoutHint)
|
|
80502
|
+
parts.push(layoutHint);
|
|
80503
|
+
if (parts.length > 0)
|
|
80504
|
+
await writeStdout(`${parts.join(`
|
|
80435
80505
|
`)}
|
|
80436
80506
|
`);
|
|
80437
80507
|
}
|
|
@@ -80571,254 +80641,36 @@ var init_respond = __esm(() => {
|
|
|
80571
80641
|
};
|
|
80572
80642
|
});
|
|
80573
80643
|
|
|
80574
|
-
// src/cli/
|
|
80575
|
-
|
|
80576
|
-
|
|
80577
|
-
|
|
80578
|
-
|
|
80579
|
-
|
|
80580
|
-
|
|
80581
|
-
|
|
80582
|
-
|
|
80583
|
-
|
|
80584
|
-
|
|
80585
|
-
return EXIT2.OK;
|
|
80586
|
-
}
|
|
80587
|
-
setVerboseAck(Boolean(parsed.values.verbose));
|
|
80588
|
-
const filePath = parsed.positionals[0];
|
|
80589
|
-
if (!filePath)
|
|
80590
|
-
return fail("USAGE", "Missing FILE argument", HELP);
|
|
80591
|
-
const at = parsed.values.at;
|
|
80592
|
-
if (!at) {
|
|
80593
|
-
return fail("USAGE", "Missing --at LOCATOR (a range pN-pM or a section sN)", HELP);
|
|
80594
|
-
}
|
|
80595
|
-
const count = parseCount(parsed.values.count);
|
|
80596
|
-
if (typeof count === "number" && Number.isNaN(count)) {
|
|
80597
|
-
return fail("USAGE", `--count must be a positive integer`, HELP);
|
|
80598
|
-
}
|
|
80599
|
-
if (count === undefined)
|
|
80600
|
-
return fail("USAGE", "Missing --count N", HELP);
|
|
80601
|
-
const typeRaw = parsed.values.type;
|
|
80602
|
-
if (typeRaw !== undefined && !isSectionType(typeRaw)) {
|
|
80603
|
-
return fail("USAGE", `Invalid --type: ${typeRaw}`, "Valid values: continuous, nextPage, evenPage, oddPage, nextColumn");
|
|
80604
|
-
}
|
|
80605
|
-
let locator;
|
|
80606
|
-
try {
|
|
80607
|
-
locator = parseLocator(at);
|
|
80608
|
-
} catch (error) {
|
|
80609
|
-
if (error instanceof LocatorParseError) {
|
|
80610
|
-
return fail("INVALID_LOCATOR", error.message, HELP);
|
|
80611
|
-
}
|
|
80612
|
-
throw error;
|
|
80613
|
-
}
|
|
80614
|
-
const document4 = await openOrFail(filePath);
|
|
80615
|
-
if (typeof document4 === "number")
|
|
80616
|
-
return document4;
|
|
80617
|
-
const opts = {
|
|
80618
|
-
filePath,
|
|
80619
|
-
count,
|
|
80620
|
-
sectionType: typeRaw,
|
|
80621
|
-
authorFlag: parsed.values.author,
|
|
80622
|
-
trackFlag: Boolean(parsed.values.track),
|
|
80623
|
-
outputPath: parsed.values.output,
|
|
80624
|
-
dryRun: Boolean(parsed.values["dry-run"])
|
|
80625
|
-
};
|
|
80626
|
-
if (locator.kind === "blockRange") {
|
|
80627
|
-
const range = await resolveBlockRangeOrFail(document4, at);
|
|
80628
|
-
if (typeof range === "number")
|
|
80629
|
-
return range;
|
|
80630
|
-
return wrapRange(document4, range.parent, range.startIndex, range.endIndex, at, opts);
|
|
80631
|
-
}
|
|
80632
|
-
const blockRef = await resolveBlockOrFail(document4, at);
|
|
80633
|
-
if (typeof blockRef === "number")
|
|
80634
|
-
return blockRef;
|
|
80635
|
-
if (blockRef.node.tag === "w:sectPr") {
|
|
80636
|
-
return editSection(document4, blockRef, at, opts);
|
|
80637
|
-
}
|
|
80638
|
-
if (blockRef.node.tag === "w:p") {
|
|
80639
|
-
const index2 = blockRef.parent.indexOf(blockRef.node);
|
|
80640
|
-
return wrapRange(document4, blockRef.parent, index2, index2, at, opts);
|
|
80641
|
-
}
|
|
80642
|
-
return fail("INVALID_LOCATOR", `columns needs a section (sN) or a paragraph range (pN-pM); ${at} is neither`, HELP);
|
|
80643
|
-
}
|
|
80644
|
-
async function editSection(document4, blockRef, at, opts) {
|
|
80645
|
-
try {
|
|
80646
|
-
new Edit(document4).section(blockRef, { columns: opts.count, sectionType: opts.sectionType }, { authorFlag: opts.authorFlag, track: opts.trackFlag });
|
|
80647
|
-
} catch (error) {
|
|
80648
|
-
if (error instanceof EditError)
|
|
80649
|
-
return fail(error.code, error.message);
|
|
80650
|
-
throw error;
|
|
80651
|
-
}
|
|
80652
|
-
return commit(document4, opts, { at, mode: "section" });
|
|
80653
|
-
}
|
|
80654
|
-
async function wrapRange(document4, parent, startIndex, endIndex, at, opts) {
|
|
80655
|
-
if (parent !== document4.body.findBodyChildren()) {
|
|
80656
|
-
return fail("USAGE", `columns can only wrap body-level paragraphs; ${at} is inside a table cell`, "Section breaks carry column layout and cannot live in a table cell.");
|
|
80657
|
-
}
|
|
80658
|
-
for (let index2 = startIndex;index2 <= endIndex; index2++) {
|
|
80659
|
-
if (containsSectionBreak(parent[index2])) {
|
|
80660
|
-
return fail("USAGE", `The range ${at} already contains a section break`, "Target the existing section directly with `--at sN`, or pick a range without one.");
|
|
80661
|
-
}
|
|
80662
|
-
}
|
|
80663
|
-
const governing = governingColumns(parent, endIndex + 1);
|
|
80664
|
-
const track = resolveTracked(document4, opts.trackFlag);
|
|
80665
|
-
const insert = new Insert(document4);
|
|
80666
|
-
const allocator = track ? new TrackChanges(document4).createAllocator() : undefined;
|
|
80667
|
-
const endNode = parent[endIndex];
|
|
80668
|
-
if (!endNode) {
|
|
80669
|
-
return fail("BLOCK_NOT_FOUND", "Range end is stale (parent does not contain it)");
|
|
80670
|
-
}
|
|
80671
|
-
const startNode = startIndex > 0 ? parent[startIndex] : undefined;
|
|
80672
|
-
if (startIndex > 0 && !startNode) {
|
|
80673
|
-
return fail("BLOCK_NOT_FOUND", "Range start is stale (parent does not contain it)");
|
|
80674
|
-
}
|
|
80675
|
-
let afterBlocks;
|
|
80676
|
-
let beforeBlocks = [];
|
|
80677
|
-
try {
|
|
80678
|
-
afterBlocks = await insert.paragraph({ node: endNode, parent }, {
|
|
80679
|
-
kind: "section",
|
|
80680
|
-
columns: opts.count,
|
|
80681
|
-
sectionType: opts.sectionType ?? "continuous"
|
|
80682
|
-
}, {}, { placement: "after", authorFlag: opts.authorFlag, track, allocator });
|
|
80683
|
-
if (startNode) {
|
|
80684
|
-
beforeBlocks = await insert.paragraph({ node: startNode, parent }, {
|
|
80685
|
-
kind: "section",
|
|
80686
|
-
...governing > 1 ? { columns: governing } : {},
|
|
80687
|
-
sectionType: "continuous"
|
|
80688
|
-
}, {}, { placement: "before", authorFlag: opts.authorFlag, track, allocator });
|
|
80689
|
-
}
|
|
80690
|
-
} catch (error) {
|
|
80691
|
-
if (error instanceof InsertError)
|
|
80692
|
-
return fail(error.code, error.message, error.hint);
|
|
80693
|
-
throw error;
|
|
80694
|
-
}
|
|
80695
|
-
if (opts.dryRun) {
|
|
80696
|
-
return commit(document4, opts, { at, mode: "range", dryRunOnly: true });
|
|
80697
|
-
}
|
|
80698
|
-
parent.splice(endIndex + 1, 0, ...afterBlocks);
|
|
80699
|
-
parent.splice(startIndex, 0, ...beforeBlocks);
|
|
80700
|
-
return commit(document4, opts, { at, mode: "range" });
|
|
80701
|
-
}
|
|
80702
|
-
function containsSectionBreak(node2) {
|
|
80703
|
-
if (!node2)
|
|
80704
|
-
return false;
|
|
80705
|
-
if (node2.tag === "w:sectPr")
|
|
80706
|
-
return true;
|
|
80707
|
-
if (node2.tag !== "w:p")
|
|
80708
|
-
return false;
|
|
80709
|
-
return Boolean(node2.findChild("w:pPr")?.findChild("w:sectPr"));
|
|
80710
|
-
}
|
|
80711
|
-
function governingColumns(parent, fromIndex) {
|
|
80712
|
-
for (let index2 = fromIndex;index2 < parent.length; index2++) {
|
|
80713
|
-
const node2 = parent[index2];
|
|
80714
|
-
if (!node2)
|
|
80715
|
-
continue;
|
|
80716
|
-
if (node2.tag === "w:sectPr")
|
|
80717
|
-
return columnsOf(node2);
|
|
80718
|
-
if (node2.tag === "w:p") {
|
|
80719
|
-
const inline = node2.findChild("w:pPr")?.findChild("w:sectPr");
|
|
80720
|
-
if (inline)
|
|
80721
|
-
return columnsOf(inline);
|
|
80722
|
-
}
|
|
80723
|
-
}
|
|
80724
|
-
return 1;
|
|
80644
|
+
// src/cli/parse-helpers.ts
|
|
80645
|
+
function detectMarkdownInPlainText(text6) {
|
|
80646
|
+
if (/\*\*[^*\n]+\*\*/.test(text6))
|
|
80647
|
+
return "bold (**\u2026**)";
|
|
80648
|
+
if (/__[^_\n]+__/.test(text6))
|
|
80649
|
+
return "bold (__\u2026__)";
|
|
80650
|
+
if (/(^|\n) {0,3}#{1,6}\s/.test(text6))
|
|
80651
|
+
return "a heading (#\u2026)";
|
|
80652
|
+
if (/\[[^\]\n]+\]\([^)\n]+\)/.test(text6))
|
|
80653
|
+
return "a link ([text](url))";
|
|
80654
|
+
return null;
|
|
80725
80655
|
}
|
|
80726
|
-
function
|
|
80727
|
-
const
|
|
80728
|
-
|
|
80729
|
-
|
|
80656
|
+
async function rejectMarkdownInText(text6, help) {
|
|
80657
|
+
const found = detectMarkdownInPlainText(text6);
|
|
80658
|
+
if (!found)
|
|
80659
|
+
return null;
|
|
80660
|
+
return await fail("USAGE", `--text writes literal characters, but this value looks like markdown: ${found}. It would be baked in verbatim (e.g. literal ** around the word), not rendered.`, `Use --markdown to parse it (handles ${found}, headings, lists, links), --bold/--italic for a uniformly-emphasized run, or --runs for literal text that really contains these characters. Help:
|
|
80661
|
+
${help}`);
|
|
80730
80662
|
}
|
|
80731
|
-
function
|
|
80732
|
-
|
|
80733
|
-
|
|
80734
|
-
if (!/^\d+$/.test(raw.trim()))
|
|
80735
|
-
return Number.NaN;
|
|
80736
|
-
const parsed = Number.parseInt(raw, 10);
|
|
80737
|
-
if (!Number.isFinite(parsed) || parsed < 1)
|
|
80738
|
-
return Number.NaN;
|
|
80739
|
-
return parsed;
|
|
80663
|
+
function detectShellMangledCurrency(text6) {
|
|
80664
|
+
const match = text6.match(/(?<![\d$])([.,]\d{2,})/);
|
|
80665
|
+
return match?.[1] ?? null;
|
|
80740
80666
|
}
|
|
80741
|
-
async function
|
|
80742
|
-
|
|
80743
|
-
|
|
80744
|
-
|
|
80745
|
-
|
|
80746
|
-
|
|
80747
|
-
locator: meta.at,
|
|
80748
|
-
columnCount: opts.count,
|
|
80749
|
-
mode: meta.mode,
|
|
80750
|
-
...opts.outputPath ? { output: opts.outputPath } : {}
|
|
80751
|
-
});
|
|
80752
|
-
return EXIT2.OK;
|
|
80753
|
-
}
|
|
80754
|
-
await document4.save(opts.outputPath);
|
|
80755
|
-
await respondAck({
|
|
80756
|
-
ok: true,
|
|
80757
|
-
operation: "columns",
|
|
80758
|
-
path: opts.outputPath ?? opts.filePath,
|
|
80759
|
-
locator: meta.at,
|
|
80760
|
-
columnCount: opts.count,
|
|
80761
|
-
mode: meta.mode
|
|
80762
|
-
});
|
|
80763
|
-
return EXIT2.OK;
|
|
80667
|
+
async function rejectShellMangledValue(text6, help, label = "this value") {
|
|
80668
|
+
const fragment = detectShellMangledCurrency(text6);
|
|
80669
|
+
if (!fragment)
|
|
80670
|
+
return null;
|
|
80671
|
+
return await fail("USAGE", `${label} contains "${fragment}" \u2014 a number with no integer part, the signature of a "$" amount gutted by the shell (bash turns double-quoted "$300.00" into ".00" and "$10,000" into ",000"). docx would write the corrupted value verbatim.`, `Wrap any "$"-bearing value in SINGLE quotes ('$300.00') so bash leaves it alone, or supply it via --batch FILE (JSONL never touches the shell). If you really mean "${fragment}", write its integer part (0${fragment}) or use --batch. Help:
|
|
80672
|
+
${help}`);
|
|
80764
80673
|
}
|
|
80765
|
-
var HELP = `docx columns \u2014 lay text out in multiple columns
|
|
80766
|
-
|
|
80767
|
-
Usage:
|
|
80768
|
-
docx columns FILE --at LOCATOR --count N [options]
|
|
80769
|
-
|
|
80770
|
-
The intuitive verb for column layout, so you don't have to hand-build section
|
|
80771
|
-
breaks. Two addressing modes:
|
|
80772
|
-
|
|
80773
|
-
--at pN-pM Wrap the paragraph range pN\u2026pM in its own N-column section
|
|
80774
|
-
(inserts the bounding continuous section breaks for you). Also
|
|
80775
|
-
accepts a single paragraph (--at pN).
|
|
80776
|
-
--at sN Set the column count on an EXISTING section break sN (the section
|
|
80777
|
-
whose content ENDS at sN). Equivalent to \`edit --at sN --columns N\`.
|
|
80778
|
-
|
|
80779
|
-
Options:
|
|
80780
|
-
--at LOCATOR Paragraph range (pN-pM), single paragraph (pN), or section (sN)
|
|
80781
|
-
--count N Number of columns (>= 1; use 1 to collapse back to single column)
|
|
80782
|
-
--type T Section type for the wrapping break: continuous (default),
|
|
80783
|
-
nextPage, evenPage, oddPage, nextColumn. Only meaningful with
|
|
80784
|
-
a pN-pM/pN range; with sN it overrides the section's type.
|
|
80785
|
-
--author NAME Author for tracked changes (default: $DOCX_AUTHOR)
|
|
80786
|
-
--track Record as a tracked change even when the doc toggle is off
|
|
80787
|
-
-o, --output PATH Write to PATH instead of overwriting FILE
|
|
80788
|
-
--dry-run Print what would change; do not write the file
|
|
80789
|
-
-v, --verbose Print the full success ack JSON
|
|
80790
|
-
-h, --help Show this help
|
|
80791
|
-
|
|
80792
|
-
Agent tip: VERIFY LAYOUT VISUALLY. \`docx read\` shows the section as a
|
|
80793
|
-
\`<!-- docx:section \u2026 cols="N" -->\` annotation but NOT how the columns actually
|
|
80794
|
-
flow on the page (balance, overflow). After setting columns, render and look:
|
|
80795
|
-
docx render FILE --out pages/
|
|
80796
|
-
Adjust the range and re-render until the columns read the way you intended.
|
|
80797
|
-
|
|
80798
|
-
Output:
|
|
80799
|
-
Prints a one-line confirmation on success (exit 0); --verbose prints {ok:true, \u2026}. Positional ids shift
|
|
80800
|
-
after a range wrap (two section breaks are inserted), so re-read before further
|
|
80801
|
-
edits. Errors print {code, error, hint?} + nonzero exit.
|
|
80802
|
-
|
|
80803
|
-
Examples:
|
|
80804
|
-
docx columns doc.docx --at p4-p9 --count 2
|
|
80805
|
-
docx columns doc.docx --at p4-p9 --count 3 --type continuous
|
|
80806
|
-
docx columns doc.docx --at s2 --count 1 # collapse section s2 to one column
|
|
80807
|
-
`, OPTION_SPEC;
|
|
80808
|
-
var init_columns = __esm(() => {
|
|
80809
|
-
init_core2();
|
|
80810
|
-
init_respond();
|
|
80811
|
-
OPTION_SPEC = {
|
|
80812
|
-
at: { type: "string" },
|
|
80813
|
-
count: { type: "string" },
|
|
80814
|
-
type: { type: "string" },
|
|
80815
|
-
author: { type: "string" },
|
|
80816
|
-
track: { type: "boolean" },
|
|
80817
|
-
...SAVE_FLAGS
|
|
80818
|
-
};
|
|
80819
|
-
});
|
|
80820
|
-
|
|
80821
|
-
// src/cli/parse-helpers.ts
|
|
80822
80674
|
function parseTaskFlag(value) {
|
|
80823
80675
|
const normalized = value.toLowerCase();
|
|
80824
80676
|
if (normalized === "checked" || normalized === "true" || normalized === "1")
|
|
@@ -80849,9 +80701,9 @@ async function parseRunsArg(json2) {
|
|
|
80849
80701
|
return fail("USAGE", "--runs must be a JSON array of Run objects");
|
|
80850
80702
|
}
|
|
80851
80703
|
const runs = parsed;
|
|
80852
|
-
for (const
|
|
80853
|
-
if (
|
|
80854
|
-
const invalid = firstInvalidRunFormat(
|
|
80704
|
+
for (const run of runs) {
|
|
80705
|
+
if (run !== null && typeof run === "object" && run.type === "text") {
|
|
80706
|
+
const invalid = firstInvalidRunFormat(run);
|
|
80855
80707
|
if (invalid) {
|
|
80856
80708
|
return fail("USAGE", `Invalid ${invalid.field} "${invalid.value}" in a --runs text run`, `Use ${invalid.valid}.`);
|
|
80857
80709
|
}
|
|
@@ -80937,9 +80789,9 @@ var init_parse_helpers = __esm(() => {
|
|
|
80937
80789
|
// src/cli/comments/add.tsx
|
|
80938
80790
|
var exports_add = {};
|
|
80939
80791
|
__export(exports_add, {
|
|
80940
|
-
run: () =>
|
|
80792
|
+
run: () => run
|
|
80941
80793
|
});
|
|
80942
|
-
async function
|
|
80794
|
+
async function run(args) {
|
|
80943
80795
|
const parsed = await tryParseArgs(args, {
|
|
80944
80796
|
at: { type: "string" },
|
|
80945
80797
|
anchor: { type: "string" },
|
|
@@ -80950,17 +80802,17 @@ async function run2(args) {
|
|
|
80950
80802
|
current: { type: "boolean" },
|
|
80951
80803
|
baseline: { type: "boolean" },
|
|
80952
80804
|
...SAVE_FLAGS
|
|
80953
|
-
},
|
|
80805
|
+
}, HELP);
|
|
80954
80806
|
if (typeof parsed === "number")
|
|
80955
80807
|
return parsed;
|
|
80956
80808
|
if (parsed.values.help) {
|
|
80957
|
-
await writeStdout(
|
|
80809
|
+
await writeStdout(HELP);
|
|
80958
80810
|
return EXIT2.OK;
|
|
80959
80811
|
}
|
|
80960
80812
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
80961
80813
|
const path2 = parsed.positionals[0];
|
|
80962
80814
|
if (!path2)
|
|
80963
|
-
return fail("USAGE", "Missing FILE argument",
|
|
80815
|
+
return fail("USAGE", "Missing FILE argument", HELP);
|
|
80964
80816
|
const atInput = parsed.values.at;
|
|
80965
80817
|
const anchorInput = parsed.values.anchor;
|
|
80966
80818
|
const batchInput = parsed.values.batch;
|
|
@@ -80975,10 +80827,10 @@ async function run2(args) {
|
|
|
80975
80827
|
}
|
|
80976
80828
|
const anchorCount = (atInput ? 1 : 0) + (anchorInput ? 1 : 0) + (batchInput ? 1 : 0);
|
|
80977
80829
|
if (anchorCount === 0) {
|
|
80978
|
-
return fail("USAGE", "Specify exactly one of --at, --anchor, or --batch",
|
|
80830
|
+
return fail("USAGE", "Specify exactly one of --at, --anchor, or --batch", HELP);
|
|
80979
80831
|
}
|
|
80980
80832
|
if (anchorCount > 1) {
|
|
80981
|
-
return fail("USAGE", "--at, --anchor, and --batch are mutually exclusive",
|
|
80833
|
+
return fail("USAGE", "--at, --anchor, and --batch are mutually exclusive", HELP);
|
|
80982
80834
|
}
|
|
80983
80835
|
const document4 = await openOrFail(path2);
|
|
80984
80836
|
if (typeof document4 === "number")
|
|
@@ -80986,7 +80838,7 @@ async function run2(args) {
|
|
|
80986
80838
|
let rawEntries;
|
|
80987
80839
|
if (batchInput) {
|
|
80988
80840
|
if (text6 !== undefined || atInput || anchorInput || occurrenceRaw) {
|
|
80989
|
-
return fail("USAGE", "--batch reads each entry's at/anchor/text/author from JSONL \u2014 do not pass them on the CLI",
|
|
80841
|
+
return fail("USAGE", "--batch reads each entry's at/anchor/text/author from JSONL \u2014 do not pass them on the CLI", HELP);
|
|
80990
80842
|
}
|
|
80991
80843
|
try {
|
|
80992
80844
|
rawEntries = await readJsonlObjects(batchInput);
|
|
@@ -80999,7 +80851,7 @@ async function run2(args) {
|
|
|
80999
80851
|
}
|
|
81000
80852
|
} else {
|
|
81001
80853
|
if (!text6)
|
|
81002
|
-
return fail("USAGE", "Missing --text TEXT",
|
|
80854
|
+
return fail("USAGE", "Missing --text TEXT", HELP);
|
|
81003
80855
|
const occurrence = occurrenceRaw === undefined ? undefined : Number(occurrenceRaw);
|
|
81004
80856
|
if (occurrence !== undefined && (!Number.isInteger(occurrence) || occurrence < 1)) {
|
|
81005
80857
|
return fail("USAGE", `--occurrence must be a positive integer (1-indexed), got "${occurrenceRaw}"`);
|
|
@@ -81173,14 +81025,14 @@ function resolveAnchorEntry(document4, anchor, occurrence, occurrenceExplicit, t
|
|
|
81173
81025
|
locatorString
|
|
81174
81026
|
};
|
|
81175
81027
|
}
|
|
81176
|
-
var AT_FORMS,
|
|
81028
|
+
var AT_FORMS, HELP, EntryError;
|
|
81177
81029
|
var init_add = __esm(() => {
|
|
81178
81030
|
init_core2();
|
|
81179
81031
|
init_find();
|
|
81180
81032
|
init_parse_helpers();
|
|
81181
81033
|
init_respond();
|
|
81182
81034
|
AT_FORMS = describeForms(["paragraph", "span", "crossSpan", "cellParagraph", "cellSpan"], " ");
|
|
81183
|
-
|
|
81035
|
+
HELP = `docx comments add \u2014 anchor a new comment to a locator or phrase
|
|
81184
81036
|
|
|
81185
81037
|
Usage:
|
|
81186
81038
|
docx comments add FILE --at LOCATOR --text TEXT [options]
|
|
@@ -81254,31 +81106,31 @@ Batch JSONL example:
|
|
|
81254
81106
|
// src/cli/comments/delete.ts
|
|
81255
81107
|
var exports_delete = {};
|
|
81256
81108
|
__export(exports_delete, {
|
|
81257
|
-
run: () =>
|
|
81109
|
+
run: () => run2
|
|
81258
81110
|
});
|
|
81259
|
-
async function
|
|
81111
|
+
async function run2(args) {
|
|
81260
81112
|
const parsed = await tryParseArgs(args, {
|
|
81261
81113
|
at: { type: "string", multiple: true },
|
|
81262
81114
|
batch: { type: "string" },
|
|
81263
81115
|
...SAVE_FLAGS
|
|
81264
|
-
},
|
|
81116
|
+
}, HELP2);
|
|
81265
81117
|
if (typeof parsed === "number")
|
|
81266
81118
|
return parsed;
|
|
81267
81119
|
if (parsed.values.help) {
|
|
81268
|
-
await writeStdout(
|
|
81120
|
+
await writeStdout(HELP2);
|
|
81269
81121
|
return EXIT2.OK;
|
|
81270
81122
|
}
|
|
81271
81123
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
81272
81124
|
const path2 = parsed.positionals[0];
|
|
81273
81125
|
if (!path2)
|
|
81274
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81126
|
+
return fail("USAGE", "Missing FILE argument", HELP2);
|
|
81275
81127
|
const atValues = parsed.values.at ?? [];
|
|
81276
81128
|
const batchInput = parsed.values.batch;
|
|
81277
81129
|
if (atValues.length > 0 && batchInput) {
|
|
81278
|
-
return fail("USAGE", "--at and --batch are mutually exclusive",
|
|
81130
|
+
return fail("USAGE", "--at and --batch are mutually exclusive", HELP2);
|
|
81279
81131
|
}
|
|
81280
81132
|
if (atValues.length === 0 && !batchInput) {
|
|
81281
|
-
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE",
|
|
81133
|
+
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE", HELP2);
|
|
81282
81134
|
}
|
|
81283
81135
|
let rawIds;
|
|
81284
81136
|
if (batchInput) {
|
|
@@ -81333,7 +81185,7 @@ async function run3(args) {
|
|
|
81333
81185
|
});
|
|
81334
81186
|
return EXIT2.OK;
|
|
81335
81187
|
}
|
|
81336
|
-
var
|
|
81188
|
+
var HELP2 = `docx comments delete \u2014 remove one or more comments
|
|
81337
81189
|
|
|
81338
81190
|
Usage:
|
|
81339
81191
|
docx comments delete FILE --at cN [--at cM ...] [options]
|
|
@@ -81372,23 +81224,23 @@ var init_delete = __esm(() => {
|
|
|
81372
81224
|
// src/cli/comments/list.ts
|
|
81373
81225
|
var exports_list = {};
|
|
81374
81226
|
__export(exports_list, {
|
|
81375
|
-
run: () =>
|
|
81227
|
+
run: () => run3
|
|
81376
81228
|
});
|
|
81377
|
-
async function
|
|
81229
|
+
async function run3(args) {
|
|
81378
81230
|
const parsed = await tryParseArgs(args, {
|
|
81379
81231
|
"include-resolved": { type: "boolean" },
|
|
81380
81232
|
thread: { type: "string" },
|
|
81381
81233
|
help: { type: "boolean", short: "h" }
|
|
81382
|
-
},
|
|
81234
|
+
}, HELP3);
|
|
81383
81235
|
if (typeof parsed === "number")
|
|
81384
81236
|
return parsed;
|
|
81385
81237
|
if (parsed.values.help) {
|
|
81386
|
-
await writeStdout(
|
|
81238
|
+
await writeStdout(HELP3);
|
|
81387
81239
|
return EXIT2.OK;
|
|
81388
81240
|
}
|
|
81389
81241
|
const path2 = parsed.positionals[0];
|
|
81390
81242
|
if (!path2)
|
|
81391
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81243
|
+
return fail("USAGE", "Missing FILE argument", HELP3);
|
|
81392
81244
|
const document4 = await openOrFail(path2);
|
|
81393
81245
|
if (typeof document4 === "number")
|
|
81394
81246
|
return document4;
|
|
@@ -81399,7 +81251,7 @@ async function run4(args) {
|
|
|
81399
81251
|
await respond(comments);
|
|
81400
81252
|
return EXIT2.OK;
|
|
81401
81253
|
}
|
|
81402
|
-
var
|
|
81254
|
+
var HELP3 = `docx comments list \u2014 print existing comments as JSON
|
|
81403
81255
|
|
|
81404
81256
|
Usage:
|
|
81405
81257
|
docx comments list FILE [options]
|
|
@@ -81427,31 +81279,31 @@ var init_list3 = __esm(() => {
|
|
|
81427
81279
|
// src/cli/comments/reply.tsx
|
|
81428
81280
|
var exports_reply = {};
|
|
81429
81281
|
__export(exports_reply, {
|
|
81430
|
-
run: () =>
|
|
81282
|
+
run: () => run4
|
|
81431
81283
|
});
|
|
81432
|
-
async function
|
|
81284
|
+
async function run4(args) {
|
|
81433
81285
|
const parsed = await tryParseArgs(args, {
|
|
81434
81286
|
at: { type: "string" },
|
|
81435
81287
|
text: { type: "string" },
|
|
81436
81288
|
author: { type: "string" },
|
|
81437
81289
|
...SAVE_FLAGS
|
|
81438
|
-
},
|
|
81290
|
+
}, HELP4);
|
|
81439
81291
|
if (typeof parsed === "number")
|
|
81440
81292
|
return parsed;
|
|
81441
81293
|
if (parsed.values.help) {
|
|
81442
|
-
await writeStdout(
|
|
81294
|
+
await writeStdout(HELP4);
|
|
81443
81295
|
return EXIT2.OK;
|
|
81444
81296
|
}
|
|
81445
81297
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
81446
81298
|
const path2 = parsed.positionals[0];
|
|
81447
81299
|
if (!path2)
|
|
81448
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81300
|
+
return fail("USAGE", "Missing FILE argument", HELP4);
|
|
81449
81301
|
const parentInput = parsed.values.at;
|
|
81450
81302
|
const text6 = parsed.values.text;
|
|
81451
81303
|
if (!parentInput)
|
|
81452
|
-
return fail("USAGE", "Missing --at cN",
|
|
81304
|
+
return fail("USAGE", "Missing --at cN", HELP4);
|
|
81453
81305
|
if (!text6)
|
|
81454
|
-
return fail("USAGE", "Missing --text TEXT",
|
|
81306
|
+
return fail("USAGE", "Missing --text TEXT", HELP4);
|
|
81455
81307
|
const document4 = await openOrFail(path2);
|
|
81456
81308
|
if (typeof document4 === "number")
|
|
81457
81309
|
return document4;
|
|
@@ -81492,7 +81344,7 @@ async function run5(args) {
|
|
|
81492
81344
|
});
|
|
81493
81345
|
return EXIT2.OK;
|
|
81494
81346
|
}
|
|
81495
|
-
var
|
|
81347
|
+
var HELP4 = `docx comments reply \u2014 reply to an existing comment
|
|
81496
81348
|
|
|
81497
81349
|
Usage:
|
|
81498
81350
|
docx comments reply FILE --at cN --text TEXT [options]
|
|
@@ -81525,33 +81377,33 @@ var init_reply = __esm(() => {
|
|
|
81525
81377
|
// src/cli/comments/resolve.ts
|
|
81526
81378
|
var exports_resolve = {};
|
|
81527
81379
|
__export(exports_resolve, {
|
|
81528
|
-
run: () =>
|
|
81380
|
+
run: () => run5
|
|
81529
81381
|
});
|
|
81530
|
-
async function
|
|
81382
|
+
async function run5(args) {
|
|
81531
81383
|
const parsed = await tryParseArgs(args, {
|
|
81532
81384
|
at: { type: "string", multiple: true },
|
|
81533
81385
|
batch: { type: "string" },
|
|
81534
81386
|
unset: { type: "boolean" },
|
|
81535
81387
|
...SAVE_FLAGS
|
|
81536
|
-
},
|
|
81388
|
+
}, HELP5);
|
|
81537
81389
|
if (typeof parsed === "number")
|
|
81538
81390
|
return parsed;
|
|
81539
81391
|
if (parsed.values.help) {
|
|
81540
|
-
await writeStdout(
|
|
81392
|
+
await writeStdout(HELP5);
|
|
81541
81393
|
return EXIT2.OK;
|
|
81542
81394
|
}
|
|
81543
81395
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
81544
81396
|
const path2 = parsed.positionals[0];
|
|
81545
81397
|
if (!path2)
|
|
81546
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81398
|
+
return fail("USAGE", "Missing FILE argument", HELP5);
|
|
81547
81399
|
const atValues = parsed.values.at ?? [];
|
|
81548
81400
|
const batchInput = parsed.values.batch;
|
|
81549
81401
|
const resolved = !parsed.values.unset;
|
|
81550
81402
|
if (atValues.length > 0 && batchInput) {
|
|
81551
|
-
return fail("USAGE", "--at and --batch are mutually exclusive",
|
|
81403
|
+
return fail("USAGE", "--at and --batch are mutually exclusive", HELP5);
|
|
81552
81404
|
}
|
|
81553
81405
|
if (atValues.length === 0 && !batchInput) {
|
|
81554
|
-
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE",
|
|
81406
|
+
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE", HELP5);
|
|
81555
81407
|
}
|
|
81556
81408
|
let rawIds;
|
|
81557
81409
|
if (batchInput) {
|
|
@@ -81608,7 +81460,7 @@ async function run6(args) {
|
|
|
81608
81460
|
});
|
|
81609
81461
|
return EXIT2.OK;
|
|
81610
81462
|
}
|
|
81611
|
-
var
|
|
81463
|
+
var HELP5 = `docx comments resolve \u2014 mark one or more comments resolved
|
|
81612
81464
|
|
|
81613
81465
|
Usage:
|
|
81614
81466
|
docx comments resolve FILE --at cN [--at cM ...] [options]
|
|
@@ -81649,12 +81501,12 @@ var init_resolve2 = __esm(() => {
|
|
|
81649
81501
|
// src/cli/comments/index.ts
|
|
81650
81502
|
var exports_comments = {};
|
|
81651
81503
|
__export(exports_comments, {
|
|
81652
|
-
run: () =>
|
|
81504
|
+
run: () => run6
|
|
81653
81505
|
});
|
|
81654
|
-
async function
|
|
81506
|
+
async function run6(args) {
|
|
81655
81507
|
const verb = args[0];
|
|
81656
81508
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
81657
|
-
await writeStdout(
|
|
81509
|
+
await writeStdout(HELP6);
|
|
81658
81510
|
return verb ? 0 : 2;
|
|
81659
81511
|
}
|
|
81660
81512
|
const loader = SUBCOMMANDS[verb];
|
|
@@ -81664,7 +81516,7 @@ async function run7(args) {
|
|
|
81664
81516
|
const module_ = await loader();
|
|
81665
81517
|
return module_.run(args.slice(1));
|
|
81666
81518
|
}
|
|
81667
|
-
var SUBCOMMANDS,
|
|
81519
|
+
var SUBCOMMANDS, HELP6 = `docx comments \u2014 manage Word comments
|
|
81668
81520
|
|
|
81669
81521
|
Usage:
|
|
81670
81522
|
docx comments <verb> FILE [options]
|
|
@@ -81984,9 +81836,9 @@ var init_create = __esm(() => {
|
|
|
81984
81836
|
// src/cli/create/index.tsx
|
|
81985
81837
|
var exports_create = {};
|
|
81986
81838
|
__export(exports_create, {
|
|
81987
|
-
run: () =>
|
|
81839
|
+
run: () => run7
|
|
81988
81840
|
});
|
|
81989
|
-
async function
|
|
81841
|
+
async function run7(args) {
|
|
81990
81842
|
const parsed = await tryParseArgs(args, {
|
|
81991
81843
|
title: { type: "string" },
|
|
81992
81844
|
author: { type: "string" },
|
|
@@ -81996,17 +81848,17 @@ async function run8(args) {
|
|
|
81996
81848
|
"dry-run": { type: "boolean" },
|
|
81997
81849
|
verbose: { type: "boolean", short: "v" },
|
|
81998
81850
|
help: { type: "boolean", short: "h" }
|
|
81999
|
-
},
|
|
81851
|
+
}, HELP7);
|
|
82000
81852
|
if (typeof parsed === "number")
|
|
82001
81853
|
return parsed;
|
|
82002
81854
|
if (parsed.values.help) {
|
|
82003
|
-
await writeStdout(
|
|
81855
|
+
await writeStdout(HELP7);
|
|
82004
81856
|
return EXIT2.OK;
|
|
82005
81857
|
}
|
|
82006
81858
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
82007
81859
|
const path2 = parsed.positionals[0];
|
|
82008
81860
|
if (!path2) {
|
|
82009
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81861
|
+
return fail("USAGE", "Missing FILE argument", HELP7);
|
|
82010
81862
|
}
|
|
82011
81863
|
const text6 = parsed.values.text;
|
|
82012
81864
|
const fromPath = parsed.values.from;
|
|
@@ -82078,7 +81930,7 @@ async function applyMarkdownToBody(docxPath, markdownPath) {
|
|
|
82078
81930
|
await document4.save();
|
|
82079
81931
|
return { blockCount: blocks.length };
|
|
82080
81932
|
}
|
|
82081
|
-
var
|
|
81933
|
+
var HELP7 = `docx create \u2014 create a new minimal .docx
|
|
82082
81934
|
|
|
82083
81935
|
Usage:
|
|
82084
81936
|
docx create FILE [options]
|
|
@@ -82220,27 +82072,27 @@ var init_batch = __esm(() => {
|
|
|
82220
82072
|
// src/cli/delete/index.tsx
|
|
82221
82073
|
var exports_delete2 = {};
|
|
82222
82074
|
__export(exports_delete2, {
|
|
82223
|
-
run: () =>
|
|
82075
|
+
run: () => run8
|
|
82224
82076
|
});
|
|
82225
|
-
async function
|
|
82226
|
-
const parsed = await tryParseArgs(args,
|
|
82077
|
+
async function run8(args) {
|
|
82078
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC, HELP8);
|
|
82227
82079
|
if (typeof parsed === "number")
|
|
82228
82080
|
return parsed;
|
|
82229
82081
|
if (parsed.values.help) {
|
|
82230
|
-
await writeStdout(
|
|
82082
|
+
await writeStdout(HELP8);
|
|
82231
82083
|
return EXIT2.OK;
|
|
82232
82084
|
}
|
|
82233
82085
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
82234
82086
|
const filePath = parsed.positionals[0];
|
|
82235
82087
|
if (!filePath)
|
|
82236
|
-
return fail("USAGE", "Missing FILE argument",
|
|
82088
|
+
return fail("USAGE", "Missing FILE argument", HELP8);
|
|
82237
82089
|
const batchSource = parsed.values.batch;
|
|
82238
82090
|
if (batchSource !== undefined) {
|
|
82239
82091
|
return runDeleteBatch(filePath, batchSource, parsed.values);
|
|
82240
82092
|
}
|
|
82241
82093
|
const locator = parsed.values.at;
|
|
82242
82094
|
if (!locator)
|
|
82243
|
-
return fail("USAGE", "Missing --at LOCATOR (or --batch FILE)",
|
|
82095
|
+
return fail("USAGE", "Missing --at LOCATOR (or --batch FILE)", HELP8);
|
|
82244
82096
|
const opts = {
|
|
82245
82097
|
filePath,
|
|
82246
82098
|
locator,
|
|
@@ -82358,7 +82210,7 @@ function findBodyChildren(document4) {
|
|
|
82358
82210
|
return null;
|
|
82359
82211
|
return body.children;
|
|
82360
82212
|
}
|
|
82361
|
-
var
|
|
82213
|
+
var HELP8 = `docx delete \u2014 remove a block at a locator
|
|
82362
82214
|
|
|
82363
82215
|
Usage:
|
|
82364
82216
|
docx delete FILE --at LOCATOR [options]
|
|
@@ -82397,7 +82249,7 @@ Tracked behavior:
|
|
|
82397
82249
|
the paragraph mark as deleted (accept removes the paragraph by merging it
|
|
82398
82250
|
forward). Section deletion under tracking emits a [docx-cli] audit comment
|
|
82399
82251
|
on the owning paragraph if it has runs to anchor on; otherwise (sentinel
|
|
82400
|
-
|
|
82252
|
+
section sentinel paragraphs have no runs) the mutation is silent.
|
|
82401
82253
|
delete --at tN under tracking is rejected (tracked table-row deletion is
|
|
82402
82254
|
not supported).
|
|
82403
82255
|
|
|
@@ -82410,7 +82262,7 @@ Examples:
|
|
|
82410
82262
|
docx delete doc.docx --at t0
|
|
82411
82263
|
docx delete doc.docx --at s2
|
|
82412
82264
|
docx delete doc.docx --batch drop.jsonl # {"at":"p26"} per line
|
|
82413
|
-
`,
|
|
82265
|
+
`, OPTION_SPEC;
|
|
82414
82266
|
var init_delete2 = __esm(() => {
|
|
82415
82267
|
init_core2();
|
|
82416
82268
|
init_comments2();
|
|
@@ -82418,7 +82270,7 @@ var init_delete2 = __esm(() => {
|
|
|
82418
82270
|
init_replace();
|
|
82419
82271
|
init_respond();
|
|
82420
82272
|
init_batch();
|
|
82421
|
-
|
|
82273
|
+
OPTION_SPEC = {
|
|
82422
82274
|
at: { type: "string" },
|
|
82423
82275
|
batch: { type: "string" },
|
|
82424
82276
|
author: { type: "string" },
|
|
@@ -82427,6 +82279,42 @@ var init_delete2 = __esm(() => {
|
|
|
82427
82279
|
};
|
|
82428
82280
|
});
|
|
82429
82281
|
|
|
82282
|
+
// src/cli/edit/tabs.ts
|
|
82283
|
+
function parseTabsValue(value) {
|
|
82284
|
+
const normalized = value.trim().toLowerCase();
|
|
82285
|
+
if (normalized === "right" || normalized === "right-margin")
|
|
82286
|
+
return { kind: "right-margin" };
|
|
82287
|
+
if (normalized === "clear" || normalized === "none" || normalized === "off")
|
|
82288
|
+
return { kind: "clear" };
|
|
82289
|
+
const stops = [];
|
|
82290
|
+
for (const token of value.split(",")) {
|
|
82291
|
+
const match = token.trim().match(/^(left|right|center)@([\d.]+)in$/i);
|
|
82292
|
+
const align = (match?.[1] ?? "").toLowerCase();
|
|
82293
|
+
const inches = Number(match?.[2] ?? Number.NaN);
|
|
82294
|
+
if (!match || !TAB_ALIGNS.has(align) || !Number.isFinite(inches)) {
|
|
82295
|
+
return {
|
|
82296
|
+
error: `Invalid --tabs value: "${token.trim()}"`,
|
|
82297
|
+
hint: TABS_HINT
|
|
82298
|
+
};
|
|
82299
|
+
}
|
|
82300
|
+
stops.push({ align, pos: Math.round(inches * 1440) });
|
|
82301
|
+
}
|
|
82302
|
+
return { kind: "explicit", stops };
|
|
82303
|
+
}
|
|
82304
|
+
function resolveTabsDirective(directive, document4) {
|
|
82305
|
+
if (directive.kind === "clear")
|
|
82306
|
+
return [];
|
|
82307
|
+
if (directive.kind === "explicit")
|
|
82308
|
+
return directive.stops;
|
|
82309
|
+
const marginTwips = Math.round(getPageContentWidthEmu(document4) / 635);
|
|
82310
|
+
return [{ align: "right", pos: marginTwips }];
|
|
82311
|
+
}
|
|
82312
|
+
var TAB_ALIGNS, TABS_HINT = "Use `right` (a right tab at the margin \u2014 cures the wrapping LEFT-tab `docx:layout` warning from `read`), `clear`, or explicit stops like `right@7.5in` / `left@1in,right@7.5in`.";
|
|
82313
|
+
var init_tabs = __esm(() => {
|
|
82314
|
+
init_core2();
|
|
82315
|
+
TAB_ALIGNS = new Set(["left", "right", "center"]);
|
|
82316
|
+
});
|
|
82317
|
+
|
|
82430
82318
|
// src/cli/edit/batch.ts
|
|
82431
82319
|
async function runEditBatch(filePath, batchSource, values2) {
|
|
82432
82320
|
const conflicting = SINGLE_SHOT_FLAGS.find((flag) => values2[flag] !== undefined && values2[flag] !== false);
|
|
@@ -82512,13 +82400,14 @@ async function runEditBatch(filePath, batchSource, values2) {
|
|
|
82512
82400
|
async function resolveEntry2(document4, raw, index2, opts) {
|
|
82513
82401
|
const present = CONTENT_KEYS.filter((key) => raw[key] !== undefined);
|
|
82514
82402
|
const hasClear = raw.clear !== undefined;
|
|
82515
|
-
|
|
82516
|
-
|
|
82403
|
+
const hasProps = raw.style !== undefined || raw.alignment !== undefined || raw.tabs !== undefined;
|
|
82404
|
+
if (present.length === 0 && !hasClear && !hasProps) {
|
|
82405
|
+
throw new EntryError2("USAGE", `entry ${index2}: no content \u2014 provide one of ${CONTENT_KEYS.join(", ")}, "clear", or "style"/"alignment"/"tabs" to adjust in place`);
|
|
82517
82406
|
}
|
|
82518
82407
|
if (present.length > 1) {
|
|
82519
82408
|
throw new EntryError2("USAGE", `entry ${index2}: provide exactly one content field, got ${present.join(", ")}`);
|
|
82520
82409
|
}
|
|
82521
|
-
const kind = present[0] ?? "clear";
|
|
82410
|
+
const kind = present[0] ?? (hasClear ? "clear" : "props");
|
|
82522
82411
|
const at = raw.at;
|
|
82523
82412
|
if (typeof at !== "string" || at.length === 0) {
|
|
82524
82413
|
throw new EntryError2("USAGE", `entry ${index2}: "at" is required`);
|
|
@@ -82557,6 +82446,13 @@ async function resolveEntry2(document4, raw, index2, opts) {
|
|
|
82557
82446
|
async function buildApply(document4, raw, index2, kind, blockRef, span, opts) {
|
|
82558
82447
|
const author = typeof raw.author === "string" ? raw.author : opts.authorFlag;
|
|
82559
82448
|
const clearTags = raw.clear !== undefined ? resolveClearOrThrow(raw.clear, index2) : null;
|
|
82449
|
+
if (kind === "props") {
|
|
82450
|
+
if (span) {
|
|
82451
|
+
throw new EntryError2("USAGE", `entry ${index2}: a character span (${raw.at}) can't take "style"/"alignment" \u2014 restyle the whole paragraph (pN).`);
|
|
82452
|
+
}
|
|
82453
|
+
const paragraphOptions = readParagraphOptions(document4, raw, index2);
|
|
82454
|
+
return () => void new Edit(document4).paragraphProperties(blockRef, paragraphOptions);
|
|
82455
|
+
}
|
|
82560
82456
|
if (kind === "clear") {
|
|
82561
82457
|
const tags = clearTags ?? new Set;
|
|
82562
82458
|
return () => new Edit(document4).clearFormatting(blockRef, span, tags);
|
|
@@ -82591,9 +82487,12 @@ async function buildApply(document4, raw, index2, kind, blockRef, span, opts) {
|
|
|
82591
82487
|
};
|
|
82592
82488
|
}
|
|
82593
82489
|
async function buildWholeParagraphContent(document4, raw, index2, kind, blockRef, author, opts) {
|
|
82594
|
-
const paragraphOptions = readParagraphOptions(raw, index2);
|
|
82490
|
+
const paragraphOptions = readParagraphOptions(document4, raw, index2);
|
|
82595
82491
|
if (kind === "text") {
|
|
82596
82492
|
const text6 = requireString(raw.text, index2, "text");
|
|
82493
|
+
if (text6 === "") {
|
|
82494
|
+
throw new EntryError2("USAGE", `entry ${index2}: empty "text" leaves a blank paragraph in place, it doesn't remove the line (${raw.at}).`, 'Remove lines with `docx delete --batch` ({ "at": "pN" } per line). To keep an empty spacer, use "runs": [] instead.');
|
|
82495
|
+
}
|
|
82597
82496
|
const format = readTextFormat(raw, index2);
|
|
82598
82497
|
return () => new Edit(document4).paragraph(blockRef, { kind: "text", text: text6, format, paragraphOptions }, {
|
|
82599
82498
|
authorFlag: author,
|
|
@@ -82691,8 +82590,8 @@ function rejectSpanFormatFlags(raw, index2) {
|
|
|
82691
82590
|
if (raw.color !== undefined || raw.bold !== undefined || raw.italic !== undefined) {
|
|
82692
82591
|
throw new EntryError2("USAGE", `entry ${index2}: --color/--bold/--italic aren't supported on a character span \u2014 the replacement inherits the run's formatting`);
|
|
82693
82592
|
}
|
|
82694
|
-
if (raw.style !== undefined || raw.alignment !== undefined) {
|
|
82695
|
-
throw new EntryError2("USAGE", `entry ${index2}: style/alignment apply to a whole paragraph, not a character span`);
|
|
82593
|
+
if (raw.style !== undefined || raw.alignment !== undefined || raw.tabs !== undefined) {
|
|
82594
|
+
throw new EntryError2("USAGE", `entry ${index2}: style/alignment/tabs apply to a whole paragraph, not a character span`);
|
|
82696
82595
|
}
|
|
82697
82596
|
}
|
|
82698
82597
|
function readTextFormat(raw, index2) {
|
|
@@ -82709,7 +82608,7 @@ function readTextFormat(raw, index2) {
|
|
|
82709
82608
|
out.italic = Boolean(raw.italic);
|
|
82710
82609
|
return out;
|
|
82711
82610
|
}
|
|
82712
|
-
function readParagraphOptions(raw, index2) {
|
|
82611
|
+
function readParagraphOptions(document4, raw, index2) {
|
|
82713
82612
|
const out = {};
|
|
82714
82613
|
if (raw.style !== undefined) {
|
|
82715
82614
|
if (typeof raw.style !== "string") {
|
|
@@ -82724,15 +82623,25 @@ function readParagraphOptions(raw, index2) {
|
|
|
82724
82623
|
}
|
|
82725
82624
|
out.alignment = alignment;
|
|
82726
82625
|
}
|
|
82626
|
+
if (raw.tabs !== undefined) {
|
|
82627
|
+
if (typeof raw.tabs !== "string") {
|
|
82628
|
+
throw new EntryError2("USAGE", `entry ${index2}: "tabs" must be a string`);
|
|
82629
|
+
}
|
|
82630
|
+
const parsed = parseTabsValue(raw.tabs);
|
|
82631
|
+
if ("error" in parsed) {
|
|
82632
|
+
throw new EntryError2("USAGE", `entry ${index2}: ${parsed.error}`, parsed.hint);
|
|
82633
|
+
}
|
|
82634
|
+
out.tabs = resolveTabsDirective(parsed, document4);
|
|
82635
|
+
}
|
|
82727
82636
|
return out;
|
|
82728
82637
|
}
|
|
82729
82638
|
function readRuns(value, index2) {
|
|
82730
82639
|
if (!Array.isArray(value)) {
|
|
82731
82640
|
throw new EntryError2("USAGE", `entry ${index2}: "runs" must be a JSON array of Run objects`);
|
|
82732
82641
|
}
|
|
82733
|
-
for (const
|
|
82734
|
-
if (
|
|
82735
|
-
const invalid = firstInvalidRunFormat(
|
|
82642
|
+
for (const run9 of value) {
|
|
82643
|
+
if (run9 !== null && typeof run9 === "object" && run9.type === "text") {
|
|
82644
|
+
const invalid = firstInvalidRunFormat(run9);
|
|
82736
82645
|
if (invalid) {
|
|
82737
82646
|
throw new EntryError2("USAGE", `entry ${index2}: invalid ${invalid.field} "${invalid.value}" in a run`, `Use ${invalid.valid}.`);
|
|
82738
82647
|
}
|
|
@@ -82761,6 +82670,7 @@ var init_batch2 = __esm(() => {
|
|
|
82761
82670
|
init_run_formatting();
|
|
82762
82671
|
init_parse_helpers();
|
|
82763
82672
|
init_respond();
|
|
82673
|
+
init_tabs();
|
|
82764
82674
|
SINGLE_SHOT_FLAGS = [
|
|
82765
82675
|
"at",
|
|
82766
82676
|
"text",
|
|
@@ -82778,6 +82688,7 @@ var init_batch2 = __esm(() => {
|
|
|
82778
82688
|
"type",
|
|
82779
82689
|
"style",
|
|
82780
82690
|
"alignment",
|
|
82691
|
+
"tabs",
|
|
82781
82692
|
"color",
|
|
82782
82693
|
"bold",
|
|
82783
82694
|
"italic"
|
|
@@ -82798,20 +82709,20 @@ var init_batch2 = __esm(() => {
|
|
|
82798
82709
|
// src/cli/edit/index.tsx
|
|
82799
82710
|
var exports_edit = {};
|
|
82800
82711
|
__export(exports_edit, {
|
|
82801
|
-
run: () =>
|
|
82712
|
+
run: () => run9
|
|
82802
82713
|
});
|
|
82803
|
-
async function
|
|
82804
|
-
const parsed = await tryParseArgs(args,
|
|
82714
|
+
async function run9(args) {
|
|
82715
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC2, HELP9);
|
|
82805
82716
|
if (typeof parsed === "number")
|
|
82806
82717
|
return parsed;
|
|
82807
82718
|
if (parsed.values.help) {
|
|
82808
|
-
await writeStdout(
|
|
82719
|
+
await writeStdout(HELP9);
|
|
82809
82720
|
return EXIT2.OK;
|
|
82810
82721
|
}
|
|
82811
82722
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
82812
82723
|
const filePath = parsed.positionals[0];
|
|
82813
82724
|
if (!filePath)
|
|
82814
|
-
return fail("USAGE", "Missing FILE argument",
|
|
82725
|
+
return fail("USAGE", "Missing FILE argument", HELP9);
|
|
82815
82726
|
const batchInput = parsed.values.batch;
|
|
82816
82727
|
if (batchInput !== undefined) {
|
|
82817
82728
|
return runEditBatch(filePath, batchInput, parsed.values);
|
|
@@ -82822,9 +82733,12 @@ async function run10(args) {
|
|
|
82822
82733
|
const document4 = await openOrFail(opts.filePath);
|
|
82823
82734
|
if (typeof document4 === "number")
|
|
82824
82735
|
return document4;
|
|
82736
|
+
if (opts.tabsDirective) {
|
|
82737
|
+
injectTabsIntoSpec(opts.spec, resolveTabsDirective(opts.tabsDirective, document4));
|
|
82738
|
+
}
|
|
82825
82739
|
if (isBlockRangeLocator2(opts.locator)) {
|
|
82826
82740
|
if (opts.spec.kind === "section") {
|
|
82827
|
-
return fail("USAGE", "Range locators (pN-pM) don't accept --columns/--type \u2014 use sN for section edits",
|
|
82741
|
+
return fail("USAGE", "Range locators (pN-pM) don't accept --columns/--type \u2014 use sN for section edits", HELP9);
|
|
82828
82742
|
}
|
|
82829
82743
|
return commitRangeEdit(document4, opts);
|
|
82830
82744
|
}
|
|
@@ -82857,14 +82771,14 @@ function spanLocatorTarget(locator) {
|
|
|
82857
82771
|
async function commitSpanEdit(document4, spanTarget, opts) {
|
|
82858
82772
|
const spec = opts.spec;
|
|
82859
82773
|
if (spec.kind !== "text" && spec.kind !== "clear") {
|
|
82860
|
-
return fail("USAGE", "A character-span locator (pN:S-E) supports --text or --clear. Use a whole-paragraph locator (pN) for --markdown/--runs/--code.",
|
|
82774
|
+
return fail("USAGE", "A character-span locator (pN:S-E) supports --text or --clear. Use a whole-paragraph locator (pN) for --markdown/--runs/--code.", HELP9);
|
|
82861
82775
|
}
|
|
82862
82776
|
if (spec.kind === "text") {
|
|
82863
82777
|
if (spec.format.color || spec.format.bold || spec.format.italic) {
|
|
82864
|
-
return fail("USAGE", "--color/--bold/--italic aren't supported on a character span \u2014 the replacement inherits the existing run's formatting. Edit the whole paragraph (pN) to set uniform run formatting.",
|
|
82778
|
+
return fail("USAGE", "--color/--bold/--italic aren't supported on a character span \u2014 the replacement inherits the existing run's formatting. Edit the whole paragraph (pN) to set uniform run formatting.", HELP9);
|
|
82865
82779
|
}
|
|
82866
82780
|
if (spec.paragraphOptions.style || spec.paragraphOptions.alignment) {
|
|
82867
|
-
return fail("USAGE", "--style/--alignment apply to a whole paragraph, not a character span (pN:S-E).",
|
|
82781
|
+
return fail("USAGE", "--style/--alignment apply to a whole paragraph, not a character span (pN:S-E).", HELP9);
|
|
82868
82782
|
}
|
|
82869
82783
|
}
|
|
82870
82784
|
const blockRef = await resolveBlockOrFail(document4, spanTarget.blockId);
|
|
@@ -82928,6 +82842,8 @@ async function commitBlockEdit(document4, blockRef, opts) {
|
|
|
82928
82842
|
});
|
|
82929
82843
|
} else if (opts.spec.kind === "clear") {
|
|
82930
82844
|
edit.clearFormatting(blockRef, null, opts.spec.tags);
|
|
82845
|
+
} else if (opts.spec.kind === "paragraphProps") {
|
|
82846
|
+
resultNode = edit.paragraphProperties(blockRef, opts.spec.paragraphOptions);
|
|
82931
82847
|
} else {
|
|
82932
82848
|
return fail("USAGE", "Unsupported edit spec for single-block locator");
|
|
82933
82849
|
}
|
|
@@ -82945,13 +82861,16 @@ async function commitBlockEdit(document4, blockRef, opts) {
|
|
|
82945
82861
|
}
|
|
82946
82862
|
async function commitRangeEdit(document4, opts) {
|
|
82947
82863
|
if (opts.spec.kind === "section") {
|
|
82948
|
-
return fail("USAGE", "Section edits don't support range locators",
|
|
82864
|
+
return fail("USAGE", "Section edits don't support range locators", HELP9);
|
|
82949
82865
|
}
|
|
82950
82866
|
if (opts.spec.kind === "task") {
|
|
82951
|
-
return fail("USAGE", "--task takes a single paragraph locator (pN), not a range",
|
|
82867
|
+
return fail("USAGE", "--task takes a single paragraph locator (pN), not a range", HELP9);
|
|
82952
82868
|
}
|
|
82953
82869
|
if (opts.spec.kind === "equation") {
|
|
82954
|
-
return fail("USAGE", "--equation takes a single equation locator (eqN), not a paragraph range",
|
|
82870
|
+
return fail("USAGE", "--equation takes a single equation locator (eqN), not a paragraph range", HELP9);
|
|
82871
|
+
}
|
|
82872
|
+
if (opts.spec.kind === "paragraphProps") {
|
|
82873
|
+
return commitRangeProps(document4, opts, opts.spec.paragraphOptions);
|
|
82955
82874
|
}
|
|
82956
82875
|
const rangeRef = await resolveBlockRangeOrFail(document4, opts.locator);
|
|
82957
82876
|
if (typeof rangeRef === "number")
|
|
@@ -82983,6 +82902,53 @@ async function commitRangeEdit(document4, opts) {
|
|
|
82983
82902
|
await document4.save(opts.outputPath);
|
|
82984
82903
|
return emitEditAck(opts);
|
|
82985
82904
|
}
|
|
82905
|
+
async function commitRangeProps(document4, opts, options) {
|
|
82906
|
+
const rangeRef = await resolveBlockRangeOrFail(document4, opts.locator);
|
|
82907
|
+
if (typeof rangeRef === "number")
|
|
82908
|
+
return rangeRef;
|
|
82909
|
+
if (opts.dryRun)
|
|
82910
|
+
return respondDryRun2(opts);
|
|
82911
|
+
let applied = 0;
|
|
82912
|
+
try {
|
|
82913
|
+
const edit = new Edit(document4);
|
|
82914
|
+
for (let index2 = rangeRef.startIndex;index2 <= rangeRef.endIndex; index2++) {
|
|
82915
|
+
const node2 = rangeRef.parent[index2];
|
|
82916
|
+
if (!node2 || node2.tag !== "w:p")
|
|
82917
|
+
continue;
|
|
82918
|
+
const perParagraph = scopeRangeProps(node2, options);
|
|
82919
|
+
if (!perParagraph)
|
|
82920
|
+
continue;
|
|
82921
|
+
edit.paragraphProperties({ node: node2, parent: rangeRef.parent }, perParagraph);
|
|
82922
|
+
applied++;
|
|
82923
|
+
}
|
|
82924
|
+
} catch (error) {
|
|
82925
|
+
if (error instanceof EditError) {
|
|
82926
|
+
return fail(error.code, error.message, error.hint);
|
|
82927
|
+
}
|
|
82928
|
+
throw error;
|
|
82929
|
+
}
|
|
82930
|
+
if (applied === 0) {
|
|
82931
|
+
return fail("BLOCK_NOT_FOUND", options.tabs !== undefined ? `No paragraphs with tab stops in ${opts.locator} \u2014 --tabs only adjusts tab-using lines (the ones \`read\` flags with docx:layout).` : `No paragraphs in ${opts.locator} to restyle.`);
|
|
82932
|
+
}
|
|
82933
|
+
await document4.save(opts.outputPath);
|
|
82934
|
+
return emitEditAck(opts);
|
|
82935
|
+
}
|
|
82936
|
+
function scopeRangeProps(node2, options) {
|
|
82937
|
+
const out = {};
|
|
82938
|
+
if (options.style !== undefined)
|
|
82939
|
+
out.style = options.style;
|
|
82940
|
+
if (options.alignment !== undefined)
|
|
82941
|
+
out.alignment = options.alignment;
|
|
82942
|
+
if (options.tabs !== undefined && paragraphHasTabStops(node2)) {
|
|
82943
|
+
out.tabs = options.tabs;
|
|
82944
|
+
}
|
|
82945
|
+
if (out.style === undefined && out.alignment === undefined && out.tabs === undefined)
|
|
82946
|
+
return null;
|
|
82947
|
+
return out;
|
|
82948
|
+
}
|
|
82949
|
+
function paragraphHasTabStops(node2) {
|
|
82950
|
+
return node2.findChild("w:pPr")?.findChild("w:tabs") !== undefined;
|
|
82951
|
+
}
|
|
82986
82952
|
async function commitEquationEdit(document4, spec, opts) {
|
|
82987
82953
|
if (spec.latex === undefined && spec.display === undefined) {
|
|
82988
82954
|
return fail("USAGE", "--equation requires --equation NEW_LATEX, --display, or --inline");
|
|
@@ -83013,10 +82979,17 @@ async function commitEquationEdit(document4, spec, opts) {
|
|
|
83013
82979
|
async function validateSingleShotOptions(filePath, values2) {
|
|
83014
82980
|
const locator = values2.at;
|
|
83015
82981
|
if (!locator)
|
|
83016
|
-
return fail("USAGE", "Missing --at LOCATOR",
|
|
82982
|
+
return fail("USAGE", "Missing --at LOCATOR", HELP9);
|
|
83017
82983
|
const paragraphOptions = await parseParagraphOptions(values2);
|
|
83018
82984
|
if (typeof paragraphOptions === "number")
|
|
83019
82985
|
return paragraphOptions;
|
|
82986
|
+
let tabsDirective;
|
|
82987
|
+
if (values2.tabs !== undefined) {
|
|
82988
|
+
const parsed = parseTabsValue(values2.tabs);
|
|
82989
|
+
if ("error" in parsed)
|
|
82990
|
+
return fail("USAGE", parsed.error, parsed.hint);
|
|
82991
|
+
tabsDirective = parsed;
|
|
82992
|
+
}
|
|
83020
82993
|
const isSectionLocator = /^s\d+$/.test(locator);
|
|
83021
82994
|
const spec = isSectionLocator ? await validateSectionEdit(values2) : await validateParagraphEdit(values2, paragraphOptions);
|
|
83022
82995
|
if (typeof spec === "number")
|
|
@@ -83037,15 +83010,16 @@ async function validateSingleShotOptions(filePath, values2) {
|
|
|
83037
83010
|
outputPath: values2.output,
|
|
83038
83011
|
dryRun: Boolean(values2["dry-run"]),
|
|
83039
83012
|
noFormatting: Boolean(values2["no-formatting"]),
|
|
83040
|
-
...clearTags ? { clearTags } : {}
|
|
83013
|
+
...clearTags ? { clearTags } : {},
|
|
83014
|
+
...tabsDirective ? { tabsDirective } : {}
|
|
83041
83015
|
};
|
|
83042
83016
|
}
|
|
83043
83017
|
async function validateSectionEdit(values2) {
|
|
83044
83018
|
if (values2.text !== undefined || values2.runs !== undefined) {
|
|
83045
|
-
return fail("USAGE", "Section locators (sN) take --columns and --type, not --text/--runs",
|
|
83019
|
+
return fail("USAGE", "Section locators (sN) take --columns and --type, not --text/--runs", HELP9);
|
|
83046
83020
|
}
|
|
83047
83021
|
if (values2.columns === undefined && values2.type === undefined) {
|
|
83048
|
-
return fail("USAGE", "Section edit requires --columns and/or --type",
|
|
83022
|
+
return fail("USAGE", "Section edit requires --columns and/or --type", HELP9);
|
|
83049
83023
|
}
|
|
83050
83024
|
const sectionFlags = await parseSectionFlags(values2);
|
|
83051
83025
|
if (typeof sectionFlags === "number")
|
|
@@ -83056,22 +83030,22 @@ async function parseClearTagsOrFail(clearFlag) {
|
|
|
83056
83030
|
const raw = Array.isArray(clearFlag) ? clearFlag : [clearFlag];
|
|
83057
83031
|
const names = raw.flatMap((entry) => entry.split(",")).map((name) => name.trim().toLowerCase()).filter(Boolean);
|
|
83058
83032
|
if (names.length === 0) {
|
|
83059
|
-
return fail("USAGE", "--clear needs an attribute name, or 'all'",
|
|
83033
|
+
return fail("USAGE", "--clear needs an attribute name, or 'all'", HELP9);
|
|
83060
83034
|
}
|
|
83061
83035
|
const tags = resolveClearTags(names);
|
|
83062
83036
|
if (!tags) {
|
|
83063
|
-
return fail("USAGE", `--clear: unknown attribute in "${raw.join(",")}". Valid: ${CLEARABLE_ATTRS.join(", ")}, all`,
|
|
83037
|
+
return fail("USAGE", `--clear: unknown attribute in "${raw.join(",")}". Valid: ${CLEARABLE_ATTRS.join(", ")}, all`, HELP9);
|
|
83064
83038
|
}
|
|
83065
83039
|
return tags;
|
|
83066
83040
|
}
|
|
83067
83041
|
async function validateParagraphEdit(values2, paragraphOptions) {
|
|
83068
83042
|
if (values2.columns !== undefined || values2.type !== undefined) {
|
|
83069
|
-
return fail("USAGE", "--columns and --type require a section locator (sN)",
|
|
83043
|
+
return fail("USAGE", "--columns and --type require a section locator (sN)", HELP9);
|
|
83070
83044
|
}
|
|
83071
83045
|
const clearFlag = values2.clear;
|
|
83072
83046
|
if (clearFlag !== undefined) {
|
|
83073
83047
|
if (values2.equation !== undefined || values2.display === true || values2.inline === true) {
|
|
83074
|
-
return fail("USAGE", "--clear can't be combined with --equation/--display/--inline",
|
|
83048
|
+
return fail("USAGE", "--clear can't be combined with --equation/--display/--inline", HELP9);
|
|
83075
83049
|
}
|
|
83076
83050
|
const hasContent = [
|
|
83077
83051
|
"text",
|
|
@@ -83108,10 +83082,10 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83108
83082
|
taskFlag !== undefined
|
|
83109
83083
|
].filter(Boolean).length;
|
|
83110
83084
|
if (otherContent > 0) {
|
|
83111
|
-
return fail("USAGE", "--equation / --display / --inline cannot be combined with --text/--runs/--code/--code-file/--task",
|
|
83085
|
+
return fail("USAGE", "--equation / --display / --inline cannot be combined with --text/--runs/--code/--code-file/--task", HELP9);
|
|
83112
83086
|
}
|
|
83113
83087
|
if (displayFlag && inlineFlag) {
|
|
83114
|
-
return fail("USAGE", "--display and --inline are mutually exclusive",
|
|
83088
|
+
return fail("USAGE", "--display and --inline are mutually exclusive", HELP9);
|
|
83115
83089
|
}
|
|
83116
83090
|
const displayMode = displayFlag ? true : inlineFlag ? false : undefined;
|
|
83117
83091
|
return {
|
|
@@ -83129,11 +83103,11 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83129
83103
|
codeFile !== undefined
|
|
83130
83104
|
].filter(Boolean).length;
|
|
83131
83105
|
if (otherFlags > 0) {
|
|
83132
|
-
return fail("USAGE", "--task cannot be combined with --text, --runs, --code, or --code-file",
|
|
83106
|
+
return fail("USAGE", "--task cannot be combined with --text, --runs, --code, or --code-file", HELP9);
|
|
83133
83107
|
}
|
|
83134
83108
|
const checked = parseTaskFlag(taskFlag);
|
|
83135
83109
|
if (checked === null) {
|
|
83136
|
-
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskFlag}"`,
|
|
83110
|
+
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskFlag}"`, HELP9);
|
|
83137
83111
|
}
|
|
83138
83112
|
return { kind: "task", checked };
|
|
83139
83113
|
}
|
|
@@ -83148,15 +83122,29 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83148
83122
|
markdownFile !== undefined
|
|
83149
83123
|
].filter(Boolean).length;
|
|
83150
83124
|
if (contentFlags === 0) {
|
|
83151
|
-
|
|
83125
|
+
if (paragraphOptions.style || paragraphOptions.alignment || values2.tabs !== undefined) {
|
|
83126
|
+
return { kind: "paragraphProps", paragraphOptions };
|
|
83127
|
+
}
|
|
83128
|
+
return fail("USAGE", "Missing content: pass --text, --runs, --code, --code-file, --markdown, --markdown-file, --task, or --equation \u2014 or --style/--alignment/--tabs to adjust the paragraph in place", HELP9);
|
|
83152
83129
|
}
|
|
83153
83130
|
if (contentFlags > 1) {
|
|
83154
|
-
return fail("USAGE", "Pass only one of --text, --runs, --code, --code-file, --markdown, --markdown-file",
|
|
83131
|
+
return fail("USAGE", "Pass only one of --text, --runs, --code, --code-file, --markdown, --markdown-file", HELP9);
|
|
83155
83132
|
}
|
|
83156
83133
|
if (language !== undefined && codeInline === undefined && codeFile === undefined) {
|
|
83157
|
-
return fail("USAGE", "--language requires --code or --code-file",
|
|
83134
|
+
return fail("USAGE", "--language requires --code or --code-file", HELP9);
|
|
83158
83135
|
}
|
|
83159
83136
|
if (text6 !== undefined) {
|
|
83137
|
+
const at = values2.at;
|
|
83138
|
+
if (text6 === "" && !(at && spanLocatorTarget(at))) {
|
|
83139
|
+
return fail("USAGE", `Empty --text leaves a blank paragraph in place, it doesn't remove the line.`, `To DELETE the paragraph: \`docx delete --at ${at ?? "pN"}\` (or \`docx delete --batch\` for many). To delete just SOME characters, use a span locator (\`--at pN:S-E --text ""\`). To blank the paragraph but keep an empty spacer, pass --runs '[]'. Help:
|
|
83140
|
+
${HELP9}`);
|
|
83141
|
+
}
|
|
83142
|
+
const rejected = await rejectMarkdownInText(text6, HELP9);
|
|
83143
|
+
if (typeof rejected === "number")
|
|
83144
|
+
return rejected;
|
|
83145
|
+
const mangled = await rejectShellMangledValue(text6, HELP9, "--text");
|
|
83146
|
+
if (typeof mangled === "number")
|
|
83147
|
+
return mangled;
|
|
83160
83148
|
return {
|
|
83161
83149
|
kind: "text",
|
|
83162
83150
|
text: text6,
|
|
@@ -83182,7 +83170,7 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83182
83170
|
if (markdownInline !== undefined || markdownFile !== undefined) {
|
|
83183
83171
|
const conflict = MARKDOWN_INCOMPATIBLE_FLAGS.find((flag) => values2[flag] !== undefined);
|
|
83184
83172
|
if (conflict) {
|
|
83185
|
-
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`,
|
|
83173
|
+
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`, HELP9);
|
|
83186
83174
|
}
|
|
83187
83175
|
const source2 = markdownInline !== undefined ? markdownInline : await loadMarkdownFile(markdownFile);
|
|
83188
83176
|
if (typeof source2 === "number")
|
|
@@ -83239,6 +83227,11 @@ async function parseParagraphOptions(values2) {
|
|
|
83239
83227
|
}
|
|
83240
83228
|
return out;
|
|
83241
83229
|
}
|
|
83230
|
+
function injectTabsIntoSpec(spec, tabs) {
|
|
83231
|
+
if (spec.kind === "text" || spec.kind === "runs" || spec.kind === "code" || spec.kind === "markdown" || spec.kind === "paragraphProps") {
|
|
83232
|
+
spec.paragraphOptions.tabs = tabs;
|
|
83233
|
+
}
|
|
83234
|
+
}
|
|
83242
83235
|
async function respondDryRun2(opts) {
|
|
83243
83236
|
await respond({
|
|
83244
83237
|
operation: "edit",
|
|
@@ -83258,13 +83251,14 @@ async function emitEditAck(opts) {
|
|
|
83258
83251
|
});
|
|
83259
83252
|
return EXIT2.OK;
|
|
83260
83253
|
}
|
|
83261
|
-
var AT_FORMS2,
|
|
83254
|
+
var AT_FORMS2, HELP9, MARKDOWN_INCOMPATIBLE_FLAGS, OPTION_SPEC2;
|
|
83262
83255
|
var init_edit2 = __esm(() => {
|
|
83263
83256
|
init_core2();
|
|
83264
83257
|
init_equation();
|
|
83265
83258
|
init_parse_helpers();
|
|
83266
83259
|
init_respond();
|
|
83267
83260
|
init_batch2();
|
|
83261
|
+
init_tabs();
|
|
83268
83262
|
AT_FORMS2 = describeForms([
|
|
83269
83263
|
"paragraph",
|
|
83270
83264
|
"span",
|
|
@@ -83274,7 +83268,7 @@ var init_edit2 = __esm(() => {
|
|
|
83274
83268
|
"section",
|
|
83275
83269
|
"equation"
|
|
83276
83270
|
], " ");
|
|
83277
|
-
|
|
83271
|
+
HELP9 = `docx edit \u2014 replace a paragraph (or paragraph range), a section, or an equation
|
|
83278
83272
|
|
|
83279
83273
|
Usage:
|
|
83280
83274
|
docx edit FILE --at LOCATOR <content> [options]
|
|
@@ -83291,7 +83285,8 @@ ${AT_FORMS2}
|
|
|
83291
83285
|
inheriting the existing run's formatting \u2014 paste a locator
|
|
83292
83286
|
straight from \`docx find\`. See \`docx info locators\`.
|
|
83293
83287
|
|
|
83294
|
-
Paragraph content (one required for paragraph / range locators
|
|
83288
|
+
Paragraph content (one required for paragraph / range locators \u2014 UNLESS you pass
|
|
83289
|
+
only --style/--alignment below, which restyle the paragraph in place):
|
|
83295
83290
|
--text TEXT Replace with a single-run paragraph
|
|
83296
83291
|
--runs JSON Replace with custom runs (Run[] JSON)
|
|
83297
83292
|
--code TEXT Replace with a code block \u2014 newlines split into one
|
|
@@ -83334,6 +83329,25 @@ Equation editing (requires --at eqN):
|
|
|
83334
83329
|
Paragraph options:
|
|
83335
83330
|
--style NAME Paragraph style (e.g., Heading1)
|
|
83336
83331
|
--alignment ALIGN left | center | right | justify
|
|
83332
|
+
--tabs SPEC Replace the paragraph's tab stops. SPEC is:
|
|
83333
|
+
right \u2014 a single RIGHT tab flush at the text margin.
|
|
83334
|
+
This is the CURE for the \`docx:layout \u2026 warn=\u2026\`
|
|
83335
|
+
hint \`read\` prints on a line whose trailing
|
|
83336
|
+
content sits on a fixed LEFT tab: a long value
|
|
83337
|
+
(e.g. "San Francisco, CA") overflows the margin
|
|
83338
|
+
and WRAPS to a second line. A right tab at the
|
|
83339
|
+
margin right-aligns it instead, so it never wraps.
|
|
83340
|
+
clear \u2014 remove the paragraph's tab stops.
|
|
83341
|
+
<list> \u2014 explicit stops, e.g. \`right@7.5in\` or
|
|
83342
|
+
\`left@1in,right@7.5in\` (ALIGN@POSin, comma list).
|
|
83343
|
+
Pass any of --style/--alignment/--tabs ALONE (no content flag) to adjust the
|
|
83344
|
+
paragraph in place, keeping its text/runs: \`docx edit doc.docx --at p4 --style
|
|
83345
|
+
Heading1\`, \`docx edit doc.docx --at p9 --tabs right\`. --tabs also rides along
|
|
83346
|
+
with --text (fill the line AND fix its tab in one call), and works per-entry in
|
|
83347
|
+
--batch ({"at":"p9","text":"Harvard University\\tCambridge, MA","tabs":"right"}).
|
|
83348
|
+
ONE-CALL cure: a RANGE locator fixes every wrapping tab line at once \u2014
|
|
83349
|
+
\`docx edit doc.docx --at p9-p38 --tabs right\` (the exact "fix-all" command
|
|
83350
|
+
\`read\` prints at the top when lines wrap; it skips paragraphs with no tab stops).
|
|
83337
83351
|
|
|
83338
83352
|
Run options (only with --text):
|
|
83339
83353
|
--color HEX Run color, hex (e.g., 800080 for purple)
|
|
@@ -83413,7 +83427,7 @@ Batch JSONL example (one edit per line):
|
|
|
83413
83427
|
{"at": "p1", "markdown": "## Revised heading"}
|
|
83414
83428
|
`;
|
|
83415
83429
|
MARKDOWN_INCOMPATIBLE_FLAGS = ["style", "alignment"];
|
|
83416
|
-
|
|
83430
|
+
OPTION_SPEC2 = {
|
|
83417
83431
|
at: { type: "string" },
|
|
83418
83432
|
batch: { type: "string" },
|
|
83419
83433
|
text: { type: "string" },
|
|
@@ -83432,6 +83446,7 @@ Batch JSONL example (one edit per line):
|
|
|
83432
83446
|
type: { type: "string" },
|
|
83433
83447
|
style: { type: "string" },
|
|
83434
83448
|
alignment: { type: "string" },
|
|
83449
|
+
tabs: { type: "string" },
|
|
83435
83450
|
color: { type: "string" },
|
|
83436
83451
|
bold: { type: "boolean" },
|
|
83437
83452
|
italic: { type: "boolean" },
|
|
@@ -83446,7 +83461,7 @@ Batch JSONL example (one edit per line):
|
|
|
83446
83461
|
var exports_add2 = {};
|
|
83447
83462
|
__export(exports_add2, {
|
|
83448
83463
|
runAddNote: () => runAddNote,
|
|
83449
|
-
run: () =>
|
|
83464
|
+
run: () => run10
|
|
83450
83465
|
});
|
|
83451
83466
|
function helpFor(kind) {
|
|
83452
83467
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -83712,8 +83727,8 @@ function splitMarkdownBlocks(blocks) {
|
|
|
83712
83727
|
}
|
|
83713
83728
|
function runsToXml(runs) {
|
|
83714
83729
|
const out = [];
|
|
83715
|
-
for (const
|
|
83716
|
-
const element = RunElement({ run:
|
|
83730
|
+
for (const run10 of runs) {
|
|
83731
|
+
const element = RunElement({ run: run10 });
|
|
83717
83732
|
if (element)
|
|
83718
83733
|
out.push(element);
|
|
83719
83734
|
}
|
|
@@ -83751,7 +83766,7 @@ function parseAnchor(input) {
|
|
|
83751
83766
|
}
|
|
83752
83767
|
return null;
|
|
83753
83768
|
}
|
|
83754
|
-
async function
|
|
83769
|
+
async function run10(args) {
|
|
83755
83770
|
return runAddNote(args, "footnote");
|
|
83756
83771
|
}
|
|
83757
83772
|
var ANCHOR_FORMS;
|
|
@@ -83773,7 +83788,7 @@ var init_add2 = __esm(() => {
|
|
|
83773
83788
|
var exports_delete3 = {};
|
|
83774
83789
|
__export(exports_delete3, {
|
|
83775
83790
|
runDeleteNote: () => runDeleteNote,
|
|
83776
|
-
run: () =>
|
|
83791
|
+
run: () => run11
|
|
83777
83792
|
});
|
|
83778
83793
|
function helpFor2(kind) {
|
|
83779
83794
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -83882,7 +83897,7 @@ async function runDeleteNote(args, kind) {
|
|
|
83882
83897
|
});
|
|
83883
83898
|
return EXIT2.OK;
|
|
83884
83899
|
}
|
|
83885
|
-
async function
|
|
83900
|
+
async function run11(args) {
|
|
83886
83901
|
return runDeleteNote(args, "footnote");
|
|
83887
83902
|
}
|
|
83888
83903
|
var init_delete3 = __esm(() => {
|
|
@@ -83895,7 +83910,7 @@ var init_delete3 = __esm(() => {
|
|
|
83895
83910
|
var exports_edit2 = {};
|
|
83896
83911
|
__export(exports_edit2, {
|
|
83897
83912
|
runEditNote: () => runEditNote,
|
|
83898
|
-
run: () =>
|
|
83913
|
+
run: () => run12
|
|
83899
83914
|
});
|
|
83900
83915
|
function helpFor3(kind) {
|
|
83901
83916
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -84086,8 +84101,8 @@ function splitMarkdownBlocks2(blocks) {
|
|
|
84086
84101
|
}
|
|
84087
84102
|
function runsToXml2(runs) {
|
|
84088
84103
|
const out = [];
|
|
84089
|
-
for (const
|
|
84090
|
-
const element = RunElement({ run:
|
|
84104
|
+
for (const run12 of runs) {
|
|
84105
|
+
const element = RunElement({ run: run12 });
|
|
84091
84106
|
if (element)
|
|
84092
84107
|
out.push(element);
|
|
84093
84108
|
}
|
|
@@ -84136,7 +84151,7 @@ function NoteParagraph({
|
|
|
84136
84151
|
]
|
|
84137
84152
|
}, undefined, true, undefined, this);
|
|
84138
84153
|
}
|
|
84139
|
-
async function
|
|
84154
|
+
async function run12(args) {
|
|
84140
84155
|
return runEditNote(args, "footnote");
|
|
84141
84156
|
}
|
|
84142
84157
|
var init_edit3 = __esm(() => {
|
|
@@ -84154,7 +84169,7 @@ var init_edit3 = __esm(() => {
|
|
|
84154
84169
|
var exports_list2 = {};
|
|
84155
84170
|
__export(exports_list2, {
|
|
84156
84171
|
runListNotes: () => runListNotes,
|
|
84157
|
-
run: () =>
|
|
84172
|
+
run: () => run13
|
|
84158
84173
|
});
|
|
84159
84174
|
function helpFor4(kind) {
|
|
84160
84175
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -84196,7 +84211,7 @@ async function runListNotes(args, kind) {
|
|
|
84196
84211
|
await respond(notes);
|
|
84197
84212
|
return EXIT2.OK;
|
|
84198
84213
|
}
|
|
84199
|
-
async function
|
|
84214
|
+
async function run13(args) {
|
|
84200
84215
|
return runListNotes(args, "footnote");
|
|
84201
84216
|
}
|
|
84202
84217
|
var init_list4 = __esm(() => {
|
|
@@ -84206,12 +84221,12 @@ var init_list4 = __esm(() => {
|
|
|
84206
84221
|
// src/cli/endnotes/index.ts
|
|
84207
84222
|
var exports_endnotes = {};
|
|
84208
84223
|
__export(exports_endnotes, {
|
|
84209
|
-
run: () =>
|
|
84224
|
+
run: () => run14
|
|
84210
84225
|
});
|
|
84211
|
-
async function
|
|
84226
|
+
async function run14(args) {
|
|
84212
84227
|
const verb = args[0];
|
|
84213
84228
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
84214
|
-
await writeStdout(
|
|
84229
|
+
await writeStdout(HELP10);
|
|
84215
84230
|
return verb ? 0 : 2;
|
|
84216
84231
|
}
|
|
84217
84232
|
const handler = SUBCOMMANDS2[verb];
|
|
@@ -84220,7 +84235,7 @@ async function run15(args) {
|
|
|
84220
84235
|
}
|
|
84221
84236
|
return handler(args.slice(1));
|
|
84222
84237
|
}
|
|
84223
|
-
var SUBCOMMANDS2,
|
|
84238
|
+
var SUBCOMMANDS2, HELP10 = `docx endnotes \u2014 author endnotes
|
|
84224
84239
|
|
|
84225
84240
|
Usage:
|
|
84226
84241
|
docx endnotes <verb> FILE [options]
|
|
@@ -84250,7 +84265,7 @@ var init_endnotes = __esm(() => {
|
|
|
84250
84265
|
// src/cli/find/index.ts
|
|
84251
84266
|
var exports_find = {};
|
|
84252
84267
|
__export(exports_find, {
|
|
84253
|
-
run: () =>
|
|
84268
|
+
run: () => run15
|
|
84254
84269
|
});
|
|
84255
84270
|
function withBareHighlightAsAny(args) {
|
|
84256
84271
|
const out = [];
|
|
@@ -84272,7 +84287,7 @@ function withBareHighlightAsAny(args) {
|
|
|
84272
84287
|
}
|
|
84273
84288
|
return out;
|
|
84274
84289
|
}
|
|
84275
|
-
async function
|
|
84290
|
+
async function run15(args) {
|
|
84276
84291
|
const parsed = await tryParseArgs(withBareHighlightAsAny(args), {
|
|
84277
84292
|
regex: { type: "boolean" },
|
|
84278
84293
|
"ignore-case": { type: "boolean" },
|
|
@@ -84288,17 +84303,17 @@ async function run16(args) {
|
|
|
84288
84303
|
underline: { type: "boolean" },
|
|
84289
84304
|
json: { type: "boolean" },
|
|
84290
84305
|
help: { type: "boolean", short: "h" }
|
|
84291
|
-
},
|
|
84306
|
+
}, HELP11);
|
|
84292
84307
|
if (typeof parsed === "number")
|
|
84293
84308
|
return parsed;
|
|
84294
84309
|
if (parsed.values.help) {
|
|
84295
|
-
await writeStdout(
|
|
84310
|
+
await writeStdout(HELP11);
|
|
84296
84311
|
return EXIT2.OK;
|
|
84297
84312
|
}
|
|
84298
84313
|
const path2 = parsed.positionals[0];
|
|
84299
84314
|
const query = parsed.positionals[1];
|
|
84300
84315
|
if (!path2)
|
|
84301
|
-
return fail("USAGE", "Missing FILE argument",
|
|
84316
|
+
return fail("USAGE", "Missing FILE argument", HELP11);
|
|
84302
84317
|
const formatFilter = {};
|
|
84303
84318
|
if (parsed.values.highlight !== undefined)
|
|
84304
84319
|
formatFilter.highlight = parsed.values.highlight;
|
|
@@ -84312,10 +84327,10 @@ async function run16(args) {
|
|
|
84312
84327
|
formatFilter.underline = true;
|
|
84313
84328
|
const hasFormatFilter = Object.keys(formatFilter).length > 0;
|
|
84314
84329
|
if (query == null && !hasFormatFilter) {
|
|
84315
|
-
return fail("USAGE", "Missing QUERY (or a --highlight/--color/--bold/--italic/--underline filter)",
|
|
84330
|
+
return fail("USAGE", "Missing QUERY (or a --highlight/--color/--bold/--italic/--underline filter)", HELP11);
|
|
84316
84331
|
}
|
|
84317
84332
|
if (query != null && hasFormatFilter) {
|
|
84318
|
-
return fail("USAGE", "Pass a text QUERY or formatting filters (--highlight/--color/...), not both",
|
|
84333
|
+
return fail("USAGE", "Pass a text QUERY or formatting filters (--highlight/--color/...), not both", HELP11);
|
|
84319
84334
|
}
|
|
84320
84335
|
const ignoreCase = Boolean(parsed.values["ignore-case"]);
|
|
84321
84336
|
const useRegex = Boolean(parsed.values.regex);
|
|
@@ -84390,7 +84405,7 @@ async function run16(args) {
|
|
|
84390
84405
|
}
|
|
84391
84406
|
return EXIT2.OK;
|
|
84392
84407
|
}
|
|
84393
|
-
var
|
|
84408
|
+
var HELP11 = `docx find \u2014 locate text spans and return their locators
|
|
84394
84409
|
|
|
84395
84410
|
Usage:
|
|
84396
84411
|
docx find FILE QUERY [options]
|
|
@@ -84463,12 +84478,12 @@ var init_find2 = __esm(() => {
|
|
|
84463
84478
|
// src/cli/footnotes/index.ts
|
|
84464
84479
|
var exports_footnotes = {};
|
|
84465
84480
|
__export(exports_footnotes, {
|
|
84466
|
-
run: () =>
|
|
84481
|
+
run: () => run16
|
|
84467
84482
|
});
|
|
84468
|
-
async function
|
|
84483
|
+
async function run16(args) {
|
|
84469
84484
|
const verb = args[0];
|
|
84470
84485
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
84471
|
-
await writeStdout(
|
|
84486
|
+
await writeStdout(HELP12);
|
|
84472
84487
|
return verb ? 0 : 2;
|
|
84473
84488
|
}
|
|
84474
84489
|
const loader = SUBCOMMANDS3[verb];
|
|
@@ -84478,7 +84493,7 @@ async function run17(args) {
|
|
|
84478
84493
|
const module_ = await loader();
|
|
84479
84494
|
return module_.run(args.slice(1));
|
|
84480
84495
|
}
|
|
84481
|
-
var SUBCOMMANDS3,
|
|
84496
|
+
var SUBCOMMANDS3, HELP12 = `docx footnotes \u2014 author footnotes
|
|
84482
84497
|
|
|
84483
84498
|
Usage:
|
|
84484
84499
|
docx footnotes <verb> FILE [options]
|
|
@@ -84502,7 +84517,7 @@ var init_footnotes = __esm(() => {
|
|
|
84502
84517
|
});
|
|
84503
84518
|
|
|
84504
84519
|
// src/core/hyperlinks/wrap.tsx
|
|
84505
|
-
function wrapSpanInHyperlink(paragraph2, span, relationshipId) {
|
|
84520
|
+
function wrapSpanInHyperlink(paragraph2, span, relationshipId, applyStyle = true) {
|
|
84506
84521
|
if (span.start >= span.end) {
|
|
84507
84522
|
throw new HyperlinkWrapError(`Empty or inverted span ${span.start}-${span.end}`);
|
|
84508
84523
|
}
|
|
@@ -84513,6 +84528,9 @@ function wrapSpanInHyperlink(paragraph2, span, relationshipId) {
|
|
|
84513
84528
|
const placeWrapper = () => {
|
|
84514
84529
|
if (placed || wrappedRuns.length === 0)
|
|
84515
84530
|
return;
|
|
84531
|
+
if (applyStyle)
|
|
84532
|
+
for (const run17 of wrappedRuns)
|
|
84533
|
+
applyHyperlinkRunStyle(run17);
|
|
84516
84534
|
newChildren.push(hyperlinkWrapper(relationshipId, wrappedRuns));
|
|
84517
84535
|
wrappedRuns.length = 0;
|
|
84518
84536
|
placed = true;
|
|
@@ -84573,6 +84591,20 @@ function hyperlinkWrapper(relationshipId, runs) {
|
|
|
84573
84591
|
children: runs
|
|
84574
84592
|
}, undefined, false, undefined, this);
|
|
84575
84593
|
}
|
|
84594
|
+
function applyHyperlinkRunStyle(run17) {
|
|
84595
|
+
if (run17.tag !== "w:r")
|
|
84596
|
+
return;
|
|
84597
|
+
let rPr = run17.findChild("w:rPr");
|
|
84598
|
+
if (!rPr) {
|
|
84599
|
+
rPr = /* @__PURE__ */ jsxDEV(w.rPr, {}, undefined, false, undefined, this);
|
|
84600
|
+
run17.children.unshift(rPr);
|
|
84601
|
+
}
|
|
84602
|
+
if (rPr.findChild("w:rStyle"))
|
|
84603
|
+
return;
|
|
84604
|
+
rPr.children.unshift(/* @__PURE__ */ jsxDEV(w.rStyle, {
|
|
84605
|
+
"w-val": "Hyperlink"
|
|
84606
|
+
}, undefined, false, undefined, this));
|
|
84607
|
+
}
|
|
84576
84608
|
var HyperlinkWrapError;
|
|
84577
84609
|
var init_wrap = __esm(() => {
|
|
84578
84610
|
init_jsx();
|
|
@@ -84594,7 +84626,10 @@ class Hyperlinks {
|
|
|
84594
84626
|
}
|
|
84595
84627
|
add(paragraph2, span, url, options = {}) {
|
|
84596
84628
|
const relationshipId = this.document.relationships.addHyperlink(url);
|
|
84597
|
-
|
|
84629
|
+
const applyStyle = options.style ?? true;
|
|
84630
|
+
if (applyStyle)
|
|
84631
|
+
this.document.ensureStyles().ensureStyle("Hyperlink");
|
|
84632
|
+
wrapSpanInHyperlink(paragraph2, span, relationshipId, applyStyle);
|
|
84598
84633
|
this.document.relationships.hyperlinksByRelationshipId.set(relationshipId, {
|
|
84599
84634
|
url
|
|
84600
84635
|
});
|
|
@@ -84697,31 +84732,32 @@ var init_hyperlinks = __esm(() => {
|
|
|
84697
84732
|
// src/cli/hyperlinks/add.tsx
|
|
84698
84733
|
var exports_add3 = {};
|
|
84699
84734
|
__export(exports_add3, {
|
|
84700
|
-
run: () =>
|
|
84735
|
+
run: () => run17
|
|
84701
84736
|
});
|
|
84702
|
-
async function
|
|
84737
|
+
async function run17(args) {
|
|
84703
84738
|
const parsed = await tryParseArgs(args, {
|
|
84704
84739
|
at: { type: "string" },
|
|
84705
84740
|
url: { type: "string" },
|
|
84706
84741
|
author: { type: "string" },
|
|
84742
|
+
"no-style": { type: "boolean" },
|
|
84707
84743
|
...SAVE_FLAGS
|
|
84708
|
-
},
|
|
84744
|
+
}, HELP13);
|
|
84709
84745
|
if (typeof parsed === "number")
|
|
84710
84746
|
return parsed;
|
|
84711
84747
|
if (parsed.values.help) {
|
|
84712
|
-
await writeStdout(
|
|
84748
|
+
await writeStdout(HELP13);
|
|
84713
84749
|
return EXIT2.OK;
|
|
84714
84750
|
}
|
|
84715
84751
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
84716
84752
|
const path2 = parsed.positionals[0];
|
|
84717
84753
|
if (!path2)
|
|
84718
|
-
return fail("USAGE", "Missing FILE argument",
|
|
84754
|
+
return fail("USAGE", "Missing FILE argument", HELP13);
|
|
84719
84755
|
const atInput = parsed.values.at;
|
|
84720
84756
|
const url = parsed.values.url;
|
|
84721
84757
|
if (!atInput)
|
|
84722
|
-
return fail("USAGE", "Missing --at LOCATOR",
|
|
84758
|
+
return fail("USAGE", "Missing --at LOCATOR", HELP13);
|
|
84723
84759
|
if (!url)
|
|
84724
|
-
return fail("USAGE", "Missing --url URL",
|
|
84760
|
+
return fail("USAGE", "Missing --url URL", HELP13);
|
|
84725
84761
|
let locator;
|
|
84726
84762
|
try {
|
|
84727
84763
|
locator = parseLocator(atInput);
|
|
@@ -84755,7 +84791,8 @@ async function run18(args) {
|
|
|
84755
84791
|
}
|
|
84756
84792
|
try {
|
|
84757
84793
|
new Hyperlinks(document4).add(paragraphRef.node, target.span, url, {
|
|
84758
|
-
author: parsed.values.author
|
|
84794
|
+
author: parsed.values.author,
|
|
84795
|
+
style: !parsed.values["no-style"]
|
|
84759
84796
|
});
|
|
84760
84797
|
} catch (error) {
|
|
84761
84798
|
if (error instanceof HyperlinkWrapError) {
|
|
@@ -84784,27 +84821,27 @@ async function findMintedHyperlink(savedPath, blockId, spanStart) {
|
|
|
84784
84821
|
let offset2 = 0;
|
|
84785
84822
|
let foundId;
|
|
84786
84823
|
let text6 = "";
|
|
84787
|
-
for (const
|
|
84788
|
-
if (
|
|
84824
|
+
for (const run18 of block.runs) {
|
|
84825
|
+
if (run18.type !== "text")
|
|
84789
84826
|
continue;
|
|
84790
|
-
const runEnd = offset2 +
|
|
84791
|
-
if (foundId === undefined &&
|
|
84792
|
-
foundId =
|
|
84827
|
+
const runEnd = offset2 + run18.text.length;
|
|
84828
|
+
if (foundId === undefined && run18.hyperlink && spanStart < runEnd) {
|
|
84829
|
+
foundId = run18.hyperlink.id;
|
|
84793
84830
|
}
|
|
84794
|
-
if (foundId !== undefined &&
|
|
84795
|
-
text6 +=
|
|
84831
|
+
if (foundId !== undefined && run18.hyperlink?.id === foundId) {
|
|
84832
|
+
text6 += run18.text;
|
|
84796
84833
|
}
|
|
84797
84834
|
offset2 = runEnd;
|
|
84798
84835
|
}
|
|
84799
84836
|
return foundId === undefined ? undefined : { id: foundId, text: text6 };
|
|
84800
84837
|
}
|
|
84801
|
-
var AT_FORMS3,
|
|
84838
|
+
var AT_FORMS3, HELP13;
|
|
84802
84839
|
var init_add3 = __esm(() => {
|
|
84803
84840
|
init_core2();
|
|
84804
84841
|
init_hyperlinks();
|
|
84805
84842
|
init_respond();
|
|
84806
84843
|
AT_FORMS3 = describeForms(["span", "cellSpan"], " ");
|
|
84807
|
-
|
|
84844
|
+
HELP13 = `docx hyperlinks add \u2014 wrap an existing span in a hyperlink
|
|
84808
84845
|
|
|
84809
84846
|
Usage:
|
|
84810
84847
|
docx hyperlinks add FILE --at LOCATOR --url URL [options]
|
|
@@ -84818,6 +84855,9 @@ ${AT_FORMS3}
|
|
|
84818
84855
|
--url URL Target URL
|
|
84819
84856
|
|
|
84820
84857
|
Optional:
|
|
84858
|
+
--no-style Don't apply Word's "Hyperlink" character style (blue +
|
|
84859
|
+
underline). By default the wrapped text is styled so the link
|
|
84860
|
+
is visibly a link; pass this to keep the original run look.
|
|
84821
84861
|
--author NAME Author for the audit comment when track-changes is on
|
|
84822
84862
|
(default: $DOCX_AUTHOR)
|
|
84823
84863
|
-o, --output PATH Write to PATH instead of overwriting FILE
|
|
@@ -84851,27 +84891,27 @@ Examples:
|
|
|
84851
84891
|
// src/cli/hyperlinks/delete.ts
|
|
84852
84892
|
var exports_delete4 = {};
|
|
84853
84893
|
__export(exports_delete4, {
|
|
84854
|
-
run: () =>
|
|
84894
|
+
run: () => run18
|
|
84855
84895
|
});
|
|
84856
|
-
async function
|
|
84896
|
+
async function run18(args) {
|
|
84857
84897
|
const parsed = await tryParseArgs(args, {
|
|
84858
84898
|
at: { type: "string" },
|
|
84859
84899
|
author: { type: "string" },
|
|
84860
84900
|
...SAVE_FLAGS
|
|
84861
|
-
},
|
|
84901
|
+
}, HELP14);
|
|
84862
84902
|
if (typeof parsed === "number")
|
|
84863
84903
|
return parsed;
|
|
84864
84904
|
if (parsed.values.help) {
|
|
84865
|
-
await writeStdout(
|
|
84905
|
+
await writeStdout(HELP14);
|
|
84866
84906
|
return EXIT2.OK;
|
|
84867
84907
|
}
|
|
84868
84908
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
84869
84909
|
const path2 = parsed.positionals[0];
|
|
84870
84910
|
if (!path2)
|
|
84871
|
-
return fail("USAGE", "Missing FILE argument",
|
|
84911
|
+
return fail("USAGE", "Missing FILE argument", HELP14);
|
|
84872
84912
|
const targetId = parsed.values.at;
|
|
84873
84913
|
if (!targetId)
|
|
84874
|
-
return fail("USAGE", "Missing --at linkN",
|
|
84914
|
+
return fail("USAGE", "Missing --at linkN", HELP14);
|
|
84875
84915
|
const document4 = await openOrFail(path2);
|
|
84876
84916
|
if (typeof document4 === "number")
|
|
84877
84917
|
return document4;
|
|
@@ -84912,13 +84952,13 @@ async function run19(args) {
|
|
|
84912
84952
|
});
|
|
84913
84953
|
return EXIT2.OK;
|
|
84914
84954
|
}
|
|
84915
|
-
var AT_FORMS4,
|
|
84955
|
+
var AT_FORMS4, HELP14;
|
|
84916
84956
|
var init_delete4 = __esm(() => {
|
|
84917
84957
|
init_core2();
|
|
84918
84958
|
init_hyperlinks();
|
|
84919
84959
|
init_respond();
|
|
84920
84960
|
AT_FORMS4 = describeForms(["hyperlink"], " ");
|
|
84921
|
-
|
|
84961
|
+
HELP14 = `docx hyperlinks delete \u2014 unwrap a hyperlink (keep the text)
|
|
84922
84962
|
|
|
84923
84963
|
Usage:
|
|
84924
84964
|
docx hyperlinks delete FILE --at linkN [options]
|
|
@@ -84957,21 +84997,21 @@ Examples:
|
|
|
84957
84997
|
// src/cli/hyperlinks/list.ts
|
|
84958
84998
|
var exports_list3 = {};
|
|
84959
84999
|
__export(exports_list3, {
|
|
84960
|
-
run: () =>
|
|
85000
|
+
run: () => run19
|
|
84961
85001
|
});
|
|
84962
|
-
async function
|
|
85002
|
+
async function run19(args) {
|
|
84963
85003
|
const parsed = await tryParseArgs(args, {
|
|
84964
85004
|
help: { type: "boolean", short: "h" }
|
|
84965
|
-
},
|
|
85005
|
+
}, HELP15);
|
|
84966
85006
|
if (typeof parsed === "number")
|
|
84967
85007
|
return parsed;
|
|
84968
85008
|
if (parsed.values.help) {
|
|
84969
|
-
await writeStdout(
|
|
85009
|
+
await writeStdout(HELP15);
|
|
84970
85010
|
return EXIT2.OK;
|
|
84971
85011
|
}
|
|
84972
85012
|
const path2 = parsed.positionals[0];
|
|
84973
85013
|
if (!path2)
|
|
84974
|
-
return fail("USAGE", "Missing FILE argument",
|
|
85014
|
+
return fail("USAGE", "Missing FILE argument", HELP15);
|
|
84975
85015
|
const document4 = await openOrFail(path2);
|
|
84976
85016
|
if (typeof document4 === "number")
|
|
84977
85017
|
return document4;
|
|
@@ -84984,10 +85024,10 @@ function collectHyperlinks(blocks, entries) {
|
|
|
84984
85024
|
for (const block of iterateBlocks(blocks)) {
|
|
84985
85025
|
if (block.type !== "paragraph")
|
|
84986
85026
|
continue;
|
|
84987
|
-
for (const
|
|
84988
|
-
if (
|
|
85027
|
+
for (const run20 of block.runs) {
|
|
85028
|
+
if (run20.type !== "text" || !run20.hyperlink)
|
|
84989
85029
|
continue;
|
|
84990
|
-
addToEntry(entries,
|
|
85030
|
+
addToEntry(entries, run20.hyperlink, block.id, run20.text);
|
|
84991
85031
|
}
|
|
84992
85032
|
}
|
|
84993
85033
|
}
|
|
@@ -85010,7 +85050,7 @@ function addToEntry(entries, hyperlink, blockId, text6) {
|
|
|
85010
85050
|
entry.tooltip = hyperlink.tooltip;
|
|
85011
85051
|
entries.set(hyperlink.id, entry);
|
|
85012
85052
|
}
|
|
85013
|
-
var
|
|
85053
|
+
var HELP15 = `docx hyperlinks list \u2014 print hyperlink manifest as JSON
|
|
85014
85054
|
|
|
85015
85055
|
Usage:
|
|
85016
85056
|
docx hyperlinks list FILE [options]
|
|
@@ -85036,31 +85076,31 @@ var init_list5 = __esm(() => {
|
|
|
85036
85076
|
// src/cli/hyperlinks/replace.ts
|
|
85037
85077
|
var exports_replace = {};
|
|
85038
85078
|
__export(exports_replace, {
|
|
85039
|
-
run: () =>
|
|
85079
|
+
run: () => run20
|
|
85040
85080
|
});
|
|
85041
|
-
async function
|
|
85081
|
+
async function run20(args) {
|
|
85042
85082
|
const parsed = await tryParseArgs(args, {
|
|
85043
85083
|
at: { type: "string" },
|
|
85044
85084
|
with: { type: "string" },
|
|
85045
85085
|
author: { type: "string" },
|
|
85046
85086
|
...SAVE_FLAGS
|
|
85047
|
-
},
|
|
85087
|
+
}, HELP16);
|
|
85048
85088
|
if (typeof parsed === "number")
|
|
85049
85089
|
return parsed;
|
|
85050
85090
|
if (parsed.values.help) {
|
|
85051
|
-
await writeStdout(
|
|
85091
|
+
await writeStdout(HELP16);
|
|
85052
85092
|
return EXIT2.OK;
|
|
85053
85093
|
}
|
|
85054
85094
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
85055
85095
|
const path2 = parsed.positionals[0];
|
|
85056
85096
|
if (!path2)
|
|
85057
|
-
return fail("USAGE", "Missing FILE argument",
|
|
85097
|
+
return fail("USAGE", "Missing FILE argument", HELP16);
|
|
85058
85098
|
const targetId = parsed.values.at;
|
|
85059
85099
|
if (!targetId)
|
|
85060
|
-
return fail("USAGE", "Missing --at linkN",
|
|
85100
|
+
return fail("USAGE", "Missing --at linkN", HELP16);
|
|
85061
85101
|
const newUrl = parsed.values.with;
|
|
85062
85102
|
if (!newUrl)
|
|
85063
|
-
return fail("USAGE", "Missing --with URL",
|
|
85103
|
+
return fail("USAGE", "Missing --with URL", HELP16);
|
|
85064
85104
|
const document4 = await openOrFail(path2);
|
|
85065
85105
|
if (typeof document4 === "number")
|
|
85066
85106
|
return document4;
|
|
@@ -85099,13 +85139,13 @@ async function run21(args) {
|
|
|
85099
85139
|
});
|
|
85100
85140
|
return EXIT2.OK;
|
|
85101
85141
|
}
|
|
85102
|
-
var AT_FORMS5,
|
|
85142
|
+
var AT_FORMS5, HELP16;
|
|
85103
85143
|
var init_replace2 = __esm(() => {
|
|
85104
85144
|
init_core2();
|
|
85105
85145
|
init_hyperlinks();
|
|
85106
85146
|
init_respond();
|
|
85107
85147
|
AT_FORMS5 = describeForms(["hyperlink"], " ");
|
|
85108
|
-
|
|
85148
|
+
HELP16 = `docx hyperlinks replace \u2014 change a hyperlink's URL
|
|
85109
85149
|
|
|
85110
85150
|
Usage:
|
|
85111
85151
|
docx hyperlinks replace FILE --at linkN --with URL [options]
|
|
@@ -85146,12 +85186,12 @@ Examples:
|
|
|
85146
85186
|
// src/cli/hyperlinks/index.ts
|
|
85147
85187
|
var exports_hyperlinks = {};
|
|
85148
85188
|
__export(exports_hyperlinks, {
|
|
85149
|
-
run: () =>
|
|
85189
|
+
run: () => run21
|
|
85150
85190
|
});
|
|
85151
|
-
async function
|
|
85191
|
+
async function run21(args) {
|
|
85152
85192
|
const verb = args[0];
|
|
85153
85193
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
85154
|
-
await writeStdout(
|
|
85194
|
+
await writeStdout(HELP17);
|
|
85155
85195
|
return verb ? 0 : 2;
|
|
85156
85196
|
}
|
|
85157
85197
|
const loader = SUBCOMMANDS4[verb];
|
|
@@ -85161,7 +85201,7 @@ async function run22(args) {
|
|
|
85161
85201
|
const module_ = await loader();
|
|
85162
85202
|
return module_.run(args.slice(1));
|
|
85163
85203
|
}
|
|
85164
|
-
var SUBCOMMANDS4,
|
|
85204
|
+
var SUBCOMMANDS4, HELP17 = `docx hyperlinks \u2014 manage hyperlinks
|
|
85165
85205
|
|
|
85166
85206
|
Usage:
|
|
85167
85207
|
docx hyperlinks <verb> FILE [options]
|
|
@@ -85380,24 +85420,24 @@ var init_batch3 = __esm(() => {
|
|
|
85380
85420
|
// src/cli/insert/index.tsx
|
|
85381
85421
|
var exports_insert = {};
|
|
85382
85422
|
__export(exports_insert, {
|
|
85383
|
-
run: () =>
|
|
85423
|
+
run: () => run22,
|
|
85384
85424
|
parseTargetPlacement: () => parseTargetPlacement,
|
|
85385
85425
|
parseParagraphOptions: () => parseParagraphOptions2,
|
|
85386
85426
|
chooseContentSpec: () => chooseContentSpec,
|
|
85387
85427
|
MARKDOWN_INCOMPATIBLE_FLAGS: () => MARKDOWN_INCOMPATIBLE_FLAGS2
|
|
85388
85428
|
});
|
|
85389
|
-
async function
|
|
85390
|
-
const parsed = await tryParseArgs(args,
|
|
85429
|
+
async function run22(args) {
|
|
85430
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC3, HELP18);
|
|
85391
85431
|
if (typeof parsed === "number")
|
|
85392
85432
|
return parsed;
|
|
85393
85433
|
if (parsed.values.help) {
|
|
85394
|
-
await writeStdout(
|
|
85434
|
+
await writeStdout(HELP18);
|
|
85395
85435
|
return EXIT2.OK;
|
|
85396
85436
|
}
|
|
85397
85437
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
85398
85438
|
const filePath = parsed.positionals[0];
|
|
85399
85439
|
if (!filePath)
|
|
85400
|
-
return fail("USAGE", "Missing FILE argument",
|
|
85440
|
+
return fail("USAGE", "Missing FILE argument", HELP18);
|
|
85401
85441
|
const batchInput = parsed.values.batch;
|
|
85402
85442
|
if (batchInput !== undefined) {
|
|
85403
85443
|
return runInsertBatch(filePath, batchInput, parsed.values);
|
|
@@ -85452,16 +85492,20 @@ async function commitInsert(document4, blockRef, blocks, opts) {
|
|
|
85452
85492
|
if (insertedNodes.has(reference.node))
|
|
85453
85493
|
locators.push(blockId);
|
|
85454
85494
|
}
|
|
85495
|
+
const destination = opts.outputPath ?? opts.filePath;
|
|
85455
85496
|
await respondMinted(locators, {
|
|
85456
85497
|
ok: true,
|
|
85457
85498
|
operation: "insert",
|
|
85458
|
-
path:
|
|
85499
|
+
path: destination,
|
|
85459
85500
|
locators,
|
|
85460
85501
|
anchor: opts.placement.locator,
|
|
85461
85502
|
placement: opts.placement.mode
|
|
85462
|
-
});
|
|
85503
|
+
}, isLayoutAffecting(opts.spec) ? renderVerifyHint(destination) : undefined);
|
|
85463
85504
|
return EXIT2.OK;
|
|
85464
85505
|
}
|
|
85506
|
+
function isLayoutAffecting(spec) {
|
|
85507
|
+
return spec.kind === "section" || spec.kind === "image" || spec.kind === "table" || spec.kind === "break";
|
|
85508
|
+
}
|
|
85465
85509
|
async function buildSingleShotOptions(filePath, values2) {
|
|
85466
85510
|
const placement = await parseTargetPlacement(values2);
|
|
85467
85511
|
if (typeof placement === "number")
|
|
@@ -85469,10 +85513,18 @@ async function buildSingleShotOptions(filePath, values2) {
|
|
|
85469
85513
|
const spec = await chooseContentSpec(values2);
|
|
85470
85514
|
if (typeof spec === "number")
|
|
85471
85515
|
return spec;
|
|
85516
|
+
if (spec.kind === "text") {
|
|
85517
|
+
const rejected = await rejectMarkdownInText(values2.text, HELP18);
|
|
85518
|
+
if (typeof rejected === "number")
|
|
85519
|
+
return rejected;
|
|
85520
|
+
const mangled = await rejectShellMangledValue(values2.text, HELP18, "--text");
|
|
85521
|
+
if (typeof mangled === "number")
|
|
85522
|
+
return mangled;
|
|
85523
|
+
}
|
|
85472
85524
|
if (spec.kind === "markdown") {
|
|
85473
85525
|
const conflict = MARKDOWN_INCOMPATIBLE_FLAGS2.find((flag) => values2[flag] !== undefined);
|
|
85474
85526
|
if (conflict) {
|
|
85475
|
-
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`,
|
|
85527
|
+
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`, HELP18);
|
|
85476
85528
|
}
|
|
85477
85529
|
}
|
|
85478
85530
|
const paragraphOptions = await parseParagraphOptions2(values2);
|
|
@@ -85493,23 +85545,26 @@ async function parseTargetPlacement(values2) {
|
|
|
85493
85545
|
const after = values2.after;
|
|
85494
85546
|
const before = values2.before;
|
|
85495
85547
|
if (!after && !before) {
|
|
85496
|
-
return fail("USAGE", "Missing locator: pass --after or --before",
|
|
85548
|
+
return fail("USAGE", "Missing locator: pass --after or --before", HELP18);
|
|
85497
85549
|
}
|
|
85498
85550
|
if (after && before) {
|
|
85499
|
-
return fail("USAGE", "Pass either --after or --before, not both",
|
|
85551
|
+
return fail("USAGE", "Pass either --after or --before, not both", HELP18);
|
|
85500
85552
|
}
|
|
85501
85553
|
if (after !== undefined)
|
|
85502
85554
|
return { mode: "after", locator: after };
|
|
85503
85555
|
return { mode: "before", locator: before };
|
|
85504
85556
|
}
|
|
85505
85557
|
async function chooseContentSpec(values2) {
|
|
85558
|
+
if (values2.section !== undefined || values2.columns !== undefined || values2.type !== undefined) {
|
|
85559
|
+
return fail("USAGE", "insert no longer creates section/column layout \u2014 use `docx sections`", "To put paragraphs pN\u2026pM in N columns: `docx sections --at pN-pM --columns N`. To recount an existing section: `docx sections --at sN --columns N`.");
|
|
85560
|
+
}
|
|
85506
85561
|
const present = CONTENT_KINDS.filter((kind) => values2[kind.flag] !== undefined);
|
|
85507
85562
|
if (present.length > 1) {
|
|
85508
|
-
return fail("USAGE", `Pass only one of ${CONTENT_FLAG_LIST}`,
|
|
85563
|
+
return fail("USAGE", `Pass only one of ${CONTENT_FLAG_LIST}`, HELP18);
|
|
85509
85564
|
}
|
|
85510
85565
|
const chosen = present[0];
|
|
85511
85566
|
if (!chosen) {
|
|
85512
|
-
return fail("USAGE", `Missing content: pass ${CONTENT_FLAG_LIST}`,
|
|
85567
|
+
return fail("USAGE", `Missing content: pass ${CONTENT_FLAG_LIST}`, HELP18);
|
|
85513
85568
|
}
|
|
85514
85569
|
const chosenSubFlags = new Set(chosen.subFlags);
|
|
85515
85570
|
for (const kind of CONTENT_KINDS) {
|
|
@@ -85517,7 +85572,7 @@ async function chooseContentSpec(values2) {
|
|
|
85517
85572
|
continue;
|
|
85518
85573
|
const orphan = kind.subFlags.find((flag) => values2[flag] !== undefined && !chosenSubFlags.has(flag));
|
|
85519
85574
|
if (orphan) {
|
|
85520
|
-
return fail("USAGE", `--${orphan} requires --${kind.flag}`,
|
|
85575
|
+
return fail("USAGE", `--${orphan} requires --${kind.flag}`, HELP18);
|
|
85521
85576
|
}
|
|
85522
85577
|
}
|
|
85523
85578
|
switch (chosen.flag) {
|
|
@@ -85531,10 +85586,6 @@ async function chooseContentSpec(values2) {
|
|
|
85531
85586
|
return { kind: "break", breakKind: "page" };
|
|
85532
85587
|
case "column-break":
|
|
85533
85588
|
return { kind: "break", breakKind: "column" };
|
|
85534
|
-
case "section": {
|
|
85535
|
-
const flags = await parseSectionFlags(values2);
|
|
85536
|
-
return typeof flags === "number" ? flags : { kind: "section", ...flags };
|
|
85537
|
-
}
|
|
85538
85589
|
case "table": {
|
|
85539
85590
|
const flags = await parseTableFlags(values2);
|
|
85540
85591
|
return typeof flags === "number" ? flags : { kind: "table", ...flags };
|
|
@@ -85589,7 +85640,7 @@ async function resolveCodeSpec(values2, flag) {
|
|
|
85589
85640
|
async function parseImageFlags(values2) {
|
|
85590
85641
|
const src = values2.image;
|
|
85591
85642
|
if (!src)
|
|
85592
|
-
return fail("USAGE", "--image requires a SRC argument",
|
|
85643
|
+
return fail("USAGE", "--image requires a SRC argument", HELP18);
|
|
85593
85644
|
const out = { src };
|
|
85594
85645
|
const alt = values2.alt;
|
|
85595
85646
|
if (alt !== undefined)
|
|
@@ -85632,7 +85683,7 @@ async function parseTableFlags(values2) {
|
|
|
85632
85683
|
const rowsRaw = values2.rows;
|
|
85633
85684
|
const colsRaw = values2.cols;
|
|
85634
85685
|
if (rowsRaw === undefined || colsRaw === undefined) {
|
|
85635
|
-
return fail("USAGE", "--table requires --rows and --cols",
|
|
85686
|
+
return fail("USAGE", "--table requires --rows and --cols", HELP18);
|
|
85636
85687
|
}
|
|
85637
85688
|
const rows = Number.parseInt(rowsRaw, 10);
|
|
85638
85689
|
const cols = Number.parseInt(colsRaw, 10);
|
|
@@ -85709,18 +85760,18 @@ async function parseParagraphOptions2(values2) {
|
|
|
85709
85760
|
const listValue = values2.list;
|
|
85710
85761
|
const listLevelValue = values2["list-level"];
|
|
85711
85762
|
if (taskValue !== undefined && listValue !== undefined) {
|
|
85712
|
-
return fail("USAGE", "--task and --list are mutually exclusive (--task already implies a bullet list)",
|
|
85763
|
+
return fail("USAGE", "--task and --list are mutually exclusive (--task already implies a bullet list)", HELP18);
|
|
85713
85764
|
}
|
|
85714
85765
|
if (taskValue !== undefined) {
|
|
85715
85766
|
const checked = parseTaskFlag(taskValue);
|
|
85716
85767
|
if (checked === null) {
|
|
85717
|
-
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskValue}"`,
|
|
85768
|
+
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskValue}"`, HELP18);
|
|
85718
85769
|
}
|
|
85719
85770
|
out.taskState = checked ? "checked" : "unchecked";
|
|
85720
85771
|
}
|
|
85721
85772
|
if (listValue !== undefined) {
|
|
85722
85773
|
if (listValue !== "bullet" && listValue !== "ordered") {
|
|
85723
|
-
return fail("USAGE", `--list must be "bullet" or "ordered", got "${listValue}"`,
|
|
85774
|
+
return fail("USAGE", `--list must be "bullet" or "ordered", got "${listValue}"`, HELP18);
|
|
85724
85775
|
}
|
|
85725
85776
|
out.list = { level: 0, numId: -1 };
|
|
85726
85777
|
out.listKind = listValue;
|
|
@@ -85728,7 +85779,7 @@ async function parseParagraphOptions2(values2) {
|
|
|
85728
85779
|
if (listLevelValue !== undefined) {
|
|
85729
85780
|
const level = Number(listLevelValue);
|
|
85730
85781
|
if (!Number.isInteger(level) || level < 0 || level > 8) {
|
|
85731
|
-
return fail("USAGE", `--list-level must be an integer 0-8, got "${listLevelValue}"`,
|
|
85782
|
+
return fail("USAGE", `--list-level must be an integer 0-8, got "${listLevelValue}"`, HELP18);
|
|
85732
85783
|
}
|
|
85733
85784
|
if (out.list)
|
|
85734
85785
|
out.list.level = level;
|
|
@@ -85736,14 +85787,14 @@ async function parseParagraphOptions2(values2) {
|
|
|
85736
85787
|
}
|
|
85737
85788
|
return out;
|
|
85738
85789
|
}
|
|
85739
|
-
var ANCHOR_FORMS2,
|
|
85790
|
+
var ANCHOR_FORMS2, HELP18, OPTION_SPEC3, MARKDOWN_INCOMPATIBLE_FLAGS2, CONTENT_KINDS, CONTENT_FLAG_LIST;
|
|
85740
85791
|
var init_insert2 = __esm(() => {
|
|
85741
85792
|
init_core2();
|
|
85742
85793
|
init_parse_helpers();
|
|
85743
85794
|
init_respond();
|
|
85744
85795
|
init_batch3();
|
|
85745
85796
|
ANCHOR_FORMS2 = describeForms(["paragraph", "table", "section", "cellParagraph"], " ");
|
|
85746
|
-
|
|
85797
|
+
HELP18 = `docx insert \u2014 insert a block (paragraph, table, image, \u2026) at a locator
|
|
85747
85798
|
|
|
85748
85799
|
Usage:
|
|
85749
85800
|
docx insert FILE (--after | --before) LOCATOR <content> [options]
|
|
@@ -85762,7 +85813,6 @@ Content (one required):
|
|
|
85762
85813
|
--runs JSON Insert a paragraph with custom runs (Run[] JSON)
|
|
85763
85814
|
--page-break Insert an empty paragraph containing a page break
|
|
85764
85815
|
--column-break Insert an empty paragraph containing a column break
|
|
85765
|
-
--section Insert a section boundary (sentinel paragraph w/ inline sectPr)
|
|
85766
85816
|
--table Insert an empty rows\xD7cols table (requires --rows and --cols)
|
|
85767
85817
|
--image SRC Insert an image (SRC is a file path, data: URI, or http(s) URL)
|
|
85768
85818
|
--code TEXT Insert a multi-line code block. Newlines split into one
|
|
@@ -85808,19 +85858,20 @@ Run options (only with --text):
|
|
|
85808
85858
|
--italic Italic
|
|
85809
85859
|
--url URL Wrap the inserted text in a hyperlink to URL
|
|
85810
85860
|
|
|
85811
|
-
|
|
85812
|
-
|
|
85813
|
-
|
|
85861
|
+
Column / section layout: NOT here \u2014 use \`docx sections\`. Name the range and it
|
|
85862
|
+
inserts the bounding breaks correctly: \`docx sections --at p6-p16 --columns 2\`.
|
|
85863
|
+
(A raw section break formats the content ABOVE it, the off-by-one that made
|
|
85864
|
+
\`insert --section\` a footgun, so it was removed.)
|
|
85814
85865
|
|
|
85815
85866
|
Agent tip: VERIFY LAYOUT VISUALLY: \`docx read\` shows text and structure as
|
|
85816
|
-
Markdown, but NOT how the page actually looks \u2014
|
|
85817
|
-
|
|
85818
|
-
|
|
85819
|
-
|
|
85867
|
+
Markdown, but NOT how the page actually looks \u2014 page breaks, image sizing, and
|
|
85868
|
+
where content lands on the page do not appear there. After inserting
|
|
85869
|
+
layout-affecting content (--page-break, --image, --table), render the document to
|
|
85870
|
+
images and look at them:
|
|
85820
85871
|
docx render FILE --out pages/ # writes page-001.png, page-002.png, \u2026
|
|
85821
|
-
Read the PNGs, check the layout reads the way you intended (
|
|
85822
|
-
|
|
85823
|
-
|
|
85872
|
+
Read the PNGs, check the layout reads the way you intended (no stray blank page,
|
|
85873
|
+
figure sized sensibly), and adjust placement + re-render until it looks right.
|
|
85874
|
+
Don't assume a layout-affecting insert looks good without seeing it.
|
|
85824
85875
|
|
|
85825
85876
|
Table options (only with --table):
|
|
85826
85877
|
--rows N Number of rows (required, >= 1)
|
|
@@ -85869,7 +85920,6 @@ Examples:
|
|
|
85869
85920
|
docx insert doc.docx --after p2 --runs '[{"type":"text","text":"X","bold":true}]'
|
|
85870
85921
|
docx insert doc.docx --after p3 --text "click here" --url https://example.com
|
|
85871
85922
|
docx insert doc.docx --after p3 --page-break
|
|
85872
|
-
docx insert doc.docx --after p9 --section --columns 2 --type continuous
|
|
85873
85923
|
docx insert doc.docx --after p3 --table --rows 3 --cols 2
|
|
85874
85924
|
docx insert doc.docx --after p3 --table --rows 2 --cols 3 --widths 1440,2880,4320
|
|
85875
85925
|
docx insert doc.docx --after p3 --image ./diagram.png --alt "System diagram"
|
|
@@ -85887,7 +85937,7 @@ Batch JSONL example (keys mirror the flags; one insert per line):
|
|
|
85887
85937
|
{"before": "p0", "text": "ALERT", "color": "CC0000", "bold": true}
|
|
85888
85938
|
{"after": "p5", "markdown": "## Summary\\n\\n- point a\\n- point b"}
|
|
85889
85939
|
`;
|
|
85890
|
-
|
|
85940
|
+
OPTION_SPEC3 = {
|
|
85891
85941
|
after: { type: "string" },
|
|
85892
85942
|
before: { type: "string" },
|
|
85893
85943
|
batch: { type: "string" },
|
|
@@ -85942,7 +85992,6 @@ Batch JSONL example (keys mirror the flags; one insert per line):
|
|
|
85942
85992
|
{ flag: "runs", subFlags: [] },
|
|
85943
85993
|
{ flag: "page-break", subFlags: [] },
|
|
85944
85994
|
{ flag: "column-break", subFlags: [] },
|
|
85945
|
-
{ flag: "section", subFlags: ["columns", "type"] },
|
|
85946
85995
|
{
|
|
85947
85996
|
flag: "table",
|
|
85948
85997
|
subFlags: ["rows", "cols", "widths", "table-width", "borders", "layout"]
|
|
@@ -85960,16 +86009,16 @@ Batch JSONL example (keys mirror the flags; one insert per line):
|
|
|
85960
86009
|
// src/cli/images/add.ts
|
|
85961
86010
|
var exports_add4 = {};
|
|
85962
86011
|
__export(exports_add4, {
|
|
85963
|
-
run: () =>
|
|
86012
|
+
run: () => run23
|
|
85964
86013
|
});
|
|
85965
|
-
async function
|
|
86014
|
+
async function run23(args) {
|
|
85966
86015
|
if (args[0] === "-h" || args[0] === "--help") {
|
|
85967
|
-
await writeStdout(
|
|
86016
|
+
await writeStdout(HELP19);
|
|
85968
86017
|
return 0;
|
|
85969
86018
|
}
|
|
85970
|
-
return
|
|
86019
|
+
return run22(args);
|
|
85971
86020
|
}
|
|
85972
|
-
var
|
|
86021
|
+
var HELP19 = `docx images add \u2014 insert an image (an alias for \`docx insert --image\`)
|
|
85973
86022
|
|
|
85974
86023
|
Usage:
|
|
85975
86024
|
docx images add FILE --image PATH --after pN [options]
|
|
@@ -85993,28 +86042,28 @@ var init_add4 = __esm(() => {
|
|
|
85993
86042
|
// src/cli/images/delete.tsx
|
|
85994
86043
|
var exports_delete5 = {};
|
|
85995
86044
|
__export(exports_delete5, {
|
|
85996
|
-
run: () =>
|
|
86045
|
+
run: () => run24
|
|
85997
86046
|
});
|
|
85998
|
-
async function
|
|
86047
|
+
async function run24(args) {
|
|
85999
86048
|
const parsed = await tryParseArgs(args, {
|
|
86000
86049
|
at: { type: "string" },
|
|
86001
86050
|
author: { type: "string" },
|
|
86002
86051
|
track: { type: "boolean" },
|
|
86003
86052
|
...SAVE_FLAGS
|
|
86004
|
-
},
|
|
86053
|
+
}, HELP20);
|
|
86005
86054
|
if (typeof parsed === "number")
|
|
86006
86055
|
return parsed;
|
|
86007
86056
|
if (parsed.values.help) {
|
|
86008
|
-
await writeStdout(
|
|
86057
|
+
await writeStdout(HELP20);
|
|
86009
86058
|
return EXIT2.OK;
|
|
86010
86059
|
}
|
|
86011
86060
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
86012
86061
|
const path2 = parsed.positionals[0];
|
|
86013
86062
|
if (!path2)
|
|
86014
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86063
|
+
return fail("USAGE", "Missing FILE argument", HELP20);
|
|
86015
86064
|
const targetId = parsed.values.at;
|
|
86016
86065
|
if (!targetId)
|
|
86017
|
-
return fail("USAGE", "Missing --at imgN",
|
|
86066
|
+
return fail("USAGE", "Missing --at imgN", HELP20);
|
|
86018
86067
|
const document4 = await openOrFail(path2);
|
|
86019
86068
|
if (typeof document4 === "number")
|
|
86020
86069
|
return document4;
|
|
@@ -86084,7 +86133,7 @@ function pruneIfUnreferenced(document4, relationshipId) {
|
|
|
86084
86133
|
}
|
|
86085
86134
|
return true;
|
|
86086
86135
|
}
|
|
86087
|
-
var
|
|
86136
|
+
var HELP20 = `docx images delete \u2014 remove an embedded image
|
|
86088
86137
|
|
|
86089
86138
|
Usage:
|
|
86090
86139
|
docx images delete FILE --at imgN [options]
|
|
@@ -86129,27 +86178,27 @@ var init_delete5 = __esm(() => {
|
|
|
86129
86178
|
// src/cli/images/extract.ts
|
|
86130
86179
|
var exports_extract = {};
|
|
86131
86180
|
__export(exports_extract, {
|
|
86132
|
-
run: () =>
|
|
86181
|
+
run: () => run25
|
|
86133
86182
|
});
|
|
86134
86183
|
import { join as join6 } from "path";
|
|
86135
|
-
async function
|
|
86184
|
+
async function run25(args) {
|
|
86136
86185
|
const parsed = await tryParseArgs(args, {
|
|
86137
86186
|
to: { type: "string" },
|
|
86138
86187
|
at: { type: "string" },
|
|
86139
86188
|
help: { type: "boolean", short: "h" }
|
|
86140
|
-
},
|
|
86189
|
+
}, HELP21);
|
|
86141
86190
|
if (typeof parsed === "number")
|
|
86142
86191
|
return parsed;
|
|
86143
86192
|
if (parsed.values.help) {
|
|
86144
|
-
await writeStdout(
|
|
86193
|
+
await writeStdout(HELP21);
|
|
86145
86194
|
return EXIT2.OK;
|
|
86146
86195
|
}
|
|
86147
86196
|
const path2 = parsed.positionals[0];
|
|
86148
86197
|
if (!path2)
|
|
86149
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86198
|
+
return fail("USAGE", "Missing FILE argument", HELP21);
|
|
86150
86199
|
const outputDir = parsed.values.to;
|
|
86151
86200
|
if (!outputDir)
|
|
86152
|
-
return fail("USAGE", "Missing --to DIR",
|
|
86201
|
+
return fail("USAGE", "Missing --to DIR", HELP21);
|
|
86153
86202
|
const targetId = parsed.values.at;
|
|
86154
86203
|
const document4 = await openOrFail(path2);
|
|
86155
86204
|
if (typeof document4 === "number")
|
|
@@ -86190,7 +86239,7 @@ function extensionFor(contentType, partName) {
|
|
|
86190
86239
|
const fromName = partName.split(".").pop()?.toLowerCase();
|
|
86191
86240
|
return fromName ?? "bin";
|
|
86192
86241
|
}
|
|
86193
|
-
var
|
|
86242
|
+
var HELP21 = `docx images extract \u2014 dump image bytes to a directory
|
|
86194
86243
|
|
|
86195
86244
|
Usage:
|
|
86196
86245
|
docx images extract FILE --to DIR [options]
|
|
@@ -86223,21 +86272,21 @@ var init_extract = __esm(() => {
|
|
|
86223
86272
|
// src/cli/images/list.ts
|
|
86224
86273
|
var exports_list4 = {};
|
|
86225
86274
|
__export(exports_list4, {
|
|
86226
|
-
run: () =>
|
|
86275
|
+
run: () => run26
|
|
86227
86276
|
});
|
|
86228
|
-
async function
|
|
86277
|
+
async function run26(args) {
|
|
86229
86278
|
const parsed = await tryParseArgs(args, {
|
|
86230
86279
|
help: { type: "boolean", short: "h" }
|
|
86231
|
-
},
|
|
86280
|
+
}, HELP22);
|
|
86232
86281
|
if (typeof parsed === "number")
|
|
86233
86282
|
return parsed;
|
|
86234
86283
|
if (parsed.values.help) {
|
|
86235
|
-
await writeStdout(
|
|
86284
|
+
await writeStdout(HELP22);
|
|
86236
86285
|
return EXIT2.OK;
|
|
86237
86286
|
}
|
|
86238
86287
|
const path2 = parsed.positionals[0];
|
|
86239
86288
|
if (!path2)
|
|
86240
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86289
|
+
return fail("USAGE", "Missing FILE argument", HELP22);
|
|
86241
86290
|
const document4 = await openOrFail(path2);
|
|
86242
86291
|
if (typeof document4 === "number")
|
|
86243
86292
|
return document4;
|
|
@@ -86245,7 +86294,7 @@ async function run27(args) {
|
|
|
86245
86294
|
await respond(flattenImageRuns(document4.body.blocks));
|
|
86246
86295
|
return EXIT2.OK;
|
|
86247
86296
|
}
|
|
86248
|
-
var
|
|
86297
|
+
var HELP22 = `docx images list \u2014 print image manifest as JSON
|
|
86249
86298
|
|
|
86250
86299
|
Usage:
|
|
86251
86300
|
docx images list FILE [options]
|
|
@@ -86271,31 +86320,31 @@ var init_list6 = __esm(() => {
|
|
|
86271
86320
|
// src/cli/images/replace.ts
|
|
86272
86321
|
var exports_replace2 = {};
|
|
86273
86322
|
__export(exports_replace2, {
|
|
86274
|
-
run: () =>
|
|
86323
|
+
run: () => run27
|
|
86275
86324
|
});
|
|
86276
|
-
async function
|
|
86325
|
+
async function run27(args) {
|
|
86277
86326
|
const parsed = await tryParseArgs(args, {
|
|
86278
86327
|
at: { type: "string" },
|
|
86279
86328
|
with: { type: "string" },
|
|
86280
86329
|
author: { type: "string" },
|
|
86281
86330
|
...SAVE_FLAGS
|
|
86282
|
-
},
|
|
86331
|
+
}, HELP23);
|
|
86283
86332
|
if (typeof parsed === "number")
|
|
86284
86333
|
return parsed;
|
|
86285
86334
|
if (parsed.values.help) {
|
|
86286
|
-
await writeStdout(
|
|
86335
|
+
await writeStdout(HELP23);
|
|
86287
86336
|
return EXIT2.OK;
|
|
86288
86337
|
}
|
|
86289
86338
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
86290
86339
|
const path2 = parsed.positionals[0];
|
|
86291
86340
|
if (!path2)
|
|
86292
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86341
|
+
return fail("USAGE", "Missing FILE argument", HELP23);
|
|
86293
86342
|
const targetId = parsed.values.at;
|
|
86294
86343
|
if (!targetId)
|
|
86295
|
-
return fail("USAGE", "Missing --at imgN",
|
|
86344
|
+
return fail("USAGE", "Missing --at imgN", HELP23);
|
|
86296
86345
|
const sourcePath = parsed.values.with;
|
|
86297
86346
|
if (!sourcePath)
|
|
86298
|
-
return fail("USAGE", "Missing --with PATH",
|
|
86347
|
+
return fail("USAGE", "Missing --with PATH", HELP23);
|
|
86299
86348
|
const sourceFile = Bun.file(sourcePath);
|
|
86300
86349
|
if (!await sourceFile.exists()) {
|
|
86301
86350
|
return fail("FILE_NOT_FOUND", `Replacement file not found: ${sourcePath}`);
|
|
@@ -86386,7 +86435,7 @@ function renameExtension(partName, newExtension) {
|
|
|
86386
86435
|
function relativeTargetFor(partName) {
|
|
86387
86436
|
return partName.startsWith("word/") ? partName.slice("word/".length) : partName;
|
|
86388
86437
|
}
|
|
86389
|
-
var
|
|
86438
|
+
var HELP23 = `docx images replace \u2014 swap an image's bytes
|
|
86390
86439
|
|
|
86391
86440
|
Usage:
|
|
86392
86441
|
docx images replace FILE --at imgN --with PATH [options]
|
|
@@ -86431,12 +86480,12 @@ var init_replace3 = __esm(() => {
|
|
|
86431
86480
|
// src/cli/images/index.ts
|
|
86432
86481
|
var exports_images = {};
|
|
86433
86482
|
__export(exports_images, {
|
|
86434
|
-
run: () =>
|
|
86483
|
+
run: () => run28
|
|
86435
86484
|
});
|
|
86436
|
-
async function
|
|
86485
|
+
async function run28(args) {
|
|
86437
86486
|
const verb = args[0];
|
|
86438
86487
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
86439
|
-
await writeStdout(
|
|
86488
|
+
await writeStdout(HELP24);
|
|
86440
86489
|
return verb ? 0 : 2;
|
|
86441
86490
|
}
|
|
86442
86491
|
const loader = SUBCOMMANDS5[verb];
|
|
@@ -86446,7 +86495,7 @@ async function run29(args) {
|
|
|
86446
86495
|
const module_ = await loader();
|
|
86447
86496
|
return module_.run(args.slice(1));
|
|
86448
86497
|
}
|
|
86449
|
-
var SUBCOMMANDS5,
|
|
86498
|
+
var SUBCOMMANDS5, HELP24 = `docx images \u2014 manage embedded images
|
|
86450
86499
|
|
|
86451
86500
|
Usage:
|
|
86452
86501
|
docx images <verb> FILE [options]
|
|
@@ -86501,6 +86550,13 @@ export type Paragraph = {
|
|
|
86501
86550
|
* them at top level, breaking the quote at that point. See
|
|
86502
86551
|
* [src/core/markdown/CLAUDE.md](../markdown/CLAUDE.md). */
|
|
86503
86552
|
quoteDepth?: number;
|
|
86553
|
+
/** Explicit tab stops from \`<w:pPr><w:tabs>\`, each \`{ align, pos }\` (pos in
|
|
86554
|
+
* twips). Surfaced so \`read\` can flag a fragile right-alignment: a LEFT (or
|
|
86555
|
+
* center) tab stop near the right margin pushes content rightward but \u2014 unlike
|
|
86556
|
+
* a RIGHT tab \u2014 wraps anything wider than the gap to the margin (the r\xE9sum\xE9
|
|
86557
|
+
* "San / Francisco, CA" break). Present only when the paragraph declares
|
|
86558
|
+
* explicit tab stops. */
|
|
86559
|
+
tabStops?: { align: string; pos: number }[];
|
|
86504
86560
|
runs: Run[];
|
|
86505
86561
|
};
|
|
86506
86562
|
|
|
@@ -86806,18 +86862,18 @@ var init_types3 = () => {};
|
|
|
86806
86862
|
// src/cli/info/schema.ts
|
|
86807
86863
|
var exports_schema = {};
|
|
86808
86864
|
__export(exports_schema, {
|
|
86809
|
-
run: () =>
|
|
86865
|
+
run: () => run29
|
|
86810
86866
|
});
|
|
86811
|
-
async function
|
|
86867
|
+
async function run29(args) {
|
|
86812
86868
|
const parsed = await tryParseArgs(args, {
|
|
86813
86869
|
json: { type: "boolean" },
|
|
86814
86870
|
ts: { type: "boolean" },
|
|
86815
86871
|
help: { type: "boolean", short: "h" }
|
|
86816
|
-
},
|
|
86872
|
+
}, HELP25);
|
|
86817
86873
|
if (typeof parsed === "number")
|
|
86818
86874
|
return parsed;
|
|
86819
86875
|
if (parsed.values.help) {
|
|
86820
|
-
await writeStdout(
|
|
86876
|
+
await writeStdout(HELP25);
|
|
86821
86877
|
return EXIT2.OK;
|
|
86822
86878
|
}
|
|
86823
86879
|
if (parsed.values.ts) {
|
|
@@ -86827,7 +86883,7 @@ async function run30(args) {
|
|
|
86827
86883
|
await respond(JSON_SCHEMA);
|
|
86828
86884
|
return EXIT2.OK;
|
|
86829
86885
|
}
|
|
86830
|
-
var
|
|
86886
|
+
var HELP25 = `docx info schema \u2014 print the AST type definitions
|
|
86831
86887
|
|
|
86832
86888
|
Usage:
|
|
86833
86889
|
docx info schema [options]
|
|
@@ -86901,6 +86957,17 @@ var init_schema = __esm(() => {
|
|
|
86901
86957
|
}
|
|
86902
86958
|
},
|
|
86903
86959
|
taskState: { enum: ["checked", "unchecked"] },
|
|
86960
|
+
tabStops: {
|
|
86961
|
+
type: "array",
|
|
86962
|
+
items: {
|
|
86963
|
+
type: "object",
|
|
86964
|
+
required: ["align", "pos"],
|
|
86965
|
+
properties: {
|
|
86966
|
+
align: { type: "string" },
|
|
86967
|
+
pos: { type: "number" }
|
|
86968
|
+
}
|
|
86969
|
+
}
|
|
86970
|
+
},
|
|
86904
86971
|
runs: { type: "array", items: { $ref: "#/$defs/Run" } }
|
|
86905
86972
|
}
|
|
86906
86973
|
},
|
|
@@ -87155,7 +87222,7 @@ var init_schema = __esm(() => {
|
|
|
87155
87222
|
// src/cli/info/locators.ts
|
|
87156
87223
|
var exports_locators = {};
|
|
87157
87224
|
__export(exports_locators, {
|
|
87158
|
-
run: () =>
|
|
87225
|
+
run: () => run30
|
|
87159
87226
|
});
|
|
87160
87227
|
function renderReference() {
|
|
87161
87228
|
const sections = GROUPS.map((group) => {
|
|
@@ -87286,15 +87353,15 @@ function renderJson() {
|
|
|
87286
87353
|
]
|
|
87287
87354
|
};
|
|
87288
87355
|
}
|
|
87289
|
-
async function
|
|
87356
|
+
async function run30(args) {
|
|
87290
87357
|
const parsed = await tryParseArgs(args, {
|
|
87291
87358
|
json: { type: "boolean" },
|
|
87292
87359
|
help: { type: "boolean", short: "h" }
|
|
87293
|
-
},
|
|
87360
|
+
}, HELP26);
|
|
87294
87361
|
if (typeof parsed === "number")
|
|
87295
87362
|
return parsed;
|
|
87296
87363
|
if (parsed.values.help) {
|
|
87297
|
-
await writeStdout(
|
|
87364
|
+
await writeStdout(HELP26);
|
|
87298
87365
|
return EXIT2.OK;
|
|
87299
87366
|
}
|
|
87300
87367
|
if (parsed.values.json) {
|
|
@@ -87305,7 +87372,7 @@ async function run31(args) {
|
|
|
87305
87372
|
await writeStdout(renderReference());
|
|
87306
87373
|
return EXIT2.OK;
|
|
87307
87374
|
}
|
|
87308
|
-
var
|
|
87375
|
+
var HELP26 = `docx info locators \u2014 print the locator grammar reference
|
|
87309
87376
|
|
|
87310
87377
|
Usage:
|
|
87311
87378
|
docx info locators [options]
|
|
@@ -87357,12 +87424,12 @@ var init_locators2 = __esm(() => {
|
|
|
87357
87424
|
// src/cli/info/index.ts
|
|
87358
87425
|
var exports_info = {};
|
|
87359
87426
|
__export(exports_info, {
|
|
87360
|
-
run: () =>
|
|
87427
|
+
run: () => run31
|
|
87361
87428
|
});
|
|
87362
|
-
async function
|
|
87429
|
+
async function run31(args) {
|
|
87363
87430
|
const topic = args[0];
|
|
87364
87431
|
if (!topic || topic === "--help" || topic === "-h" || topic === "help") {
|
|
87365
|
-
await writeStdout(
|
|
87432
|
+
await writeStdout(HELP27);
|
|
87366
87433
|
return topic ? 0 : 2;
|
|
87367
87434
|
}
|
|
87368
87435
|
const loader = SUBCOMMANDS6[topic];
|
|
@@ -87372,7 +87439,7 @@ async function run32(args) {
|
|
|
87372
87439
|
const module_ = await loader();
|
|
87373
87440
|
return module_.run(args.slice(1));
|
|
87374
87441
|
}
|
|
87375
|
-
var SUBCOMMANDS6,
|
|
87442
|
+
var SUBCOMMANDS6, HELP27 = `docx info \u2014 print reference material about the CLI
|
|
87376
87443
|
|
|
87377
87444
|
Usage:
|
|
87378
87445
|
docx info <topic> [options]
|
|
@@ -87452,23 +87519,23 @@ var init_build = __esm(() => {
|
|
|
87452
87519
|
// src/cli/outline/index.ts
|
|
87453
87520
|
var exports_outline = {};
|
|
87454
87521
|
__export(exports_outline, {
|
|
87455
|
-
run: () =>
|
|
87522
|
+
run: () => run32
|
|
87456
87523
|
});
|
|
87457
|
-
async function
|
|
87524
|
+
async function run32(args) {
|
|
87458
87525
|
const parsed = await tryParseArgs(args, {
|
|
87459
87526
|
"style-prefix": { type: "string" },
|
|
87460
87527
|
json: { type: "boolean" },
|
|
87461
87528
|
help: { type: "boolean", short: "h" }
|
|
87462
|
-
},
|
|
87529
|
+
}, HELP28);
|
|
87463
87530
|
if (typeof parsed === "number")
|
|
87464
87531
|
return parsed;
|
|
87465
87532
|
if (parsed.values.help) {
|
|
87466
|
-
await writeStdout(
|
|
87533
|
+
await writeStdout(HELP28);
|
|
87467
87534
|
return EXIT2.OK;
|
|
87468
87535
|
}
|
|
87469
87536
|
const path2 = parsed.positionals[0];
|
|
87470
87537
|
if (!path2)
|
|
87471
|
-
return fail("USAGE", "Missing FILE argument",
|
|
87538
|
+
return fail("USAGE", "Missing FILE argument", HELP28);
|
|
87472
87539
|
const stylePrefix = parsed.values["style-prefix"] ?? "Heading";
|
|
87473
87540
|
if (stylePrefix.length === 0) {
|
|
87474
87541
|
return fail("USAGE", "--style-prefix cannot be empty");
|
|
@@ -87496,7 +87563,7 @@ function renderOutlineText(entries, depth = 0) {
|
|
|
87496
87563
|
}
|
|
87497
87564
|
return lines;
|
|
87498
87565
|
}
|
|
87499
|
-
var
|
|
87566
|
+
var HELP28 = `docx outline \u2014 list headings as a hierarchical tree
|
|
87500
87567
|
|
|
87501
87568
|
Usage:
|
|
87502
87569
|
docx outline FILE [options]
|
|
@@ -87564,7 +87631,9 @@ function renderMarkdown(doc, options = {}) {
|
|
|
87564
87631
|
referencedEndnoteIds: new Set,
|
|
87565
87632
|
referencedTrackedChanges: new Map,
|
|
87566
87633
|
orderedCounters: new Map,
|
|
87567
|
-
contentWidthEmu: contentWidthEmu(documentGeometry(blocks))
|
|
87634
|
+
contentWidthEmu: contentWidthEmu(documentGeometry(blocks)),
|
|
87635
|
+
governingColumns: computeGoverningColumns(blocks),
|
|
87636
|
+
wrappingTabLines: []
|
|
87568
87637
|
};
|
|
87569
87638
|
const parts = [];
|
|
87570
87639
|
let cursor = 0;
|
|
@@ -87591,7 +87660,7 @@ function renderMarkdown(doc, options = {}) {
|
|
|
87591
87660
|
cursor = lookahead2;
|
|
87592
87661
|
continue;
|
|
87593
87662
|
}
|
|
87594
|
-
const rendered = renderBlock(block, ctx);
|
|
87663
|
+
const rendered = renderBlock(block, ctx, blocks, cursor);
|
|
87595
87664
|
if (rendered !== null)
|
|
87596
87665
|
parts.push(rendered);
|
|
87597
87666
|
cursor++;
|
|
@@ -87618,7 +87687,9 @@ function renderMarkdown(doc, options = {}) {
|
|
|
87618
87687
|
return "";
|
|
87619
87688
|
const baseNote = formatBaseNote(dominant);
|
|
87620
87689
|
const pageNote = formatPageNote(documentGeometry(blocks));
|
|
87621
|
-
const
|
|
87690
|
+
const trackNote = options.trackChangesOn ? formatNote("track-changes", [], ["on"]) : "";
|
|
87691
|
+
const wrapSummary = formatWrappingTabSummary(ctx.wrappingTabLines);
|
|
87692
|
+
const headLines = [baseNote, pageNote, trackNote, wrapSummary].filter((line) => line.length > 0);
|
|
87622
87693
|
const head = headLines.length > 0 ? `${headLines.join(`
|
|
87623
87694
|
`)}
|
|
87624
87695
|
|
|
@@ -87633,17 +87704,17 @@ function detectFormatBaseline(blocks) {
|
|
|
87633
87704
|
const sizeChars = new Map;
|
|
87634
87705
|
let total = 0;
|
|
87635
87706
|
for (const paragraph2 of flattenParagraphs(blocks)) {
|
|
87636
|
-
for (const
|
|
87637
|
-
if (
|
|
87707
|
+
for (const run33 of paragraph2.runs) {
|
|
87708
|
+
if (run33.type !== "text")
|
|
87638
87709
|
continue;
|
|
87639
|
-
const length =
|
|
87710
|
+
const length = run33.text.length;
|
|
87640
87711
|
if (length === 0)
|
|
87641
87712
|
continue;
|
|
87642
87713
|
total += length;
|
|
87643
|
-
if (
|
|
87644
|
-
fontChars.set(
|
|
87645
|
-
if (
|
|
87646
|
-
sizeChars.set(
|
|
87714
|
+
if (run33.font)
|
|
87715
|
+
fontChars.set(run33.font, (fontChars.get(run33.font) ?? 0) + length);
|
|
87716
|
+
if (run33.sizeHalfPoints !== undefined) {
|
|
87717
|
+
sizeChars.set(run33.sizeHalfPoints, (sizeChars.get(run33.sizeHalfPoints) ?? 0) + length);
|
|
87647
87718
|
}
|
|
87648
87719
|
}
|
|
87649
87720
|
}
|
|
@@ -87677,8 +87748,8 @@ function emptyCommentIndex() {
|
|
|
87677
87748
|
orderedIds: []
|
|
87678
87749
|
};
|
|
87679
87750
|
}
|
|
87680
|
-
function isRunVisible(
|
|
87681
|
-
const kind =
|
|
87751
|
+
function isRunVisible(run33, view) {
|
|
87752
|
+
const kind = run33.trackedChange?.kind;
|
|
87682
87753
|
if (!kind)
|
|
87683
87754
|
return true;
|
|
87684
87755
|
if (view === "accepted" && (kind === "del" || kind === "moveFrom"))
|
|
@@ -87693,13 +87764,13 @@ function buildCommentIndex(blocks, options) {
|
|
|
87693
87764
|
const spanText = new Map;
|
|
87694
87765
|
const orderedIds = [];
|
|
87695
87766
|
for (const paragraph2 of flattenParagraphs(blocks)) {
|
|
87696
|
-
paragraph2.runs.forEach((
|
|
87697
|
-
const comments = runComments(
|
|
87767
|
+
paragraph2.runs.forEach((run33, index2) => {
|
|
87768
|
+
const comments = runComments(run33);
|
|
87698
87769
|
if (!comments)
|
|
87699
87770
|
return;
|
|
87700
|
-
if (
|
|
87771
|
+
if (run33.type === "text" && !isRunVisible(run33, view))
|
|
87701
87772
|
return;
|
|
87702
|
-
const spanContribution =
|
|
87773
|
+
const spanContribution = run33.type === "text" ? run33.text : run33.type === "equation" ? run33.text : "";
|
|
87703
87774
|
for (const commentId of comments) {
|
|
87704
87775
|
if (!spanText.has(commentId))
|
|
87705
87776
|
orderedIds.push(commentId);
|
|
@@ -87719,32 +87790,121 @@ function buildCommentIndex(blocks, options) {
|
|
|
87719
87790
|
}
|
|
87720
87791
|
return { endingsByRun, spanText, orderedIds };
|
|
87721
87792
|
}
|
|
87722
|
-
function runComments(
|
|
87723
|
-
if (
|
|
87724
|
-
return
|
|
87725
|
-
if (
|
|
87726
|
-
return
|
|
87793
|
+
function runComments(run33) {
|
|
87794
|
+
if (run33.type === "text")
|
|
87795
|
+
return run33.comments;
|
|
87796
|
+
if (run33.type === "equation")
|
|
87797
|
+
return run33.comments;
|
|
87727
87798
|
return;
|
|
87728
87799
|
}
|
|
87729
87800
|
function slotKey(paragraphId, runIndex) {
|
|
87730
87801
|
return `${paragraphId}#${runIndex}`;
|
|
87731
87802
|
}
|
|
87732
|
-
function renderBlock(block, ctx) {
|
|
87803
|
+
function renderBlock(block, ctx, blocks, index2) {
|
|
87733
87804
|
if (block.type === "paragraph")
|
|
87734
87805
|
return renderParagraph(block, ctx);
|
|
87735
87806
|
if (block.type === "table")
|
|
87736
87807
|
return renderTable(block, ctx);
|
|
87737
|
-
if (block.type === "sectionBreak")
|
|
87738
|
-
return renderSectionBreak(block);
|
|
87808
|
+
if (block.type === "sectionBreak") {
|
|
87809
|
+
return renderSectionBreak(block, governedRange(blocks, index2));
|
|
87810
|
+
}
|
|
87739
87811
|
return null;
|
|
87740
87812
|
}
|
|
87741
|
-
function
|
|
87813
|
+
function computeGoverningColumns(blocks) {
|
|
87814
|
+
const map3 = new Map;
|
|
87815
|
+
let cols = 1;
|
|
87816
|
+
for (let index2 = blocks.length - 1;index2 >= 0; index2--) {
|
|
87817
|
+
const block = blocks[index2];
|
|
87818
|
+
if (!block)
|
|
87819
|
+
continue;
|
|
87820
|
+
if (block.type === "sectionBreak") {
|
|
87821
|
+
cols = block.columns ?? 1;
|
|
87822
|
+
continue;
|
|
87823
|
+
}
|
|
87824
|
+
map3.set(block.id, cols);
|
|
87825
|
+
}
|
|
87826
|
+
return map3;
|
|
87827
|
+
}
|
|
87828
|
+
function formatWrappingTabSummary(ids) {
|
|
87829
|
+
if (ids.length === 0)
|
|
87830
|
+
return "";
|
|
87831
|
+
const count = `${ids.length} line${ids.length > 1 ? "s" : ""}`;
|
|
87832
|
+
const range = tabCureRange(ids);
|
|
87833
|
+
const fix = range ? `edit FILE --at ${range} --tabs right` : ids.map((id) => `edit FILE --at ${id} --tabs right`).join(" ; ");
|
|
87834
|
+
return formatNote("layout", [
|
|
87835
|
+
["wrap", count],
|
|
87836
|
+
[
|
|
87837
|
+
"warn",
|
|
87838
|
+
"tab-aligned content (e.g. dates/locations) overflows the right margin and WRAPS in render until cured"
|
|
87839
|
+
],
|
|
87840
|
+
["fix-all", fix]
|
|
87841
|
+
], ids);
|
|
87842
|
+
}
|
|
87843
|
+
function tabCureRange(ids) {
|
|
87844
|
+
const nums = ids.map((id) => /^p(\d+)$/.exec(id)?.[1]).filter((value) => value !== undefined).map(Number);
|
|
87845
|
+
if (nums.length === 0)
|
|
87846
|
+
return null;
|
|
87847
|
+
const min = Math.min(...nums);
|
|
87848
|
+
const max = Math.max(...nums);
|
|
87849
|
+
return min === max ? `p${min}` : `p${min}-p${max}`;
|
|
87850
|
+
}
|
|
87851
|
+
function layoutHazardNote(paragraph2, ctx) {
|
|
87852
|
+
if (!paragraph2.runs.some((run33) => run33.type === "tab"))
|
|
87853
|
+
return "";
|
|
87854
|
+
const cols = ctx.governingColumns.get(paragraph2.id) ?? 1;
|
|
87855
|
+
if (cols > 1) {
|
|
87856
|
+
return ` ${formatNote("layout", [
|
|
87857
|
+
["cols", cols],
|
|
87858
|
+
[
|
|
87859
|
+
"warn",
|
|
87860
|
+
`tab alignment can wrap mid-line in this ${cols}-column section; render to verify`
|
|
87861
|
+
]
|
|
87862
|
+
], [paragraph2.id])}`;
|
|
87863
|
+
}
|
|
87864
|
+
const tabs = paragraph2.tabStops ?? [];
|
|
87865
|
+
if (tabs.some((tab) => tab.align === "right"))
|
|
87866
|
+
return "";
|
|
87867
|
+
const textWidthTwips = Math.round(ctx.contentWidthEmu / EMU_PER_TWIP2);
|
|
87868
|
+
const fragile = tabs.find((tab) => (tab.align === "left" || tab.align === "center" || tab.align === "") && tab.pos > textWidthTwips * 0.7);
|
|
87869
|
+
if (!fragile)
|
|
87870
|
+
return "";
|
|
87871
|
+
ctx.wrappingTabLines.push(paragraph2.id);
|
|
87872
|
+
const gapIn = twipsToInches(Math.max(0, textWidthTwips - fragile.pos));
|
|
87873
|
+
return ` ${formatNote("layout", [
|
|
87874
|
+
["tab", `${fragile.align || "left"}@${twipsToInches(fragile.pos)}in`],
|
|
87875
|
+
[
|
|
87876
|
+
"warn",
|
|
87877
|
+
`right content on a LEFT tab ~${gapIn}in from the margin \u2014 wraps when longer (cure: --tabs right; see the docx:layout fix-all at top)`
|
|
87878
|
+
]
|
|
87879
|
+
], [paragraph2.id])}`;
|
|
87880
|
+
}
|
|
87881
|
+
function governedRange(blocks, index2) {
|
|
87882
|
+
let first;
|
|
87883
|
+
let last;
|
|
87884
|
+
for (let cursor = index2 - 1;cursor >= 0; cursor--) {
|
|
87885
|
+
const block = blocks[cursor];
|
|
87886
|
+
if (!block)
|
|
87887
|
+
continue;
|
|
87888
|
+
if (block.type === "sectionBreak")
|
|
87889
|
+
break;
|
|
87890
|
+
first = block.id;
|
|
87891
|
+
if (last === undefined)
|
|
87892
|
+
last = block.id;
|
|
87893
|
+
}
|
|
87894
|
+
if (!first || !last)
|
|
87895
|
+
return;
|
|
87896
|
+
return first === last ? first : `${first}..${last}`;
|
|
87897
|
+
}
|
|
87898
|
+
function renderSectionBreak(block, governs) {
|
|
87742
87899
|
const pairs = [];
|
|
87743
87900
|
if (block.columns !== undefined && block.columns > 1) {
|
|
87744
87901
|
pairs.push(["cols", block.columns]);
|
|
87745
87902
|
}
|
|
87746
87903
|
if (block.sectionType !== undefined)
|
|
87747
87904
|
pairs.push(["type", block.sectionType]);
|
|
87905
|
+
if (governs !== undefined && pairs.length > 0) {
|
|
87906
|
+
pairs.push(["applies-to", `${governs} (above)`]);
|
|
87907
|
+
}
|
|
87748
87908
|
return formatNote("section", pairs, [block.id]);
|
|
87749
87909
|
}
|
|
87750
87910
|
function contentWidthEmu(geometry) {
|
|
@@ -87755,25 +87915,25 @@ function contentWidthEmu(geometry) {
|
|
|
87755
87915
|
const fallback = (DEFAULT_PAGE.width - 2 * DEFAULT_PAGE.margin) * EMU_PER_TWIP2;
|
|
87756
87916
|
return contentTwips > 0 ? contentTwips * EMU_PER_TWIP2 : fallback;
|
|
87757
87917
|
}
|
|
87758
|
-
function formatImageNote(
|
|
87918
|
+
function formatImageNote(run33, contentEmu) {
|
|
87759
87919
|
const pairs = [];
|
|
87760
|
-
if (
|
|
87920
|
+
if (run33.widthEmu && run33.heightEmu) {
|
|
87761
87921
|
pairs.push([
|
|
87762
87922
|
"size",
|
|
87763
|
-
`${emuToInches(
|
|
87923
|
+
`${emuToInches(run33.widthEmu)}x${emuToInches(run33.heightEmu)}in`
|
|
87764
87924
|
]);
|
|
87765
87925
|
}
|
|
87766
|
-
if (
|
|
87926
|
+
if (run33.floating)
|
|
87767
87927
|
pairs.push(["float", "yes"]);
|
|
87768
|
-
if (
|
|
87769
|
-
pairs.push(["wrap",
|
|
87770
|
-
if (
|
|
87771
|
-
pairs.push(["align",
|
|
87772
|
-
if (
|
|
87928
|
+
if (run33.wrap)
|
|
87929
|
+
pairs.push(["wrap", run33.wrap]);
|
|
87930
|
+
if (run33.align)
|
|
87931
|
+
pairs.push(["align", run33.align]);
|
|
87932
|
+
if (run33.widthEmu && run33.widthEmu > contentEmu)
|
|
87773
87933
|
pairs.push(["overflow", "yes"]);
|
|
87774
87934
|
if (pairs.length === 0)
|
|
87775
87935
|
return "";
|
|
87776
|
-
return ` ${formatNote("image", pairs, [
|
|
87936
|
+
return ` ${formatNote("image", pairs, [run33.id])}`;
|
|
87777
87937
|
}
|
|
87778
87938
|
function documentGeometry(blocks) {
|
|
87779
87939
|
for (let index2 = blocks.length - 1;index2 >= 0; index2--) {
|
|
@@ -87825,14 +87985,14 @@ function isCodeBlockParagraph(block) {
|
|
|
87825
87985
|
function renderCodeBlockGroup(paragraphs, ctx) {
|
|
87826
87986
|
if (ctx.options.view !== "baseline" && ctx.options.view !== "accepted") {
|
|
87827
87987
|
for (const paragraph2 of paragraphs) {
|
|
87828
|
-
for (const
|
|
87829
|
-
if (
|
|
87830
|
-
ctx.referencedTrackedChanges.set(
|
|
87988
|
+
for (const run33 of paragraph2.runs) {
|
|
87989
|
+
if (run33.type === "text" && run33.trackedChange) {
|
|
87990
|
+
ctx.referencedTrackedChanges.set(run33.trackedChange.id, run33.trackedChange);
|
|
87831
87991
|
}
|
|
87832
87992
|
}
|
|
87833
87993
|
}
|
|
87834
87994
|
}
|
|
87835
|
-
const lines = paragraphs.map((paragraph2) => paragraph2.runs.filter((
|
|
87995
|
+
const lines = paragraphs.map((paragraph2) => paragraph2.runs.filter((run33) => run33.type === "text" && typeof run33.text === "string").map((run33) => run33.text).join(""));
|
|
87836
87996
|
const firstId = paragraphs[0]?.id ?? "";
|
|
87837
87997
|
const lastId = paragraphs[paragraphs.length - 1]?.id ?? firstId;
|
|
87838
87998
|
const language = codeBlockLanguageFromStyleId(paragraphs[0]?.style) ?? "";
|
|
@@ -87852,7 +88012,7 @@ function renderParagraph(paragraph2, ctx) {
|
|
|
87852
88012
|
const body = rendered.replace(/[ \t]+$/, "");
|
|
87853
88013
|
const separator = isDisplayEquationOnly(body) ? `
|
|
87854
88014
|
` : " ";
|
|
87855
|
-
return `${prefix}${body}${separator}<!-- ${paragraph2.id} -->${formatParagraphNote(paragraph2)}`;
|
|
88015
|
+
return `${prefix}${body}${separator}<!-- ${paragraph2.id} -->${formatParagraphNote(paragraph2)}${layoutHazardNote(paragraph2, ctx)}`;
|
|
87856
88016
|
}
|
|
87857
88017
|
function formatParagraphNote(paragraph2) {
|
|
87858
88018
|
const pairs = [];
|
|
@@ -87925,10 +88085,10 @@ function headingLevelFor(style) {
|
|
|
87925
88085
|
function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
|
|
87926
88086
|
const view = ctx.options.view ?? "accepted";
|
|
87927
88087
|
const visibleEntries = [];
|
|
87928
|
-
runs.forEach((
|
|
87929
|
-
if (
|
|
88088
|
+
runs.forEach((run33, index2) => {
|
|
88089
|
+
if (run33.type === "text" && !isRunVisible(run33, view))
|
|
87930
88090
|
return;
|
|
87931
|
-
visibleEntries.push({ run:
|
|
88091
|
+
visibleEntries.push({ run: run33, originalIndex: index2 });
|
|
87932
88092
|
});
|
|
87933
88093
|
let out = "";
|
|
87934
88094
|
let cursor = 0;
|
|
@@ -87939,14 +88099,14 @@ function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
|
|
|
87939
88099
|
cursor++;
|
|
87940
88100
|
continue;
|
|
87941
88101
|
}
|
|
87942
|
-
const { run:
|
|
87943
|
-
if (
|
|
88102
|
+
const { run: run33 } = entry;
|
|
88103
|
+
if (run33.type === "text") {
|
|
87944
88104
|
let lookahead2 = cursor + 1;
|
|
87945
88105
|
while (lookahead2 < visibleEntries.length) {
|
|
87946
88106
|
const next = visibleEntries[lookahead2];
|
|
87947
88107
|
if (!next || next.run.type !== "text")
|
|
87948
88108
|
break;
|
|
87949
|
-
if (!sameDecoration(
|
|
88109
|
+
if (!sameDecoration(run33, next.run))
|
|
87950
88110
|
break;
|
|
87951
88111
|
lookahead2++;
|
|
87952
88112
|
}
|
|
@@ -87967,29 +88127,29 @@ function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
|
|
|
87967
88127
|
cursor = lookahead2;
|
|
87968
88128
|
continue;
|
|
87969
88129
|
}
|
|
87970
|
-
if (
|
|
87971
|
-
const alt = sanitizeAltText(
|
|
87972
|
-
const extension2 = extensionForImageMime(
|
|
87973
|
-
out += ` {
|
|
88131
|
+
const alt = sanitizeAltText(run33.alt ?? run33.id);
|
|
88132
|
+
const extension2 = extensionForImageMime(run33.contentType) ?? "bin";
|
|
88133
|
+
out += ``;
|
|
88134
|
+
out += formatImageNote(run33, ctx.contentWidthEmu);
|
|
88135
|
+
} else if (run33.type === "break") {
|
|
88136
|
+
if (run33.kind === "line")
|
|
87977
88137
|
out += `
|
|
87978
88138
|
`;
|
|
87979
|
-
} else if (
|
|
88139
|
+
} else if (run33.type === "tab") {
|
|
87980
88140
|
out += "\t";
|
|
87981
|
-
} else if (
|
|
87982
|
-
const body =
|
|
87983
|
-
out +=
|
|
88141
|
+
} else if (run33.type === "equation") {
|
|
88142
|
+
const body = run33.latex.length > 0 ? run33.latex : run33.text;
|
|
88143
|
+
out += run33.display ? `$$${body}$$` : `$${body}$`;
|
|
87984
88144
|
out += commentEndingsFor(paragraphId, [{ originalIndex: cursor }], ctx.commentIndex);
|
|
87985
|
-
} else if (
|
|
87986
|
-
if (
|
|
87987
|
-
ctx.referencedFootnoteIds.add(
|
|
88145
|
+
} else if (run33.type === "noteRef") {
|
|
88146
|
+
if (run33.kind === "footnote")
|
|
88147
|
+
ctx.referencedFootnoteIds.add(run33.id);
|
|
87988
88148
|
else
|
|
87989
|
-
ctx.referencedEndnoteIds.add(
|
|
87990
|
-
out += `[^${
|
|
87991
|
-
} else if (
|
|
87992
|
-
out += `\`[${
|
|
88149
|
+
ctx.referencedEndnoteIds.add(run33.id);
|
|
88150
|
+
out += `[^${run33.id}]`;
|
|
88151
|
+
} else if (run33.type === "chart") {
|
|
88152
|
+
out += `\`[${run33.kind}]\``;
|
|
87993
88153
|
}
|
|
87994
88154
|
cursor++;
|
|
87995
88155
|
}
|
|
@@ -88023,7 +88183,7 @@ function sameCommentSet(left, right) {
|
|
|
88023
88183
|
return true;
|
|
88024
88184
|
}
|
|
88025
88185
|
function renderTextSegment(runs, view, baseline, mask, offset2) {
|
|
88026
|
-
const text6 = runs.map((
|
|
88186
|
+
const text6 = runs.map((run33) => run33.text).join("");
|
|
88027
88187
|
if (text6.length === 0)
|
|
88028
88188
|
return "";
|
|
88029
88189
|
const first = runs[0];
|
|
@@ -88067,33 +88227,33 @@ function criticMarkerFor(kind) {
|
|
|
88067
88227
|
return "++";
|
|
88068
88228
|
return "--";
|
|
88069
88229
|
}
|
|
88070
|
-
function needsHtmlWrap(
|
|
88071
|
-
return Boolean(
|
|
88230
|
+
function needsHtmlWrap(run33, baseline) {
|
|
88231
|
+
return Boolean(run33.color && !isDefaultColor(run33.color) || run33.colorTheme && !isDefaultThemeColor(run33) || run33.shade || run33.font && run33.font !== baseline.font || run33.sizeHalfPoints !== undefined && run33.sizeHalfPoints !== baseline.sizeHalfPoints || run33.smallCaps || run33.allCaps || run33.underline || run33.vertAlign === "superscript" || run33.vertAlign === "subscript" || run33.highlight);
|
|
88072
88232
|
}
|
|
88073
|
-
function wrapRunFormatting(body,
|
|
88233
|
+
function wrapRunFormatting(body, run33, baseline) {
|
|
88074
88234
|
const styles = [];
|
|
88075
88235
|
const attrs = [];
|
|
88076
|
-
if (
|
|
88077
|
-
styles.push(`color:#${
|
|
88078
|
-
if (
|
|
88079
|
-
styles.push(`background-color:#${
|
|
88080
|
-
if (
|
|
88081
|
-
styles.push(`font-family:${cssFontFamily(
|
|
88236
|
+
if (run33.color && !isDefaultColor(run33.color))
|
|
88237
|
+
styles.push(`color:#${run33.color}`);
|
|
88238
|
+
if (run33.shade)
|
|
88239
|
+
styles.push(`background-color:#${run33.shade}`);
|
|
88240
|
+
if (run33.font && run33.font !== baseline.font) {
|
|
88241
|
+
styles.push(`font-family:${cssFontFamily(run33.font)}`);
|
|
88082
88242
|
}
|
|
88083
|
-
if (
|
|
88084
|
-
styles.push(`font-size:${
|
|
88243
|
+
if (run33.sizeHalfPoints !== undefined && run33.sizeHalfPoints !== baseline.sizeHalfPoints) {
|
|
88244
|
+
styles.push(`font-size:${run33.sizeHalfPoints / 2}pt`);
|
|
88085
88245
|
}
|
|
88086
|
-
if (
|
|
88246
|
+
if (run33.smallCaps)
|
|
88087
88247
|
styles.push("font-variant:small-caps");
|
|
88088
|
-
if (
|
|
88248
|
+
if (run33.allCaps)
|
|
88089
88249
|
styles.push("text-transform:uppercase");
|
|
88090
|
-
if (
|
|
88091
|
-
attrs.push(htmlAttr("data-color-theme",
|
|
88092
|
-
if (
|
|
88093
|
-
attrs.push(htmlAttr("data-color-theme-tint",
|
|
88250
|
+
if (run33.colorTheme && !isDefaultThemeColor(run33)) {
|
|
88251
|
+
attrs.push(htmlAttr("data-color-theme", run33.colorTheme));
|
|
88252
|
+
if (run33.colorThemeTint) {
|
|
88253
|
+
attrs.push(htmlAttr("data-color-theme-tint", run33.colorThemeTint));
|
|
88094
88254
|
}
|
|
88095
|
-
if (
|
|
88096
|
-
attrs.push(htmlAttr("data-color-theme-shade",
|
|
88255
|
+
if (run33.colorThemeShade) {
|
|
88256
|
+
attrs.push(htmlAttr("data-color-theme-shade", run33.colorThemeShade));
|
|
88097
88257
|
}
|
|
88098
88258
|
}
|
|
88099
88259
|
let out = body;
|
|
@@ -88102,18 +88262,18 @@ function wrapRunFormatting(body, run34, baseline) {
|
|
|
88102
88262
|
const attrPart = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
88103
88263
|
out = `<span${stylePart}${attrPart}>${out}</span>`;
|
|
88104
88264
|
}
|
|
88105
|
-
if (
|
|
88265
|
+
if (run33.underline === "single") {
|
|
88106
88266
|
out = `<u>${out}</u>`;
|
|
88107
|
-
} else if (
|
|
88108
|
-
const color2 =
|
|
88109
|
-
out = `<u ${htmlAttr("data-underline",
|
|
88267
|
+
} else if (run33.underline) {
|
|
88268
|
+
const color2 = run33.underlineColor ? ` ${htmlAttr("data-underline-color", run33.underlineColor)}` : "";
|
|
88269
|
+
out = `<u ${htmlAttr("data-underline", run33.underline)}${color2}>${out}</u>`;
|
|
88110
88270
|
}
|
|
88111
|
-
if (
|
|
88271
|
+
if (run33.vertAlign === "superscript")
|
|
88112
88272
|
out = `<sup>${out}</sup>`;
|
|
88113
|
-
else if (
|
|
88273
|
+
else if (run33.vertAlign === "subscript")
|
|
88114
88274
|
out = `<sub>${out}</sub>`;
|
|
88115
|
-
if (
|
|
88116
|
-
const named =
|
|
88275
|
+
if (run33.highlight) {
|
|
88276
|
+
const named = run33.highlight === "yellow" ? "" : ` ${htmlAttr("data-highlight", run33.highlight)}`;
|
|
88117
88277
|
out = `<mark${named}>${out}</mark>`;
|
|
88118
88278
|
}
|
|
88119
88279
|
return out;
|
|
@@ -88122,8 +88282,8 @@ function isDefaultColor(color2) {
|
|
|
88122
88282
|
const normalized = color2.toLowerCase();
|
|
88123
88283
|
return normalized === "000000" || normalized === "auto";
|
|
88124
88284
|
}
|
|
88125
|
-
function isDefaultThemeColor(
|
|
88126
|
-
return (
|
|
88285
|
+
function isDefaultThemeColor(run33) {
|
|
88286
|
+
return (run33.colorTheme === "text1" || run33.colorTheme === "dark1") && !run33.colorThemeTint && !run33.colorThemeShade;
|
|
88127
88287
|
}
|
|
88128
88288
|
function cssFontFamily(font) {
|
|
88129
88289
|
return /\s/.test(font) ? `'${font}'` : font;
|
|
@@ -88140,19 +88300,19 @@ function applyEscapeMask(text6, mask, offset2) {
|
|
|
88140
88300
|
}
|
|
88141
88301
|
function paragraphContent(runs, view) {
|
|
88142
88302
|
let content3 = "";
|
|
88143
|
-
for (const
|
|
88144
|
-
if (
|
|
88303
|
+
for (const run33 of runs) {
|
|
88304
|
+
if (run33.type !== "text")
|
|
88145
88305
|
continue;
|
|
88146
|
-
if (
|
|
88306
|
+
if (run33.runStyle === "Code")
|
|
88147
88307
|
continue;
|
|
88148
|
-
if (!isRunVisible(
|
|
88308
|
+
if (!isRunVisible(run33, view))
|
|
88149
88309
|
continue;
|
|
88150
|
-
content3 +=
|
|
88310
|
+
content3 += run33.text;
|
|
88151
88311
|
}
|
|
88152
88312
|
return content3;
|
|
88153
88313
|
}
|
|
88154
88314
|
function hasEquationRun(runs) {
|
|
88155
|
-
return runs.some((
|
|
88315
|
+
return runs.some((run33) => run33.type === "equation");
|
|
88156
88316
|
}
|
|
88157
88317
|
function renderTable(table, ctx) {
|
|
88158
88318
|
const view = ctx.options.view ?? "accepted";
|
|
@@ -88438,9 +88598,9 @@ var init_markdown3 = __esm(() => {
|
|
|
88438
88598
|
// src/cli/read/index.ts
|
|
88439
88599
|
var exports_read = {};
|
|
88440
88600
|
__export(exports_read, {
|
|
88441
|
-
run: () =>
|
|
88601
|
+
run: () => run33
|
|
88442
88602
|
});
|
|
88443
|
-
async function
|
|
88603
|
+
async function run33(args) {
|
|
88444
88604
|
const parsed = await tryParseArgs(args, {
|
|
88445
88605
|
ast: { type: "boolean" },
|
|
88446
88606
|
from: { type: "string" },
|
|
@@ -88450,16 +88610,16 @@ async function run34(args) {
|
|
|
88450
88610
|
current: { type: "boolean" },
|
|
88451
88611
|
comments: { type: "boolean" },
|
|
88452
88612
|
help: { type: "boolean", short: "h" }
|
|
88453
|
-
},
|
|
88613
|
+
}, HELP29);
|
|
88454
88614
|
if (typeof parsed === "number")
|
|
88455
88615
|
return parsed;
|
|
88456
88616
|
if (parsed.values.help) {
|
|
88457
|
-
await writeStdout(
|
|
88617
|
+
await writeStdout(HELP29);
|
|
88458
88618
|
return EXIT2.OK;
|
|
88459
88619
|
}
|
|
88460
88620
|
const path2 = parsed.positionals[0];
|
|
88461
88621
|
if (!path2)
|
|
88462
|
-
return fail("USAGE", "Missing FILE argument",
|
|
88622
|
+
return fail("USAGE", "Missing FILE argument", HELP29);
|
|
88463
88623
|
const ast = Boolean(parsed.values.ast);
|
|
88464
88624
|
const from = parsed.values.from;
|
|
88465
88625
|
const to = parsed.values.to;
|
|
@@ -88468,11 +88628,11 @@ async function run34(args) {
|
|
|
88468
88628
|
const current = Boolean(parsed.values.current);
|
|
88469
88629
|
const showComments = Boolean(parsed.values.comments);
|
|
88470
88630
|
if (ast && (from || to || accepted || baseline || current || showComments)) {
|
|
88471
|
-
return fail("USAGE", "--from, --to, --accepted, --baseline, --current, and --comments are Markdown-only and cannot be combined with --ast",
|
|
88631
|
+
return fail("USAGE", "--from, --to, --accepted, --baseline, --current, and --comments are Markdown-only and cannot be combined with --ast", HELP29);
|
|
88472
88632
|
}
|
|
88473
88633
|
const view = resolveView({ accepted, baseline, current });
|
|
88474
88634
|
if (!view) {
|
|
88475
|
-
return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive",
|
|
88635
|
+
return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive", HELP29);
|
|
88476
88636
|
}
|
|
88477
88637
|
const docView = await openOrFail(path2);
|
|
88478
88638
|
if (typeof docView === "number")
|
|
@@ -88488,7 +88648,8 @@ async function run34(args) {
|
|
|
88488
88648
|
to,
|
|
88489
88649
|
view,
|
|
88490
88650
|
showComments,
|
|
88491
|
-
defaultSizeHalfPoints: docView.styles?.defaultSizeHalfPoints()
|
|
88651
|
+
defaultSizeHalfPoints: docView.styles?.defaultSizeHalfPoints(),
|
|
88652
|
+
trackChangesOn: docView.isTrackChangesEnabled()
|
|
88492
88653
|
});
|
|
88493
88654
|
await writeStdout(rendered);
|
|
88494
88655
|
return EXIT2.OK;
|
|
@@ -88499,7 +88660,7 @@ async function run34(args) {
|
|
|
88499
88660
|
throw err;
|
|
88500
88661
|
}
|
|
88501
88662
|
}
|
|
88502
|
-
var
|
|
88663
|
+
var HELP29 = `docx read \u2014 render document body as Markdown, or print AST as JSON
|
|
88503
88664
|
|
|
88504
88665
|
Usage:
|
|
88505
88666
|
docx read FILE [options]
|
|
@@ -88589,20 +88750,20 @@ function parsePagesSpec(spec) {
|
|
|
88589
88750
|
// src/cli/render/index.ts
|
|
88590
88751
|
var exports_render = {};
|
|
88591
88752
|
__export(exports_render, {
|
|
88592
|
-
run: () =>
|
|
88753
|
+
run: () => run34
|
|
88593
88754
|
});
|
|
88594
88755
|
import { basename as basename2, extname as extname2, resolve as resolve2 } from "path";
|
|
88595
|
-
async function
|
|
88596
|
-
const parsed = await tryParseArgs(args,
|
|
88756
|
+
async function run34(args) {
|
|
88757
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC4, HELP30);
|
|
88597
88758
|
if (typeof parsed === "number")
|
|
88598
88759
|
return parsed;
|
|
88599
88760
|
if (parsed.values.help) {
|
|
88600
|
-
await writeStdout(
|
|
88761
|
+
await writeStdout(HELP30);
|
|
88601
88762
|
return EXIT2.OK;
|
|
88602
88763
|
}
|
|
88603
88764
|
const filePath = parsed.positionals[0];
|
|
88604
88765
|
if (!filePath)
|
|
88605
|
-
return fail("USAGE", "Missing FILE argument",
|
|
88766
|
+
return fail("USAGE", "Missing FILE argument", HELP30);
|
|
88606
88767
|
if (!await Bun.file(filePath).exists()) {
|
|
88607
88768
|
return fail("FILE_NOT_FOUND", `File not found: ${filePath}`);
|
|
88608
88769
|
}
|
|
@@ -88682,7 +88843,7 @@ function availabilityHint(installed) {
|
|
|
88682
88843
|
}
|
|
88683
88844
|
return `Detected engines: ${installed.join(", ")} \u2014 but none chose auto-select; pass --engine explicitly.`;
|
|
88684
88845
|
}
|
|
88685
|
-
var
|
|
88846
|
+
var HELP30 = `docx render \u2014 render each page of a .docx as a PNG/JPG image
|
|
88686
88847
|
|
|
88687
88848
|
Usage:
|
|
88688
88849
|
docx render FILE [options]
|
|
@@ -88734,11 +88895,11 @@ Runtime dependencies:
|
|
|
88734
88895
|
\u2014 no extra system tools (poppler / pdftoppm / ImageMagick) required.
|
|
88735
88896
|
|
|
88736
88897
|
Run "docx render --help" or "docx --help" for the full command list.
|
|
88737
|
-
`,
|
|
88898
|
+
`, OPTION_SPEC4;
|
|
88738
88899
|
var init_render2 = __esm(() => {
|
|
88739
88900
|
init_core2();
|
|
88740
88901
|
init_respond();
|
|
88741
|
-
|
|
88902
|
+
OPTION_SPEC4 = {
|
|
88742
88903
|
out: { type: "string" },
|
|
88743
88904
|
engine: { type: "string" },
|
|
88744
88905
|
dpi: { type: "string" },
|
|
@@ -88899,9 +89060,9 @@ var init_batch4 = __esm(() => {
|
|
|
88899
89060
|
// src/cli/replace/index.ts
|
|
88900
89061
|
var exports_replace3 = {};
|
|
88901
89062
|
__export(exports_replace3, {
|
|
88902
|
-
run: () =>
|
|
89063
|
+
run: () => run35
|
|
88903
89064
|
});
|
|
88904
|
-
async function
|
|
89065
|
+
async function run35(args) {
|
|
88905
89066
|
const parsed = await tryParseArgs(args, {
|
|
88906
89067
|
batch: { type: "string" },
|
|
88907
89068
|
regex: { type: "boolean" },
|
|
@@ -88914,30 +89075,30 @@ async function run36(args) {
|
|
|
88914
89075
|
baseline: { type: "boolean" },
|
|
88915
89076
|
exact: { type: "boolean" },
|
|
88916
89077
|
...SAVE_FLAGS
|
|
88917
|
-
},
|
|
89078
|
+
}, HELP31);
|
|
88918
89079
|
if (typeof parsed === "number")
|
|
88919
89080
|
return parsed;
|
|
88920
89081
|
if (parsed.values.help) {
|
|
88921
|
-
await writeStdout(
|
|
89082
|
+
await writeStdout(HELP31);
|
|
88922
89083
|
return EXIT2.OK;
|
|
88923
89084
|
}
|
|
88924
89085
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
88925
89086
|
const path2 = parsed.positionals[0];
|
|
88926
89087
|
if (!path2)
|
|
88927
|
-
return fail("USAGE", "Missing FILE argument",
|
|
89088
|
+
return fail("USAGE", "Missing FILE argument", HELP31);
|
|
88928
89089
|
const batchInput = parsed.values.batch;
|
|
88929
89090
|
if (batchInput !== undefined) {
|
|
88930
89091
|
if (parsed.positionals.length > 1) {
|
|
88931
|
-
return fail("USAGE", "--batch reads pattern/replacement from the JSONL file; don't also pass them as positionals",
|
|
89092
|
+
return fail("USAGE", "--batch reads pattern/replacement from the JSONL file; don't also pass them as positionals", HELP31);
|
|
88932
89093
|
}
|
|
88933
89094
|
return runReplaceBatch(path2, batchInput, parsed.values);
|
|
88934
89095
|
}
|
|
88935
89096
|
const pattern = parsed.positionals[1];
|
|
88936
89097
|
const replacement = parsed.positionals[2];
|
|
88937
89098
|
if (pattern == null)
|
|
88938
|
-
return fail("USAGE", "Missing PATTERN argument",
|
|
89099
|
+
return fail("USAGE", "Missing PATTERN argument", HELP31);
|
|
88939
89100
|
if (replacement == null) {
|
|
88940
|
-
return fail("USAGE", "Missing REPLACEMENT argument",
|
|
89101
|
+
return fail("USAGE", "Missing REPLACEMENT argument", HELP31);
|
|
88941
89102
|
}
|
|
88942
89103
|
const ignoreCase = Boolean(parsed.values["ignore-case"]);
|
|
88943
89104
|
const useRegex = Boolean(parsed.values.regex);
|
|
@@ -89041,6 +89202,8 @@ async function run36(args) {
|
|
|
89041
89202
|
replaceSpanInParagraph(blockRef.node, { start: match.start, end: match.end }, concreteReplacement, tracked, findView);
|
|
89042
89203
|
}
|
|
89043
89204
|
await document4.save(outputPath);
|
|
89205
|
+
const remaining = allMatches.length - selected.length;
|
|
89206
|
+
const partialHint = remaining > 0 ? `\u21B3 ${remaining} more match${remaining === 1 ? "" : "es"} left unreplaced (${selected.length} of ${allMatches.length} done) \u2014 pass --all to replace every match, or --limit N for a specific count.` : undefined;
|
|
89044
89207
|
await respondAck({
|
|
89045
89208
|
ok: true,
|
|
89046
89209
|
operation: "replace",
|
|
@@ -89054,10 +89217,10 @@ async function run36(args) {
|
|
|
89054
89217
|
replaced: selected.length,
|
|
89055
89218
|
matches: matchesPayload,
|
|
89056
89219
|
...normalizationFields
|
|
89057
|
-
});
|
|
89220
|
+
}, partialHint);
|
|
89058
89221
|
return EXIT2.OK;
|
|
89059
89222
|
}
|
|
89060
|
-
var
|
|
89223
|
+
var HELP31 = `docx replace \u2014 substitute text spans (sed for docx)
|
|
89061
89224
|
|
|
89062
89225
|
Usage:
|
|
89063
89226
|
docx replace FILE PATTERN REPLACEMENT [options]
|
|
@@ -89135,6 +89298,258 @@ var init_replace4 = __esm(() => {
|
|
|
89135
89298
|
init_batch4();
|
|
89136
89299
|
});
|
|
89137
89300
|
|
|
89301
|
+
// src/cli/sections/index.tsx
|
|
89302
|
+
var exports_sections = {};
|
|
89303
|
+
__export(exports_sections, {
|
|
89304
|
+
run: () => run36
|
|
89305
|
+
});
|
|
89306
|
+
async function run36(args) {
|
|
89307
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC5, HELP32);
|
|
89308
|
+
if (typeof parsed === "number")
|
|
89309
|
+
return parsed;
|
|
89310
|
+
if (parsed.values.help) {
|
|
89311
|
+
await writeStdout(HELP32);
|
|
89312
|
+
return EXIT2.OK;
|
|
89313
|
+
}
|
|
89314
|
+
setVerboseAck(Boolean(parsed.values.verbose));
|
|
89315
|
+
const filePath = parsed.positionals[0];
|
|
89316
|
+
if (!filePath)
|
|
89317
|
+
return fail("USAGE", "Missing FILE argument", HELP32);
|
|
89318
|
+
const at = parsed.values.at;
|
|
89319
|
+
if (!at) {
|
|
89320
|
+
return fail("USAGE", "Missing --at LOCATOR (a range pN-pM or a section sN)", HELP32);
|
|
89321
|
+
}
|
|
89322
|
+
const count = parseCount(parsed.values.columns);
|
|
89323
|
+
if (typeof count === "number" && Number.isNaN(count)) {
|
|
89324
|
+
return fail("USAGE", `--columns must be a positive integer`, HELP32);
|
|
89325
|
+
}
|
|
89326
|
+
if (count === undefined)
|
|
89327
|
+
return fail("USAGE", "Missing --columns N", HELP32);
|
|
89328
|
+
const typeRaw = parsed.values.type;
|
|
89329
|
+
if (typeRaw !== undefined && !isSectionType(typeRaw)) {
|
|
89330
|
+
return fail("USAGE", `Invalid --type: ${typeRaw}`, "Valid values: continuous, nextPage, evenPage, oddPage, nextColumn");
|
|
89331
|
+
}
|
|
89332
|
+
let locator;
|
|
89333
|
+
try {
|
|
89334
|
+
locator = parseLocator(at);
|
|
89335
|
+
} catch (error) {
|
|
89336
|
+
if (error instanceof LocatorParseError) {
|
|
89337
|
+
return fail("INVALID_LOCATOR", error.message, HELP32);
|
|
89338
|
+
}
|
|
89339
|
+
throw error;
|
|
89340
|
+
}
|
|
89341
|
+
const document4 = await openOrFail(filePath);
|
|
89342
|
+
if (typeof document4 === "number")
|
|
89343
|
+
return document4;
|
|
89344
|
+
const opts = {
|
|
89345
|
+
filePath,
|
|
89346
|
+
count,
|
|
89347
|
+
sectionType: typeRaw,
|
|
89348
|
+
authorFlag: parsed.values.author,
|
|
89349
|
+
trackFlag: Boolean(parsed.values.track),
|
|
89350
|
+
outputPath: parsed.values.output,
|
|
89351
|
+
dryRun: Boolean(parsed.values["dry-run"])
|
|
89352
|
+
};
|
|
89353
|
+
if (locator.kind === "blockRange") {
|
|
89354
|
+
const range = await resolveBlockRangeOrFail(document4, at);
|
|
89355
|
+
if (typeof range === "number")
|
|
89356
|
+
return range;
|
|
89357
|
+
return wrapRange(document4, range.parent, range.startIndex, range.endIndex, at, opts);
|
|
89358
|
+
}
|
|
89359
|
+
const blockRef = await resolveBlockOrFail(document4, at);
|
|
89360
|
+
if (typeof blockRef === "number")
|
|
89361
|
+
return blockRef;
|
|
89362
|
+
if (blockRef.node.tag === "w:sectPr") {
|
|
89363
|
+
return editSection(document4, blockRef, at, opts);
|
|
89364
|
+
}
|
|
89365
|
+
if (blockRef.node.tag === "w:p") {
|
|
89366
|
+
const index2 = blockRef.parent.indexOf(blockRef.node);
|
|
89367
|
+
return wrapRange(document4, blockRef.parent, index2, index2, at, opts);
|
|
89368
|
+
}
|
|
89369
|
+
return fail("INVALID_LOCATOR", `columns needs a section (sN) or a paragraph range (pN-pM); ${at} is neither`, HELP32);
|
|
89370
|
+
}
|
|
89371
|
+
async function editSection(document4, blockRef, at, opts) {
|
|
89372
|
+
try {
|
|
89373
|
+
new Edit(document4).section(blockRef, { columns: opts.count, sectionType: opts.sectionType }, { authorFlag: opts.authorFlag, track: opts.trackFlag });
|
|
89374
|
+
} catch (error) {
|
|
89375
|
+
if (error instanceof EditError)
|
|
89376
|
+
return fail(error.code, error.message);
|
|
89377
|
+
throw error;
|
|
89378
|
+
}
|
|
89379
|
+
return commit(document4, opts, { at, mode: "section" });
|
|
89380
|
+
}
|
|
89381
|
+
async function wrapRange(document4, parent, startIndex, endIndex, at, opts) {
|
|
89382
|
+
if (parent !== document4.body.findBodyChildren()) {
|
|
89383
|
+
return fail("USAGE", `columns can only wrap body-level paragraphs; ${at} is inside a table cell`, "Section breaks carry column layout and cannot live in a table cell.");
|
|
89384
|
+
}
|
|
89385
|
+
for (let index2 = startIndex;index2 <= endIndex; index2++) {
|
|
89386
|
+
if (containsSectionBreak(parent[index2])) {
|
|
89387
|
+
return fail("USAGE", `The range ${at} already contains a section break`, "Target the existing section directly with `--at sN`, or pick a range without one.");
|
|
89388
|
+
}
|
|
89389
|
+
}
|
|
89390
|
+
const governing = governingColumns(parent, endIndex + 1);
|
|
89391
|
+
const track = resolveTracked(document4, opts.trackFlag);
|
|
89392
|
+
const insert = new Insert(document4);
|
|
89393
|
+
const allocator = track ? new TrackChanges(document4).createAllocator() : undefined;
|
|
89394
|
+
const endNode = parent[endIndex];
|
|
89395
|
+
if (!endNode) {
|
|
89396
|
+
return fail("BLOCK_NOT_FOUND", "Range end is stale (parent does not contain it)");
|
|
89397
|
+
}
|
|
89398
|
+
const startNode = startIndex > 0 ? parent[startIndex] : undefined;
|
|
89399
|
+
if (startIndex > 0 && !startNode) {
|
|
89400
|
+
return fail("BLOCK_NOT_FOUND", "Range start is stale (parent does not contain it)");
|
|
89401
|
+
}
|
|
89402
|
+
let afterBlocks;
|
|
89403
|
+
let beforeBlocks = [];
|
|
89404
|
+
try {
|
|
89405
|
+
afterBlocks = await insert.paragraph({ node: endNode, parent }, {
|
|
89406
|
+
kind: "section",
|
|
89407
|
+
columns: opts.count,
|
|
89408
|
+
sectionType: opts.sectionType ?? "continuous"
|
|
89409
|
+
}, {}, { placement: "after", authorFlag: opts.authorFlag, track, allocator });
|
|
89410
|
+
if (startNode) {
|
|
89411
|
+
beforeBlocks = await insert.paragraph({ node: startNode, parent }, {
|
|
89412
|
+
kind: "section",
|
|
89413
|
+
...governing > 1 ? { columns: governing } : {},
|
|
89414
|
+
sectionType: "continuous"
|
|
89415
|
+
}, {}, { placement: "before", authorFlag: opts.authorFlag, track, allocator });
|
|
89416
|
+
}
|
|
89417
|
+
} catch (error) {
|
|
89418
|
+
if (error instanceof InsertError)
|
|
89419
|
+
return fail(error.code, error.message, error.hint);
|
|
89420
|
+
throw error;
|
|
89421
|
+
}
|
|
89422
|
+
if (opts.dryRun) {
|
|
89423
|
+
return commit(document4, opts, { at, mode: "range", dryRunOnly: true });
|
|
89424
|
+
}
|
|
89425
|
+
parent.splice(endIndex + 1, 0, ...afterBlocks);
|
|
89426
|
+
parent.splice(startIndex, 0, ...beforeBlocks);
|
|
89427
|
+
return commit(document4, opts, { at, mode: "range" });
|
|
89428
|
+
}
|
|
89429
|
+
function containsSectionBreak(node2) {
|
|
89430
|
+
if (!node2)
|
|
89431
|
+
return false;
|
|
89432
|
+
if (node2.tag === "w:sectPr")
|
|
89433
|
+
return true;
|
|
89434
|
+
if (node2.tag !== "w:p")
|
|
89435
|
+
return false;
|
|
89436
|
+
return Boolean(node2.findChild("w:pPr")?.findChild("w:sectPr"));
|
|
89437
|
+
}
|
|
89438
|
+
function governingColumns(parent, fromIndex) {
|
|
89439
|
+
for (let index2 = fromIndex;index2 < parent.length; index2++) {
|
|
89440
|
+
const node2 = parent[index2];
|
|
89441
|
+
if (!node2)
|
|
89442
|
+
continue;
|
|
89443
|
+
if (node2.tag === "w:sectPr")
|
|
89444
|
+
return columnsOf(node2);
|
|
89445
|
+
if (node2.tag === "w:p") {
|
|
89446
|
+
const inline = node2.findChild("w:pPr")?.findChild("w:sectPr");
|
|
89447
|
+
if (inline)
|
|
89448
|
+
return columnsOf(inline);
|
|
89449
|
+
}
|
|
89450
|
+
}
|
|
89451
|
+
return 1;
|
|
89452
|
+
}
|
|
89453
|
+
function columnsOf(sectPr) {
|
|
89454
|
+
const raw = sectPr.findChild("w:cols")?.getAttribute("w:num");
|
|
89455
|
+
const parsed = raw ? Number.parseInt(raw, 10) : 1;
|
|
89456
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
|
|
89457
|
+
}
|
|
89458
|
+
function parseCount(raw) {
|
|
89459
|
+
if (raw === undefined)
|
|
89460
|
+
return;
|
|
89461
|
+
if (!/^\d+$/.test(raw.trim()))
|
|
89462
|
+
return Number.NaN;
|
|
89463
|
+
const parsed = Number.parseInt(raw, 10);
|
|
89464
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
89465
|
+
return Number.NaN;
|
|
89466
|
+
return parsed;
|
|
89467
|
+
}
|
|
89468
|
+
async function commit(document4, opts, meta) {
|
|
89469
|
+
if (opts.dryRun || meta.dryRunOnly) {
|
|
89470
|
+
await respond({
|
|
89471
|
+
operation: "sections",
|
|
89472
|
+
dryRun: true,
|
|
89473
|
+
path: opts.filePath,
|
|
89474
|
+
locator: meta.at,
|
|
89475
|
+
columnCount: opts.count,
|
|
89476
|
+
mode: meta.mode,
|
|
89477
|
+
...opts.outputPath ? { output: opts.outputPath } : {}
|
|
89478
|
+
});
|
|
89479
|
+
return EXIT2.OK;
|
|
89480
|
+
}
|
|
89481
|
+
await document4.save(opts.outputPath);
|
|
89482
|
+
const destination = opts.outputPath ?? opts.filePath;
|
|
89483
|
+
await respondAck({
|
|
89484
|
+
ok: true,
|
|
89485
|
+
operation: "sections",
|
|
89486
|
+
path: destination,
|
|
89487
|
+
locator: meta.at,
|
|
89488
|
+
columnCount: opts.count,
|
|
89489
|
+
mode: meta.mode
|
|
89490
|
+
}, renderVerifyHint(destination));
|
|
89491
|
+
return EXIT2.OK;
|
|
89492
|
+
}
|
|
89493
|
+
var HELP32 = `docx sections \u2014 multi-column layout & section breaks
|
|
89494
|
+
|
|
89495
|
+
Usage:
|
|
89496
|
+
docx sections FILE --at LOCATOR --columns N [options]
|
|
89497
|
+
|
|
89498
|
+
The verb for section layout \u2014 multi-column flow and section breaks \u2014 so you
|
|
89499
|
+
don't have to hand-build them with the right OOXML semantics. This is the ONLY
|
|
89500
|
+
way to add/change column layout; \`insert\` no longer takes --section (a raw
|
|
89501
|
+
section break formats the content ABOVE it, which is the classic off-by-one).
|
|
89502
|
+
Two addressing modes:
|
|
89503
|
+
|
|
89504
|
+
--at pN-pM Wrap the paragraph range pN\u2026pM in its own N-column section
|
|
89505
|
+
(inserts the bounding continuous section breaks for you, so the
|
|
89506
|
+
columns land on EXACTLY pN\u2026pM). Also accepts a single paragraph
|
|
89507
|
+
(--at pN). THIS is how you put text in columns \u2014 name the range.
|
|
89508
|
+
--at sN Set the column count on an EXISTING section break sN (the section
|
|
89509
|
+
whose content ENDS at sN). Equivalent to \`edit --at sN --columns N\`.
|
|
89510
|
+
|
|
89511
|
+
Options:
|
|
89512
|
+
--at LOCATOR Paragraph range (pN-pM), single paragraph (pN), or section (sN)
|
|
89513
|
+
--columns N Number of columns (>= 1; use 1 to collapse back to single column)
|
|
89514
|
+
--type T Section type for the wrapping break: continuous (default),
|
|
89515
|
+
nextPage, evenPage, oddPage, nextColumn. Only meaningful with
|
|
89516
|
+
a pN-pM/pN range; with sN it overrides the section's type.
|
|
89517
|
+
--author NAME Author for tracked changes (default: $DOCX_AUTHOR)
|
|
89518
|
+
--track Record as a tracked change even when the doc toggle is off
|
|
89519
|
+
-o, --output PATH Write to PATH instead of overwriting FILE
|
|
89520
|
+
--dry-run Print what would change; do not write the file
|
|
89521
|
+
-v, --verbose Print the full success ack JSON
|
|
89522
|
+
-h, --help Show this help
|
|
89523
|
+
|
|
89524
|
+
Agent tip: VERIFY LAYOUT VISUALLY. \`docx read\` shows the section as a
|
|
89525
|
+
\`<!-- docx:section \u2026 cols="N" -->\` annotation but NOT how the columns actually
|
|
89526
|
+
flow on the page (balance, overflow). After setting columns, render and look:
|
|
89527
|
+
docx render FILE --out pages/
|
|
89528
|
+
Adjust the range and re-render until the columns read the way you intended.
|
|
89529
|
+
|
|
89530
|
+
Output:
|
|
89531
|
+
Prints a one-line confirmation on success (exit 0); --verbose prints {ok:true, \u2026}. Positional ids shift
|
|
89532
|
+
after a range wrap (two section breaks are inserted), so re-read before further
|
|
89533
|
+
edits. Errors print {code, error, hint?} + nonzero exit.
|
|
89534
|
+
|
|
89535
|
+
Examples:
|
|
89536
|
+
docx sections doc.docx --at p4-p9 --columns 2
|
|
89537
|
+
docx sections doc.docx --at p4-p9 --columns 3 --type continuous
|
|
89538
|
+
docx sections doc.docx --at s2 --columns 1 # collapse section s2 to one column
|
|
89539
|
+
`, OPTION_SPEC5;
|
|
89540
|
+
var init_sections2 = __esm(() => {
|
|
89541
|
+
init_core2();
|
|
89542
|
+
init_respond();
|
|
89543
|
+
OPTION_SPEC5 = {
|
|
89544
|
+
at: { type: "string" },
|
|
89545
|
+
columns: { type: "string" },
|
|
89546
|
+
type: { type: "string" },
|
|
89547
|
+
author: { type: "string" },
|
|
89548
|
+
track: { type: "boolean" },
|
|
89549
|
+
...SAVE_FLAGS
|
|
89550
|
+
};
|
|
89551
|
+
});
|
|
89552
|
+
|
|
89138
89553
|
// src/cli/styles/index.ts
|
|
89139
89554
|
var exports_styles = {};
|
|
89140
89555
|
__export(exports_styles, {
|
|
@@ -89366,8 +89781,15 @@ async function run38(args) {
|
|
|
89366
89781
|
return fail("USAGE", `--position must be an integer in 0..${grid.rows.length}`);
|
|
89367
89782
|
}
|
|
89368
89783
|
const cellTexts = parsed.values.cells ? parsed.values.cells.split(",") : [];
|
|
89369
|
-
|
|
89370
|
-
|
|
89784
|
+
for (const cell of cellTexts) {
|
|
89785
|
+
const mangled = await rejectShellMangledValue(cell, HELP34, "--cells");
|
|
89786
|
+
if (typeof mangled === "number")
|
|
89787
|
+
return mangled;
|
|
89788
|
+
}
|
|
89789
|
+
const reference = referenceRow(grid, position2);
|
|
89790
|
+
const logicalCols = reference ? reference.cells.length : grid.colCount;
|
|
89791
|
+
if (cellTexts.length > logicalCols) {
|
|
89792
|
+
return fail("USAGE", `--cells has ${cellTexts.length} entries but the row has ${logicalCols} columns (a merged cell counts once)`);
|
|
89371
89793
|
}
|
|
89372
89794
|
const newRow = buildRow(grid, position2, cellTexts);
|
|
89373
89795
|
const tracking = resolveTracked(document4, parsed.values.track);
|
|
@@ -89409,9 +89831,16 @@ function resolveRowPosition(raw, rowCount) {
|
|
|
89409
89831
|
return null;
|
|
89410
89832
|
return value;
|
|
89411
89833
|
}
|
|
89834
|
+
function referenceRow(grid, position2) {
|
|
89835
|
+
const above = position2 > 0 ? grid.rows[position2 - 1] : undefined;
|
|
89836
|
+
const below = position2 < grid.rows.length ? grid.rows[position2] : undefined;
|
|
89837
|
+
return above ?? below;
|
|
89838
|
+
}
|
|
89412
89839
|
function buildRow(grid, position2, cellTexts) {
|
|
89413
89840
|
const below = position2 > 0 && position2 < grid.rows.length ? grid.rows[position2] : undefined;
|
|
89841
|
+
const spans = referenceRow(grid, position2);
|
|
89414
89842
|
const cells = [];
|
|
89843
|
+
let logical = 0;
|
|
89415
89844
|
for (let col = 0;col < grid.colCount; ) {
|
|
89416
89845
|
const continued = below ? cellAt(below, col) : undefined;
|
|
89417
89846
|
if (continued?.vMerge === "continue") {
|
|
@@ -89425,12 +89854,15 @@ function buildRow(grid, position2, cellTexts) {
|
|
|
89425
89854
|
col += continued.colSpan;
|
|
89426
89855
|
continue;
|
|
89427
89856
|
}
|
|
89857
|
+
const refSpan = spans ? cellAt(spans, col)?.colSpan ?? 1 : 1;
|
|
89428
89858
|
cells.push(/* @__PURE__ */ jsxDEV(TableCell, {
|
|
89859
|
+
gridSpan: refSpan > 1 ? refSpan : undefined,
|
|
89429
89860
|
children: /* @__PURE__ */ jsxDEV(Paragraph, {
|
|
89430
|
-
text: cellTexts[
|
|
89861
|
+
text: cellTexts[logical] ?? ""
|
|
89431
89862
|
}, undefined, false, undefined, this)
|
|
89432
89863
|
}, undefined, false, undefined, this));
|
|
89433
|
-
|
|
89864
|
+
logical += 1;
|
|
89865
|
+
col += refSpan;
|
|
89434
89866
|
}
|
|
89435
89867
|
return /* @__PURE__ */ jsxDEV(w.tr, {
|
|
89436
89868
|
children: cells
|
|
@@ -89450,6 +89882,7 @@ var init_insert_row = __esm(() => {
|
|
|
89450
89882
|
init_jsx();
|
|
89451
89883
|
init_locators();
|
|
89452
89884
|
init_table();
|
|
89885
|
+
init_parse_helpers();
|
|
89453
89886
|
init_respond();
|
|
89454
89887
|
init_jsx_dev_runtime();
|
|
89455
89888
|
AT_FORMS6 = describeForms(["table"], " ");
|
|
@@ -89465,8 +89898,11 @@ ${AT_FORMS6}
|
|
|
89465
89898
|
|
|
89466
89899
|
Optional:
|
|
89467
89900
|
--position INDEX 0-based row index to insert at (default: append at end)
|
|
89468
|
-
--cells "a,b,c" Comma-separated text
|
|
89469
|
-
|
|
89901
|
+
--cells "a,b,c" Comma-separated text, one value per VISIBLE cell left to
|
|
89902
|
+
right (default: empty). On a table with merged cells the new
|
|
89903
|
+
row copies the neighbor row's gridSpan pattern, so you pass
|
|
89904
|
+
one value per logical column (a spanned cell counts once),
|
|
89905
|
+
NOT one per underlying grid column.
|
|
89470
89906
|
--author NAME Author for tracked insertion (default: $DOCX_AUTHOR)
|
|
89471
89907
|
-o, --output PATH Write to PATH instead of overwriting FILE
|
|
89472
89908
|
--dry-run Print what would change; do not write
|
|
@@ -89999,10 +90435,13 @@ async function run42(args) {
|
|
|
89999
90435
|
const cols = grid.tblGrid.findChildren("w:gridCol");
|
|
90000
90436
|
let twips = [];
|
|
90001
90437
|
if (!auto) {
|
|
90002
|
-
const resolved = resolveWidths(widthsSpec, cols);
|
|
90438
|
+
const resolved = resolveWidths(widthsSpec, cols, grid);
|
|
90003
90439
|
if (typeof resolved === "string")
|
|
90004
90440
|
return fail("USAGE", resolved);
|
|
90005
90441
|
twips = resolved;
|
|
90442
|
+
const tooNarrow = findTooNarrowCell(grid, twips);
|
|
90443
|
+
if (tooNarrow)
|
|
90444
|
+
return fail("USAGE", tooNarrow);
|
|
90006
90445
|
}
|
|
90007
90446
|
const outputPath = parsed.values.output;
|
|
90008
90447
|
if (parsed.values["dry-run"]) {
|
|
@@ -90038,20 +90477,24 @@ async function run42(args) {
|
|
|
90038
90477
|
appendTblGridChange(grid.tblGrid, priorCols, new TrackChanges(document4).mintMeta(author));
|
|
90039
90478
|
}
|
|
90040
90479
|
await document4.save(outputPath);
|
|
90480
|
+
const destination = outputPath ?? path2;
|
|
90481
|
+
const echo = auto ? "" : `${describeColumnWidths(twips)}
|
|
90482
|
+
`;
|
|
90041
90483
|
await respondAck({
|
|
90042
90484
|
ok: true,
|
|
90043
90485
|
operation: "tables.set-widths",
|
|
90044
|
-
path:
|
|
90486
|
+
path: destination,
|
|
90045
90487
|
table: tableId,
|
|
90046
90488
|
layout: auto ? "autofit" : "fixed",
|
|
90047
90489
|
widths: auto ? "auto" : twips
|
|
90048
|
-
});
|
|
90490
|
+
}, `${echo}${renderVerifyHint(destination)}`);
|
|
90049
90491
|
return EXIT2.OK;
|
|
90050
90492
|
}
|
|
90051
|
-
function resolveWidths(spec, cols) {
|
|
90493
|
+
function resolveWidths(spec, cols, grid) {
|
|
90052
90494
|
const tokens = spec.split(",").map((token) => token.trim());
|
|
90053
90495
|
if (tokens.length !== cols.length) {
|
|
90054
|
-
|
|
90496
|
+
const base = `--widths has ${tokens.length} entries but the table has ${cols.length} grid columns`;
|
|
90497
|
+
return hasMergedColumns(grid) ? `${base}. This table has merged cells, so some visible columns span multiple grid columns and the grid has more columns than any single row shows. Supply one width per GRID column (${cols.length} values), left-to-right; a merged cell takes the sum of the grid columns it covers. Inspect the gridSpan layout with \`docx read --ast\`.` : base;
|
|
90055
90498
|
}
|
|
90056
90499
|
const percentage = tokens.every((token) => token.endsWith("%"));
|
|
90057
90500
|
const anyPercent = tokens.some((token) => token.endsWith("%"));
|
|
@@ -90103,7 +90546,30 @@ function cellWidth(cell, twips) {
|
|
|
90103
90546
|
}
|
|
90104
90547
|
return width;
|
|
90105
90548
|
}
|
|
90106
|
-
|
|
90549
|
+
function findTooNarrowCell(grid, twips) {
|
|
90550
|
+
for (const row of grid.rows) {
|
|
90551
|
+
for (const cell of row.cells) {
|
|
90552
|
+
const width = cellWidth(cell, twips);
|
|
90553
|
+
if (width >= MIN_COL_TWIPS)
|
|
90554
|
+
continue;
|
|
90555
|
+
const text6 = cell.node.collectText().trim();
|
|
90556
|
+
if (text6.length === 0)
|
|
90557
|
+
continue;
|
|
90558
|
+
const where = cell.colSpan > 1 ? `grid columns ${cell.colStart}\u2013${cell.colStart + cell.colSpan - 1}` : `grid column ${cell.colStart}`;
|
|
90559
|
+
const sample = text6.length > 24 ? `${text6.slice(0, 24)}\u2026` : text6;
|
|
90560
|
+
return `--widths collapses ${where} to ${twipsToInches(width)}in (${width} twips); that cell holds "${sample}" but ~0.15in goes to cell margins, leaving under one character \u2014 Word wraps it one char per line. Widen it and lower a wider column to compensate.`;
|
|
90561
|
+
}
|
|
90562
|
+
}
|
|
90563
|
+
return null;
|
|
90564
|
+
}
|
|
90565
|
+
function hasMergedColumns(grid) {
|
|
90566
|
+
return grid.rows.some((row) => row.cells.some((cell) => cell.colSpan > 1));
|
|
90567
|
+
}
|
|
90568
|
+
function describeColumnWidths(twips) {
|
|
90569
|
+
const cells = twips.map((value, index2) => `g${index2}=${twipsToInches(value)}in`);
|
|
90570
|
+
return `widths: ${cells.join(" ")}`;
|
|
90571
|
+
}
|
|
90572
|
+
var AT_FORMS10, HELP38, MIN_COL_TWIPS = 288;
|
|
90107
90573
|
var init_set_widths = __esm(() => {
|
|
90108
90574
|
init_core2();
|
|
90109
90575
|
init_locators();
|
|
@@ -90136,6 +90602,15 @@ cell's <w:tcW>. Under track-changes the resize is recorded as a real revision
|
|
|
90136
90602
|
(<w:tblGridChange> for the grid plus a per-cell <w:tcPrChange>), so it can be
|
|
90137
90603
|
accepted or rejected \u2014 matching what Word emits for a width change.
|
|
90138
90604
|
|
|
90605
|
+
Widths map one value per GRID column, not per visible column. On a table with
|
|
90606
|
+
merged cells (gridSpan), the grid has MORE columns than a single row shows, so
|
|
90607
|
+
the count you pass must match the grid (run \`docx read --ast\` to see it). A
|
|
90608
|
+
cell that HOLDS TEXT but lands narrower than ~0.2in is refused \u2014 after ~0.15in
|
|
90609
|
+
of cell margin it fits under one character, so Word wraps it one char per line
|
|
90610
|
+
(empty/spacer columns that thin are fine, nothing to wrap). The success line
|
|
90611
|
+
echoes the resulting per-column widths; since layout changes don't show in
|
|
90612
|
+
\`read\`, render to verify.
|
|
90613
|
+
|
|
90139
90614
|
Output:
|
|
90140
90615
|
Prints a one-line confirmation on success (exit 0). --verbose prints {ok:true, operation, path, table,
|
|
90141
90616
|
layout, widths}. --dry-run prints the preview object (no ok field). Errors
|
|
@@ -90677,6 +91152,64 @@ var init_tables = __esm(() => {
|
|
|
90677
91152
|
};
|
|
90678
91153
|
});
|
|
90679
91154
|
|
|
91155
|
+
// src/cli/track-changes/groups.ts
|
|
91156
|
+
function revisionGroups(changes) {
|
|
91157
|
+
const sorted = [...changes].sort((a2, b) => tcIndex(a2.id) - tcIndex(b.id));
|
|
91158
|
+
const membersOf = new Map;
|
|
91159
|
+
const revOf = new Map;
|
|
91160
|
+
let next = 0;
|
|
91161
|
+
let index2 = 0;
|
|
91162
|
+
while (index2 < sorted.length) {
|
|
91163
|
+
const a2 = sorted[index2];
|
|
91164
|
+
const b = sorted[index2 + 1];
|
|
91165
|
+
if (a2 && b && isTextReplacePair(a2, b)) {
|
|
91166
|
+
const rev = `rev${next++}`;
|
|
91167
|
+
membersOf.set(rev, [a2.id, b.id]);
|
|
91168
|
+
revOf.set(a2.id, rev);
|
|
91169
|
+
revOf.set(b.id, rev);
|
|
91170
|
+
index2 += 2;
|
|
91171
|
+
continue;
|
|
91172
|
+
}
|
|
91173
|
+
index2 += 1;
|
|
91174
|
+
}
|
|
91175
|
+
return { membersOf, revOf };
|
|
91176
|
+
}
|
|
91177
|
+
function isTextReplacePair(a2, b) {
|
|
91178
|
+
if (a2.blockId === undefined || a2.blockId !== b.blockId)
|
|
91179
|
+
return false;
|
|
91180
|
+
const pair = `${a2.kind}+${b.kind}`;
|
|
91181
|
+
return pair === "del+ins" || pair === "ins+del";
|
|
91182
|
+
}
|
|
91183
|
+
function expandRevisionTargets(targets, groups) {
|
|
91184
|
+
const out = [];
|
|
91185
|
+
for (const target of targets) {
|
|
91186
|
+
if (/^rev\d+$/.test(target)) {
|
|
91187
|
+
const members = groups.membersOf.get(target);
|
|
91188
|
+
if (!members)
|
|
91189
|
+
throw new UnknownRevisionError(target);
|
|
91190
|
+
out.push(...members);
|
|
91191
|
+
continue;
|
|
91192
|
+
}
|
|
91193
|
+
out.push(target);
|
|
91194
|
+
}
|
|
91195
|
+
return out;
|
|
91196
|
+
}
|
|
91197
|
+
function tcIndex(id) {
|
|
91198
|
+
const match = id.match(/^tc(\d+)$/);
|
|
91199
|
+
return match?.[1] ? Number(match[1]) : 0;
|
|
91200
|
+
}
|
|
91201
|
+
var UnknownRevisionError;
|
|
91202
|
+
var init_groups = __esm(() => {
|
|
91203
|
+
UnknownRevisionError = class UnknownRevisionError extends Error {
|
|
91204
|
+
revision;
|
|
91205
|
+
constructor(revision) {
|
|
91206
|
+
super(`Unknown revision group "${revision}"`);
|
|
91207
|
+
this.revision = revision;
|
|
91208
|
+
this.name = "UnknownRevisionError";
|
|
91209
|
+
}
|
|
91210
|
+
};
|
|
91211
|
+
});
|
|
91212
|
+
|
|
90680
91213
|
// src/cli/track-changes/list.ts
|
|
90681
91214
|
var exports_list5 = {};
|
|
90682
91215
|
__export(exports_list5, {
|
|
@@ -90737,6 +91270,12 @@ async function run47(args) {
|
|
|
90737
91270
|
byId.set(change.id, record);
|
|
90738
91271
|
}
|
|
90739
91272
|
const sorted = [...byId.values()].sort((a2, b) => trackedChangeIndex(a2.id) - trackedChangeIndex(b.id));
|
|
91273
|
+
const { revOf } = revisionGroups(sorted);
|
|
91274
|
+
for (const record of sorted) {
|
|
91275
|
+
const group = revOf.get(record.id);
|
|
91276
|
+
if (group)
|
|
91277
|
+
record.group = group;
|
|
91278
|
+
}
|
|
90740
91279
|
await respond(sorted);
|
|
90741
91280
|
return EXIT2.OK;
|
|
90742
91281
|
}
|
|
@@ -90761,7 +91300,11 @@ apart.
|
|
|
90761
91300
|
|
|
90762
91301
|
Output: a bare JSON array of { id, kind, author, date, revisionId, blockId,
|
|
90763
91302
|
text } sorted by id (document order). Each item's "id" (e.g. tc0) is its
|
|
90764
|
-
addressable handle \u2014 pass it to \`accept\`/\`reject --at tcN\`.
|
|
91303
|
+
addressable handle \u2014 pass it to \`accept\`/\`reject --at tcN\`. When a del and an
|
|
91304
|
+
ins are an adjacent REPLACE pair on the same paragraph, BOTH carry a shared
|
|
91305
|
+
"group": "revN" \u2014 accept/reject the whole logical change in one call with
|
|
91306
|
+
\`--at revN\` instead of accepting each half separately (tcN ids renumber after
|
|
91307
|
+
each single accept, so the revN handle avoids the re-list ping-pong). Errors print
|
|
90765
91308
|
{code, error, hint?} with a nonzero exit. kind is one of: "ins", "del", "moveFrom",
|
|
90766
91309
|
"moveTo", "sectPrChange", "rowIns", "rowDel", "cellIns", "cellDel",
|
|
90767
91310
|
"tblGridChange", "tblPrChange", "tcPrChange", "checkboxToggle". Paragraph-mark
|
|
@@ -90790,6 +91333,7 @@ var init_list7 = __esm(() => {
|
|
|
90790
91333
|
init_core2();
|
|
90791
91334
|
init_track_changes();
|
|
90792
91335
|
init_respond();
|
|
91336
|
+
init_groups();
|
|
90793
91337
|
});
|
|
90794
91338
|
|
|
90795
91339
|
// src/cli/track-changes/apply.ts
|
|
@@ -90820,8 +91364,20 @@ async function runApply(args, verb, help) {
|
|
|
90820
91364
|
const document4 = await openOrFail(path2);
|
|
90821
91365
|
if (typeof document4 === "number")
|
|
90822
91366
|
return document4;
|
|
90823
|
-
const target = all2 ? "all" : atRaw ?? [];
|
|
90824
91367
|
const trackChanges = new TrackChanges(document4);
|
|
91368
|
+
let target;
|
|
91369
|
+
if (all2) {
|
|
91370
|
+
target = "all";
|
|
91371
|
+
} else {
|
|
91372
|
+
try {
|
|
91373
|
+
target = expandRevisionTargets(atRaw ?? [], revisionGroups(trackChanges.list()));
|
|
91374
|
+
} catch (error) {
|
|
91375
|
+
if (error instanceof UnknownRevisionError) {
|
|
91376
|
+
return fail("TRACKED_CHANGE_NOT_FOUND", error.message, "Run 'docx track-changes list FILE' \u2014 revN handles appear as the `group` field on paired changes.");
|
|
91377
|
+
}
|
|
91378
|
+
throw error;
|
|
91379
|
+
}
|
|
91380
|
+
}
|
|
90825
91381
|
const outputPath = parsed.values.output;
|
|
90826
91382
|
try {
|
|
90827
91383
|
if (parsed.values["dry-run"]) {
|
|
@@ -90853,6 +91409,7 @@ async function runApply(args, verb, help) {
|
|
|
90853
91409
|
var init_apply2 = __esm(() => {
|
|
90854
91410
|
init_track_changes();
|
|
90855
91411
|
init_respond();
|
|
91412
|
+
init_groups();
|
|
90856
91413
|
});
|
|
90857
91414
|
|
|
90858
91415
|
// src/cli/track-changes/accept.ts
|
|
@@ -90899,6 +91456,10 @@ Target (one required, mutually exclusive):
|
|
|
90899
91456
|
batch is not a concern. Supports:
|
|
90900
91457
|
${AT_FORMS14}
|
|
90901
91458
|
See \`docx info locators\`.
|
|
91459
|
+
--at revN Accept a del+ins REPLACE pair in one call (both halves of one
|
|
91460
|
+
logical change). \`list\` tags the two tcNs with a shared
|
|
91461
|
+
"group": "revN"; addressing the revN saves the accept-relist-
|
|
91462
|
+
accept ping-pong (tcN ids renumber after each single accept).
|
|
90902
91463
|
--all Accept every tracked change.
|
|
90903
91464
|
|
|
90904
91465
|
Options:
|
|
@@ -90952,7 +91513,7 @@ were in effect before the tracked edit.
|
|
|
90952
91513
|
|
|
90953
91514
|
Paragraph-mark trackings (<w:ins>/<w:del> inside <w:pPr><w:rPr>): rejecting
|
|
90954
91515
|
a paragraph-mark insertion removes the entire owning paragraph (the inserted
|
|
90955
|
-
break disappears \u2014 for sentinels created by "
|
|
91516
|
+
break disappears \u2014 for sentinels created by "docx sections" this also
|
|
90956
91517
|
removes the section break the sentinel was carrying). Rejecting a
|
|
90957
91518
|
paragraph-mark deletion just removes the marker (the paragraph stays).
|
|
90958
91519
|
|
|
@@ -90970,6 +91531,10 @@ Target (one required, mutually exclusive):
|
|
|
90970
91531
|
batch is not a concern. Supports:
|
|
90971
91532
|
${AT_FORMS15}
|
|
90972
91533
|
See \`docx info locators\`.
|
|
91534
|
+
--at revN Reject a del+ins REPLACE pair in one call (both halves of one
|
|
91535
|
+
logical change). \`list\` tags the two tcNs with a shared
|
|
91536
|
+
"group": "revN"; addressing the revN saves the reject-relist-
|
|
91537
|
+
reject ping-pong (tcN ids renumber after each single reject).
|
|
90973
91538
|
--all Reject every tracked change.
|
|
90974
91539
|
|
|
90975
91540
|
Options:
|
|
@@ -91520,7 +92085,7 @@ Examples:
|
|
|
91520
92085
|
// package.json
|
|
91521
92086
|
var package_default = {
|
|
91522
92087
|
name: "bun-docx",
|
|
91523
|
-
version: "0.
|
|
92088
|
+
version: "0.14.0",
|
|
91524
92089
|
description: "CLI for AI agents (Claude, Codex) to read, edit, and comment on .docx files with full format fidelity.",
|
|
91525
92090
|
keywords: [
|
|
91526
92091
|
"docx",
|
|
@@ -91611,13 +92176,13 @@ Commands (each one-liner names capabilities you'd otherwise miss; see <command>
|
|
|
91611
92176
|
create FILE Create a new .docx (--from PATH.md | --from - builds from Markdown; --force to overwrite)
|
|
91612
92177
|
read FILE Render as Markdown with pN locators; --from/--to to slice, --accepted (default)/--current/--baseline tracked views, --comments, --ast for JSON-AST
|
|
91613
92178
|
edit FILE Replace or strip text/formatting at pN, pN:S-E, pN-pM, sN, eqN, or table-cell locators (--clear to strip formatting, --track to redline, --batch for many edits in one read)
|
|
91614
|
-
insert FILE Insert a paragraph, image, table, equation, code block, markdown, or
|
|
92179
|
+
insert FILE Insert a paragraph, image, table, equation, code block, markdown, or page break (--after/--before LOCATOR; --track; --batch for many inserts in one read). For COLUMN layout use "docx sections", not insert.
|
|
91615
92180
|
delete FILE Remove a paragraph, range, table, or section break (--at LOCATOR; --track for tracked deletion; --batch to remove many in one read)
|
|
91616
92181
|
find FILE [QUERY] Find spans by text, OR by formatting (--highlight/--color/--bold/--italic/--underline); returns locators for --at
|
|
91617
92182
|
replace FILE PATTERN REPL Substitute text spans, sed-style (--regex, --track to redline, --dry-run to preview, --batch for a multi-pattern script)
|
|
91618
92183
|
wc FILE [LOCATOR] Count words in the doc or a slice (--accepted/--baseline/--current tracked view, --json)
|
|
91619
92184
|
outline FILE List headings as a locator tree (pN feeds --at / read --from; --style-prefix, --json)
|
|
91620
|
-
|
|
92185
|
+
sections FILE Multi-column layout & section breaks \u2014 put a paragraph range in N columns (--at pN-pM --columns N) or recount a section (--at sN). The ONLY way to do columns; insert does not.
|
|
91621
92186
|
styles FILE List the styles you can apply (--used for ones in use; --at ID to describe one) \u2014 the catalog isn't in the body
|
|
91622
92187
|
render FILE Visual page verification \u2014 render each page as PNG/JPG via Word or LibreOffice
|
|
91623
92188
|
comments \u2026 Add (--at LOCATOR | --anchor PHRASE | --batch), reply, resolve (--unset to reopen), delete, list (--thread cN)
|
|
@@ -91645,7 +92210,7 @@ render (each render spins up Word and is slow). Render only for what Markdown ca
|
|
|
91645
92210
|
multi-column sections, page/section breaks, image sizing/placement, table geometry \u2014 and
|
|
91646
92211
|
then ONCE at the end (not after every edit), or one final time if you're genuinely unsure
|
|
91647
92212
|
it looks right: "docx render FILE --out pages/" writes page-001.png, \u2026 which you can read.
|
|
91648
|
-
(
|
|
92213
|
+
(To put text in columns, name the range: "docx sections --at pN-pM --columns N" \u2014 it inserts the bounding breaks so the columns land on exactly that range. A raw section break's columns apply to the content BEFORE it, which is why insert no longer takes --section.)
|
|
91649
92214
|
|
|
91650
92215
|
Environment:
|
|
91651
92216
|
DOCX_AUTHOR Default author for comments and tracked-change attribution
|
|
@@ -91666,7 +92231,6 @@ async function printTopHelp() {
|
|
|
91666
92231
|
// src/cli/index.ts
|
|
91667
92232
|
init_respond();
|
|
91668
92233
|
var COMMANDS = {
|
|
91669
|
-
columns: () => Promise.resolve().then(() => (init_columns(), exports_columns)),
|
|
91670
92234
|
comments: () => Promise.resolve().then(() => (init_comments3(), exports_comments)),
|
|
91671
92235
|
create: () => Promise.resolve().then(() => (init_create2(), exports_create)),
|
|
91672
92236
|
delete: () => Promise.resolve().then(() => (init_delete2(), exports_delete2)),
|
|
@@ -91682,6 +92246,7 @@ var COMMANDS = {
|
|
|
91682
92246
|
read: () => Promise.resolve().then(() => (init_read3(), exports_read)),
|
|
91683
92247
|
render: () => Promise.resolve().then(() => (init_render2(), exports_render)),
|
|
91684
92248
|
replace: () => Promise.resolve().then(() => (init_replace4(), exports_replace3)),
|
|
92249
|
+
sections: () => Promise.resolve().then(() => (init_sections2(), exports_sections)),
|
|
91685
92250
|
styles: () => Promise.resolve().then(() => (init_styles2(), exports_styles)),
|
|
91686
92251
|
tables: () => Promise.resolve().then(() => (init_tables(), exports_tables)),
|
|
91687
92252
|
"track-changes": () => Promise.resolve().then(() => (init_track_changes2(), exports_track_changes)),
|
|
@@ -91711,6 +92276,9 @@ Run "docx --help" for available commands.
|
|
|
91711
92276
|
}
|
|
91712
92277
|
return 0;
|
|
91713
92278
|
}
|
|
92279
|
+
if (cmd === "columns") {
|
|
92280
|
+
return fail("USAGE", "`docx columns` was renamed to `docx sections`", "Run `docx sections --at pN-pM --columns N` (or `docx sections --help`).");
|
|
92281
|
+
}
|
|
91714
92282
|
const loader = COMMANDS[cmd];
|
|
91715
92283
|
if (!loader) {
|
|
91716
92284
|
return fail("USAGE", `Unknown command: ${cmd}`, 'Run "docx --help" for the list of commands.');
|