bun-docx 0.13.0 → 0.14.1
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 +1453 -718
- 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");
|
|
@@ -22188,15 +22198,12 @@ class CommentsView {
|
|
|
22188
22198
|
}
|
|
22189
22199
|
paraIdFor(commentId) {
|
|
22190
22200
|
const numericId = commentId.startsWith("c") ? commentId.slice(1) : commentId;
|
|
22191
|
-
|
|
22192
|
-
const paragraph = comment?.findChild("w:p");
|
|
22193
|
-
return paragraph?.getAttribute("w14:paraId");
|
|
22201
|
+
return lastParagraph(this.findById(numericId))?.getAttribute("w14:paraId");
|
|
22194
22202
|
}
|
|
22195
22203
|
ensureParaId(commentId) {
|
|
22196
22204
|
const numericId = commentId.startsWith("c") ? commentId.slice(1) : commentId;
|
|
22197
22205
|
const root = XmlNode2.findRoot(this.tree, "w:comments");
|
|
22198
|
-
const
|
|
22199
|
-
const paragraph = comment?.findChild("w:p");
|
|
22206
|
+
const paragraph = lastParagraph(this.findById(numericId));
|
|
22200
22207
|
if (!root || !paragraph)
|
|
22201
22208
|
return;
|
|
22202
22209
|
const existing = paragraph.getAttribute("w14:paraId");
|
|
@@ -22226,6 +22233,96 @@ class CommentsView {
|
|
|
22226
22233
|
}
|
|
22227
22234
|
return String(highest + 1);
|
|
22228
22235
|
}
|
|
22236
|
+
threadRootId(commentId) {
|
|
22237
|
+
const root = XmlNode2.findRoot(this.tree, "w:comments");
|
|
22238
|
+
const numericId = commentId.startsWith("c") ? commentId.slice(1) : commentId;
|
|
22239
|
+
if (!root)
|
|
22240
|
+
return numericId;
|
|
22241
|
+
const extended = this.#readExtended();
|
|
22242
|
+
const idByParaId = new Map;
|
|
22243
|
+
for (const child2 of root.children) {
|
|
22244
|
+
if (child2.tag !== "w:comment")
|
|
22245
|
+
continue;
|
|
22246
|
+
const childId = child2.getAttribute("w:id");
|
|
22247
|
+
if (childId == null)
|
|
22248
|
+
continue;
|
|
22249
|
+
const paraId = lastParagraph(child2)?.getAttribute("w14:paraId");
|
|
22250
|
+
if (paraId)
|
|
22251
|
+
idByParaId.set(paraId, childId);
|
|
22252
|
+
}
|
|
22253
|
+
let currentId = numericId;
|
|
22254
|
+
const seen = new Set([currentId]);
|
|
22255
|
+
for (;; ) {
|
|
22256
|
+
const paraId = lastParagraph(this.findById(currentId))?.getAttribute("w14:paraId");
|
|
22257
|
+
const parentParaId = paraId ? extended.get(paraId)?.parentParaId : undefined;
|
|
22258
|
+
const parentId = parentParaId ? idByParaId.get(parentParaId) : undefined;
|
|
22259
|
+
if (!parentId || seen.has(parentId))
|
|
22260
|
+
return currentId;
|
|
22261
|
+
seen.add(parentId);
|
|
22262
|
+
currentId = parentId;
|
|
22263
|
+
}
|
|
22264
|
+
}
|
|
22265
|
+
descendantReplyIds(commentId) {
|
|
22266
|
+
const root = XmlNode2.findRoot(this.tree, "w:comments");
|
|
22267
|
+
if (!root)
|
|
22268
|
+
return [];
|
|
22269
|
+
const numericId = commentId.startsWith("c") ? commentId.slice(1) : commentId;
|
|
22270
|
+
const startParaId = lastParagraph(this.findById(numericId))?.getAttribute("w14:paraId");
|
|
22271
|
+
if (!startParaId)
|
|
22272
|
+
return [];
|
|
22273
|
+
const extended = this.#readExtended();
|
|
22274
|
+
const idByParaId = new Map;
|
|
22275
|
+
const childParaIdsByParent = new Map;
|
|
22276
|
+
for (const child2 of root.children) {
|
|
22277
|
+
if (child2.tag !== "w:comment")
|
|
22278
|
+
continue;
|
|
22279
|
+
const childId = child2.getAttribute("w:id");
|
|
22280
|
+
if (childId == null)
|
|
22281
|
+
continue;
|
|
22282
|
+
const paraId = lastParagraph(child2)?.getAttribute("w14:paraId");
|
|
22283
|
+
if (!paraId)
|
|
22284
|
+
continue;
|
|
22285
|
+
idByParaId.set(paraId, childId);
|
|
22286
|
+
const parentParaId = extended.get(paraId)?.parentParaId;
|
|
22287
|
+
if (!parentParaId)
|
|
22288
|
+
continue;
|
|
22289
|
+
const siblings = childParaIdsByParent.get(parentParaId) ?? [];
|
|
22290
|
+
siblings.push(paraId);
|
|
22291
|
+
childParaIdsByParent.set(parentParaId, siblings);
|
|
22292
|
+
}
|
|
22293
|
+
const descendants = [];
|
|
22294
|
+
const queue = [startParaId];
|
|
22295
|
+
while (queue.length > 0) {
|
|
22296
|
+
const paraId = queue.pop();
|
|
22297
|
+
if (!paraId)
|
|
22298
|
+
break;
|
|
22299
|
+
for (const childParaId of childParaIdsByParent.get(paraId) ?? []) {
|
|
22300
|
+
const childId = idByParaId.get(childParaId);
|
|
22301
|
+
if (childId)
|
|
22302
|
+
descendants.push(childId);
|
|
22303
|
+
queue.push(childParaId);
|
|
22304
|
+
}
|
|
22305
|
+
}
|
|
22306
|
+
return descendants;
|
|
22307
|
+
}
|
|
22308
|
+
insertReplyAfter(parentNumericId, comment) {
|
|
22309
|
+
const root = XmlNode2.findRoot(this.tree, "w:comments");
|
|
22310
|
+
if (!root)
|
|
22311
|
+
throw new Error("expected <w:comments> root");
|
|
22312
|
+
const threadIds = new Set([
|
|
22313
|
+
parentNumericId,
|
|
22314
|
+
...this.descendantReplyIds(parentNumericId)
|
|
22315
|
+
]);
|
|
22316
|
+
let insertIndex = root.children.length;
|
|
22317
|
+
for (const [index, child2] of root.children.entries()) {
|
|
22318
|
+
if (child2.tag !== "w:comment")
|
|
22319
|
+
continue;
|
|
22320
|
+
const id = child2.getAttribute("w:id");
|
|
22321
|
+
if (id != null && threadIds.has(id))
|
|
22322
|
+
insertIndex = index + 1;
|
|
22323
|
+
}
|
|
22324
|
+
root.children.splice(insertIndex, 0, comment);
|
|
22325
|
+
}
|
|
22229
22326
|
toComments(anchors) {
|
|
22230
22327
|
const root = XmlNode2.findRoot(this.tree, "w:comments");
|
|
22231
22328
|
if (!root)
|
|
@@ -22237,8 +22334,7 @@ class CommentsView {
|
|
|
22237
22334
|
const numericId = child2.getAttribute("w:id");
|
|
22238
22335
|
if (numericId == null)
|
|
22239
22336
|
continue;
|
|
22240
|
-
const
|
|
22241
|
-
const paraId = paragraph?.getAttribute("w14:paraId");
|
|
22337
|
+
const paraId = lastParagraph(child2)?.getAttribute("w14:paraId");
|
|
22242
22338
|
if (paraId)
|
|
22243
22339
|
commentIdByParaId.set(paraId, `c${numericId}`);
|
|
22244
22340
|
}
|
|
@@ -22261,8 +22357,7 @@ class CommentsView {
|
|
|
22261
22357
|
endBlockId: "",
|
|
22262
22358
|
endOffset: 0
|
|
22263
22359
|
};
|
|
22264
|
-
const
|
|
22265
|
-
const paraId = paragraph?.getAttribute("w14:paraId");
|
|
22360
|
+
const paraId = lastParagraph(child2)?.getAttribute("w14:paraId");
|
|
22266
22361
|
const meta = paraId ? extendedByParaId.get(paraId) ?? {} : {};
|
|
22267
22362
|
const parentCommentId = meta.parentParaId ? commentIdByParaId.get(meta.parentParaId) : undefined;
|
|
22268
22363
|
comments.push({
|
|
@@ -22321,12 +22416,21 @@ function CommentsRoot() {
|
|
|
22321
22416
|
"xmlns:w14": NS_W14
|
|
22322
22417
|
}, undefined, false, undefined, this);
|
|
22323
22418
|
}
|
|
22419
|
+
function lastParagraph(comment) {
|
|
22420
|
+
return comment?.findChildren("w:p").at(-1);
|
|
22421
|
+
}
|
|
22324
22422
|
function generateParaId() {
|
|
22423
|
+
const seed = Bun.env.DOCX_CLI_PARA_ID_SEED;
|
|
22424
|
+
if (seed) {
|
|
22425
|
+
const minted = (Number.parseInt(seed, 16) + seededParaIds++) % 2147483648;
|
|
22426
|
+
return (minted || 1).toString(16).padStart(8, "0").toUpperCase();
|
|
22427
|
+
}
|
|
22325
22428
|
const bytes = new Uint8Array(4);
|
|
22326
22429
|
crypto.getRandomValues(bytes);
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22430
|
+
bytes[0] = (bytes[0] ?? 0) & 127;
|
|
22431
|
+
const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
22432
|
+
if (hex === "00000000")
|
|
22433
|
+
return "00000001";
|
|
22330
22434
|
return hex.toUpperCase();
|
|
22331
22435
|
}
|
|
22332
22436
|
function CommentsExRoot() {
|
|
@@ -22336,7 +22440,7 @@ function CommentsExRoot() {
|
|
|
22336
22440
|
"mc:Ignorable": "w15"
|
|
22337
22441
|
}, undefined, false, undefined, this);
|
|
22338
22442
|
}
|
|
22339
|
-
var COMMENTS_PART_NAME = "word/comments.xml", COMMENTS_EXT_PART_NAME = "word/commentsExtended.xml", COMMENTS_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", COMMENTS_EXT_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended", COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", COMMENTS_EXT_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", NS_W2 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", NS_W14 = "http://schemas.microsoft.com/office/word/2010/wordml", NS_W15 = "http://schemas.microsoft.com/office/word/2012/wordml";
|
|
22443
|
+
var COMMENTS_PART_NAME = "word/comments.xml", COMMENTS_EXT_PART_NAME = "word/commentsExtended.xml", COMMENTS_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments", COMMENTS_EXT_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended", COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml", COMMENTS_EXT_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml", NS_W2 = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", NS_W14 = "http://schemas.microsoft.com/office/word/2010/wordml", NS_W15 = "http://schemas.microsoft.com/office/word/2012/wordml", seededParaIds = 0;
|
|
22340
22444
|
var init_comments = __esm(() => {
|
|
22341
22445
|
init_jsx();
|
|
22342
22446
|
init_parser();
|
|
@@ -33816,6 +33920,38 @@ function CommentBody({
|
|
|
33816
33920
|
}, undefined, false, undefined, this)
|
|
33817
33921
|
}, undefined, false, undefined, this);
|
|
33818
33922
|
}
|
|
33923
|
+
function addReplyCommentMarkers(documentTree, threadNumericIds, replyNumericId) {
|
|
33924
|
+
const document2 = XmlNode2.findRoot(documentTree, "w:document");
|
|
33925
|
+
if (!document2)
|
|
33926
|
+
return false;
|
|
33927
|
+
const threadIds = new Set(threadNumericIds);
|
|
33928
|
+
const referenceRun = findLastDescendant(document2, (node) => node.tag === "w:r" && node.children.some((child2) => child2.tag === "w:commentReference" && threadIds.has(child2.getAttribute("w:id") ?? "")));
|
|
33929
|
+
if (!referenceRun)
|
|
33930
|
+
return false;
|
|
33931
|
+
const rangeStart = findLastDescendant(document2, (node) => node.tag === "w:commentRangeStart" && threadIds.has(node.getAttribute("w:id") ?? ""));
|
|
33932
|
+
if (!rangeStart) {
|
|
33933
|
+
spliceAfter(referenceRun, commentReferenceRun(replyNumericId));
|
|
33934
|
+
return true;
|
|
33935
|
+
}
|
|
33936
|
+
spliceAfter(rangeStart, commentRangeStartMarker(replyNumericId));
|
|
33937
|
+
spliceAfter(referenceRun, commentRangeEndMarker(replyNumericId), commentReferenceRun(replyNumericId));
|
|
33938
|
+
return true;
|
|
33939
|
+
}
|
|
33940
|
+
function findLastDescendant(root, matches) {
|
|
33941
|
+
let last;
|
|
33942
|
+
for (const child2 of root.children) {
|
|
33943
|
+
if (matches(child2))
|
|
33944
|
+
last = { node: child2, siblings: root.children };
|
|
33945
|
+
const found = findLastDescendant(child2, matches);
|
|
33946
|
+
if (found)
|
|
33947
|
+
last = found;
|
|
33948
|
+
}
|
|
33949
|
+
return last;
|
|
33950
|
+
}
|
|
33951
|
+
function spliceAfter(target, ...nodes) {
|
|
33952
|
+
const index = target.siblings.indexOf(target.node);
|
|
33953
|
+
target.siblings.splice(index + 1, 0, ...nodes);
|
|
33954
|
+
}
|
|
33819
33955
|
function removeCommentMarkers(documentTree, numericId) {
|
|
33820
33956
|
const document2 = XmlNode2.findRoot(documentTree, "w:document");
|
|
33821
33957
|
if (!document2)
|
|
@@ -33876,7 +34012,7 @@ class Comments {
|
|
|
33876
34012
|
return comments;
|
|
33877
34013
|
}
|
|
33878
34014
|
add(anchor, options) {
|
|
33879
|
-
const date = options.date ??
|
|
34015
|
+
const date = options.date ?? resolveDate();
|
|
33880
34016
|
const numericId = this.document.comments?.nextId() ?? "0";
|
|
33881
34017
|
const paraId = generateParaId();
|
|
33882
34018
|
try {
|
|
@@ -33903,21 +34039,47 @@ class Comments {
|
|
|
33903
34039
|
if (!view?.findById(parentNumericId)) {
|
|
33904
34040
|
throw new CommentsError("COMMENT_NOT_FOUND", `Parent comment not found: c${parentNumericId}`);
|
|
33905
34041
|
}
|
|
33906
|
-
const
|
|
33907
|
-
|
|
33908
|
-
|
|
34042
|
+
const rootNumericId = view.threadRootId(parentNumericId);
|
|
34043
|
+
const rootParaId = view.ensureParaId(rootNumericId);
|
|
34044
|
+
if (!rootParaId) {
|
|
34045
|
+
throw new CommentsError("COMMENT_NOT_FOUND", `Parent comment c${rootNumericId} could not be assigned a w14:paraId.`);
|
|
33909
34046
|
}
|
|
33910
|
-
const date = options.date ??
|
|
34047
|
+
const date = options.date ?? resolveDate();
|
|
33911
34048
|
const numericId = view.nextId();
|
|
33912
34049
|
const replyParaId = generateParaId();
|
|
33913
|
-
this
|
|
34050
|
+
const anchored = addReplyCommentMarkers(this.document.documentTree, [rootNumericId, ...view.descendantReplyIds(rootNumericId)], numericId);
|
|
34051
|
+
if (!anchored) {
|
|
34052
|
+
throw new CommentsError("COMMENT_NOT_FOUND", `Parent comment c${parentNumericId} has no anchor in the document body; cannot anchor a reply to it.`);
|
|
34053
|
+
}
|
|
34054
|
+
this.#appendCommentBody(numericId, replyParaId, body, options.author, date, {
|
|
34055
|
+
threadParentNumericId: rootNumericId
|
|
34056
|
+
});
|
|
33914
34057
|
const extView = this.document.ensureCommentsExtended();
|
|
33915
34058
|
const extRoot = extView.extendedTree ? XmlNode2.findRoot(extView.extendedTree, "w15:commentsEx") : undefined;
|
|
33916
34059
|
if (!extRoot)
|
|
33917
34060
|
throw new Error("expected <w15:commentsEx> root");
|
|
33918
|
-
|
|
34061
|
+
const threadParaIds = new Set([
|
|
34062
|
+
rootParaId,
|
|
34063
|
+
...view.descendantReplyIds(rootNumericId).map((replyId) => view.paraIdFor(replyId))
|
|
34064
|
+
]);
|
|
34065
|
+
const hasRootEntry = extRoot.children.some((child2) => child2.tag === "w15:commentEx" && child2.getAttribute("w15:paraId") === rootParaId);
|
|
34066
|
+
if (!hasRootEntry) {
|
|
34067
|
+
extRoot.children.push(new XmlNode2("w15:commentEx", {
|
|
34068
|
+
"w15:paraId": rootParaId,
|
|
34069
|
+
"w15:done": "0"
|
|
34070
|
+
}));
|
|
34071
|
+
}
|
|
34072
|
+
let insertIndex = extRoot.children.length;
|
|
34073
|
+
for (const [index, child2] of extRoot.children.entries()) {
|
|
34074
|
+
if (child2.tag !== "w15:commentEx")
|
|
34075
|
+
continue;
|
|
34076
|
+
const paraId = child2.getAttribute("w15:paraId");
|
|
34077
|
+
if (paraId && threadParaIds.has(paraId))
|
|
34078
|
+
insertIndex = index + 1;
|
|
34079
|
+
}
|
|
34080
|
+
extRoot.children.splice(insertIndex, 0, new XmlNode2("w15:commentEx", {
|
|
33919
34081
|
"w15:paraId": replyParaId,
|
|
33920
|
-
"w15:paraIdParent":
|
|
34082
|
+
"w15:paraIdParent": rootParaId,
|
|
33921
34083
|
"w15:done": "0"
|
|
33922
34084
|
}));
|
|
33923
34085
|
return numericId;
|
|
@@ -33967,10 +34129,16 @@ class Comments {
|
|
|
33967
34129
|
}
|
|
33968
34130
|
if (!view)
|
|
33969
34131
|
return;
|
|
34132
|
+
const cascaded = new Set(normalized);
|
|
34133
|
+
for (const commentId of normalized) {
|
|
34134
|
+
for (const replyId of view.descendantReplyIds(commentId)) {
|
|
34135
|
+
cascaded.add(`c${replyId}`);
|
|
34136
|
+
}
|
|
34137
|
+
}
|
|
33970
34138
|
const root = XmlNode2.findRoot(view.tree, "w:comments");
|
|
33971
34139
|
if (!root)
|
|
33972
34140
|
return;
|
|
33973
|
-
for (const commentId of
|
|
34141
|
+
for (const commentId of cascaded) {
|
|
33974
34142
|
const numericId = commentId.slice(1);
|
|
33975
34143
|
const node = view.findById(numericId);
|
|
33976
34144
|
if (!node)
|
|
@@ -33999,12 +34167,12 @@ class Comments {
|
|
|
33999
34167
|
this.#appendCommentBody(numericId, paraId, options.body, options.author, options.date);
|
|
34000
34168
|
return numericId;
|
|
34001
34169
|
}
|
|
34002
|
-
#appendCommentBody(numericId, paraId, text2, author, date) {
|
|
34170
|
+
#appendCommentBody(numericId, paraId, text2, author, date, options) {
|
|
34003
34171
|
const commentsView = this.document.ensureComments();
|
|
34004
34172
|
const commentsRoot = XmlNode2.findRoot(commentsView.tree, "w:comments");
|
|
34005
34173
|
if (!commentsRoot)
|
|
34006
34174
|
throw new Error("expected <w:comments> root");
|
|
34007
|
-
|
|
34175
|
+
const comment = /* @__PURE__ */ jsxDEV(CommentBody, {
|
|
34008
34176
|
options: {
|
|
34009
34177
|
id: numericId,
|
|
34010
34178
|
author,
|
|
@@ -34013,7 +34181,12 @@ class Comments {
|
|
|
34013
34181
|
paraId,
|
|
34014
34182
|
text: text2
|
|
34015
34183
|
}
|
|
34016
|
-
}, undefined, false, undefined, this)
|
|
34184
|
+
}, undefined, false, undefined, this);
|
|
34185
|
+
if (options?.threadParentNumericId) {
|
|
34186
|
+
commentsView.insertReplyAfter(options.threadParentNumericId, comment);
|
|
34187
|
+
return;
|
|
34188
|
+
}
|
|
34189
|
+
commentsRoot.children.push(comment);
|
|
34017
34190
|
}
|
|
34018
34191
|
#resolveBlock(blockId) {
|
|
34019
34192
|
try {
|
|
@@ -34048,6 +34221,7 @@ var init_comments2 = __esm(() => {
|
|
|
34048
34221
|
init_parser();
|
|
34049
34222
|
init_markers();
|
|
34050
34223
|
init_markers();
|
|
34224
|
+
init_track_changes();
|
|
34051
34225
|
init_jsx_dev_runtime();
|
|
34052
34226
|
CommentsError = class CommentsError extends Error {
|
|
34053
34227
|
code;
|
|
@@ -34067,6 +34241,7 @@ function Paragraph({
|
|
|
34067
34241
|
alignment,
|
|
34068
34242
|
list,
|
|
34069
34243
|
taskState,
|
|
34244
|
+
tabs,
|
|
34070
34245
|
text: text2,
|
|
34071
34246
|
runs,
|
|
34072
34247
|
...formatting
|
|
@@ -34075,7 +34250,7 @@ function Paragraph({
|
|
|
34075
34250
|
return /* @__PURE__ */ jsxDEV(w.p, {
|
|
34076
34251
|
children: [
|
|
34077
34252
|
/* @__PURE__ */ jsxDEV(ParagraphProperties, {
|
|
34078
|
-
options: { style, alignment, list }
|
|
34253
|
+
options: { style, alignment, list, tabs }
|
|
34079
34254
|
}, undefined, false, undefined, this),
|
|
34080
34255
|
taskState && /* @__PURE__ */ jsxDEV(TaskCheckbox, {
|
|
34081
34256
|
checked: taskState === "checked"
|
|
@@ -34131,13 +34306,26 @@ function RunElement({ run }) {
|
|
|
34131
34306
|
return null;
|
|
34132
34307
|
}
|
|
34133
34308
|
function applyParagraphOptionsInPlace(rebuilt, options) {
|
|
34134
|
-
if (!options.style && !options.alignment)
|
|
34309
|
+
if (!options.style && !options.alignment && !options.tabs)
|
|
34135
34310
|
return;
|
|
34136
34311
|
let pPr = rebuilt.find((child2) => child2.tag === "w:pPr");
|
|
34137
34312
|
if (!pPr) {
|
|
34138
34313
|
pPr = new XmlNode2("w:pPr");
|
|
34139
34314
|
rebuilt.unshift(pPr);
|
|
34140
34315
|
}
|
|
34316
|
+
if (options.tabs) {
|
|
34317
|
+
pPr.children = pPr.children.filter((child2) => child2.tag !== "w:tabs");
|
|
34318
|
+
if (options.tabs.length > 0) {
|
|
34319
|
+
const tabsNode = new XmlNode2("w:tabs");
|
|
34320
|
+
for (const stop of options.tabs) {
|
|
34321
|
+
tabsNode.children.push(new XmlNode2("w:tab", {
|
|
34322
|
+
"w:val": stop.align,
|
|
34323
|
+
"w:pos": String(Math.round(stop.pos))
|
|
34324
|
+
}));
|
|
34325
|
+
}
|
|
34326
|
+
insertPprChildInOrder(pPr, tabsNode);
|
|
34327
|
+
}
|
|
34328
|
+
}
|
|
34141
34329
|
if (options.style) {
|
|
34142
34330
|
const existingStyle = pPr.findChild("w:pStyle");
|
|
34143
34331
|
if (existingStyle) {
|
|
@@ -34244,7 +34432,8 @@ function RunProperties({ run }) {
|
|
|
34244
34432
|
function ParagraphProperties({
|
|
34245
34433
|
options
|
|
34246
34434
|
}) {
|
|
34247
|
-
|
|
34435
|
+
const hasTabs = options.tabs !== undefined && options.tabs.length > 0;
|
|
34436
|
+
if (!options.style && !options.alignment && !options.list && !hasTabs)
|
|
34248
34437
|
return null;
|
|
34249
34438
|
return /* @__PURE__ */ jsxDEV(w.pPr, {
|
|
34250
34439
|
children: [
|
|
@@ -34261,6 +34450,12 @@ function ParagraphProperties({
|
|
|
34261
34450
|
}, undefined, false, undefined, this)
|
|
34262
34451
|
]
|
|
34263
34452
|
}, undefined, true, undefined, this),
|
|
34453
|
+
hasTabs && /* @__PURE__ */ jsxDEV(w.tabs, {
|
|
34454
|
+
children: options.tabs?.map((stop) => /* @__PURE__ */ jsxDEV(w.tab, {
|
|
34455
|
+
"w-val": stop.align,
|
|
34456
|
+
"w-pos": String(Math.round(stop.pos))
|
|
34457
|
+
}, undefined, false, undefined, this))
|
|
34458
|
+
}, undefined, false, undefined, this),
|
|
34264
34459
|
options.alignment && /* @__PURE__ */ jsxDEV(w.jc, {
|
|
34265
34460
|
"w-val": options.alignment
|
|
34266
34461
|
}, undefined, false, undefined, this)
|
|
@@ -49400,7 +49595,7 @@ function collectRunText(run) {
|
|
|
49400
49595
|
function tokenize(text2) {
|
|
49401
49596
|
if (text2.length === 0)
|
|
49402
49597
|
return [];
|
|
49403
|
-
return text2.match(/\S+|\
|
|
49598
|
+
return text2.match(/\S+|\t+|[^\S\t]+/g) ?? [];
|
|
49404
49599
|
}
|
|
49405
49600
|
function diffTokens(oldTokens, newTokens) {
|
|
49406
49601
|
const m2 = oldTokens.length;
|
|
@@ -49461,6 +49656,10 @@ function demoteOrphanWhitespaceKeeps(ops) {
|
|
|
49461
49656
|
out.push(op2);
|
|
49462
49657
|
continue;
|
|
49463
49658
|
}
|
|
49659
|
+
if (op2.old.text.includes("\t")) {
|
|
49660
|
+
out.push(op2);
|
|
49661
|
+
continue;
|
|
49662
|
+
}
|
|
49464
49663
|
const prev = ops[index - 1];
|
|
49465
49664
|
const next = ops[index + 1];
|
|
49466
49665
|
const prevIsEdit = prev !== undefined && prev.kind !== "keep";
|
|
@@ -49549,25 +49748,45 @@ function inheritedRprForInsert(ops, index, fallbackRpr) {
|
|
|
49549
49748
|
break;
|
|
49550
49749
|
groupEnd++;
|
|
49551
49750
|
}
|
|
49552
|
-
const
|
|
49553
|
-
|
|
49554
|
-
|
|
49751
|
+
const targetText = (() => {
|
|
49752
|
+
const op2 = ops[index];
|
|
49753
|
+
return op2 && op2.kind === "insert" ? op2.text : "";
|
|
49754
|
+
})();
|
|
49755
|
+
const targetIsWord = !isWhitespaceOnly(targetText);
|
|
49756
|
+
const allDeletes = [];
|
|
49757
|
+
const wordDeletes = [];
|
|
49758
|
+
let allInsertOrdinal = 0;
|
|
49759
|
+
let wordInsertOrdinal = 0;
|
|
49760
|
+
let myAllOrdinal = -1;
|
|
49761
|
+
let myWordOrdinal = -1;
|
|
49555
49762
|
for (let cursor = groupStart;cursor <= groupEnd; cursor++) {
|
|
49556
49763
|
const op2 = ops[cursor];
|
|
49557
49764
|
if (!op2)
|
|
49558
49765
|
continue;
|
|
49559
49766
|
if (op2.kind === "delete") {
|
|
49560
|
-
|
|
49767
|
+
allDeletes.push(op2.old.rPr);
|
|
49768
|
+
if (!isWhitespaceOnly(op2.old.text))
|
|
49769
|
+
wordDeletes.push(op2.old.rPr);
|
|
49561
49770
|
continue;
|
|
49562
49771
|
}
|
|
49563
49772
|
if (op2.kind === "insert") {
|
|
49564
|
-
|
|
49565
|
-
|
|
49566
|
-
|
|
49773
|
+
const isWord = !isWhitespaceOnly(op2.text);
|
|
49774
|
+
if (cursor === index) {
|
|
49775
|
+
myAllOrdinal = allInsertOrdinal;
|
|
49776
|
+
myWordOrdinal = isWord ? wordInsertOrdinal : -1;
|
|
49777
|
+
}
|
|
49778
|
+
allInsertOrdinal++;
|
|
49779
|
+
if (isWord)
|
|
49780
|
+
wordInsertOrdinal++;
|
|
49567
49781
|
}
|
|
49568
49782
|
}
|
|
49569
|
-
if (
|
|
49570
|
-
const paired =
|
|
49783
|
+
if (targetIsWord && wordDeletes.length > 0 && myWordOrdinal >= 0) {
|
|
49784
|
+
const paired = myWordOrdinal < wordDeletes.length ? wordDeletes[myWordOrdinal] : wordDeletes[wordDeletes.length - 1];
|
|
49785
|
+
if (paired !== undefined)
|
|
49786
|
+
return paired;
|
|
49787
|
+
}
|
|
49788
|
+
if (!targetIsWord && allDeletes.length > 0 && myAllOrdinal >= 0) {
|
|
49789
|
+
const paired = myAllOrdinal < allDeletes.length ? allDeletes[myAllOrdinal] : allDeletes[allDeletes.length - 1];
|
|
49571
49790
|
if (paired !== undefined)
|
|
49572
49791
|
return paired;
|
|
49573
49792
|
}
|
|
@@ -49964,6 +50183,14 @@ class Edit {
|
|
|
49964
50183
|
}
|
|
49965
50184
|
return anchorTarget ?? blockRef.node;
|
|
49966
50185
|
}
|
|
50186
|
+
paragraphProperties(blockRef, options) {
|
|
50187
|
+
if (blockRef.node.tag !== "w:p") {
|
|
50188
|
+
throw new EditError("USAGE", "--style/--alignment alone restyle a paragraph; this locator is not a paragraph.");
|
|
50189
|
+
}
|
|
50190
|
+
this.document.ensureStyles().ensureReferencedStyle(options.style);
|
|
50191
|
+
applyParagraphOptionsInPlace(blockRef.node.children, options);
|
|
50192
|
+
return blockRef.node;
|
|
50193
|
+
}
|
|
49967
50194
|
span(blockRef, span, replacement, opts = {}) {
|
|
49968
50195
|
if (blockRef.node.tag !== "w:p") {
|
|
49969
50196
|
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 +80595,20 @@ async function respond(payload) {
|
|
|
80368
80595
|
function setVerboseAck(verbose) {
|
|
80369
80596
|
verboseAck = verbose;
|
|
80370
80597
|
}
|
|
80371
|
-
async function respondAck(payload) {
|
|
80598
|
+
async function respondAck(payload, layoutHint) {
|
|
80372
80599
|
if (verboseAck) {
|
|
80373
80600
|
await respond(payload);
|
|
80374
80601
|
return;
|
|
80375
80602
|
}
|
|
80376
|
-
const
|
|
80377
|
-
if (
|
|
80378
|
-
await writeStdout(`${
|
|
80603
|
+
const parts = [summarizeAck(payload), layoutHint].filter((part) => Boolean(part));
|
|
80604
|
+
if (parts.length > 0)
|
|
80605
|
+
await writeStdout(`${parts.join(`
|
|
80606
|
+
`)}
|
|
80379
80607
|
`);
|
|
80380
80608
|
}
|
|
80609
|
+
function renderVerifyHint(path2) {
|
|
80610
|
+
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)`;
|
|
80611
|
+
}
|
|
80381
80612
|
function summarizeAck(payload) {
|
|
80382
80613
|
if (!payload || typeof payload !== "object")
|
|
80383
80614
|
return null;
|
|
@@ -80425,13 +80656,16 @@ function ackTarget(ack) {
|
|
|
80425
80656
|
return str(ack.path);
|
|
80426
80657
|
return null;
|
|
80427
80658
|
}
|
|
80428
|
-
async function respondMinted(locators, verbosePayload) {
|
|
80659
|
+
async function respondMinted(locators, verbosePayload, layoutHint) {
|
|
80429
80660
|
if (verboseAck) {
|
|
80430
80661
|
await respond(verbosePayload);
|
|
80431
80662
|
return;
|
|
80432
80663
|
}
|
|
80433
|
-
|
|
80434
|
-
|
|
80664
|
+
const parts = [...locators];
|
|
80665
|
+
if (layoutHint)
|
|
80666
|
+
parts.push(layoutHint);
|
|
80667
|
+
if (parts.length > 0)
|
|
80668
|
+
await writeStdout(`${parts.join(`
|
|
80435
80669
|
`)}
|
|
80436
80670
|
`);
|
|
80437
80671
|
}
|
|
@@ -80571,254 +80805,36 @@ var init_respond = __esm(() => {
|
|
|
80571
80805
|
};
|
|
80572
80806
|
});
|
|
80573
80807
|
|
|
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;
|
|
80808
|
+
// src/cli/parse-helpers.ts
|
|
80809
|
+
function detectMarkdownInPlainText(text6) {
|
|
80810
|
+
if (/\*\*[^*\n]+\*\*/.test(text6))
|
|
80811
|
+
return "bold (**\u2026**)";
|
|
80812
|
+
if (/__[^_\n]+__/.test(text6))
|
|
80813
|
+
return "bold (__\u2026__)";
|
|
80814
|
+
if (/(^|\n) {0,3}#{1,6}\s/.test(text6))
|
|
80815
|
+
return "a heading (#\u2026)";
|
|
80816
|
+
if (/\[[^\]\n]+\]\([^)\n]+\)/.test(text6))
|
|
80817
|
+
return "a link ([text](url))";
|
|
80818
|
+
return null;
|
|
80725
80819
|
}
|
|
80726
|
-
function
|
|
80727
|
-
const
|
|
80728
|
-
|
|
80729
|
-
|
|
80820
|
+
async function rejectMarkdownInText(text6, help) {
|
|
80821
|
+
const found = detectMarkdownInPlainText(text6);
|
|
80822
|
+
if (!found)
|
|
80823
|
+
return null;
|
|
80824
|
+
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:
|
|
80825
|
+
${help}`);
|
|
80730
80826
|
}
|
|
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;
|
|
80827
|
+
function detectShellMangledCurrency(text6) {
|
|
80828
|
+
const match = text6.match(/(?<![\d$])([.,]\d{2,})/);
|
|
80829
|
+
return match?.[1] ?? null;
|
|
80740
80830
|
}
|
|
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;
|
|
80831
|
+
async function rejectShellMangledValue(text6, help, label = "this value") {
|
|
80832
|
+
const fragment = detectShellMangledCurrency(text6);
|
|
80833
|
+
if (!fragment)
|
|
80834
|
+
return null;
|
|
80835
|
+
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:
|
|
80836
|
+
${help}`);
|
|
80764
80837
|
}
|
|
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
80838
|
function parseTaskFlag(value) {
|
|
80823
80839
|
const normalized = value.toLowerCase();
|
|
80824
80840
|
if (normalized === "checked" || normalized === "true" || normalized === "1")
|
|
@@ -80849,9 +80865,9 @@ async function parseRunsArg(json2) {
|
|
|
80849
80865
|
return fail("USAGE", "--runs must be a JSON array of Run objects");
|
|
80850
80866
|
}
|
|
80851
80867
|
const runs = parsed;
|
|
80852
|
-
for (const
|
|
80853
|
-
if (
|
|
80854
|
-
const invalid = firstInvalidRunFormat(
|
|
80868
|
+
for (const run of runs) {
|
|
80869
|
+
if (run !== null && typeof run === "object" && run.type === "text") {
|
|
80870
|
+
const invalid = firstInvalidRunFormat(run);
|
|
80855
80871
|
if (invalid) {
|
|
80856
80872
|
return fail("USAGE", `Invalid ${invalid.field} "${invalid.value}" in a --runs text run`, `Use ${invalid.valid}.`);
|
|
80857
80873
|
}
|
|
@@ -80937,9 +80953,9 @@ var init_parse_helpers = __esm(() => {
|
|
|
80937
80953
|
// src/cli/comments/add.tsx
|
|
80938
80954
|
var exports_add = {};
|
|
80939
80955
|
__export(exports_add, {
|
|
80940
|
-
run: () =>
|
|
80956
|
+
run: () => run
|
|
80941
80957
|
});
|
|
80942
|
-
async function
|
|
80958
|
+
async function run(args) {
|
|
80943
80959
|
const parsed = await tryParseArgs(args, {
|
|
80944
80960
|
at: { type: "string" },
|
|
80945
80961
|
anchor: { type: "string" },
|
|
@@ -80950,17 +80966,17 @@ async function run2(args) {
|
|
|
80950
80966
|
current: { type: "boolean" },
|
|
80951
80967
|
baseline: { type: "boolean" },
|
|
80952
80968
|
...SAVE_FLAGS
|
|
80953
|
-
},
|
|
80969
|
+
}, HELP);
|
|
80954
80970
|
if (typeof parsed === "number")
|
|
80955
80971
|
return parsed;
|
|
80956
80972
|
if (parsed.values.help) {
|
|
80957
|
-
await writeStdout(
|
|
80973
|
+
await writeStdout(HELP);
|
|
80958
80974
|
return EXIT2.OK;
|
|
80959
80975
|
}
|
|
80960
80976
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
80961
80977
|
const path2 = parsed.positionals[0];
|
|
80962
80978
|
if (!path2)
|
|
80963
|
-
return fail("USAGE", "Missing FILE argument",
|
|
80979
|
+
return fail("USAGE", "Missing FILE argument", HELP);
|
|
80964
80980
|
const atInput = parsed.values.at;
|
|
80965
80981
|
const anchorInput = parsed.values.anchor;
|
|
80966
80982
|
const batchInput = parsed.values.batch;
|
|
@@ -80975,10 +80991,10 @@ async function run2(args) {
|
|
|
80975
80991
|
}
|
|
80976
80992
|
const anchorCount = (atInput ? 1 : 0) + (anchorInput ? 1 : 0) + (batchInput ? 1 : 0);
|
|
80977
80993
|
if (anchorCount === 0) {
|
|
80978
|
-
return fail("USAGE", "Specify exactly one of --at, --anchor, or --batch",
|
|
80994
|
+
return fail("USAGE", "Specify exactly one of --at, --anchor, or --batch", HELP);
|
|
80979
80995
|
}
|
|
80980
80996
|
if (anchorCount > 1) {
|
|
80981
|
-
return fail("USAGE", "--at, --anchor, and --batch are mutually exclusive",
|
|
80997
|
+
return fail("USAGE", "--at, --anchor, and --batch are mutually exclusive", HELP);
|
|
80982
80998
|
}
|
|
80983
80999
|
const document4 = await openOrFail(path2);
|
|
80984
81000
|
if (typeof document4 === "number")
|
|
@@ -80986,7 +81002,7 @@ async function run2(args) {
|
|
|
80986
81002
|
let rawEntries;
|
|
80987
81003
|
if (batchInput) {
|
|
80988
81004
|
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",
|
|
81005
|
+
return fail("USAGE", "--batch reads each entry's at/anchor/text/author from JSONL \u2014 do not pass them on the CLI", HELP);
|
|
80990
81006
|
}
|
|
80991
81007
|
try {
|
|
80992
81008
|
rawEntries = await readJsonlObjects(batchInput);
|
|
@@ -80999,7 +81015,7 @@ async function run2(args) {
|
|
|
80999
81015
|
}
|
|
81000
81016
|
} else {
|
|
81001
81017
|
if (!text6)
|
|
81002
|
-
return fail("USAGE", "Missing --text TEXT",
|
|
81018
|
+
return fail("USAGE", "Missing --text TEXT", HELP);
|
|
81003
81019
|
const occurrence = occurrenceRaw === undefined ? undefined : Number(occurrenceRaw);
|
|
81004
81020
|
if (occurrence !== undefined && (!Number.isInteger(occurrence) || occurrence < 1)) {
|
|
81005
81021
|
return fail("USAGE", `--occurrence must be a positive integer (1-indexed), got "${occurrenceRaw}"`);
|
|
@@ -81173,14 +81189,14 @@ function resolveAnchorEntry(document4, anchor, occurrence, occurrenceExplicit, t
|
|
|
81173
81189
|
locatorString
|
|
81174
81190
|
};
|
|
81175
81191
|
}
|
|
81176
|
-
var AT_FORMS,
|
|
81192
|
+
var AT_FORMS, HELP, EntryError;
|
|
81177
81193
|
var init_add = __esm(() => {
|
|
81178
81194
|
init_core2();
|
|
81179
81195
|
init_find();
|
|
81180
81196
|
init_parse_helpers();
|
|
81181
81197
|
init_respond();
|
|
81182
81198
|
AT_FORMS = describeForms(["paragraph", "span", "crossSpan", "cellParagraph", "cellSpan"], " ");
|
|
81183
|
-
|
|
81199
|
+
HELP = `docx comments add \u2014 anchor a new comment to a locator or phrase
|
|
81184
81200
|
|
|
81185
81201
|
Usage:
|
|
81186
81202
|
docx comments add FILE --at LOCATOR --text TEXT [options]
|
|
@@ -81254,31 +81270,31 @@ Batch JSONL example:
|
|
|
81254
81270
|
// src/cli/comments/delete.ts
|
|
81255
81271
|
var exports_delete = {};
|
|
81256
81272
|
__export(exports_delete, {
|
|
81257
|
-
run: () =>
|
|
81273
|
+
run: () => run2
|
|
81258
81274
|
});
|
|
81259
|
-
async function
|
|
81275
|
+
async function run2(args) {
|
|
81260
81276
|
const parsed = await tryParseArgs(args, {
|
|
81261
81277
|
at: { type: "string", multiple: true },
|
|
81262
81278
|
batch: { type: "string" },
|
|
81263
81279
|
...SAVE_FLAGS
|
|
81264
|
-
},
|
|
81280
|
+
}, HELP2);
|
|
81265
81281
|
if (typeof parsed === "number")
|
|
81266
81282
|
return parsed;
|
|
81267
81283
|
if (parsed.values.help) {
|
|
81268
|
-
await writeStdout(
|
|
81284
|
+
await writeStdout(HELP2);
|
|
81269
81285
|
return EXIT2.OK;
|
|
81270
81286
|
}
|
|
81271
81287
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
81272
81288
|
const path2 = parsed.positionals[0];
|
|
81273
81289
|
if (!path2)
|
|
81274
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81290
|
+
return fail("USAGE", "Missing FILE argument", HELP2);
|
|
81275
81291
|
const atValues = parsed.values.at ?? [];
|
|
81276
81292
|
const batchInput = parsed.values.batch;
|
|
81277
81293
|
if (atValues.length > 0 && batchInput) {
|
|
81278
|
-
return fail("USAGE", "--at and --batch are mutually exclusive",
|
|
81294
|
+
return fail("USAGE", "--at and --batch are mutually exclusive", HELP2);
|
|
81279
81295
|
}
|
|
81280
81296
|
if (atValues.length === 0 && !batchInput) {
|
|
81281
|
-
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE",
|
|
81297
|
+
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE", HELP2);
|
|
81282
81298
|
}
|
|
81283
81299
|
let rawIds;
|
|
81284
81300
|
if (batchInput) {
|
|
@@ -81333,7 +81349,7 @@ async function run3(args) {
|
|
|
81333
81349
|
});
|
|
81334
81350
|
return EXIT2.OK;
|
|
81335
81351
|
}
|
|
81336
|
-
var
|
|
81352
|
+
var HELP2 = `docx comments delete \u2014 remove one or more comments
|
|
81337
81353
|
|
|
81338
81354
|
Usage:
|
|
81339
81355
|
docx comments delete FILE --at cN [--at cM ...] [options]
|
|
@@ -81344,7 +81360,8 @@ Target (one required, mutually exclusive):
|
|
|
81344
81360
|
--at cN Comment id (e.g., c0). Repeat for multiple ids:
|
|
81345
81361
|
--at c1 --at c3 --at c5. All ids are validated against
|
|
81346
81362
|
the pre-mutation tree, so the batch is atomic. The "c"
|
|
81347
|
-
prefix is optional.
|
|
81363
|
+
prefix is optional. Deleting a thread parent also
|
|
81364
|
+
deletes its replies.
|
|
81348
81365
|
--batch PATH JSONL with one {"id": "cN"} per line. Use - for stdin.
|
|
81349
81366
|
|
|
81350
81367
|
Optional:
|
|
@@ -81372,23 +81389,23 @@ var init_delete = __esm(() => {
|
|
|
81372
81389
|
// src/cli/comments/list.ts
|
|
81373
81390
|
var exports_list = {};
|
|
81374
81391
|
__export(exports_list, {
|
|
81375
|
-
run: () =>
|
|
81392
|
+
run: () => run3
|
|
81376
81393
|
});
|
|
81377
|
-
async function
|
|
81394
|
+
async function run3(args) {
|
|
81378
81395
|
const parsed = await tryParseArgs(args, {
|
|
81379
81396
|
"include-resolved": { type: "boolean" },
|
|
81380
81397
|
thread: { type: "string" },
|
|
81381
81398
|
help: { type: "boolean", short: "h" }
|
|
81382
|
-
},
|
|
81399
|
+
}, HELP3);
|
|
81383
81400
|
if (typeof parsed === "number")
|
|
81384
81401
|
return parsed;
|
|
81385
81402
|
if (parsed.values.help) {
|
|
81386
|
-
await writeStdout(
|
|
81403
|
+
await writeStdout(HELP3);
|
|
81387
81404
|
return EXIT2.OK;
|
|
81388
81405
|
}
|
|
81389
81406
|
const path2 = parsed.positionals[0];
|
|
81390
81407
|
if (!path2)
|
|
81391
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81408
|
+
return fail("USAGE", "Missing FILE argument", HELP3);
|
|
81392
81409
|
const document4 = await openOrFail(path2);
|
|
81393
81410
|
if (typeof document4 === "number")
|
|
81394
81411
|
return document4;
|
|
@@ -81399,7 +81416,7 @@ async function run4(args) {
|
|
|
81399
81416
|
await respond(comments);
|
|
81400
81417
|
return EXIT2.OK;
|
|
81401
81418
|
}
|
|
81402
|
-
var
|
|
81419
|
+
var HELP3 = `docx comments list \u2014 print existing comments as JSON
|
|
81403
81420
|
|
|
81404
81421
|
Usage:
|
|
81405
81422
|
docx comments list FILE [options]
|
|
@@ -81427,31 +81444,31 @@ var init_list3 = __esm(() => {
|
|
|
81427
81444
|
// src/cli/comments/reply.tsx
|
|
81428
81445
|
var exports_reply = {};
|
|
81429
81446
|
__export(exports_reply, {
|
|
81430
|
-
run: () =>
|
|
81447
|
+
run: () => run4
|
|
81431
81448
|
});
|
|
81432
|
-
async function
|
|
81449
|
+
async function run4(args) {
|
|
81433
81450
|
const parsed = await tryParseArgs(args, {
|
|
81434
81451
|
at: { type: "string" },
|
|
81435
81452
|
text: { type: "string" },
|
|
81436
81453
|
author: { type: "string" },
|
|
81437
81454
|
...SAVE_FLAGS
|
|
81438
|
-
},
|
|
81455
|
+
}, HELP4);
|
|
81439
81456
|
if (typeof parsed === "number")
|
|
81440
81457
|
return parsed;
|
|
81441
81458
|
if (parsed.values.help) {
|
|
81442
|
-
await writeStdout(
|
|
81459
|
+
await writeStdout(HELP4);
|
|
81443
81460
|
return EXIT2.OK;
|
|
81444
81461
|
}
|
|
81445
81462
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
81446
81463
|
const path2 = parsed.positionals[0];
|
|
81447
81464
|
if (!path2)
|
|
81448
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81465
|
+
return fail("USAGE", "Missing FILE argument", HELP4);
|
|
81449
81466
|
const parentInput = parsed.values.at;
|
|
81450
81467
|
const text6 = parsed.values.text;
|
|
81451
81468
|
if (!parentInput)
|
|
81452
|
-
return fail("USAGE", "Missing --at cN",
|
|
81469
|
+
return fail("USAGE", "Missing --at cN", HELP4);
|
|
81453
81470
|
if (!text6)
|
|
81454
|
-
return fail("USAGE", "Missing --text TEXT",
|
|
81471
|
+
return fail("USAGE", "Missing --text TEXT", HELP4);
|
|
81455
81472
|
const document4 = await openOrFail(path2);
|
|
81456
81473
|
if (typeof document4 === "number")
|
|
81457
81474
|
return document4;
|
|
@@ -81468,7 +81485,7 @@ async function run5(args) {
|
|
|
81468
81485
|
dryRun: true,
|
|
81469
81486
|
path: path2,
|
|
81470
81487
|
commentId: `c${nextId}`,
|
|
81471
|
-
parentId: `c${parentNumericId}`,
|
|
81488
|
+
parentId: `c${document4.comments.threadRootId(parentNumericId)}`,
|
|
81472
81489
|
...outputPath ? { output: outputPath } : {}
|
|
81473
81490
|
});
|
|
81474
81491
|
return EXIT2.OK;
|
|
@@ -81488,17 +81505,19 @@ async function run5(args) {
|
|
|
81488
81505
|
operation: "comments.reply",
|
|
81489
81506
|
path: outputPath ?? path2,
|
|
81490
81507
|
commentId: `c${numericId}`,
|
|
81491
|
-
parentId: `c${parentNumericId}`
|
|
81508
|
+
parentId: `c${document4.comments?.threadRootId(parentNumericId) ?? parentNumericId}`
|
|
81492
81509
|
});
|
|
81493
81510
|
return EXIT2.OK;
|
|
81494
81511
|
}
|
|
81495
|
-
var
|
|
81512
|
+
var HELP4 = `docx comments reply \u2014 reply to an existing comment
|
|
81496
81513
|
|
|
81497
81514
|
Usage:
|
|
81498
81515
|
docx comments reply FILE --at cN --text TEXT [options]
|
|
81499
81516
|
|
|
81500
81517
|
Required:
|
|
81501
81518
|
--at cN Parent comment id (e.g., c0). The "c" prefix is optional.
|
|
81519
|
+
Replying to a reply attaches to the thread root (Word
|
|
81520
|
+
threads are single-level); the ack's parentId reports it.
|
|
81502
81521
|
--text TEXT Reply body
|
|
81503
81522
|
|
|
81504
81523
|
Optional:
|
|
@@ -81525,33 +81544,33 @@ var init_reply = __esm(() => {
|
|
|
81525
81544
|
// src/cli/comments/resolve.ts
|
|
81526
81545
|
var exports_resolve = {};
|
|
81527
81546
|
__export(exports_resolve, {
|
|
81528
|
-
run: () =>
|
|
81547
|
+
run: () => run5
|
|
81529
81548
|
});
|
|
81530
|
-
async function
|
|
81549
|
+
async function run5(args) {
|
|
81531
81550
|
const parsed = await tryParseArgs(args, {
|
|
81532
81551
|
at: { type: "string", multiple: true },
|
|
81533
81552
|
batch: { type: "string" },
|
|
81534
81553
|
unset: { type: "boolean" },
|
|
81535
81554
|
...SAVE_FLAGS
|
|
81536
|
-
},
|
|
81555
|
+
}, HELP5);
|
|
81537
81556
|
if (typeof parsed === "number")
|
|
81538
81557
|
return parsed;
|
|
81539
81558
|
if (parsed.values.help) {
|
|
81540
|
-
await writeStdout(
|
|
81559
|
+
await writeStdout(HELP5);
|
|
81541
81560
|
return EXIT2.OK;
|
|
81542
81561
|
}
|
|
81543
81562
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
81544
81563
|
const path2 = parsed.positionals[0];
|
|
81545
81564
|
if (!path2)
|
|
81546
|
-
return fail("USAGE", "Missing FILE argument",
|
|
81565
|
+
return fail("USAGE", "Missing FILE argument", HELP5);
|
|
81547
81566
|
const atValues = parsed.values.at ?? [];
|
|
81548
81567
|
const batchInput = parsed.values.batch;
|
|
81549
81568
|
const resolved = !parsed.values.unset;
|
|
81550
81569
|
if (atValues.length > 0 && batchInput) {
|
|
81551
|
-
return fail("USAGE", "--at and --batch are mutually exclusive",
|
|
81570
|
+
return fail("USAGE", "--at and --batch are mutually exclusive", HELP5);
|
|
81552
81571
|
}
|
|
81553
81572
|
if (atValues.length === 0 && !batchInput) {
|
|
81554
|
-
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE",
|
|
81573
|
+
return fail("USAGE", "Specify --at cN (repeatable) or --batch FILE", HELP5);
|
|
81555
81574
|
}
|
|
81556
81575
|
let rawIds;
|
|
81557
81576
|
if (batchInput) {
|
|
@@ -81608,7 +81627,7 @@ async function run6(args) {
|
|
|
81608
81627
|
});
|
|
81609
81628
|
return EXIT2.OK;
|
|
81610
81629
|
}
|
|
81611
|
-
var
|
|
81630
|
+
var HELP5 = `docx comments resolve \u2014 mark one or more comments resolved
|
|
81612
81631
|
|
|
81613
81632
|
Usage:
|
|
81614
81633
|
docx comments resolve FILE --at cN [--at cM ...] [options]
|
|
@@ -81649,12 +81668,12 @@ var init_resolve2 = __esm(() => {
|
|
|
81649
81668
|
// src/cli/comments/index.ts
|
|
81650
81669
|
var exports_comments = {};
|
|
81651
81670
|
__export(exports_comments, {
|
|
81652
|
-
run: () =>
|
|
81671
|
+
run: () => run6
|
|
81653
81672
|
});
|
|
81654
|
-
async function
|
|
81673
|
+
async function run6(args) {
|
|
81655
81674
|
const verb = args[0];
|
|
81656
81675
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
81657
|
-
await writeStdout(
|
|
81676
|
+
await writeStdout(HELP6);
|
|
81658
81677
|
return verb ? 0 : 2;
|
|
81659
81678
|
}
|
|
81660
81679
|
const loader = SUBCOMMANDS[verb];
|
|
@@ -81664,7 +81683,7 @@ async function run7(args) {
|
|
|
81664
81683
|
const module_ = await loader();
|
|
81665
81684
|
return module_.run(args.slice(1));
|
|
81666
81685
|
}
|
|
81667
|
-
var SUBCOMMANDS,
|
|
81686
|
+
var SUBCOMMANDS, HELP6 = `docx comments \u2014 manage Word comments
|
|
81668
81687
|
|
|
81669
81688
|
Usage:
|
|
81670
81689
|
docx comments <verb> FILE [options]
|
|
@@ -81984,9 +82003,9 @@ var init_create = __esm(() => {
|
|
|
81984
82003
|
// src/cli/create/index.tsx
|
|
81985
82004
|
var exports_create = {};
|
|
81986
82005
|
__export(exports_create, {
|
|
81987
|
-
run: () =>
|
|
82006
|
+
run: () => run7
|
|
81988
82007
|
});
|
|
81989
|
-
async function
|
|
82008
|
+
async function run7(args) {
|
|
81990
82009
|
const parsed = await tryParseArgs(args, {
|
|
81991
82010
|
title: { type: "string" },
|
|
81992
82011
|
author: { type: "string" },
|
|
@@ -81996,17 +82015,17 @@ async function run8(args) {
|
|
|
81996
82015
|
"dry-run": { type: "boolean" },
|
|
81997
82016
|
verbose: { type: "boolean", short: "v" },
|
|
81998
82017
|
help: { type: "boolean", short: "h" }
|
|
81999
|
-
},
|
|
82018
|
+
}, HELP7);
|
|
82000
82019
|
if (typeof parsed === "number")
|
|
82001
82020
|
return parsed;
|
|
82002
82021
|
if (parsed.values.help) {
|
|
82003
|
-
await writeStdout(
|
|
82022
|
+
await writeStdout(HELP7);
|
|
82004
82023
|
return EXIT2.OK;
|
|
82005
82024
|
}
|
|
82006
82025
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
82007
82026
|
const path2 = parsed.positionals[0];
|
|
82008
82027
|
if (!path2) {
|
|
82009
|
-
return fail("USAGE", "Missing FILE argument",
|
|
82028
|
+
return fail("USAGE", "Missing FILE argument", HELP7);
|
|
82010
82029
|
}
|
|
82011
82030
|
const text6 = parsed.values.text;
|
|
82012
82031
|
const fromPath = parsed.values.from;
|
|
@@ -82078,7 +82097,7 @@ async function applyMarkdownToBody(docxPath, markdownPath) {
|
|
|
82078
82097
|
await document4.save();
|
|
82079
82098
|
return { blockCount: blocks.length };
|
|
82080
82099
|
}
|
|
82081
|
-
var
|
|
82100
|
+
var HELP7 = `docx create \u2014 create a new minimal .docx
|
|
82082
82101
|
|
|
82083
82102
|
Usage:
|
|
82084
82103
|
docx create FILE [options]
|
|
@@ -82220,27 +82239,27 @@ var init_batch = __esm(() => {
|
|
|
82220
82239
|
// src/cli/delete/index.tsx
|
|
82221
82240
|
var exports_delete2 = {};
|
|
82222
82241
|
__export(exports_delete2, {
|
|
82223
|
-
run: () =>
|
|
82242
|
+
run: () => run8
|
|
82224
82243
|
});
|
|
82225
|
-
async function
|
|
82226
|
-
const parsed = await tryParseArgs(args,
|
|
82244
|
+
async function run8(args) {
|
|
82245
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC, HELP8);
|
|
82227
82246
|
if (typeof parsed === "number")
|
|
82228
82247
|
return parsed;
|
|
82229
82248
|
if (parsed.values.help) {
|
|
82230
|
-
await writeStdout(
|
|
82249
|
+
await writeStdout(HELP8);
|
|
82231
82250
|
return EXIT2.OK;
|
|
82232
82251
|
}
|
|
82233
82252
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
82234
82253
|
const filePath = parsed.positionals[0];
|
|
82235
82254
|
if (!filePath)
|
|
82236
|
-
return fail("USAGE", "Missing FILE argument",
|
|
82255
|
+
return fail("USAGE", "Missing FILE argument", HELP8);
|
|
82237
82256
|
const batchSource = parsed.values.batch;
|
|
82238
82257
|
if (batchSource !== undefined) {
|
|
82239
82258
|
return runDeleteBatch(filePath, batchSource, parsed.values);
|
|
82240
82259
|
}
|
|
82241
82260
|
const locator = parsed.values.at;
|
|
82242
82261
|
if (!locator)
|
|
82243
|
-
return fail("USAGE", "Missing --at LOCATOR (or --batch FILE)",
|
|
82262
|
+
return fail("USAGE", "Missing --at LOCATOR (or --batch FILE)", HELP8);
|
|
82244
82263
|
const opts = {
|
|
82245
82264
|
filePath,
|
|
82246
82265
|
locator,
|
|
@@ -82358,7 +82377,7 @@ function findBodyChildren(document4) {
|
|
|
82358
82377
|
return null;
|
|
82359
82378
|
return body.children;
|
|
82360
82379
|
}
|
|
82361
|
-
var
|
|
82380
|
+
var HELP8 = `docx delete \u2014 remove a block at a locator
|
|
82362
82381
|
|
|
82363
82382
|
Usage:
|
|
82364
82383
|
docx delete FILE --at LOCATOR [options]
|
|
@@ -82397,7 +82416,7 @@ Tracked behavior:
|
|
|
82397
82416
|
the paragraph mark as deleted (accept removes the paragraph by merging it
|
|
82398
82417
|
forward). Section deletion under tracking emits a [docx-cli] audit comment
|
|
82399
82418
|
on the owning paragraph if it has runs to anchor on; otherwise (sentinel
|
|
82400
|
-
|
|
82419
|
+
section sentinel paragraphs have no runs) the mutation is silent.
|
|
82401
82420
|
delete --at tN under tracking is rejected (tracked table-row deletion is
|
|
82402
82421
|
not supported).
|
|
82403
82422
|
|
|
@@ -82410,7 +82429,7 @@ Examples:
|
|
|
82410
82429
|
docx delete doc.docx --at t0
|
|
82411
82430
|
docx delete doc.docx --at s2
|
|
82412
82431
|
docx delete doc.docx --batch drop.jsonl # {"at":"p26"} per line
|
|
82413
|
-
`,
|
|
82432
|
+
`, OPTION_SPEC;
|
|
82414
82433
|
var init_delete2 = __esm(() => {
|
|
82415
82434
|
init_core2();
|
|
82416
82435
|
init_comments2();
|
|
@@ -82418,7 +82437,7 @@ var init_delete2 = __esm(() => {
|
|
|
82418
82437
|
init_replace();
|
|
82419
82438
|
init_respond();
|
|
82420
82439
|
init_batch();
|
|
82421
|
-
|
|
82440
|
+
OPTION_SPEC = {
|
|
82422
82441
|
at: { type: "string" },
|
|
82423
82442
|
batch: { type: "string" },
|
|
82424
82443
|
author: { type: "string" },
|
|
@@ -82427,6 +82446,42 @@ var init_delete2 = __esm(() => {
|
|
|
82427
82446
|
};
|
|
82428
82447
|
});
|
|
82429
82448
|
|
|
82449
|
+
// src/cli/edit/tabs.ts
|
|
82450
|
+
function parseTabsValue(value) {
|
|
82451
|
+
const normalized = value.trim().toLowerCase();
|
|
82452
|
+
if (normalized === "right" || normalized === "right-margin")
|
|
82453
|
+
return { kind: "right-margin" };
|
|
82454
|
+
if (normalized === "clear" || normalized === "none" || normalized === "off")
|
|
82455
|
+
return { kind: "clear" };
|
|
82456
|
+
const stops = [];
|
|
82457
|
+
for (const token of value.split(",")) {
|
|
82458
|
+
const match = token.trim().match(/^(left|right|center)@([\d.]+)in$/i);
|
|
82459
|
+
const align = (match?.[1] ?? "").toLowerCase();
|
|
82460
|
+
const inches = Number(match?.[2] ?? Number.NaN);
|
|
82461
|
+
if (!match || !TAB_ALIGNS.has(align) || !Number.isFinite(inches)) {
|
|
82462
|
+
return {
|
|
82463
|
+
error: `Invalid --tabs value: "${token.trim()}"`,
|
|
82464
|
+
hint: TABS_HINT
|
|
82465
|
+
};
|
|
82466
|
+
}
|
|
82467
|
+
stops.push({ align, pos: Math.round(inches * 1440) });
|
|
82468
|
+
}
|
|
82469
|
+
return { kind: "explicit", stops };
|
|
82470
|
+
}
|
|
82471
|
+
function resolveTabsDirective(directive, document4) {
|
|
82472
|
+
if (directive.kind === "clear")
|
|
82473
|
+
return [];
|
|
82474
|
+
if (directive.kind === "explicit")
|
|
82475
|
+
return directive.stops;
|
|
82476
|
+
const marginTwips = Math.round(getPageContentWidthEmu(document4) / 635);
|
|
82477
|
+
return [{ align: "right", pos: marginTwips }];
|
|
82478
|
+
}
|
|
82479
|
+
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`.";
|
|
82480
|
+
var init_tabs = __esm(() => {
|
|
82481
|
+
init_core2();
|
|
82482
|
+
TAB_ALIGNS = new Set(["left", "right", "center"]);
|
|
82483
|
+
});
|
|
82484
|
+
|
|
82430
82485
|
// src/cli/edit/batch.ts
|
|
82431
82486
|
async function runEditBatch(filePath, batchSource, values2) {
|
|
82432
82487
|
const conflicting = SINGLE_SHOT_FLAGS.find((flag) => values2[flag] !== undefined && values2[flag] !== false);
|
|
@@ -82512,13 +82567,14 @@ async function runEditBatch(filePath, batchSource, values2) {
|
|
|
82512
82567
|
async function resolveEntry2(document4, raw, index2, opts) {
|
|
82513
82568
|
const present = CONTENT_KEYS.filter((key) => raw[key] !== undefined);
|
|
82514
82569
|
const hasClear = raw.clear !== undefined;
|
|
82515
|
-
|
|
82516
|
-
|
|
82570
|
+
const hasProps = raw.style !== undefined || raw.alignment !== undefined || raw.tabs !== undefined;
|
|
82571
|
+
if (present.length === 0 && !hasClear && !hasProps) {
|
|
82572
|
+
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
82573
|
}
|
|
82518
82574
|
if (present.length > 1) {
|
|
82519
82575
|
throw new EntryError2("USAGE", `entry ${index2}: provide exactly one content field, got ${present.join(", ")}`);
|
|
82520
82576
|
}
|
|
82521
|
-
const kind = present[0] ?? "clear";
|
|
82577
|
+
const kind = present[0] ?? (hasClear ? "clear" : "props");
|
|
82522
82578
|
const at = raw.at;
|
|
82523
82579
|
if (typeof at !== "string" || at.length === 0) {
|
|
82524
82580
|
throw new EntryError2("USAGE", `entry ${index2}: "at" is required`);
|
|
@@ -82557,6 +82613,13 @@ async function resolveEntry2(document4, raw, index2, opts) {
|
|
|
82557
82613
|
async function buildApply(document4, raw, index2, kind, blockRef, span, opts) {
|
|
82558
82614
|
const author = typeof raw.author === "string" ? raw.author : opts.authorFlag;
|
|
82559
82615
|
const clearTags = raw.clear !== undefined ? resolveClearOrThrow(raw.clear, index2) : null;
|
|
82616
|
+
if (kind === "props") {
|
|
82617
|
+
if (span) {
|
|
82618
|
+
throw new EntryError2("USAGE", `entry ${index2}: a character span (${raw.at}) can't take "style"/"alignment" \u2014 restyle the whole paragraph (pN).`);
|
|
82619
|
+
}
|
|
82620
|
+
const paragraphOptions = readParagraphOptions(document4, raw, index2);
|
|
82621
|
+
return () => void new Edit(document4).paragraphProperties(blockRef, paragraphOptions);
|
|
82622
|
+
}
|
|
82560
82623
|
if (kind === "clear") {
|
|
82561
82624
|
const tags = clearTags ?? new Set;
|
|
82562
82625
|
return () => new Edit(document4).clearFormatting(blockRef, span, tags);
|
|
@@ -82591,9 +82654,12 @@ async function buildApply(document4, raw, index2, kind, blockRef, span, opts) {
|
|
|
82591
82654
|
};
|
|
82592
82655
|
}
|
|
82593
82656
|
async function buildWholeParagraphContent(document4, raw, index2, kind, blockRef, author, opts) {
|
|
82594
|
-
const paragraphOptions = readParagraphOptions(raw, index2);
|
|
82657
|
+
const paragraphOptions = readParagraphOptions(document4, raw, index2);
|
|
82595
82658
|
if (kind === "text") {
|
|
82596
82659
|
const text6 = requireString(raw.text, index2, "text");
|
|
82660
|
+
if (text6 === "") {
|
|
82661
|
+
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.');
|
|
82662
|
+
}
|
|
82597
82663
|
const format = readTextFormat(raw, index2);
|
|
82598
82664
|
return () => new Edit(document4).paragraph(blockRef, { kind: "text", text: text6, format, paragraphOptions }, {
|
|
82599
82665
|
authorFlag: author,
|
|
@@ -82691,8 +82757,8 @@ function rejectSpanFormatFlags(raw, index2) {
|
|
|
82691
82757
|
if (raw.color !== undefined || raw.bold !== undefined || raw.italic !== undefined) {
|
|
82692
82758
|
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
82759
|
}
|
|
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`);
|
|
82760
|
+
if (raw.style !== undefined || raw.alignment !== undefined || raw.tabs !== undefined) {
|
|
82761
|
+
throw new EntryError2("USAGE", `entry ${index2}: style/alignment/tabs apply to a whole paragraph, not a character span`);
|
|
82696
82762
|
}
|
|
82697
82763
|
}
|
|
82698
82764
|
function readTextFormat(raw, index2) {
|
|
@@ -82709,7 +82775,7 @@ function readTextFormat(raw, index2) {
|
|
|
82709
82775
|
out.italic = Boolean(raw.italic);
|
|
82710
82776
|
return out;
|
|
82711
82777
|
}
|
|
82712
|
-
function readParagraphOptions(raw, index2) {
|
|
82778
|
+
function readParagraphOptions(document4, raw, index2) {
|
|
82713
82779
|
const out = {};
|
|
82714
82780
|
if (raw.style !== undefined) {
|
|
82715
82781
|
if (typeof raw.style !== "string") {
|
|
@@ -82724,15 +82790,25 @@ function readParagraphOptions(raw, index2) {
|
|
|
82724
82790
|
}
|
|
82725
82791
|
out.alignment = alignment;
|
|
82726
82792
|
}
|
|
82793
|
+
if (raw.tabs !== undefined) {
|
|
82794
|
+
if (typeof raw.tabs !== "string") {
|
|
82795
|
+
throw new EntryError2("USAGE", `entry ${index2}: "tabs" must be a string`);
|
|
82796
|
+
}
|
|
82797
|
+
const parsed = parseTabsValue(raw.tabs);
|
|
82798
|
+
if ("error" in parsed) {
|
|
82799
|
+
throw new EntryError2("USAGE", `entry ${index2}: ${parsed.error}`, parsed.hint);
|
|
82800
|
+
}
|
|
82801
|
+
out.tabs = resolveTabsDirective(parsed, document4);
|
|
82802
|
+
}
|
|
82727
82803
|
return out;
|
|
82728
82804
|
}
|
|
82729
82805
|
function readRuns(value, index2) {
|
|
82730
82806
|
if (!Array.isArray(value)) {
|
|
82731
82807
|
throw new EntryError2("USAGE", `entry ${index2}: "runs" must be a JSON array of Run objects`);
|
|
82732
82808
|
}
|
|
82733
|
-
for (const
|
|
82734
|
-
if (
|
|
82735
|
-
const invalid = firstInvalidRunFormat(
|
|
82809
|
+
for (const run9 of value) {
|
|
82810
|
+
if (run9 !== null && typeof run9 === "object" && run9.type === "text") {
|
|
82811
|
+
const invalid = firstInvalidRunFormat(run9);
|
|
82736
82812
|
if (invalid) {
|
|
82737
82813
|
throw new EntryError2("USAGE", `entry ${index2}: invalid ${invalid.field} "${invalid.value}" in a run`, `Use ${invalid.valid}.`);
|
|
82738
82814
|
}
|
|
@@ -82761,6 +82837,7 @@ var init_batch2 = __esm(() => {
|
|
|
82761
82837
|
init_run_formatting();
|
|
82762
82838
|
init_parse_helpers();
|
|
82763
82839
|
init_respond();
|
|
82840
|
+
init_tabs();
|
|
82764
82841
|
SINGLE_SHOT_FLAGS = [
|
|
82765
82842
|
"at",
|
|
82766
82843
|
"text",
|
|
@@ -82778,6 +82855,7 @@ var init_batch2 = __esm(() => {
|
|
|
82778
82855
|
"type",
|
|
82779
82856
|
"style",
|
|
82780
82857
|
"alignment",
|
|
82858
|
+
"tabs",
|
|
82781
82859
|
"color",
|
|
82782
82860
|
"bold",
|
|
82783
82861
|
"italic"
|
|
@@ -82798,20 +82876,20 @@ var init_batch2 = __esm(() => {
|
|
|
82798
82876
|
// src/cli/edit/index.tsx
|
|
82799
82877
|
var exports_edit = {};
|
|
82800
82878
|
__export(exports_edit, {
|
|
82801
|
-
run: () =>
|
|
82879
|
+
run: () => run9
|
|
82802
82880
|
});
|
|
82803
|
-
async function
|
|
82804
|
-
const parsed = await tryParseArgs(args,
|
|
82881
|
+
async function run9(args) {
|
|
82882
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC2, HELP9);
|
|
82805
82883
|
if (typeof parsed === "number")
|
|
82806
82884
|
return parsed;
|
|
82807
82885
|
if (parsed.values.help) {
|
|
82808
|
-
await writeStdout(
|
|
82886
|
+
await writeStdout(HELP9);
|
|
82809
82887
|
return EXIT2.OK;
|
|
82810
82888
|
}
|
|
82811
82889
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
82812
82890
|
const filePath = parsed.positionals[0];
|
|
82813
82891
|
if (!filePath)
|
|
82814
|
-
return fail("USAGE", "Missing FILE argument",
|
|
82892
|
+
return fail("USAGE", "Missing FILE argument", HELP9);
|
|
82815
82893
|
const batchInput = parsed.values.batch;
|
|
82816
82894
|
if (batchInput !== undefined) {
|
|
82817
82895
|
return runEditBatch(filePath, batchInput, parsed.values);
|
|
@@ -82822,9 +82900,12 @@ async function run10(args) {
|
|
|
82822
82900
|
const document4 = await openOrFail(opts.filePath);
|
|
82823
82901
|
if (typeof document4 === "number")
|
|
82824
82902
|
return document4;
|
|
82903
|
+
if (opts.tabsDirective) {
|
|
82904
|
+
injectTabsIntoSpec(opts.spec, resolveTabsDirective(opts.tabsDirective, document4));
|
|
82905
|
+
}
|
|
82825
82906
|
if (isBlockRangeLocator2(opts.locator)) {
|
|
82826
82907
|
if (opts.spec.kind === "section") {
|
|
82827
|
-
return fail("USAGE", "Range locators (pN-pM) don't accept --columns/--type \u2014 use sN for section edits",
|
|
82908
|
+
return fail("USAGE", "Range locators (pN-pM) don't accept --columns/--type \u2014 use sN for section edits", HELP9);
|
|
82828
82909
|
}
|
|
82829
82910
|
return commitRangeEdit(document4, opts);
|
|
82830
82911
|
}
|
|
@@ -82857,14 +82938,14 @@ function spanLocatorTarget(locator) {
|
|
|
82857
82938
|
async function commitSpanEdit(document4, spanTarget, opts) {
|
|
82858
82939
|
const spec = opts.spec;
|
|
82859
82940
|
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.",
|
|
82941
|
+
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
82942
|
}
|
|
82862
82943
|
if (spec.kind === "text") {
|
|
82863
82944
|
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.",
|
|
82945
|
+
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
82946
|
}
|
|
82866
82947
|
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).",
|
|
82948
|
+
return fail("USAGE", "--style/--alignment apply to a whole paragraph, not a character span (pN:S-E).", HELP9);
|
|
82868
82949
|
}
|
|
82869
82950
|
}
|
|
82870
82951
|
const blockRef = await resolveBlockOrFail(document4, spanTarget.blockId);
|
|
@@ -82928,6 +83009,8 @@ async function commitBlockEdit(document4, blockRef, opts) {
|
|
|
82928
83009
|
});
|
|
82929
83010
|
} else if (opts.spec.kind === "clear") {
|
|
82930
83011
|
edit.clearFormatting(blockRef, null, opts.spec.tags);
|
|
83012
|
+
} else if (opts.spec.kind === "paragraphProps") {
|
|
83013
|
+
resultNode = edit.paragraphProperties(blockRef, opts.spec.paragraphOptions);
|
|
82931
83014
|
} else {
|
|
82932
83015
|
return fail("USAGE", "Unsupported edit spec for single-block locator");
|
|
82933
83016
|
}
|
|
@@ -82945,13 +83028,16 @@ async function commitBlockEdit(document4, blockRef, opts) {
|
|
|
82945
83028
|
}
|
|
82946
83029
|
async function commitRangeEdit(document4, opts) {
|
|
82947
83030
|
if (opts.spec.kind === "section") {
|
|
82948
|
-
return fail("USAGE", "Section edits don't support range locators",
|
|
83031
|
+
return fail("USAGE", "Section edits don't support range locators", HELP9);
|
|
82949
83032
|
}
|
|
82950
83033
|
if (opts.spec.kind === "task") {
|
|
82951
|
-
return fail("USAGE", "--task takes a single paragraph locator (pN), not a range",
|
|
83034
|
+
return fail("USAGE", "--task takes a single paragraph locator (pN), not a range", HELP9);
|
|
82952
83035
|
}
|
|
82953
83036
|
if (opts.spec.kind === "equation") {
|
|
82954
|
-
return fail("USAGE", "--equation takes a single equation locator (eqN), not a paragraph range",
|
|
83037
|
+
return fail("USAGE", "--equation takes a single equation locator (eqN), not a paragraph range", HELP9);
|
|
83038
|
+
}
|
|
83039
|
+
if (opts.spec.kind === "paragraphProps") {
|
|
83040
|
+
return commitRangeProps(document4, opts, opts.spec.paragraphOptions);
|
|
82955
83041
|
}
|
|
82956
83042
|
const rangeRef = await resolveBlockRangeOrFail(document4, opts.locator);
|
|
82957
83043
|
if (typeof rangeRef === "number")
|
|
@@ -82983,6 +83069,53 @@ async function commitRangeEdit(document4, opts) {
|
|
|
82983
83069
|
await document4.save(opts.outputPath);
|
|
82984
83070
|
return emitEditAck(opts);
|
|
82985
83071
|
}
|
|
83072
|
+
async function commitRangeProps(document4, opts, options) {
|
|
83073
|
+
const rangeRef = await resolveBlockRangeOrFail(document4, opts.locator);
|
|
83074
|
+
if (typeof rangeRef === "number")
|
|
83075
|
+
return rangeRef;
|
|
83076
|
+
if (opts.dryRun)
|
|
83077
|
+
return respondDryRun2(opts);
|
|
83078
|
+
let applied = 0;
|
|
83079
|
+
try {
|
|
83080
|
+
const edit = new Edit(document4);
|
|
83081
|
+
for (let index2 = rangeRef.startIndex;index2 <= rangeRef.endIndex; index2++) {
|
|
83082
|
+
const node2 = rangeRef.parent[index2];
|
|
83083
|
+
if (!node2 || node2.tag !== "w:p")
|
|
83084
|
+
continue;
|
|
83085
|
+
const perParagraph = scopeRangeProps(node2, options);
|
|
83086
|
+
if (!perParagraph)
|
|
83087
|
+
continue;
|
|
83088
|
+
edit.paragraphProperties({ node: node2, parent: rangeRef.parent }, perParagraph);
|
|
83089
|
+
applied++;
|
|
83090
|
+
}
|
|
83091
|
+
} catch (error) {
|
|
83092
|
+
if (error instanceof EditError) {
|
|
83093
|
+
return fail(error.code, error.message, error.hint);
|
|
83094
|
+
}
|
|
83095
|
+
throw error;
|
|
83096
|
+
}
|
|
83097
|
+
if (applied === 0) {
|
|
83098
|
+
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.`);
|
|
83099
|
+
}
|
|
83100
|
+
await document4.save(opts.outputPath);
|
|
83101
|
+
return emitEditAck(opts);
|
|
83102
|
+
}
|
|
83103
|
+
function scopeRangeProps(node2, options) {
|
|
83104
|
+
const out = {};
|
|
83105
|
+
if (options.style !== undefined)
|
|
83106
|
+
out.style = options.style;
|
|
83107
|
+
if (options.alignment !== undefined)
|
|
83108
|
+
out.alignment = options.alignment;
|
|
83109
|
+
if (options.tabs !== undefined && paragraphHasTabStops(node2)) {
|
|
83110
|
+
out.tabs = options.tabs;
|
|
83111
|
+
}
|
|
83112
|
+
if (out.style === undefined && out.alignment === undefined && out.tabs === undefined)
|
|
83113
|
+
return null;
|
|
83114
|
+
return out;
|
|
83115
|
+
}
|
|
83116
|
+
function paragraphHasTabStops(node2) {
|
|
83117
|
+
return node2.findChild("w:pPr")?.findChild("w:tabs") !== undefined;
|
|
83118
|
+
}
|
|
82986
83119
|
async function commitEquationEdit(document4, spec, opts) {
|
|
82987
83120
|
if (spec.latex === undefined && spec.display === undefined) {
|
|
82988
83121
|
return fail("USAGE", "--equation requires --equation NEW_LATEX, --display, or --inline");
|
|
@@ -83013,10 +83146,17 @@ async function commitEquationEdit(document4, spec, opts) {
|
|
|
83013
83146
|
async function validateSingleShotOptions(filePath, values2) {
|
|
83014
83147
|
const locator = values2.at;
|
|
83015
83148
|
if (!locator)
|
|
83016
|
-
return fail("USAGE", "Missing --at LOCATOR",
|
|
83149
|
+
return fail("USAGE", "Missing --at LOCATOR", HELP9);
|
|
83017
83150
|
const paragraphOptions = await parseParagraphOptions(values2);
|
|
83018
83151
|
if (typeof paragraphOptions === "number")
|
|
83019
83152
|
return paragraphOptions;
|
|
83153
|
+
let tabsDirective;
|
|
83154
|
+
if (values2.tabs !== undefined) {
|
|
83155
|
+
const parsed = parseTabsValue(values2.tabs);
|
|
83156
|
+
if ("error" in parsed)
|
|
83157
|
+
return fail("USAGE", parsed.error, parsed.hint);
|
|
83158
|
+
tabsDirective = parsed;
|
|
83159
|
+
}
|
|
83020
83160
|
const isSectionLocator = /^s\d+$/.test(locator);
|
|
83021
83161
|
const spec = isSectionLocator ? await validateSectionEdit(values2) : await validateParagraphEdit(values2, paragraphOptions);
|
|
83022
83162
|
if (typeof spec === "number")
|
|
@@ -83037,15 +83177,16 @@ async function validateSingleShotOptions(filePath, values2) {
|
|
|
83037
83177
|
outputPath: values2.output,
|
|
83038
83178
|
dryRun: Boolean(values2["dry-run"]),
|
|
83039
83179
|
noFormatting: Boolean(values2["no-formatting"]),
|
|
83040
|
-
...clearTags ? { clearTags } : {}
|
|
83180
|
+
...clearTags ? { clearTags } : {},
|
|
83181
|
+
...tabsDirective ? { tabsDirective } : {}
|
|
83041
83182
|
};
|
|
83042
83183
|
}
|
|
83043
83184
|
async function validateSectionEdit(values2) {
|
|
83044
83185
|
if (values2.text !== undefined || values2.runs !== undefined) {
|
|
83045
|
-
return fail("USAGE", "Section locators (sN) take --columns and --type, not --text/--runs",
|
|
83186
|
+
return fail("USAGE", "Section locators (sN) take --columns and --type, not --text/--runs", HELP9);
|
|
83046
83187
|
}
|
|
83047
83188
|
if (values2.columns === undefined && values2.type === undefined) {
|
|
83048
|
-
return fail("USAGE", "Section edit requires --columns and/or --type",
|
|
83189
|
+
return fail("USAGE", "Section edit requires --columns and/or --type", HELP9);
|
|
83049
83190
|
}
|
|
83050
83191
|
const sectionFlags = await parseSectionFlags(values2);
|
|
83051
83192
|
if (typeof sectionFlags === "number")
|
|
@@ -83056,22 +83197,22 @@ async function parseClearTagsOrFail(clearFlag) {
|
|
|
83056
83197
|
const raw = Array.isArray(clearFlag) ? clearFlag : [clearFlag];
|
|
83057
83198
|
const names = raw.flatMap((entry) => entry.split(",")).map((name) => name.trim().toLowerCase()).filter(Boolean);
|
|
83058
83199
|
if (names.length === 0) {
|
|
83059
|
-
return fail("USAGE", "--clear needs an attribute name, or 'all'",
|
|
83200
|
+
return fail("USAGE", "--clear needs an attribute name, or 'all'", HELP9);
|
|
83060
83201
|
}
|
|
83061
83202
|
const tags = resolveClearTags(names);
|
|
83062
83203
|
if (!tags) {
|
|
83063
|
-
return fail("USAGE", `--clear: unknown attribute in "${raw.join(",")}". Valid: ${CLEARABLE_ATTRS.join(", ")}, all`,
|
|
83204
|
+
return fail("USAGE", `--clear: unknown attribute in "${raw.join(",")}". Valid: ${CLEARABLE_ATTRS.join(", ")}, all`, HELP9);
|
|
83064
83205
|
}
|
|
83065
83206
|
return tags;
|
|
83066
83207
|
}
|
|
83067
83208
|
async function validateParagraphEdit(values2, paragraphOptions) {
|
|
83068
83209
|
if (values2.columns !== undefined || values2.type !== undefined) {
|
|
83069
|
-
return fail("USAGE", "--columns and --type require a section locator (sN)",
|
|
83210
|
+
return fail("USAGE", "--columns and --type require a section locator (sN)", HELP9);
|
|
83070
83211
|
}
|
|
83071
83212
|
const clearFlag = values2.clear;
|
|
83072
83213
|
if (clearFlag !== undefined) {
|
|
83073
83214
|
if (values2.equation !== undefined || values2.display === true || values2.inline === true) {
|
|
83074
|
-
return fail("USAGE", "--clear can't be combined with --equation/--display/--inline",
|
|
83215
|
+
return fail("USAGE", "--clear can't be combined with --equation/--display/--inline", HELP9);
|
|
83075
83216
|
}
|
|
83076
83217
|
const hasContent = [
|
|
83077
83218
|
"text",
|
|
@@ -83108,10 +83249,10 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83108
83249
|
taskFlag !== undefined
|
|
83109
83250
|
].filter(Boolean).length;
|
|
83110
83251
|
if (otherContent > 0) {
|
|
83111
|
-
return fail("USAGE", "--equation / --display / --inline cannot be combined with --text/--runs/--code/--code-file/--task",
|
|
83252
|
+
return fail("USAGE", "--equation / --display / --inline cannot be combined with --text/--runs/--code/--code-file/--task", HELP9);
|
|
83112
83253
|
}
|
|
83113
83254
|
if (displayFlag && inlineFlag) {
|
|
83114
|
-
return fail("USAGE", "--display and --inline are mutually exclusive",
|
|
83255
|
+
return fail("USAGE", "--display and --inline are mutually exclusive", HELP9);
|
|
83115
83256
|
}
|
|
83116
83257
|
const displayMode = displayFlag ? true : inlineFlag ? false : undefined;
|
|
83117
83258
|
return {
|
|
@@ -83129,11 +83270,11 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83129
83270
|
codeFile !== undefined
|
|
83130
83271
|
].filter(Boolean).length;
|
|
83131
83272
|
if (otherFlags > 0) {
|
|
83132
|
-
return fail("USAGE", "--task cannot be combined with --text, --runs, --code, or --code-file",
|
|
83273
|
+
return fail("USAGE", "--task cannot be combined with --text, --runs, --code, or --code-file", HELP9);
|
|
83133
83274
|
}
|
|
83134
83275
|
const checked = parseTaskFlag(taskFlag);
|
|
83135
83276
|
if (checked === null) {
|
|
83136
|
-
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskFlag}"`,
|
|
83277
|
+
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskFlag}"`, HELP9);
|
|
83137
83278
|
}
|
|
83138
83279
|
return { kind: "task", checked };
|
|
83139
83280
|
}
|
|
@@ -83148,15 +83289,29 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83148
83289
|
markdownFile !== undefined
|
|
83149
83290
|
].filter(Boolean).length;
|
|
83150
83291
|
if (contentFlags === 0) {
|
|
83151
|
-
|
|
83292
|
+
if (paragraphOptions.style || paragraphOptions.alignment || values2.tabs !== undefined) {
|
|
83293
|
+
return { kind: "paragraphProps", paragraphOptions };
|
|
83294
|
+
}
|
|
83295
|
+
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
83296
|
}
|
|
83153
83297
|
if (contentFlags > 1) {
|
|
83154
|
-
return fail("USAGE", "Pass only one of --text, --runs, --code, --code-file, --markdown, --markdown-file",
|
|
83298
|
+
return fail("USAGE", "Pass only one of --text, --runs, --code, --code-file, --markdown, --markdown-file", HELP9);
|
|
83155
83299
|
}
|
|
83156
83300
|
if (language !== undefined && codeInline === undefined && codeFile === undefined) {
|
|
83157
|
-
return fail("USAGE", "--language requires --code or --code-file",
|
|
83301
|
+
return fail("USAGE", "--language requires --code or --code-file", HELP9);
|
|
83158
83302
|
}
|
|
83159
83303
|
if (text6 !== undefined) {
|
|
83304
|
+
const at = values2.at;
|
|
83305
|
+
if (text6 === "" && !(at && spanLocatorTarget(at))) {
|
|
83306
|
+
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:
|
|
83307
|
+
${HELP9}`);
|
|
83308
|
+
}
|
|
83309
|
+
const rejected = await rejectMarkdownInText(text6, HELP9);
|
|
83310
|
+
if (typeof rejected === "number")
|
|
83311
|
+
return rejected;
|
|
83312
|
+
const mangled = await rejectShellMangledValue(text6, HELP9, "--text");
|
|
83313
|
+
if (typeof mangled === "number")
|
|
83314
|
+
return mangled;
|
|
83160
83315
|
return {
|
|
83161
83316
|
kind: "text",
|
|
83162
83317
|
text: text6,
|
|
@@ -83182,7 +83337,7 @@ async function validateParagraphEdit(values2, paragraphOptions) {
|
|
|
83182
83337
|
if (markdownInline !== undefined || markdownFile !== undefined) {
|
|
83183
83338
|
const conflict = MARKDOWN_INCOMPATIBLE_FLAGS.find((flag) => values2[flag] !== undefined);
|
|
83184
83339
|
if (conflict) {
|
|
83185
|
-
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`,
|
|
83340
|
+
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`, HELP9);
|
|
83186
83341
|
}
|
|
83187
83342
|
const source2 = markdownInline !== undefined ? markdownInline : await loadMarkdownFile(markdownFile);
|
|
83188
83343
|
if (typeof source2 === "number")
|
|
@@ -83239,6 +83394,11 @@ async function parseParagraphOptions(values2) {
|
|
|
83239
83394
|
}
|
|
83240
83395
|
return out;
|
|
83241
83396
|
}
|
|
83397
|
+
function injectTabsIntoSpec(spec, tabs) {
|
|
83398
|
+
if (spec.kind === "text" || spec.kind === "runs" || spec.kind === "code" || spec.kind === "markdown" || spec.kind === "paragraphProps") {
|
|
83399
|
+
spec.paragraphOptions.tabs = tabs;
|
|
83400
|
+
}
|
|
83401
|
+
}
|
|
83242
83402
|
async function respondDryRun2(opts) {
|
|
83243
83403
|
await respond({
|
|
83244
83404
|
operation: "edit",
|
|
@@ -83258,13 +83418,14 @@ async function emitEditAck(opts) {
|
|
|
83258
83418
|
});
|
|
83259
83419
|
return EXIT2.OK;
|
|
83260
83420
|
}
|
|
83261
|
-
var AT_FORMS2,
|
|
83421
|
+
var AT_FORMS2, HELP9, MARKDOWN_INCOMPATIBLE_FLAGS, OPTION_SPEC2;
|
|
83262
83422
|
var init_edit2 = __esm(() => {
|
|
83263
83423
|
init_core2();
|
|
83264
83424
|
init_equation();
|
|
83265
83425
|
init_parse_helpers();
|
|
83266
83426
|
init_respond();
|
|
83267
83427
|
init_batch2();
|
|
83428
|
+
init_tabs();
|
|
83268
83429
|
AT_FORMS2 = describeForms([
|
|
83269
83430
|
"paragraph",
|
|
83270
83431
|
"span",
|
|
@@ -83274,7 +83435,7 @@ var init_edit2 = __esm(() => {
|
|
|
83274
83435
|
"section",
|
|
83275
83436
|
"equation"
|
|
83276
83437
|
], " ");
|
|
83277
|
-
|
|
83438
|
+
HELP9 = `docx edit \u2014 replace a paragraph (or paragraph range), a section, or an equation
|
|
83278
83439
|
|
|
83279
83440
|
Usage:
|
|
83280
83441
|
docx edit FILE --at LOCATOR <content> [options]
|
|
@@ -83291,7 +83452,8 @@ ${AT_FORMS2}
|
|
|
83291
83452
|
inheriting the existing run's formatting \u2014 paste a locator
|
|
83292
83453
|
straight from \`docx find\`. See \`docx info locators\`.
|
|
83293
83454
|
|
|
83294
|
-
Paragraph content (one required for paragraph / range locators
|
|
83455
|
+
Paragraph content (one required for paragraph / range locators \u2014 UNLESS you pass
|
|
83456
|
+
only --style/--alignment below, which restyle the paragraph in place):
|
|
83295
83457
|
--text TEXT Replace with a single-run paragraph
|
|
83296
83458
|
--runs JSON Replace with custom runs (Run[] JSON)
|
|
83297
83459
|
--code TEXT Replace with a code block \u2014 newlines split into one
|
|
@@ -83334,6 +83496,25 @@ Equation editing (requires --at eqN):
|
|
|
83334
83496
|
Paragraph options:
|
|
83335
83497
|
--style NAME Paragraph style (e.g., Heading1)
|
|
83336
83498
|
--alignment ALIGN left | center | right | justify
|
|
83499
|
+
--tabs SPEC Replace the paragraph's tab stops. SPEC is:
|
|
83500
|
+
right \u2014 a single RIGHT tab flush at the text margin.
|
|
83501
|
+
This is the CURE for the \`docx:layout \u2026 warn=\u2026\`
|
|
83502
|
+
hint \`read\` prints on a line whose trailing
|
|
83503
|
+
content sits on a fixed LEFT tab: a long value
|
|
83504
|
+
(e.g. "San Francisco, CA") overflows the margin
|
|
83505
|
+
and WRAPS to a second line. A right tab at the
|
|
83506
|
+
margin right-aligns it instead, so it never wraps.
|
|
83507
|
+
clear \u2014 remove the paragraph's tab stops.
|
|
83508
|
+
<list> \u2014 explicit stops, e.g. \`right@7.5in\` or
|
|
83509
|
+
\`left@1in,right@7.5in\` (ALIGN@POSin, comma list).
|
|
83510
|
+
Pass any of --style/--alignment/--tabs ALONE (no content flag) to adjust the
|
|
83511
|
+
paragraph in place, keeping its text/runs: \`docx edit doc.docx --at p4 --style
|
|
83512
|
+
Heading1\`, \`docx edit doc.docx --at p9 --tabs right\`. --tabs also rides along
|
|
83513
|
+
with --text (fill the line AND fix its tab in one call), and works per-entry in
|
|
83514
|
+
--batch ({"at":"p9","text":"Harvard University\\tCambridge, MA","tabs":"right"}).
|
|
83515
|
+
ONE-CALL cure: a RANGE locator fixes every wrapping tab line at once \u2014
|
|
83516
|
+
\`docx edit doc.docx --at p9-p38 --tabs right\` (the exact "fix-all" command
|
|
83517
|
+
\`read\` prints at the top when lines wrap; it skips paragraphs with no tab stops).
|
|
83337
83518
|
|
|
83338
83519
|
Run options (only with --text):
|
|
83339
83520
|
--color HEX Run color, hex (e.g., 800080 for purple)
|
|
@@ -83413,7 +83594,7 @@ Batch JSONL example (one edit per line):
|
|
|
83413
83594
|
{"at": "p1", "markdown": "## Revised heading"}
|
|
83414
83595
|
`;
|
|
83415
83596
|
MARKDOWN_INCOMPATIBLE_FLAGS = ["style", "alignment"];
|
|
83416
|
-
|
|
83597
|
+
OPTION_SPEC2 = {
|
|
83417
83598
|
at: { type: "string" },
|
|
83418
83599
|
batch: { type: "string" },
|
|
83419
83600
|
text: { type: "string" },
|
|
@@ -83432,6 +83613,7 @@ Batch JSONL example (one edit per line):
|
|
|
83432
83613
|
type: { type: "string" },
|
|
83433
83614
|
style: { type: "string" },
|
|
83434
83615
|
alignment: { type: "string" },
|
|
83616
|
+
tabs: { type: "string" },
|
|
83435
83617
|
color: { type: "string" },
|
|
83436
83618
|
bold: { type: "boolean" },
|
|
83437
83619
|
italic: { type: "boolean" },
|
|
@@ -83446,7 +83628,7 @@ Batch JSONL example (one edit per line):
|
|
|
83446
83628
|
var exports_add2 = {};
|
|
83447
83629
|
__export(exports_add2, {
|
|
83448
83630
|
runAddNote: () => runAddNote,
|
|
83449
|
-
run: () =>
|
|
83631
|
+
run: () => run10
|
|
83450
83632
|
});
|
|
83451
83633
|
function helpFor(kind) {
|
|
83452
83634
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -83712,8 +83894,8 @@ function splitMarkdownBlocks(blocks) {
|
|
|
83712
83894
|
}
|
|
83713
83895
|
function runsToXml(runs) {
|
|
83714
83896
|
const out = [];
|
|
83715
|
-
for (const
|
|
83716
|
-
const element = RunElement({ run:
|
|
83897
|
+
for (const run10 of runs) {
|
|
83898
|
+
const element = RunElement({ run: run10 });
|
|
83717
83899
|
if (element)
|
|
83718
83900
|
out.push(element);
|
|
83719
83901
|
}
|
|
@@ -83751,7 +83933,7 @@ function parseAnchor(input) {
|
|
|
83751
83933
|
}
|
|
83752
83934
|
return null;
|
|
83753
83935
|
}
|
|
83754
|
-
async function
|
|
83936
|
+
async function run10(args) {
|
|
83755
83937
|
return runAddNote(args, "footnote");
|
|
83756
83938
|
}
|
|
83757
83939
|
var ANCHOR_FORMS;
|
|
@@ -83773,7 +83955,7 @@ var init_add2 = __esm(() => {
|
|
|
83773
83955
|
var exports_delete3 = {};
|
|
83774
83956
|
__export(exports_delete3, {
|
|
83775
83957
|
runDeleteNote: () => runDeleteNote,
|
|
83776
|
-
run: () =>
|
|
83958
|
+
run: () => run11
|
|
83777
83959
|
});
|
|
83778
83960
|
function helpFor2(kind) {
|
|
83779
83961
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -83882,7 +84064,7 @@ async function runDeleteNote(args, kind) {
|
|
|
83882
84064
|
});
|
|
83883
84065
|
return EXIT2.OK;
|
|
83884
84066
|
}
|
|
83885
|
-
async function
|
|
84067
|
+
async function run11(args) {
|
|
83886
84068
|
return runDeleteNote(args, "footnote");
|
|
83887
84069
|
}
|
|
83888
84070
|
var init_delete3 = __esm(() => {
|
|
@@ -83895,7 +84077,7 @@ var init_delete3 = __esm(() => {
|
|
|
83895
84077
|
var exports_edit2 = {};
|
|
83896
84078
|
__export(exports_edit2, {
|
|
83897
84079
|
runEditNote: () => runEditNote,
|
|
83898
|
-
run: () =>
|
|
84080
|
+
run: () => run12
|
|
83899
84081
|
});
|
|
83900
84082
|
function helpFor3(kind) {
|
|
83901
84083
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -84086,8 +84268,8 @@ function splitMarkdownBlocks2(blocks) {
|
|
|
84086
84268
|
}
|
|
84087
84269
|
function runsToXml2(runs) {
|
|
84088
84270
|
const out = [];
|
|
84089
|
-
for (const
|
|
84090
|
-
const element = RunElement({ run:
|
|
84271
|
+
for (const run12 of runs) {
|
|
84272
|
+
const element = RunElement({ run: run12 });
|
|
84091
84273
|
if (element)
|
|
84092
84274
|
out.push(element);
|
|
84093
84275
|
}
|
|
@@ -84136,7 +84318,7 @@ function NoteParagraph({
|
|
|
84136
84318
|
]
|
|
84137
84319
|
}, undefined, true, undefined, this);
|
|
84138
84320
|
}
|
|
84139
|
-
async function
|
|
84321
|
+
async function run12(args) {
|
|
84140
84322
|
return runEditNote(args, "footnote");
|
|
84141
84323
|
}
|
|
84142
84324
|
var init_edit3 = __esm(() => {
|
|
@@ -84154,7 +84336,7 @@ var init_edit3 = __esm(() => {
|
|
|
84154
84336
|
var exports_list2 = {};
|
|
84155
84337
|
__export(exports_list2, {
|
|
84156
84338
|
runListNotes: () => runListNotes,
|
|
84157
|
-
run: () =>
|
|
84339
|
+
run: () => run13
|
|
84158
84340
|
});
|
|
84159
84341
|
function helpFor4(kind) {
|
|
84160
84342
|
const verb = kind === "footnote" ? "footnotes" : "endnotes";
|
|
@@ -84196,7 +84378,7 @@ async function runListNotes(args, kind) {
|
|
|
84196
84378
|
await respond(notes);
|
|
84197
84379
|
return EXIT2.OK;
|
|
84198
84380
|
}
|
|
84199
|
-
async function
|
|
84381
|
+
async function run13(args) {
|
|
84200
84382
|
return runListNotes(args, "footnote");
|
|
84201
84383
|
}
|
|
84202
84384
|
var init_list4 = __esm(() => {
|
|
@@ -84206,12 +84388,12 @@ var init_list4 = __esm(() => {
|
|
|
84206
84388
|
// src/cli/endnotes/index.ts
|
|
84207
84389
|
var exports_endnotes = {};
|
|
84208
84390
|
__export(exports_endnotes, {
|
|
84209
|
-
run: () =>
|
|
84391
|
+
run: () => run14
|
|
84210
84392
|
});
|
|
84211
|
-
async function
|
|
84393
|
+
async function run14(args) {
|
|
84212
84394
|
const verb = args[0];
|
|
84213
84395
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
84214
|
-
await writeStdout(
|
|
84396
|
+
await writeStdout(HELP10);
|
|
84215
84397
|
return verb ? 0 : 2;
|
|
84216
84398
|
}
|
|
84217
84399
|
const handler = SUBCOMMANDS2[verb];
|
|
@@ -84220,7 +84402,7 @@ async function run15(args) {
|
|
|
84220
84402
|
}
|
|
84221
84403
|
return handler(args.slice(1));
|
|
84222
84404
|
}
|
|
84223
|
-
var SUBCOMMANDS2,
|
|
84405
|
+
var SUBCOMMANDS2, HELP10 = `docx endnotes \u2014 author endnotes
|
|
84224
84406
|
|
|
84225
84407
|
Usage:
|
|
84226
84408
|
docx endnotes <verb> FILE [options]
|
|
@@ -84250,7 +84432,7 @@ var init_endnotes = __esm(() => {
|
|
|
84250
84432
|
// src/cli/find/index.ts
|
|
84251
84433
|
var exports_find = {};
|
|
84252
84434
|
__export(exports_find, {
|
|
84253
|
-
run: () =>
|
|
84435
|
+
run: () => run15
|
|
84254
84436
|
});
|
|
84255
84437
|
function withBareHighlightAsAny(args) {
|
|
84256
84438
|
const out = [];
|
|
@@ -84272,7 +84454,7 @@ function withBareHighlightAsAny(args) {
|
|
|
84272
84454
|
}
|
|
84273
84455
|
return out;
|
|
84274
84456
|
}
|
|
84275
|
-
async function
|
|
84457
|
+
async function run15(args) {
|
|
84276
84458
|
const parsed = await tryParseArgs(withBareHighlightAsAny(args), {
|
|
84277
84459
|
regex: { type: "boolean" },
|
|
84278
84460
|
"ignore-case": { type: "boolean" },
|
|
@@ -84288,17 +84470,17 @@ async function run16(args) {
|
|
|
84288
84470
|
underline: { type: "boolean" },
|
|
84289
84471
|
json: { type: "boolean" },
|
|
84290
84472
|
help: { type: "boolean", short: "h" }
|
|
84291
|
-
},
|
|
84473
|
+
}, HELP11);
|
|
84292
84474
|
if (typeof parsed === "number")
|
|
84293
84475
|
return parsed;
|
|
84294
84476
|
if (parsed.values.help) {
|
|
84295
|
-
await writeStdout(
|
|
84477
|
+
await writeStdout(HELP11);
|
|
84296
84478
|
return EXIT2.OK;
|
|
84297
84479
|
}
|
|
84298
84480
|
const path2 = parsed.positionals[0];
|
|
84299
84481
|
const query = parsed.positionals[1];
|
|
84300
84482
|
if (!path2)
|
|
84301
|
-
return fail("USAGE", "Missing FILE argument",
|
|
84483
|
+
return fail("USAGE", "Missing FILE argument", HELP11);
|
|
84302
84484
|
const formatFilter = {};
|
|
84303
84485
|
if (parsed.values.highlight !== undefined)
|
|
84304
84486
|
formatFilter.highlight = parsed.values.highlight;
|
|
@@ -84312,10 +84494,10 @@ async function run16(args) {
|
|
|
84312
84494
|
formatFilter.underline = true;
|
|
84313
84495
|
const hasFormatFilter = Object.keys(formatFilter).length > 0;
|
|
84314
84496
|
if (query == null && !hasFormatFilter) {
|
|
84315
|
-
return fail("USAGE", "Missing QUERY (or a --highlight/--color/--bold/--italic/--underline filter)",
|
|
84497
|
+
return fail("USAGE", "Missing QUERY (or a --highlight/--color/--bold/--italic/--underline filter)", HELP11);
|
|
84316
84498
|
}
|
|
84317
84499
|
if (query != null && hasFormatFilter) {
|
|
84318
|
-
return fail("USAGE", "Pass a text QUERY or formatting filters (--highlight/--color/...), not both",
|
|
84500
|
+
return fail("USAGE", "Pass a text QUERY or formatting filters (--highlight/--color/...), not both", HELP11);
|
|
84319
84501
|
}
|
|
84320
84502
|
const ignoreCase = Boolean(parsed.values["ignore-case"]);
|
|
84321
84503
|
const useRegex = Boolean(parsed.values.regex);
|
|
@@ -84390,7 +84572,7 @@ async function run16(args) {
|
|
|
84390
84572
|
}
|
|
84391
84573
|
return EXIT2.OK;
|
|
84392
84574
|
}
|
|
84393
|
-
var
|
|
84575
|
+
var HELP11 = `docx find \u2014 locate text spans and return their locators
|
|
84394
84576
|
|
|
84395
84577
|
Usage:
|
|
84396
84578
|
docx find FILE QUERY [options]
|
|
@@ -84463,12 +84645,12 @@ var init_find2 = __esm(() => {
|
|
|
84463
84645
|
// src/cli/footnotes/index.ts
|
|
84464
84646
|
var exports_footnotes = {};
|
|
84465
84647
|
__export(exports_footnotes, {
|
|
84466
|
-
run: () =>
|
|
84648
|
+
run: () => run16
|
|
84467
84649
|
});
|
|
84468
|
-
async function
|
|
84650
|
+
async function run16(args) {
|
|
84469
84651
|
const verb = args[0];
|
|
84470
84652
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
84471
|
-
await writeStdout(
|
|
84653
|
+
await writeStdout(HELP12);
|
|
84472
84654
|
return verb ? 0 : 2;
|
|
84473
84655
|
}
|
|
84474
84656
|
const loader = SUBCOMMANDS3[verb];
|
|
@@ -84478,7 +84660,7 @@ async function run17(args) {
|
|
|
84478
84660
|
const module_ = await loader();
|
|
84479
84661
|
return module_.run(args.slice(1));
|
|
84480
84662
|
}
|
|
84481
|
-
var SUBCOMMANDS3,
|
|
84663
|
+
var SUBCOMMANDS3, HELP12 = `docx footnotes \u2014 author footnotes
|
|
84482
84664
|
|
|
84483
84665
|
Usage:
|
|
84484
84666
|
docx footnotes <verb> FILE [options]
|
|
@@ -84502,7 +84684,7 @@ var init_footnotes = __esm(() => {
|
|
|
84502
84684
|
});
|
|
84503
84685
|
|
|
84504
84686
|
// src/core/hyperlinks/wrap.tsx
|
|
84505
|
-
function wrapSpanInHyperlink(paragraph2, span, relationshipId) {
|
|
84687
|
+
function wrapSpanInHyperlink(paragraph2, span, relationshipId, applyStyle = true) {
|
|
84506
84688
|
if (span.start >= span.end) {
|
|
84507
84689
|
throw new HyperlinkWrapError(`Empty or inverted span ${span.start}-${span.end}`);
|
|
84508
84690
|
}
|
|
@@ -84513,6 +84695,9 @@ function wrapSpanInHyperlink(paragraph2, span, relationshipId) {
|
|
|
84513
84695
|
const placeWrapper = () => {
|
|
84514
84696
|
if (placed || wrappedRuns.length === 0)
|
|
84515
84697
|
return;
|
|
84698
|
+
if (applyStyle)
|
|
84699
|
+
for (const run17 of wrappedRuns)
|
|
84700
|
+
applyHyperlinkRunStyle(run17);
|
|
84516
84701
|
newChildren.push(hyperlinkWrapper(relationshipId, wrappedRuns));
|
|
84517
84702
|
wrappedRuns.length = 0;
|
|
84518
84703
|
placed = true;
|
|
@@ -84573,6 +84758,20 @@ function hyperlinkWrapper(relationshipId, runs) {
|
|
|
84573
84758
|
children: runs
|
|
84574
84759
|
}, undefined, false, undefined, this);
|
|
84575
84760
|
}
|
|
84761
|
+
function applyHyperlinkRunStyle(run17) {
|
|
84762
|
+
if (run17.tag !== "w:r")
|
|
84763
|
+
return;
|
|
84764
|
+
let rPr = run17.findChild("w:rPr");
|
|
84765
|
+
if (!rPr) {
|
|
84766
|
+
rPr = /* @__PURE__ */ jsxDEV(w.rPr, {}, undefined, false, undefined, this);
|
|
84767
|
+
run17.children.unshift(rPr);
|
|
84768
|
+
}
|
|
84769
|
+
if (rPr.findChild("w:rStyle"))
|
|
84770
|
+
return;
|
|
84771
|
+
rPr.children.unshift(/* @__PURE__ */ jsxDEV(w.rStyle, {
|
|
84772
|
+
"w-val": "Hyperlink"
|
|
84773
|
+
}, undefined, false, undefined, this));
|
|
84774
|
+
}
|
|
84576
84775
|
var HyperlinkWrapError;
|
|
84577
84776
|
var init_wrap = __esm(() => {
|
|
84578
84777
|
init_jsx();
|
|
@@ -84594,7 +84793,10 @@ class Hyperlinks {
|
|
|
84594
84793
|
}
|
|
84595
84794
|
add(paragraph2, span, url, options = {}) {
|
|
84596
84795
|
const relationshipId = this.document.relationships.addHyperlink(url);
|
|
84597
|
-
|
|
84796
|
+
const applyStyle = options.style ?? true;
|
|
84797
|
+
if (applyStyle)
|
|
84798
|
+
this.document.ensureStyles().ensureStyle("Hyperlink");
|
|
84799
|
+
wrapSpanInHyperlink(paragraph2, span, relationshipId, applyStyle);
|
|
84598
84800
|
this.document.relationships.hyperlinksByRelationshipId.set(relationshipId, {
|
|
84599
84801
|
url
|
|
84600
84802
|
});
|
|
@@ -84697,31 +84899,32 @@ var init_hyperlinks = __esm(() => {
|
|
|
84697
84899
|
// src/cli/hyperlinks/add.tsx
|
|
84698
84900
|
var exports_add3 = {};
|
|
84699
84901
|
__export(exports_add3, {
|
|
84700
|
-
run: () =>
|
|
84902
|
+
run: () => run17
|
|
84701
84903
|
});
|
|
84702
|
-
async function
|
|
84904
|
+
async function run17(args) {
|
|
84703
84905
|
const parsed = await tryParseArgs(args, {
|
|
84704
84906
|
at: { type: "string" },
|
|
84705
84907
|
url: { type: "string" },
|
|
84706
84908
|
author: { type: "string" },
|
|
84909
|
+
"no-style": { type: "boolean" },
|
|
84707
84910
|
...SAVE_FLAGS
|
|
84708
|
-
},
|
|
84911
|
+
}, HELP13);
|
|
84709
84912
|
if (typeof parsed === "number")
|
|
84710
84913
|
return parsed;
|
|
84711
84914
|
if (parsed.values.help) {
|
|
84712
|
-
await writeStdout(
|
|
84915
|
+
await writeStdout(HELP13);
|
|
84713
84916
|
return EXIT2.OK;
|
|
84714
84917
|
}
|
|
84715
84918
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
84716
84919
|
const path2 = parsed.positionals[0];
|
|
84717
84920
|
if (!path2)
|
|
84718
|
-
return fail("USAGE", "Missing FILE argument",
|
|
84921
|
+
return fail("USAGE", "Missing FILE argument", HELP13);
|
|
84719
84922
|
const atInput = parsed.values.at;
|
|
84720
84923
|
const url = parsed.values.url;
|
|
84721
84924
|
if (!atInput)
|
|
84722
|
-
return fail("USAGE", "Missing --at LOCATOR",
|
|
84925
|
+
return fail("USAGE", "Missing --at LOCATOR", HELP13);
|
|
84723
84926
|
if (!url)
|
|
84724
|
-
return fail("USAGE", "Missing --url URL",
|
|
84927
|
+
return fail("USAGE", "Missing --url URL", HELP13);
|
|
84725
84928
|
let locator;
|
|
84726
84929
|
try {
|
|
84727
84930
|
locator = parseLocator(atInput);
|
|
@@ -84755,7 +84958,8 @@ async function run18(args) {
|
|
|
84755
84958
|
}
|
|
84756
84959
|
try {
|
|
84757
84960
|
new Hyperlinks(document4).add(paragraphRef.node, target.span, url, {
|
|
84758
|
-
author: parsed.values.author
|
|
84961
|
+
author: parsed.values.author,
|
|
84962
|
+
style: !parsed.values["no-style"]
|
|
84759
84963
|
});
|
|
84760
84964
|
} catch (error) {
|
|
84761
84965
|
if (error instanceof HyperlinkWrapError) {
|
|
@@ -84784,27 +84988,27 @@ async function findMintedHyperlink(savedPath, blockId, spanStart) {
|
|
|
84784
84988
|
let offset2 = 0;
|
|
84785
84989
|
let foundId;
|
|
84786
84990
|
let text6 = "";
|
|
84787
|
-
for (const
|
|
84788
|
-
if (
|
|
84991
|
+
for (const run18 of block.runs) {
|
|
84992
|
+
if (run18.type !== "text")
|
|
84789
84993
|
continue;
|
|
84790
|
-
const runEnd = offset2 +
|
|
84791
|
-
if (foundId === undefined &&
|
|
84792
|
-
foundId =
|
|
84994
|
+
const runEnd = offset2 + run18.text.length;
|
|
84995
|
+
if (foundId === undefined && run18.hyperlink && spanStart < runEnd) {
|
|
84996
|
+
foundId = run18.hyperlink.id;
|
|
84793
84997
|
}
|
|
84794
|
-
if (foundId !== undefined &&
|
|
84795
|
-
text6 +=
|
|
84998
|
+
if (foundId !== undefined && run18.hyperlink?.id === foundId) {
|
|
84999
|
+
text6 += run18.text;
|
|
84796
85000
|
}
|
|
84797
85001
|
offset2 = runEnd;
|
|
84798
85002
|
}
|
|
84799
85003
|
return foundId === undefined ? undefined : { id: foundId, text: text6 };
|
|
84800
85004
|
}
|
|
84801
|
-
var AT_FORMS3,
|
|
85005
|
+
var AT_FORMS3, HELP13;
|
|
84802
85006
|
var init_add3 = __esm(() => {
|
|
84803
85007
|
init_core2();
|
|
84804
85008
|
init_hyperlinks();
|
|
84805
85009
|
init_respond();
|
|
84806
85010
|
AT_FORMS3 = describeForms(["span", "cellSpan"], " ");
|
|
84807
|
-
|
|
85011
|
+
HELP13 = `docx hyperlinks add \u2014 wrap an existing span in a hyperlink
|
|
84808
85012
|
|
|
84809
85013
|
Usage:
|
|
84810
85014
|
docx hyperlinks add FILE --at LOCATOR --url URL [options]
|
|
@@ -84818,6 +85022,9 @@ ${AT_FORMS3}
|
|
|
84818
85022
|
--url URL Target URL
|
|
84819
85023
|
|
|
84820
85024
|
Optional:
|
|
85025
|
+
--no-style Don't apply Word's "Hyperlink" character style (blue +
|
|
85026
|
+
underline). By default the wrapped text is styled so the link
|
|
85027
|
+
is visibly a link; pass this to keep the original run look.
|
|
84821
85028
|
--author NAME Author for the audit comment when track-changes is on
|
|
84822
85029
|
(default: $DOCX_AUTHOR)
|
|
84823
85030
|
-o, --output PATH Write to PATH instead of overwriting FILE
|
|
@@ -84851,27 +85058,27 @@ Examples:
|
|
|
84851
85058
|
// src/cli/hyperlinks/delete.ts
|
|
84852
85059
|
var exports_delete4 = {};
|
|
84853
85060
|
__export(exports_delete4, {
|
|
84854
|
-
run: () =>
|
|
85061
|
+
run: () => run18
|
|
84855
85062
|
});
|
|
84856
|
-
async function
|
|
85063
|
+
async function run18(args) {
|
|
84857
85064
|
const parsed = await tryParseArgs(args, {
|
|
84858
85065
|
at: { type: "string" },
|
|
84859
85066
|
author: { type: "string" },
|
|
84860
85067
|
...SAVE_FLAGS
|
|
84861
|
-
},
|
|
85068
|
+
}, HELP14);
|
|
84862
85069
|
if (typeof parsed === "number")
|
|
84863
85070
|
return parsed;
|
|
84864
85071
|
if (parsed.values.help) {
|
|
84865
|
-
await writeStdout(
|
|
85072
|
+
await writeStdout(HELP14);
|
|
84866
85073
|
return EXIT2.OK;
|
|
84867
85074
|
}
|
|
84868
85075
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
84869
85076
|
const path2 = parsed.positionals[0];
|
|
84870
85077
|
if (!path2)
|
|
84871
|
-
return fail("USAGE", "Missing FILE argument",
|
|
85078
|
+
return fail("USAGE", "Missing FILE argument", HELP14);
|
|
84872
85079
|
const targetId = parsed.values.at;
|
|
84873
85080
|
if (!targetId)
|
|
84874
|
-
return fail("USAGE", "Missing --at linkN",
|
|
85081
|
+
return fail("USAGE", "Missing --at linkN", HELP14);
|
|
84875
85082
|
const document4 = await openOrFail(path2);
|
|
84876
85083
|
if (typeof document4 === "number")
|
|
84877
85084
|
return document4;
|
|
@@ -84912,13 +85119,13 @@ async function run19(args) {
|
|
|
84912
85119
|
});
|
|
84913
85120
|
return EXIT2.OK;
|
|
84914
85121
|
}
|
|
84915
|
-
var AT_FORMS4,
|
|
85122
|
+
var AT_FORMS4, HELP14;
|
|
84916
85123
|
var init_delete4 = __esm(() => {
|
|
84917
85124
|
init_core2();
|
|
84918
85125
|
init_hyperlinks();
|
|
84919
85126
|
init_respond();
|
|
84920
85127
|
AT_FORMS4 = describeForms(["hyperlink"], " ");
|
|
84921
|
-
|
|
85128
|
+
HELP14 = `docx hyperlinks delete \u2014 unwrap a hyperlink (keep the text)
|
|
84922
85129
|
|
|
84923
85130
|
Usage:
|
|
84924
85131
|
docx hyperlinks delete FILE --at linkN [options]
|
|
@@ -84957,21 +85164,21 @@ Examples:
|
|
|
84957
85164
|
// src/cli/hyperlinks/list.ts
|
|
84958
85165
|
var exports_list3 = {};
|
|
84959
85166
|
__export(exports_list3, {
|
|
84960
|
-
run: () =>
|
|
85167
|
+
run: () => run19
|
|
84961
85168
|
});
|
|
84962
|
-
async function
|
|
85169
|
+
async function run19(args) {
|
|
84963
85170
|
const parsed = await tryParseArgs(args, {
|
|
84964
85171
|
help: { type: "boolean", short: "h" }
|
|
84965
|
-
},
|
|
85172
|
+
}, HELP15);
|
|
84966
85173
|
if (typeof parsed === "number")
|
|
84967
85174
|
return parsed;
|
|
84968
85175
|
if (parsed.values.help) {
|
|
84969
|
-
await writeStdout(
|
|
85176
|
+
await writeStdout(HELP15);
|
|
84970
85177
|
return EXIT2.OK;
|
|
84971
85178
|
}
|
|
84972
85179
|
const path2 = parsed.positionals[0];
|
|
84973
85180
|
if (!path2)
|
|
84974
|
-
return fail("USAGE", "Missing FILE argument",
|
|
85181
|
+
return fail("USAGE", "Missing FILE argument", HELP15);
|
|
84975
85182
|
const document4 = await openOrFail(path2);
|
|
84976
85183
|
if (typeof document4 === "number")
|
|
84977
85184
|
return document4;
|
|
@@ -84984,10 +85191,10 @@ function collectHyperlinks(blocks, entries) {
|
|
|
84984
85191
|
for (const block of iterateBlocks(blocks)) {
|
|
84985
85192
|
if (block.type !== "paragraph")
|
|
84986
85193
|
continue;
|
|
84987
|
-
for (const
|
|
84988
|
-
if (
|
|
85194
|
+
for (const run20 of block.runs) {
|
|
85195
|
+
if (run20.type !== "text" || !run20.hyperlink)
|
|
84989
85196
|
continue;
|
|
84990
|
-
addToEntry(entries,
|
|
85197
|
+
addToEntry(entries, run20.hyperlink, block.id, run20.text);
|
|
84991
85198
|
}
|
|
84992
85199
|
}
|
|
84993
85200
|
}
|
|
@@ -85010,7 +85217,7 @@ function addToEntry(entries, hyperlink, blockId, text6) {
|
|
|
85010
85217
|
entry.tooltip = hyperlink.tooltip;
|
|
85011
85218
|
entries.set(hyperlink.id, entry);
|
|
85012
85219
|
}
|
|
85013
|
-
var
|
|
85220
|
+
var HELP15 = `docx hyperlinks list \u2014 print hyperlink manifest as JSON
|
|
85014
85221
|
|
|
85015
85222
|
Usage:
|
|
85016
85223
|
docx hyperlinks list FILE [options]
|
|
@@ -85036,31 +85243,31 @@ var init_list5 = __esm(() => {
|
|
|
85036
85243
|
// src/cli/hyperlinks/replace.ts
|
|
85037
85244
|
var exports_replace = {};
|
|
85038
85245
|
__export(exports_replace, {
|
|
85039
|
-
run: () =>
|
|
85246
|
+
run: () => run20
|
|
85040
85247
|
});
|
|
85041
|
-
async function
|
|
85248
|
+
async function run20(args) {
|
|
85042
85249
|
const parsed = await tryParseArgs(args, {
|
|
85043
85250
|
at: { type: "string" },
|
|
85044
85251
|
with: { type: "string" },
|
|
85045
85252
|
author: { type: "string" },
|
|
85046
85253
|
...SAVE_FLAGS
|
|
85047
|
-
},
|
|
85254
|
+
}, HELP16);
|
|
85048
85255
|
if (typeof parsed === "number")
|
|
85049
85256
|
return parsed;
|
|
85050
85257
|
if (parsed.values.help) {
|
|
85051
|
-
await writeStdout(
|
|
85258
|
+
await writeStdout(HELP16);
|
|
85052
85259
|
return EXIT2.OK;
|
|
85053
85260
|
}
|
|
85054
85261
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
85055
85262
|
const path2 = parsed.positionals[0];
|
|
85056
85263
|
if (!path2)
|
|
85057
|
-
return fail("USAGE", "Missing FILE argument",
|
|
85264
|
+
return fail("USAGE", "Missing FILE argument", HELP16);
|
|
85058
85265
|
const targetId = parsed.values.at;
|
|
85059
85266
|
if (!targetId)
|
|
85060
|
-
return fail("USAGE", "Missing --at linkN",
|
|
85267
|
+
return fail("USAGE", "Missing --at linkN", HELP16);
|
|
85061
85268
|
const newUrl = parsed.values.with;
|
|
85062
85269
|
if (!newUrl)
|
|
85063
|
-
return fail("USAGE", "Missing --with URL",
|
|
85270
|
+
return fail("USAGE", "Missing --with URL", HELP16);
|
|
85064
85271
|
const document4 = await openOrFail(path2);
|
|
85065
85272
|
if (typeof document4 === "number")
|
|
85066
85273
|
return document4;
|
|
@@ -85099,13 +85306,13 @@ async function run21(args) {
|
|
|
85099
85306
|
});
|
|
85100
85307
|
return EXIT2.OK;
|
|
85101
85308
|
}
|
|
85102
|
-
var AT_FORMS5,
|
|
85309
|
+
var AT_FORMS5, HELP16;
|
|
85103
85310
|
var init_replace2 = __esm(() => {
|
|
85104
85311
|
init_core2();
|
|
85105
85312
|
init_hyperlinks();
|
|
85106
85313
|
init_respond();
|
|
85107
85314
|
AT_FORMS5 = describeForms(["hyperlink"], " ");
|
|
85108
|
-
|
|
85315
|
+
HELP16 = `docx hyperlinks replace \u2014 change a hyperlink's URL
|
|
85109
85316
|
|
|
85110
85317
|
Usage:
|
|
85111
85318
|
docx hyperlinks replace FILE --at linkN --with URL [options]
|
|
@@ -85146,12 +85353,12 @@ Examples:
|
|
|
85146
85353
|
// src/cli/hyperlinks/index.ts
|
|
85147
85354
|
var exports_hyperlinks = {};
|
|
85148
85355
|
__export(exports_hyperlinks, {
|
|
85149
|
-
run: () =>
|
|
85356
|
+
run: () => run21
|
|
85150
85357
|
});
|
|
85151
|
-
async function
|
|
85358
|
+
async function run21(args) {
|
|
85152
85359
|
const verb = args[0];
|
|
85153
85360
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
85154
|
-
await writeStdout(
|
|
85361
|
+
await writeStdout(HELP17);
|
|
85155
85362
|
return verb ? 0 : 2;
|
|
85156
85363
|
}
|
|
85157
85364
|
const loader = SUBCOMMANDS4[verb];
|
|
@@ -85161,7 +85368,7 @@ async function run22(args) {
|
|
|
85161
85368
|
const module_ = await loader();
|
|
85162
85369
|
return module_.run(args.slice(1));
|
|
85163
85370
|
}
|
|
85164
|
-
var SUBCOMMANDS4,
|
|
85371
|
+
var SUBCOMMANDS4, HELP17 = `docx hyperlinks \u2014 manage hyperlinks
|
|
85165
85372
|
|
|
85166
85373
|
Usage:
|
|
85167
85374
|
docx hyperlinks <verb> FILE [options]
|
|
@@ -85380,24 +85587,24 @@ var init_batch3 = __esm(() => {
|
|
|
85380
85587
|
// src/cli/insert/index.tsx
|
|
85381
85588
|
var exports_insert = {};
|
|
85382
85589
|
__export(exports_insert, {
|
|
85383
|
-
run: () =>
|
|
85590
|
+
run: () => run22,
|
|
85384
85591
|
parseTargetPlacement: () => parseTargetPlacement,
|
|
85385
85592
|
parseParagraphOptions: () => parseParagraphOptions2,
|
|
85386
85593
|
chooseContentSpec: () => chooseContentSpec,
|
|
85387
85594
|
MARKDOWN_INCOMPATIBLE_FLAGS: () => MARKDOWN_INCOMPATIBLE_FLAGS2
|
|
85388
85595
|
});
|
|
85389
|
-
async function
|
|
85390
|
-
const parsed = await tryParseArgs(args,
|
|
85596
|
+
async function run22(args) {
|
|
85597
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC3, HELP18);
|
|
85391
85598
|
if (typeof parsed === "number")
|
|
85392
85599
|
return parsed;
|
|
85393
85600
|
if (parsed.values.help) {
|
|
85394
|
-
await writeStdout(
|
|
85601
|
+
await writeStdout(HELP18);
|
|
85395
85602
|
return EXIT2.OK;
|
|
85396
85603
|
}
|
|
85397
85604
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
85398
85605
|
const filePath = parsed.positionals[0];
|
|
85399
85606
|
if (!filePath)
|
|
85400
|
-
return fail("USAGE", "Missing FILE argument",
|
|
85607
|
+
return fail("USAGE", "Missing FILE argument", HELP18);
|
|
85401
85608
|
const batchInput = parsed.values.batch;
|
|
85402
85609
|
if (batchInput !== undefined) {
|
|
85403
85610
|
return runInsertBatch(filePath, batchInput, parsed.values);
|
|
@@ -85452,16 +85659,20 @@ async function commitInsert(document4, blockRef, blocks, opts) {
|
|
|
85452
85659
|
if (insertedNodes.has(reference.node))
|
|
85453
85660
|
locators.push(blockId);
|
|
85454
85661
|
}
|
|
85662
|
+
const destination = opts.outputPath ?? opts.filePath;
|
|
85455
85663
|
await respondMinted(locators, {
|
|
85456
85664
|
ok: true,
|
|
85457
85665
|
operation: "insert",
|
|
85458
|
-
path:
|
|
85666
|
+
path: destination,
|
|
85459
85667
|
locators,
|
|
85460
85668
|
anchor: opts.placement.locator,
|
|
85461
85669
|
placement: opts.placement.mode
|
|
85462
|
-
});
|
|
85670
|
+
}, isLayoutAffecting(opts.spec) ? renderVerifyHint(destination) : undefined);
|
|
85463
85671
|
return EXIT2.OK;
|
|
85464
85672
|
}
|
|
85673
|
+
function isLayoutAffecting(spec) {
|
|
85674
|
+
return spec.kind === "section" || spec.kind === "image" || spec.kind === "table" || spec.kind === "break";
|
|
85675
|
+
}
|
|
85465
85676
|
async function buildSingleShotOptions(filePath, values2) {
|
|
85466
85677
|
const placement = await parseTargetPlacement(values2);
|
|
85467
85678
|
if (typeof placement === "number")
|
|
@@ -85469,10 +85680,18 @@ async function buildSingleShotOptions(filePath, values2) {
|
|
|
85469
85680
|
const spec = await chooseContentSpec(values2);
|
|
85470
85681
|
if (typeof spec === "number")
|
|
85471
85682
|
return spec;
|
|
85683
|
+
if (spec.kind === "text") {
|
|
85684
|
+
const rejected = await rejectMarkdownInText(values2.text, HELP18);
|
|
85685
|
+
if (typeof rejected === "number")
|
|
85686
|
+
return rejected;
|
|
85687
|
+
const mangled = await rejectShellMangledValue(values2.text, HELP18, "--text");
|
|
85688
|
+
if (typeof mangled === "number")
|
|
85689
|
+
return mangled;
|
|
85690
|
+
}
|
|
85472
85691
|
if (spec.kind === "markdown") {
|
|
85473
85692
|
const conflict = MARKDOWN_INCOMPATIBLE_FLAGS2.find((flag) => values2[flag] !== undefined);
|
|
85474
85693
|
if (conflict) {
|
|
85475
|
-
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`,
|
|
85694
|
+
return fail("USAGE", `--${conflict} can't be combined with --markdown / --markdown-file (the markdown source controls block-level styling)`, HELP18);
|
|
85476
85695
|
}
|
|
85477
85696
|
}
|
|
85478
85697
|
const paragraphOptions = await parseParagraphOptions2(values2);
|
|
@@ -85493,23 +85712,26 @@ async function parseTargetPlacement(values2) {
|
|
|
85493
85712
|
const after = values2.after;
|
|
85494
85713
|
const before = values2.before;
|
|
85495
85714
|
if (!after && !before) {
|
|
85496
|
-
return fail("USAGE", "Missing locator: pass --after or --before",
|
|
85715
|
+
return fail("USAGE", "Missing locator: pass --after or --before", HELP18);
|
|
85497
85716
|
}
|
|
85498
85717
|
if (after && before) {
|
|
85499
|
-
return fail("USAGE", "Pass either --after or --before, not both",
|
|
85718
|
+
return fail("USAGE", "Pass either --after or --before, not both", HELP18);
|
|
85500
85719
|
}
|
|
85501
85720
|
if (after !== undefined)
|
|
85502
85721
|
return { mode: "after", locator: after };
|
|
85503
85722
|
return { mode: "before", locator: before };
|
|
85504
85723
|
}
|
|
85505
85724
|
async function chooseContentSpec(values2) {
|
|
85725
|
+
if (values2.section !== undefined || values2.columns !== undefined || values2.type !== undefined) {
|
|
85726
|
+
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`.");
|
|
85727
|
+
}
|
|
85506
85728
|
const present = CONTENT_KINDS.filter((kind) => values2[kind.flag] !== undefined);
|
|
85507
85729
|
if (present.length > 1) {
|
|
85508
|
-
return fail("USAGE", `Pass only one of ${CONTENT_FLAG_LIST}`,
|
|
85730
|
+
return fail("USAGE", `Pass only one of ${CONTENT_FLAG_LIST}`, HELP18);
|
|
85509
85731
|
}
|
|
85510
85732
|
const chosen = present[0];
|
|
85511
85733
|
if (!chosen) {
|
|
85512
|
-
return fail("USAGE", `Missing content: pass ${CONTENT_FLAG_LIST}`,
|
|
85734
|
+
return fail("USAGE", `Missing content: pass ${CONTENT_FLAG_LIST}`, HELP18);
|
|
85513
85735
|
}
|
|
85514
85736
|
const chosenSubFlags = new Set(chosen.subFlags);
|
|
85515
85737
|
for (const kind of CONTENT_KINDS) {
|
|
@@ -85517,7 +85739,7 @@ async function chooseContentSpec(values2) {
|
|
|
85517
85739
|
continue;
|
|
85518
85740
|
const orphan = kind.subFlags.find((flag) => values2[flag] !== undefined && !chosenSubFlags.has(flag));
|
|
85519
85741
|
if (orphan) {
|
|
85520
|
-
return fail("USAGE", `--${orphan} requires --${kind.flag}`,
|
|
85742
|
+
return fail("USAGE", `--${orphan} requires --${kind.flag}`, HELP18);
|
|
85521
85743
|
}
|
|
85522
85744
|
}
|
|
85523
85745
|
switch (chosen.flag) {
|
|
@@ -85531,10 +85753,6 @@ async function chooseContentSpec(values2) {
|
|
|
85531
85753
|
return { kind: "break", breakKind: "page" };
|
|
85532
85754
|
case "column-break":
|
|
85533
85755
|
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
85756
|
case "table": {
|
|
85539
85757
|
const flags = await parseTableFlags(values2);
|
|
85540
85758
|
return typeof flags === "number" ? flags : { kind: "table", ...flags };
|
|
@@ -85589,7 +85807,7 @@ async function resolveCodeSpec(values2, flag) {
|
|
|
85589
85807
|
async function parseImageFlags(values2) {
|
|
85590
85808
|
const src = values2.image;
|
|
85591
85809
|
if (!src)
|
|
85592
|
-
return fail("USAGE", "--image requires a SRC argument",
|
|
85810
|
+
return fail("USAGE", "--image requires a SRC argument", HELP18);
|
|
85593
85811
|
const out = { src };
|
|
85594
85812
|
const alt = values2.alt;
|
|
85595
85813
|
if (alt !== undefined)
|
|
@@ -85632,7 +85850,7 @@ async function parseTableFlags(values2) {
|
|
|
85632
85850
|
const rowsRaw = values2.rows;
|
|
85633
85851
|
const colsRaw = values2.cols;
|
|
85634
85852
|
if (rowsRaw === undefined || colsRaw === undefined) {
|
|
85635
|
-
return fail("USAGE", "--table requires --rows and --cols",
|
|
85853
|
+
return fail("USAGE", "--table requires --rows and --cols", HELP18);
|
|
85636
85854
|
}
|
|
85637
85855
|
const rows = Number.parseInt(rowsRaw, 10);
|
|
85638
85856
|
const cols = Number.parseInt(colsRaw, 10);
|
|
@@ -85709,18 +85927,18 @@ async function parseParagraphOptions2(values2) {
|
|
|
85709
85927
|
const listValue = values2.list;
|
|
85710
85928
|
const listLevelValue = values2["list-level"];
|
|
85711
85929
|
if (taskValue !== undefined && listValue !== undefined) {
|
|
85712
|
-
return fail("USAGE", "--task and --list are mutually exclusive (--task already implies a bullet list)",
|
|
85930
|
+
return fail("USAGE", "--task and --list are mutually exclusive (--task already implies a bullet list)", HELP18);
|
|
85713
85931
|
}
|
|
85714
85932
|
if (taskValue !== undefined) {
|
|
85715
85933
|
const checked = parseTaskFlag(taskValue);
|
|
85716
85934
|
if (checked === null) {
|
|
85717
|
-
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskValue}"`,
|
|
85935
|
+
return fail("USAGE", `--task must be "checked" or "unchecked", got "${taskValue}"`, HELP18);
|
|
85718
85936
|
}
|
|
85719
85937
|
out.taskState = checked ? "checked" : "unchecked";
|
|
85720
85938
|
}
|
|
85721
85939
|
if (listValue !== undefined) {
|
|
85722
85940
|
if (listValue !== "bullet" && listValue !== "ordered") {
|
|
85723
|
-
return fail("USAGE", `--list must be "bullet" or "ordered", got "${listValue}"`,
|
|
85941
|
+
return fail("USAGE", `--list must be "bullet" or "ordered", got "${listValue}"`, HELP18);
|
|
85724
85942
|
}
|
|
85725
85943
|
out.list = { level: 0, numId: -1 };
|
|
85726
85944
|
out.listKind = listValue;
|
|
@@ -85728,7 +85946,7 @@ async function parseParagraphOptions2(values2) {
|
|
|
85728
85946
|
if (listLevelValue !== undefined) {
|
|
85729
85947
|
const level = Number(listLevelValue);
|
|
85730
85948
|
if (!Number.isInteger(level) || level < 0 || level > 8) {
|
|
85731
|
-
return fail("USAGE", `--list-level must be an integer 0-8, got "${listLevelValue}"`,
|
|
85949
|
+
return fail("USAGE", `--list-level must be an integer 0-8, got "${listLevelValue}"`, HELP18);
|
|
85732
85950
|
}
|
|
85733
85951
|
if (out.list)
|
|
85734
85952
|
out.list.level = level;
|
|
@@ -85736,14 +85954,14 @@ async function parseParagraphOptions2(values2) {
|
|
|
85736
85954
|
}
|
|
85737
85955
|
return out;
|
|
85738
85956
|
}
|
|
85739
|
-
var ANCHOR_FORMS2,
|
|
85957
|
+
var ANCHOR_FORMS2, HELP18, OPTION_SPEC3, MARKDOWN_INCOMPATIBLE_FLAGS2, CONTENT_KINDS, CONTENT_FLAG_LIST;
|
|
85740
85958
|
var init_insert2 = __esm(() => {
|
|
85741
85959
|
init_core2();
|
|
85742
85960
|
init_parse_helpers();
|
|
85743
85961
|
init_respond();
|
|
85744
85962
|
init_batch3();
|
|
85745
85963
|
ANCHOR_FORMS2 = describeForms(["paragraph", "table", "section", "cellParagraph"], " ");
|
|
85746
|
-
|
|
85964
|
+
HELP18 = `docx insert \u2014 insert a block (paragraph, table, image, \u2026) at a locator
|
|
85747
85965
|
|
|
85748
85966
|
Usage:
|
|
85749
85967
|
docx insert FILE (--after | --before) LOCATOR <content> [options]
|
|
@@ -85762,7 +85980,6 @@ Content (one required):
|
|
|
85762
85980
|
--runs JSON Insert a paragraph with custom runs (Run[] JSON)
|
|
85763
85981
|
--page-break Insert an empty paragraph containing a page break
|
|
85764
85982
|
--column-break Insert an empty paragraph containing a column break
|
|
85765
|
-
--section Insert a section boundary (sentinel paragraph w/ inline sectPr)
|
|
85766
85983
|
--table Insert an empty rows\xD7cols table (requires --rows and --cols)
|
|
85767
85984
|
--image SRC Insert an image (SRC is a file path, data: URI, or http(s) URL)
|
|
85768
85985
|
--code TEXT Insert a multi-line code block. Newlines split into one
|
|
@@ -85808,19 +86025,20 @@ Run options (only with --text):
|
|
|
85808
86025
|
--italic Italic
|
|
85809
86026
|
--url URL Wrap the inserted text in a hyperlink to URL
|
|
85810
86027
|
|
|
85811
|
-
|
|
85812
|
-
|
|
85813
|
-
|
|
86028
|
+
Column / section layout: NOT here \u2014 use \`docx sections\`. Name the range and it
|
|
86029
|
+
inserts the bounding breaks correctly: \`docx sections --at p6-p16 --columns 2\`.
|
|
86030
|
+
(A raw section break formats the content ABOVE it, the off-by-one that made
|
|
86031
|
+
\`insert --section\` a footgun, so it was removed.)
|
|
85814
86032
|
|
|
85815
86033
|
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
|
-
|
|
86034
|
+
Markdown, but NOT how the page actually looks \u2014 page breaks, image sizing, and
|
|
86035
|
+
where content lands on the page do not appear there. After inserting
|
|
86036
|
+
layout-affecting content (--page-break, --image, --table), render the document to
|
|
86037
|
+
images and look at them:
|
|
85820
86038
|
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
|
-
|
|
86039
|
+
Read the PNGs, check the layout reads the way you intended (no stray blank page,
|
|
86040
|
+
figure sized sensibly), and adjust placement + re-render until it looks right.
|
|
86041
|
+
Don't assume a layout-affecting insert looks good without seeing it.
|
|
85824
86042
|
|
|
85825
86043
|
Table options (only with --table):
|
|
85826
86044
|
--rows N Number of rows (required, >= 1)
|
|
@@ -85869,7 +86087,6 @@ Examples:
|
|
|
85869
86087
|
docx insert doc.docx --after p2 --runs '[{"type":"text","text":"X","bold":true}]'
|
|
85870
86088
|
docx insert doc.docx --after p3 --text "click here" --url https://example.com
|
|
85871
86089
|
docx insert doc.docx --after p3 --page-break
|
|
85872
|
-
docx insert doc.docx --after p9 --section --columns 2 --type continuous
|
|
85873
86090
|
docx insert doc.docx --after p3 --table --rows 3 --cols 2
|
|
85874
86091
|
docx insert doc.docx --after p3 --table --rows 2 --cols 3 --widths 1440,2880,4320
|
|
85875
86092
|
docx insert doc.docx --after p3 --image ./diagram.png --alt "System diagram"
|
|
@@ -85887,7 +86104,7 @@ Batch JSONL example (keys mirror the flags; one insert per line):
|
|
|
85887
86104
|
{"before": "p0", "text": "ALERT", "color": "CC0000", "bold": true}
|
|
85888
86105
|
{"after": "p5", "markdown": "## Summary\\n\\n- point a\\n- point b"}
|
|
85889
86106
|
`;
|
|
85890
|
-
|
|
86107
|
+
OPTION_SPEC3 = {
|
|
85891
86108
|
after: { type: "string" },
|
|
85892
86109
|
before: { type: "string" },
|
|
85893
86110
|
batch: { type: "string" },
|
|
@@ -85942,7 +86159,6 @@ Batch JSONL example (keys mirror the flags; one insert per line):
|
|
|
85942
86159
|
{ flag: "runs", subFlags: [] },
|
|
85943
86160
|
{ flag: "page-break", subFlags: [] },
|
|
85944
86161
|
{ flag: "column-break", subFlags: [] },
|
|
85945
|
-
{ flag: "section", subFlags: ["columns", "type"] },
|
|
85946
86162
|
{
|
|
85947
86163
|
flag: "table",
|
|
85948
86164
|
subFlags: ["rows", "cols", "widths", "table-width", "borders", "layout"]
|
|
@@ -85960,16 +86176,16 @@ Batch JSONL example (keys mirror the flags; one insert per line):
|
|
|
85960
86176
|
// src/cli/images/add.ts
|
|
85961
86177
|
var exports_add4 = {};
|
|
85962
86178
|
__export(exports_add4, {
|
|
85963
|
-
run: () =>
|
|
86179
|
+
run: () => run23
|
|
85964
86180
|
});
|
|
85965
|
-
async function
|
|
86181
|
+
async function run23(args) {
|
|
85966
86182
|
if (args[0] === "-h" || args[0] === "--help") {
|
|
85967
|
-
await writeStdout(
|
|
86183
|
+
await writeStdout(HELP19);
|
|
85968
86184
|
return 0;
|
|
85969
86185
|
}
|
|
85970
|
-
return
|
|
86186
|
+
return run22(args);
|
|
85971
86187
|
}
|
|
85972
|
-
var
|
|
86188
|
+
var HELP19 = `docx images add \u2014 insert an image (an alias for \`docx insert --image\`)
|
|
85973
86189
|
|
|
85974
86190
|
Usage:
|
|
85975
86191
|
docx images add FILE --image PATH --after pN [options]
|
|
@@ -85993,28 +86209,28 @@ var init_add4 = __esm(() => {
|
|
|
85993
86209
|
// src/cli/images/delete.tsx
|
|
85994
86210
|
var exports_delete5 = {};
|
|
85995
86211
|
__export(exports_delete5, {
|
|
85996
|
-
run: () =>
|
|
86212
|
+
run: () => run24
|
|
85997
86213
|
});
|
|
85998
|
-
async function
|
|
86214
|
+
async function run24(args) {
|
|
85999
86215
|
const parsed = await tryParseArgs(args, {
|
|
86000
86216
|
at: { type: "string" },
|
|
86001
86217
|
author: { type: "string" },
|
|
86002
86218
|
track: { type: "boolean" },
|
|
86003
86219
|
...SAVE_FLAGS
|
|
86004
|
-
},
|
|
86220
|
+
}, HELP20);
|
|
86005
86221
|
if (typeof parsed === "number")
|
|
86006
86222
|
return parsed;
|
|
86007
86223
|
if (parsed.values.help) {
|
|
86008
|
-
await writeStdout(
|
|
86224
|
+
await writeStdout(HELP20);
|
|
86009
86225
|
return EXIT2.OK;
|
|
86010
86226
|
}
|
|
86011
86227
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
86012
86228
|
const path2 = parsed.positionals[0];
|
|
86013
86229
|
if (!path2)
|
|
86014
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86230
|
+
return fail("USAGE", "Missing FILE argument", HELP20);
|
|
86015
86231
|
const targetId = parsed.values.at;
|
|
86016
86232
|
if (!targetId)
|
|
86017
|
-
return fail("USAGE", "Missing --at imgN",
|
|
86233
|
+
return fail("USAGE", "Missing --at imgN", HELP20);
|
|
86018
86234
|
const document4 = await openOrFail(path2);
|
|
86019
86235
|
if (typeof document4 === "number")
|
|
86020
86236
|
return document4;
|
|
@@ -86084,7 +86300,7 @@ function pruneIfUnreferenced(document4, relationshipId) {
|
|
|
86084
86300
|
}
|
|
86085
86301
|
return true;
|
|
86086
86302
|
}
|
|
86087
|
-
var
|
|
86303
|
+
var HELP20 = `docx images delete \u2014 remove an embedded image
|
|
86088
86304
|
|
|
86089
86305
|
Usage:
|
|
86090
86306
|
docx images delete FILE --at imgN [options]
|
|
@@ -86129,27 +86345,27 @@ var init_delete5 = __esm(() => {
|
|
|
86129
86345
|
// src/cli/images/extract.ts
|
|
86130
86346
|
var exports_extract = {};
|
|
86131
86347
|
__export(exports_extract, {
|
|
86132
|
-
run: () =>
|
|
86348
|
+
run: () => run25
|
|
86133
86349
|
});
|
|
86134
86350
|
import { join as join6 } from "path";
|
|
86135
|
-
async function
|
|
86351
|
+
async function run25(args) {
|
|
86136
86352
|
const parsed = await tryParseArgs(args, {
|
|
86137
86353
|
to: { type: "string" },
|
|
86138
86354
|
at: { type: "string" },
|
|
86139
86355
|
help: { type: "boolean", short: "h" }
|
|
86140
|
-
},
|
|
86356
|
+
}, HELP21);
|
|
86141
86357
|
if (typeof parsed === "number")
|
|
86142
86358
|
return parsed;
|
|
86143
86359
|
if (parsed.values.help) {
|
|
86144
|
-
await writeStdout(
|
|
86360
|
+
await writeStdout(HELP21);
|
|
86145
86361
|
return EXIT2.OK;
|
|
86146
86362
|
}
|
|
86147
86363
|
const path2 = parsed.positionals[0];
|
|
86148
86364
|
if (!path2)
|
|
86149
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86365
|
+
return fail("USAGE", "Missing FILE argument", HELP21);
|
|
86150
86366
|
const outputDir = parsed.values.to;
|
|
86151
86367
|
if (!outputDir)
|
|
86152
|
-
return fail("USAGE", "Missing --to DIR",
|
|
86368
|
+
return fail("USAGE", "Missing --to DIR", HELP21);
|
|
86153
86369
|
const targetId = parsed.values.at;
|
|
86154
86370
|
const document4 = await openOrFail(path2);
|
|
86155
86371
|
if (typeof document4 === "number")
|
|
@@ -86190,7 +86406,7 @@ function extensionFor(contentType, partName) {
|
|
|
86190
86406
|
const fromName = partName.split(".").pop()?.toLowerCase();
|
|
86191
86407
|
return fromName ?? "bin";
|
|
86192
86408
|
}
|
|
86193
|
-
var
|
|
86409
|
+
var HELP21 = `docx images extract \u2014 dump image bytes to a directory
|
|
86194
86410
|
|
|
86195
86411
|
Usage:
|
|
86196
86412
|
docx images extract FILE --to DIR [options]
|
|
@@ -86223,21 +86439,21 @@ var init_extract = __esm(() => {
|
|
|
86223
86439
|
// src/cli/images/list.ts
|
|
86224
86440
|
var exports_list4 = {};
|
|
86225
86441
|
__export(exports_list4, {
|
|
86226
|
-
run: () =>
|
|
86442
|
+
run: () => run26
|
|
86227
86443
|
});
|
|
86228
|
-
async function
|
|
86444
|
+
async function run26(args) {
|
|
86229
86445
|
const parsed = await tryParseArgs(args, {
|
|
86230
86446
|
help: { type: "boolean", short: "h" }
|
|
86231
|
-
},
|
|
86447
|
+
}, HELP22);
|
|
86232
86448
|
if (typeof parsed === "number")
|
|
86233
86449
|
return parsed;
|
|
86234
86450
|
if (parsed.values.help) {
|
|
86235
|
-
await writeStdout(
|
|
86451
|
+
await writeStdout(HELP22);
|
|
86236
86452
|
return EXIT2.OK;
|
|
86237
86453
|
}
|
|
86238
86454
|
const path2 = parsed.positionals[0];
|
|
86239
86455
|
if (!path2)
|
|
86240
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86456
|
+
return fail("USAGE", "Missing FILE argument", HELP22);
|
|
86241
86457
|
const document4 = await openOrFail(path2);
|
|
86242
86458
|
if (typeof document4 === "number")
|
|
86243
86459
|
return document4;
|
|
@@ -86245,7 +86461,7 @@ async function run27(args) {
|
|
|
86245
86461
|
await respond(flattenImageRuns(document4.body.blocks));
|
|
86246
86462
|
return EXIT2.OK;
|
|
86247
86463
|
}
|
|
86248
|
-
var
|
|
86464
|
+
var HELP22 = `docx images list \u2014 print image manifest as JSON
|
|
86249
86465
|
|
|
86250
86466
|
Usage:
|
|
86251
86467
|
docx images list FILE [options]
|
|
@@ -86271,31 +86487,31 @@ var init_list6 = __esm(() => {
|
|
|
86271
86487
|
// src/cli/images/replace.ts
|
|
86272
86488
|
var exports_replace2 = {};
|
|
86273
86489
|
__export(exports_replace2, {
|
|
86274
|
-
run: () =>
|
|
86490
|
+
run: () => run27
|
|
86275
86491
|
});
|
|
86276
|
-
async function
|
|
86492
|
+
async function run27(args) {
|
|
86277
86493
|
const parsed = await tryParseArgs(args, {
|
|
86278
86494
|
at: { type: "string" },
|
|
86279
86495
|
with: { type: "string" },
|
|
86280
86496
|
author: { type: "string" },
|
|
86281
86497
|
...SAVE_FLAGS
|
|
86282
|
-
},
|
|
86498
|
+
}, HELP23);
|
|
86283
86499
|
if (typeof parsed === "number")
|
|
86284
86500
|
return parsed;
|
|
86285
86501
|
if (parsed.values.help) {
|
|
86286
|
-
await writeStdout(
|
|
86502
|
+
await writeStdout(HELP23);
|
|
86287
86503
|
return EXIT2.OK;
|
|
86288
86504
|
}
|
|
86289
86505
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
86290
86506
|
const path2 = parsed.positionals[0];
|
|
86291
86507
|
if (!path2)
|
|
86292
|
-
return fail("USAGE", "Missing FILE argument",
|
|
86508
|
+
return fail("USAGE", "Missing FILE argument", HELP23);
|
|
86293
86509
|
const targetId = parsed.values.at;
|
|
86294
86510
|
if (!targetId)
|
|
86295
|
-
return fail("USAGE", "Missing --at imgN",
|
|
86511
|
+
return fail("USAGE", "Missing --at imgN", HELP23);
|
|
86296
86512
|
const sourcePath = parsed.values.with;
|
|
86297
86513
|
if (!sourcePath)
|
|
86298
|
-
return fail("USAGE", "Missing --with PATH",
|
|
86514
|
+
return fail("USAGE", "Missing --with PATH", HELP23);
|
|
86299
86515
|
const sourceFile = Bun.file(sourcePath);
|
|
86300
86516
|
if (!await sourceFile.exists()) {
|
|
86301
86517
|
return fail("FILE_NOT_FOUND", `Replacement file not found: ${sourcePath}`);
|
|
@@ -86386,7 +86602,7 @@ function renameExtension(partName, newExtension) {
|
|
|
86386
86602
|
function relativeTargetFor(partName) {
|
|
86387
86603
|
return partName.startsWith("word/") ? partName.slice("word/".length) : partName;
|
|
86388
86604
|
}
|
|
86389
|
-
var
|
|
86605
|
+
var HELP23 = `docx images replace \u2014 swap an image's bytes
|
|
86390
86606
|
|
|
86391
86607
|
Usage:
|
|
86392
86608
|
docx images replace FILE --at imgN --with PATH [options]
|
|
@@ -86431,12 +86647,12 @@ var init_replace3 = __esm(() => {
|
|
|
86431
86647
|
// src/cli/images/index.ts
|
|
86432
86648
|
var exports_images = {};
|
|
86433
86649
|
__export(exports_images, {
|
|
86434
|
-
run: () =>
|
|
86650
|
+
run: () => run28
|
|
86435
86651
|
});
|
|
86436
|
-
async function
|
|
86652
|
+
async function run28(args) {
|
|
86437
86653
|
const verb = args[0];
|
|
86438
86654
|
if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
|
|
86439
|
-
await writeStdout(
|
|
86655
|
+
await writeStdout(HELP24);
|
|
86440
86656
|
return verb ? 0 : 2;
|
|
86441
86657
|
}
|
|
86442
86658
|
const loader = SUBCOMMANDS5[verb];
|
|
@@ -86446,7 +86662,7 @@ async function run29(args) {
|
|
|
86446
86662
|
const module_ = await loader();
|
|
86447
86663
|
return module_.run(args.slice(1));
|
|
86448
86664
|
}
|
|
86449
|
-
var SUBCOMMANDS5,
|
|
86665
|
+
var SUBCOMMANDS5, HELP24 = `docx images \u2014 manage embedded images
|
|
86450
86666
|
|
|
86451
86667
|
Usage:
|
|
86452
86668
|
docx images <verb> FILE [options]
|
|
@@ -86501,6 +86717,13 @@ export type Paragraph = {
|
|
|
86501
86717
|
* them at top level, breaking the quote at that point. See
|
|
86502
86718
|
* [src/core/markdown/CLAUDE.md](../markdown/CLAUDE.md). */
|
|
86503
86719
|
quoteDepth?: number;
|
|
86720
|
+
/** Explicit tab stops from \`<w:pPr><w:tabs>\`, each \`{ align, pos }\` (pos in
|
|
86721
|
+
* twips). Surfaced so \`read\` can flag a fragile right-alignment: a LEFT (or
|
|
86722
|
+
* center) tab stop near the right margin pushes content rightward but \u2014 unlike
|
|
86723
|
+
* a RIGHT tab \u2014 wraps anything wider than the gap to the margin (the r\xE9sum\xE9
|
|
86724
|
+
* "San / Francisco, CA" break). Present only when the paragraph declares
|
|
86725
|
+
* explicit tab stops. */
|
|
86726
|
+
tabStops?: { align: string; pos: number }[];
|
|
86504
86727
|
runs: Run[];
|
|
86505
86728
|
};
|
|
86506
86729
|
|
|
@@ -86806,18 +87029,18 @@ var init_types3 = () => {};
|
|
|
86806
87029
|
// src/cli/info/schema.ts
|
|
86807
87030
|
var exports_schema = {};
|
|
86808
87031
|
__export(exports_schema, {
|
|
86809
|
-
run: () =>
|
|
87032
|
+
run: () => run29
|
|
86810
87033
|
});
|
|
86811
|
-
async function
|
|
87034
|
+
async function run29(args) {
|
|
86812
87035
|
const parsed = await tryParseArgs(args, {
|
|
86813
87036
|
json: { type: "boolean" },
|
|
86814
87037
|
ts: { type: "boolean" },
|
|
86815
87038
|
help: { type: "boolean", short: "h" }
|
|
86816
|
-
},
|
|
87039
|
+
}, HELP25);
|
|
86817
87040
|
if (typeof parsed === "number")
|
|
86818
87041
|
return parsed;
|
|
86819
87042
|
if (parsed.values.help) {
|
|
86820
|
-
await writeStdout(
|
|
87043
|
+
await writeStdout(HELP25);
|
|
86821
87044
|
return EXIT2.OK;
|
|
86822
87045
|
}
|
|
86823
87046
|
if (parsed.values.ts) {
|
|
@@ -86827,7 +87050,7 @@ async function run30(args) {
|
|
|
86827
87050
|
await respond(JSON_SCHEMA);
|
|
86828
87051
|
return EXIT2.OK;
|
|
86829
87052
|
}
|
|
86830
|
-
var
|
|
87053
|
+
var HELP25 = `docx info schema \u2014 print the AST type definitions
|
|
86831
87054
|
|
|
86832
87055
|
Usage:
|
|
86833
87056
|
docx info schema [options]
|
|
@@ -86901,6 +87124,17 @@ var init_schema = __esm(() => {
|
|
|
86901
87124
|
}
|
|
86902
87125
|
},
|
|
86903
87126
|
taskState: { enum: ["checked", "unchecked"] },
|
|
87127
|
+
tabStops: {
|
|
87128
|
+
type: "array",
|
|
87129
|
+
items: {
|
|
87130
|
+
type: "object",
|
|
87131
|
+
required: ["align", "pos"],
|
|
87132
|
+
properties: {
|
|
87133
|
+
align: { type: "string" },
|
|
87134
|
+
pos: { type: "number" }
|
|
87135
|
+
}
|
|
87136
|
+
}
|
|
87137
|
+
},
|
|
86904
87138
|
runs: { type: "array", items: { $ref: "#/$defs/Run" } }
|
|
86905
87139
|
}
|
|
86906
87140
|
},
|
|
@@ -87155,7 +87389,7 @@ var init_schema = __esm(() => {
|
|
|
87155
87389
|
// src/cli/info/locators.ts
|
|
87156
87390
|
var exports_locators = {};
|
|
87157
87391
|
__export(exports_locators, {
|
|
87158
|
-
run: () =>
|
|
87392
|
+
run: () => run30
|
|
87159
87393
|
});
|
|
87160
87394
|
function renderReference() {
|
|
87161
87395
|
const sections = GROUPS.map((group) => {
|
|
@@ -87286,15 +87520,15 @@ function renderJson() {
|
|
|
87286
87520
|
]
|
|
87287
87521
|
};
|
|
87288
87522
|
}
|
|
87289
|
-
async function
|
|
87523
|
+
async function run30(args) {
|
|
87290
87524
|
const parsed = await tryParseArgs(args, {
|
|
87291
87525
|
json: { type: "boolean" },
|
|
87292
87526
|
help: { type: "boolean", short: "h" }
|
|
87293
|
-
},
|
|
87527
|
+
}, HELP26);
|
|
87294
87528
|
if (typeof parsed === "number")
|
|
87295
87529
|
return parsed;
|
|
87296
87530
|
if (parsed.values.help) {
|
|
87297
|
-
await writeStdout(
|
|
87531
|
+
await writeStdout(HELP26);
|
|
87298
87532
|
return EXIT2.OK;
|
|
87299
87533
|
}
|
|
87300
87534
|
if (parsed.values.json) {
|
|
@@ -87305,7 +87539,7 @@ async function run31(args) {
|
|
|
87305
87539
|
await writeStdout(renderReference());
|
|
87306
87540
|
return EXIT2.OK;
|
|
87307
87541
|
}
|
|
87308
|
-
var
|
|
87542
|
+
var HELP26 = `docx info locators \u2014 print the locator grammar reference
|
|
87309
87543
|
|
|
87310
87544
|
Usage:
|
|
87311
87545
|
docx info locators [options]
|
|
@@ -87357,12 +87591,12 @@ var init_locators2 = __esm(() => {
|
|
|
87357
87591
|
// src/cli/info/index.ts
|
|
87358
87592
|
var exports_info = {};
|
|
87359
87593
|
__export(exports_info, {
|
|
87360
|
-
run: () =>
|
|
87594
|
+
run: () => run31
|
|
87361
87595
|
});
|
|
87362
|
-
async function
|
|
87596
|
+
async function run31(args) {
|
|
87363
87597
|
const topic = args[0];
|
|
87364
87598
|
if (!topic || topic === "--help" || topic === "-h" || topic === "help") {
|
|
87365
|
-
await writeStdout(
|
|
87599
|
+
await writeStdout(HELP27);
|
|
87366
87600
|
return topic ? 0 : 2;
|
|
87367
87601
|
}
|
|
87368
87602
|
const loader = SUBCOMMANDS6[topic];
|
|
@@ -87372,7 +87606,7 @@ async function run32(args) {
|
|
|
87372
87606
|
const module_ = await loader();
|
|
87373
87607
|
return module_.run(args.slice(1));
|
|
87374
87608
|
}
|
|
87375
|
-
var SUBCOMMANDS6,
|
|
87609
|
+
var SUBCOMMANDS6, HELP27 = `docx info \u2014 print reference material about the CLI
|
|
87376
87610
|
|
|
87377
87611
|
Usage:
|
|
87378
87612
|
docx info <topic> [options]
|
|
@@ -87452,23 +87686,23 @@ var init_build = __esm(() => {
|
|
|
87452
87686
|
// src/cli/outline/index.ts
|
|
87453
87687
|
var exports_outline = {};
|
|
87454
87688
|
__export(exports_outline, {
|
|
87455
|
-
run: () =>
|
|
87689
|
+
run: () => run32
|
|
87456
87690
|
});
|
|
87457
|
-
async function
|
|
87691
|
+
async function run32(args) {
|
|
87458
87692
|
const parsed = await tryParseArgs(args, {
|
|
87459
87693
|
"style-prefix": { type: "string" },
|
|
87460
87694
|
json: { type: "boolean" },
|
|
87461
87695
|
help: { type: "boolean", short: "h" }
|
|
87462
|
-
},
|
|
87696
|
+
}, HELP28);
|
|
87463
87697
|
if (typeof parsed === "number")
|
|
87464
87698
|
return parsed;
|
|
87465
87699
|
if (parsed.values.help) {
|
|
87466
|
-
await writeStdout(
|
|
87700
|
+
await writeStdout(HELP28);
|
|
87467
87701
|
return EXIT2.OK;
|
|
87468
87702
|
}
|
|
87469
87703
|
const path2 = parsed.positionals[0];
|
|
87470
87704
|
if (!path2)
|
|
87471
|
-
return fail("USAGE", "Missing FILE argument",
|
|
87705
|
+
return fail("USAGE", "Missing FILE argument", HELP28);
|
|
87472
87706
|
const stylePrefix = parsed.values["style-prefix"] ?? "Heading";
|
|
87473
87707
|
if (stylePrefix.length === 0) {
|
|
87474
87708
|
return fail("USAGE", "--style-prefix cannot be empty");
|
|
@@ -87496,7 +87730,7 @@ function renderOutlineText(entries, depth = 0) {
|
|
|
87496
87730
|
}
|
|
87497
87731
|
return lines;
|
|
87498
87732
|
}
|
|
87499
|
-
var
|
|
87733
|
+
var HELP28 = `docx outline \u2014 list headings as a hierarchical tree
|
|
87500
87734
|
|
|
87501
87735
|
Usage:
|
|
87502
87736
|
docx outline FILE [options]
|
|
@@ -87564,7 +87798,9 @@ function renderMarkdown(doc, options = {}) {
|
|
|
87564
87798
|
referencedEndnoteIds: new Set,
|
|
87565
87799
|
referencedTrackedChanges: new Map,
|
|
87566
87800
|
orderedCounters: new Map,
|
|
87567
|
-
contentWidthEmu: contentWidthEmu(documentGeometry(blocks))
|
|
87801
|
+
contentWidthEmu: contentWidthEmu(documentGeometry(blocks)),
|
|
87802
|
+
governingColumns: computeGoverningColumns(blocks),
|
|
87803
|
+
wrappingTabLines: []
|
|
87568
87804
|
};
|
|
87569
87805
|
const parts = [];
|
|
87570
87806
|
let cursor = 0;
|
|
@@ -87591,7 +87827,7 @@ function renderMarkdown(doc, options = {}) {
|
|
|
87591
87827
|
cursor = lookahead2;
|
|
87592
87828
|
continue;
|
|
87593
87829
|
}
|
|
87594
|
-
const rendered = renderBlock(block, ctx);
|
|
87830
|
+
const rendered = renderBlock(block, ctx, blocks, cursor);
|
|
87595
87831
|
if (rendered !== null)
|
|
87596
87832
|
parts.push(rendered);
|
|
87597
87833
|
cursor++;
|
|
@@ -87618,7 +87854,9 @@ function renderMarkdown(doc, options = {}) {
|
|
|
87618
87854
|
return "";
|
|
87619
87855
|
const baseNote = formatBaseNote(dominant);
|
|
87620
87856
|
const pageNote = formatPageNote(documentGeometry(blocks));
|
|
87621
|
-
const
|
|
87857
|
+
const trackNote = options.trackChangesOn ? formatNote("track-changes", [], ["on"]) : "";
|
|
87858
|
+
const wrapSummary = formatWrappingTabSummary(ctx.wrappingTabLines);
|
|
87859
|
+
const headLines = [baseNote, pageNote, trackNote, wrapSummary].filter((line) => line.length > 0);
|
|
87622
87860
|
const head = headLines.length > 0 ? `${headLines.join(`
|
|
87623
87861
|
`)}
|
|
87624
87862
|
|
|
@@ -87633,17 +87871,17 @@ function detectFormatBaseline(blocks) {
|
|
|
87633
87871
|
const sizeChars = new Map;
|
|
87634
87872
|
let total = 0;
|
|
87635
87873
|
for (const paragraph2 of flattenParagraphs(blocks)) {
|
|
87636
|
-
for (const
|
|
87637
|
-
if (
|
|
87874
|
+
for (const run33 of paragraph2.runs) {
|
|
87875
|
+
if (run33.type !== "text")
|
|
87638
87876
|
continue;
|
|
87639
|
-
const length =
|
|
87877
|
+
const length = run33.text.length;
|
|
87640
87878
|
if (length === 0)
|
|
87641
87879
|
continue;
|
|
87642
87880
|
total += length;
|
|
87643
|
-
if (
|
|
87644
|
-
fontChars.set(
|
|
87645
|
-
if (
|
|
87646
|
-
sizeChars.set(
|
|
87881
|
+
if (run33.font)
|
|
87882
|
+
fontChars.set(run33.font, (fontChars.get(run33.font) ?? 0) + length);
|
|
87883
|
+
if (run33.sizeHalfPoints !== undefined) {
|
|
87884
|
+
sizeChars.set(run33.sizeHalfPoints, (sizeChars.get(run33.sizeHalfPoints) ?? 0) + length);
|
|
87647
87885
|
}
|
|
87648
87886
|
}
|
|
87649
87887
|
}
|
|
@@ -87677,8 +87915,8 @@ function emptyCommentIndex() {
|
|
|
87677
87915
|
orderedIds: []
|
|
87678
87916
|
};
|
|
87679
87917
|
}
|
|
87680
|
-
function isRunVisible(
|
|
87681
|
-
const kind =
|
|
87918
|
+
function isRunVisible(run33, view) {
|
|
87919
|
+
const kind = run33.trackedChange?.kind;
|
|
87682
87920
|
if (!kind)
|
|
87683
87921
|
return true;
|
|
87684
87922
|
if (view === "accepted" && (kind === "del" || kind === "moveFrom"))
|
|
@@ -87693,13 +87931,13 @@ function buildCommentIndex(blocks, options) {
|
|
|
87693
87931
|
const spanText = new Map;
|
|
87694
87932
|
const orderedIds = [];
|
|
87695
87933
|
for (const paragraph2 of flattenParagraphs(blocks)) {
|
|
87696
|
-
paragraph2.runs.forEach((
|
|
87697
|
-
const comments = runComments(
|
|
87934
|
+
paragraph2.runs.forEach((run33, index2) => {
|
|
87935
|
+
const comments = runComments(run33);
|
|
87698
87936
|
if (!comments)
|
|
87699
87937
|
return;
|
|
87700
|
-
if (
|
|
87938
|
+
if (run33.type === "text" && !isRunVisible(run33, view))
|
|
87701
87939
|
return;
|
|
87702
|
-
const spanContribution =
|
|
87940
|
+
const spanContribution = run33.type === "text" ? run33.text : run33.type === "equation" ? run33.text : "";
|
|
87703
87941
|
for (const commentId of comments) {
|
|
87704
87942
|
if (!spanText.has(commentId))
|
|
87705
87943
|
orderedIds.push(commentId);
|
|
@@ -87719,32 +87957,121 @@ function buildCommentIndex(blocks, options) {
|
|
|
87719
87957
|
}
|
|
87720
87958
|
return { endingsByRun, spanText, orderedIds };
|
|
87721
87959
|
}
|
|
87722
|
-
function runComments(
|
|
87723
|
-
if (
|
|
87724
|
-
return
|
|
87725
|
-
if (
|
|
87726
|
-
return
|
|
87960
|
+
function runComments(run33) {
|
|
87961
|
+
if (run33.type === "text")
|
|
87962
|
+
return run33.comments;
|
|
87963
|
+
if (run33.type === "equation")
|
|
87964
|
+
return run33.comments;
|
|
87727
87965
|
return;
|
|
87728
87966
|
}
|
|
87729
87967
|
function slotKey(paragraphId, runIndex) {
|
|
87730
87968
|
return `${paragraphId}#${runIndex}`;
|
|
87731
87969
|
}
|
|
87732
|
-
function renderBlock(block, ctx) {
|
|
87970
|
+
function renderBlock(block, ctx, blocks, index2) {
|
|
87733
87971
|
if (block.type === "paragraph")
|
|
87734
87972
|
return renderParagraph(block, ctx);
|
|
87735
87973
|
if (block.type === "table")
|
|
87736
87974
|
return renderTable(block, ctx);
|
|
87737
|
-
if (block.type === "sectionBreak")
|
|
87738
|
-
return renderSectionBreak(block);
|
|
87975
|
+
if (block.type === "sectionBreak") {
|
|
87976
|
+
return renderSectionBreak(block, governedRange(blocks, index2));
|
|
87977
|
+
}
|
|
87739
87978
|
return null;
|
|
87740
87979
|
}
|
|
87741
|
-
function
|
|
87980
|
+
function computeGoverningColumns(blocks) {
|
|
87981
|
+
const map3 = new Map;
|
|
87982
|
+
let cols = 1;
|
|
87983
|
+
for (let index2 = blocks.length - 1;index2 >= 0; index2--) {
|
|
87984
|
+
const block = blocks[index2];
|
|
87985
|
+
if (!block)
|
|
87986
|
+
continue;
|
|
87987
|
+
if (block.type === "sectionBreak") {
|
|
87988
|
+
cols = block.columns ?? 1;
|
|
87989
|
+
continue;
|
|
87990
|
+
}
|
|
87991
|
+
map3.set(block.id, cols);
|
|
87992
|
+
}
|
|
87993
|
+
return map3;
|
|
87994
|
+
}
|
|
87995
|
+
function formatWrappingTabSummary(ids) {
|
|
87996
|
+
if (ids.length === 0)
|
|
87997
|
+
return "";
|
|
87998
|
+
const count = `${ids.length} line${ids.length > 1 ? "s" : ""}`;
|
|
87999
|
+
const range = tabCureRange(ids);
|
|
88000
|
+
const fix = range ? `edit FILE --at ${range} --tabs right` : ids.map((id) => `edit FILE --at ${id} --tabs right`).join(" ; ");
|
|
88001
|
+
return formatNote("layout", [
|
|
88002
|
+
["wrap", count],
|
|
88003
|
+
[
|
|
88004
|
+
"warn",
|
|
88005
|
+
"tab-aligned content (e.g. dates/locations) overflows the right margin and WRAPS in render until cured"
|
|
88006
|
+
],
|
|
88007
|
+
["fix-all", fix]
|
|
88008
|
+
], ids);
|
|
88009
|
+
}
|
|
88010
|
+
function tabCureRange(ids) {
|
|
88011
|
+
const nums = ids.map((id) => /^p(\d+)$/.exec(id)?.[1]).filter((value) => value !== undefined).map(Number);
|
|
88012
|
+
if (nums.length === 0)
|
|
88013
|
+
return null;
|
|
88014
|
+
const min = Math.min(...nums);
|
|
88015
|
+
const max = Math.max(...nums);
|
|
88016
|
+
return min === max ? `p${min}` : `p${min}-p${max}`;
|
|
88017
|
+
}
|
|
88018
|
+
function layoutHazardNote(paragraph2, ctx) {
|
|
88019
|
+
if (!paragraph2.runs.some((run33) => run33.type === "tab"))
|
|
88020
|
+
return "";
|
|
88021
|
+
const cols = ctx.governingColumns.get(paragraph2.id) ?? 1;
|
|
88022
|
+
if (cols > 1) {
|
|
88023
|
+
return ` ${formatNote("layout", [
|
|
88024
|
+
["cols", cols],
|
|
88025
|
+
[
|
|
88026
|
+
"warn",
|
|
88027
|
+
`tab alignment can wrap mid-line in this ${cols}-column section; render to verify`
|
|
88028
|
+
]
|
|
88029
|
+
], [paragraph2.id])}`;
|
|
88030
|
+
}
|
|
88031
|
+
const tabs = paragraph2.tabStops ?? [];
|
|
88032
|
+
if (tabs.some((tab) => tab.align === "right"))
|
|
88033
|
+
return "";
|
|
88034
|
+
const textWidthTwips = Math.round(ctx.contentWidthEmu / EMU_PER_TWIP2);
|
|
88035
|
+
const fragile = tabs.find((tab) => (tab.align === "left" || tab.align === "center" || tab.align === "") && tab.pos > textWidthTwips * 0.7);
|
|
88036
|
+
if (!fragile)
|
|
88037
|
+
return "";
|
|
88038
|
+
ctx.wrappingTabLines.push(paragraph2.id);
|
|
88039
|
+
const gapIn = twipsToInches(Math.max(0, textWidthTwips - fragile.pos));
|
|
88040
|
+
return ` ${formatNote("layout", [
|
|
88041
|
+
["tab", `${fragile.align || "left"}@${twipsToInches(fragile.pos)}in`],
|
|
88042
|
+
[
|
|
88043
|
+
"warn",
|
|
88044
|
+
`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)`
|
|
88045
|
+
]
|
|
88046
|
+
], [paragraph2.id])}`;
|
|
88047
|
+
}
|
|
88048
|
+
function governedRange(blocks, index2) {
|
|
88049
|
+
let first;
|
|
88050
|
+
let last;
|
|
88051
|
+
for (let cursor = index2 - 1;cursor >= 0; cursor--) {
|
|
88052
|
+
const block = blocks[cursor];
|
|
88053
|
+
if (!block)
|
|
88054
|
+
continue;
|
|
88055
|
+
if (block.type === "sectionBreak")
|
|
88056
|
+
break;
|
|
88057
|
+
first = block.id;
|
|
88058
|
+
if (last === undefined)
|
|
88059
|
+
last = block.id;
|
|
88060
|
+
}
|
|
88061
|
+
if (!first || !last)
|
|
88062
|
+
return;
|
|
88063
|
+
return first === last ? first : `${first}..${last}`;
|
|
88064
|
+
}
|
|
88065
|
+
function renderSectionBreak(block, governs) {
|
|
87742
88066
|
const pairs = [];
|
|
87743
88067
|
if (block.columns !== undefined && block.columns > 1) {
|
|
87744
88068
|
pairs.push(["cols", block.columns]);
|
|
87745
88069
|
}
|
|
87746
88070
|
if (block.sectionType !== undefined)
|
|
87747
88071
|
pairs.push(["type", block.sectionType]);
|
|
88072
|
+
if (governs !== undefined && pairs.length > 0) {
|
|
88073
|
+
pairs.push(["applies-to", `${governs} (above)`]);
|
|
88074
|
+
}
|
|
87748
88075
|
return formatNote("section", pairs, [block.id]);
|
|
87749
88076
|
}
|
|
87750
88077
|
function contentWidthEmu(geometry) {
|
|
@@ -87755,25 +88082,25 @@ function contentWidthEmu(geometry) {
|
|
|
87755
88082
|
const fallback = (DEFAULT_PAGE.width - 2 * DEFAULT_PAGE.margin) * EMU_PER_TWIP2;
|
|
87756
88083
|
return contentTwips > 0 ? contentTwips * EMU_PER_TWIP2 : fallback;
|
|
87757
88084
|
}
|
|
87758
|
-
function formatImageNote(
|
|
88085
|
+
function formatImageNote(run33, contentEmu) {
|
|
87759
88086
|
const pairs = [];
|
|
87760
|
-
if (
|
|
88087
|
+
if (run33.widthEmu && run33.heightEmu) {
|
|
87761
88088
|
pairs.push([
|
|
87762
88089
|
"size",
|
|
87763
|
-
`${emuToInches(
|
|
88090
|
+
`${emuToInches(run33.widthEmu)}x${emuToInches(run33.heightEmu)}in`
|
|
87764
88091
|
]);
|
|
87765
88092
|
}
|
|
87766
|
-
if (
|
|
88093
|
+
if (run33.floating)
|
|
87767
88094
|
pairs.push(["float", "yes"]);
|
|
87768
|
-
if (
|
|
87769
|
-
pairs.push(["wrap",
|
|
87770
|
-
if (
|
|
87771
|
-
pairs.push(["align",
|
|
87772
|
-
if (
|
|
88095
|
+
if (run33.wrap)
|
|
88096
|
+
pairs.push(["wrap", run33.wrap]);
|
|
88097
|
+
if (run33.align)
|
|
88098
|
+
pairs.push(["align", run33.align]);
|
|
88099
|
+
if (run33.widthEmu && run33.widthEmu > contentEmu)
|
|
87773
88100
|
pairs.push(["overflow", "yes"]);
|
|
87774
88101
|
if (pairs.length === 0)
|
|
87775
88102
|
return "";
|
|
87776
|
-
return ` ${formatNote("image", pairs, [
|
|
88103
|
+
return ` ${formatNote("image", pairs, [run33.id])}`;
|
|
87777
88104
|
}
|
|
87778
88105
|
function documentGeometry(blocks) {
|
|
87779
88106
|
for (let index2 = blocks.length - 1;index2 >= 0; index2--) {
|
|
@@ -87825,14 +88152,14 @@ function isCodeBlockParagraph(block) {
|
|
|
87825
88152
|
function renderCodeBlockGroup(paragraphs, ctx) {
|
|
87826
88153
|
if (ctx.options.view !== "baseline" && ctx.options.view !== "accepted") {
|
|
87827
88154
|
for (const paragraph2 of paragraphs) {
|
|
87828
|
-
for (const
|
|
87829
|
-
if (
|
|
87830
|
-
ctx.referencedTrackedChanges.set(
|
|
88155
|
+
for (const run33 of paragraph2.runs) {
|
|
88156
|
+
if (run33.type === "text" && run33.trackedChange) {
|
|
88157
|
+
ctx.referencedTrackedChanges.set(run33.trackedChange.id, run33.trackedChange);
|
|
87831
88158
|
}
|
|
87832
88159
|
}
|
|
87833
88160
|
}
|
|
87834
88161
|
}
|
|
87835
|
-
const lines = paragraphs.map((paragraph2) => paragraph2.runs.filter((
|
|
88162
|
+
const lines = paragraphs.map((paragraph2) => paragraph2.runs.filter((run33) => run33.type === "text" && typeof run33.text === "string").map((run33) => run33.text).join(""));
|
|
87836
88163
|
const firstId = paragraphs[0]?.id ?? "";
|
|
87837
88164
|
const lastId = paragraphs[paragraphs.length - 1]?.id ?? firstId;
|
|
87838
88165
|
const language = codeBlockLanguageFromStyleId(paragraphs[0]?.style) ?? "";
|
|
@@ -87852,7 +88179,7 @@ function renderParagraph(paragraph2, ctx) {
|
|
|
87852
88179
|
const body = rendered.replace(/[ \t]+$/, "");
|
|
87853
88180
|
const separator = isDisplayEquationOnly(body) ? `
|
|
87854
88181
|
` : " ";
|
|
87855
|
-
return `${prefix}${body}${separator}<!-- ${paragraph2.id} -->${formatParagraphNote(paragraph2)}`;
|
|
88182
|
+
return `${prefix}${body}${separator}<!-- ${paragraph2.id} -->${formatParagraphNote(paragraph2)}${layoutHazardNote(paragraph2, ctx)}`;
|
|
87856
88183
|
}
|
|
87857
88184
|
function formatParagraphNote(paragraph2) {
|
|
87858
88185
|
const pairs = [];
|
|
@@ -87925,10 +88252,10 @@ function headingLevelFor(style) {
|
|
|
87925
88252
|
function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
|
|
87926
88253
|
const view = ctx.options.view ?? "accepted";
|
|
87927
88254
|
const visibleEntries = [];
|
|
87928
|
-
runs.forEach((
|
|
87929
|
-
if (
|
|
88255
|
+
runs.forEach((run33, index2) => {
|
|
88256
|
+
if (run33.type === "text" && !isRunVisible(run33, view))
|
|
87930
88257
|
return;
|
|
87931
|
-
visibleEntries.push({ run:
|
|
88258
|
+
visibleEntries.push({ run: run33, originalIndex: index2 });
|
|
87932
88259
|
});
|
|
87933
88260
|
let out = "";
|
|
87934
88261
|
let cursor = 0;
|
|
@@ -87939,14 +88266,14 @@ function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
|
|
|
87939
88266
|
cursor++;
|
|
87940
88267
|
continue;
|
|
87941
88268
|
}
|
|
87942
|
-
const { run:
|
|
87943
|
-
if (
|
|
88269
|
+
const { run: run33 } = entry;
|
|
88270
|
+
if (run33.type === "text") {
|
|
87944
88271
|
let lookahead2 = cursor + 1;
|
|
87945
88272
|
while (lookahead2 < visibleEntries.length) {
|
|
87946
88273
|
const next = visibleEntries[lookahead2];
|
|
87947
88274
|
if (!next || next.run.type !== "text")
|
|
87948
88275
|
break;
|
|
87949
|
-
if (!sameDecoration(
|
|
88276
|
+
if (!sameDecoration(run33, next.run))
|
|
87950
88277
|
break;
|
|
87951
88278
|
lookahead2++;
|
|
87952
88279
|
}
|
|
@@ -87967,29 +88294,29 @@ function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
|
|
|
87967
88294
|
cursor = lookahead2;
|
|
87968
88295
|
continue;
|
|
87969
88296
|
}
|
|
87970
|
-
if (
|
|
87971
|
-
const alt = sanitizeAltText(
|
|
87972
|
-
const extension2 = extensionForImageMime(
|
|
87973
|
-
out += ` {
|
|
88298
|
+
const alt = sanitizeAltText(run33.alt ?? run33.id);
|
|
88299
|
+
const extension2 = extensionForImageMime(run33.contentType) ?? "bin";
|
|
88300
|
+
out += ``;
|
|
88301
|
+
out += formatImageNote(run33, ctx.contentWidthEmu);
|
|
88302
|
+
} else if (run33.type === "break") {
|
|
88303
|
+
if (run33.kind === "line")
|
|
87977
88304
|
out += `
|
|
87978
88305
|
`;
|
|
87979
|
-
} else if (
|
|
88306
|
+
} else if (run33.type === "tab") {
|
|
87980
88307
|
out += "\t";
|
|
87981
|
-
} else if (
|
|
87982
|
-
const body =
|
|
87983
|
-
out +=
|
|
88308
|
+
} else if (run33.type === "equation") {
|
|
88309
|
+
const body = run33.latex.length > 0 ? run33.latex : run33.text;
|
|
88310
|
+
out += run33.display ? `$$${body}$$` : `$${body}$`;
|
|
87984
88311
|
out += commentEndingsFor(paragraphId, [{ originalIndex: cursor }], ctx.commentIndex);
|
|
87985
|
-
} else if (
|
|
87986
|
-
if (
|
|
87987
|
-
ctx.referencedFootnoteIds.add(
|
|
88312
|
+
} else if (run33.type === "noteRef") {
|
|
88313
|
+
if (run33.kind === "footnote")
|
|
88314
|
+
ctx.referencedFootnoteIds.add(run33.id);
|
|
87988
88315
|
else
|
|
87989
|
-
ctx.referencedEndnoteIds.add(
|
|
87990
|
-
out += `[^${
|
|
87991
|
-
} else if (
|
|
87992
|
-
out += `\`[${
|
|
88316
|
+
ctx.referencedEndnoteIds.add(run33.id);
|
|
88317
|
+
out += `[^${run33.id}]`;
|
|
88318
|
+
} else if (run33.type === "chart") {
|
|
88319
|
+
out += `\`[${run33.kind}]\``;
|
|
87993
88320
|
}
|
|
87994
88321
|
cursor++;
|
|
87995
88322
|
}
|
|
@@ -88023,7 +88350,7 @@ function sameCommentSet(left, right) {
|
|
|
88023
88350
|
return true;
|
|
88024
88351
|
}
|
|
88025
88352
|
function renderTextSegment(runs, view, baseline, mask, offset2) {
|
|
88026
|
-
const text6 = runs.map((
|
|
88353
|
+
const text6 = runs.map((run33) => run33.text).join("");
|
|
88027
88354
|
if (text6.length === 0)
|
|
88028
88355
|
return "";
|
|
88029
88356
|
const first = runs[0];
|
|
@@ -88067,33 +88394,33 @@ function criticMarkerFor(kind) {
|
|
|
88067
88394
|
return "++";
|
|
88068
88395
|
return "--";
|
|
88069
88396
|
}
|
|
88070
|
-
function needsHtmlWrap(
|
|
88071
|
-
return Boolean(
|
|
88397
|
+
function needsHtmlWrap(run33, baseline) {
|
|
88398
|
+
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
88399
|
}
|
|
88073
|
-
function wrapRunFormatting(body,
|
|
88400
|
+
function wrapRunFormatting(body, run33, baseline) {
|
|
88074
88401
|
const styles = [];
|
|
88075
88402
|
const attrs = [];
|
|
88076
|
-
if (
|
|
88077
|
-
styles.push(`color:#${
|
|
88078
|
-
if (
|
|
88079
|
-
styles.push(`background-color:#${
|
|
88080
|
-
if (
|
|
88081
|
-
styles.push(`font-family:${cssFontFamily(
|
|
88403
|
+
if (run33.color && !isDefaultColor(run33.color))
|
|
88404
|
+
styles.push(`color:#${run33.color}`);
|
|
88405
|
+
if (run33.shade)
|
|
88406
|
+
styles.push(`background-color:#${run33.shade}`);
|
|
88407
|
+
if (run33.font && run33.font !== baseline.font) {
|
|
88408
|
+
styles.push(`font-family:${cssFontFamily(run33.font)}`);
|
|
88082
88409
|
}
|
|
88083
|
-
if (
|
|
88084
|
-
styles.push(`font-size:${
|
|
88410
|
+
if (run33.sizeHalfPoints !== undefined && run33.sizeHalfPoints !== baseline.sizeHalfPoints) {
|
|
88411
|
+
styles.push(`font-size:${run33.sizeHalfPoints / 2}pt`);
|
|
88085
88412
|
}
|
|
88086
|
-
if (
|
|
88413
|
+
if (run33.smallCaps)
|
|
88087
88414
|
styles.push("font-variant:small-caps");
|
|
88088
|
-
if (
|
|
88415
|
+
if (run33.allCaps)
|
|
88089
88416
|
styles.push("text-transform:uppercase");
|
|
88090
|
-
if (
|
|
88091
|
-
attrs.push(htmlAttr("data-color-theme",
|
|
88092
|
-
if (
|
|
88093
|
-
attrs.push(htmlAttr("data-color-theme-tint",
|
|
88417
|
+
if (run33.colorTheme && !isDefaultThemeColor(run33)) {
|
|
88418
|
+
attrs.push(htmlAttr("data-color-theme", run33.colorTheme));
|
|
88419
|
+
if (run33.colorThemeTint) {
|
|
88420
|
+
attrs.push(htmlAttr("data-color-theme-tint", run33.colorThemeTint));
|
|
88094
88421
|
}
|
|
88095
|
-
if (
|
|
88096
|
-
attrs.push(htmlAttr("data-color-theme-shade",
|
|
88422
|
+
if (run33.colorThemeShade) {
|
|
88423
|
+
attrs.push(htmlAttr("data-color-theme-shade", run33.colorThemeShade));
|
|
88097
88424
|
}
|
|
88098
88425
|
}
|
|
88099
88426
|
let out = body;
|
|
@@ -88102,18 +88429,18 @@ function wrapRunFormatting(body, run34, baseline) {
|
|
|
88102
88429
|
const attrPart = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
88103
88430
|
out = `<span${stylePart}${attrPart}>${out}</span>`;
|
|
88104
88431
|
}
|
|
88105
|
-
if (
|
|
88432
|
+
if (run33.underline === "single") {
|
|
88106
88433
|
out = `<u>${out}</u>`;
|
|
88107
|
-
} else if (
|
|
88108
|
-
const color2 =
|
|
88109
|
-
out = `<u ${htmlAttr("data-underline",
|
|
88434
|
+
} else if (run33.underline) {
|
|
88435
|
+
const color2 = run33.underlineColor ? ` ${htmlAttr("data-underline-color", run33.underlineColor)}` : "";
|
|
88436
|
+
out = `<u ${htmlAttr("data-underline", run33.underline)}${color2}>${out}</u>`;
|
|
88110
88437
|
}
|
|
88111
|
-
if (
|
|
88438
|
+
if (run33.vertAlign === "superscript")
|
|
88112
88439
|
out = `<sup>${out}</sup>`;
|
|
88113
|
-
else if (
|
|
88440
|
+
else if (run33.vertAlign === "subscript")
|
|
88114
88441
|
out = `<sub>${out}</sub>`;
|
|
88115
|
-
if (
|
|
88116
|
-
const named =
|
|
88442
|
+
if (run33.highlight) {
|
|
88443
|
+
const named = run33.highlight === "yellow" ? "" : ` ${htmlAttr("data-highlight", run33.highlight)}`;
|
|
88117
88444
|
out = `<mark${named}>${out}</mark>`;
|
|
88118
88445
|
}
|
|
88119
88446
|
return out;
|
|
@@ -88122,8 +88449,8 @@ function isDefaultColor(color2) {
|
|
|
88122
88449
|
const normalized = color2.toLowerCase();
|
|
88123
88450
|
return normalized === "000000" || normalized === "auto";
|
|
88124
88451
|
}
|
|
88125
|
-
function isDefaultThemeColor(
|
|
88126
|
-
return (
|
|
88452
|
+
function isDefaultThemeColor(run33) {
|
|
88453
|
+
return (run33.colorTheme === "text1" || run33.colorTheme === "dark1") && !run33.colorThemeTint && !run33.colorThemeShade;
|
|
88127
88454
|
}
|
|
88128
88455
|
function cssFontFamily(font) {
|
|
88129
88456
|
return /\s/.test(font) ? `'${font}'` : font;
|
|
@@ -88140,19 +88467,19 @@ function applyEscapeMask(text6, mask, offset2) {
|
|
|
88140
88467
|
}
|
|
88141
88468
|
function paragraphContent(runs, view) {
|
|
88142
88469
|
let content3 = "";
|
|
88143
|
-
for (const
|
|
88144
|
-
if (
|
|
88470
|
+
for (const run33 of runs) {
|
|
88471
|
+
if (run33.type !== "text")
|
|
88145
88472
|
continue;
|
|
88146
|
-
if (
|
|
88473
|
+
if (run33.runStyle === "Code")
|
|
88147
88474
|
continue;
|
|
88148
|
-
if (!isRunVisible(
|
|
88475
|
+
if (!isRunVisible(run33, view))
|
|
88149
88476
|
continue;
|
|
88150
|
-
content3 +=
|
|
88477
|
+
content3 += run33.text;
|
|
88151
88478
|
}
|
|
88152
88479
|
return content3;
|
|
88153
88480
|
}
|
|
88154
88481
|
function hasEquationRun(runs) {
|
|
88155
|
-
return runs.some((
|
|
88482
|
+
return runs.some((run33) => run33.type === "equation");
|
|
88156
88483
|
}
|
|
88157
88484
|
function renderTable(table, ctx) {
|
|
88158
88485
|
const view = ctx.options.view ?? "accepted";
|
|
@@ -88438,9 +88765,9 @@ var init_markdown3 = __esm(() => {
|
|
|
88438
88765
|
// src/cli/read/index.ts
|
|
88439
88766
|
var exports_read = {};
|
|
88440
88767
|
__export(exports_read, {
|
|
88441
|
-
run: () =>
|
|
88768
|
+
run: () => run33
|
|
88442
88769
|
});
|
|
88443
|
-
async function
|
|
88770
|
+
async function run33(args) {
|
|
88444
88771
|
const parsed = await tryParseArgs(args, {
|
|
88445
88772
|
ast: { type: "boolean" },
|
|
88446
88773
|
from: { type: "string" },
|
|
@@ -88450,16 +88777,16 @@ async function run34(args) {
|
|
|
88450
88777
|
current: { type: "boolean" },
|
|
88451
88778
|
comments: { type: "boolean" },
|
|
88452
88779
|
help: { type: "boolean", short: "h" }
|
|
88453
|
-
},
|
|
88780
|
+
}, HELP29);
|
|
88454
88781
|
if (typeof parsed === "number")
|
|
88455
88782
|
return parsed;
|
|
88456
88783
|
if (parsed.values.help) {
|
|
88457
|
-
await writeStdout(
|
|
88784
|
+
await writeStdout(HELP29);
|
|
88458
88785
|
return EXIT2.OK;
|
|
88459
88786
|
}
|
|
88460
88787
|
const path2 = parsed.positionals[0];
|
|
88461
88788
|
if (!path2)
|
|
88462
|
-
return fail("USAGE", "Missing FILE argument",
|
|
88789
|
+
return fail("USAGE", "Missing FILE argument", HELP29);
|
|
88463
88790
|
const ast = Boolean(parsed.values.ast);
|
|
88464
88791
|
const from = parsed.values.from;
|
|
88465
88792
|
const to = parsed.values.to;
|
|
@@ -88468,11 +88795,11 @@ async function run34(args) {
|
|
|
88468
88795
|
const current = Boolean(parsed.values.current);
|
|
88469
88796
|
const showComments = Boolean(parsed.values.comments);
|
|
88470
88797
|
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",
|
|
88798
|
+
return fail("USAGE", "--from, --to, --accepted, --baseline, --current, and --comments are Markdown-only and cannot be combined with --ast", HELP29);
|
|
88472
88799
|
}
|
|
88473
88800
|
const view = resolveView({ accepted, baseline, current });
|
|
88474
88801
|
if (!view) {
|
|
88475
|
-
return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive",
|
|
88802
|
+
return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive", HELP29);
|
|
88476
88803
|
}
|
|
88477
88804
|
const docView = await openOrFail(path2);
|
|
88478
88805
|
if (typeof docView === "number")
|
|
@@ -88488,7 +88815,8 @@ async function run34(args) {
|
|
|
88488
88815
|
to,
|
|
88489
88816
|
view,
|
|
88490
88817
|
showComments,
|
|
88491
|
-
defaultSizeHalfPoints: docView.styles?.defaultSizeHalfPoints()
|
|
88818
|
+
defaultSizeHalfPoints: docView.styles?.defaultSizeHalfPoints(),
|
|
88819
|
+
trackChangesOn: docView.isTrackChangesEnabled()
|
|
88492
88820
|
});
|
|
88493
88821
|
await writeStdout(rendered);
|
|
88494
88822
|
return EXIT2.OK;
|
|
@@ -88499,7 +88827,7 @@ async function run34(args) {
|
|
|
88499
88827
|
throw err;
|
|
88500
88828
|
}
|
|
88501
88829
|
}
|
|
88502
|
-
var
|
|
88830
|
+
var HELP29 = `docx read \u2014 render document body as Markdown, or print AST as JSON
|
|
88503
88831
|
|
|
88504
88832
|
Usage:
|
|
88505
88833
|
docx read FILE [options]
|
|
@@ -88589,20 +88917,20 @@ function parsePagesSpec(spec) {
|
|
|
88589
88917
|
// src/cli/render/index.ts
|
|
88590
88918
|
var exports_render = {};
|
|
88591
88919
|
__export(exports_render, {
|
|
88592
|
-
run: () =>
|
|
88920
|
+
run: () => run34
|
|
88593
88921
|
});
|
|
88594
88922
|
import { basename as basename2, extname as extname2, resolve as resolve2 } from "path";
|
|
88595
|
-
async function
|
|
88596
|
-
const parsed = await tryParseArgs(args,
|
|
88923
|
+
async function run34(args) {
|
|
88924
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC4, HELP30);
|
|
88597
88925
|
if (typeof parsed === "number")
|
|
88598
88926
|
return parsed;
|
|
88599
88927
|
if (parsed.values.help) {
|
|
88600
|
-
await writeStdout(
|
|
88928
|
+
await writeStdout(HELP30);
|
|
88601
88929
|
return EXIT2.OK;
|
|
88602
88930
|
}
|
|
88603
88931
|
const filePath = parsed.positionals[0];
|
|
88604
88932
|
if (!filePath)
|
|
88605
|
-
return fail("USAGE", "Missing FILE argument",
|
|
88933
|
+
return fail("USAGE", "Missing FILE argument", HELP30);
|
|
88606
88934
|
if (!await Bun.file(filePath).exists()) {
|
|
88607
88935
|
return fail("FILE_NOT_FOUND", `File not found: ${filePath}`);
|
|
88608
88936
|
}
|
|
@@ -88682,7 +89010,7 @@ function availabilityHint(installed) {
|
|
|
88682
89010
|
}
|
|
88683
89011
|
return `Detected engines: ${installed.join(", ")} \u2014 but none chose auto-select; pass --engine explicitly.`;
|
|
88684
89012
|
}
|
|
88685
|
-
var
|
|
89013
|
+
var HELP30 = `docx render \u2014 render each page of a .docx as a PNG/JPG image
|
|
88686
89014
|
|
|
88687
89015
|
Usage:
|
|
88688
89016
|
docx render FILE [options]
|
|
@@ -88734,11 +89062,11 @@ Runtime dependencies:
|
|
|
88734
89062
|
\u2014 no extra system tools (poppler / pdftoppm / ImageMagick) required.
|
|
88735
89063
|
|
|
88736
89064
|
Run "docx render --help" or "docx --help" for the full command list.
|
|
88737
|
-
`,
|
|
89065
|
+
`, OPTION_SPEC4;
|
|
88738
89066
|
var init_render2 = __esm(() => {
|
|
88739
89067
|
init_core2();
|
|
88740
89068
|
init_respond();
|
|
88741
|
-
|
|
89069
|
+
OPTION_SPEC4 = {
|
|
88742
89070
|
out: { type: "string" },
|
|
88743
89071
|
engine: { type: "string" },
|
|
88744
89072
|
dpi: { type: "string" },
|
|
@@ -88899,9 +89227,9 @@ var init_batch4 = __esm(() => {
|
|
|
88899
89227
|
// src/cli/replace/index.ts
|
|
88900
89228
|
var exports_replace3 = {};
|
|
88901
89229
|
__export(exports_replace3, {
|
|
88902
|
-
run: () =>
|
|
89230
|
+
run: () => run35
|
|
88903
89231
|
});
|
|
88904
|
-
async function
|
|
89232
|
+
async function run35(args) {
|
|
88905
89233
|
const parsed = await tryParseArgs(args, {
|
|
88906
89234
|
batch: { type: "string" },
|
|
88907
89235
|
regex: { type: "boolean" },
|
|
@@ -88914,30 +89242,30 @@ async function run36(args) {
|
|
|
88914
89242
|
baseline: { type: "boolean" },
|
|
88915
89243
|
exact: { type: "boolean" },
|
|
88916
89244
|
...SAVE_FLAGS
|
|
88917
|
-
},
|
|
89245
|
+
}, HELP31);
|
|
88918
89246
|
if (typeof parsed === "number")
|
|
88919
89247
|
return parsed;
|
|
88920
89248
|
if (parsed.values.help) {
|
|
88921
|
-
await writeStdout(
|
|
89249
|
+
await writeStdout(HELP31);
|
|
88922
89250
|
return EXIT2.OK;
|
|
88923
89251
|
}
|
|
88924
89252
|
setVerboseAck(Boolean(parsed.values.verbose));
|
|
88925
89253
|
const path2 = parsed.positionals[0];
|
|
88926
89254
|
if (!path2)
|
|
88927
|
-
return fail("USAGE", "Missing FILE argument",
|
|
89255
|
+
return fail("USAGE", "Missing FILE argument", HELP31);
|
|
88928
89256
|
const batchInput = parsed.values.batch;
|
|
88929
89257
|
if (batchInput !== undefined) {
|
|
88930
89258
|
if (parsed.positionals.length > 1) {
|
|
88931
|
-
return fail("USAGE", "--batch reads pattern/replacement from the JSONL file; don't also pass them as positionals",
|
|
89259
|
+
return fail("USAGE", "--batch reads pattern/replacement from the JSONL file; don't also pass them as positionals", HELP31);
|
|
88932
89260
|
}
|
|
88933
89261
|
return runReplaceBatch(path2, batchInput, parsed.values);
|
|
88934
89262
|
}
|
|
88935
89263
|
const pattern = parsed.positionals[1];
|
|
88936
89264
|
const replacement = parsed.positionals[2];
|
|
88937
89265
|
if (pattern == null)
|
|
88938
|
-
return fail("USAGE", "Missing PATTERN argument",
|
|
89266
|
+
return fail("USAGE", "Missing PATTERN argument", HELP31);
|
|
88939
89267
|
if (replacement == null) {
|
|
88940
|
-
return fail("USAGE", "Missing REPLACEMENT argument",
|
|
89268
|
+
return fail("USAGE", "Missing REPLACEMENT argument", HELP31);
|
|
88941
89269
|
}
|
|
88942
89270
|
const ignoreCase = Boolean(parsed.values["ignore-case"]);
|
|
88943
89271
|
const useRegex = Boolean(parsed.values.regex);
|
|
@@ -89041,6 +89369,8 @@ async function run36(args) {
|
|
|
89041
89369
|
replaceSpanInParagraph(blockRef.node, { start: match.start, end: match.end }, concreteReplacement, tracked, findView);
|
|
89042
89370
|
}
|
|
89043
89371
|
await document4.save(outputPath);
|
|
89372
|
+
const remaining = allMatches.length - selected.length;
|
|
89373
|
+
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
89374
|
await respondAck({
|
|
89045
89375
|
ok: true,
|
|
89046
89376
|
operation: "replace",
|
|
@@ -89054,10 +89384,10 @@ async function run36(args) {
|
|
|
89054
89384
|
replaced: selected.length,
|
|
89055
89385
|
matches: matchesPayload,
|
|
89056
89386
|
...normalizationFields
|
|
89057
|
-
});
|
|
89387
|
+
}, partialHint);
|
|
89058
89388
|
return EXIT2.OK;
|
|
89059
89389
|
}
|
|
89060
|
-
var
|
|
89390
|
+
var HELP31 = `docx replace \u2014 substitute text spans (sed for docx)
|
|
89061
89391
|
|
|
89062
89392
|
Usage:
|
|
89063
89393
|
docx replace FILE PATTERN REPLACEMENT [options]
|
|
@@ -89135,6 +89465,258 @@ var init_replace4 = __esm(() => {
|
|
|
89135
89465
|
init_batch4();
|
|
89136
89466
|
});
|
|
89137
89467
|
|
|
89468
|
+
// src/cli/sections/index.tsx
|
|
89469
|
+
var exports_sections = {};
|
|
89470
|
+
__export(exports_sections, {
|
|
89471
|
+
run: () => run36
|
|
89472
|
+
});
|
|
89473
|
+
async function run36(args) {
|
|
89474
|
+
const parsed = await tryParseArgs(args, OPTION_SPEC5, HELP32);
|
|
89475
|
+
if (typeof parsed === "number")
|
|
89476
|
+
return parsed;
|
|
89477
|
+
if (parsed.values.help) {
|
|
89478
|
+
await writeStdout(HELP32);
|
|
89479
|
+
return EXIT2.OK;
|
|
89480
|
+
}
|
|
89481
|
+
setVerboseAck(Boolean(parsed.values.verbose));
|
|
89482
|
+
const filePath = parsed.positionals[0];
|
|
89483
|
+
if (!filePath)
|
|
89484
|
+
return fail("USAGE", "Missing FILE argument", HELP32);
|
|
89485
|
+
const at = parsed.values.at;
|
|
89486
|
+
if (!at) {
|
|
89487
|
+
return fail("USAGE", "Missing --at LOCATOR (a range pN-pM or a section sN)", HELP32);
|
|
89488
|
+
}
|
|
89489
|
+
const count = parseCount(parsed.values.columns);
|
|
89490
|
+
if (typeof count === "number" && Number.isNaN(count)) {
|
|
89491
|
+
return fail("USAGE", `--columns must be a positive integer`, HELP32);
|
|
89492
|
+
}
|
|
89493
|
+
if (count === undefined)
|
|
89494
|
+
return fail("USAGE", "Missing --columns N", HELP32);
|
|
89495
|
+
const typeRaw = parsed.values.type;
|
|
89496
|
+
if (typeRaw !== undefined && !isSectionType(typeRaw)) {
|
|
89497
|
+
return fail("USAGE", `Invalid --type: ${typeRaw}`, "Valid values: continuous, nextPage, evenPage, oddPage, nextColumn");
|
|
89498
|
+
}
|
|
89499
|
+
let locator;
|
|
89500
|
+
try {
|
|
89501
|
+
locator = parseLocator(at);
|
|
89502
|
+
} catch (error) {
|
|
89503
|
+
if (error instanceof LocatorParseError) {
|
|
89504
|
+
return fail("INVALID_LOCATOR", error.message, HELP32);
|
|
89505
|
+
}
|
|
89506
|
+
throw error;
|
|
89507
|
+
}
|
|
89508
|
+
const document4 = await openOrFail(filePath);
|
|
89509
|
+
if (typeof document4 === "number")
|
|
89510
|
+
return document4;
|
|
89511
|
+
const opts = {
|
|
89512
|
+
filePath,
|
|
89513
|
+
count,
|
|
89514
|
+
sectionType: typeRaw,
|
|
89515
|
+
authorFlag: parsed.values.author,
|
|
89516
|
+
trackFlag: Boolean(parsed.values.track),
|
|
89517
|
+
outputPath: parsed.values.output,
|
|
89518
|
+
dryRun: Boolean(parsed.values["dry-run"])
|
|
89519
|
+
};
|
|
89520
|
+
if (locator.kind === "blockRange") {
|
|
89521
|
+
const range = await resolveBlockRangeOrFail(document4, at);
|
|
89522
|
+
if (typeof range === "number")
|
|
89523
|
+
return range;
|
|
89524
|
+
return wrapRange(document4, range.parent, range.startIndex, range.endIndex, at, opts);
|
|
89525
|
+
}
|
|
89526
|
+
const blockRef = await resolveBlockOrFail(document4, at);
|
|
89527
|
+
if (typeof blockRef === "number")
|
|
89528
|
+
return blockRef;
|
|
89529
|
+
if (blockRef.node.tag === "w:sectPr") {
|
|
89530
|
+
return editSection(document4, blockRef, at, opts);
|
|
89531
|
+
}
|
|
89532
|
+
if (blockRef.node.tag === "w:p") {
|
|
89533
|
+
const index2 = blockRef.parent.indexOf(blockRef.node);
|
|
89534
|
+
return wrapRange(document4, blockRef.parent, index2, index2, at, opts);
|
|
89535
|
+
}
|
|
89536
|
+
return fail("INVALID_LOCATOR", `columns needs a section (sN) or a paragraph range (pN-pM); ${at} is neither`, HELP32);
|
|
89537
|
+
}
|
|
89538
|
+
async function editSection(document4, blockRef, at, opts) {
|
|
89539
|
+
try {
|
|
89540
|
+
new Edit(document4).section(blockRef, { columns: opts.count, sectionType: opts.sectionType }, { authorFlag: opts.authorFlag, track: opts.trackFlag });
|
|
89541
|
+
} catch (error) {
|
|
89542
|
+
if (error instanceof EditError)
|
|
89543
|
+
return fail(error.code, error.message);
|
|
89544
|
+
throw error;
|
|
89545
|
+
}
|
|
89546
|
+
return commit(document4, opts, { at, mode: "section" });
|
|
89547
|
+
}
|
|
89548
|
+
async function wrapRange(document4, parent, startIndex, endIndex, at, opts) {
|
|
89549
|
+
if (parent !== document4.body.findBodyChildren()) {
|
|
89550
|
+
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.");
|
|
89551
|
+
}
|
|
89552
|
+
for (let index2 = startIndex;index2 <= endIndex; index2++) {
|
|
89553
|
+
if (containsSectionBreak(parent[index2])) {
|
|
89554
|
+
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.");
|
|
89555
|
+
}
|
|
89556
|
+
}
|
|
89557
|
+
const governing = governingColumns(parent, endIndex + 1);
|
|
89558
|
+
const track = resolveTracked(document4, opts.trackFlag);
|
|
89559
|
+
const insert = new Insert(document4);
|
|
89560
|
+
const allocator = track ? new TrackChanges(document4).createAllocator() : undefined;
|
|
89561
|
+
const endNode = parent[endIndex];
|
|
89562
|
+
if (!endNode) {
|
|
89563
|
+
return fail("BLOCK_NOT_FOUND", "Range end is stale (parent does not contain it)");
|
|
89564
|
+
}
|
|
89565
|
+
const startNode = startIndex > 0 ? parent[startIndex] : undefined;
|
|
89566
|
+
if (startIndex > 0 && !startNode) {
|
|
89567
|
+
return fail("BLOCK_NOT_FOUND", "Range start is stale (parent does not contain it)");
|
|
89568
|
+
}
|
|
89569
|
+
let afterBlocks;
|
|
89570
|
+
let beforeBlocks = [];
|
|
89571
|
+
try {
|
|
89572
|
+
afterBlocks = await insert.paragraph({ node: endNode, parent }, {
|
|
89573
|
+
kind: "section",
|
|
89574
|
+
columns: opts.count,
|
|
89575
|
+
sectionType: opts.sectionType ?? "continuous"
|
|
89576
|
+
}, {}, { placement: "after", authorFlag: opts.authorFlag, track, allocator });
|
|
89577
|
+
if (startNode) {
|
|
89578
|
+
beforeBlocks = await insert.paragraph({ node: startNode, parent }, {
|
|
89579
|
+
kind: "section",
|
|
89580
|
+
...governing > 1 ? { columns: governing } : {},
|
|
89581
|
+
sectionType: "continuous"
|
|
89582
|
+
}, {}, { placement: "before", authorFlag: opts.authorFlag, track, allocator });
|
|
89583
|
+
}
|
|
89584
|
+
} catch (error) {
|
|
89585
|
+
if (error instanceof InsertError)
|
|
89586
|
+
return fail(error.code, error.message, error.hint);
|
|
89587
|
+
throw error;
|
|
89588
|
+
}
|
|
89589
|
+
if (opts.dryRun) {
|
|
89590
|
+
return commit(document4, opts, { at, mode: "range", dryRunOnly: true });
|
|
89591
|
+
}
|
|
89592
|
+
parent.splice(endIndex + 1, 0, ...afterBlocks);
|
|
89593
|
+
parent.splice(startIndex, 0, ...beforeBlocks);
|
|
89594
|
+
return commit(document4, opts, { at, mode: "range" });
|
|
89595
|
+
}
|
|
89596
|
+
function containsSectionBreak(node2) {
|
|
89597
|
+
if (!node2)
|
|
89598
|
+
return false;
|
|
89599
|
+
if (node2.tag === "w:sectPr")
|
|
89600
|
+
return true;
|
|
89601
|
+
if (node2.tag !== "w:p")
|
|
89602
|
+
return false;
|
|
89603
|
+
return Boolean(node2.findChild("w:pPr")?.findChild("w:sectPr"));
|
|
89604
|
+
}
|
|
89605
|
+
function governingColumns(parent, fromIndex) {
|
|
89606
|
+
for (let index2 = fromIndex;index2 < parent.length; index2++) {
|
|
89607
|
+
const node2 = parent[index2];
|
|
89608
|
+
if (!node2)
|
|
89609
|
+
continue;
|
|
89610
|
+
if (node2.tag === "w:sectPr")
|
|
89611
|
+
return columnsOf(node2);
|
|
89612
|
+
if (node2.tag === "w:p") {
|
|
89613
|
+
const inline = node2.findChild("w:pPr")?.findChild("w:sectPr");
|
|
89614
|
+
if (inline)
|
|
89615
|
+
return columnsOf(inline);
|
|
89616
|
+
}
|
|
89617
|
+
}
|
|
89618
|
+
return 1;
|
|
89619
|
+
}
|
|
89620
|
+
function columnsOf(sectPr) {
|
|
89621
|
+
const raw = sectPr.findChild("w:cols")?.getAttribute("w:num");
|
|
89622
|
+
const parsed = raw ? Number.parseInt(raw, 10) : 1;
|
|
89623
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
|
|
89624
|
+
}
|
|
89625
|
+
function parseCount(raw) {
|
|
89626
|
+
if (raw === undefined)
|
|
89627
|
+
return;
|
|
89628
|
+
if (!/^\d+$/.test(raw.trim()))
|
|
89629
|
+
return Number.NaN;
|
|
89630
|
+
const parsed = Number.parseInt(raw, 10);
|
|
89631
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
89632
|
+
return Number.NaN;
|
|
89633
|
+
return parsed;
|
|
89634
|
+
}
|
|
89635
|
+
async function commit(document4, opts, meta) {
|
|
89636
|
+
if (opts.dryRun || meta.dryRunOnly) {
|
|
89637
|
+
await respond({
|
|
89638
|
+
operation: "sections",
|
|
89639
|
+
dryRun: true,
|
|
89640
|
+
path: opts.filePath,
|
|
89641
|
+
locator: meta.at,
|
|
89642
|
+
columnCount: opts.count,
|
|
89643
|
+
mode: meta.mode,
|
|
89644
|
+
...opts.outputPath ? { output: opts.outputPath } : {}
|
|
89645
|
+
});
|
|
89646
|
+
return EXIT2.OK;
|
|
89647
|
+
}
|
|
89648
|
+
await document4.save(opts.outputPath);
|
|
89649
|
+
const destination = opts.outputPath ?? opts.filePath;
|
|
89650
|
+
await respondAck({
|
|
89651
|
+
ok: true,
|
|
89652
|
+
operation: "sections",
|
|
89653
|
+
path: destination,
|
|
89654
|
+
locator: meta.at,
|
|
89655
|
+
columnCount: opts.count,
|
|
89656
|
+
mode: meta.mode
|
|
89657
|
+
}, renderVerifyHint(destination));
|
|
89658
|
+
return EXIT2.OK;
|
|
89659
|
+
}
|
|
89660
|
+
var HELP32 = `docx sections \u2014 multi-column layout & section breaks
|
|
89661
|
+
|
|
89662
|
+
Usage:
|
|
89663
|
+
docx sections FILE --at LOCATOR --columns N [options]
|
|
89664
|
+
|
|
89665
|
+
The verb for section layout \u2014 multi-column flow and section breaks \u2014 so you
|
|
89666
|
+
don't have to hand-build them with the right OOXML semantics. This is the ONLY
|
|
89667
|
+
way to add/change column layout; \`insert\` no longer takes --section (a raw
|
|
89668
|
+
section break formats the content ABOVE it, which is the classic off-by-one).
|
|
89669
|
+
Two addressing modes:
|
|
89670
|
+
|
|
89671
|
+
--at pN-pM Wrap the paragraph range pN\u2026pM in its own N-column section
|
|
89672
|
+
(inserts the bounding continuous section breaks for you, so the
|
|
89673
|
+
columns land on EXACTLY pN\u2026pM). Also accepts a single paragraph
|
|
89674
|
+
(--at pN). THIS is how you put text in columns \u2014 name the range.
|
|
89675
|
+
--at sN Set the column count on an EXISTING section break sN (the section
|
|
89676
|
+
whose content ENDS at sN). Equivalent to \`edit --at sN --columns N\`.
|
|
89677
|
+
|
|
89678
|
+
Options:
|
|
89679
|
+
--at LOCATOR Paragraph range (pN-pM), single paragraph (pN), or section (sN)
|
|
89680
|
+
--columns N Number of columns (>= 1; use 1 to collapse back to single column)
|
|
89681
|
+
--type T Section type for the wrapping break: continuous (default),
|
|
89682
|
+
nextPage, evenPage, oddPage, nextColumn. Only meaningful with
|
|
89683
|
+
a pN-pM/pN range; with sN it overrides the section's type.
|
|
89684
|
+
--author NAME Author for tracked changes (default: $DOCX_AUTHOR)
|
|
89685
|
+
--track Record as a tracked change even when the doc toggle is off
|
|
89686
|
+
-o, --output PATH Write to PATH instead of overwriting FILE
|
|
89687
|
+
--dry-run Print what would change; do not write the file
|
|
89688
|
+
-v, --verbose Print the full success ack JSON
|
|
89689
|
+
-h, --help Show this help
|
|
89690
|
+
|
|
89691
|
+
Agent tip: VERIFY LAYOUT VISUALLY. \`docx read\` shows the section as a
|
|
89692
|
+
\`<!-- docx:section \u2026 cols="N" -->\` annotation but NOT how the columns actually
|
|
89693
|
+
flow on the page (balance, overflow). After setting columns, render and look:
|
|
89694
|
+
docx render FILE --out pages/
|
|
89695
|
+
Adjust the range and re-render until the columns read the way you intended.
|
|
89696
|
+
|
|
89697
|
+
Output:
|
|
89698
|
+
Prints a one-line confirmation on success (exit 0); --verbose prints {ok:true, \u2026}. Positional ids shift
|
|
89699
|
+
after a range wrap (two section breaks are inserted), so re-read before further
|
|
89700
|
+
edits. Errors print {code, error, hint?} + nonzero exit.
|
|
89701
|
+
|
|
89702
|
+
Examples:
|
|
89703
|
+
docx sections doc.docx --at p4-p9 --columns 2
|
|
89704
|
+
docx sections doc.docx --at p4-p9 --columns 3 --type continuous
|
|
89705
|
+
docx sections doc.docx --at s2 --columns 1 # collapse section s2 to one column
|
|
89706
|
+
`, OPTION_SPEC5;
|
|
89707
|
+
var init_sections2 = __esm(() => {
|
|
89708
|
+
init_core2();
|
|
89709
|
+
init_respond();
|
|
89710
|
+
OPTION_SPEC5 = {
|
|
89711
|
+
at: { type: "string" },
|
|
89712
|
+
columns: { type: "string" },
|
|
89713
|
+
type: { type: "string" },
|
|
89714
|
+
author: { type: "string" },
|
|
89715
|
+
track: { type: "boolean" },
|
|
89716
|
+
...SAVE_FLAGS
|
|
89717
|
+
};
|
|
89718
|
+
});
|
|
89719
|
+
|
|
89138
89720
|
// src/cli/styles/index.ts
|
|
89139
89721
|
var exports_styles = {};
|
|
89140
89722
|
__export(exports_styles, {
|
|
@@ -89366,8 +89948,15 @@ async function run38(args) {
|
|
|
89366
89948
|
return fail("USAGE", `--position must be an integer in 0..${grid.rows.length}`);
|
|
89367
89949
|
}
|
|
89368
89950
|
const cellTexts = parsed.values.cells ? parsed.values.cells.split(",") : [];
|
|
89369
|
-
|
|
89370
|
-
|
|
89951
|
+
for (const cell of cellTexts) {
|
|
89952
|
+
const mangled = await rejectShellMangledValue(cell, HELP34, "--cells");
|
|
89953
|
+
if (typeof mangled === "number")
|
|
89954
|
+
return mangled;
|
|
89955
|
+
}
|
|
89956
|
+
const reference = referenceRow(grid, position2);
|
|
89957
|
+
const logicalCols = reference ? reference.cells.length : grid.colCount;
|
|
89958
|
+
if (cellTexts.length > logicalCols) {
|
|
89959
|
+
return fail("USAGE", `--cells has ${cellTexts.length} entries but the row has ${logicalCols} columns (a merged cell counts once)`);
|
|
89371
89960
|
}
|
|
89372
89961
|
const newRow = buildRow(grid, position2, cellTexts);
|
|
89373
89962
|
const tracking = resolveTracked(document4, parsed.values.track);
|
|
@@ -89409,9 +89998,16 @@ function resolveRowPosition(raw, rowCount) {
|
|
|
89409
89998
|
return null;
|
|
89410
89999
|
return value;
|
|
89411
90000
|
}
|
|
90001
|
+
function referenceRow(grid, position2) {
|
|
90002
|
+
const above = position2 > 0 ? grid.rows[position2 - 1] : undefined;
|
|
90003
|
+
const below = position2 < grid.rows.length ? grid.rows[position2] : undefined;
|
|
90004
|
+
return above ?? below;
|
|
90005
|
+
}
|
|
89412
90006
|
function buildRow(grid, position2, cellTexts) {
|
|
89413
90007
|
const below = position2 > 0 && position2 < grid.rows.length ? grid.rows[position2] : undefined;
|
|
90008
|
+
const spans = referenceRow(grid, position2);
|
|
89414
90009
|
const cells = [];
|
|
90010
|
+
let logical = 0;
|
|
89415
90011
|
for (let col = 0;col < grid.colCount; ) {
|
|
89416
90012
|
const continued = below ? cellAt(below, col) : undefined;
|
|
89417
90013
|
if (continued?.vMerge === "continue") {
|
|
@@ -89425,12 +90021,15 @@ function buildRow(grid, position2, cellTexts) {
|
|
|
89425
90021
|
col += continued.colSpan;
|
|
89426
90022
|
continue;
|
|
89427
90023
|
}
|
|
90024
|
+
const refSpan = spans ? cellAt(spans, col)?.colSpan ?? 1 : 1;
|
|
89428
90025
|
cells.push(/* @__PURE__ */ jsxDEV(TableCell, {
|
|
90026
|
+
gridSpan: refSpan > 1 ? refSpan : undefined,
|
|
89429
90027
|
children: /* @__PURE__ */ jsxDEV(Paragraph, {
|
|
89430
|
-
text: cellTexts[
|
|
90028
|
+
text: cellTexts[logical] ?? ""
|
|
89431
90029
|
}, undefined, false, undefined, this)
|
|
89432
90030
|
}, undefined, false, undefined, this));
|
|
89433
|
-
|
|
90031
|
+
logical += 1;
|
|
90032
|
+
col += refSpan;
|
|
89434
90033
|
}
|
|
89435
90034
|
return /* @__PURE__ */ jsxDEV(w.tr, {
|
|
89436
90035
|
children: cells
|
|
@@ -89450,6 +90049,7 @@ var init_insert_row = __esm(() => {
|
|
|
89450
90049
|
init_jsx();
|
|
89451
90050
|
init_locators();
|
|
89452
90051
|
init_table();
|
|
90052
|
+
init_parse_helpers();
|
|
89453
90053
|
init_respond();
|
|
89454
90054
|
init_jsx_dev_runtime();
|
|
89455
90055
|
AT_FORMS6 = describeForms(["table"], " ");
|
|
@@ -89465,8 +90065,11 @@ ${AT_FORMS6}
|
|
|
89465
90065
|
|
|
89466
90066
|
Optional:
|
|
89467
90067
|
--position INDEX 0-based row index to insert at (default: append at end)
|
|
89468
|
-
--cells "a,b,c" Comma-separated text
|
|
89469
|
-
|
|
90068
|
+
--cells "a,b,c" Comma-separated text, one value per VISIBLE cell left to
|
|
90069
|
+
right (default: empty). On a table with merged cells the new
|
|
90070
|
+
row copies the neighbor row's gridSpan pattern, so you pass
|
|
90071
|
+
one value per logical column (a spanned cell counts once),
|
|
90072
|
+
NOT one per underlying grid column.
|
|
89470
90073
|
--author NAME Author for tracked insertion (default: $DOCX_AUTHOR)
|
|
89471
90074
|
-o, --output PATH Write to PATH instead of overwriting FILE
|
|
89472
90075
|
--dry-run Print what would change; do not write
|
|
@@ -89999,10 +90602,13 @@ async function run42(args) {
|
|
|
89999
90602
|
const cols = grid.tblGrid.findChildren("w:gridCol");
|
|
90000
90603
|
let twips = [];
|
|
90001
90604
|
if (!auto) {
|
|
90002
|
-
const resolved = resolveWidths(widthsSpec, cols);
|
|
90605
|
+
const resolved = resolveWidths(widthsSpec, cols, grid);
|
|
90003
90606
|
if (typeof resolved === "string")
|
|
90004
90607
|
return fail("USAGE", resolved);
|
|
90005
90608
|
twips = resolved;
|
|
90609
|
+
const tooNarrow = findTooNarrowCell(grid, twips);
|
|
90610
|
+
if (tooNarrow)
|
|
90611
|
+
return fail("USAGE", tooNarrow);
|
|
90006
90612
|
}
|
|
90007
90613
|
const outputPath = parsed.values.output;
|
|
90008
90614
|
if (parsed.values["dry-run"]) {
|
|
@@ -90038,20 +90644,24 @@ async function run42(args) {
|
|
|
90038
90644
|
appendTblGridChange(grid.tblGrid, priorCols, new TrackChanges(document4).mintMeta(author));
|
|
90039
90645
|
}
|
|
90040
90646
|
await document4.save(outputPath);
|
|
90647
|
+
const destination = outputPath ?? path2;
|
|
90648
|
+
const echo = auto ? "" : `${describeColumnWidths(twips)}
|
|
90649
|
+
`;
|
|
90041
90650
|
await respondAck({
|
|
90042
90651
|
ok: true,
|
|
90043
90652
|
operation: "tables.set-widths",
|
|
90044
|
-
path:
|
|
90653
|
+
path: destination,
|
|
90045
90654
|
table: tableId,
|
|
90046
90655
|
layout: auto ? "autofit" : "fixed",
|
|
90047
90656
|
widths: auto ? "auto" : twips
|
|
90048
|
-
});
|
|
90657
|
+
}, `${echo}${renderVerifyHint(destination)}`);
|
|
90049
90658
|
return EXIT2.OK;
|
|
90050
90659
|
}
|
|
90051
|
-
function resolveWidths(spec, cols) {
|
|
90660
|
+
function resolveWidths(spec, cols, grid) {
|
|
90052
90661
|
const tokens = spec.split(",").map((token) => token.trim());
|
|
90053
90662
|
if (tokens.length !== cols.length) {
|
|
90054
|
-
|
|
90663
|
+
const base = `--widths has ${tokens.length} entries but the table has ${cols.length} grid columns`;
|
|
90664
|
+
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
90665
|
}
|
|
90056
90666
|
const percentage = tokens.every((token) => token.endsWith("%"));
|
|
90057
90667
|
const anyPercent = tokens.some((token) => token.endsWith("%"));
|
|
@@ -90103,7 +90713,30 @@ function cellWidth(cell, twips) {
|
|
|
90103
90713
|
}
|
|
90104
90714
|
return width;
|
|
90105
90715
|
}
|
|
90106
|
-
|
|
90716
|
+
function findTooNarrowCell(grid, twips) {
|
|
90717
|
+
for (const row of grid.rows) {
|
|
90718
|
+
for (const cell of row.cells) {
|
|
90719
|
+
const width = cellWidth(cell, twips);
|
|
90720
|
+
if (width >= MIN_COL_TWIPS)
|
|
90721
|
+
continue;
|
|
90722
|
+
const text6 = cell.node.collectText().trim();
|
|
90723
|
+
if (text6.length === 0)
|
|
90724
|
+
continue;
|
|
90725
|
+
const where = cell.colSpan > 1 ? `grid columns ${cell.colStart}\u2013${cell.colStart + cell.colSpan - 1}` : `grid column ${cell.colStart}`;
|
|
90726
|
+
const sample = text6.length > 24 ? `${text6.slice(0, 24)}\u2026` : text6;
|
|
90727
|
+
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.`;
|
|
90728
|
+
}
|
|
90729
|
+
}
|
|
90730
|
+
return null;
|
|
90731
|
+
}
|
|
90732
|
+
function hasMergedColumns(grid) {
|
|
90733
|
+
return grid.rows.some((row) => row.cells.some((cell) => cell.colSpan > 1));
|
|
90734
|
+
}
|
|
90735
|
+
function describeColumnWidths(twips) {
|
|
90736
|
+
const cells = twips.map((value, index2) => `g${index2}=${twipsToInches(value)}in`);
|
|
90737
|
+
return `widths: ${cells.join(" ")}`;
|
|
90738
|
+
}
|
|
90739
|
+
var AT_FORMS10, HELP38, MIN_COL_TWIPS = 288;
|
|
90107
90740
|
var init_set_widths = __esm(() => {
|
|
90108
90741
|
init_core2();
|
|
90109
90742
|
init_locators();
|
|
@@ -90136,6 +90769,15 @@ cell's <w:tcW>. Under track-changes the resize is recorded as a real revision
|
|
|
90136
90769
|
(<w:tblGridChange> for the grid plus a per-cell <w:tcPrChange>), so it can be
|
|
90137
90770
|
accepted or rejected \u2014 matching what Word emits for a width change.
|
|
90138
90771
|
|
|
90772
|
+
Widths map one value per GRID column, not per visible column. On a table with
|
|
90773
|
+
merged cells (gridSpan), the grid has MORE columns than a single row shows, so
|
|
90774
|
+
the count you pass must match the grid (run \`docx read --ast\` to see it). A
|
|
90775
|
+
cell that HOLDS TEXT but lands narrower than ~0.2in is refused \u2014 after ~0.15in
|
|
90776
|
+
of cell margin it fits under one character, so Word wraps it one char per line
|
|
90777
|
+
(empty/spacer columns that thin are fine, nothing to wrap). The success line
|
|
90778
|
+
echoes the resulting per-column widths; since layout changes don't show in
|
|
90779
|
+
\`read\`, render to verify.
|
|
90780
|
+
|
|
90139
90781
|
Output:
|
|
90140
90782
|
Prints a one-line confirmation on success (exit 0). --verbose prints {ok:true, operation, path, table,
|
|
90141
90783
|
layout, widths}. --dry-run prints the preview object (no ok field). Errors
|
|
@@ -90677,6 +91319,64 @@ var init_tables = __esm(() => {
|
|
|
90677
91319
|
};
|
|
90678
91320
|
});
|
|
90679
91321
|
|
|
91322
|
+
// src/cli/track-changes/groups.ts
|
|
91323
|
+
function revisionGroups(changes) {
|
|
91324
|
+
const sorted = [...changes].sort((a2, b) => tcIndex(a2.id) - tcIndex(b.id));
|
|
91325
|
+
const membersOf = new Map;
|
|
91326
|
+
const revOf = new Map;
|
|
91327
|
+
let next = 0;
|
|
91328
|
+
let index2 = 0;
|
|
91329
|
+
while (index2 < sorted.length) {
|
|
91330
|
+
const a2 = sorted[index2];
|
|
91331
|
+
const b = sorted[index2 + 1];
|
|
91332
|
+
if (a2 && b && isTextReplacePair(a2, b)) {
|
|
91333
|
+
const rev = `rev${next++}`;
|
|
91334
|
+
membersOf.set(rev, [a2.id, b.id]);
|
|
91335
|
+
revOf.set(a2.id, rev);
|
|
91336
|
+
revOf.set(b.id, rev);
|
|
91337
|
+
index2 += 2;
|
|
91338
|
+
continue;
|
|
91339
|
+
}
|
|
91340
|
+
index2 += 1;
|
|
91341
|
+
}
|
|
91342
|
+
return { membersOf, revOf };
|
|
91343
|
+
}
|
|
91344
|
+
function isTextReplacePair(a2, b) {
|
|
91345
|
+
if (a2.blockId === undefined || a2.blockId !== b.blockId)
|
|
91346
|
+
return false;
|
|
91347
|
+
const pair = `${a2.kind}+${b.kind}`;
|
|
91348
|
+
return pair === "del+ins" || pair === "ins+del";
|
|
91349
|
+
}
|
|
91350
|
+
function expandRevisionTargets(targets, groups) {
|
|
91351
|
+
const out = [];
|
|
91352
|
+
for (const target of targets) {
|
|
91353
|
+
if (/^rev\d+$/.test(target)) {
|
|
91354
|
+
const members = groups.membersOf.get(target);
|
|
91355
|
+
if (!members)
|
|
91356
|
+
throw new UnknownRevisionError(target);
|
|
91357
|
+
out.push(...members);
|
|
91358
|
+
continue;
|
|
91359
|
+
}
|
|
91360
|
+
out.push(target);
|
|
91361
|
+
}
|
|
91362
|
+
return out;
|
|
91363
|
+
}
|
|
91364
|
+
function tcIndex(id) {
|
|
91365
|
+
const match = id.match(/^tc(\d+)$/);
|
|
91366
|
+
return match?.[1] ? Number(match[1]) : 0;
|
|
91367
|
+
}
|
|
91368
|
+
var UnknownRevisionError;
|
|
91369
|
+
var init_groups = __esm(() => {
|
|
91370
|
+
UnknownRevisionError = class UnknownRevisionError extends Error {
|
|
91371
|
+
revision;
|
|
91372
|
+
constructor(revision) {
|
|
91373
|
+
super(`Unknown revision group "${revision}"`);
|
|
91374
|
+
this.revision = revision;
|
|
91375
|
+
this.name = "UnknownRevisionError";
|
|
91376
|
+
}
|
|
91377
|
+
};
|
|
91378
|
+
});
|
|
91379
|
+
|
|
90680
91380
|
// src/cli/track-changes/list.ts
|
|
90681
91381
|
var exports_list5 = {};
|
|
90682
91382
|
__export(exports_list5, {
|
|
@@ -90737,6 +91437,12 @@ async function run47(args) {
|
|
|
90737
91437
|
byId.set(change.id, record);
|
|
90738
91438
|
}
|
|
90739
91439
|
const sorted = [...byId.values()].sort((a2, b) => trackedChangeIndex(a2.id) - trackedChangeIndex(b.id));
|
|
91440
|
+
const { revOf } = revisionGroups(sorted);
|
|
91441
|
+
for (const record of sorted) {
|
|
91442
|
+
const group = revOf.get(record.id);
|
|
91443
|
+
if (group)
|
|
91444
|
+
record.group = group;
|
|
91445
|
+
}
|
|
90740
91446
|
await respond(sorted);
|
|
90741
91447
|
return EXIT2.OK;
|
|
90742
91448
|
}
|
|
@@ -90761,7 +91467,11 @@ apart.
|
|
|
90761
91467
|
|
|
90762
91468
|
Output: a bare JSON array of { id, kind, author, date, revisionId, blockId,
|
|
90763
91469
|
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\`.
|
|
91470
|
+
addressable handle \u2014 pass it to \`accept\`/\`reject --at tcN\`. When a del and an
|
|
91471
|
+
ins are an adjacent REPLACE pair on the same paragraph, BOTH carry a shared
|
|
91472
|
+
"group": "revN" \u2014 accept/reject the whole logical change in one call with
|
|
91473
|
+
\`--at revN\` instead of accepting each half separately (tcN ids renumber after
|
|
91474
|
+
each single accept, so the revN handle avoids the re-list ping-pong). Errors print
|
|
90765
91475
|
{code, error, hint?} with a nonzero exit. kind is one of: "ins", "del", "moveFrom",
|
|
90766
91476
|
"moveTo", "sectPrChange", "rowIns", "rowDel", "cellIns", "cellDel",
|
|
90767
91477
|
"tblGridChange", "tblPrChange", "tcPrChange", "checkboxToggle". Paragraph-mark
|
|
@@ -90790,6 +91500,7 @@ var init_list7 = __esm(() => {
|
|
|
90790
91500
|
init_core2();
|
|
90791
91501
|
init_track_changes();
|
|
90792
91502
|
init_respond();
|
|
91503
|
+
init_groups();
|
|
90793
91504
|
});
|
|
90794
91505
|
|
|
90795
91506
|
// src/cli/track-changes/apply.ts
|
|
@@ -90820,8 +91531,20 @@ async function runApply(args, verb, help) {
|
|
|
90820
91531
|
const document4 = await openOrFail(path2);
|
|
90821
91532
|
if (typeof document4 === "number")
|
|
90822
91533
|
return document4;
|
|
90823
|
-
const target = all2 ? "all" : atRaw ?? [];
|
|
90824
91534
|
const trackChanges = new TrackChanges(document4);
|
|
91535
|
+
let target;
|
|
91536
|
+
if (all2) {
|
|
91537
|
+
target = "all";
|
|
91538
|
+
} else {
|
|
91539
|
+
try {
|
|
91540
|
+
target = expandRevisionTargets(atRaw ?? [], revisionGroups(trackChanges.list()));
|
|
91541
|
+
} catch (error) {
|
|
91542
|
+
if (error instanceof UnknownRevisionError) {
|
|
91543
|
+
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.");
|
|
91544
|
+
}
|
|
91545
|
+
throw error;
|
|
91546
|
+
}
|
|
91547
|
+
}
|
|
90825
91548
|
const outputPath = parsed.values.output;
|
|
90826
91549
|
try {
|
|
90827
91550
|
if (parsed.values["dry-run"]) {
|
|
@@ -90853,6 +91576,7 @@ async function runApply(args, verb, help) {
|
|
|
90853
91576
|
var init_apply2 = __esm(() => {
|
|
90854
91577
|
init_track_changes();
|
|
90855
91578
|
init_respond();
|
|
91579
|
+
init_groups();
|
|
90856
91580
|
});
|
|
90857
91581
|
|
|
90858
91582
|
// src/cli/track-changes/accept.ts
|
|
@@ -90899,6 +91623,10 @@ Target (one required, mutually exclusive):
|
|
|
90899
91623
|
batch is not a concern. Supports:
|
|
90900
91624
|
${AT_FORMS14}
|
|
90901
91625
|
See \`docx info locators\`.
|
|
91626
|
+
--at revN Accept a del+ins REPLACE pair in one call (both halves of one
|
|
91627
|
+
logical change). \`list\` tags the two tcNs with a shared
|
|
91628
|
+
"group": "revN"; addressing the revN saves the accept-relist-
|
|
91629
|
+
accept ping-pong (tcN ids renumber after each single accept).
|
|
90902
91630
|
--all Accept every tracked change.
|
|
90903
91631
|
|
|
90904
91632
|
Options:
|
|
@@ -90952,7 +91680,7 @@ were in effect before the tracked edit.
|
|
|
90952
91680
|
|
|
90953
91681
|
Paragraph-mark trackings (<w:ins>/<w:del> inside <w:pPr><w:rPr>): rejecting
|
|
90954
91682
|
a paragraph-mark insertion removes the entire owning paragraph (the inserted
|
|
90955
|
-
break disappears \u2014 for sentinels created by "
|
|
91683
|
+
break disappears \u2014 for sentinels created by "docx sections" this also
|
|
90956
91684
|
removes the section break the sentinel was carrying). Rejecting a
|
|
90957
91685
|
paragraph-mark deletion just removes the marker (the paragraph stays).
|
|
90958
91686
|
|
|
@@ -90970,6 +91698,10 @@ Target (one required, mutually exclusive):
|
|
|
90970
91698
|
batch is not a concern. Supports:
|
|
90971
91699
|
${AT_FORMS15}
|
|
90972
91700
|
See \`docx info locators\`.
|
|
91701
|
+
--at revN Reject a del+ins REPLACE pair in one call (both halves of one
|
|
91702
|
+
logical change). \`list\` tags the two tcNs with a shared
|
|
91703
|
+
"group": "revN"; addressing the revN saves the reject-relist-
|
|
91704
|
+
reject ping-pong (tcN ids renumber after each single reject).
|
|
90973
91705
|
--all Reject every tracked change.
|
|
90974
91706
|
|
|
90975
91707
|
Options:
|
|
@@ -91520,7 +92252,7 @@ Examples:
|
|
|
91520
92252
|
// package.json
|
|
91521
92253
|
var package_default = {
|
|
91522
92254
|
name: "bun-docx",
|
|
91523
|
-
version: "0.
|
|
92255
|
+
version: "0.14.1",
|
|
91524
92256
|
description: "CLI for AI agents (Claude, Codex) to read, edit, and comment on .docx files with full format fidelity.",
|
|
91525
92257
|
keywords: [
|
|
91526
92258
|
"docx",
|
|
@@ -91611,13 +92343,13 @@ Commands (each one-liner names capabilities you'd otherwise miss; see <command>
|
|
|
91611
92343
|
create FILE Create a new .docx (--from PATH.md | --from - builds from Markdown; --force to overwrite)
|
|
91612
92344
|
read FILE Render as Markdown with pN locators; --from/--to to slice, --accepted (default)/--current/--baseline tracked views, --comments, --ast for JSON-AST
|
|
91613
92345
|
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
|
|
92346
|
+
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
92347
|
delete FILE Remove a paragraph, range, table, or section break (--at LOCATOR; --track for tracked deletion; --batch to remove many in one read)
|
|
91616
92348
|
find FILE [QUERY] Find spans by text, OR by formatting (--highlight/--color/--bold/--italic/--underline); returns locators for --at
|
|
91617
92349
|
replace FILE PATTERN REPL Substitute text spans, sed-style (--regex, --track to redline, --dry-run to preview, --batch for a multi-pattern script)
|
|
91618
92350
|
wc FILE [LOCATOR] Count words in the doc or a slice (--accepted/--baseline/--current tracked view, --json)
|
|
91619
92351
|
outline FILE List headings as a locator tree (pN feeds --at / read --from; --style-prefix, --json)
|
|
91620
|
-
|
|
92352
|
+
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
92353
|
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
92354
|
render FILE Visual page verification \u2014 render each page as PNG/JPG via Word or LibreOffice
|
|
91623
92355
|
comments \u2026 Add (--at LOCATOR | --anchor PHRASE | --batch), reply, resolve (--unset to reopen), delete, list (--thread cN)
|
|
@@ -91645,7 +92377,7 @@ render (each render spins up Word and is slow). Render only for what Markdown ca
|
|
|
91645
92377
|
multi-column sections, page/section breaks, image sizing/placement, table geometry \u2014 and
|
|
91646
92378
|
then ONCE at the end (not after every edit), or one final time if you're genuinely unsure
|
|
91647
92379
|
it looks right: "docx render FILE --out pages/" writes page-001.png, \u2026 which you can read.
|
|
91648
|
-
(
|
|
92380
|
+
(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
92381
|
|
|
91650
92382
|
Environment:
|
|
91651
92383
|
DOCX_AUTHOR Default author for comments and tracked-change attribution
|
|
@@ -91666,7 +92398,6 @@ async function printTopHelp() {
|
|
|
91666
92398
|
// src/cli/index.ts
|
|
91667
92399
|
init_respond();
|
|
91668
92400
|
var COMMANDS = {
|
|
91669
|
-
columns: () => Promise.resolve().then(() => (init_columns(), exports_columns)),
|
|
91670
92401
|
comments: () => Promise.resolve().then(() => (init_comments3(), exports_comments)),
|
|
91671
92402
|
create: () => Promise.resolve().then(() => (init_create2(), exports_create)),
|
|
91672
92403
|
delete: () => Promise.resolve().then(() => (init_delete2(), exports_delete2)),
|
|
@@ -91682,6 +92413,7 @@ var COMMANDS = {
|
|
|
91682
92413
|
read: () => Promise.resolve().then(() => (init_read3(), exports_read)),
|
|
91683
92414
|
render: () => Promise.resolve().then(() => (init_render2(), exports_render)),
|
|
91684
92415
|
replace: () => Promise.resolve().then(() => (init_replace4(), exports_replace3)),
|
|
92416
|
+
sections: () => Promise.resolve().then(() => (init_sections2(), exports_sections)),
|
|
91685
92417
|
styles: () => Promise.resolve().then(() => (init_styles2(), exports_styles)),
|
|
91686
92418
|
tables: () => Promise.resolve().then(() => (init_tables(), exports_tables)),
|
|
91687
92419
|
"track-changes": () => Promise.resolve().then(() => (init_track_changes2(), exports_track_changes)),
|
|
@@ -91711,6 +92443,9 @@ Run "docx --help" for available commands.
|
|
|
91711
92443
|
}
|
|
91712
92444
|
return 0;
|
|
91713
92445
|
}
|
|
92446
|
+
if (cmd === "columns") {
|
|
92447
|
+
return fail("USAGE", "`docx columns` was renamed to `docx sections`", "Run `docx sections --at pN-pM --columns N` (or `docx sections --help`).");
|
|
92448
|
+
}
|
|
91714
92449
|
const loader = COMMANDS[cmd];
|
|
91715
92450
|
if (!loader) {
|
|
91716
92451
|
return fail("USAGE", `Unknown command: ${cmd}`, 'Run "docx --help" for the list of commands.');
|