bun-docx 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4710,12 +4710,15 @@ var init_jsx = __esm(() => {
4710
4710
  "type",
4711
4711
  "tbl",
4712
4712
  "tblPr",
4713
+ "tblStyle",
4713
4714
  "tblPrChange",
4714
4715
  "tblGrid",
4715
4716
  "tblGridChange",
4716
4717
  "gridCol",
4717
4718
  "tr",
4718
4719
  "trPr",
4720
+ "trHeight",
4721
+ "tblHeader",
4719
4722
  "tc",
4720
4723
  "tcPr",
4721
4724
  "tcPrChange",
@@ -4761,6 +4764,7 @@ var init_jsx = __esm(() => {
4761
4764
  "tcW",
4762
4765
  "tblLayout",
4763
4766
  "vMerge",
4767
+ "vAlign",
4764
4768
  "gridSpan",
4765
4769
  "numbering",
4766
4770
  "num",
@@ -21607,6 +21611,481 @@ var init_body = __esm(() => {
21607
21611
  };
21608
21612
  });
21609
21613
 
21614
+ // src/core/ast/document/numbering.tsx
21615
+ function numFmtToFormat(numFmt) {
21616
+ return NUMFMT_TO_FORMAT[numFmt] ?? numFmt;
21617
+ }
21618
+
21619
+ class NumberingView {
21620
+ tree;
21621
+ constructor(tree = XmlNode2.parse(EMPTY_NUMBERING_XML)) {
21622
+ this.tree = tree;
21623
+ }
21624
+ static async fromPackage(pkg) {
21625
+ const tree = await pkg.readPart(NUMBERING_PART_NAME);
21626
+ return tree ? new NumberingView(tree) : undefined;
21627
+ }
21628
+ static fromXml(xml) {
21629
+ return xml ? new NumberingView(XmlNode2.parse(xml)) : undefined;
21630
+ }
21631
+ writeTo(pkg) {
21632
+ pkg.writeText(NUMBERING_PART_NAME, XmlNode2.serialize(this.tree));
21633
+ }
21634
+ static register(deps) {
21635
+ if (!deps.relationships.hasTarget("numbering.xml")) {
21636
+ deps.relationships.add(NUMBERING_RELATIONSHIP_TYPE, "numbering.xml");
21637
+ }
21638
+ deps.contentTypes.registerPart(NUMBERING_PART_NAME, NUMBERING_CONTENT_TYPE);
21639
+ return new NumberingView;
21640
+ }
21641
+ listNumIds() {
21642
+ const root = XmlNode2.findRoot(this.tree, "w:numbering");
21643
+ if (!root)
21644
+ return [];
21645
+ const out = [];
21646
+ for (const child2 of root.findChildren("w:num")) {
21647
+ const id = child2.getAttribute("w:numId");
21648
+ if (id)
21649
+ out.push(id);
21650
+ }
21651
+ return out;
21652
+ }
21653
+ listAbstractNumIds() {
21654
+ const root = XmlNode2.findRoot(this.tree, "w:numbering");
21655
+ if (!root)
21656
+ return [];
21657
+ const out = [];
21658
+ for (const child2 of root.findChildren("w:abstractNum")) {
21659
+ const id = child2.getAttribute("w:abstractNumId");
21660
+ if (id)
21661
+ out.push(id);
21662
+ }
21663
+ return out;
21664
+ }
21665
+ allocate(kind, start = 1) {
21666
+ const root = this.ensureNumberingRoot();
21667
+ const abstractNumId = this.ensureAbstractNum(root, kind);
21668
+ const numId = nextNumId(root);
21669
+ root.children.push(/* @__PURE__ */ jsxDEV(NumElement, {
21670
+ numId,
21671
+ abstractNumId,
21672
+ start
21673
+ }, undefined, false, undefined, this));
21674
+ return numId;
21675
+ }
21676
+ getLevelInfo(numId, level) {
21677
+ const num = this.findNum(numId);
21678
+ const lvlOverride = num ? this.findLvlOverride(num, level) : undefined;
21679
+ const override = lvlOverride?.findChild("w:lvl")?.findChild("w:numFmt")?.getAttribute("w:val");
21680
+ const abstractNum = this.resolveAbstractNum(numId);
21681
+ const abstractLvl = abstractNum ? findLevel(abstractNum, level) ?? findLevel(abstractNum, 0) : undefined;
21682
+ const format = override ?? abstractLvl?.findChild("w:numFmt")?.getAttribute("w:val");
21683
+ const startRaw = lvlOverride?.findChild("w:startOverride")?.getAttribute("w:val") ?? abstractLvl?.findChild("w:start")?.getAttribute("w:val");
21684
+ const startNum = Number(startRaw);
21685
+ const start = startRaw !== undefined && Number.isFinite(startNum) ? startNum : 1;
21686
+ return { format, override, start };
21687
+ }
21688
+ getFormat(numId, level) {
21689
+ return this.getLevelInfo(numId, level).format;
21690
+ }
21691
+ getBulletText(numId, level) {
21692
+ const fromOverride = this.overrideLevel(numId, level)?.findChild("w:lvlText")?.getAttribute("w:val");
21693
+ if (fromOverride !== undefined)
21694
+ return fromOverride;
21695
+ const abstractNum = this.resolveAbstractNum(numId);
21696
+ if (!abstractNum)
21697
+ return;
21698
+ const lvl = findLevel(abstractNum, level) ?? findLevel(abstractNum, 0);
21699
+ return lvl?.findChild("w:lvlText")?.getAttribute("w:val") ?? undefined;
21700
+ }
21701
+ getStart(numId, level) {
21702
+ return this.getLevelInfo(numId, level).start;
21703
+ }
21704
+ setStart(numId, level, start) {
21705
+ const num = this.findNum(numId);
21706
+ if (!num)
21707
+ return false;
21708
+ const lvlOverride = this.ensureLvlOverride(num, level);
21709
+ const existing = lvlOverride.findChild("w:startOverride");
21710
+ if (existing)
21711
+ existing.setAttribute("w:val", String(start));
21712
+ else
21713
+ insertLvlOverrideChildInOrder(lvlOverride, /* @__PURE__ */ jsxDEV(w.startOverride, {
21714
+ "w-val": String(start)
21715
+ }, undefined, false, undefined, this));
21716
+ return true;
21717
+ }
21718
+ setFormat(numId, level, numFmt) {
21719
+ const num = this.findNum(numId);
21720
+ if (!num)
21721
+ return false;
21722
+ const lvl = this.buildOverrideLevel(numId, level, numFmt);
21723
+ const lvlOverride = this.ensureLvlOverride(num, level);
21724
+ const existing = lvlOverride.findChild("w:lvl");
21725
+ if (existing) {
21726
+ lvlOverride.children.splice(lvlOverride.children.indexOf(existing), 1, lvl);
21727
+ } else {
21728
+ insertLvlOverrideChildInOrder(lvlOverride, lvl);
21729
+ }
21730
+ return true;
21731
+ }
21732
+ cloneListDefinition(srcNumId, start) {
21733
+ const root = this.ensureNumberingRoot();
21734
+ const src = this.findNum(srcNumId);
21735
+ const abstractNumId = src?.findChild("w:abstractNumId")?.getAttribute("w:val") ?? "0";
21736
+ const numId = nextNumId(root);
21737
+ const num = /* @__PURE__ */ jsxDEV(w.num, {
21738
+ "w-numId": String(numId)
21739
+ }, undefined, false, undefined, this);
21740
+ num.children.push(/* @__PURE__ */ jsxDEV(w.abstractNumId, {
21741
+ "w-val": abstractNumId
21742
+ }, undefined, false, undefined, this));
21743
+ if (src) {
21744
+ for (const lvlOverride of src.findChildren("w:lvlOverride")) {
21745
+ const lvl = lvlOverride.findChild("w:lvl");
21746
+ if (!lvl)
21747
+ continue;
21748
+ const carried = /* @__PURE__ */ jsxDEV(w.lvlOverride, {
21749
+ "w-ilvl": lvlOverride.getAttribute("w:ilvl") ?? "0"
21750
+ }, undefined, false, undefined, this);
21751
+ carried.children.push(lvl.clone());
21752
+ num.children.push(carried);
21753
+ }
21754
+ }
21755
+ root.children.push(num);
21756
+ this.setStart(String(numId), 0, start);
21757
+ return numId;
21758
+ }
21759
+ findNum(numId) {
21760
+ const root = XmlNode2.findRoot(this.tree, "w:numbering");
21761
+ return root?.findChildren("w:num").find((node) => node.getAttribute("w:numId") === numId);
21762
+ }
21763
+ findLvlOverride(num, level) {
21764
+ const target = String(level);
21765
+ return num.findChildren("w:lvlOverride").find((node) => node.getAttribute("w:ilvl") === target);
21766
+ }
21767
+ ensureLvlOverride(num, level) {
21768
+ const existing = this.findLvlOverride(num, level);
21769
+ if (existing)
21770
+ return existing;
21771
+ const created = /* @__PURE__ */ jsxDEV(w.lvlOverride, {
21772
+ "w-ilvl": String(level)
21773
+ }, undefined, false, undefined, this);
21774
+ const abstractIdx = num.children.findIndex((child2) => child2.tag === "w:abstractNumId");
21775
+ num.children.splice(abstractIdx + 1, 0, created);
21776
+ return created;
21777
+ }
21778
+ overrideLevel(numId, level) {
21779
+ const num = this.findNum(numId);
21780
+ const lvlOverride = num ? this.findLvlOverride(num, level) : undefined;
21781
+ return lvlOverride?.findChild("w:lvl");
21782
+ }
21783
+ buildOverrideLevel(numId, level, numFmt) {
21784
+ const abstractNum = this.resolveAbstractNum(numId);
21785
+ const base = abstractNum && (findLevel(abstractNum, level) ?? findLevel(abstractNum, 0));
21786
+ const lvl = base ? base.clone() : /* @__PURE__ */ jsxDEV(OrderedLevel, {
21787
+ ilvl: level,
21788
+ text: `%${level + 1}.`,
21789
+ fmt: numFmt
21790
+ }, undefined, false, undefined, this);
21791
+ lvl.setAttribute("w:ilvl", String(level));
21792
+ lvl.findChild("w:numFmt")?.setAttribute("w:val", numFmt);
21793
+ lvl.children = lvl.children.filter((child2) => child2.tag !== "w:start");
21794
+ return lvl;
21795
+ }
21796
+ resolveAbstractNum(numId) {
21797
+ const root = XmlNode2.findRoot(this.tree, "w:numbering");
21798
+ if (!root)
21799
+ return;
21800
+ const num = root.findChildren("w:num").find((node) => node.getAttribute("w:numId") === numId);
21801
+ if (!num)
21802
+ return;
21803
+ const abstractNumId = num.findChild("w:abstractNumId")?.getAttribute("w:val");
21804
+ if (!abstractNumId)
21805
+ return;
21806
+ return root.findChildren("w:abstractNum").find((node) => node.getAttribute("w:abstractNumId") === abstractNumId);
21807
+ }
21808
+ ensureNumberingRoot() {
21809
+ const root = XmlNode2.findRoot(this.tree, "w:numbering");
21810
+ if (!root) {
21811
+ throw new Error("expected <w:numbering> root in numbering tree");
21812
+ }
21813
+ return root;
21814
+ }
21815
+ ensureAbstractNum(root, kind) {
21816
+ const targetFormat = kind === "bullet" ? "bullet" : "decimal";
21817
+ for (const child2 of root.findChildren("w:abstractNum")) {
21818
+ const lvl0 = findLevel(child2, 0);
21819
+ const numFmt = lvl0?.findChild("w:numFmt");
21820
+ if (numFmt?.getAttribute("w:val") === targetFormat) {
21821
+ const id = child2.getAttribute("w:abstractNumId");
21822
+ if (id)
21823
+ return Number(id);
21824
+ }
21825
+ }
21826
+ const newId = nextAbstractNumId(root);
21827
+ const def = /* @__PURE__ */ jsxDEV(AbstractNum, {
21828
+ kind,
21829
+ id: newId
21830
+ }, undefined, false, undefined, this);
21831
+ const firstNumIdx = root.children.findIndex((child2) => child2.tag === "w:num");
21832
+ if (firstNumIdx === -1)
21833
+ root.children.push(def);
21834
+ else
21835
+ root.children.splice(firstNumIdx, 0, def);
21836
+ return newId;
21837
+ }
21838
+ }
21839
+ function nextAbstractNumId(root) {
21840
+ let max = -1;
21841
+ for (const child2 of root.findChildren("w:abstractNum")) {
21842
+ const id = child2.getAttribute("w:abstractNumId");
21843
+ if (id) {
21844
+ const numeric = Number(id);
21845
+ if (Number.isFinite(numeric) && numeric > max)
21846
+ max = numeric;
21847
+ }
21848
+ }
21849
+ return max + 1;
21850
+ }
21851
+ function nextNumId(root) {
21852
+ let max = 0;
21853
+ for (const child2 of root.findChildren("w:num")) {
21854
+ const id = child2.getAttribute("w:numId");
21855
+ if (id) {
21856
+ const numeric = Number(id);
21857
+ if (Number.isFinite(numeric) && numeric > max)
21858
+ max = numeric;
21859
+ }
21860
+ }
21861
+ return max + 1;
21862
+ }
21863
+ function insertLvlOverrideChildInOrder(lvlOverride, child2) {
21864
+ const order = ["w:startOverride", "w:lvl"];
21865
+ const rank = order.indexOf(child2.tag);
21866
+ const at = lvlOverride.children.findIndex((existing) => !existing.isText && order.indexOf(existing.tag) > rank);
21867
+ if (at < 0)
21868
+ lvlOverride.children.push(child2);
21869
+ else
21870
+ lvlOverride.children.splice(at, 0, child2);
21871
+ }
21872
+ function findLevel(abstractNum, ilvl) {
21873
+ const target = String(ilvl);
21874
+ return abstractNum.findChildren("w:lvl").find((lvl) => lvl.getAttribute("w:ilvl") === target);
21875
+ }
21876
+ function NumElement({
21877
+ numId,
21878
+ abstractNumId,
21879
+ start
21880
+ }) {
21881
+ return /* @__PURE__ */ jsxDEV(w.num, {
21882
+ "w-numId": String(numId),
21883
+ children: [
21884
+ /* @__PURE__ */ jsxDEV(w.abstractNumId, {
21885
+ "w-val": String(abstractNumId)
21886
+ }, undefined, false, undefined, this),
21887
+ /* @__PURE__ */ jsxDEV(w.lvlOverride, {
21888
+ "w-ilvl": "0",
21889
+ children: /* @__PURE__ */ jsxDEV(w.startOverride, {
21890
+ "w-val": String(start)
21891
+ }, undefined, false, undefined, this)
21892
+ }, undefined, false, undefined, this)
21893
+ ]
21894
+ }, undefined, true, undefined, this);
21895
+ }
21896
+ function AbstractNum({
21897
+ kind,
21898
+ id
21899
+ }) {
21900
+ return kind === "bullet" ? /* @__PURE__ */ jsxDEV(BulletAbstractNum, {
21901
+ id
21902
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(OrderedAbstractNum, {
21903
+ id
21904
+ }, undefined, false, undefined, this);
21905
+ }
21906
+ function BulletAbstractNum({ id }) {
21907
+ return /* @__PURE__ */ jsxDEV(w.abstractNum, {
21908
+ "w-abstractNumId": String(id),
21909
+ children: [
21910
+ /* @__PURE__ */ jsxDEV(w.multiLevelType, {
21911
+ "w-val": "hybridMultilevel"
21912
+ }, undefined, false, undefined, this),
21913
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21914
+ ilvl: 0,
21915
+ glyph: "\u2022"
21916
+ }, undefined, false, undefined, this),
21917
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21918
+ ilvl: 1,
21919
+ glyph: "\u25E6"
21920
+ }, undefined, false, undefined, this),
21921
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21922
+ ilvl: 2,
21923
+ glyph: "\u25AA"
21924
+ }, undefined, false, undefined, this),
21925
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21926
+ ilvl: 3,
21927
+ glyph: "\u2022"
21928
+ }, undefined, false, undefined, this),
21929
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21930
+ ilvl: 4,
21931
+ glyph: "\u25E6"
21932
+ }, undefined, false, undefined, this),
21933
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21934
+ ilvl: 5,
21935
+ glyph: "\u25AA"
21936
+ }, undefined, false, undefined, this),
21937
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21938
+ ilvl: 6,
21939
+ glyph: "\u2022"
21940
+ }, undefined, false, undefined, this),
21941
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21942
+ ilvl: 7,
21943
+ glyph: "\u25E6"
21944
+ }, undefined, false, undefined, this),
21945
+ /* @__PURE__ */ jsxDEV(BulletLevel, {
21946
+ ilvl: 8,
21947
+ glyph: "\u25AA"
21948
+ }, undefined, false, undefined, this)
21949
+ ]
21950
+ }, undefined, true, undefined, this);
21951
+ }
21952
+ function BulletLevel({
21953
+ ilvl,
21954
+ glyph
21955
+ }) {
21956
+ return /* @__PURE__ */ jsxDEV(w.lvl, {
21957
+ "w-ilvl": String(ilvl),
21958
+ children: [
21959
+ /* @__PURE__ */ jsxDEV(w.start, {
21960
+ "w-val": "1"
21961
+ }, undefined, false, undefined, this),
21962
+ /* @__PURE__ */ jsxDEV(w.numFmt, {
21963
+ "w-val": "bullet"
21964
+ }, undefined, false, undefined, this),
21965
+ /* @__PURE__ */ jsxDEV(w.lvlText, {
21966
+ "w-val": glyph
21967
+ }, undefined, false, undefined, this),
21968
+ /* @__PURE__ */ jsxDEV(w.lvlJc, {
21969
+ "w-val": "left"
21970
+ }, undefined, false, undefined, this),
21971
+ /* @__PURE__ */ jsxDEV(w.pPr, {
21972
+ children: /* @__PURE__ */ jsxDEV(w.ind, {
21973
+ "w-left": String(levelIndent(ilvl)),
21974
+ "w-hanging": HANGING
21975
+ }, undefined, false, undefined, this)
21976
+ }, undefined, false, undefined, this)
21977
+ ]
21978
+ }, undefined, true, undefined, this);
21979
+ }
21980
+ function OrderedAbstractNum({ id }) {
21981
+ return /* @__PURE__ */ jsxDEV(w.abstractNum, {
21982
+ "w-abstractNumId": String(id),
21983
+ children: [
21984
+ /* @__PURE__ */ jsxDEV(w.multiLevelType, {
21985
+ "w-val": "hybridMultilevel"
21986
+ }, undefined, false, undefined, this),
21987
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
21988
+ ilvl: 0,
21989
+ text: "%1.",
21990
+ fmt: "decimal"
21991
+ }, undefined, false, undefined, this),
21992
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
21993
+ ilvl: 1,
21994
+ text: "%2.",
21995
+ fmt: "lowerLetter"
21996
+ }, undefined, false, undefined, this),
21997
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
21998
+ ilvl: 2,
21999
+ text: "%3.",
22000
+ fmt: "lowerRoman"
22001
+ }, undefined, false, undefined, this),
22002
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
22003
+ ilvl: 3,
22004
+ text: "%4.",
22005
+ fmt: "decimal"
22006
+ }, undefined, false, undefined, this),
22007
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
22008
+ ilvl: 4,
22009
+ text: "%5.",
22010
+ fmt: "lowerLetter"
22011
+ }, undefined, false, undefined, this),
22012
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
22013
+ ilvl: 5,
22014
+ text: "%6.",
22015
+ fmt: "lowerRoman"
22016
+ }, undefined, false, undefined, this),
22017
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
22018
+ ilvl: 6,
22019
+ text: "%7.",
22020
+ fmt: "decimal"
22021
+ }, undefined, false, undefined, this),
22022
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
22023
+ ilvl: 7,
22024
+ text: "%8.",
22025
+ fmt: "lowerLetter"
22026
+ }, undefined, false, undefined, this),
22027
+ /* @__PURE__ */ jsxDEV(OrderedLevel, {
22028
+ ilvl: 8,
22029
+ text: "%9.",
22030
+ fmt: "lowerRoman"
22031
+ }, undefined, false, undefined, this)
22032
+ ]
22033
+ }, undefined, true, undefined, this);
22034
+ }
22035
+ function OrderedLevel({
22036
+ ilvl,
22037
+ text: text2,
22038
+ fmt
22039
+ }) {
22040
+ return /* @__PURE__ */ jsxDEV(w.lvl, {
22041
+ "w-ilvl": String(ilvl),
22042
+ children: [
22043
+ /* @__PURE__ */ jsxDEV(w.start, {
22044
+ "w-val": "1"
22045
+ }, undefined, false, undefined, this),
22046
+ /* @__PURE__ */ jsxDEV(w.numFmt, {
22047
+ "w-val": fmt
22048
+ }, undefined, false, undefined, this),
22049
+ /* @__PURE__ */ jsxDEV(w.lvlText, {
22050
+ "w-val": text2
22051
+ }, undefined, false, undefined, this),
22052
+ /* @__PURE__ */ jsxDEV(w.lvlJc, {
22053
+ "w-val": "left"
22054
+ }, undefined, false, undefined, this),
22055
+ /* @__PURE__ */ jsxDEV(w.pPr, {
22056
+ children: /* @__PURE__ */ jsxDEV(w.ind, {
22057
+ "w-left": String(levelIndent(ilvl)),
22058
+ "w-hanging": HANGING
22059
+ }, undefined, false, undefined, this)
22060
+ }, undefined, false, undefined, this)
22061
+ ]
22062
+ }, undefined, true, undefined, this);
22063
+ }
22064
+ function levelIndent(ilvl) {
22065
+ return (ilvl + 1) * 300;
22066
+ }
22067
+ var FORMAT_TO_NUMFMT, NUMFMT_TO_FORMAT, NUMBERING_PART_NAME = "word/numbering.xml", NUMBERING_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", NUMBERING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", EMPTY_NUMBERING_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
22068
+ <w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"/>`, HANGING = "240";
22069
+ var init_numbering = __esm(() => {
22070
+ init_jsx();
22071
+ init_parser();
22072
+ init_jsx_dev_runtime();
22073
+ FORMAT_TO_NUMFMT = {
22074
+ decimal: "decimal",
22075
+ "lower-alpha": "lowerLetter",
22076
+ "upper-alpha": "upperLetter",
22077
+ "lower-roman": "lowerRoman",
22078
+ "upper-roman": "upperRoman"
22079
+ };
22080
+ NUMFMT_TO_FORMAT = {
22081
+ decimal: "decimal",
22082
+ lowerLetter: "lower-alpha",
22083
+ upperLetter: "upper-alpha",
22084
+ lowerRoman: "lower-roman",
22085
+ upperRoman: "upper-roman"
22086
+ };
22087
+ });
22088
+
21610
22089
  // src/core/ast/sym.ts
21611
22090
  function decodeSym(font, charHex) {
21612
22091
  const codepoint = Number.parseInt(charHex, 16);
@@ -22380,9 +22859,13 @@ function applyParagraphProperties(document2, paragraph, paragraphProperties) {
22380
22859
  level,
22381
22860
  numId: id
22382
22861
  };
22383
- const format = id ? document2.numbering?.getFormat(id, level) : undefined;
22384
- if (format !== undefined && format !== "bullet" && format !== "none") {
22862
+ const info = id ? document2.numbering?.getLevelInfo(id, level) : undefined;
22863
+ if (info?.format !== undefined && info.format !== "bullet" && info.format !== "none") {
22385
22864
  list.ordered = true;
22865
+ if (info.override !== undefined)
22866
+ list.format = numFmtToFormat(info.override);
22867
+ if (info.start !== 1)
22868
+ list.start = info.start;
22386
22869
  }
22387
22870
  paragraph.list = list;
22388
22871
  }
@@ -22692,6 +23175,7 @@ function readTable(document2, node, id, state) {
22692
23175
  const width = readTableWidth(node);
22693
23176
  const borders = readTableBorders(node);
22694
23177
  const style = readTableStyle(node);
23178
+ const align = readTableAlign(node);
22695
23179
  readTablePropertyRevision(document2, node, id, state);
22696
23180
  readGridRevision(document2, node, id, state);
22697
23181
  const rows = [];
@@ -22711,6 +23195,11 @@ function readTable(document2, node, id, state) {
22711
23195
  const row = { cells };
22712
23196
  if (rowChange)
22713
23197
  row.trackedChange = rowChange;
23198
+ const height = readRowHeight(child2);
23199
+ if (height)
23200
+ row.height = height;
23201
+ if (readRepeatHeader(child2))
23202
+ row.repeatHeader = true;
22714
23203
  rows.push(row);
22715
23204
  rowIndex++;
22716
23205
  }
@@ -22721,8 +23210,35 @@ function readTable(document2, node, id, state) {
22721
23210
  table.borders = borders;
22722
23211
  if (style)
22723
23212
  table.style = style;
23213
+ if (align)
23214
+ table.align = align;
22724
23215
  return table;
22725
23216
  }
23217
+ function readTableAlign(table) {
23218
+ const val = table.findChild("w:tblPr")?.findChild("w:jc")?.getAttribute("w:val");
23219
+ return val === "center" || val === "right" ? val : undefined;
23220
+ }
23221
+ function readRowHeight(row) {
23222
+ const trHeight = row.findChild("w:trPr")?.findChild("w:trHeight");
23223
+ if (!trHeight)
23224
+ return;
23225
+ const raw = trHeight.getAttribute("w:val");
23226
+ const value = raw ? Number(raw) : NaN;
23227
+ if (!Number.isFinite(value))
23228
+ return;
23229
+ const rule = trHeight.getAttribute("w:hRule");
23230
+ return {
23231
+ value,
23232
+ rule: rule === "exact" || rule === "auto" ? rule : "atLeast"
23233
+ };
23234
+ }
23235
+ function readRepeatHeader(row) {
23236
+ const marker = row.findChild("w:trPr")?.findChild("w:tblHeader");
23237
+ if (!marker)
23238
+ return false;
23239
+ const val = marker.getAttribute("w:val");
23240
+ return val !== "false" && val !== "0" && val !== "off";
23241
+ }
22726
23242
  function readTableStyle(table) {
22727
23243
  return table.findChild("w:tblPr")?.findChild("w:tblStyle")?.getAttribute("w:val") ?? undefined;
22728
23244
  }
@@ -22854,8 +23370,39 @@ function readTableCell(document2, cellNode, rowChildren, tableId, rowIndex, colu
22854
23370
  if (fill && fill.toLowerCase() !== "auto")
22855
23371
  cell.shading = fill.toUpperCase();
22856
23372
  }
23373
+ const vAlignNode = tcPr.findChild("w:vAlign");
23374
+ if (vAlignNode) {
23375
+ const raw = vAlignNode.getAttribute("w:val");
23376
+ if (raw === "center" || raw === "bottom")
23377
+ cell.vAlign = raw;
23378
+ }
23379
+ const cellBorders = readCellBorders(tcPr);
23380
+ if (cellBorders)
23381
+ cell.borders = cellBorders;
22857
23382
  return cell;
22858
23383
  }
23384
+ function readCellBorders(tcPr) {
23385
+ const tcBorders = tcPr.findChild("w:tcBorders");
23386
+ if (!tcBorders)
23387
+ return;
23388
+ const byStyle = new Map;
23389
+ for (const edge of CELL_BORDER_EDGES) {
23390
+ const val = tcBorders.findChild(`w:${edge}`)?.getAttribute("w:val");
23391
+ if (!val || val === "nil" || val === "none")
23392
+ continue;
23393
+ const sides = byStyle.get(val) ?? [];
23394
+ sides.push(edge);
23395
+ byStyle.set(val, sides);
23396
+ }
23397
+ if (byStyle.size === 0)
23398
+ return;
23399
+ const parts = [];
23400
+ for (const [style, sides] of byStyle) {
23401
+ const label = sides.length === CELL_BORDER_EDGES.length ? "all" : sides.join(",");
23402
+ parts.push(`${label}:${style}`);
23403
+ }
23404
+ return parts.join(" ");
23405
+ }
22859
23406
  function readCellPropertyRevision(document2, cell, tableId, state) {
22860
23407
  const tcPr = cell.findChild("w:tcPr");
22861
23408
  const change = tcPr?.findChild("w:tcPrChange");
@@ -22891,7 +23438,7 @@ function readCellBlocks(document2, cell, tableId, rowIndex, columnIndex, state)
22891
23438
  }
22892
23439
  return blocks;
22893
23440
  }
22894
- var TRACKED_CHANGE_KIND_BY_TAG, WRAP_TAGS, TABLE_BORDER_EDGES;
23441
+ var TRACKED_CHANGE_KIND_BY_TAG, WRAP_TAGS, TABLE_BORDER_EDGES, CELL_BORDER_EDGES;
22895
23442
  var init_read2 = __esm(() => {
22896
23443
  init_blocks();
22897
23444
  init_equation();
@@ -22902,6 +23449,7 @@ var init_read2 = __esm(() => {
22902
23449
  init_sections();
22903
23450
  init_task_list();
22904
23451
  init_body();
23452
+ init_numbering();
22905
23453
  init_sym();
22906
23454
  TRACKED_CHANGE_KIND_BY_TAG = {
22907
23455
  "w:ins": "ins",
@@ -22924,6 +23472,14 @@ var init_read2 = __esm(() => {
22924
23472
  "w:insideH",
22925
23473
  "w:insideV"
22926
23474
  ];
23475
+ CELL_BORDER_EDGES = [
23476
+ "top",
23477
+ "left",
23478
+ "bottom",
23479
+ "right",
23480
+ "insideH",
23481
+ "insideV"
23482
+ ];
22927
23483
  });
22928
23484
 
22929
23485
  // src/core/ast/document/comments.tsx
@@ -23731,348 +24287,6 @@ var init_notes2 = __esm(() => {
23731
24287
  init_relationships();
23732
24288
  });
23733
24289
 
23734
- // src/core/ast/document/numbering.tsx
23735
- class NumberingView {
23736
- tree;
23737
- constructor(tree = XmlNode2.parse(EMPTY_NUMBERING_XML)) {
23738
- this.tree = tree;
23739
- }
23740
- static async fromPackage(pkg) {
23741
- const tree = await pkg.readPart(NUMBERING_PART_NAME);
23742
- return tree ? new NumberingView(tree) : undefined;
23743
- }
23744
- static fromXml(xml) {
23745
- return xml ? new NumberingView(XmlNode2.parse(xml)) : undefined;
23746
- }
23747
- writeTo(pkg) {
23748
- pkg.writeText(NUMBERING_PART_NAME, XmlNode2.serialize(this.tree));
23749
- }
23750
- static register(deps) {
23751
- if (!deps.relationships.hasTarget("numbering.xml")) {
23752
- deps.relationships.add(NUMBERING_RELATIONSHIP_TYPE, "numbering.xml");
23753
- }
23754
- deps.contentTypes.registerPart(NUMBERING_PART_NAME, NUMBERING_CONTENT_TYPE);
23755
- return new NumberingView;
23756
- }
23757
- listNumIds() {
23758
- const root = XmlNode2.findRoot(this.tree, "w:numbering");
23759
- if (!root)
23760
- return [];
23761
- const out = [];
23762
- for (const child2 of root.findChildren("w:num")) {
23763
- const id = child2.getAttribute("w:numId");
23764
- if (id)
23765
- out.push(id);
23766
- }
23767
- return out;
23768
- }
23769
- listAbstractNumIds() {
23770
- const root = XmlNode2.findRoot(this.tree, "w:numbering");
23771
- if (!root)
23772
- return [];
23773
- const out = [];
23774
- for (const child2 of root.findChildren("w:abstractNum")) {
23775
- const id = child2.getAttribute("w:abstractNumId");
23776
- if (id)
23777
- out.push(id);
23778
- }
23779
- return out;
23780
- }
23781
- allocate(kind, start = 1) {
23782
- const root = this.ensureNumberingRoot();
23783
- const abstractNumId = this.ensureAbstractNum(root, kind);
23784
- const numId = nextNumId(root);
23785
- root.children.push(/* @__PURE__ */ jsxDEV(NumElement, {
23786
- numId,
23787
- abstractNumId,
23788
- start
23789
- }, undefined, false, undefined, this));
23790
- return numId;
23791
- }
23792
- getFormat(numId, level) {
23793
- const abstractNum = this.resolveAbstractNum(numId);
23794
- if (!abstractNum)
23795
- return;
23796
- const lvl = findLevel(abstractNum, level) ?? findLevel(abstractNum, 0);
23797
- return lvl?.findChild("w:numFmt")?.getAttribute("w:val") ?? undefined;
23798
- }
23799
- getBulletText(numId, level) {
23800
- const abstractNum = this.resolveAbstractNum(numId);
23801
- if (!abstractNum)
23802
- return;
23803
- const lvl = findLevel(abstractNum, level) ?? findLevel(abstractNum, 0);
23804
- return lvl?.findChild("w:lvlText")?.getAttribute("w:val") ?? undefined;
23805
- }
23806
- resolveAbstractNum(numId) {
23807
- const root = XmlNode2.findRoot(this.tree, "w:numbering");
23808
- if (!root)
23809
- return;
23810
- const num = root.findChildren("w:num").find((node) => node.getAttribute("w:numId") === numId);
23811
- if (!num)
23812
- return;
23813
- const abstractNumId = num.findChild("w:abstractNumId")?.getAttribute("w:val");
23814
- if (!abstractNumId)
23815
- return;
23816
- return root.findChildren("w:abstractNum").find((node) => node.getAttribute("w:abstractNumId") === abstractNumId);
23817
- }
23818
- ensureNumberingRoot() {
23819
- const root = XmlNode2.findRoot(this.tree, "w:numbering");
23820
- if (!root) {
23821
- throw new Error("expected <w:numbering> root in numbering tree");
23822
- }
23823
- return root;
23824
- }
23825
- ensureAbstractNum(root, kind) {
23826
- const targetFormat = kind === "bullet" ? "bullet" : "decimal";
23827
- for (const child2 of root.findChildren("w:abstractNum")) {
23828
- const lvl0 = findLevel(child2, 0);
23829
- const numFmt = lvl0?.findChild("w:numFmt");
23830
- if (numFmt?.getAttribute("w:val") === targetFormat) {
23831
- const id = child2.getAttribute("w:abstractNumId");
23832
- if (id)
23833
- return Number(id);
23834
- }
23835
- }
23836
- const newId = nextAbstractNumId(root);
23837
- const def = /* @__PURE__ */ jsxDEV(AbstractNum, {
23838
- kind,
23839
- id: newId
23840
- }, undefined, false, undefined, this);
23841
- const firstNumIdx = root.children.findIndex((child2) => child2.tag === "w:num");
23842
- if (firstNumIdx === -1)
23843
- root.children.push(def);
23844
- else
23845
- root.children.splice(firstNumIdx, 0, def);
23846
- return newId;
23847
- }
23848
- }
23849
- function nextAbstractNumId(root) {
23850
- let max = -1;
23851
- for (const child2 of root.findChildren("w:abstractNum")) {
23852
- const id = child2.getAttribute("w:abstractNumId");
23853
- if (id) {
23854
- const numeric = Number(id);
23855
- if (Number.isFinite(numeric) && numeric > max)
23856
- max = numeric;
23857
- }
23858
- }
23859
- return max + 1;
23860
- }
23861
- function nextNumId(root) {
23862
- let max = 0;
23863
- for (const child2 of root.findChildren("w:num")) {
23864
- const id = child2.getAttribute("w:numId");
23865
- if (id) {
23866
- const numeric = Number(id);
23867
- if (Number.isFinite(numeric) && numeric > max)
23868
- max = numeric;
23869
- }
23870
- }
23871
- return max + 1;
23872
- }
23873
- function findLevel(abstractNum, ilvl) {
23874
- const target = String(ilvl);
23875
- return abstractNum.findChildren("w:lvl").find((lvl) => lvl.getAttribute("w:ilvl") === target);
23876
- }
23877
- function NumElement({
23878
- numId,
23879
- abstractNumId,
23880
- start
23881
- }) {
23882
- return /* @__PURE__ */ jsxDEV(w.num, {
23883
- "w-numId": String(numId),
23884
- children: [
23885
- /* @__PURE__ */ jsxDEV(w.abstractNumId, {
23886
- "w-val": String(abstractNumId)
23887
- }, undefined, false, undefined, this),
23888
- /* @__PURE__ */ jsxDEV(w.lvlOverride, {
23889
- "w-ilvl": "0",
23890
- children: /* @__PURE__ */ jsxDEV(w.startOverride, {
23891
- "w-val": String(start)
23892
- }, undefined, false, undefined, this)
23893
- }, undefined, false, undefined, this)
23894
- ]
23895
- }, undefined, true, undefined, this);
23896
- }
23897
- function AbstractNum({
23898
- kind,
23899
- id
23900
- }) {
23901
- return kind === "bullet" ? /* @__PURE__ */ jsxDEV(BulletAbstractNum, {
23902
- id
23903
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(OrderedAbstractNum, {
23904
- id
23905
- }, undefined, false, undefined, this);
23906
- }
23907
- function BulletAbstractNum({ id }) {
23908
- return /* @__PURE__ */ jsxDEV(w.abstractNum, {
23909
- "w-abstractNumId": String(id),
23910
- children: [
23911
- /* @__PURE__ */ jsxDEV(w.multiLevelType, {
23912
- "w-val": "hybridMultilevel"
23913
- }, undefined, false, undefined, this),
23914
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23915
- ilvl: 0,
23916
- glyph: "\u2022"
23917
- }, undefined, false, undefined, this),
23918
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23919
- ilvl: 1,
23920
- glyph: "\u25E6"
23921
- }, undefined, false, undefined, this),
23922
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23923
- ilvl: 2,
23924
- glyph: "\u25AA"
23925
- }, undefined, false, undefined, this),
23926
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23927
- ilvl: 3,
23928
- glyph: "\u2022"
23929
- }, undefined, false, undefined, this),
23930
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23931
- ilvl: 4,
23932
- glyph: "\u25E6"
23933
- }, undefined, false, undefined, this),
23934
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23935
- ilvl: 5,
23936
- glyph: "\u25AA"
23937
- }, undefined, false, undefined, this),
23938
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23939
- ilvl: 6,
23940
- glyph: "\u2022"
23941
- }, undefined, false, undefined, this),
23942
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23943
- ilvl: 7,
23944
- glyph: "\u25E6"
23945
- }, undefined, false, undefined, this),
23946
- /* @__PURE__ */ jsxDEV(BulletLevel, {
23947
- ilvl: 8,
23948
- glyph: "\u25AA"
23949
- }, undefined, false, undefined, this)
23950
- ]
23951
- }, undefined, true, undefined, this);
23952
- }
23953
- function BulletLevel({
23954
- ilvl,
23955
- glyph
23956
- }) {
23957
- return /* @__PURE__ */ jsxDEV(w.lvl, {
23958
- "w-ilvl": String(ilvl),
23959
- children: [
23960
- /* @__PURE__ */ jsxDEV(w.start, {
23961
- "w-val": "1"
23962
- }, undefined, false, undefined, this),
23963
- /* @__PURE__ */ jsxDEV(w.numFmt, {
23964
- "w-val": "bullet"
23965
- }, undefined, false, undefined, this),
23966
- /* @__PURE__ */ jsxDEV(w.lvlText, {
23967
- "w-val": glyph
23968
- }, undefined, false, undefined, this),
23969
- /* @__PURE__ */ jsxDEV(w.lvlJc, {
23970
- "w-val": "left"
23971
- }, undefined, false, undefined, this),
23972
- /* @__PURE__ */ jsxDEV(w.pPr, {
23973
- children: /* @__PURE__ */ jsxDEV(w.ind, {
23974
- "w-left": String(levelIndent(ilvl)),
23975
- "w-hanging": HANGING
23976
- }, undefined, false, undefined, this)
23977
- }, undefined, false, undefined, this)
23978
- ]
23979
- }, undefined, true, undefined, this);
23980
- }
23981
- function OrderedAbstractNum({ id }) {
23982
- return /* @__PURE__ */ jsxDEV(w.abstractNum, {
23983
- "w-abstractNumId": String(id),
23984
- children: [
23985
- /* @__PURE__ */ jsxDEV(w.multiLevelType, {
23986
- "w-val": "hybridMultilevel"
23987
- }, undefined, false, undefined, this),
23988
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
23989
- ilvl: 0,
23990
- text: "%1.",
23991
- fmt: "decimal"
23992
- }, undefined, false, undefined, this),
23993
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
23994
- ilvl: 1,
23995
- text: "%2.",
23996
- fmt: "lowerLetter"
23997
- }, undefined, false, undefined, this),
23998
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
23999
- ilvl: 2,
24000
- text: "%3.",
24001
- fmt: "lowerRoman"
24002
- }, undefined, false, undefined, this),
24003
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
24004
- ilvl: 3,
24005
- text: "%4.",
24006
- fmt: "decimal"
24007
- }, undefined, false, undefined, this),
24008
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
24009
- ilvl: 4,
24010
- text: "%5.",
24011
- fmt: "lowerLetter"
24012
- }, undefined, false, undefined, this),
24013
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
24014
- ilvl: 5,
24015
- text: "%6.",
24016
- fmt: "lowerRoman"
24017
- }, undefined, false, undefined, this),
24018
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
24019
- ilvl: 6,
24020
- text: "%7.",
24021
- fmt: "decimal"
24022
- }, undefined, false, undefined, this),
24023
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
24024
- ilvl: 7,
24025
- text: "%8.",
24026
- fmt: "lowerLetter"
24027
- }, undefined, false, undefined, this),
24028
- /* @__PURE__ */ jsxDEV(OrderedLevel, {
24029
- ilvl: 8,
24030
- text: "%9.",
24031
- fmt: "lowerRoman"
24032
- }, undefined, false, undefined, this)
24033
- ]
24034
- }, undefined, true, undefined, this);
24035
- }
24036
- function OrderedLevel({
24037
- ilvl,
24038
- text: text2,
24039
- fmt
24040
- }) {
24041
- return /* @__PURE__ */ jsxDEV(w.lvl, {
24042
- "w-ilvl": String(ilvl),
24043
- children: [
24044
- /* @__PURE__ */ jsxDEV(w.start, {
24045
- "w-val": "1"
24046
- }, undefined, false, undefined, this),
24047
- /* @__PURE__ */ jsxDEV(w.numFmt, {
24048
- "w-val": fmt
24049
- }, undefined, false, undefined, this),
24050
- /* @__PURE__ */ jsxDEV(w.lvlText, {
24051
- "w-val": text2
24052
- }, undefined, false, undefined, this),
24053
- /* @__PURE__ */ jsxDEV(w.lvlJc, {
24054
- "w-val": "left"
24055
- }, undefined, false, undefined, this),
24056
- /* @__PURE__ */ jsxDEV(w.pPr, {
24057
- children: /* @__PURE__ */ jsxDEV(w.ind, {
24058
- "w-left": String(levelIndent(ilvl)),
24059
- "w-hanging": HANGING
24060
- }, undefined, false, undefined, this)
24061
- }, undefined, false, undefined, this)
24062
- ]
24063
- }, undefined, true, undefined, this);
24064
- }
24065
- function levelIndent(ilvl) {
24066
- return (ilvl + 1) * 300;
24067
- }
24068
- var NUMBERING_PART_NAME = "word/numbering.xml", NUMBERING_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering", NUMBERING_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", EMPTY_NUMBERING_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
24069
- <w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"/>`, HANGING = "240";
24070
- var init_numbering = __esm(() => {
24071
- init_jsx();
24072
- init_parser();
24073
- init_jsx_dev_runtime();
24074
- });
24075
-
24076
24290
  // node_modules/process-nextick-args/index.js
24077
24291
  var require_process_nextick_args = __commonJS((exports, module) => {
24078
24292
  if (typeof process === "undefined" || !process.version || process.version.indexOf("v0.") === 0 || process.version.indexOf("v1.") === 0 && process.version.indexOf("v1.8.") !== 0) {
@@ -72485,6 +72699,69 @@ function setCellWidth(cell, width) {
72485
72699
  }, undefined, false, undefined, this) : null);
72486
72700
  pruneEmptyTcPr(cell, tcPr);
72487
72701
  }
72702
+ function setCellShading(cell, hex) {
72703
+ const tcPr = ensureTcPr(cell);
72704
+ setTcPrChild(tcPr, "w:shd", hex ? /* @__PURE__ */ jsxDEV(w.shd, {
72705
+ "w-val": "clear",
72706
+ "w-color": "auto",
72707
+ "w-fill": hex
72708
+ }, undefined, false, undefined, this) : null);
72709
+ pruneEmptyTcPr(cell, tcPr);
72710
+ }
72711
+ function setCellVAlign(cell, value) {
72712
+ const tcPr = ensureTcPr(cell);
72713
+ setTcPrChild(tcPr, "w:vAlign", value && value !== "top" ? /* @__PURE__ */ jsxDEV(w.vAlign, {
72714
+ "w-val": value
72715
+ }, undefined, false, undefined, this) : null);
72716
+ pruneEmptyTcPr(cell, tcPr);
72717
+ }
72718
+ function setCellBorders(cell, updates, clearAll = false) {
72719
+ const tcPr = ensureTcPr(cell);
72720
+ if (clearAll) {
72721
+ setTcPrChild(tcPr, "w:tcBorders", null);
72722
+ pruneEmptyTcPr(cell, tcPr);
72723
+ return;
72724
+ }
72725
+ let tcBorders = tcPr.findChild("w:tcBorders");
72726
+ if (!tcBorders) {
72727
+ if (updates.every((update) => update.edge === null)) {
72728
+ pruneEmptyTcPr(cell, tcPr);
72729
+ return;
72730
+ }
72731
+ tcBorders = /* @__PURE__ */ jsxDEV(w.tcBorders, {}, undefined, false, undefined, this);
72732
+ setTcPrChild(tcPr, "w:tcBorders", tcBorders);
72733
+ }
72734
+ for (const { side, edge } of updates) {
72735
+ const tag = `w:${side}`;
72736
+ tcBorders.children = tcBorders.children.filter((child2) => child2.tag !== tag);
72737
+ if (edge)
72738
+ insertEdgeInOrder(tcBorders, tag, borderEdge(tag, edge));
72739
+ }
72740
+ if (tcBorders.children.length === 0)
72741
+ setTcPrChild(tcPr, "w:tcBorders", null);
72742
+ pruneEmptyTcPr(cell, tcPr);
72743
+ }
72744
+ function borderEdge(tag, edge) {
72745
+ const attributes = edge.style === "none" ? { "w:val": "none" } : {
72746
+ "w:val": edge.style,
72747
+ "w:sz": String(edge.sizeEighths),
72748
+ "w:space": "0",
72749
+ "w:color": edge.color
72750
+ };
72751
+ return XmlNode2.element(tag, attributes);
72752
+ }
72753
+ function insertEdgeInOrder(parent, tag, node2) {
72754
+ const target = orderIndex(CELL_BORDER_ORDER, tag);
72755
+ let insertAt = parent.children.length;
72756
+ for (let index2 = 0;index2 < parent.children.length; index2++) {
72757
+ const child2 = parent.children[index2];
72758
+ if (child2 && orderIndex(CELL_BORDER_ORDER, child2.tag) > target) {
72759
+ insertAt = index2;
72760
+ break;
72761
+ }
72762
+ }
72763
+ parent.children.splice(insertAt, 0, node2);
72764
+ }
72488
72765
  function markRowTracked(row, kind, meta) {
72489
72766
  const trPr = ensureTrPr(row);
72490
72767
  trPr.children = trPr.children.filter((child2) => child2.tag !== "w:ins" && child2.tag !== "w:del");
@@ -72515,6 +72792,24 @@ function ensureTrPr(row) {
72515
72792
  row.children.unshift(trPr);
72516
72793
  return trPr;
72517
72794
  }
72795
+ function setRowHeight(row, height) {
72796
+ const trPr = ensureTrPr(row);
72797
+ setTrPrChild(trPr, "w:trHeight", height ? /* @__PURE__ */ jsxDEV(w.trHeight, {
72798
+ "w-val": String(height.value),
72799
+ "w-hRule": height.rule
72800
+ }, undefined, false, undefined, this) : null);
72801
+ pruneEmptyTrPr(row, trPr);
72802
+ }
72803
+ function setRepeatHeader(row, on) {
72804
+ const trPr = ensureTrPr(row);
72805
+ setTrPrChild(trPr, "w:tblHeader", on ? /* @__PURE__ */ jsxDEV(w.tblHeader, {}, undefined, false, undefined, this) : null);
72806
+ pruneEmptyTrPr(row, trPr);
72807
+ }
72808
+ function pruneEmptyTrPr(row, trPr) {
72809
+ if (trPr.children.length === 0) {
72810
+ row.children = row.children.filter((child2) => child2 !== trPr);
72811
+ }
72812
+ }
72518
72813
  function appendTblGridChange(tblGrid, priorCols, meta) {
72519
72814
  tblGrid.children = tblGrid.children.filter((child2) => child2.tag !== "w:tblGridChange");
72520
72815
  tblGrid.children.push(/* @__PURE__ */ jsxDEV(w.tblGridChange, {
@@ -72566,6 +72861,16 @@ function setTableLayout(table, layout) {
72566
72861
  function setTablePropertiesChild(table, tag, node2) {
72567
72862
  setTblPrChild(ensureTblPr(table), tag, node2);
72568
72863
  }
72864
+ function setTableJustification(table, value) {
72865
+ setTablePropertiesChild(table, "w:jc", value && value !== "left" ? /* @__PURE__ */ jsxDEV(w.jc, {
72866
+ "w-val": value
72867
+ }, undefined, false, undefined, this) : null);
72868
+ }
72869
+ function setTableStyle(table, styleId) {
72870
+ setTablePropertiesChild(table, "w:tblStyle", styleId ? /* @__PURE__ */ jsxDEV(w.tblStyle, {
72871
+ "w-val": styleId
72872
+ }, undefined, false, undefined, this) : null);
72873
+ }
72569
72874
  function setTblPrChild(tblPr, tag, node2) {
72570
72875
  tblPr.children = tblPr.children.filter((child2) => child2.tag !== tag);
72571
72876
  if (!node2)
@@ -72600,13 +72905,37 @@ function setTcPrChild(tcPr, tag, node2) {
72600
72905
  }
72601
72906
  tcPr.children.splice(insertAt, 0, node2);
72602
72907
  }
72603
- var TBL_PR_ORDER, TC_PR_ORDER;
72908
+ function setTrPrChild(trPr, tag, node2) {
72909
+ trPr.children = trPr.children.filter((child2) => child2.tag !== tag);
72910
+ if (!node2)
72911
+ return;
72912
+ const target = orderIndex(TR_PR_ORDER, tag);
72913
+ let insertAt = trPr.children.length;
72914
+ for (let index2 = 0;index2 < trPr.children.length; index2++) {
72915
+ const child2 = trPr.children[index2];
72916
+ if (child2 && orderIndex(TR_PR_ORDER, child2.tag) > target) {
72917
+ insertAt = index2;
72918
+ break;
72919
+ }
72920
+ }
72921
+ trPr.children.splice(insertAt, 0, node2);
72922
+ }
72923
+ var CELL_BORDER_ORDER, TBL_PR_ORDER, TC_PR_ORDER, TR_PR_ORDER;
72604
72924
  var init_mutate = __esm(() => {
72605
72925
  init_blocks();
72606
72926
  init_jsx();
72927
+ init_parser();
72607
72928
  init_emit2();
72608
72929
  init_table();
72609
72930
  init_jsx_dev_runtime();
72931
+ CELL_BORDER_ORDER = [
72932
+ "w:top",
72933
+ "w:left",
72934
+ "w:bottom",
72935
+ "w:right",
72936
+ "w:insideH",
72937
+ "w:insideV"
72938
+ ];
72610
72939
  TBL_PR_ORDER = [
72611
72940
  "w:tblStyle",
72612
72941
  "w:tblpPr",
@@ -72644,6 +72973,23 @@ var init_mutate = __esm(() => {
72644
72973
  "w:cellMerge",
72645
72974
  "w:tcPrChange"
72646
72975
  ];
72976
+ TR_PR_ORDER = [
72977
+ "w:cnfStyle",
72978
+ "w:divId",
72979
+ "w:gridBefore",
72980
+ "w:gridAfter",
72981
+ "w:wBefore",
72982
+ "w:wAfter",
72983
+ "w:cantSplit",
72984
+ "w:trHeight",
72985
+ "w:tblHeader",
72986
+ "w:tblCellSpacing",
72987
+ "w:jc",
72988
+ "w:hidden",
72989
+ "w:ins",
72990
+ "w:del",
72991
+ "w:trPrChange"
72992
+ ];
72647
72993
  });
72648
72994
 
72649
72995
  // src/core/table/index.tsx
@@ -73741,6 +74087,99 @@ var init_insert = __esm(() => {
73741
74087
  };
73742
74088
  });
73743
74089
 
74090
+ // src/core/lists/index.ts
74091
+ class Lists {
74092
+ document;
74093
+ constructor(document4) {
74094
+ this.document = document4;
74095
+ }
74096
+ setStart(blockRef, start) {
74097
+ const list3 = this.requireList(blockRef.node);
74098
+ this.numbering().setStart(list3.numId, list3.level, start);
74099
+ }
74100
+ setFormat(blockRef, format) {
74101
+ const list3 = this.requireList(blockRef.node);
74102
+ this.numbering().setFormat(list3.numId, list3.level, FORMAT_TO_NUMFMT[format]);
74103
+ }
74104
+ restart(blockRef, start) {
74105
+ const list3 = this.requireList(blockRef.node);
74106
+ const newNumId = String(this.numbering().cloneListDefinition(list3.numId, start));
74107
+ const startIdx = blockRef.parent.indexOf(blockRef.node);
74108
+ this.repointFrom(blockRef.parent, startIdx, list3.numId, newNumId);
74109
+ }
74110
+ continue(blockRef) {
74111
+ const list3 = this.requireList(blockRef.node);
74112
+ const siblings = blockRef.parent;
74113
+ const startIdx = siblings.indexOf(blockRef.node);
74114
+ let precedingNumId;
74115
+ for (let i = startIdx - 1;i >= 0; i--) {
74116
+ const sibling = siblings[i];
74117
+ if (!sibling)
74118
+ continue;
74119
+ const numbered = readNumPr(sibling);
74120
+ if (!numbered)
74121
+ continue;
74122
+ if (numbered.numId !== list3.numId && this.isOrdered(numbered)) {
74123
+ precedingNumId = numbered.numId;
74124
+ break;
74125
+ }
74126
+ }
74127
+ if (!precedingNumId) {
74128
+ throw new ListOperationError("no preceding list to continue from");
74129
+ }
74130
+ this.repointFrom(siblings, startIdx, list3.numId, precedingNumId);
74131
+ }
74132
+ repointFrom(siblings, startIdx, oldNumId, newNumId) {
74133
+ for (let i = startIdx;i < siblings.length; i++) {
74134
+ const sibling = siblings[i];
74135
+ if (!sibling)
74136
+ continue;
74137
+ if (readNumPr(sibling)?.numId === oldNumId)
74138
+ setNumId(sibling, newNumId);
74139
+ }
74140
+ }
74141
+ isOrdered(numbered) {
74142
+ const format = this.numbering().getFormat(numbered.numId, numbered.level);
74143
+ return format !== undefined && format !== "bullet" && format !== "none";
74144
+ }
74145
+ requireList(paragraph2) {
74146
+ const numbered = readNumPr(paragraph2);
74147
+ if (!numbered) {
74148
+ throw new ListOperationError("paragraph is not a list item");
74149
+ }
74150
+ return numbered;
74151
+ }
74152
+ numbering() {
74153
+ if (!this.document.numbering) {
74154
+ throw new ListOperationError("document has no numbering definitions");
74155
+ }
74156
+ return this.document.numbering;
74157
+ }
74158
+ }
74159
+ function readNumPr(paragraph2) {
74160
+ const numPr = paragraph2.findChild("w:pPr")?.findChild("w:numPr");
74161
+ if (!numPr)
74162
+ return;
74163
+ const numId = numPr.findChild("w:numId")?.getAttribute("w:val");
74164
+ if (numId === undefined)
74165
+ return;
74166
+ const level = Number(numPr.findChild("w:ilvl")?.getAttribute("w:val") ?? "0");
74167
+ return { numId, level };
74168
+ }
74169
+ function setNumId(paragraph2, numId) {
74170
+ paragraph2.findChild("w:pPr")?.findChild("w:numPr")?.findChild("w:numId")?.setAttribute("w:val", numId);
74171
+ }
74172
+ var ListOperationError;
74173
+ var init_lists = __esm(() => {
74174
+ init_numbering();
74175
+ ListOperationError = class ListOperationError extends Error {
74176
+ constructor(message) {
74177
+ super(message);
74178
+ this.name = "ListOperationError";
74179
+ }
74180
+ };
74181
+ });
74182
+
73744
74183
  // src/core/marginals/index.tsx
73745
74184
  class Marginals {
73746
74185
  document;
@@ -82082,11 +82521,13 @@ var init_render = __esm(() => {
82082
82521
  // src/core/index.ts
82083
82522
  var init_core2 = __esm(() => {
82084
82523
  init_ast();
82524
+ init_numbering();
82085
82525
  init_package();
82086
82526
  init_comments2();
82087
82527
  init_edit();
82088
82528
  init_fonts();
82089
82529
  init_insert();
82530
+ init_lists();
82090
82531
  init_literal_text();
82091
82532
  init_locators();
82092
82533
  init_marginals2();
@@ -89569,7 +90010,19 @@ export type Paragraph = {
89569
90010
  type: "paragraph";
89570
90011
  style?: string;
89571
90012
  alignment?: "left" | "center" | "right" | "justify";
89572
- list?: { level: number; numId: string; ordered?: boolean };
90013
+ /** List membership from \`<w:pPr><w:numPr>\`. \`start\`/\`format\` are the
90014
+ * numbering-control properties \`docx lists set\` authors: \`start\` is the
90015
+ * effective level-start (omitted when 1), \`format\` the friendly
90016
+ * \`--format\` glyph vocabulary (decimal/lower-alpha/upper-roman/\u2026, omitted
90017
+ * when the default \`decimal\`). Two paragraphs sharing a \`numId\` are the same
90018
+ * (or continued) list, so a \`--continue\` link needs no field of its own. */
90019
+ list?: {
90020
+ level: number;
90021
+ numId: string;
90022
+ ordered?: boolean;
90023
+ start?: number;
90024
+ format?: string;
90025
+ };
89573
90026
  /** GFM task-list marker. Set when the paragraph's first content is a Word
89574
90027
  * checkbox content control (\`<w:sdt><w14:checkbox/></w:sdt>\`); the SDT itself
89575
90028
  * plus the leading whitespace run after it are stripped from \`runs\` so the
@@ -89642,6 +90095,10 @@ export type Table = {
89642
90095
  * \`borders\` summary. Surfaced so \`styles --used\` can report the table styles
89643
90096
  * a document actually applies. Present only when the table references one. */
89644
90097
  style?: string;
90098
+ /** Justification of the whole table on the page, from \`<w:tblPr><w:jc w:val="\u2026"/>\`
90099
+ * (\`"center"\` / \`"right"\`). Absent \u21D2 the default \`"left"\`. Authorable via
90100
+ * \`docx tables format --at tN --align\`. */
90101
+ align?: "left" | "center" | "right";
89645
90102
  rows: TableRow[];
89646
90103
  };
89647
90104
 
@@ -89650,6 +90107,15 @@ export type TableRow = {
89650
90107
  /** Tracked row insertion/deletion from <w:trPr><w:ins/> or <w:del/>
89651
90108
  * (kind "rowIns" / "rowDel"). Present only under track-changes. */
89652
90109
  trackedChange?: TrackedChange;
90110
+ /** Row height from \`<w:trPr><w:trHeight w:val="\u2026" w:hRule="\u2026"/>\`. \`value\` is
90111
+ * in twips; \`rule\` is \`atLeast\` (minimum, the default), \`exact\` (fixed), or
90112
+ * \`auto\` (fit content). Present only when the row declares an explicit height.
90113
+ * Authorable via \`docx tables format --at tN:rR --row-height\`. */
90114
+ height?: { value: number; rule: "atLeast" | "exact" | "auto" };
90115
+ /** Whether the row repeats as a header at the top of each page that the table
90116
+ * spans, from \`<w:trPr><w:tblHeader/>\`. Present (true) only when the marker is
90117
+ * set. Authorable via \`docx tables format --at tN:rR --repeat-header\`. */
90118
+ repeatHeader?: boolean;
89653
90119
  };
89654
90120
 
89655
90121
  export type TableCell = {
@@ -89674,6 +90140,17 @@ export type TableCell = {
89674
90140
  * hint \u2014 GFM can't show cell shading; the fill survives edits via in-place
89675
90141
  * mutation. */
89676
90142
  shading?: string;
90143
+ /** Vertical alignment of the cell's content from \`<w:tcPr><w:vAlign w:val="\u2026"/>\`
90144
+ * (\`"center"\` / \`"bottom"\`). Absent \u21D2 the default \`"top"\`. Authorable via
90145
+ * \`docx tables format --at \u2026 --valign\`. (Horizontal alignment is NOT a cell
90146
+ * property \u2014 it lives on each paragraph's \`<w:jc>\`, surfaced as \`docx:p align\`.) */
90147
+ vAlign?: "top" | "center" | "bottom";
90148
+ /** Summary of \`<w:tcPr><w:tcBorders>\` \u2014 the set edges and their dominant style,
90149
+ * as a compact \`side:style\` string (e.g. \`"bottom:double"\`, \`"all:single"\`).
90150
+ * A read-time hint mirroring \`Table.borders\`; full per-edge fidelity stays in
90151
+ * the XML via in-place mutation. Authorable via \`docx tables format --at \u2026
90152
+ * --cell-borders\`. Present only when the cell declares explicit borders. */
90153
+ borders?: string;
89677
90154
  };
89678
90155
 
89679
90156
  export type TableWidth = {
@@ -90042,7 +90519,10 @@ var init_schema = __esm(() => {
90042
90519
  required: ["level", "numId"],
90043
90520
  properties: {
90044
90521
  level: { type: "number" },
90045
- numId: { type: "string" }
90522
+ numId: { type: "string" },
90523
+ ordered: { type: "boolean" },
90524
+ start: { type: "number" },
90525
+ format: { type: "string" }
90046
90526
  }
90047
90527
  },
90048
90528
  taskState: { enum: ["checked", "unchecked"] },
@@ -90236,6 +90716,7 @@ var init_schema = __esm(() => {
90236
90716
  width: { $ref: "#/$defs/TableWidth" },
90237
90717
  borders: { type: "string" },
90238
90718
  style: { type: "string" },
90719
+ align: { enum: ["left", "center", "right"] },
90239
90720
  rows: {
90240
90721
  type: "array",
90241
90722
  items: {
@@ -90254,6 +90735,8 @@ var init_schema = __esm(() => {
90254
90735
  vMerge: { enum: ["restart", "continue"] },
90255
90736
  width: { $ref: "#/$defs/TableWidth" },
90256
90737
  shading: { type: "string" },
90738
+ vAlign: { enum: ["top", "center", "bottom"] },
90739
+ borders: { type: "string" },
90257
90740
  trackedChange: {
90258
90741
  $ref: "#/$defs/TableRevision",
90259
90742
  description: "cellIns / cellDel (tracked column change)"
@@ -90264,7 +90747,15 @@ var init_schema = __esm(() => {
90264
90747
  trackedChange: {
90265
90748
  $ref: "#/$defs/TableRevision",
90266
90749
  description: "rowIns / rowDel (tracked row change)"
90267
- }
90750
+ },
90751
+ height: {
90752
+ type: "object",
90753
+ properties: {
90754
+ value: { type: "number" },
90755
+ rule: { enum: ["atLeast", "exact", "auto"] }
90756
+ }
90757
+ },
90758
+ repeatHeader: { type: "boolean" }
90268
90759
  }
90269
90760
  }
90270
90761
  }
@@ -90539,15 +91030,190 @@ var init_locators2 = __esm(() => {
90539
91030
  ];
90540
91031
  });
90541
91032
 
91033
+ // src/cli/info/skill.ts
91034
+ var exports_skill = {};
91035
+ __export(exports_skill, {
91036
+ run: () => run33
91037
+ });
91038
+ function renderMarkdown() {
91039
+ return `---
91040
+ name: ${NAME}
91041
+ description: ${JSON.stringify(DESCRIPTION)}
91042
+ ---
91043
+
91044
+ ${BODY}`;
91045
+ }
91046
+ async function run33(args) {
91047
+ const parsed = await tryParseArgs(args, {
91048
+ json: { type: "boolean" },
91049
+ help: { type: "boolean", short: "h" }
91050
+ }, HELP29);
91051
+ if (typeof parsed === "number")
91052
+ return parsed;
91053
+ if (parsed.values.help) {
91054
+ await writeStdout(HELP29);
91055
+ return EXIT2.OK;
91056
+ }
91057
+ if (parsed.values.json) {
91058
+ await writeStdout(`${JSON.stringify({ name: NAME, description: DESCRIPTION, shortDescription: SHORT_DESCRIPTION, body: BODY }, null, 2)}
91059
+ `);
91060
+ return EXIT2.OK;
91061
+ }
91062
+ await writeStdout(renderMarkdown());
91063
+ return EXIT2.OK;
91064
+ }
91065
+ var HELP29 = `docx info skill \u2014 print the canonical Agent Skill (SKILL.md)
91066
+
91067
+ The binary is the source of truth for the skill. Regenerate the committed copy with:
91068
+ docx info skill > skills/docx-cli/SKILL.md
91069
+ A CI drift test fails if the committed SKILL.md no longer matches this output.
91070
+
91071
+ Usage:
91072
+ docx info skill [options]
91073
+
91074
+ Options:
91075
+ --json Emit { name, description, shortDescription, body } as JSON
91076
+ -h, --help Show this help
91077
+
91078
+ Examples:
91079
+ docx info skill
91080
+ docx info skill > skills/docx-cli/SKILL.md
91081
+ docx info skill --json | jq -r '.description'
91082
+ `, NAME = "docx-cli", DESCRIPTION, SHORT_DESCRIPTION = "Read, edit, redline, and comment on Microsoft Word .docx files from the command line \u2014 built for AI agents.", BODY = `# docx-cli
91083
+
91084
+ \`docx\` is a command-line tool for reading, editing, redlining, and commenting on
91085
+ Microsoft Word \`.docx\` files. It edits the underlying OOXML **in place** (it never
91086
+ rebuilds the document from a lossy view), addresses everything with **stable
91087
+ locators**, and signals success through an **exit code** plus a one-line
91088
+ confirmation \u2014 so even small, cheap models can drive it reliably.
91089
+
91090
+ ## 0. Make sure the binary is on PATH
91091
+
91092
+ Run \`docx --version\`. If you get "command not found", install it:
91093
+
91094
+ \`\`\`sh
91095
+ curl -fsSL https://raw.githubusercontent.com/kklimuk/docx-cli/main/install.sh | sh
91096
+ \`\`\`
91097
+
91098
+ Or, from this skill folder, run \`bash scripts/bootstrap.sh\` \u2014 it checks the
91099
+ installed version against the latest release and self-updates. Every verb works
91100
+ against the \`.docx\` zip directly; only \`docx render\` needs Word (macOS/Windows)
91101
+ or LibreOffice installed.
91102
+
91103
+ ## 1. The contract is \`--help\` / \`docx info\` \u2014 start there
91104
+
91105
+ The help text is authoritative and versioned with the binary. This skill is thin
91106
+ on purpose and defers to it. Before doing anything, run (none of these need a FILE):
91107
+
91108
+ \`\`\`sh
91109
+ docx --help # every command + a one-line capability hint each
91110
+ docx info locators # the addressing grammar \u2014 READ THIS, it is the backbone
91111
+ docx info schema # the JSON-AST shape that "docx read --ast" emits
91112
+ \`\`\`
91113
+
91114
+ Then \`docx <command> --help\` for any verb before you use it.
91115
+
91116
+ ## 2. Locators \u2014 how you address things
91117
+
91118
+ - \`pN\` paragraph, \`tN\` table, \`sN\` section; \`p3:5-20\` = characters 5..19 of \`p3\`;
91119
+ \`pN-pM\` a block range; \`tN:rRcC\` a table cell.
91120
+ - Entities: \`cN\` comment, \`imgN\` image, \`linkN\` hyperlink, \`fnN\`/\`enN\`
91121
+ foot/endnote, \`tcN\` tracked change, \`eqN\` equation.
91122
+ - Get them from \`docx read FILE\` (locators ride the Markdown as \`<!-- pN -->\`
91123
+ comments) or \`docx read FILE --ast\` (lossless JSON).
91124
+ - **Ids are positional and SHIFT after structural edits.** Re-read between
91125
+ mutations \u2014 OR apply many changes from ONE read with \`--batch\` (below).
91126
+ - Pass a locator with \`--at\` (edit / delete / comments / footnotes / images /
91127
+ hyperlinks / tables / track-changes), \`--after\`/\`--before\` (insert), or
91128
+ \`--from\`/\`--to\` (read a slice).
91129
+ - Don't hand-count character offsets: \`docx find FILE "phrase"\` returns the exact
91130
+ span locator (e.g. \`p3:5-20\`) to paste into \`--at\`.
91131
+
91132
+ ## 3. Golden workflows
91133
+
91134
+ ### Fill out a form or contract (keeps formatting)
91135
+ \`docx replace\` swaps only the text and preserves the run's bold/font and any tab
91136
+ stops \u2014 so it fills bold, tabbed template lines without rebuilding runs.
91137
+ \`\`\`sh
91138
+ docx read contract.docx # see content + locators
91139
+ docx replace contract.docx "[Client Name]" "Acme, Inc." # one field
91140
+ docx replace contract.docx --batch fills.jsonl # many fields, one read/write
91141
+ \`\`\`
91142
+
91143
+ ### Redline with tracked changes
91144
+ \`\`\`sh
91145
+ docx track-changes on contract.docx # turn tracking on (doc-level)
91146
+ docx replace contract.docx "Net 90" "Net 30" # now auto-emits <w:ins>/<w:del>
91147
+ docx edit --at p12:0-40 contract.docx --text "\u2026" --track # or redline one edit
91148
+ docx track-changes list contract.docx # the tcN handles
91149
+ docx read contract.docx --current # view redlines as CriticMarkup
91150
+ docx track-changes accept contract.docx --at tc3 # or --all / reject
91151
+ \`\`\`
91152
+
91153
+ ### Comment on clauses
91154
+ \`\`\`sh
91155
+ docx comments add contract.docx --anchor "limitation of liability" --text "Cap is too low."
91156
+ docx comments list contract.docx
91157
+ docx comments reply contract.docx --at c0 --text "Agreed, raising to \\$5M."
91158
+ docx comments resolve contract.docx --at c0
91159
+ \`\`\`
91160
+
91161
+ ### Read / extract
91162
+ \`\`\`sh
91163
+ docx read FILE # Markdown (default; tracked changes shown accepted-clean)
91164
+ docx read FILE --ast # lossless JSON AST
91165
+ docx wc FILE # word count (whole doc or a slice)
91166
+ docx outline FILE # headings as a locator tree
91167
+ \`\`\`
91168
+
91169
+ ### Build from scratch / verify layout
91170
+ \`\`\`sh
91171
+ docx create out.docx --from draft.md # GFM + math + CriticMarkup + inline HTML
91172
+ docx render FILE --out pages/ # PNG per page \u2014 only when LAYOUT is the question
91173
+ \`\`\`
91174
+
91175
+ ## 4. Apply many changes from one read \u2014 \`--batch\`
91176
+
91177
+ \`edit\`, \`insert\`, \`replace\`, \`delete\`, and the \`comments\` verbs take
91178
+ \`--batch FILE.jsonl\` (one JSON change per line; \`-\` reads stdin). Every locator
91179
+ in the batch addresses the document **as read**, so ids stay valid across the whole
91180
+ batch \u2014 one read, one write, no re-reading between changes. Keys mirror the
91181
+ command's flags. This is the right tool for filling a form or applying a review.
91182
+
91183
+ ## 5. Output & safety contract
91184
+
91185
+ - **Exit code is the success signal:** \`0\` ok, \`1\` error, \`2\` usage, \`3\`
91186
+ not-found. Every command also prints a one-line text confirmation \u2014 you never
91187
+ have to re-read just to learn whether a mutation landed.
91188
+ - Mutators overwrite \`FILE\` **in place** (git is your history). \`-o/--output PATH\`
91189
+ writes a copy instead; \`--dry-run\` previews without writing.
91190
+ - A command that mints a new handle (\`comments add\`\u2192\`cN\`, \`insert\`\u2192\`pN\`,
91191
+ \`footnotes add\`\u2192\`fnN\`, \u2026) prints the bare locator(s), one per line.
91192
+ - Re-read after structural edits (ids shift), or batch from one read.
91193
+ - Need exact literal text in (a URL, prose GFM would mangle)? \`insert\` and
91194
+ \`create\` take \`--text-file PATH\` (\`-\` = stdin): every character lands verbatim,
91195
+ each newline a new paragraph. No escaping burden.
91196
+
91197
+ ## 6. Going deeper
91198
+
91199
+ - \`references/commands.md\` \u2014 the full command surface at a glance.
91200
+ - \`references/troubleshooting.md\` \u2014 install, PATH, render runtime, common errors.
91201
+ - Or just run \`docx <command> --help\` \u2014 the authoritative, versioned contract.
91202
+ `;
91203
+ var init_skill = __esm(() => {
91204
+ init_respond();
91205
+ DESCRIPTION = "Read, edit, redline, comment on, and create Microsoft Word .docx files. " + "Use to fill out or edit a Word doc, redline a contract with tracked changes, " + "add/resolve comments, replace text keeping its formatting, restyle headings/fonts, " + "edit tables, or read/extract a .docx as Markdown or text. Also BUILD a new .docx \u2014 " + "from Markdown or programmatically (code that outputs a Word report with headings, " + "tables, images). Not for PDF, Google Docs, Excel, PowerPoint, or .doc.";
91206
+ });
91207
+
90542
91208
  // src/cli/info/index.ts
90543
91209
  var exports_info = {};
90544
91210
  __export(exports_info, {
90545
- run: () => run33
91211
+ run: () => run34
90546
91212
  });
90547
- async function run33(args) {
91213
+ async function run34(args) {
90548
91214
  const topic = args[0];
90549
91215
  if (!topic || topic === "--help" || topic === "-h" || topic === "help") {
90550
- await writeStdout(HELP29);
91216
+ await writeStdout(HELP30);
90551
91217
  return topic ? 0 : 2;
90552
91218
  }
90553
91219
  const loader = SUBCOMMANDS8[topic];
@@ -90557,7 +91223,7 @@ async function run33(args) {
90557
91223
  const module_ = await loader();
90558
91224
  return module_.run(args.slice(1));
90559
91225
  }
90560
- var SUBCOMMANDS8, HELP29 = `docx info \u2014 print reference material about the CLI
91226
+ var SUBCOMMANDS8, HELP30 = `docx info \u2014 print reference material about the CLI
90561
91227
 
90562
91228
  Usage:
90563
91229
  docx info <topic> [options]
@@ -90565,6 +91231,7 @@ Usage:
90565
91231
  Topics:
90566
91232
  schema Dump AST JSON Schema (or TS source via --ts)
90567
91233
  locators Dump locator grammar reference
91234
+ skill Print the canonical Agent Skill (SKILL.md)
90568
91235
 
90569
91236
  Run "docx info <topic> --help" for topic-specific help.
90570
91237
  `;
@@ -90572,7 +91239,218 @@ var init_info = __esm(() => {
90572
91239
  init_respond();
90573
91240
  SUBCOMMANDS8 = {
90574
91241
  schema: () => Promise.resolve().then(() => (init_schema(), exports_schema)),
90575
- locators: () => Promise.resolve().then(() => (init_locators2(), exports_locators))
91242
+ locators: () => Promise.resolve().then(() => (init_locators2(), exports_locators)),
91243
+ skill: () => Promise.resolve().then(() => (init_skill(), exports_skill))
91244
+ };
91245
+ });
91246
+
91247
+ // src/cli/lists/set.ts
91248
+ var exports_set = {};
91249
+ __export(exports_set, {
91250
+ run: () => run35
91251
+ });
91252
+ async function run35(args) {
91253
+ const parsed = await tryParseArgs(args, {
91254
+ at: { type: "string" },
91255
+ start: { type: "string" },
91256
+ format: { type: "string" },
91257
+ restart: { type: "boolean" },
91258
+ continue: { type: "boolean" },
91259
+ ...SAVE_FLAGS
91260
+ }, HELP31);
91261
+ if (typeof parsed === "number")
91262
+ return parsed;
91263
+ if (parsed.values.help) {
91264
+ await writeStdout(HELP31);
91265
+ return EXIT2.OK;
91266
+ }
91267
+ setVerboseAck(Boolean(parsed.values.verbose));
91268
+ const path2 = parsed.positionals[0];
91269
+ if (!path2)
91270
+ return fail("USAGE", "Missing FILE argument", HELP31);
91271
+ const at = parsed.values.at;
91272
+ if (!at) {
91273
+ return fail("USAGE", "Missing --at LOCATOR (a list item, e.g. p5)", HELP31);
91274
+ }
91275
+ const plan = buildPlan(parsed.values);
91276
+ if (typeof plan === "string")
91277
+ return fail("USAGE", plan);
91278
+ const document4 = await openOrFail(path2);
91279
+ if (typeof document4 === "number")
91280
+ return document4;
91281
+ const blockRef = await resolveBlockOrFail(document4, at);
91282
+ if (typeof blockRef === "number")
91283
+ return blockRef;
91284
+ const orderedError = validateOrderedList(document4, at);
91285
+ if (orderedError)
91286
+ return fail("USAGE", orderedError);
91287
+ const outputPath = parsed.values.output;
91288
+ if (parsed.values["dry-run"]) {
91289
+ await respond({
91290
+ operation: "lists.set",
91291
+ dryRun: true,
91292
+ path: path2,
91293
+ at,
91294
+ applied: appliedList(plan),
91295
+ ...outputPath ? { output: outputPath } : {}
91296
+ });
91297
+ return EXIT2.OK;
91298
+ }
91299
+ const lists = new Lists(document4);
91300
+ try {
91301
+ if (plan.continue) {
91302
+ lists.continue(blockRef);
91303
+ } else if (plan.restart) {
91304
+ lists.restart(blockRef, plan.start ?? 1);
91305
+ if (plan.format)
91306
+ lists.setFormat(blockRef, plan.format);
91307
+ } else {
91308
+ if (plan.start !== undefined)
91309
+ lists.setStart(blockRef, plan.start);
91310
+ if (plan.format)
91311
+ lists.setFormat(blockRef, plan.format);
91312
+ }
91313
+ } catch (error) {
91314
+ if (error instanceof ListOperationError) {
91315
+ return fail("BLOCK_NOT_FOUND", error.message);
91316
+ }
91317
+ throw error;
91318
+ }
91319
+ await document4.save(outputPath);
91320
+ const destination = outputPath ?? path2;
91321
+ await respondAck({
91322
+ ok: true,
91323
+ operation: "lists.set",
91324
+ path: destination,
91325
+ locator: at,
91326
+ applied: appliedList(plan)
91327
+ });
91328
+ return EXIT2.OK;
91329
+ }
91330
+ function buildPlan(values2) {
91331
+ const restart = Boolean(values2.restart);
91332
+ const continueFlag = Boolean(values2.continue);
91333
+ if (restart && continueFlag) {
91334
+ return "Pass only one of --restart / --continue";
91335
+ }
91336
+ let start;
91337
+ if (values2.start !== undefined) {
91338
+ const parsedStart = Number(values2.start);
91339
+ if (!Number.isInteger(parsedStart) || parsedStart < 1) {
91340
+ return `--start must be a positive integer (got ${values2.start})`;
91341
+ }
91342
+ start = parsedStart;
91343
+ }
91344
+ let format;
91345
+ if (values2.format !== undefined) {
91346
+ const candidate = String(values2.format);
91347
+ if (!Object.hasOwn(FORMAT_TO_NUMFMT, candidate)) {
91348
+ return `--format must be one of ${Object.keys(FORMAT_TO_NUMFMT).join(", ")} (got ${candidate})`;
91349
+ }
91350
+ format = candidate;
91351
+ }
91352
+ if (continueFlag && (start !== undefined || format !== undefined)) {
91353
+ return "--continue adopts the previous list's numbering \u2014 it can't combine with --start/--format";
91354
+ }
91355
+ if (!restart && !continueFlag && start === undefined && format === undefined) {
91356
+ return "Nothing to do \u2014 pass --start, --format, --restart, or --continue";
91357
+ }
91358
+ return { start, format, restart, continue: continueFlag };
91359
+ }
91360
+ function validateOrderedList(document4, at) {
91361
+ const block = document4.body.findBlockById(at);
91362
+ if (!block || block.type !== "paragraph" || !block.list) {
91363
+ return `${at} is not a list item \u2014 list numbering controls only apply to numbered lists`;
91364
+ }
91365
+ if (!block.list.ordered) {
91366
+ return `${at} is a bulleted list \u2014 numbering controls (start/format/restart/continue) apply to numbered (ordered) lists`;
91367
+ }
91368
+ return null;
91369
+ }
91370
+ function appliedList(plan) {
91371
+ const applied = [];
91372
+ if (plan.continue)
91373
+ applied.push("continue");
91374
+ if (plan.restart)
91375
+ applied.push("restart");
91376
+ if (plan.start !== undefined)
91377
+ applied.push(`start=${plan.start}`);
91378
+ if (plan.format)
91379
+ applied.push(`format=${plan.format}`);
91380
+ return applied;
91381
+ }
91382
+ var HELP31 = `docx lists set \u2014 renumber a numbered list (start value, glyph format, restart/continue)
91383
+
91384
+ Usage:
91385
+ docx lists set FILE --at pN [options]
91386
+
91387
+ --at names any item of a NUMBERED (ordered) list. --start/--format change the whole
91388
+ list (every paragraph sharing its numbering); --restart/--continue act from the
91389
+ addressed item onward. Bulleted lists aren't numbered, so they're rejected.
91390
+
91391
+ Options:
91392
+ --start N Start the list's numbering at N (a positive integer)
91393
+ --format FMT Glyph style: decimal | lower-alpha | upper-alpha | lower-roman | upper-roman
91394
+ (decimal = 1.2.3., lower-alpha = a.b.c., upper-roman = I.II.III., \u2026)
91395
+ --restart Begin a FRESH list at this item: split it off with its own numbering
91396
+ (combine with --start/--format to set the new list's first number/style)
91397
+ --continue Continue the PREVIOUS list's numbering here instead of restarting at 1
91398
+ -o, --output PATH / --dry-run / -v, --verbose / -h, --help
91399
+
91400
+ --restart and --continue are mutually exclusive; --continue can't combine with
91401
+ --start/--format (it adopts the previous list's numbering). List numbering edits
91402
+ are applied directly (untracked) \u2014 Word records no revision for them.
91403
+
91404
+ Examples:
91405
+ docx lists set report.docx --at p12 --start 5
91406
+ docx lists set report.docx --at p12 --format upper-roman
91407
+ docx lists set report.docx --at p20 --restart --start 1
91408
+ docx lists set report.docx --at p20 --continue
91409
+ `;
91410
+ var init_set2 = __esm(() => {
91411
+ init_core2();
91412
+ init_respond();
91413
+ });
91414
+
91415
+ // src/cli/lists/index.ts
91416
+ var exports_lists = {};
91417
+ __export(exports_lists, {
91418
+ run: () => run36
91419
+ });
91420
+ async function run36(args) {
91421
+ const verb = args[0];
91422
+ if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
91423
+ await writeStdout(HELP32);
91424
+ return verb ? 0 : 2;
91425
+ }
91426
+ const loader = SUBCOMMANDS9[verb];
91427
+ if (!loader) {
91428
+ return fail("USAGE", `Unknown lists subcommand: ${verb}`, 'Run "docx lists --help".');
91429
+ }
91430
+ const module_ = await loader();
91431
+ return module_.run(args.slice(1));
91432
+ }
91433
+ var SUBCOMMANDS9, HELP32 = `docx lists \u2014 control list numbering (start value, glyph format, restart/continue)
91434
+
91435
+ Usage:
91436
+ docx lists set FILE --at pN [options]
91437
+
91438
+ Verbs:
91439
+ set Renumber a numbered list \u2014 set its start value or glyph format, or make it
91440
+ restart vs. continue the previous list
91441
+ (--at pN [--start N] [--format FMT] [--restart] [--continue])
91442
+
91443
+ Lists are otherwise handled by the standard verbs:
91444
+ create a list docx insert FILE --after pN --list "first,second" (or markdown "1. \u2026")
91445
+ edit an item docx edit FILE --at pN --text "..."
91446
+ inspect docx read FILE --ast (list.numId / level / ordered / start / format)
91447
+
91448
+ Run "docx lists set --help" for option detail.
91449
+ `;
91450
+ var init_lists2 = __esm(() => {
91451
+ init_respond();
91452
+ SUBCOMMANDS9 = {
91453
+ set: () => Promise.resolve().then(() => (init_set2(), exports_set))
90576
91454
  };
90577
91455
  });
90578
91456
 
@@ -90637,23 +91515,23 @@ var init_build = __esm(() => {
90637
91515
  // src/cli/outline/index.ts
90638
91516
  var exports_outline = {};
90639
91517
  __export(exports_outline, {
90640
- run: () => run34
91518
+ run: () => run37
90641
91519
  });
90642
- async function run34(args) {
91520
+ async function run37(args) {
90643
91521
  const parsed = await tryParseArgs(args, {
90644
91522
  "style-prefix": { type: "string" },
90645
91523
  json: { type: "boolean" },
90646
91524
  help: { type: "boolean", short: "h" }
90647
- }, HELP30);
91525
+ }, HELP33);
90648
91526
  if (typeof parsed === "number")
90649
91527
  return parsed;
90650
91528
  if (parsed.values.help) {
90651
- await writeStdout(HELP30);
91529
+ await writeStdout(HELP33);
90652
91530
  return EXIT2.OK;
90653
91531
  }
90654
91532
  const path2 = parsed.positionals[0];
90655
91533
  if (!path2)
90656
- return fail("USAGE", "Missing FILE argument", HELP30);
91534
+ return fail("USAGE", "Missing FILE argument", HELP33);
90657
91535
  const stylePrefix = parsed.values["style-prefix"] ?? "Heading";
90658
91536
  if (stylePrefix.length === 0) {
90659
91537
  return fail("USAGE", "--style-prefix cannot be empty");
@@ -90681,7 +91559,7 @@ function renderOutlineText(entries, depth = 0) {
90681
91559
  }
90682
91560
  return lines;
90683
91561
  }
90684
- var HELP30 = `docx outline \u2014 list headings as a hierarchical tree
91562
+ var HELP33 = `docx outline \u2014 list headings as a hierarchical tree
90685
91563
 
90686
91564
  Usage:
90687
91565
  docx outline FILE [options]
@@ -90739,7 +91617,7 @@ function emuToInches(emu) {
90739
91617
  function deviation(value, def) {
90740
91618
  return value !== undefined && value !== def ? value : undefined;
90741
91619
  }
90742
- function renderMarkdown(doc, options = {}) {
91620
+ function renderMarkdown2(doc, options = {}) {
90743
91621
  const blocks = sliceBlocks(doc.blocks, options.from, options.to);
90744
91622
  const dominant = detectFormatBaseline(blocks);
90745
91623
  const baseline = {
@@ -90761,6 +91639,8 @@ function renderMarkdown(doc, options = {}) {
90761
91639
  referencedEndnoteIds: new Set,
90762
91640
  referencedTrackedChanges: new Map,
90763
91641
  orderedCounters: new Map,
91642
+ prevListNumId: null,
91643
+ seenListNumIds: new Set,
90764
91644
  contentWidthEmu: contentWidthEmu(documentGeometry(blocks)?.geometry),
90765
91645
  governingColumns: computeGoverningColumns(blocks),
90766
91646
  wrappingTabLines: [],
@@ -90847,17 +91727,17 @@ function detectFormatBaseline(blocks) {
90847
91727
  const sizeChars = new Map;
90848
91728
  let total = 0;
90849
91729
  for (const paragraph2 of flattenParagraphs(blocks)) {
90850
- for (const run35 of paragraph2.runs) {
90851
- if (run35.type !== "text")
91730
+ for (const run38 of paragraph2.runs) {
91731
+ if (run38.type !== "text")
90852
91732
  continue;
90853
- const length = run35.text.length;
91733
+ const length = run38.text.length;
90854
91734
  if (length === 0)
90855
91735
  continue;
90856
91736
  total += length;
90857
- if (run35.font)
90858
- fontChars.set(run35.font, (fontChars.get(run35.font) ?? 0) + length);
90859
- if (run35.sizeHalfPoints !== undefined) {
90860
- sizeChars.set(run35.sizeHalfPoints, (sizeChars.get(run35.sizeHalfPoints) ?? 0) + length);
91737
+ if (run38.font)
91738
+ fontChars.set(run38.font, (fontChars.get(run38.font) ?? 0) + length);
91739
+ if (run38.sizeHalfPoints !== undefined) {
91740
+ sizeChars.set(run38.sizeHalfPoints, (sizeChars.get(run38.sizeHalfPoints) ?? 0) + length);
90861
91741
  }
90862
91742
  }
90863
91743
  }
@@ -90891,8 +91771,8 @@ function emptyCommentIndex() {
90891
91771
  orderedIds: []
90892
91772
  };
90893
91773
  }
90894
- function isRunVisible(run35, view) {
90895
- const kind = run35.trackedChange?.kind;
91774
+ function isRunVisible(run38, view) {
91775
+ const kind = run38.trackedChange?.kind;
90896
91776
  if (!kind)
90897
91777
  return true;
90898
91778
  if (view === "accepted" && (kind === "del" || kind === "moveFrom"))
@@ -90907,13 +91787,13 @@ function buildCommentIndex(blocks, options) {
90907
91787
  const spanText = new Map;
90908
91788
  const orderedIds = [];
90909
91789
  for (const paragraph2 of flattenParagraphs(blocks)) {
90910
- paragraph2.runs.forEach((run35, index2) => {
90911
- const comments = runComments(run35);
91790
+ paragraph2.runs.forEach((run38, index2) => {
91791
+ const comments = runComments(run38);
90912
91792
  if (!comments)
90913
91793
  return;
90914
- if (run35.type === "text" && !isRunVisible(run35, view))
91794
+ if (run38.type === "text" && !isRunVisible(run38, view))
90915
91795
  return;
90916
- const spanContribution = run35.type === "text" ? run35.text : run35.type === "equation" ? run35.text : "";
91796
+ const spanContribution = run38.type === "text" ? run38.text : run38.type === "equation" ? run38.text : "";
90917
91797
  for (const commentId of comments) {
90918
91798
  if (!spanText.has(commentId))
90919
91799
  orderedIds.push(commentId);
@@ -90933,11 +91813,11 @@ function buildCommentIndex(blocks, options) {
90933
91813
  }
90934
91814
  return { endingsByRun, spanText, orderedIds };
90935
91815
  }
90936
- function runComments(run35) {
90937
- if (run35.type === "text")
90938
- return run35.comments;
90939
- if (run35.type === "equation")
90940
- return run35.comments;
91816
+ function runComments(run38) {
91817
+ if (run38.type === "text")
91818
+ return run38.comments;
91819
+ if (run38.type === "equation")
91820
+ return run38.comments;
90941
91821
  return;
90942
91822
  }
90943
91823
  function slotKey(paragraphId, runIndex) {
@@ -90946,6 +91826,7 @@ function slotKey(paragraphId, runIndex) {
90946
91826
  function renderBlock(block, ctx) {
90947
91827
  if (block.type === "paragraph")
90948
91828
  return renderParagraph(block, ctx);
91829
+ ctx.prevListNumId = null;
90949
91830
  if (block.type === "table")
90950
91831
  return renderTable(block, ctx);
90951
91832
  return null;
@@ -91009,7 +91890,7 @@ function tabCureRange(ids) {
91009
91890
  return min === max ? `p${min}` : `p${min}-p${max}`;
91010
91891
  }
91011
91892
  function layoutHazardNote(paragraph2, ctx) {
91012
- if (!paragraph2.runs.some((run35) => run35.type === "tab"))
91893
+ if (!paragraph2.runs.some((run38) => run38.type === "tab"))
91013
91894
  return "";
91014
91895
  const cols = ctx.governingColumns.get(paragraph2.id) ?? 1;
91015
91896
  if (cols > 1) {
@@ -91082,25 +91963,25 @@ function contentWidthEmu(geometry) {
91082
91963
  const fallback = (DEFAULT_PAGE.width - 2 * DEFAULT_PAGE.margin) * EMU_PER_TWIP2;
91083
91964
  return contentTwips > 0 ? contentTwips * EMU_PER_TWIP2 : fallback;
91084
91965
  }
91085
- function formatImageNote(run35, contentEmu) {
91966
+ function formatImageNote(run38, contentEmu) {
91086
91967
  const pairs = [];
91087
- if (run35.widthEmu && run35.heightEmu) {
91968
+ if (run38.widthEmu && run38.heightEmu) {
91088
91969
  pairs.push([
91089
91970
  "size",
91090
- `${emuToInches(run35.widthEmu)}x${emuToInches(run35.heightEmu)}in`
91971
+ `${emuToInches(run38.widthEmu)}x${emuToInches(run38.heightEmu)}in`
91091
91972
  ]);
91092
91973
  }
91093
- if (run35.floating)
91974
+ if (run38.floating)
91094
91975
  pairs.push(["float", "yes"]);
91095
- if (run35.wrap)
91096
- pairs.push(["wrap", run35.wrap]);
91097
- if (run35.align)
91098
- pairs.push(["align", run35.align]);
91099
- if (run35.widthEmu && run35.widthEmu > contentEmu)
91976
+ if (run38.wrap)
91977
+ pairs.push(["wrap", run38.wrap]);
91978
+ if (run38.align)
91979
+ pairs.push(["align", run38.align]);
91980
+ if (run38.widthEmu && run38.widthEmu > contentEmu)
91100
91981
  pairs.push(["overflow", "yes"]);
91101
91982
  if (pairs.length === 0)
91102
91983
  return "";
91103
- return ` ${formatNote("image", pairs, [run35.id])}`;
91984
+ return ` ${formatNote("image", pairs, [run38.id])}`;
91104
91985
  }
91105
91986
  function documentGeometry(blocks) {
91106
91987
  const geometric = blocks.filter((block) => block.type === "sectionBreak" && hasGeometry(block));
@@ -91206,14 +92087,14 @@ function isCodeBlockParagraph(block) {
91206
92087
  function renderCodeBlockGroup(paragraphs, ctx) {
91207
92088
  if (ctx.options.view !== "baseline" && ctx.options.view !== "accepted") {
91208
92089
  for (const paragraph2 of paragraphs) {
91209
- for (const run35 of paragraph2.runs) {
91210
- if (run35.type === "text" && run35.trackedChange) {
91211
- ctx.referencedTrackedChanges.set(run35.trackedChange.id, run35.trackedChange);
92090
+ for (const run38 of paragraph2.runs) {
92091
+ if (run38.type === "text" && run38.trackedChange) {
92092
+ ctx.referencedTrackedChanges.set(run38.trackedChange.id, run38.trackedChange);
91212
92093
  }
91213
92094
  }
91214
92095
  }
91215
92096
  }
91216
- const lines = paragraphs.map((paragraph2) => paragraph2.runs.filter((run35) => run35.type === "text" && typeof run35.text === "string").map((run35) => run35.text).join(""));
92097
+ const lines = paragraphs.map((paragraph2) => paragraph2.runs.filter((run38) => run38.type === "text" && typeof run38.text === "string").map((run38) => run38.text).join(""));
91217
92098
  const firstId = paragraphs[0]?.id ?? "";
91218
92099
  const lastId = paragraphs[paragraphs.length - 1]?.id ?? firstId;
91219
92100
  const language = codeBlockLanguageFromStyleId(paragraphs[0]?.style) ?? "";
@@ -91227,11 +92108,14 @@ function renderParagraph(paragraph2, ctx) {
91227
92108
  const view = ctx.options.view ?? "accepted";
91228
92109
  const mask = inlineEscapeMask(paragraphContent(paragraph2.runs, view), hasEquationRun(paragraph2.runs));
91229
92110
  const rendered = renderRuns(paragraph2.id, paragraph2.runs, ctx, mask, 0);
91230
- if (rendered.length === 0)
92111
+ if (rendered.length === 0) {
92112
+ ctx.prevListNumId = paragraph2.list?.numId ?? null;
91231
92113
  return null;
92114
+ }
91232
92115
  const prefix = paragraphPrefix(paragraph2, orderedOrdinal(paragraph2, ctx));
91233
92116
  const body = rendered.replace(/[ \t]+$/, "");
91234
- const note = formatParagraphNote(paragraph2);
92117
+ const listNote = listAnnotation(paragraph2, ctx);
92118
+ const note = listNote !== "" ? listNote : formatParagraphNote(paragraph2);
91235
92119
  const locatorOrNote = note !== "" ? note : ` <!-- ${paragraph2.id} -->`;
91236
92120
  const trailing = `${locatorOrNote}${layoutHazardNote(paragraph2, ctx)}`;
91237
92121
  if (isDisplayEquationOnly(body)) {
@@ -91296,7 +92180,8 @@ function orderedOrdinal(paragraph2, ctx) {
91296
92180
  return 1;
91297
92181
  const { numId, level } = paragraph2.list;
91298
92182
  const key = `${numId}:${level}`;
91299
- const next = (ctx.orderedCounters.get(key) ?? 0) + 1;
92183
+ const base = ctx.orderedCounters.get(key) ?? (paragraph2.list.start ?? 1) - 1;
92184
+ const next = base + 1;
91300
92185
  ctx.orderedCounters.set(key, next);
91301
92186
  for (const existing of ctx.orderedCounters.keys()) {
91302
92187
  const [keyNumId, keyLevel] = existing.split(":");
@@ -91306,6 +92191,32 @@ function orderedOrdinal(paragraph2, ctx) {
91306
92191
  }
91307
92192
  return next;
91308
92193
  }
92194
+ function listAnnotation(paragraph2, ctx) {
92195
+ const list3 = paragraph2.list;
92196
+ if (!list3) {
92197
+ ctx.prevListNumId = null;
92198
+ return "";
92199
+ }
92200
+ const isRunStart = ctx.prevListNumId !== list3.numId;
92201
+ ctx.prevListNumId = list3.numId;
92202
+ if (!isRunStart)
92203
+ return "";
92204
+ const isContinuation = ctx.seenListNumIds.has(list3.numId);
92205
+ ctx.seenListNumIds.add(list3.numId);
92206
+ if (!list3.ordered)
92207
+ return "";
92208
+ if (isContinuation) {
92209
+ return ` ${formatNote("list", [], [paragraph2.id, "continues"])}`;
92210
+ }
92211
+ const pairs = [];
92212
+ if (list3.start !== undefined && list3.start !== 1)
92213
+ pairs.push(["start", list3.start]);
92214
+ if (list3.format)
92215
+ pairs.push(["format", list3.format]);
92216
+ if (pairs.length === 0)
92217
+ return "";
92218
+ return ` ${formatNote("list", pairs, [paragraph2.id])}`;
92219
+ }
91309
92220
  function paragraphPrefix(paragraph2, ordinal) {
91310
92221
  const quotePrefix = paragraph2.quoteDepth ? "> ".repeat(paragraph2.quoteDepth) : "";
91311
92222
  const headingLevel2 = headingLevelFor(paragraph2.style);
@@ -91336,10 +92247,10 @@ function headingLevelFor(style) {
91336
92247
  function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
91337
92248
  const view = ctx.options.view ?? "accepted";
91338
92249
  const visibleEntries = [];
91339
- runs.forEach((run35, index2) => {
91340
- if (run35.type === "text" && !isRunVisible(run35, view))
92250
+ runs.forEach((run38, index2) => {
92251
+ if (run38.type === "text" && !isRunVisible(run38, view))
91341
92252
  return;
91342
- visibleEntries.push({ run: run35, originalIndex: index2 });
92253
+ visibleEntries.push({ run: run38, originalIndex: index2 });
91343
92254
  });
91344
92255
  let out = "";
91345
92256
  let cursor = 0;
@@ -91350,14 +92261,14 @@ function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
91350
92261
  cursor++;
91351
92262
  continue;
91352
92263
  }
91353
- const { run: run35 } = entry;
91354
- if (run35.type === "text") {
92264
+ const { run: run38 } = entry;
92265
+ if (run38.type === "text") {
91355
92266
  let lookahead2 = cursor + 1;
91356
92267
  while (lookahead2 < visibleEntries.length) {
91357
92268
  const next = visibleEntries[lookahead2];
91358
92269
  if (!next || next.run.type !== "text")
91359
92270
  break;
91360
- if (!sameDecoration(run35, next.run))
92271
+ if (!sameDecoration(run38, next.run))
91361
92272
  break;
91362
92273
  lookahead2++;
91363
92274
  }
@@ -91378,29 +92289,29 @@ function renderRuns(paragraphId, runs, ctx, mask, baseOffset) {
91378
92289
  cursor = lookahead2;
91379
92290
  continue;
91380
92291
  }
91381
- if (run35.type === "image") {
91382
- const alt = sanitizeAltText(run35.alt ?? run35.id);
91383
- const extension2 = extensionForImageMime(run35.contentType) ?? "bin";
91384
- out += `![${alt}](${run35.hash}.${extension2})`;
91385
- out += formatImageNote(run35, ctx.contentWidthEmu);
91386
- } else if (run35.type === "break") {
91387
- if (run35.kind === "line")
92292
+ if (run38.type === "image") {
92293
+ const alt = sanitizeAltText(run38.alt ?? run38.id);
92294
+ const extension2 = extensionForImageMime(run38.contentType) ?? "bin";
92295
+ out += `![${alt}](${run38.hash}.${extension2})`;
92296
+ out += formatImageNote(run38, ctx.contentWidthEmu);
92297
+ } else if (run38.type === "break") {
92298
+ if (run38.kind === "line")
91388
92299
  out += `
91389
92300
  `;
91390
- } else if (run35.type === "tab") {
92301
+ } else if (run38.type === "tab") {
91391
92302
  out += "\t";
91392
- } else if (run35.type === "equation") {
91393
- const body = run35.latex.length > 0 ? run35.latex : run35.text;
91394
- out += run35.display ? `$$${body}$$` : `$${body}$`;
92303
+ } else if (run38.type === "equation") {
92304
+ const body = run38.latex.length > 0 ? run38.latex : run38.text;
92305
+ out += run38.display ? `$$${body}$$` : `$${body}$`;
91395
92306
  out += commentEndingsFor(paragraphId, [{ originalIndex: cursor }], ctx.commentIndex);
91396
- } else if (run35.type === "noteRef") {
91397
- if (run35.kind === "footnote")
91398
- ctx.referencedFootnoteIds.add(run35.id);
92307
+ } else if (run38.type === "noteRef") {
92308
+ if (run38.kind === "footnote")
92309
+ ctx.referencedFootnoteIds.add(run38.id);
91399
92310
  else
91400
- ctx.referencedEndnoteIds.add(run35.id);
91401
- out += `[^${run35.id}]`;
91402
- } else if (run35.type === "chart") {
91403
- out += `\`[${run35.kind}]\``;
92311
+ ctx.referencedEndnoteIds.add(run38.id);
92312
+ out += `[^${run38.id}]`;
92313
+ } else if (run38.type === "chart") {
92314
+ out += `\`[${run38.kind}]\``;
91404
92315
  }
91405
92316
  cursor++;
91406
92317
  }
@@ -91434,7 +92345,7 @@ function sameCommentSet(left, right) {
91434
92345
  return true;
91435
92346
  }
91436
92347
  function renderTextSegment(runs, view, baseline, mask, offset2) {
91437
- const text6 = runs.map((run35) => run35.text).join("");
92348
+ const text6 = runs.map((run38) => run38.text).join("");
91438
92349
  if (text6.length === 0)
91439
92350
  return "";
91440
92351
  const first = runs[0];
@@ -91478,33 +92389,33 @@ function criticMarkerFor(kind) {
91478
92389
  return "++";
91479
92390
  return "--";
91480
92391
  }
91481
- function needsHtmlWrap(run35, baseline) {
91482
- return Boolean(run35.color && !isDefaultColor(run35.color) || run35.colorTheme && !isDefaultThemeColor(run35) || run35.shade || run35.font && run35.font !== baseline.font || run35.sizeHalfPoints !== undefined && run35.sizeHalfPoints !== baseline.sizeHalfPoints || run35.smallCaps || run35.allCaps || run35.underline || run35.vertAlign === "superscript" || run35.vertAlign === "subscript" || run35.highlight);
92392
+ function needsHtmlWrap(run38, baseline) {
92393
+ return Boolean(run38.color && !isDefaultColor(run38.color) || run38.colorTheme && !isDefaultThemeColor(run38) || run38.shade || run38.font && run38.font !== baseline.font || run38.sizeHalfPoints !== undefined && run38.sizeHalfPoints !== baseline.sizeHalfPoints || run38.smallCaps || run38.allCaps || run38.underline || run38.vertAlign === "superscript" || run38.vertAlign === "subscript" || run38.highlight);
91483
92394
  }
91484
- function wrapRunFormatting(body, run35, baseline) {
92395
+ function wrapRunFormatting(body, run38, baseline) {
91485
92396
  const styles = [];
91486
92397
  const attrs = [];
91487
- if (run35.color && !isDefaultColor(run35.color))
91488
- styles.push(`color:#${run35.color}`);
91489
- if (run35.shade)
91490
- styles.push(`background-color:#${run35.shade}`);
91491
- if (run35.font && run35.font !== baseline.font) {
91492
- styles.push(`font-family:${cssFontFamily(run35.font)}`);
92398
+ if (run38.color && !isDefaultColor(run38.color))
92399
+ styles.push(`color:#${run38.color}`);
92400
+ if (run38.shade)
92401
+ styles.push(`background-color:#${run38.shade}`);
92402
+ if (run38.font && run38.font !== baseline.font) {
92403
+ styles.push(`font-family:${cssFontFamily(run38.font)}`);
91493
92404
  }
91494
- if (run35.sizeHalfPoints !== undefined && run35.sizeHalfPoints !== baseline.sizeHalfPoints) {
91495
- styles.push(`font-size:${run35.sizeHalfPoints / 2}pt`);
92405
+ if (run38.sizeHalfPoints !== undefined && run38.sizeHalfPoints !== baseline.sizeHalfPoints) {
92406
+ styles.push(`font-size:${run38.sizeHalfPoints / 2}pt`);
91496
92407
  }
91497
- if (run35.smallCaps)
92408
+ if (run38.smallCaps)
91498
92409
  styles.push("font-variant:small-caps");
91499
- if (run35.allCaps)
92410
+ if (run38.allCaps)
91500
92411
  styles.push("text-transform:uppercase");
91501
- if (run35.colorTheme && !isDefaultThemeColor(run35)) {
91502
- attrs.push(htmlAttr("data-color-theme", run35.colorTheme));
91503
- if (run35.colorThemeTint) {
91504
- attrs.push(htmlAttr("data-color-theme-tint", run35.colorThemeTint));
92412
+ if (run38.colorTheme && !isDefaultThemeColor(run38)) {
92413
+ attrs.push(htmlAttr("data-color-theme", run38.colorTheme));
92414
+ if (run38.colorThemeTint) {
92415
+ attrs.push(htmlAttr("data-color-theme-tint", run38.colorThemeTint));
91505
92416
  }
91506
- if (run35.colorThemeShade) {
91507
- attrs.push(htmlAttr("data-color-theme-shade", run35.colorThemeShade));
92417
+ if (run38.colorThemeShade) {
92418
+ attrs.push(htmlAttr("data-color-theme-shade", run38.colorThemeShade));
91508
92419
  }
91509
92420
  }
91510
92421
  let out = body;
@@ -91513,18 +92424,18 @@ function wrapRunFormatting(body, run35, baseline) {
91513
92424
  const attrPart = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
91514
92425
  out = `<span${stylePart}${attrPart}>${out}</span>`;
91515
92426
  }
91516
- if (run35.underline === "single") {
92427
+ if (run38.underline === "single") {
91517
92428
  out = `<u>${out}</u>`;
91518
- } else if (run35.underline) {
91519
- const color2 = run35.underlineColor ? ` ${htmlAttr("data-underline-color", run35.underlineColor)}` : "";
91520
- out = `<u ${htmlAttr("data-underline", run35.underline)}${color2}>${out}</u>`;
92429
+ } else if (run38.underline) {
92430
+ const color2 = run38.underlineColor ? ` ${htmlAttr("data-underline-color", run38.underlineColor)}` : "";
92431
+ out = `<u ${htmlAttr("data-underline", run38.underline)}${color2}>${out}</u>`;
91521
92432
  }
91522
- if (run35.vertAlign === "superscript")
92433
+ if (run38.vertAlign === "superscript")
91523
92434
  out = `<sup>${out}</sup>`;
91524
- else if (run35.vertAlign === "subscript")
92435
+ else if (run38.vertAlign === "subscript")
91525
92436
  out = `<sub>${out}</sub>`;
91526
- if (run35.highlight) {
91527
- const named = run35.highlight === "yellow" ? "" : ` ${htmlAttr("data-highlight", run35.highlight)}`;
92437
+ if (run38.highlight) {
92438
+ const named = run38.highlight === "yellow" ? "" : ` ${htmlAttr("data-highlight", run38.highlight)}`;
91528
92439
  out = `<mark${named}>${out}</mark>`;
91529
92440
  }
91530
92441
  return out;
@@ -91533,8 +92444,8 @@ function isDefaultColor(color2) {
91533
92444
  const normalized = color2.toLowerCase();
91534
92445
  return normalized === "000000" || normalized === "auto";
91535
92446
  }
91536
- function isDefaultThemeColor(run35) {
91537
- return (run35.colorTheme === "text1" || run35.colorTheme === "dark1") && !run35.colorThemeTint && !run35.colorThemeShade;
92447
+ function isDefaultThemeColor(run38) {
92448
+ return (run38.colorTheme === "text1" || run38.colorTheme === "dark1") && !run38.colorThemeTint && !run38.colorThemeShade;
91538
92449
  }
91539
92450
  function cssFontFamily(font) {
91540
92451
  return /\s/.test(font) ? `'${font}'` : font;
@@ -91551,19 +92462,19 @@ function applyEscapeMask(text6, mask, offset2) {
91551
92462
  }
91552
92463
  function paragraphContent(runs, view) {
91553
92464
  let content3 = "";
91554
- for (const run35 of runs) {
91555
- if (run35.type !== "text")
92465
+ for (const run38 of runs) {
92466
+ if (run38.type !== "text")
91556
92467
  continue;
91557
- if (run35.runStyle === "Code")
92468
+ if (run38.runStyle === "Code")
91558
92469
  continue;
91559
- if (!isRunVisible(run35, view))
92470
+ if (!isRunVisible(run38, view))
91560
92471
  continue;
91561
- content3 += run35.text;
92472
+ content3 += run38.text;
91562
92473
  }
91563
92474
  return content3;
91564
92475
  }
91565
92476
  function hasEquationRun(runs) {
91566
- return runs.some((run35) => run35.type === "equation");
92477
+ return runs.some((run38) => run38.type === "equation");
91567
92478
  }
91568
92479
  function renderTable(table, ctx) {
91569
92480
  const view = ctx.options.view ?? "accepted";
@@ -91607,10 +92518,24 @@ function formatTableNote(table) {
91607
92518
  if (table.borders && table.borders !== "single") {
91608
92519
  pairs.push(["borders", table.borders]);
91609
92520
  }
92521
+ if (table.align && table.align !== "left")
92522
+ pairs.push(["align", table.align]);
92523
+ if (table.style)
92524
+ pairs.push(["style", table.style]);
92525
+ const repeatHeaderRows = table.rows.map((row, index2) => row.repeatHeader ? `r${index2}` : null).filter((value) => value !== null);
92526
+ if (repeatHeaderRows.length > 0)
92527
+ pairs.push(["repeat-header", repeatHeaderRows.join(",")]);
92528
+ const rowHeights = table.rows.map((row, index2) => row.height ? `r${index2}:${formatRowHeight(row.height)}` : null).filter((value) => value !== null);
92529
+ if (rowHeights.length > 0)
92530
+ pairs.push(["row-heights", rowHeights.join(",")]);
91610
92531
  if (pairs.length === 0)
91611
92532
  return "";
91612
92533
  return formatNote("table", pairs, [table.id]);
91613
92534
  }
92535
+ function formatRowHeight(height) {
92536
+ const inches = `${twipsToInches(height.value)}in`;
92537
+ return height.rule === "atLeast" ? inches : `${inches}(${height.rule})`;
92538
+ }
91614
92539
  function unevenWidths(grid) {
91615
92540
  if (grid.length < 2)
91616
92541
  return;
@@ -91667,11 +92592,27 @@ function cellNote(cell) {
91667
92592
  pairs.push(["vMerge", cell.vMerge]);
91668
92593
  if (cell.shading)
91669
92594
  pairs.push(["shading", cell.shading]);
92595
+ if (cell.vAlign)
92596
+ pairs.push(["vAlign", cell.vAlign]);
92597
+ if (cell.borders)
92598
+ pairs.push(["borders", cell.borders]);
92599
+ const halign = uniformCellAlignment(cell);
92600
+ if (halign)
92601
+ pairs.push(["halign", halign]);
91670
92602
  if (pairs.length === 0)
91671
92603
  return "";
91672
92604
  const address = cellAddress(cell);
91673
92605
  return formatNote("cell", pairs, address ? [address] : []);
91674
92606
  }
92607
+ function uniformCellAlignment(cell) {
92608
+ const aligns = cell.blocks.filter((block) => block.type === "paragraph").map((paragraph2) => paragraph2.alignment ?? "left");
92609
+ if (aligns.length === 0)
92610
+ return;
92611
+ const first = aligns[0];
92612
+ if (!first || first === "left")
92613
+ return;
92614
+ return aligns.every((align) => align === first) ? first : undefined;
92615
+ }
91675
92616
  function cellAddress(cell) {
91676
92617
  return cell.blocks[0]?.id.replace(/:(?:p|t)\d+$/, "");
91677
92618
  }
@@ -91849,9 +92790,9 @@ var init_markdown3 = __esm(() => {
91849
92790
  // src/cli/read/index.ts
91850
92791
  var exports_read = {};
91851
92792
  __export(exports_read, {
91852
- run: () => run35
92793
+ run: () => run38
91853
92794
  });
91854
- async function run35(args) {
92795
+ async function run38(args) {
91855
92796
  const parsed = await tryParseArgs(args, {
91856
92797
  ast: { type: "boolean" },
91857
92798
  from: { type: "string" },
@@ -91861,16 +92802,16 @@ async function run35(args) {
91861
92802
  current: { type: "boolean" },
91862
92803
  comments: { type: "boolean" },
91863
92804
  help: { type: "boolean", short: "h" }
91864
- }, HELP31);
92805
+ }, HELP34);
91865
92806
  if (typeof parsed === "number")
91866
92807
  return parsed;
91867
92808
  if (parsed.values.help) {
91868
- await writeStdout(HELP31);
92809
+ await writeStdout(HELP34);
91869
92810
  return EXIT2.OK;
91870
92811
  }
91871
92812
  const path2 = parsed.positionals[0];
91872
92813
  if (!path2)
91873
- return fail("USAGE", "Missing FILE argument", HELP31);
92814
+ return fail("USAGE", "Missing FILE argument", HELP34);
91874
92815
  const ast = Boolean(parsed.values.ast);
91875
92816
  const from = parsed.values.from;
91876
92817
  const to = parsed.values.to;
@@ -91879,11 +92820,11 @@ async function run35(args) {
91879
92820
  const current = Boolean(parsed.values.current);
91880
92821
  const showComments = Boolean(parsed.values.comments);
91881
92822
  if (ast && (from || to || accepted || baseline || current || showComments)) {
91882
- return fail("USAGE", "--from, --to, --accepted, --baseline, --current, and --comments are Markdown-only and cannot be combined with --ast", HELP31);
92823
+ return fail("USAGE", "--from, --to, --accepted, --baseline, --current, and --comments are Markdown-only and cannot be combined with --ast", HELP34);
91883
92824
  }
91884
92825
  const view = resolveView({ accepted, baseline, current });
91885
92826
  if (!view) {
91886
- return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive", HELP31);
92827
+ return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive", HELP34);
91887
92828
  }
91888
92829
  const docView = await openOrFail(path2);
91889
92830
  if (typeof docView === "number")
@@ -91894,7 +92835,7 @@ async function run35(args) {
91894
92835
  return EXIT2.OK;
91895
92836
  }
91896
92837
  try {
91897
- const rendered = renderMarkdown(docView.body, {
92838
+ const rendered = renderMarkdown2(docView.body, {
91898
92839
  from,
91899
92840
  to,
91900
92841
  view,
@@ -91912,7 +92853,7 @@ async function run35(args) {
91912
92853
  throw err;
91913
92854
  }
91914
92855
  }
91915
- var HELP31 = `docx read \u2014 render document body as Markdown, or print AST as JSON
92856
+ var HELP34 = `docx read \u2014 render document body as Markdown, or print AST as JSON
91916
92857
 
91917
92858
  Usage:
91918
92859
  docx read FILE [options]
@@ -92002,20 +92943,20 @@ function parsePagesSpec(spec) {
92002
92943
  // src/cli/render/index.ts
92003
92944
  var exports_render = {};
92004
92945
  __export(exports_render, {
92005
- run: () => run36
92946
+ run: () => run39
92006
92947
  });
92007
92948
  import { basename as basename2, extname as extname2, resolve as resolve2 } from "path";
92008
- async function run36(args) {
92009
- const parsed = await tryParseArgs(args, OPTION_SPEC6, HELP32);
92949
+ async function run39(args) {
92950
+ const parsed = await tryParseArgs(args, OPTION_SPEC6, HELP35);
92010
92951
  if (typeof parsed === "number")
92011
92952
  return parsed;
92012
92953
  if (parsed.values.help) {
92013
- await writeStdout(HELP32);
92954
+ await writeStdout(HELP35);
92014
92955
  return EXIT2.OK;
92015
92956
  }
92016
92957
  const filePath = parsed.positionals[0];
92017
92958
  if (!filePath)
92018
- return fail("USAGE", "Missing FILE argument", HELP32);
92959
+ return fail("USAGE", "Missing FILE argument", HELP35);
92019
92960
  if (!await Bun.file(filePath).exists()) {
92020
92961
  return fail("FILE_NOT_FOUND", `File not found: ${filePath}`);
92021
92962
  }
@@ -92095,7 +93036,7 @@ function availabilityHint(installed) {
92095
93036
  }
92096
93037
  return `Detected engines: ${installed.join(", ")} \u2014 but none chose auto-select; pass --engine explicitly.`;
92097
93038
  }
92098
- var HELP32 = `docx render \u2014 render each page of a .docx as a PNG/JPG image
93039
+ var HELP35 = `docx render \u2014 render each page of a .docx as a PNG/JPG image
92099
93040
 
92100
93041
  Usage:
92101
93042
  docx render FILE [options]
@@ -92384,9 +93325,9 @@ var init_batch4 = __esm(() => {
92384
93325
  // src/cli/replace/index.ts
92385
93326
  var exports_replace3 = {};
92386
93327
  __export(exports_replace3, {
92387
- run: () => run37
93328
+ run: () => run40
92388
93329
  });
92389
- async function run37(args) {
93330
+ async function run40(args) {
92390
93331
  const parsed = await tryParseArgs(args, {
92391
93332
  batch: { type: "string" },
92392
93333
  at: { type: "string" },
@@ -92400,33 +93341,33 @@ async function run37(args) {
92400
93341
  baseline: { type: "boolean" },
92401
93342
  exact: { type: "boolean" },
92402
93343
  ...SAVE_FLAGS
92403
- }, HELP33);
93344
+ }, HELP36);
92404
93345
  if (typeof parsed === "number")
92405
93346
  return parsed;
92406
93347
  if (parsed.values.help) {
92407
- await writeStdout(HELP33);
93348
+ await writeStdout(HELP36);
92408
93349
  return EXIT2.OK;
92409
93350
  }
92410
93351
  setVerboseAck(Boolean(parsed.values.verbose));
92411
93352
  const path2 = parsed.positionals[0];
92412
93353
  if (!path2)
92413
- return fail("USAGE", "Missing FILE argument", HELP33);
93354
+ return fail("USAGE", "Missing FILE argument", HELP36);
92414
93355
  const batchInput = parsed.values.batch;
92415
93356
  if (batchInput !== undefined) {
92416
93357
  if (parsed.positionals.length > 1) {
92417
- return fail("USAGE", "--batch reads pattern/replacement from the JSONL file; don't also pass them as positionals", HELP33);
93358
+ return fail("USAGE", "--batch reads pattern/replacement from the JSONL file; don't also pass them as positionals", HELP36);
92418
93359
  }
92419
93360
  if (parsed.values.at !== undefined) {
92420
- return fail("USAGE", '--at is per-entry in batch mode: put "at" on each JSONL line, not on the command', HELP33);
93361
+ return fail("USAGE", '--at is per-entry in batch mode: put "at" on each JSONL line, not on the command', HELP36);
92421
93362
  }
92422
93363
  return runReplaceBatch(path2, batchInput, parsed.values);
92423
93364
  }
92424
93365
  const pattern = parsed.positionals[1];
92425
93366
  const replacement = parsed.positionals[2];
92426
93367
  if (pattern == null)
92427
- return fail("USAGE", "Missing PATTERN argument", HELP33);
93368
+ return fail("USAGE", "Missing PATTERN argument", HELP36);
92428
93369
  if (replacement == null) {
92429
- return fail("USAGE", "Missing REPLACEMENT argument", HELP33);
93370
+ return fail("USAGE", "Missing REPLACEMENT argument", HELP36);
92430
93371
  }
92431
93372
  const ignoreCase = Boolean(parsed.values["ignore-case"]);
92432
93373
  const useRegex = Boolean(parsed.values.regex);
@@ -92563,7 +93504,7 @@ async function run37(args) {
92563
93504
  }, partialHint);
92564
93505
  return EXIT2.OK;
92565
93506
  }
92566
- var HELP33 = `docx replace \u2014 substitute text spans (sed for docx)
93507
+ var HELP36 = `docx replace \u2014 substitute text spans (sed for docx)
92567
93508
 
92568
93509
  Usage:
92569
93510
  docx replace FILE PATTERN REPLACEMENT [options]
@@ -92657,23 +93598,23 @@ var init_replace4 = __esm(() => {
92657
93598
  // src/cli/sections/index.tsx
92658
93599
  var exports_sections = {};
92659
93600
  __export(exports_sections, {
92660
- run: () => run38
93601
+ run: () => run41
92661
93602
  });
92662
93603
  function hasPageGeometry(flags) {
92663
93604
  return flags.pageSize !== undefined || flags.orientation !== undefined || flags.margins !== undefined;
92664
93605
  }
92665
- async function run38(args) {
92666
- const parsed = await tryParseArgs(args, OPTION_SPEC7, HELP34);
93606
+ async function run41(args) {
93607
+ const parsed = await tryParseArgs(args, OPTION_SPEC7, HELP37);
92667
93608
  if (typeof parsed === "number")
92668
93609
  return parsed;
92669
93610
  if (parsed.values.help) {
92670
- await writeStdout(HELP34);
93611
+ await writeStdout(HELP37);
92671
93612
  return EXIT2.OK;
92672
93613
  }
92673
93614
  setVerboseAck(Boolean(parsed.values.verbose));
92674
93615
  const filePath = parsed.positionals[0];
92675
93616
  if (!filePath)
92676
- return fail("USAGE", "Missing FILE argument", HELP34);
93617
+ return fail("USAGE", "Missing FILE argument", HELP37);
92677
93618
  const at = parsed.values.at;
92678
93619
  const flags = await parseSectionFlags(parsed.values);
92679
93620
  if (typeof flags === "number")
@@ -92693,22 +93634,22 @@ async function run38(args) {
92693
93634
  if (hasPageGeometry(flags) && flags.columns === undefined && flags.sectionType === undefined) {
92694
93635
  return editAllSections(document4, opts);
92695
93636
  }
92696
- return fail("USAGE", "Missing --at LOCATOR (a section sN, or a range pN-pM to wrap in columns). To set PAGE GEOMETRY for the whole document, omit --at and pass only --margins/--orientation/--size.", HELP34);
93637
+ return fail("USAGE", "Missing --at LOCATOR (a section sN, or a range pN-pM to wrap in columns). To set PAGE GEOMETRY for the whole document, omit --at and pass only --margins/--orientation/--size.", HELP37);
92697
93638
  }
92698
93639
  let locator;
92699
93640
  try {
92700
93641
  locator = parseLocator(at);
92701
93642
  } catch (error) {
92702
93643
  if (error instanceof LocatorParseError) {
92703
- return fail("INVALID_LOCATOR", error.message, HELP34);
93644
+ return fail("INVALID_LOCATOR", error.message, HELP37);
92704
93645
  }
92705
93646
  throw error;
92706
93647
  }
92707
93648
  if (locator.kind === "blockRange") {
92708
93649
  if (hasPageGeometry(flags))
92709
- return fail("USAGE", WRAP_REJECTS_GEOMETRY, HELP34);
93650
+ return fail("USAGE", WRAP_REJECTS_GEOMETRY, HELP37);
92710
93651
  if (flags.columns === undefined) {
92711
- return fail("USAGE", "Wrapping a range in a section needs --columns N", HELP34);
93652
+ return fail("USAGE", "Wrapping a range in a section needs --columns N", HELP37);
92712
93653
  }
92713
93654
  const range = await resolveBlockRangeOrFail(document4, at);
92714
93655
  if (typeof range === "number")
@@ -92720,20 +93661,20 @@ async function run38(args) {
92720
93661
  return blockRef;
92721
93662
  if (blockRef.node.tag === "w:sectPr") {
92722
93663
  if (flags.columns === undefined && flags.sectionType === undefined && !hasPageGeometry(flags)) {
92723
- return fail("USAGE", "Section edit needs --columns, --type, --orientation, --size, or --margins", HELP34);
93664
+ return fail("USAGE", "Section edit needs --columns, --type, --orientation, --size, or --margins", HELP37);
92724
93665
  }
92725
93666
  return editSection(document4, blockRef, at, opts);
92726
93667
  }
92727
93668
  if (blockRef.node.tag === "w:p") {
92728
93669
  if (hasPageGeometry(flags))
92729
- return fail("USAGE", WRAP_REJECTS_GEOMETRY, HELP34);
93670
+ return fail("USAGE", WRAP_REJECTS_GEOMETRY, HELP37);
92730
93671
  if (flags.columns === undefined) {
92731
- return fail("USAGE", "Wrapping a paragraph in a section needs --columns N", HELP34);
93672
+ return fail("USAGE", "Wrapping a paragraph in a section needs --columns N", HELP37);
92732
93673
  }
92733
93674
  const index2 = blockRef.parent.indexOf(blockRef.node);
92734
93675
  return wrapRange(document4, blockRef.parent, index2, index2, at, opts);
92735
93676
  }
92736
- return fail("INVALID_LOCATOR", `--at needs a section (sN) or a paragraph range (pN-pM); ${at} is neither`, HELP34);
93677
+ return fail("INVALID_LOCATOR", `--at needs a section (sN) or a paragraph range (pN-pM); ${at} is neither`, HELP37);
92737
93678
  }
92738
93679
  async function editSection(document4, blockRef, at, opts) {
92739
93680
  const track = resolveTracked(document4, opts.trackFlag);
@@ -92986,7 +93927,7 @@ async function commit(document4, opts, meta) {
92986
93927
  }, realignedNote + renderVerifyHint(destination));
92987
93928
  return EXIT2.OK;
92988
93929
  }
92989
- var HELP34 = `docx sections \u2014 multi-column layout, section breaks & page setup
93930
+ var HELP37 = `docx sections \u2014 multi-column layout, section breaks & page setup
92990
93931
 
92991
93932
  Usage:
92992
93933
  docx sections FILE --at LOCATOR (--columns N | page setup) [options]
@@ -93479,9 +94420,9 @@ function appliedStyleIds(document4) {
93479
94420
  continue;
93480
94421
  if (block.style)
93481
94422
  used.add(block.style);
93482
- for (const run39 of block.runs) {
93483
- if (run39.type === "text" && run39.runStyle)
93484
- used.add(run39.runStyle);
94423
+ for (const run42 of block.runs) {
94424
+ if (run42.type === "text" && run42.runStyle)
94425
+ used.add(run42.runStyle);
93485
94426
  }
93486
94427
  }
93487
94428
  return used;
@@ -93637,8 +94578,8 @@ function countStyleUsage(document4, styleId) {
93637
94578
  continue;
93638
94579
  if (block.style === styleId)
93639
94580
  count++;
93640
- for (const run39 of block.runs) {
93641
- if (run39.type === "text" && run39.runStyle === styleId)
94581
+ for (const run42 of block.runs) {
94582
+ if (run42.type === "text" && run42.runStyle === styleId)
93642
94583
  count++;
93643
94584
  }
93644
94585
  }
@@ -93690,7 +94631,7 @@ Examples:
93690
94631
  docx styles set report.docx --at Normal --font "Times New Roman" --size 12
93691
94632
  docx styles set report.docx --at Quote --italic --indent-left 0.5 --space-after 6
93692
94633
  `;
93693
- var init_set2 = __esm(() => {
94634
+ var init_set3 = __esm(() => {
93694
94635
  init_core2();
93695
94636
  init_respond();
93696
94637
  init_shared2();
@@ -93804,18 +94745,18 @@ var init_set_default_font = __esm(() => {
93804
94745
  // src/cli/styles/index.ts
93805
94746
  var exports_styles = {};
93806
94747
  __export(exports_styles, {
93807
- run: () => run39
94748
+ run: () => run42
93808
94749
  });
93809
- async function run39(args) {
94750
+ async function run42(args) {
93810
94751
  if (args[0] === "set-default-font")
93811
94752
  return runSetDefaultFont(args.slice(1));
93812
94753
  if (args[0] === "set")
93813
94754
  return runStylesSet(args.slice(1));
93814
94755
  if (args[0] === "create")
93815
94756
  return runStylesCreate(args.slice(1));
93816
- return runStylesRead(args, HELP35);
94757
+ return runStylesRead(args, HELP38);
93817
94758
  }
93818
- var HELP35 = `docx styles \u2014 inspect, edit, and create the styles a document can apply
94759
+ var HELP38 = `docx styles \u2014 inspect, edit, and create the styles a document can apply
93819
94760
 
93820
94761
  Usage:
93821
94762
  docx styles FILE [--used] [--at STYLEID] [--json] # list / describe (read)
@@ -93858,16 +94799,16 @@ See \`docx styles set --help\`, \`docx styles create --help\`, and
93858
94799
  var init_styles2 = __esm(() => {
93859
94800
  init_create3();
93860
94801
  init_read4();
93861
- init_set2();
94802
+ init_set3();
93862
94803
  init_set_default_font();
93863
94804
  });
93864
94805
 
93865
94806
  // src/cli/tables/insert-row.tsx
93866
94807
  var exports_insert_row = {};
93867
94808
  __export(exports_insert_row, {
93868
- run: () => run40
94809
+ run: () => run43
93869
94810
  });
93870
- async function run40(args) {
94811
+ async function run43(args) {
93871
94812
  const parsed = await tryParseArgs(args, {
93872
94813
  at: { type: "string" },
93873
94814
  position: { type: "string" },
@@ -93875,20 +94816,20 @@ async function run40(args) {
93875
94816
  author: { type: "string" },
93876
94817
  track: { type: "boolean" },
93877
94818
  ...SAVE_FLAGS
93878
- }, HELP36);
94819
+ }, HELP39);
93879
94820
  if (typeof parsed === "number")
93880
94821
  return parsed;
93881
94822
  if (parsed.values.help) {
93882
- await writeStdout(HELP36);
94823
+ await writeStdout(HELP39);
93883
94824
  return EXIT2.OK;
93884
94825
  }
93885
94826
  setVerboseAck(Boolean(parsed.values.verbose));
93886
94827
  const path2 = parsed.positionals[0];
93887
94828
  if (!path2)
93888
- return fail("USAGE", "Missing FILE argument", HELP36);
94829
+ return fail("USAGE", "Missing FILE argument", HELP39);
93889
94830
  const at = parsed.values.at;
93890
94831
  if (!at)
93891
- return fail("USAGE", "Missing --at tN", HELP36);
94832
+ return fail("USAGE", "Missing --at tN", HELP39);
93892
94833
  const tableId = parseTableAt(at);
93893
94834
  if (!tableId) {
93894
94835
  return fail("INVALID_LOCATOR", `--at must be a table id like t0 (got ${at})`);
@@ -93909,7 +94850,7 @@ async function run40(args) {
93909
94850
  }
93910
94851
  const cellTexts = parsed.values.cells ? parsed.values.cells.split(",") : [];
93911
94852
  for (const cell of cellTexts) {
93912
- const mangled = await rejectShellMangledValue(cell, HELP36, "--cells");
94853
+ const mangled = await rejectShellMangledValue(cell, HELP39, "--cells");
93913
94854
  if (typeof mangled === "number")
93914
94855
  return mangled;
93915
94856
  }
@@ -94010,7 +94951,7 @@ function rowChildIndex(table, grid, position2) {
94010
94951
  const lastRow = grid.rows[grid.rows.length - 1]?.node;
94011
94952
  return lastRow ? table.children.indexOf(lastRow) + 1 : table.children.length;
94012
94953
  }
94013
- var AT_FORMS6, HELP36;
94954
+ var AT_FORMS6, HELP39;
94014
94955
  var init_insert_row = __esm(() => {
94015
94956
  init_core2();
94016
94957
  init_blocks();
@@ -94021,7 +94962,7 @@ var init_insert_row = __esm(() => {
94021
94962
  init_respond();
94022
94963
  init_jsx_dev_runtime();
94023
94964
  AT_FORMS6 = describeForms(["table"], " ");
94024
- HELP36 = `docx tables insert-row \u2014 insert a table row
94965
+ HELP39 = `docx tables insert-row \u2014 insert a table row
94025
94966
 
94026
94967
  Usage:
94027
94968
  docx tables insert-row FILE --at tN [options]
@@ -94070,28 +95011,28 @@ Examples:
94070
95011
  // src/cli/tables/delete-row.ts
94071
95012
  var exports_delete_row = {};
94072
95013
  __export(exports_delete_row, {
94073
- run: () => run41
95014
+ run: () => run44
94074
95015
  });
94075
- async function run41(args) {
95016
+ async function run44(args) {
94076
95017
  const parsed = await tryParseArgs(args, {
94077
95018
  at: { type: "string" },
94078
95019
  author: { type: "string" },
94079
95020
  track: { type: "boolean" },
94080
95021
  ...SAVE_FLAGS
94081
- }, HELP37);
95022
+ }, HELP40);
94082
95023
  if (typeof parsed === "number")
94083
95024
  return parsed;
94084
95025
  if (parsed.values.help) {
94085
- await writeStdout(HELP37);
95026
+ await writeStdout(HELP40);
94086
95027
  return EXIT2.OK;
94087
95028
  }
94088
95029
  setVerboseAck(Boolean(parsed.values.verbose));
94089
95030
  const path2 = parsed.positionals[0];
94090
95031
  if (!path2)
94091
- return fail("USAGE", "Missing FILE argument", HELP37);
95032
+ return fail("USAGE", "Missing FILE argument", HELP40);
94092
95033
  const at = parsed.values.at;
94093
95034
  if (!at)
94094
- return fail("USAGE", "Missing --at tN:rR", HELP37);
95035
+ return fail("USAGE", "Missing --at tN:rR", HELP40);
94095
95036
  const target = parseRowAt(at);
94096
95037
  if (!target) {
94097
95038
  return fail("INVALID_LOCATOR", `--at must be a row locator like t0:r1 (got ${at})`);
@@ -94158,14 +95099,14 @@ function findVMergeOrphan(grid, rowIndex) {
94158
95099
  }
94159
95100
  return null;
94160
95101
  }
94161
- var AT_FORMS7, HELP37;
95102
+ var AT_FORMS7, HELP40;
94162
95103
  var init_delete_row = __esm(() => {
94163
95104
  init_core2();
94164
95105
  init_locators();
94165
95106
  init_table();
94166
95107
  init_respond();
94167
95108
  AT_FORMS7 = describeForms(["tableRow"], " ");
94168
- HELP37 = `docx tables delete-row \u2014 delete a table row
95109
+ HELP40 = `docx tables delete-row \u2014 delete a table row
94169
95110
 
94170
95111
  Usage:
94171
95112
  docx tables delete-row FILE --at tN:rR [options]
@@ -94201,9 +95142,9 @@ Examples:
94201
95142
  // src/cli/tables/insert-column.tsx
94202
95143
  var exports_insert_column = {};
94203
95144
  __export(exports_insert_column, {
94204
- run: () => run42
95145
+ run: () => run45
94205
95146
  });
94206
- async function run42(args) {
95147
+ async function run45(args) {
94207
95148
  const parsed = await tryParseArgs(args, {
94208
95149
  at: { type: "string" },
94209
95150
  position: { type: "string" },
@@ -94211,20 +95152,20 @@ async function run42(args) {
94211
95152
  author: { type: "string" },
94212
95153
  track: { type: "boolean" },
94213
95154
  ...SAVE_FLAGS
94214
- }, HELP38);
95155
+ }, HELP41);
94215
95156
  if (typeof parsed === "number")
94216
95157
  return parsed;
94217
95158
  if (parsed.values.help) {
94218
- await writeStdout(HELP38);
95159
+ await writeStdout(HELP41);
94219
95160
  return EXIT2.OK;
94220
95161
  }
94221
95162
  setVerboseAck(Boolean(parsed.values.verbose));
94222
95163
  const path2 = parsed.positionals[0];
94223
95164
  if (!path2)
94224
- return fail("USAGE", "Missing FILE argument", HELP38);
95165
+ return fail("USAGE", "Missing FILE argument", HELP41);
94225
95166
  const at = parsed.values.at;
94226
95167
  if (!at)
94227
- return fail("USAGE", "Missing --at tN", HELP38);
95168
+ return fail("USAGE", "Missing --at tN", HELP41);
94228
95169
  const tableId = parseTableAt(at);
94229
95170
  if (!tableId) {
94230
95171
  return fail("INVALID_LOCATOR", `--at must be a table id like t0 (got ${at})`);
@@ -94339,14 +95280,14 @@ function insertCellAtColumn(row, position2, cell) {
94339
95280
  const at = lastCell ? row.node.children.indexOf(lastCell.node) + 1 : row.node.children.length;
94340
95281
  row.node.children.splice(at, 0, cell);
94341
95282
  }
94342
- var AT_FORMS8, HELP38;
95283
+ var AT_FORMS8, HELP41;
94343
95284
  var init_insert_column = __esm(() => {
94344
95285
  init_core2();
94345
95286
  init_locators();
94346
95287
  init_table();
94347
95288
  init_respond();
94348
95289
  AT_FORMS8 = describeForms(["table"], " ");
94349
- HELP38 = `docx tables insert-column \u2014 insert a table column
95290
+ HELP41 = `docx tables insert-column \u2014 insert a table column
94350
95291
 
94351
95292
  Usage:
94352
95293
  docx tables insert-column FILE --at tN [options]
@@ -94384,28 +95325,28 @@ Examples:
94384
95325
  // src/cli/tables/delete-column.ts
94385
95326
  var exports_delete_column = {};
94386
95327
  __export(exports_delete_column, {
94387
- run: () => run43
95328
+ run: () => run46
94388
95329
  });
94389
- async function run43(args) {
95330
+ async function run46(args) {
94390
95331
  const parsed = await tryParseArgs(args, {
94391
95332
  at: { type: "string" },
94392
95333
  author: { type: "string" },
94393
95334
  track: { type: "boolean" },
94394
95335
  ...SAVE_FLAGS
94395
- }, HELP39);
95336
+ }, HELP42);
94396
95337
  if (typeof parsed === "number")
94397
95338
  return parsed;
94398
95339
  if (parsed.values.help) {
94399
- await writeStdout(HELP39);
95340
+ await writeStdout(HELP42);
94400
95341
  return EXIT2.OK;
94401
95342
  }
94402
95343
  setVerboseAck(Boolean(parsed.values.verbose));
94403
95344
  const path2 = parsed.positionals[0];
94404
95345
  if (!path2)
94405
- return fail("USAGE", "Missing FILE argument", HELP39);
95346
+ return fail("USAGE", "Missing FILE argument", HELP42);
94406
95347
  const at = parsed.values.at;
94407
95348
  if (!at)
94408
- return fail("USAGE", "Missing --at tN:cC", HELP39);
95349
+ return fail("USAGE", "Missing --at tN:cC", HELP42);
94409
95350
  const target = parseColumnAt(at);
94410
95351
  if (!target) {
94411
95352
  return fail("INVALID_LOCATOR", `--at must be a column locator like t0:c2 (got ${at})`);
@@ -94489,14 +95430,14 @@ function removeGridColumn(tblGrid, col) {
94489
95430
  if (index2 !== -1)
94490
95431
  tblGrid.children.splice(index2, 1);
94491
95432
  }
94492
- var AT_FORMS9, HELP39;
95433
+ var AT_FORMS9, HELP42;
94493
95434
  var init_delete_column = __esm(() => {
94494
95435
  init_core2();
94495
95436
  init_locators();
94496
95437
  init_table();
94497
95438
  init_respond();
94498
95439
  AT_FORMS9 = describeForms(["tableColumn"], " ");
94499
- HELP39 = `docx tables delete-column \u2014 delete a table column
95440
+ HELP42 = `docx tables delete-column \u2014 delete a table column
94500
95441
 
94501
95442
  Usage:
94502
95443
  docx tables delete-column FILE --at tN:cC [options]
@@ -94531,36 +95472,36 @@ Examples:
94531
95472
  // src/cli/tables/set-widths.ts
94532
95473
  var exports_set_widths = {};
94533
95474
  __export(exports_set_widths, {
94534
- run: () => run44
95475
+ run: () => run47
94535
95476
  });
94536
- async function run44(args) {
95477
+ async function run47(args) {
94537
95478
  const parsed = await tryParseArgs(args, {
94538
95479
  at: { type: "string" },
94539
95480
  widths: { type: "string" },
94540
95481
  author: { type: "string" },
94541
95482
  track: { type: "boolean" },
94542
95483
  ...SAVE_FLAGS
94543
- }, HELP40);
95484
+ }, HELP43);
94544
95485
  if (typeof parsed === "number")
94545
95486
  return parsed;
94546
95487
  if (parsed.values.help) {
94547
- await writeStdout(HELP40);
95488
+ await writeStdout(HELP43);
94548
95489
  return EXIT2.OK;
94549
95490
  }
94550
95491
  setVerboseAck(Boolean(parsed.values.verbose));
94551
95492
  const path2 = parsed.positionals[0];
94552
95493
  if (!path2)
94553
- return fail("USAGE", "Missing FILE argument", HELP40);
95494
+ return fail("USAGE", "Missing FILE argument", HELP43);
94554
95495
  const at = parsed.values.at;
94555
95496
  if (!at)
94556
- return fail("USAGE", "Missing --at tN", HELP40);
95497
+ return fail("USAGE", "Missing --at tN", HELP43);
94557
95498
  const tableId = parseTableAt(at);
94558
95499
  if (!tableId) {
94559
95500
  return fail("INVALID_LOCATOR", `--at must be a table id like t0 (got ${at})`);
94560
95501
  }
94561
95502
  const widthsSpec = parsed.values.widths;
94562
95503
  if (!widthsSpec)
94563
- return fail("USAGE", "Missing --widths", HELP40);
95504
+ return fail("USAGE", "Missing --widths", HELP43);
94564
95505
  const document4 = await openOrFail(path2);
94565
95506
  if (typeof document4 === "number")
94566
95507
  return document4;
@@ -94709,14 +95650,14 @@ function describeColumnWidths(twips) {
94709
95650
  const cells = twips.map((value, index2) => `g${index2}=${twipsToInches(value)}in`);
94710
95651
  return `widths: ${cells.join(" ")}`;
94711
95652
  }
94712
- var AT_FORMS10, HELP40, MIN_COL_TWIPS = 288;
95653
+ var AT_FORMS10, HELP43, MIN_COL_TWIPS = 288;
94713
95654
  var init_set_widths = __esm(() => {
94714
95655
  init_core2();
94715
95656
  init_locators();
94716
95657
  init_table();
94717
95658
  init_respond();
94718
95659
  AT_FORMS10 = describeForms(["table"], " ");
94719
- HELP40 = `docx tables set-widths \u2014 set column widths
95660
+ HELP43 = `docx tables set-widths \u2014 set column widths
94720
95661
 
94721
95662
  Usage:
94722
95663
  docx tables set-widths FILE --at tN --widths SPEC [options]
@@ -94785,28 +95726,28 @@ var init_common2 = __esm(() => {
94785
95726
  // src/cli/tables/merge.tsx
94786
95727
  var exports_merge = {};
94787
95728
  __export(exports_merge, {
94788
- run: () => run45
95729
+ run: () => run48
94789
95730
  });
94790
- async function run45(args) {
95731
+ async function run48(args) {
94791
95732
  const parsed = await tryParseArgs(args, {
94792
95733
  at: { type: "string" },
94793
95734
  author: { type: "string" },
94794
95735
  track: { type: "boolean" },
94795
95736
  ...SAVE_FLAGS
94796
- }, HELP41);
95737
+ }, HELP44);
94797
95738
  if (typeof parsed === "number")
94798
95739
  return parsed;
94799
95740
  if (parsed.values.help) {
94800
- await writeStdout(HELP41);
95741
+ await writeStdout(HELP44);
94801
95742
  return EXIT2.OK;
94802
95743
  }
94803
95744
  setVerboseAck(Boolean(parsed.values.verbose));
94804
95745
  const path2 = parsed.positionals[0];
94805
95746
  if (!path2)
94806
- return fail("USAGE", "Missing FILE argument", HELP41);
95747
+ return fail("USAGE", "Missing FILE argument", HELP44);
94807
95748
  const at = parsed.values.at;
94808
95749
  if (!at)
94809
- return fail("USAGE", "Missing --at tN:rR1cC1-rR2cC2", HELP41);
95750
+ return fail("USAGE", "Missing --at tN:rR1cC1-rR2cC2", HELP44);
94810
95751
  const region = parseCellRangeAt(at);
94811
95752
  if (!region) {
94812
95753
  return fail("INVALID_LOCATOR", `--at must be a cell-range locator like t0:r0c0-r1c1 (got ${at})`);
@@ -94899,7 +95840,7 @@ function mergeRow(row, c1, c2, width, isTop, vertical) {
94899
95840
  if (vertical && !isTop)
94900
95841
  clearCellContent(anchor.node);
94901
95842
  }
94902
- var AT_FORMS11, HELP41;
95843
+ var AT_FORMS11, HELP44;
94903
95844
  var init_merge = __esm(() => {
94904
95845
  init_core2();
94905
95846
  init_locators();
@@ -94907,7 +95848,7 @@ var init_merge = __esm(() => {
94907
95848
  init_respond();
94908
95849
  init_common2();
94909
95850
  AT_FORMS11 = describeForms(["cellRange"], " ");
94910
- HELP41 = `docx tables merge \u2014 merge a rectangular cell region
95851
+ HELP44 = `docx tables merge \u2014 merge a rectangular cell region
94911
95852
 
94912
95853
  Usage:
94913
95854
  docx tables merge FILE --at tN:rR1cC1-rR2cC2 [options]
@@ -94946,28 +95887,28 @@ Examples:
94946
95887
  // src/cli/tables/unmerge.tsx
94947
95888
  var exports_unmerge = {};
94948
95889
  __export(exports_unmerge, {
94949
- run: () => run46
95890
+ run: () => run49
94950
95891
  });
94951
- async function run46(args) {
95892
+ async function run49(args) {
94952
95893
  const parsed = await tryParseArgs(args, {
94953
95894
  at: { type: "string" },
94954
95895
  author: { type: "string" },
94955
95896
  track: { type: "boolean" },
94956
95897
  ...SAVE_FLAGS
94957
- }, HELP42);
95898
+ }, HELP45);
94958
95899
  if (typeof parsed === "number")
94959
95900
  return parsed;
94960
95901
  if (parsed.values.help) {
94961
- await writeStdout(HELP42);
95902
+ await writeStdout(HELP45);
94962
95903
  return EXIT2.OK;
94963
95904
  }
94964
95905
  setVerboseAck(Boolean(parsed.values.verbose));
94965
95906
  const path2 = parsed.positionals[0];
94966
95907
  if (!path2)
94967
- return fail("USAGE", "Missing FILE argument", HELP42);
95908
+ return fail("USAGE", "Missing FILE argument", HELP45);
94968
95909
  const at = parsed.values.at;
94969
95910
  if (!at)
94970
- return fail("USAGE", "Missing --at tN:rRcC", HELP42);
95911
+ return fail("USAGE", "Missing --at tN:rRcC", HELP45);
94971
95912
  const target = parseCellAt(at);
94972
95913
  if (!target) {
94973
95914
  return fail("INVALID_LOCATOR", `--at must be a cell locator like t0:r0c0 (got ${at})`);
@@ -95042,7 +95983,7 @@ function verticalSpanRows(grid, row, col, vertical) {
95042
95983
  }
95043
95984
  return rows;
95044
95985
  }
95045
- var AT_FORMS12, HELP42;
95986
+ var AT_FORMS12, HELP45;
95046
95987
  var init_unmerge = __esm(() => {
95047
95988
  init_core2();
95048
95989
  init_locators();
@@ -95050,7 +95991,7 @@ var init_unmerge = __esm(() => {
95050
95991
  init_respond();
95051
95992
  init_common2();
95052
95993
  AT_FORMS12 = describeForms(["cell"], " ");
95053
- HELP42 = `docx tables unmerge \u2014 split a merged cell back into individual cells
95994
+ HELP45 = `docx tables unmerge \u2014 split a merged cell back into individual cells
95054
95995
 
95055
95996
  Usage:
95056
95997
  docx tables unmerge FILE --at tN:rRcC [options]
@@ -95087,9 +96028,9 @@ Examples:
95087
96028
  // src/cli/tables/borders.tsx
95088
96029
  var exports_borders = {};
95089
96030
  __export(exports_borders, {
95090
- run: () => run47
96031
+ run: () => run50
95091
96032
  });
95092
- async function run47(args) {
96033
+ async function run50(args) {
95093
96034
  const parsed = await tryParseArgs(args, {
95094
96035
  at: { type: "string" },
95095
96036
  style: { type: "string" },
@@ -95098,20 +96039,20 @@ async function run47(args) {
95098
96039
  author: { type: "string" },
95099
96040
  track: { type: "boolean" },
95100
96041
  ...SAVE_FLAGS
95101
- }, HELP43);
96042
+ }, HELP46);
95102
96043
  if (typeof parsed === "number")
95103
96044
  return parsed;
95104
96045
  if (parsed.values.help) {
95105
- await writeStdout(HELP43);
96046
+ await writeStdout(HELP46);
95106
96047
  return EXIT2.OK;
95107
96048
  }
95108
96049
  setVerboseAck(Boolean(parsed.values.verbose));
95109
96050
  const path2 = parsed.positionals[0];
95110
96051
  if (!path2)
95111
- return fail("USAGE", "Missing FILE argument", HELP43);
96052
+ return fail("USAGE", "Missing FILE argument", HELP46);
95112
96053
  const at = parsed.values.at;
95113
96054
  if (!at)
95114
- return fail("USAGE", "Missing --at tN", HELP43);
96055
+ return fail("USAGE", "Missing --at tN", HELP46);
95115
96056
  const tableId = parseTableAt(at);
95116
96057
  if (!tableId) {
95117
96058
  return fail("INVALID_LOCATOR", `--at must be a table id like t0 (got ${at})`);
@@ -95188,7 +96129,7 @@ function buildBorders(style, sizeEighths, color2) {
95188
96129
  ]
95189
96130
  }, undefined, true, undefined, this);
95190
96131
  }
95191
- var STYLES, AT_FORMS13, HELP43;
96132
+ var STYLES, AT_FORMS13, HELP46;
95192
96133
  var init_borders = __esm(() => {
95193
96134
  init_core2();
95194
96135
  init_jsx();
@@ -95199,7 +96140,7 @@ var init_borders = __esm(() => {
95199
96140
  init_jsx_dev_runtime();
95200
96141
  STYLES = new Set(["single", "double", "none"]);
95201
96142
  AT_FORMS13 = describeForms(["table"], " ");
95202
- HELP43 = `docx tables borders \u2014 set table borders
96143
+ HELP46 = `docx tables borders \u2014 set table borders
95203
96144
 
95204
96145
  Usage:
95205
96146
  docx tables borders FILE --at tN [options]
@@ -95236,25 +96177,486 @@ Examples:
95236
96177
  `;
95237
96178
  });
95238
96179
 
96180
+ // src/cli/tables/format.tsx
96181
+ var exports_format = {};
96182
+ __export(exports_format, {
96183
+ run: () => run51
96184
+ });
96185
+ async function run51(args) {
96186
+ const parsed = await tryParseArgs(args, {
96187
+ at: { type: "string" },
96188
+ shade: { type: "string" },
96189
+ valign: { type: "string" },
96190
+ halign: { type: "string" },
96191
+ "cell-borders": { type: "string" },
96192
+ "border-style": { type: "string" },
96193
+ "border-size": { type: "string" },
96194
+ "border-color": { type: "string" },
96195
+ align: { type: "string" },
96196
+ style: { type: "string" },
96197
+ "row-height": { type: "string" },
96198
+ "height-rule": { type: "string" },
96199
+ "repeat-header": { type: "boolean" },
96200
+ "no-repeat-header": { type: "boolean" },
96201
+ author: { type: "string" },
96202
+ track: { type: "boolean" },
96203
+ ...SAVE_FLAGS
96204
+ }, HELP47);
96205
+ if (typeof parsed === "number")
96206
+ return parsed;
96207
+ if (parsed.values.help) {
96208
+ await writeStdout(HELP47);
96209
+ return EXIT2.OK;
96210
+ }
96211
+ setVerboseAck(Boolean(parsed.values.verbose));
96212
+ const path2 = parsed.positionals[0];
96213
+ if (!path2)
96214
+ return fail("USAGE", "Missing FILE argument", HELP47);
96215
+ const at = parsed.values.at;
96216
+ if (!at)
96217
+ return fail("USAGE", "Missing --at LOCATOR", HELP47);
96218
+ const scope = resolveScope(at);
96219
+ if (!scope) {
96220
+ return fail("INVALID_LOCATOR", `--at must address a table, row, column, cell, or cell range (got ${at})`, "e.g. t0 (table), t0:r0 (row), t0:c1 (column), t0:r0c0 (cell), t0:r0c0-r1c2 (range).");
96221
+ }
96222
+ const plan = buildPlan2(parsed.values);
96223
+ if (typeof plan === "string")
96224
+ return fail("USAGE", plan);
96225
+ if (planIsEmpty(plan)) {
96226
+ return fail("USAGE", "Nothing to format \u2014 pass at least one of --shade/--valign/--halign/--cell-borders/--align/--style/--row-height/--repeat-header");
96227
+ }
96228
+ const scopeError = validateScope(scope, plan);
96229
+ if (scopeError)
96230
+ return fail("USAGE", scopeError);
96231
+ const document4 = await openOrFail(path2);
96232
+ if (typeof document4 === "number")
96233
+ return document4;
96234
+ const tableNode = resolveTableNode(document4, scope.tableId);
96235
+ if (!tableNode)
96236
+ return fail("BLOCK_NOT_FOUND", `Table not found: ${scope.tableId}`);
96237
+ const grid = buildGrid(tableNode);
96238
+ const cells = selectCells(grid, scope);
96239
+ const rows = selectRows(grid, scope);
96240
+ const targetError = validateTargets(scope, plan, cells, rows);
96241
+ if (targetError)
96242
+ return fail("BLOCK_NOT_FOUND", targetError);
96243
+ const outputPath = parsed.values.output;
96244
+ if (parsed.values["dry-run"]) {
96245
+ await respond({
96246
+ operation: "tables.format",
96247
+ dryRun: true,
96248
+ path: path2,
96249
+ at,
96250
+ applied: appliedList2(plan),
96251
+ ...outputPath ? { output: outputPath } : {}
96252
+ });
96253
+ return EXIT2.OK;
96254
+ }
96255
+ const tracking = resolveTracked(document4, parsed.values.track);
96256
+ const author = parsed.values.author;
96257
+ applyCellProps(document4, cells, plan, tracking, author);
96258
+ if (plan.halign !== undefined)
96259
+ applyHalign(document4, cells, plan.halign, tracking, author);
96260
+ applyTableProps(tableNode, plan);
96261
+ applyRowProps(rows, plan);
96262
+ const untracked = untrackedSummary(plan);
96263
+ if (untracked)
96264
+ noteStructuralChange(document4, cells[0]?.node, untracked, author, parsed.values.track);
96265
+ await document4.save(outputPath);
96266
+ const destination = outputPath ?? path2;
96267
+ await respondAck({
96268
+ ok: true,
96269
+ operation: "tables.format",
96270
+ path: destination,
96271
+ table: at,
96272
+ applied: appliedList2(plan)
96273
+ }, renderVerifyHint(destination));
96274
+ return EXIT2.OK;
96275
+ }
96276
+ function resolveScope(at) {
96277
+ const cell = parseCellAt(at);
96278
+ if (cell)
96279
+ return { kind: "cell", ...cell };
96280
+ const range = parseCellRangeAt(at);
96281
+ if (range)
96282
+ return { kind: "range", ...range };
96283
+ const row = parseRowAt(at);
96284
+ if (row)
96285
+ return { kind: "row", ...row };
96286
+ const column = parseColumnAt(at);
96287
+ if (column)
96288
+ return { kind: "column", ...column };
96289
+ const tableId = parseTableAt(at);
96290
+ if (tableId)
96291
+ return { kind: "table", tableId };
96292
+ return null;
96293
+ }
96294
+ function buildPlan2(values2) {
96295
+ const plan = {};
96296
+ const shade = values2.shade;
96297
+ if (shade !== undefined) {
96298
+ if (isClear(shade))
96299
+ plan.shade = null;
96300
+ else {
96301
+ const hex = resolveColor(shade);
96302
+ if (!hex)
96303
+ return colorError("--shade", shade);
96304
+ plan.shade = hex;
96305
+ }
96306
+ }
96307
+ const valign = values2.valign;
96308
+ if (valign !== undefined) {
96309
+ if (!VALIGNS.has(valign))
96310
+ return "--valign must be top, center, or bottom";
96311
+ plan.valign = valign;
96312
+ }
96313
+ const halign = values2.halign;
96314
+ if (halign !== undefined) {
96315
+ if (!HALIGNS.has(halign))
96316
+ return "--halign must be left, center, right, or justify";
96317
+ plan.halign = halign;
96318
+ }
96319
+ const cellBorders = values2["cell-borders"];
96320
+ if (cellBorders !== undefined) {
96321
+ const built = buildCellBorders(values2, cellBorders);
96322
+ if (typeof built === "string")
96323
+ return built;
96324
+ plan.cellBorders = built;
96325
+ }
96326
+ const align = values2.align;
96327
+ if (align !== undefined) {
96328
+ if (!TABLE_ALIGNS.has(align))
96329
+ return "--align must be left, center, or right";
96330
+ plan.align = align;
96331
+ }
96332
+ const style = values2.style;
96333
+ if (style !== undefined)
96334
+ plan.style = isClear(style) ? null : style;
96335
+ const rowHeight = values2["row-height"];
96336
+ const heightRule = values2["height-rule"];
96337
+ if (heightRule !== undefined && !HEIGHT_RULES.has(heightRule))
96338
+ return "--height-rule must be atLeast, exact, or auto";
96339
+ if (heightRule !== undefined && rowHeight === undefined)
96340
+ return "--height-rule has no effect without --row-height";
96341
+ if (rowHeight !== undefined) {
96342
+ const twips = parseMeasureToTwips(rowHeight);
96343
+ if (twips === null)
96344
+ return `--row-height must be a positive measure WITH a unit, e.g. 0.4in or 28pt (got ${rowHeight})`;
96345
+ plan.rowHeight = {
96346
+ value: twips,
96347
+ rule: heightRule ?? "atLeast"
96348
+ };
96349
+ }
96350
+ if (values2["repeat-header"] && values2["no-repeat-header"])
96351
+ return "--repeat-header and --no-repeat-header are mutually exclusive";
96352
+ if (values2["repeat-header"])
96353
+ plan.repeatHeader = true;
96354
+ if (values2["no-repeat-header"])
96355
+ plan.repeatHeader = false;
96356
+ return plan;
96357
+ }
96358
+ function buildCellBorders(values2, sidesRaw) {
96359
+ if (isClear(sidesRaw))
96360
+ return { updates: [], clearAll: true };
96361
+ const style = values2["border-style"] ?? "single";
96362
+ if (!BORDER_STYLES.has(style))
96363
+ return "--border-style must be single, double, or none";
96364
+ const sizeRaw = values2["border-size"];
96365
+ if (sizeRaw !== undefined && (!Number.isInteger(Number(sizeRaw)) || Number(sizeRaw) <= 0))
96366
+ return "--border-size must be a positive integer (eighths of a point)";
96367
+ const sizeEighths = sizeRaw ? Number(sizeRaw) : 4;
96368
+ const colorRaw = values2["border-color"] ?? "auto";
96369
+ const color2 = colorRaw === "auto" ? "auto" : resolveColor(colorRaw);
96370
+ if (!color2)
96371
+ return colorError("--border-color", colorRaw);
96372
+ const edge = { style, sizeEighths, color: color2 };
96373
+ const sides = new Set;
96374
+ for (const token of sidesRaw.split(",").map((value) => value.trim())) {
96375
+ if (token === "all") {
96376
+ for (const side of ALL_SIDES)
96377
+ sides.add(side);
96378
+ continue;
96379
+ }
96380
+ if (!ALL_SIDES.includes(token))
96381
+ return `--cell-borders side "${token}" must be one of ${ALL_SIDES.join(", ")}, all, or none`;
96382
+ sides.add(token);
96383
+ }
96384
+ return {
96385
+ updates: [...sides].map((side) => ({ side, edge })),
96386
+ clearAll: false
96387
+ };
96388
+ }
96389
+ function selectCells(grid, scope) {
96390
+ if (scope.kind === "table")
96391
+ return grid.rows.flatMap((row) => row.cells);
96392
+ if (scope.kind === "row")
96393
+ return grid.rows[scope.row]?.cells ?? [];
96394
+ if (scope.kind === "cell") {
96395
+ const cell = cellAt(grid.rows[scope.row], scope.col);
96396
+ return cell ? [cell] : [];
96397
+ }
96398
+ if (scope.kind === "column") {
96399
+ const out2 = [];
96400
+ for (const row of grid.rows) {
96401
+ const cell = cellAt(row, scope.col);
96402
+ if (cell && !out2.includes(cell))
96403
+ out2.push(cell);
96404
+ }
96405
+ return out2;
96406
+ }
96407
+ const r1 = Math.min(scope.start.row, scope.end.row);
96408
+ const r2 = Math.max(scope.start.row, scope.end.row);
96409
+ const c1 = Math.min(scope.start.col, scope.end.col);
96410
+ const c2 = Math.max(scope.start.col, scope.end.col);
96411
+ const out = [];
96412
+ for (let row = r1;row <= r2; row++) {
96413
+ for (const cell of grid.rows[row]?.cells ?? []) {
96414
+ if (cell.colStart <= c2 && cell.colStart + cell.colSpan - 1 >= c1)
96415
+ out.push(cell);
96416
+ }
96417
+ }
96418
+ return out;
96419
+ }
96420
+ function selectRows(grid, scope) {
96421
+ if (scope.kind === "table")
96422
+ return grid.rows;
96423
+ if (scope.kind === "row") {
96424
+ const row = grid.rows[scope.row];
96425
+ return row ? [row] : [];
96426
+ }
96427
+ return [];
96428
+ }
96429
+ function applyCellProps(document4, cells, plan, tracking, author) {
96430
+ if (plan.shade === undefined && plan.valign === undefined && plan.cellBorders === undefined)
96431
+ return;
96432
+ for (const cell of cells) {
96433
+ const prior = tracking ? (cell.node.findChild("w:tcPr")?.children ?? []).map((child2) => child2.clone()) : [];
96434
+ if (plan.shade !== undefined)
96435
+ setCellShading(cell.node, plan.shade);
96436
+ if (plan.valign !== undefined)
96437
+ setCellVAlign(cell.node, plan.valign);
96438
+ if (plan.cellBorders !== undefined)
96439
+ setCellBorders(cell.node, plan.cellBorders.updates, plan.cellBorders.clearAll);
96440
+ if (tracking)
96441
+ appendTcPrChange(cell.node, prior, new TrackChanges(document4).mintMeta(author));
96442
+ }
96443
+ }
96444
+ function applyHalign(document4, cells, alignment, tracking, author) {
96445
+ const edit = new Edit(document4);
96446
+ for (const cell of cells) {
96447
+ for (const paragraph2 of cell.node.findChildren("w:p")) {
96448
+ edit.paragraphProperties({ node: paragraph2, parent: cell.node.children }, { alignment }, { authorFlag: author, track: tracking });
96449
+ }
96450
+ }
96451
+ }
96452
+ function applyTableProps(tableNode, plan) {
96453
+ if (plan.align !== undefined)
96454
+ setTableJustification(tableNode, plan.align);
96455
+ if (plan.style !== undefined)
96456
+ setTableStyle(tableNode, plan.style);
96457
+ }
96458
+ function applyRowProps(rows, plan) {
96459
+ if (plan.rowHeight === undefined && plan.repeatHeader === undefined)
96460
+ return;
96461
+ for (const row of rows) {
96462
+ if (plan.rowHeight !== undefined)
96463
+ setRowHeight(row.node, plan.rowHeight);
96464
+ if (plan.repeatHeader !== undefined)
96465
+ setRepeatHeader(row.node, plan.repeatHeader);
96466
+ }
96467
+ }
96468
+ function validateScope(scope, plan) {
96469
+ const hasTableFlag = plan.align !== undefined || plan.style !== undefined;
96470
+ if (hasTableFlag && scope.kind !== "table")
96471
+ return "--align/--style position or restyle the whole table \u2014 use --at tN";
96472
+ const hasRowFlag = plan.rowHeight !== undefined || plan.repeatHeader !== undefined;
96473
+ if (hasRowFlag && scope.kind !== "table" && scope.kind !== "row")
96474
+ return "--row-height/--repeat-header apply to a row \u2014 use --at tN:rR (or --at tN for every row)";
96475
+ return null;
96476
+ }
96477
+ function validateTargets(scope, plan, cells, rows) {
96478
+ const hasCellFlag = plan.shade !== undefined || plan.valign !== undefined || plan.halign !== undefined || plan.cellBorders !== undefined;
96479
+ if (hasCellFlag && cells.length === 0)
96480
+ return `No cells matched ${describeScope(scope)}`;
96481
+ const hasRowFlag = plan.rowHeight !== undefined || plan.repeatHeader !== undefined;
96482
+ if (hasRowFlag && rows.length === 0)
96483
+ return `No rows matched ${describeScope(scope)}`;
96484
+ return null;
96485
+ }
96486
+ function describeScope(scope) {
96487
+ if (scope.kind === "table")
96488
+ return scope.tableId;
96489
+ if (scope.kind === "row")
96490
+ return `${scope.tableId}:r${scope.row}`;
96491
+ if (scope.kind === "column")
96492
+ return `${scope.tableId}:c${scope.col}`;
96493
+ if (scope.kind === "cell")
96494
+ return `${scope.tableId}:r${scope.row}c${scope.col}`;
96495
+ return `${scope.tableId}:r${scope.start.row}c${scope.start.col}-r${scope.end.row}c${scope.end.col}`;
96496
+ }
96497
+ function appliedList2(plan) {
96498
+ const out = [];
96499
+ if (plan.shade !== undefined)
96500
+ out.push("shade");
96501
+ if (plan.valign !== undefined)
96502
+ out.push("valign");
96503
+ if (plan.halign !== undefined)
96504
+ out.push("halign");
96505
+ if (plan.cellBorders !== undefined)
96506
+ out.push("cell-borders");
96507
+ if (plan.align !== undefined)
96508
+ out.push("align");
96509
+ if (plan.style !== undefined)
96510
+ out.push("style");
96511
+ if (plan.rowHeight !== undefined)
96512
+ out.push("row-height");
96513
+ if (plan.repeatHeader !== undefined)
96514
+ out.push("repeat-header");
96515
+ return out;
96516
+ }
96517
+ function untrackedSummary(plan) {
96518
+ const parts = [];
96519
+ if (plan.align !== undefined)
96520
+ parts.push(`table align ${plan.align ?? "left"}`);
96521
+ if (plan.style !== undefined)
96522
+ parts.push(plan.style ? `table style ${plan.style}` : "table style cleared");
96523
+ if (plan.rowHeight !== undefined)
96524
+ parts.push("row height set");
96525
+ if (plan.repeatHeader !== undefined)
96526
+ parts.push(plan.repeatHeader ? "repeat-header on" : "repeat-header off");
96527
+ return parts.length > 0 ? `set ${parts.join("; ")}` : "";
96528
+ }
96529
+ function planIsEmpty(plan) {
96530
+ return appliedList2(plan).length === 0;
96531
+ }
96532
+ function isClear(value) {
96533
+ const lower = value.toLowerCase();
96534
+ return lower === "none" || lower === "auto";
96535
+ }
96536
+ function resolveColor(value) {
96537
+ const named = COLOR_NAMES[value.toLowerCase()];
96538
+ if (named)
96539
+ return named;
96540
+ const hex = normalizeHexColor(value).toUpperCase();
96541
+ return /^[0-9A-F]{6}$/.test(hex) ? hex : null;
96542
+ }
96543
+ function colorError(flag, value) {
96544
+ return `${flag} must be a 6-digit hex (e.g. D9D9D9) or a name (${Object.keys(COLOR_NAMES).slice(0, 6).join(", ")}, \u2026) \u2014 got ${value}`;
96545
+ }
96546
+ function parseMeasureToTwips(raw) {
96547
+ const match = raw.trim().match(/^(\d*\.?\d+)\s*(in|pt)$/i);
96548
+ if (!match)
96549
+ return null;
96550
+ const value = Number.parseFloat(match[1]);
96551
+ if (!Number.isFinite(value) || value <= 0)
96552
+ return null;
96553
+ const unit = match[2].toLowerCase();
96554
+ return Math.round(unit === "pt" ? value * 20 : value * 1440);
96555
+ }
96556
+ var HELP47 = `docx tables format \u2014 shade, align, border, and size table cells/rows/tables
96557
+
96558
+ Usage:
96559
+ docx tables format FILE --at LOCATOR [formatting options]
96560
+
96561
+ The --at locator picks WHAT to format; its granularity picks which options apply.
96562
+ --at t0 whole table
96563
+ --at t0:r2 a row --at t0:c1 a column
96564
+ --at t0:r1c2 a single cell --at t0:r1c0-r3c2 a rectangle of cells
96565
+
96566
+ Cell options (any locator \u2014 broadcast to every cell it covers):
96567
+ --shade HEX|NAME|none Cell background fill (e.g. D9D9D9, "grey", or none to clear)
96568
+ --valign top|center|bottom Vertical alignment of cell content
96569
+ --halign left|center|right|justify
96570
+ Horizontal alignment of cell TEXT (a paragraph property \u2014
96571
+ not the same as --align, which moves the whole table)
96572
+ --cell-borders SIDES Comma list of top,bottom,left,right,all,insideH,insideV
96573
+ (or none to clear). Styled by the --border-* options:
96574
+ --border-style single|double|none (default: single)
96575
+ --border-size EIGHTHS Thickness in eighths of a point (default: 4 = 0.5pt)
96576
+ --border-color HEX|NAME (default: auto)
96577
+
96578
+ Row options (--at t0:rR, or --at t0 for every row):
96579
+ --row-height MEASURE a unit is required: 0.4in or 28pt (a bare number is rejected)
96580
+ --height-rule atLeast|exact|auto (default: atLeast)
96581
+ --repeat-header / --no-repeat-header
96582
+ Repeat the row as a header atop each page the table spans
96583
+
96584
+ Table options (--at t0 only):
96585
+ --align left|center|right Position the whole table on the page
96586
+ --style STYLEID|none Apply (or clear) a table style from styles.xml
96587
+
96588
+ Common:
96589
+ --author NAME Author for tracked changes / audit comments (default: $DOCX_AUTHOR)
96590
+ --track Record as a tracked change even if the doc toggle is off
96591
+ -o, --output PATH / --dry-run / -v, --verbose / -h, --help
96592
+
96593
+ Tracking: cell shading/vAlign/borders record as a real <w:tcPrChange> and --halign
96594
+ as a <w:pPrChange> (both round-trip in Word). Table align/style and row height/
96595
+ repeat-header have no tracked-change construct Word will revert, so under tracking
96596
+ they apply in place with a [docx-cli] audit comment (same policy as tables borders).
96597
+
96598
+ Examples:
96599
+ docx tables format invoice.docx --at t0:r0 --shade D9D9D9 --valign center
96600
+ docx tables format invoice.docx --at t0:c2 --halign right
96601
+ docx tables format invoice.docx --at t0:r1c0-r3c2 --cell-borders bottom
96602
+ docx tables format invoice.docx --at t0 --align center --style LightGrid
96603
+ docx tables format invoice.docx --at t0:r0 --repeat-header --row-height 0.4in
96604
+ `, VALIGNS, HALIGNS, TABLE_ALIGNS, BORDER_STYLES, HEIGHT_RULES, ALL_SIDES, COLOR_NAMES;
96605
+ var init_format = __esm(() => {
96606
+ init_core2();
96607
+ init_locators();
96608
+ init_table();
96609
+ init_parse_helpers();
96610
+ init_respond();
96611
+ init_common2();
96612
+ VALIGNS = new Set(["top", "center", "bottom"]);
96613
+ HALIGNS = new Set(["left", "center", "right", "justify"]);
96614
+ TABLE_ALIGNS = new Set(["left", "center", "right"]);
96615
+ BORDER_STYLES = new Set(["single", "double", "none"]);
96616
+ HEIGHT_RULES = new Set(["atLeast", "exact", "auto"]);
96617
+ ALL_SIDES = [
96618
+ "top",
96619
+ "left",
96620
+ "bottom",
96621
+ "right",
96622
+ "insideH",
96623
+ "insideV"
96624
+ ];
96625
+ COLOR_NAMES = {
96626
+ white: "FFFFFF",
96627
+ black: "000000",
96628
+ gray: "808080",
96629
+ grey: "808080",
96630
+ lightgray: "D9D9D9",
96631
+ lightgrey: "D9D9D9",
96632
+ darkgray: "A6A6A6",
96633
+ darkgrey: "A6A6A6",
96634
+ red: "FF0000",
96635
+ green: "00B050",
96636
+ blue: "0070C0",
96637
+ yellow: "FFFF00"
96638
+ };
96639
+ });
96640
+
95239
96641
  // src/cli/tables/index.ts
95240
96642
  var exports_tables = {};
95241
96643
  __export(exports_tables, {
95242
- run: () => run48
96644
+ run: () => run52
95243
96645
  });
95244
- async function run48(args) {
96646
+ async function run52(args) {
95245
96647
  const verb = args[0];
95246
96648
  if (!verb || verb === "--help" || verb === "-h" || verb === "help") {
95247
- await writeStdout(HELP44);
96649
+ await writeStdout(HELP48);
95248
96650
  return verb ? 0 : 2;
95249
96651
  }
95250
- const loader = SUBCOMMANDS9[verb];
96652
+ const loader = SUBCOMMANDS10[verb];
95251
96653
  if (!loader) {
95252
96654
  return fail("USAGE", `Unknown tables subcommand: ${verb}`, 'Run "docx tables --help".');
95253
96655
  }
95254
96656
  const module_ = await loader();
95255
96657
  return module_.run(args.slice(1));
95256
96658
  }
95257
- var SUBCOMMANDS9, HELP44 = `docx tables \u2014 restructure tables (rows, columns, merges, widths, borders)
96659
+ var SUBCOMMANDS10, HELP48 = `docx tables \u2014 restructure & format tables (rows, columns, merges, widths, shading)
95258
96660
 
95259
96661
  Usage:
95260
96662
  docx tables <verb> FILE [options]
@@ -95268,6 +96670,9 @@ Verbs:
95268
96670
  merge Merge a cell region (--at tN:rR1cC1-rR2cC2)
95269
96671
  unmerge Split a merge anchor (--at tN:rRcC)
95270
96672
  borders Set table borders (--at tN [--style] [--size] [--color])
96673
+ format Shade/align/border/size cells, rows, or the table
96674
+ (--at LOCATOR [--shade] [--valign] [--halign] [--cell-borders]
96675
+ [--align] [--style] [--row-height] [--repeat-header])
95271
96676
 
95272
96677
  These verbs restructure an existing table. The rest of the table lifecycle uses
95273
96678
  the standard verbs:
@@ -95280,7 +96685,7 @@ Run "docx tables <verb> --help" for verb-specific help.
95280
96685
  `;
95281
96686
  var init_tables = __esm(() => {
95282
96687
  init_respond();
95283
- SUBCOMMANDS9 = {
96688
+ SUBCOMMANDS10 = {
95284
96689
  "insert-row": () => Promise.resolve().then(() => (init_insert_row(), exports_insert_row)),
95285
96690
  "delete-row": () => Promise.resolve().then(() => (init_delete_row(), exports_delete_row)),
95286
96691
  "insert-column": () => Promise.resolve().then(() => (init_insert_column(), exports_insert_column)),
@@ -95288,7 +96693,8 @@ var init_tables = __esm(() => {
95288
96693
  "set-widths": () => Promise.resolve().then(() => (init_set_widths(), exports_set_widths)),
95289
96694
  merge: () => Promise.resolve().then(() => (init_merge(), exports_merge)),
95290
96695
  unmerge: () => Promise.resolve().then(() => (init_unmerge(), exports_unmerge)),
95291
- borders: () => Promise.resolve().then(() => (init_borders(), exports_borders))
96696
+ borders: () => Promise.resolve().then(() => (init_borders(), exports_borders)),
96697
+ format: () => Promise.resolve().then(() => (init_format(), exports_format))
95292
96698
  };
95293
96699
  });
95294
96700
 
@@ -95354,19 +96760,19 @@ var init_groups = __esm(() => {
95354
96760
  function collectTrackedChangeRecords(document4) {
95355
96761
  const byId = new Map;
95356
96762
  for (const paragraph2 of flattenParagraphs(document4.body.blocks)) {
95357
- for (const run49 of paragraph2.runs) {
95358
- if (run49.type !== "text" || !run49.trackedChange)
96763
+ for (const run53 of paragraph2.runs) {
96764
+ if (run53.type !== "text" || !run53.trackedChange)
95359
96765
  continue;
95360
- const change = run49.trackedChange;
96766
+ const change = run53.trackedChange;
95361
96767
  const existing = byId.get(change.id);
95362
96768
  if (existing) {
95363
- existing.text += run49.text;
96769
+ existing.text += run53.text;
95364
96770
  continue;
95365
96771
  }
95366
96772
  byId.set(change.id, {
95367
96773
  ...change,
95368
96774
  blockId: paragraph2.id,
95369
- text: run49.text
96775
+ text: run53.text
95370
96776
  });
95371
96777
  }
95372
96778
  }
@@ -95609,22 +97015,22 @@ var init_list_view = __esm(() => {
95609
97015
  // src/cli/track-changes/list.ts
95610
97016
  var exports_list5 = {};
95611
97017
  __export(exports_list5, {
95612
- run: () => run49
97018
+ run: () => run53
95613
97019
  });
95614
- async function run49(args) {
97020
+ async function run53(args) {
95615
97021
  const parsed = await tryParseArgs(args, {
95616
97022
  help: { type: "boolean", short: "h" },
95617
97023
  json: { type: "boolean" }
95618
- }, HELP45);
97024
+ }, HELP49);
95619
97025
  if (typeof parsed === "number")
95620
97026
  return parsed;
95621
97027
  if (parsed.values.help) {
95622
- await writeStdout(HELP45);
97028
+ await writeStdout(HELP49);
95623
97029
  return EXIT2.OK;
95624
97030
  }
95625
97031
  const path2 = parsed.positionals[0];
95626
97032
  if (!path2)
95627
- return fail("USAGE", "Missing FILE argument", HELP45);
97033
+ return fail("USAGE", "Missing FILE argument", HELP49);
95628
97034
  const document4 = await openOrFail(path2);
95629
97035
  if (typeof document4 === "number")
95630
97036
  return document4;
@@ -95636,7 +97042,7 @@ async function run49(args) {
95636
97042
  await writeStdout(renderTrackedChangeTable(records));
95637
97043
  return EXIT2.OK;
95638
97044
  }
95639
- var HELP45 = `docx track-changes list \u2014 inventory every revision wrapper
97045
+ var HELP49 = `docx track-changes list \u2014 inventory every revision wrapper
95640
97046
 
95641
97047
  Usage:
95642
97048
  docx track-changes list FILE [options]
@@ -95786,17 +97192,17 @@ var init_run_apply = __esm(() => {
95786
97192
  // src/cli/track-changes/accept.ts
95787
97193
  var exports_accept = {};
95788
97194
  __export(exports_accept, {
95789
- run: () => run50
97195
+ run: () => run54
95790
97196
  });
95791
- async function run50(args) {
95792
- return runApply(args, "accept", HELP46);
97197
+ async function run54(args) {
97198
+ return runApply(args, "accept", HELP50);
95793
97199
  }
95794
- var AT_FORMS14, HELP46;
97200
+ var AT_FORMS14, HELP50;
95795
97201
  var init_accept = __esm(() => {
95796
97202
  init_core2();
95797
97203
  init_run_apply();
95798
97204
  AT_FORMS14 = describeForms(["trackedChange"], " ");
95799
- HELP46 = `docx track-changes accept \u2014 accept tracked changes (incorporate into the doc)
97205
+ HELP50 = `docx track-changes accept \u2014 accept tracked changes (incorporate into the doc)
95800
97206
 
95801
97207
  Usage:
95802
97208
  docx track-changes accept FILE --at tcN [options]
@@ -95857,17 +97263,17 @@ Examples:
95857
97263
  // src/cli/track-changes/reject.ts
95858
97264
  var exports_reject = {};
95859
97265
  __export(exports_reject, {
95860
- run: () => run51
97266
+ run: () => run55
95861
97267
  });
95862
- async function run51(args) {
95863
- return runApply(args, "reject", HELP47);
97268
+ async function run55(args) {
97269
+ return runApply(args, "reject", HELP51);
95864
97270
  }
95865
- var AT_FORMS15, HELP47;
97271
+ var AT_FORMS15, HELP51;
95866
97272
  var init_reject = __esm(() => {
95867
97273
  init_core2();
95868
97274
  init_run_apply();
95869
97275
  AT_FORMS15 = describeForms(["trackedChange"], " ");
95870
- HELP47 = `docx track-changes reject \u2014 reject tracked changes (revert to pre-change state)
97276
+ HELP51 = `docx track-changes reject \u2014 reject tracked changes (revert to pre-change state)
95871
97277
 
95872
97278
  Usage:
95873
97279
  docx track-changes reject FILE --at tcN [options]
@@ -95936,28 +97342,28 @@ Examples:
95936
97342
  // src/cli/track-changes/apply.ts
95937
97343
  var exports_apply = {};
95938
97344
  __export(exports_apply, {
95939
- run: () => run52
97345
+ run: () => run56
95940
97346
  });
95941
- async function run52(args) {
97347
+ async function run56(args) {
95942
97348
  const parsed = await tryParseArgs(args, {
95943
97349
  accept: { type: "string", multiple: true },
95944
97350
  reject: { type: "string", multiple: true },
95945
97351
  ...SAVE_FLAGS
95946
- }, HELP48);
97352
+ }, HELP52);
95947
97353
  if (typeof parsed === "number")
95948
97354
  return parsed;
95949
97355
  if (parsed.values.help) {
95950
- await writeStdout(HELP48);
97356
+ await writeStdout(HELP52);
95951
97357
  return EXIT2.OK;
95952
97358
  }
95953
97359
  setVerboseAck(Boolean(parsed.values.verbose));
95954
97360
  const path2 = parsed.positionals[0];
95955
97361
  if (!path2)
95956
- return fail("USAGE", "Missing FILE argument", HELP48);
97362
+ return fail("USAGE", "Missing FILE argument", HELP52);
95957
97363
  const acceptRaw = parsed.values.accept ?? [];
95958
97364
  const rejectRaw = parsed.values.reject ?? [];
95959
97365
  if (acceptRaw.length === 0 && rejectRaw.length === 0) {
95960
- return fail("USAGE", "Specify --accept and/or --reject (handle)", HELP48);
97366
+ return fail("USAGE", "Specify --accept and/or --reject (handle)", HELP52);
95961
97367
  }
95962
97368
  const document4 = await openOrFail(path2);
95963
97369
  if (typeof document4 === "number")
@@ -95978,7 +97384,7 @@ async function run52(args) {
95978
97384
  const rejectSet = new Set(rejects);
95979
97385
  const conflict = accepts.find((id) => rejectSet.has(id));
95980
97386
  if (conflict) {
95981
- return fail("USAGE", `${conflict} is named in both --accept and --reject`, HELP48);
97387
+ return fail("USAGE", `${conflict} is named in both --accept and --reject`, HELP52);
95982
97388
  }
95983
97389
  const outputPath = parsed.values.output;
95984
97390
  try {
@@ -96021,7 +97427,7 @@ function trackedChangeIndex2(id) {
96021
97427
  const match = id.match(/^tc(\d+)$/);
96022
97428
  return match?.[1] ? Number(match[1]) : 0;
96023
97429
  }
96024
- var HELP48 = `docx track-changes apply \u2014 finalize: accept AND reject in one atomic call
97430
+ var HELP52 = `docx track-changes apply \u2014 finalize: accept AND reject in one atomic call
96025
97431
 
96026
97432
  Usage:
96027
97433
  docx track-changes apply FILE (--accept H ... | --reject H ...) [options]
@@ -96074,16 +97480,16 @@ var init_apply2 = __esm(() => {
96074
97480
  // src/cli/track-changes/toggle.tsx
96075
97481
  var exports_toggle = {};
96076
97482
  __export(exports_toggle, {
96077
- run: () => run53
97483
+ run: () => run57
96078
97484
  });
96079
- async function run53(args) {
97485
+ async function run57(args) {
96080
97486
  const parsed = await tryParseArgs(args, {
96081
97487
  ...SAVE_FLAGS
96082
- }, HELP49);
97488
+ }, HELP53);
96083
97489
  if (typeof parsed === "number")
96084
97490
  return parsed;
96085
97491
  if (parsed.values.help) {
96086
- await writeStdout(HELP49);
97492
+ await writeStdout(HELP53);
96087
97493
  return EXIT2.OK;
96088
97494
  }
96089
97495
  setVerboseAck(Boolean(parsed.values.verbose));
@@ -96092,10 +97498,10 @@ async function run53(args) {
96092
97498
  const mode = modeFirst ? first : second;
96093
97499
  const path2 = modeFirst ? second : first;
96094
97500
  if (mode !== "on" && mode !== "off") {
96095
- return fail("USAGE", `Expected "on" or "off" (e.g. \`docx track-changes on FILE\`), got: ${parsed.positionals.join(" ") || "<nothing>"}`, HELP49);
97501
+ return fail("USAGE", `Expected "on" or "off" (e.g. \`docx track-changes on FILE\`), got: ${parsed.positionals.join(" ") || "<nothing>"}`, HELP53);
96096
97502
  }
96097
97503
  if (!path2)
96098
- return fail("USAGE", "Missing FILE argument", HELP49);
97504
+ return fail("USAGE", "Missing FILE argument", HELP53);
96099
97505
  const document4 = await openOrFail(path2);
96100
97506
  if (typeof document4 === "number")
96101
97507
  return document4;
@@ -96125,7 +97531,7 @@ async function run53(args) {
96125
97531
  });
96126
97532
  return EXIT2.OK;
96127
97533
  }
96128
- var HELP49 = `docx track-changes \u2014 toggle the document's tracked-changes mode
97534
+ var HELP53 = `docx track-changes \u2014 toggle the document's tracked-changes mode
96129
97535
 
96130
97536
  Usage:
96131
97537
  docx track-changes on|off FILE [options]
@@ -96163,16 +97569,16 @@ var init_toggle2 = __esm(() => {
96163
97569
  // src/cli/track-changes/index.ts
96164
97570
  var exports_track_changes = {};
96165
97571
  __export(exports_track_changes, {
96166
- run: () => run54
97572
+ run: () => run58
96167
97573
  });
96168
- async function run54(args) {
97574
+ async function run58(args) {
96169
97575
  const first = args[0];
96170
97576
  if (first === "--help" || first === "-h" || first === "help") {
96171
- await writeStdout(HELP50);
97577
+ await writeStdout(HELP54);
96172
97578
  return 0;
96173
97579
  }
96174
97580
  if (!first) {
96175
- return fail("USAGE", "Missing arguments", HELP50);
97581
+ return fail("USAGE", "Missing arguments", HELP54);
96176
97582
  }
96177
97583
  if (first === "list") {
96178
97584
  const module_2 = await Promise.resolve().then(() => (init_list8(), exports_list5));
@@ -96193,7 +97599,7 @@ async function run54(args) {
96193
97599
  const module_ = await Promise.resolve().then(() => (init_toggle2(), exports_toggle));
96194
97600
  return module_.run(args);
96195
97601
  }
96196
- var HELP50 = `docx track-changes \u2014 manage tracked-changes
97602
+ var HELP54 = `docx track-changes \u2014 manage tracked-changes
96197
97603
 
96198
97604
  Usage:
96199
97605
  docx track-changes on|off FILE [options]
@@ -96339,29 +97745,29 @@ var init_count = __esm(() => {
96339
97745
  // src/cli/wc/index.ts
96340
97746
  var exports_wc = {};
96341
97747
  __export(exports_wc, {
96342
- run: () => run55
97748
+ run: () => run59
96343
97749
  });
96344
- async function run55(args) {
97750
+ async function run59(args) {
96345
97751
  const parsed = await tryParseArgs(args, {
96346
97752
  accepted: { type: "boolean" },
96347
97753
  baseline: { type: "boolean" },
96348
97754
  current: { type: "boolean" },
96349
97755
  json: { type: "boolean" },
96350
97756
  help: { type: "boolean", short: "h" }
96351
- }, HELP51);
97757
+ }, HELP55);
96352
97758
  if (typeof parsed === "number")
96353
97759
  return parsed;
96354
97760
  if (parsed.values.help) {
96355
- await writeStdout(HELP51);
97761
+ await writeStdout(HELP55);
96356
97762
  return EXIT2.OK;
96357
97763
  }
96358
97764
  const path2 = parsed.positionals[0];
96359
97765
  const locatorInput = parsed.positionals[1];
96360
97766
  if (!path2)
96361
- return fail("USAGE", "Missing FILE argument", HELP51);
97767
+ return fail("USAGE", "Missing FILE argument", HELP55);
96362
97768
  const view = resolveView(parsed.values);
96363
97769
  if (!view) {
96364
- return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive", HELP51);
97770
+ return fail("USAGE", "--accepted, --baseline, and --current are mutually exclusive", HELP55);
96365
97771
  }
96366
97772
  const json2 = Boolean(parsed.values.json);
96367
97773
  const pickText = paragraphTextFor(view);
@@ -96539,13 +97945,13 @@ function paragraphTextFor(view) {
96539
97945
  return paragraphTextBaseline;
96540
97946
  return paragraphText2;
96541
97947
  }
96542
- var HELP51;
97948
+ var HELP55;
96543
97949
  var init_wc = __esm(() => {
96544
97950
  init_core2();
96545
97951
  init_parse_helpers();
96546
97952
  init_respond();
96547
97953
  init_count();
96548
- HELP51 = `docx wc \u2014 count words in a document or a locator-addressed slice
97954
+ HELP55 = `docx wc \u2014 count words in a document or a locator-addressed slice
96549
97955
 
96550
97956
  Usage:
96551
97957
  docx wc FILE [LOCATOR] [options]
@@ -96609,8 +98015,8 @@ Examples:
96609
98015
  // package.json
96610
98016
  var package_default = {
96611
98017
  name: "bun-docx",
96612
- version: "0.17.0",
96613
- description: "CLI for AI agents (Claude, Codex) to read, edit, and comment on .docx files with full format fidelity.",
98018
+ version: "0.19.0",
98019
+ description: "Read, edit, redline, and comment on Microsoft Word .docx files from the command line \u2014 built for AI agents.",
96614
98020
  keywords: [
96615
98021
  "docx",
96616
98022
  "openxml",
@@ -96620,8 +98026,15 @@ var package_default = {
96620
98026
  "ai",
96621
98027
  "claude",
96622
98028
  "codex",
96623
- "agentic"
98029
+ "agentic",
98030
+ "agent-skill",
98031
+ "pi-package"
96624
98032
  ],
98033
+ pi: {
98034
+ skills: [
98035
+ "./skills"
98036
+ ]
98037
+ },
96625
98038
  license: "MIT",
96626
98039
  author: "Kirill Klimuk",
96627
98040
  repository: {
@@ -96638,6 +98051,7 @@ var package_default = {
96638
98051
  files: [
96639
98052
  "dist/index.js",
96640
98053
  "dist/pdfium-*.wasm",
98054
+ "skills/",
96641
98055
  "README.md",
96642
98056
  "LICENSE",
96643
98057
  "LGPL-3.0.txt",
@@ -96717,6 +98131,7 @@ Commands (each one-liner names capabilities you'd otherwise miss; see <command>
96717
98131
  images \u2026 Add (--caption "Figure 1: \u2026" for a captioned figure), extract, replace, delete, list images
96718
98132
  hyperlinks \u2026 Add, list, replace, delete hyperlinks (add uses --url; replace uses --with)
96719
98133
  tables \u2026 Restructure tables \u2014 insert/delete rows & columns, merge/unmerge, set widths, borders
98134
+ lists FILE Renumber a numbered list \u2014 "lists set --at pN --start 5" / "--format upper-roman" / "--restart" / "--continue"
96720
98135
  track-changes \u2026 Toggle (on|off FILE); list / accept / reject revisions; "read" shows them as CriticMarkup
96721
98136
  info \u2026 Reference material, no FILE needed (schema for read --ast, locator grammar)
96722
98137
 
@@ -96777,6 +98192,7 @@ var COMMANDS = {
96777
98192
  images: () => Promise.resolve().then(() => (init_images(), exports_images)),
96778
98193
  info: () => Promise.resolve().then(() => (init_info(), exports_info)),
96779
98194
  insert: () => Promise.resolve().then(() => (init_insert2(), exports_insert)),
98195
+ lists: () => Promise.resolve().then(() => (init_lists2(), exports_lists)),
96780
98196
  outline: () => Promise.resolve().then(() => (init_outline(), exports_outline)),
96781
98197
  read: () => Promise.resolve().then(() => (init_read3(), exports_read)),
96782
98198
  render: () => Promise.resolve().then(() => (init_render2(), exports_render)),