@json-to-office/core-docx 7.0.1 → 7.1.2

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
@@ -2014,6 +2014,7 @@ var init_layoutUtils = __esm({
2014
2014
  if (themeConfig?.page) {
2015
2015
  const margins = themeConfig.page.margins || {};
2016
2016
  const dimensions = getPageDimensions(themeConfig.page.size);
2017
+ const gutter = margins.gutter;
2017
2018
  return {
2018
2019
  size: {
2019
2020
  width: dimensions.width,
@@ -2024,7 +2025,13 @@ var init_layoutUtils = __esm({
2024
2025
  top: margins.top ?? defaultMargins.top ?? 1440,
2025
2026
  right: margins.right ?? defaultMargins.right ?? 1440,
2026
2027
  bottom: margins.bottom ?? defaultMargins.bottom ?? 1440,
2027
- left: margins.left ?? defaultMargins.left ?? 1440
2028
+ left: margins.left ?? defaultMargins.left ?? 1440,
2029
+ // How far the running head and foot sit from the page edge. Left out,
2030
+ // each renderer writes its own default — docx.js 708, office-open 851
2031
+ // and 992 — in place of the distance the theme states.
2032
+ header: margins.header ?? defaultMargins.header ?? 720,
2033
+ footer: margins.footer ?? defaultMargins.footer ?? 720,
2034
+ ...gutter !== void 0 && { gutter }
2028
2035
  }
2029
2036
  };
2030
2037
  }
@@ -2040,50 +2047,15 @@ var init_layoutUtils = __esm({
2040
2047
  top: defaultMargins.top ?? 1440,
2041
2048
  right: defaultMargins.right ?? 1440,
2042
2049
  bottom: defaultMargins.bottom ?? 1440,
2043
- left: defaultMargins.left ?? 1440
2050
+ left: defaultMargins.left ?? 1440,
2051
+ header: defaultMargins.header ?? 720,
2052
+ footer: defaultMargins.footer ?? 720
2044
2053
  }
2045
2054
  };
2046
2055
  };
2047
2056
  }
2048
2057
  });
2049
2058
 
2050
- // src/utils/generationContext.ts
2051
- import { AsyncLocalStorage } from "async_hooks";
2052
- import { isAbsolute, resolve } from "path";
2053
- function runWithBaseDir(baseDir, callback) {
2054
- return baseDir === void 0 ? callback() : baseDirStorage.run(resolve(baseDir), callback);
2055
- }
2056
- function resolveFromBaseDir(filePath) {
2057
- const base = baseDirStorage.getStore();
2058
- if (!base || isAbsolute(filePath)) return filePath;
2059
- return resolve(base, filePath);
2060
- }
2061
- function runWithWarnings(warnings, callback) {
2062
- return warnings === void 0 ? callback() : warningsStorage.run(warnings, callback);
2063
- }
2064
- function reportWarning(component, code, message, context) {
2065
- const warnings = warningsStorage.getStore();
2066
- if (warnings) {
2067
- warnings.push({
2068
- component,
2069
- message,
2070
- severity: "warning",
2071
- context: { code, ...context }
2072
- });
2073
- return;
2074
- }
2075
- console.warn(`[json-to-docx] [${code}] ${message}`);
2076
- }
2077
- var generationDateStorage, baseDirStorage, warningsStorage;
2078
- var init_generationContext = __esm({
2079
- "src/utils/generationContext.ts"() {
2080
- "use strict";
2081
- generationDateStorage = new AsyncLocalStorage();
2082
- baseDirStorage = new AsyncLocalStorage();
2083
- warningsStorage = new AsyncLocalStorage();
2084
- }
2085
- });
2086
-
2087
2059
  // src/themes/json/parser.ts
2088
2060
  import { validateThemeJson } from "@json-to-office/shared-docx/validation/unified";
2089
2061
  var ThemeValidationError, ThemeParseError, ThemeParser;
@@ -2416,7 +2388,8 @@ function getAvailableWidthTwips(theme, themeName) {
2416
2388
  const width = page?.size?.width || 0;
2417
2389
  const left = page?.margin?.left || 0;
2418
2390
  const right = page?.margin?.right || 0;
2419
- return Math.max(0, width - left - right);
2391
+ const gutter = page?.margin?.gutter || 0;
2392
+ return Math.max(0, width - left - right - gutter);
2420
2393
  }
2421
2394
  function getPageWidthTwips(theme, themeName) {
2422
2395
  const page = getPageSetup(theme, themeName);
@@ -2451,6 +2424,13 @@ function resolveOffsetTwips(value, referenceTwips) {
2451
2424
  }
2452
2425
  return Math.round(referenceTwips * parseFloat(match[1]) / 100);
2453
2426
  }
2427
+ function splitTwips(count, totalTwips) {
2428
+ const edge = (index) => Math.round(totalTwips * index / count);
2429
+ return Array.from(
2430
+ { length: count },
2431
+ (_, index) => edge(index + 1) - edge(index)
2432
+ );
2433
+ }
2454
2434
  function relativeLengthToTwips(value, availableWidthTwips) {
2455
2435
  if (typeof value === "number") {
2456
2436
  return pointsToTwips(value);
@@ -2467,6 +2447,43 @@ var init_widthUtils = __esm({
2467
2447
  }
2468
2448
  });
2469
2449
 
2450
+ // src/utils/generationContext.ts
2451
+ import { AsyncLocalStorage } from "async_hooks";
2452
+ import { isAbsolute, resolve } from "path";
2453
+ function runWithBaseDir(baseDir, callback) {
2454
+ return baseDir === void 0 ? callback() : baseDirStorage.run(resolve(baseDir), callback);
2455
+ }
2456
+ function resolveFromBaseDir(filePath) {
2457
+ const base = baseDirStorage.getStore();
2458
+ if (!base || isAbsolute(filePath)) return filePath;
2459
+ return resolve(base, filePath);
2460
+ }
2461
+ function runWithWarnings(warnings, callback) {
2462
+ return warnings === void 0 ? callback() : warningsStorage.run(warnings, callback);
2463
+ }
2464
+ function reportWarning(component, code, message, context) {
2465
+ const warnings = warningsStorage.getStore();
2466
+ if (warnings) {
2467
+ warnings.push({
2468
+ component,
2469
+ message,
2470
+ severity: "warning",
2471
+ context: { code, ...context }
2472
+ });
2473
+ return;
2474
+ }
2475
+ console.warn(`[json-to-docx] [${code}] ${message}`);
2476
+ }
2477
+ var generationDateStorage, baseDirStorage, warningsStorage;
2478
+ var init_generationContext = __esm({
2479
+ "src/utils/generationContext.ts"() {
2480
+ "use strict";
2481
+ generationDateStorage = new AsyncLocalStorage();
2482
+ baseDirStorage = new AsyncLocalStorage();
2483
+ warningsStorage = new AsyncLocalStorage();
2484
+ }
2485
+ });
2486
+
2470
2487
  // src/utils/imageUtils.ts
2471
2488
  import { readFileSync } from "fs";
2472
2489
  import { availableParallelism } from "os";
@@ -2762,7 +2779,7 @@ var init_imageUtils = __esm({
2762
2779
  });
2763
2780
 
2764
2781
  // src/ir/types.ts
2765
- var TWIPS_PER_INCH, TWIPS_PER_POINT2, EMU_PER_INCH, EMU_PER_TWIP, DOCX_IR_SCHEMA_VERSION;
2782
+ var TWIPS_PER_INCH, TWIPS_PER_POINT2, EMU_PER_INCH, EMU_PER_TWIP, DOCX_IR_SCHEMA_VERSION, DOCX_IR_BORDER_STYLES;
2766
2783
  var init_types = __esm({
2767
2784
  "src/ir/types.ts"() {
2768
2785
  "use strict";
@@ -2771,6 +2788,35 @@ var init_types = __esm({
2771
2788
  EMU_PER_INCH = 914400;
2772
2789
  EMU_PER_TWIP = EMU_PER_INCH / TWIPS_PER_INCH;
2773
2790
  DOCX_IR_SCHEMA_VERSION = 1;
2791
+ DOCX_IR_BORDER_STYLES = [
2792
+ "single",
2793
+ "dashDotStroked",
2794
+ "dashed",
2795
+ "dashSmallGap",
2796
+ "dotDash",
2797
+ "dotDotDash",
2798
+ "dotted",
2799
+ "double",
2800
+ "doubleWave",
2801
+ "inset",
2802
+ "nil",
2803
+ "none",
2804
+ "outset",
2805
+ "thick",
2806
+ "thickThinLargeGap",
2807
+ "thickThinMediumGap",
2808
+ "thickThinSmallGap",
2809
+ "thinThickLargeGap",
2810
+ "thinThickMediumGap",
2811
+ "thinThickSmallGap",
2812
+ "thinThickThinLargeGap",
2813
+ "thinThickThinMediumGap",
2814
+ "thinThickThinSmallGap",
2815
+ "threeDEmboss",
2816
+ "threeDEngrave",
2817
+ "triple",
2818
+ "wave"
2819
+ ];
2774
2820
  }
2775
2821
  });
2776
2822
 
@@ -2830,7 +2876,6 @@ import {
2830
2876
  AlignmentType,
2831
2877
  BookmarkEnd,
2832
2878
  BookmarkStart,
2833
- BorderStyle,
2834
2879
  ColumnBreak,
2835
2880
  CommentRangeEnd,
2836
2881
  CommentRangeStart,
@@ -3276,7 +3321,8 @@ function emitTable(block2, resources = /* @__PURE__ */ new Map()) {
3276
3321
  },
3277
3322
  layout: block2.layout === "fixed" ? TableLayoutType.FIXED : TableLayoutType.AUTOFIT,
3278
3323
  // An empty grid is a table with nothing to say about its columns, which is
3279
- // not the same as one whose columns are all zero wide.
3324
+ // not the same as one whose columns are all zero wide. The compiler hands
3325
+ // over every grid in twips, the unit `columnWidths` takes.
3280
3326
  ...block2.columnGrid.values.length > 0 ? { columnWidths: block2.columnGrid.values } : {},
3281
3327
  ...block2.borders ? {
3282
3328
  borders: {
@@ -3370,7 +3416,10 @@ function emitTableCell(cell, resources) {
3370
3416
  function emitBorder(border3) {
3371
3417
  if (!border3) return void 0;
3372
3418
  return {
3373
- style: BORDER_STYLE[border3.style] ?? BorderStyle.SINGLE,
3419
+ // Already OOXML's word, and docx.js's `BorderStyle` values are exactly
3420
+ // those words. Mapping unknown ones to `single` here is what once hid an
3421
+ // authoring word the IR should never have carried.
3422
+ style: border3.style,
3374
3423
  size: border3.sizeEighthPoints ?? 0,
3375
3424
  color: border3.color?.hex ?? "000000",
3376
3425
  // Stated only when the IR states it, so every border that predates the
@@ -3379,7 +3428,7 @@ function emitBorder(border3) {
3379
3428
  ...border3.spacePoints !== void 0 ? { space: border3.spacePoints } : {}
3380
3429
  };
3381
3430
  }
3382
- var ALIGNMENT2, PAGE_FIELDS, isSequenceField, WRAP_TYPE, ThemedTableOfContents, VERTICAL_ALIGN, TABLE_ANCHOR, HORIZONTAL_POSITION, VERTICAL_POSITION, BORDER_STYLE;
3431
+ var ALIGNMENT2, PAGE_FIELDS, isSequenceField, WRAP_TYPE, ThemedTableOfContents, VERTICAL_ALIGN, TABLE_ANCHOR, HORIZONTAL_POSITION, VERTICAL_POSITION;
3383
3432
  var init_emit = __esm({
3384
3433
  "src/renderers/docxjs/emit.ts"() {
3385
3434
  "use strict";
@@ -3428,20 +3477,10 @@ var init_emit = __esm({
3428
3477
  inside: RelativeVerticalPosition.INSIDE,
3429
3478
  outside: RelativeVerticalPosition.OUTSIDE
3430
3479
  };
3431
- BORDER_STYLE = {
3432
- none: BorderStyle.NONE,
3433
- single: BorderStyle.SINGLE,
3434
- double: BorderStyle.DOUBLE,
3435
- dashed: BorderStyle.DASHED,
3436
- dotted: BorderStyle.DOTTED
3437
- };
3438
3480
  }
3439
3481
  });
3440
3482
 
3441
3483
  // src/renderers/docxjs/styles.ts
3442
- import {
3443
- BorderStyle as BorderStyle2
3444
- } from "docx";
3445
3484
  function runProperties(formatting) {
3446
3485
  const out = {};
3447
3486
  if (formatting.fontFamily !== void 0) out.font = formatting.fontFamily;
@@ -3450,7 +3489,7 @@ function runProperties(formatting) {
3450
3489
  }
3451
3490
  if (formatting.color) out.color = formatting.color.hex;
3452
3491
  if (formatting.bold !== void 0) out.bold = formatting.bold;
3453
- if (formatting.italic !== void 0) out.italic = formatting.italic;
3492
+ if (formatting.italic !== void 0) out.italics = formatting.italic;
3454
3493
  if (formatting.underline) {
3455
3494
  out.underline = {
3456
3495
  type: formatting.underline.type,
@@ -3462,7 +3501,9 @@ function runProperties(formatting) {
3462
3501
  if (formatting.subScript) out.subScript = true;
3463
3502
  if (formatting.smallCaps !== void 0) out.smallCaps = formatting.smallCaps;
3464
3503
  if (formatting.allCaps !== void 0) out.allCaps = formatting.allCaps;
3465
- if (formatting.highlight !== void 0) out.highlight = formatting.highlight;
3504
+ if (formatting.highlight !== void 0) {
3505
+ out.highlight = formatting.highlight;
3506
+ }
3466
3507
  if (formatting.characterSpacingTwentieths !== void 0) {
3467
3508
  out.characterSpacing = formatting.characterSpacingTwentieths;
3468
3509
  }
@@ -3476,7 +3517,10 @@ function runProperties(formatting) {
3476
3517
  }
3477
3518
  function border(value) {
3478
3519
  return {
3479
- style: BORDER_STYLE2[value.style] ?? BorderStyle2.SINGLE,
3520
+ // OOXML's word, which is what docx.js's `BorderStyle` values are. A theme
3521
+ // may state any of them; mapping the unlisted ones to `single` drew a
3522
+ // `wave` or `triple` rule as a plain line here and as asked on office-open.
3523
+ style: value.style,
3480
3524
  ...value.sizeEighthPoints !== void 0 ? { size: value.sizeEighthPoints } : {},
3481
3525
  ...value.color ? { color: value.color.hex } : {},
3482
3526
  ...value.spacePoints !== void 0 ? { space: value.spacePoints } : {}
@@ -3589,19 +3633,10 @@ function emitStyles(styles) {
3589
3633
  }
3590
3634
  };
3591
3635
  }
3592
- var BORDER_STYLE2;
3593
3636
  var init_styles2 = __esm({
3594
3637
  "src/renderers/docxjs/styles.ts"() {
3595
3638
  "use strict";
3596
3639
  init_emit();
3597
- BORDER_STYLE2 = {
3598
- none: BorderStyle2.NONE,
3599
- single: BorderStyle2.SINGLE,
3600
- double: BorderStyle2.DOUBLE,
3601
- dashed: BorderStyle2.DASHED,
3602
- dotted: BorderStyle2.DOTTED,
3603
- thick: BorderStyle2.THICK
3604
- };
3605
3640
  }
3606
3641
  });
3607
3642
 
@@ -3780,7 +3815,7 @@ import {
3780
3815
  Header,
3781
3816
  ImageRun,
3782
3817
  Packer,
3783
- LineRuleType as LineRuleType2,
3818
+ LineRuleType,
3784
3819
  Paragraph as Paragraph2
3785
3820
  } from "docx";
3786
3821
  function createDocxJsRenderer() {
@@ -4067,7 +4102,7 @@ function lastBlockIsFrame(section2) {
4067
4102
  function anchorParagraph(anchor) {
4068
4103
  return new Paragraph2({
4069
4104
  children: anchor ? [anchor] : [],
4070
- spacing: { before: 0, after: 0, line: 20, lineRule: LineRuleType2.EXACT }
4105
+ spacing: { before: 0, after: 0, line: 20, lineRule: LineRuleType.EXACT }
4071
4106
  });
4072
4107
  }
4073
4108
  function coreProperties(ir) {
@@ -4260,10 +4295,17 @@ function runProperties2(formatting) {
4260
4295
  if (formatting.fontFamily) out.font = formatting.fontFamily;
4261
4296
  if (formatting.sizeHalfPoints !== void 0) {
4262
4297
  out.size = formatting.sizeHalfPoints / 2;
4298
+ if (formatting.sizeHalfPoints) out.sizeComplexScript = out.size;
4263
4299
  }
4264
4300
  if (formatting.color) out.color = formatting.color.hex;
4265
- if (formatting.bold !== void 0) out.bold = formatting.bold;
4266
- if (formatting.italic !== void 0) out.italic = formatting.italic;
4301
+ if (formatting.bold !== void 0) {
4302
+ out.bold = formatting.bold;
4303
+ out.boldComplexScript = formatting.bold;
4304
+ }
4305
+ if (formatting.italic !== void 0) {
4306
+ out.italic = formatting.italic;
4307
+ out.italicComplexScript = formatting.italic;
4308
+ }
4267
4309
  if (formatting.underline) {
4268
4310
  out.underline = {
4269
4311
  type: formatting.underline.type,
@@ -4819,10 +4861,9 @@ function table(value, ctx) {
4819
4861
  },
4820
4862
  layout: value.layout,
4821
4863
  // An empty grid is a table with nothing to say about its columns, which is
4822
- // not the same as one whose columns are all zero wide.
4823
- ...value.columnGrid.values.length > 0 ? {
4824
- columnWidths: value.columnGrid.unit === "twips" ? value.columnGrid.values.map(Math.floor) : value.columnGrid.values
4825
- } : {},
4864
+ // not the same as one whose columns are all zero wide. The compiler hands
4865
+ // over every grid in twips; floored for the same reason as the width.
4866
+ ...value.columnGrid.values.length > 0 ? { columnWidths: value.columnGrid.values.map(Math.floor) } : {},
4826
4867
  ...value.alignment ? { alignment: alignment(value.alignment) } : {},
4827
4868
  ...value.borders ? { borders: borders2(value.borders) } : {},
4828
4869
  ...value.cellMargins ? { margins: cellMargins(value.cellMargins) } : {},
@@ -4956,7 +4997,13 @@ function section(value, ctx, closesDocument = false) {
4956
4997
  }))
4957
4998
  } : {}
4958
4999
  }
4959
- } : {}
5000
+ } : {},
5001
+ // No document grid, as the IR states none. Left to the backend, every
5002
+ // section gets the one Word's Chinese template sets — a 15.6pt line grid
5003
+ // (`w:type="lines"`, pitch 312) — and every line is laid out on it here
5004
+ // but at its own height on docx.js, which writes no grid type. A field
5005
+ // the backend is not given takes that default, so all three are stated.
5006
+ grid: { type: "default", linePitch: 360, charSpace: 0 }
4960
5007
  },
4961
5008
  children: sectionChildren2(value, ctx, closesDocument),
4962
5009
  ...value.headers ? { headers: headerFooterSet(value.headers, ctx) } : {},
@@ -5041,12 +5088,11 @@ function builtIn2(style) {
5041
5088
  };
5042
5089
  }
5043
5090
  function emitStyles2(styles) {
5044
- const documentDefaults = {
5045
- ...Object.keys(styles.defaults.run).length > 0 ? { run: runProperties2(styles.defaults.run) } : {},
5046
- ...Object.keys(styles.defaults.paragraph).length > 0 ? { paragraph: paragraphProperties2(styles.defaults.paragraph) } : {}
5047
- };
5048
5091
  const defaults = {
5049
- ...Object.keys(documentDefaults).length > 0 ? { document: documentDefaults } : {}
5092
+ document: {
5093
+ run: Object.keys(styles.defaults.run).length > 0 ? runProperties2(styles.defaults.run) : null,
5094
+ paragraph: Object.keys(styles.defaults.paragraph).length > 0 ? paragraphProperties2(styles.defaults.paragraph) : null
5095
+ }
5050
5096
  };
5051
5097
  for (const slot of [
5052
5098
  "footnoteText",
@@ -5075,7 +5121,7 @@ function emitStyles2(styles) {
5075
5121
  run: runProperties2(style.run)
5076
5122
  }))
5077
5123
  } : {},
5078
- ...Object.keys(defaults).length > 0 ? { default: defaults } : {}
5124
+ default: defaults
5079
5125
  };
5080
5126
  }
5081
5127
  var init_styles3 = __esm({
@@ -6023,7 +6069,7 @@ import {
6023
6069
 
6024
6070
  // src/components/highcharts.ts
6025
6071
  init_colorUtils();
6026
- init_layoutUtils();
6072
+ init_widthUtils();
6027
6073
  import {
6028
6074
  chartFamilyResolver,
6029
6075
  remoteExportNotice,
@@ -6134,8 +6180,7 @@ function placedWidthPt(config, theme) {
6134
6180
  const chart = config.options.chart;
6135
6181
  if (typeof width === "number") return width * POINTS_PER_PIXEL;
6136
6182
  if (typeof width === "string") {
6137
- const page = getPageSetup(theme);
6138
- const contentWidthPt = (page.size.width - page.margin.left - page.margin.right) * POINTS_PER_TWIP;
6183
+ const contentWidthPt = getAvailableWidthTwips(theme) * POINTS_PER_TWIP;
6139
6184
  return parseFloat(width) / 100 * contentWidthPt;
6140
6185
  }
6141
6186
  if (typeof height === "number" && chart.height > 0) {
@@ -6899,6 +6944,7 @@ function resolveColors(entries, at, deps) {
6899
6944
 
6900
6945
  // src/styles/themeToStyles.ts
6901
6946
  init_themes();
6947
+ init_types();
6902
6948
  init_colorUtils();
6903
6949
  init_styleHelpers();
6904
6950
  import {
@@ -7065,10 +7111,13 @@ function convertParagraphProperties(merged, styleProps, theme) {
7065
7111
  }
7066
7112
  };
7067
7113
  }
7114
+ function themeBorderStyle(style) {
7115
+ return DOCX_IR_BORDER_STYLES.includes(style) ? style : "single";
7116
+ }
7068
7117
  function convertBorders(borders3, theme) {
7069
7118
  if (!borders3) return void 0;
7070
7119
  const mapSide = (side) => side ? {
7071
- style: side.style,
7120
+ style: themeBorderStyle(side.style),
7072
7121
  sizeEighthPoints: side.size,
7073
7122
  color: { hex: resolveColor(side.color, theme) },
7074
7123
  ...side.space !== void 0 ? { spacePoints: side.space } : {}
@@ -8255,7 +8304,11 @@ function resolveTableModel(source, theme, themeName, options = {}) {
8255
8304
  });
8256
8305
  adjudicateInteriorEdges([...hasHeader ? [header] : [], ...rows]);
8257
8306
  return {
8258
- ...resolveWidths(source, columns, theme, themeName),
8307
+ ...resolveWidths(
8308
+ source,
8309
+ columns,
8310
+ options.measureTwips ?? getAvailableWidthTwips(theme, themeName)
8311
+ ),
8259
8312
  ...hasHeader ? { header } : {},
8260
8313
  rows,
8261
8314
  repeatHeader: source.repeatHeaderOnPageBreak ?? true
@@ -8309,22 +8362,24 @@ function adjudicateInteriorEdges(rows) {
8309
8362
  });
8310
8363
  });
8311
8364
  }
8312
- function resolveWidths(source, columns, theme, themeName) {
8365
+ function resolveWidths(source, columns, measureTwips) {
8313
8366
  const hasExplicitWidths = columns.some((col) => col.width !== void 0);
8314
8367
  if (!hasExplicitWidths) {
8315
- const share = 100 / columns.length;
8368
+ const percent = source.width ?? 100;
8316
8369
  return {
8317
- columnGrid: { unit: "percent", values: columns.map(() => share) },
8318
- width: { size: source.width ?? 100, unit: "percent" }
8370
+ columnGrid: {
8371
+ unit: "twips",
8372
+ values: splitTwips(columns.length, measureTwips * percent / 100)
8373
+ },
8374
+ width: { size: percent, unit: "percent" }
8319
8375
  };
8320
8376
  }
8321
- const available = getAvailableWidthTwips(theme, themeName);
8322
8377
  const stated = columns.map(
8323
- (col) => col.width !== void 0 ? relativeLengthToTwips(col.width, available) : void 0
8378
+ (col) => col.width !== void 0 ? relativeLengthToTwips(col.width, measureTwips) : void 0
8324
8379
  );
8325
8380
  const totalStated = stated.reduce((sum, w) => sum + (w ?? 0), 0);
8326
8381
  const unstatedCount = columns.filter((col) => col.width === void 0).length;
8327
- const remaining = Math.max(0, available - totalStated);
8382
+ const remaining = Math.max(0, measureTwips - totalStated);
8328
8383
  const shareOfRemainder = unstatedCount > 0 ? remaining / unstatedCount : pointsToTwips(72);
8329
8384
  const values = stated.map((w) => w || shareOfRemainder);
8330
8385
  return {
@@ -8333,7 +8388,7 @@ function resolveWidths(source, columns, theme, themeName) {
8333
8388
  size: values.reduce((sum, w) => sum + w, 0),
8334
8389
  unit: "twips"
8335
8390
  },
8336
- ...totalStated > available ? { overflow: { totalTwips: totalStated, availableTwips: available } } : {}
8391
+ ...totalStated > measureTwips ? { overflow: { totalTwips: totalStated, availableTwips: measureTwips } } : {}
8337
8392
  };
8338
8393
  }
8339
8394
 
@@ -9049,6 +9104,36 @@ function emptyToUndefined(formatting) {
9049
9104
 
9050
9105
  // src/ir/compiler.ts
9051
9106
  init_types();
9107
+
9108
+ // src/ir/measure.ts
9109
+ var DEFAULT_COLUMN_SPACE_TWIPS = 720;
9110
+ function textWidthTwips(page) {
9111
+ const { leftTwips, rightTwips, gutterTwips = 0 } = page.margins;
9112
+ return Math.max(0, page.widthTwips - leftTwips - rightTwips - gutterTwips);
9113
+ }
9114
+ function sectionMeasureTwips(properties) {
9115
+ const textWidth = textWidthTwips(properties.page);
9116
+ const columns = properties.columns;
9117
+ if (!columns || columns.count <= 1) return textWidth;
9118
+ if (columns.equalWidth !== true && columns.widths?.length) {
9119
+ return Math.min(...columns.widths.map((column) => column.widthTwips));
9120
+ }
9121
+ const space = columns.spaceTwips ?? DEFAULT_COLUMN_SPACE_TWIPS;
9122
+ return Math.max(0, (textWidth - space * (columns.count - 1)) / columns.count);
9123
+ }
9124
+ function cellMeasureTwips(widthTwips, margins) {
9125
+ return Math.max(
9126
+ 0,
9127
+ widthTwips - (margins?.leftTwips ?? 0) - (margins?.rightTwips ?? 0)
9128
+ );
9129
+ }
9130
+ function tableWidthTwips(width, measureTwips) {
9131
+ if (width.kind === "twips") return width.value;
9132
+ if (width.kind === "percent") return measureTwips * width.value / 100;
9133
+ return measureTwips;
9134
+ }
9135
+
9136
+ // src/ir/compiler.ts
9052
9137
  init_units();
9053
9138
  var CONTENT_BOOKMARK_ID_BASE = 2e6;
9054
9139
  var SINGLE_LINE_TWIPS = 240;
@@ -9249,6 +9334,42 @@ function compileSectionBody(section2, index, ordinal, chrome, ctx) {
9249
9334
  if (column && column.count > 1) {
9250
9335
  ctx.features.require("columns", `${path4}.properties.columns`);
9251
9336
  }
9337
+ const properties = {
9338
+ page: {
9339
+ widthTwips: page.size.width,
9340
+ heightTwips: page.size.height,
9341
+ orientation: page.size.width > page.size.height ? "landscape" : "portrait",
9342
+ ...page.size.code !== void 0 ? { code: page.size.code } : {},
9343
+ margins: {
9344
+ topTwips: page.margin.top,
9345
+ bottomTwips: page.margin.bottom,
9346
+ leftTwips: page.margin.left,
9347
+ rightTwips: page.margin.right,
9348
+ ...page.margin.header !== void 0 ? { headerTwips: page.margin.header } : {},
9349
+ ...page.margin.footer !== void 0 ? { footerTwips: page.margin.footer } : {},
9350
+ ...page.margin.gutter !== void 0 ? { gutterTwips: page.margin.gutter } : {}
9351
+ }
9352
+ },
9353
+ // A chunk that starts on a new page says so; the rest continue the flow.
9354
+ // The layout stage already decided which, so it is carried rather than
9355
+ // re-derived from `breakBefore`: a section can be continuous without the
9356
+ // two agreeing.
9357
+ ...section2.properties.type ? { type: sectionType(section2.properties.type) } : {},
9358
+ ...column ? {
9359
+ columns: {
9360
+ count: column.count,
9361
+ ...column.space !== void 0 ? { spaceTwips: column.space } : {},
9362
+ ...column.equalWidth !== void 0 ? { equalWidth: column.equalWidth } : {},
9363
+ ...column.widths ? {
9364
+ widths: column.widths.map((c) => ({
9365
+ widthTwips: c.width,
9366
+ ...c.space !== void 0 ? { spaceTwips: c.space } : {}
9367
+ }))
9368
+ } : {}
9369
+ }
9370
+ } : {}
9371
+ };
9372
+ const measureTwips = sectionMeasureTwips(properties);
9252
9373
  const children = [];
9253
9374
  const sectionBookmarkName = section2.belongsToUserSection && ordinal.ordinal !== void 0 ? `_Section_${ordinal.ordinal}` : void 0;
9254
9375
  section2.components.forEach((component, i) => {
@@ -9258,6 +9379,7 @@ function compileSectionBody(section2, index, ordinal, chrome, ctx) {
9258
9379
  ctx,
9259
9380
  path: `${path4}.children[${i}]`,
9260
9381
  id: blockId(index, [i]),
9382
+ measureTwips,
9261
9383
  ...sectionBookmarkName ? { sectionBookmarkName } : {}
9262
9384
  })
9263
9385
  );
@@ -9270,41 +9392,7 @@ function compileSectionBody(section2, index, ordinal, chrome, ctx) {
9270
9392
  id: `s${index}`,
9271
9393
  path: path4,
9272
9394
  children,
9273
- properties: {
9274
- page: {
9275
- widthTwips: page.size.width,
9276
- heightTwips: page.size.height,
9277
- orientation: page.size.width > page.size.height ? "landscape" : "portrait",
9278
- ...page.size.code !== void 0 ? { code: page.size.code } : {},
9279
- margins: {
9280
- topTwips: page.margin.top,
9281
- bottomTwips: page.margin.bottom,
9282
- leftTwips: page.margin.left,
9283
- rightTwips: page.margin.right,
9284
- ...page.margin.header !== void 0 ? { headerTwips: page.margin.header } : {},
9285
- ...page.margin.footer !== void 0 ? { footerTwips: page.margin.footer } : {},
9286
- ...page.margin.gutter !== void 0 ? { gutterTwips: page.margin.gutter } : {}
9287
- }
9288
- },
9289
- // A chunk that starts on a new page says so; the rest continue the flow.
9290
- // The layout stage already decided which, so it is carried rather than
9291
- // re-derived from `breakBefore`: a section can be continuous without the
9292
- // two agreeing.
9293
- ...section2.properties.type ? { type: sectionType(section2.properties.type) } : {},
9294
- ...column ? {
9295
- columns: {
9296
- count: column.count,
9297
- ...column.space !== void 0 ? { spaceTwips: column.space } : {},
9298
- ...column.equalWidth !== void 0 ? { equalWidth: column.equalWidth } : {},
9299
- ...column.widths ? {
9300
- widths: column.widths.map((c) => ({
9301
- widthTwips: c.width,
9302
- ...c.space !== void 0 ? { spaceTwips: c.space } : {}
9303
- }))
9304
- } : {}
9305
- }
9306
- } : {}
9307
- }
9395
+ properties
9308
9396
  };
9309
9397
  if (ordinal.ordinal !== void 0) {
9310
9398
  compiled.bookmark = {
@@ -9315,9 +9403,22 @@ function compileSectionBody(section2, index, ordinal, chrome, ctx) {
9315
9403
  };
9316
9404
  ctx.features.require("bookmarks", `${path4}.bookmark`);
9317
9405
  }
9318
- const headers = compilePart(chrome.header, "header", index, ctx);
9406
+ const chromeMeasureTwips = textWidthTwips(properties.page);
9407
+ const headers = compilePart(
9408
+ chrome.header,
9409
+ "header",
9410
+ index,
9411
+ chromeMeasureTwips,
9412
+ ctx
9413
+ );
9319
9414
  if (headers) compiled.headers = { default: headers };
9320
- const footers = compilePart(chrome.footer, "footer", index, ctx);
9415
+ const footers = compilePart(
9416
+ chrome.footer,
9417
+ "footer",
9418
+ index,
9419
+ chromeMeasureTwips,
9420
+ ctx
9421
+ );
9321
9422
  if (footers) compiled.footers = { default: footers };
9322
9423
  if (headers || footers) {
9323
9424
  ctx.features.require("headers-footers", `${path4}.headers`);
@@ -9336,7 +9437,7 @@ function sectionType(value) {
9336
9437
  return void 0;
9337
9438
  }
9338
9439
  }
9339
- function compilePart(part, kind, sectionIndex, ctx) {
9440
+ function compilePart(part, kind, sectionIndex, measureTwips, ctx) {
9340
9441
  if (!part) return void 0;
9341
9442
  const id = `${kind}:s${sectionIndex}:default`;
9342
9443
  const children = [];
@@ -9347,7 +9448,8 @@ function compilePart(part, kind, sectionIndex, ctx) {
9347
9448
  const scope = {
9348
9449
  ctx,
9349
9450
  path: `sections[${sectionIndex}].${kind}s.default.children[${i}]`,
9350
- id: headerFooterBlockId(id, [i])
9451
+ id: headerFooterBlockId(id, [i]),
9452
+ measureTwips
9351
9453
  };
9352
9454
  children.push(
9353
9455
  ...component.name === "paragraph" ? compileChromeParagraph(component, scope) : component.name === "image" ? compileChromeImage(component, scope) : compileComponent(component, scope)
@@ -9423,9 +9525,7 @@ function compileChromeImage(component, scope) {
9423
9525
  if (mediaType === "svg") ctx.features.require("svg-images", path4);
9424
9526
  const page = getPageSetup(ctx.theme);
9425
9527
  const pageWidthPx = Math.round(twipsToPixels(page.size.width));
9426
- const contentWidthPx = Math.round(
9427
- twipsToPixels(page.size.width - page.margin.left - page.margin.right)
9428
- );
9528
+ const contentWidthPx = Math.round(twipsToPixels(scope.measureTwips));
9429
9529
  const pageHeightPx = Math.round(twipsToPixels(page.size.height));
9430
9530
  const contentHeightPx = Math.round(
9431
9531
  twipsToPixels(page.size.height - page.margin.top - page.margin.bottom)
@@ -9633,7 +9733,7 @@ function compileColumns(component, scope) {
9633
9733
  const props = component.props ?? {};
9634
9734
  const configs = columnConfigs(props.columns);
9635
9735
  if (configs.length === 0) return [];
9636
- const available = getAvailableWidthTwips(ctx.theme, ctx.themeName);
9736
+ const available = scope.measureTwips;
9637
9737
  const { widths, gaps } = columnMetrics(configs, props.gap, available);
9638
9738
  const stated = widths.map(
9639
9739
  (width, index) => width + gaps[index] / 2 + (index > 0 ? gaps[index - 1] / 2 : 0)
@@ -9662,11 +9762,18 @@ function compileColumns(component, scope) {
9662
9762
  rows: [
9663
9763
  {
9664
9764
  cells: configs.map((_, index) => {
9765
+ const margins = {
9766
+ topTwips: 0,
9767
+ rightTwips: gaps[index] / 2,
9768
+ bottomTwips: 0,
9769
+ leftTwips: index > 0 ? gaps[index - 1] / 2 : 0
9770
+ };
9665
9771
  const blocks = contents[index].flatMap(
9666
9772
  (child, childIndex) => compileComponent(child, {
9667
9773
  ...scope,
9668
9774
  path: `${path4}.children[${index}][${childIndex}]`,
9669
- id: `${scope.id}:c${index}:${childIndex}`
9775
+ id: `${scope.id}:c${index}:${childIndex}`,
9776
+ measureTwips: cellMeasureTwips(cells[index], margins)
9670
9777
  })
9671
9778
  );
9672
9779
  return {
@@ -9681,12 +9788,7 @@ function compileColumns(component, scope) {
9681
9788
  }
9682
9789
  ],
9683
9790
  widthTwips: cells[index],
9684
- margins: {
9685
- topTwips: 0,
9686
- rightTwips: gaps[index] / 2,
9687
- bottomTwips: 0,
9688
- leftTwips: index > 0 ? gaps[index - 1] / 2 : 0
9689
- },
9791
+ margins,
9690
9792
  verticalAlign: "top",
9691
9793
  borders: {
9692
9794
  top: NO_BORDERS.top,
@@ -9743,6 +9845,16 @@ var DEFAULT_TEXT_BOX_WIDTH_TWIPS = 5e3;
9743
9845
  function compileTextBox(component, scope) {
9744
9846
  const { ctx, path: path4 } = scope;
9745
9847
  const props = component.props ?? {};
9848
+ const style = props.style;
9849
+ const padding = style?.padding;
9850
+ const width = textBoxWidth(props);
9851
+ const widthTwips = Math.round(tableWidthTwips(width, scope.measureTwips));
9852
+ const margins = {
9853
+ topTwips: padding?.top ? pointsToTwips2(padding.top) : 0,
9854
+ rightTwips: padding?.right ? pointsToTwips2(padding.right) : 0,
9855
+ bottomTwips: padding?.bottom ? pointsToTwips2(padding.bottom) : 0,
9856
+ leftTwips: padding?.left ? pointsToTwips2(padding.left) : 0
9857
+ };
9746
9858
  const children = [];
9747
9859
  const contents = component.children ?? [];
9748
9860
  contents.forEach((child, index) => {
@@ -9750,12 +9862,12 @@ function compileTextBox(component, scope) {
9750
9862
  ...compileComponent(child, {
9751
9863
  ...scope,
9752
9864
  path: `${path4}.children[${index}]`,
9753
- id: `${scope.id}:c${index}`
9865
+ id: `${scope.id}:c${index}`,
9866
+ // What the box holds is set against the box less its padding.
9867
+ measureTwips: cellMeasureTwips(widthTwips, margins)
9754
9868
  })
9755
9869
  );
9756
9870
  });
9757
- const style = props.style;
9758
- const padding = style?.padding;
9759
9871
  if (props.renderAs === "shape") {
9760
9872
  const shape = compileShape2(props, children, scope);
9761
9873
  if (shape) return shape;
@@ -9767,9 +9879,11 @@ function compileTextBox(component, scope) {
9767
9879
  kind: "table",
9768
9880
  id: scope.id,
9769
9881
  path: path4,
9770
- // No grid: one cell, whose width the table itself decides.
9771
- columnGrid: { unit: "twips", values: [] },
9772
- width: textBoxWidth(props),
9882
+ // One cell, as wide as the box. Left out, the grid would be each
9883
+ // backend's 100-twip placeholder, which a reader that takes the grid as
9884
+ // the column widths draws.
9885
+ columnGrid: { unit: "twips", values: [widthTwips] },
9886
+ width,
9773
9887
  layout: "fixed",
9774
9888
  // The container is invisible; whatever border the author asked for is
9775
9889
  // drawn by the cell inside it.
@@ -9789,12 +9903,7 @@ function compileTextBox(component, scope) {
9789
9903
  children: []
9790
9904
  }
9791
9905
  ],
9792
- margins: {
9793
- topTwips: padding?.top ? pointsToTwips2(padding.top) : 0,
9794
- rightTwips: padding?.right ? pointsToTwips2(padding.right) : 0,
9795
- bottomTwips: padding?.bottom ? pointsToTwips2(padding.bottom) : 0,
9796
- leftTwips: padding?.left ? pointsToTwips2(padding.left) : 0
9797
- },
9906
+ margins,
9798
9907
  ...style?.shading?.fill ? {
9799
9908
  shading: {
9800
9909
  fill: irColor(
@@ -9813,8 +9922,11 @@ function compileTextBox(component, scope) {
9813
9922
  var EMU_PER_PIXEL = 9525;
9814
9923
  function compileShape2(props, children, scope) {
9815
9924
  const { ctx, path: path4 } = scope;
9816
- const width = shapeSize(props.width, "width", ctx);
9817
- const height = shapeSize(props.height, "height", ctx);
9925
+ const width = shapeSize(props.width, scope.measureTwips);
9926
+ const height = shapeSize(
9927
+ props.height,
9928
+ getAvailableHeightTwips(ctx.theme, ctx.themeName)
9929
+ );
9818
9930
  if (width.pixels === void 0 || height.pixels === void 0) {
9819
9931
  warnOnce(
9820
9932
  ctx,
@@ -9845,7 +9957,7 @@ function compileShape2(props, children, scope) {
9845
9957
  warnOnce(
9846
9958
  ctx,
9847
9959
  "text-box",
9848
- '[core-docx] text-box renderAs "shape" resolves percentage sizes at generation time, against the current page content box; the shape will not reflow if the page size changes.'
9960
+ '[core-docx] text-box renderAs "shape" resolves percentage sizes at generation time \u2014 a width against what holds it, a height against the page \u2014 so the shape will not reflow if either changes.'
9849
9961
  );
9850
9962
  }
9851
9963
  if (outline.ignoredSides.length > 0) {
@@ -9890,7 +10002,7 @@ function compileShape2(props, children, scope) {
9890
10002
  }
9891
10003
  ];
9892
10004
  }
9893
- function shapeSize(value, axis, ctx) {
10005
+ function shapeSize(value, referenceTwips) {
9894
10006
  if (typeof value === "number") {
9895
10007
  return { pixels: Math.round(value), resolvedPercentage: false };
9896
10008
  }
@@ -9899,9 +10011,8 @@ function shapeSize(value, axis, ctx) {
9899
10011
  if (!Number.isFinite(fraction) || fraction <= 0) {
9900
10012
  return { resolvedPercentage: false };
9901
10013
  }
9902
- const availableTwips = axis === "width" ? getAvailableWidthTwips(ctx.theme, ctx.themeName) : getAvailableHeightTwips(ctx.theme, ctx.themeName);
9903
10014
  return {
9904
- pixels: Math.round(availableTwips * fraction / TWIPS_PER_PIXEL),
10015
+ pixels: Math.round(referenceTwips * fraction / TWIPS_PER_PIXEL),
9905
10016
  resolvedPercentage: true
9906
10017
  };
9907
10018
  }
@@ -9976,10 +10087,20 @@ function textBoxWidth(props) {
9976
10087
  value: typeof raw === "number" ? raw * TWIPS_PER_PIXEL : DEFAULT_TEXT_BOX_WIDTH_TWIPS
9977
10088
  };
9978
10089
  }
10090
+ function borderLineStyle(authored) {
10091
+ switch (authored) {
10092
+ case "dashed":
10093
+ case "dotted":
10094
+ case "double":
10095
+ return authored;
10096
+ default:
10097
+ return "single";
10098
+ }
10099
+ }
9979
10100
  function compileBorders(border3, ctx) {
9980
10101
  if (!border3) return void 0;
9981
10102
  const side = (value) => value ? {
9982
- style: String(value.style ?? "single"),
10103
+ style: value.style === "none" ? "none" : borderLineStyle(value.style),
9983
10104
  // Points to eighths of a point, never thinner than the hairline a
9984
10105
  // reader can actually see.
9985
10106
  sizeEighthPoints: value.width !== void 0 ? Math.max(1, Math.round(value.width * 8)) : 1,
@@ -10083,12 +10204,6 @@ function compileToc(component, scope) {
10083
10204
  var DEFAULT_DIVIDER_SPACING_PT = 6;
10084
10205
  var DEFAULT_DIVIDER_THICKNESS_PT = 1;
10085
10206
  var DIVIDER_LINE_TWIPS = 20;
10086
- var DIVIDER_BORDER_STYLE = {
10087
- solid: "single",
10088
- dashed: "dashed",
10089
- dotted: "dotted",
10090
- double: "double"
10091
- };
10092
10207
  function compileDivider(component, scope) {
10093
10208
  const { ctx, path: path4 } = scope;
10094
10209
  const props = component.props ?? {};
@@ -10117,10 +10232,10 @@ function compileDivider(component, scope) {
10117
10232
  lineTwips: DIVIDER_LINE_TWIPS,
10118
10233
  lineRule: "exact"
10119
10234
  },
10120
- ...dividerIndent(props, ctx, path4),
10235
+ ...dividerIndent(props, scope),
10121
10236
  borders: {
10122
10237
  bottom: {
10123
- style: DIVIDER_BORDER_STYLE[String(props.style)] ?? "single",
10238
+ style: borderLineStyle(props.style),
10124
10239
  sizeEighthPoints: pointsToEighthPoints(thicknessPt),
10125
10240
  color: irColor(
10126
10241
  resolveColor(String(props.color ?? "border"), ctx.theme)
@@ -10134,14 +10249,10 @@ function compileDivider(component, scope) {
10134
10249
  }
10135
10250
  ];
10136
10251
  }
10137
- function dividerIndent(props, ctx, path4) {
10252
+ function dividerIndent(props, scope) {
10253
+ const { ctx, path: path4, measureTwips } = scope;
10138
10254
  const width = props.width;
10139
10255
  if (width === void 0) return {};
10140
- const page = getPageSetup(ctx.theme);
10141
- const measureTwips = Math.max(
10142
- 0,
10143
- page.size.width - page.margin.left - page.margin.right
10144
- );
10145
10256
  let usedTwips;
10146
10257
  if (typeof width === "number" && Number.isFinite(width)) {
10147
10258
  usedTwips = pointsToTwips2(width);
@@ -10297,7 +10408,7 @@ function compileList(component, scope, referencePrefix = "list", explicitLevels)
10297
10408
  }
10298
10409
  blocks.push(
10299
10410
  paragraphNode(
10300
- { ctx, path: itemPath, id: `${scope.id}:i${index}` },
10411
+ { ...scope, path: itemPath, id: `${scope.id}:i${index}` },
10301
10412
  revision === void 0 ? parseInline(text, {
10302
10413
  base,
10303
10414
  hyperlinks: true,
@@ -10944,7 +11055,7 @@ function compileVisual(component, scope) {
10944
11055
  );
10945
11056
  if (!group) return [];
10946
11057
  const size = visualPlacementPixels(props, group.canvas, {
10947
- widthPx: Math.round(twipsToPixels(getAvailableWidthTwips(ctx.theme))),
11058
+ widthPx: Math.round(twipsToPixels(scope.measureTwips)),
10948
11059
  heightPx: Math.round(twipsToPixels(getAvailableHeightTwips(ctx.theme)))
10949
11060
  });
10950
11061
  const drawing = {
@@ -11059,7 +11170,7 @@ function compileImage2(component, scope) {
11059
11170
  `Alt text is not written to the document: the DOCX pipeline has never emitted \`wp:docPr\` descriptions, so the image at ${path4} will have none. The text is preserved in the IR.`
11060
11171
  );
11061
11172
  }
11062
- const size = imagePixelSize(props, loaded, ctx);
11173
+ const size = imagePixelSize(props, loaded, scope);
11063
11174
  const resourceId = declareResource(loaded, mediaType, ctx);
11064
11175
  const image = {
11065
11176
  kind: "image",
@@ -11169,8 +11280,7 @@ function compileChart(component, scope) {
11169
11280
  return [];
11170
11281
  }
11171
11282
  });
11172
- const page = getPageSetup(ctx.theme);
11173
- const contentWidthInches = (page.size.width - page.margin.left - page.margin.right) / 1440;
11283
+ const contentWidthInches = scope.measureTwips / 1440;
11174
11284
  const widthInches = typeof props.width === "number" ? props.width : contentWidthInches;
11175
11285
  const heightInches = typeof props.height === "number" ? props.height : DEFAULT_CHART_HEIGHT_INCHES;
11176
11286
  const chart = {
@@ -11270,12 +11380,13 @@ function wrapType(value) {
11270
11380
  return "square";
11271
11381
  }
11272
11382
  }
11273
- function imagePixelSize(props, loaded, ctx) {
11383
+ function imagePixelSize(props, loaded, scope) {
11384
+ const { ctx } = scope;
11274
11385
  const widthRef = props.widthRelativeTo === "page" ? "page" : "content";
11275
11386
  const heightRef = props.heightRelativeTo === "page" ? "page" : "content";
11276
11387
  const availableWidthPx = Math.round(
11277
11388
  twipsToPixels(
11278
- widthRef === "page" ? getPageWidthTwips(ctx.theme) : getAvailableWidthTwips(ctx.theme)
11389
+ widthRef === "page" ? getPageWidthTwips(ctx.theme) : scope.measureTwips
11279
11390
  )
11280
11391
  );
11281
11392
  const availableHeightPx = Math.round(
@@ -11462,7 +11573,10 @@ function compileTable(component, scope) {
11462
11573
  source,
11463
11574
  ctx.theme,
11464
11575
  ctx.themeName,
11465
- { onWarning: (code, message) => warnOnce(ctx, "table", message, code) }
11576
+ {
11577
+ onWarning: (code, message) => warnOnce(ctx, "table", message, code),
11578
+ measureTwips: scope.measureTwips
11579
+ }
11466
11580
  );
11467
11581
  if (model.overflow) {
11468
11582
  warnOnce(
@@ -11480,6 +11594,7 @@ function compileTable(component, scope) {
11480
11594
  ...model.header ? [
11481
11595
  compileTableRow(
11482
11596
  model.header,
11597
+ model.columnGrid.values,
11483
11598
  style.headerParagraph,
11484
11599
  style.tableHeader,
11485
11600
  {
@@ -11492,13 +11607,19 @@ function compileTable(component, scope) {
11492
11607
  )
11493
11608
  ] : [],
11494
11609
  ...model.rows.map(
11495
- (row, index) => compileTableRow(row, style.cellParagraph, style.tableCell, {
11496
- ctx,
11497
- path: `${path4}.rows[${index}]`,
11498
- id: `${scope.id}:r${index}`,
11499
- ...row.tableHeader !== void 0 ? { isHeader: row.tableHeader } : {},
11500
- ...row.cantSplit !== void 0 ? { cantSplit: row.cantSplit } : {}
11501
- })
11610
+ (row, index) => compileTableRow(
11611
+ row,
11612
+ model.columnGrid.values,
11613
+ style.cellParagraph,
11614
+ style.tableCell,
11615
+ {
11616
+ ctx,
11617
+ path: `${path4}.rows[${index}]`,
11618
+ id: `${scope.id}:r${index}`,
11619
+ ...row.tableHeader !== void 0 ? { isHeader: row.tableHeader } : {},
11620
+ ...row.cantSplit !== void 0 ? { cantSplit: row.cantSplit } : {}
11621
+ }
11622
+ )
11502
11623
  )
11503
11624
  ];
11504
11625
  ctx.features.require("tables", path4);
@@ -11576,7 +11697,7 @@ function tableBlocker(model, path4) {
11576
11697
  }
11577
11698
  return void 0;
11578
11699
  }
11579
- function compileTableRow(row, spacing, baseStyle, scope) {
11700
+ function compileTableRow(row, columnTwips, spacing, baseStyle, scope) {
11580
11701
  const { ctx } = scope;
11581
11702
  const rowRevision = row.revision;
11582
11703
  const rowMark = rowRevision ? {
@@ -11596,6 +11717,7 @@ function compileTableRow(row, spacing, baseStyle, scope) {
11596
11717
  cells: row.cells.map(
11597
11718
  (cell, colIndex) => compileTableCell(
11598
11719
  cell,
11720
+ columnTwips[colIndex] ?? 0,
11599
11721
  spacing,
11600
11722
  baseStyle,
11601
11723
  row.keepNext,
@@ -11617,7 +11739,17 @@ function compileTableRow(row, spacing, baseStyle, scope) {
11617
11739
  ...scope.cantSplit !== void 0 ? { cantSplit: scope.cantSplit } : {}
11618
11740
  };
11619
11741
  }
11620
- function compileTableCell(cell, spacing, baseStyle, keepNext, scope, rowRevision, markRevision) {
11742
+ function compileTableCell(cell, columnTwips, spacing, baseStyle, keepNext, partScope, rowRevision, markRevision) {
11743
+ const margins = !cell.missing && cell.padding ? {
11744
+ topTwips: pointsToTwips2(cell.padding.top),
11745
+ bottomTwips: pointsToTwips2(cell.padding.bottom),
11746
+ leftTwips: pointsToTwips2(cell.padding.left),
11747
+ rightTwips: pointsToTwips2(cell.padding.right)
11748
+ } : void 0;
11749
+ const scope = {
11750
+ ...partScope,
11751
+ measureTwips: cellMeasureTwips(columnTwips, margins)
11752
+ };
11621
11753
  const cellLine = compileLineSpacing(cell.font?.lineSpacing);
11622
11754
  const paragraph2 = {
11623
11755
  kind: "paragraph",
@@ -11646,14 +11778,7 @@ function compileTableCell(cell, spacing, baseStyle, keepNext, scope, rowRevision
11646
11778
  ...cell.missing ? {} : {
11647
11779
  verticalAlign: verticalAlign(cell.verticalAlignment),
11648
11780
  ...cell.backgroundColor !== void 0 && cell.backgroundColor !== "transparent" ? { shading: { fill: { hex: cell.backgroundColor } } } : {},
11649
- ...cell.padding ? {
11650
- margins: {
11651
- topTwips: pointsToTwips2(cell.padding.top),
11652
- bottomTwips: pointsToTwips2(cell.padding.bottom),
11653
- leftTwips: pointsToTwips2(cell.padding.left),
11654
- rightTwips: pointsToTwips2(cell.padding.right)
11655
- }
11656
- } : {}
11781
+ ...margins ? { margins } : {}
11657
11782
  },
11658
11783
  borders: {
11659
11784
  top: compileTableBorder(cell.borders.top),
@@ -12847,9 +12972,10 @@ function docxBlockContext(document, theme, path4, sources) {
12847
12972
  page.size ?? theme.page.size
12848
12973
  );
12849
12974
  const overrides = isBlockRecord(page.margins) ? page.margins : {};
12975
+ const gutter = "gutter" in margins ? margins.gutter : 0;
12850
12976
  const width = Object.keys(page).length ? Math.max(
12851
12977
  0,
12852
- dimensions.width - Number(overrides.left ?? margins.left ?? 1440) - Number(overrides.right ?? margins.right ?? 1440)
12978
+ dimensions.width - Number(overrides.left ?? margins.left ?? 1440) - Number(overrides.right ?? margins.right ?? 1440) - Number(overrides.gutter ?? gutter ?? 0)
12853
12979
  ) : getAvailableWidthTwips(theme);
12854
12980
  const height = Object.keys(page).length ? Math.max(
12855
12981
  0,
@@ -13430,7 +13556,7 @@ function pageBox(theme, themeName, pageOverride) {
13430
13556
  return {
13431
13557
  availableWidthTwips: Math.max(
13432
13558
  0,
13433
- page.size.width - page.margin.left - page.margin.right
13559
+ page.size.width - page.margin.left - page.margin.right - (page.margin.gutter ?? 0)
13434
13560
  ),
13435
13561
  pageBottomTwips: page.size.height
13436
13562
  };