wordinweb 0.1.14 → 0.1.16

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.d.ts CHANGED
@@ -1363,6 +1363,14 @@ declare class DocxDocument {
1363
1363
  */
1364
1364
  private rememberOriginalXml;
1365
1365
  private writeModeledXml;
1366
+ /**
1367
+ * Canonicalize producer shorthand that Google Docs otherwise interprets as
1368
+ * a fixed, few-twip table. Word treats `tblW="100%"` plus a placeholder
1369
+ * grid as autofit; Google needs the standard pct value and a usable cached
1370
+ * grid. The cached widths follow the same content-dominant shape and do not
1371
+ * change Word's autofit result.
1372
+ */
1373
+ private normalizePercentageTableGrids;
1366
1374
  save(): Uint8Array;
1367
1375
  /** Fresh unique docPr id for inserted drawings. */
1368
1376
  nextDrawingId(): number;
package/dist/index.js CHANGED
@@ -6906,7 +6906,95 @@ var DocxDocument = class _DocxDocument {
6906
6906
  const xml = serializeXml(root, true);
6907
6907
  if (xml !== this.originalModeledXml.get(part)) files[part] = strToU82(xml);
6908
6908
  }
6909
+ /**
6910
+ * Canonicalize producer shorthand that Google Docs otherwise interprets as
6911
+ * a fixed, few-twip table. Word treats `tblW="100%"` plus a placeholder
6912
+ * grid as autofit; Google needs the standard pct value and a usable cached
6913
+ * grid. The cached widths follow the same content-dominant shape and do not
6914
+ * change Word's autofit result.
6915
+ */
6916
+ normalizePercentageTableGrids() {
6917
+ const setAttr = (element, name, value) => {
6918
+ const key = Object.keys(element.attrs).find((item) => localName(item) === name);
6919
+ element.attrs[key ?? `${element.name.includes(":") ? element.name.split(":")[0] + ":" : ""}${name}`] = value;
6920
+ };
6921
+ const textLength = (blocks) => {
6922
+ let length = 0;
6923
+ for (const block of blocks) {
6924
+ if (block.type === "table") {
6925
+ for (const row of block.rows) {
6926
+ for (const cell of row.cells) length += textLength(cell.blocks);
6927
+ }
6928
+ continue;
6929
+ }
6930
+ for (const item of block.children) {
6931
+ const runs = item.type === "run" ? [item] : item.runs;
6932
+ for (const run of runs) {
6933
+ for (const content of run.content) {
6934
+ if (content.kind === "text") length += content.text.length;
6935
+ else if (content.kind === "tab") length += 4;
6936
+ }
6937
+ }
6938
+ }
6939
+ }
6940
+ return length;
6941
+ };
6942
+ const normalize = (table2, available) => {
6943
+ const source = table2.src;
6944
+ if (!source) return;
6945
+ const tableProps = child(source, "tblPr");
6946
+ const tableWidth = child(tableProps, "tblW");
6947
+ const rawWidth = attr(tableWidth, "w")?.trim();
6948
+ if (attr(tableWidth, "type") !== "pct" || !rawWidth?.endsWith("%")) return;
6949
+ const percent = Number.parseFloat(rawWidth);
6950
+ if (!Number.isFinite(percent) || percent <= 0) return;
6951
+ setAttr(tableWidth, "w", String(Math.round(percent * 50)));
6952
+ const grid = child(source, "tblGrid");
6953
+ const columns = children(grid, "gridCol");
6954
+ if (columns.length === 0) return;
6955
+ const target = Math.round(pxToTwips(available) * percent / 100);
6956
+ const authoredTotal = columns.reduce((sum2, column) => sum2 + (intAttr(column, "w") ?? 0), 0);
6957
+ if (target <= 0 || authoredTotal >= target * 0.1) return;
6958
+ const floor = 600;
6959
+ const widths = new Array(columns.length).fill(floor);
6960
+ for (const row of table2.rows) {
6961
+ let column = 0;
6962
+ for (const cell of row.cells) {
6963
+ const span = Math.max(1, Math.min(cell.props.gridSpan, columns.length - column));
6964
+ const demand = Math.max(floor * span, textLength(cell.blocks) * 100 + 300);
6965
+ for (let offset = 0; offset < span; offset++) {
6966
+ widths[column + offset] = Math.max(widths[column + offset], demand / span);
6967
+ }
6968
+ column += cell.props.gridSpan;
6969
+ if (column >= columns.length) break;
6970
+ }
6971
+ }
6972
+ const dominant = widths.indexOf(Math.max(...widths));
6973
+ const total = widths.reduce((sum2, width) => sum2 + width, 0);
6974
+ if (total < target) {
6975
+ widths[dominant] += target - total;
6976
+ } else if (total > target) {
6977
+ const slack = widths.reduce((sum2, width) => sum2 + Math.max(0, width - floor), 0);
6978
+ const scale = slack > 0 ? Math.min(1, (total - target) / slack) : 0;
6979
+ for (let index = 0; index < widths.length; index++) {
6980
+ widths[index] -= Math.max(0, widths[index] - floor) * scale;
6981
+ }
6982
+ }
6983
+ const rounded = widths.map(Math.round);
6984
+ rounded[dominant] += target - rounded.reduce((sum2, width) => sum2 + width, 0);
6985
+ columns.forEach((column, index) => setAttr(column, "w", String(rounded[index])));
6986
+ };
6987
+ for (const section of this.sections) {
6988
+ const contentWidth = section.props.pageWidth - section.props.marginLeft - section.props.marginRight - section.props.gutter;
6989
+ const columnCount = Math.max(1, section.props.columns.count);
6990
+ const available = section.props.columns.widths?.[0] ?? (contentWidth - section.props.columns.space * (columnCount - 1)) / columnCount;
6991
+ for (const block of section.blocks) {
6992
+ if (block.type === "table") normalize(block, available);
6993
+ }
6994
+ }
6995
+ }
6909
6996
  save() {
6997
+ this.normalizePercentageTableGrids();
6910
6998
  const files = { ...this.pkg.raw() };
6911
6999
  if (files["docProps/custom.xml"] && this.contentTypesRoot && !this.contentTypesRoot.children.some(
6912
7000
  (item) => localName(item.name) === "Override" && item.attrs.PartName === "/docProps/custom.xml"
@@ -20628,7 +20716,7 @@ function resizeTableRow(doc, tblEl, rowIdx, newHeightPx) {
20628
20716
  doc.refresh();
20629
20717
  return true;
20630
20718
  }
20631
- function moveTableTo(doc, tblEl, xPx, yPx) {
20719
+ function moveTableTo(doc, tblEl, xPx, yPx, preservePageStart = false) {
20632
20720
  if (localName(tblEl.name) !== "tbl") return false;
20633
20721
  const w = prefixOf5(tblEl);
20634
20722
  let tblPr = child(tblEl, "tblPr");
@@ -20638,6 +20726,27 @@ function moveTableTo(doc, tblEl, xPx, yPx) {
20638
20726
  }
20639
20727
  let position = child(tblPr, "tblpPr");
20640
20728
  if (!position) {
20729
+ if (preservePageStart) {
20730
+ const parent = doc.findParentOf(tblEl);
20731
+ const tableIndex = parent?.children.indexOf(tblEl) ?? -1;
20732
+ const previous = parent && tableIndex > 0 ? parent.children[tableIndex - 1] : void 0;
20733
+ const breakRun = {
20734
+ name: `${w}r`,
20735
+ attrs: {},
20736
+ children: [{ name: `${w}br`, attrs: { [`${w}type`]: "page" }, children: [], text: "" }],
20737
+ text: ""
20738
+ };
20739
+ if (previous && localName(previous.name) === "p") {
20740
+ previous.children.push(breakRun);
20741
+ } else if (parent && tableIndex >= 0) {
20742
+ parent.children.splice(tableIndex, 0, {
20743
+ name: `${w}p`,
20744
+ attrs: {},
20745
+ children: [breakRun],
20746
+ text: ""
20747
+ });
20748
+ }
20749
+ }
20641
20750
  position = { name: `${w}tblpPr`, attrs: {}, children: [], text: "" };
20642
20751
  const styleIdx = tblPr.children.findIndex((c) => localName(c.name) === "tblStyle");
20643
20752
  tblPr.children.splice(styleIdx + 1, 0, position);
@@ -23514,7 +23623,11 @@ var _DocxEditor = class _DocxEditor {
23514
23623
  const delta = isCol ? dx : dy;
23515
23624
  if ((isMove ? Math.hypot(dx, dy) : Math.abs(delta)) >= 1) {
23516
23625
  this.host.history?.checkpoint();
23517
- const ok = isMove ? moveTableTo(this.host.doc, grip.item.tbl, grip.item.x + dx, grip.item.y1 + dy) : isCol ? resizeTableColumn(this.host.doc, grip.item.tbl, grip.item.boundary, dx, grip.item.renderedWidths) : resizeTableRow(this.host.doc, grip.item.tbl, grip.item.boundary, (grip.item.rowHeightPx ?? 0) + dy);
23626
+ const page = surface.parentElement;
23627
+ const pages = Array.from(this.host.getHandle()?.root.querySelectorAll(".dxw-page") ?? []);
23628
+ const bodyTop = parseFloat(page?.dataset.bodyTop ?? "");
23629
+ const preservePageStart = isMove && page !== null && pages.indexOf(page) > 0 && Number.isFinite(bodyTop) && Math.abs(grip.item.y1 - bodyTop) <= 1;
23630
+ const ok = isMove ? moveTableTo(this.host.doc, grip.item.tbl, grip.item.x + dx, grip.item.y1 + dy, preservePageStart) : isCol ? resizeTableColumn(this.host.doc, grip.item.tbl, grip.item.boundary, dx, grip.item.renderedWidths) : resizeTableRow(this.host.doc, grip.item.tbl, grip.item.boundary, (grip.item.rowHeightPx ?? 0) + dy);
23518
23631
  if (ok) {
23519
23632
  this.host.rerender(void 0, isMove ? "global" : "local");
23520
23633
  this.positionCaret();