@vyaz/core 0.1.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,6 +46,8 @@ console.log(result.lines);
46
46
  - **Writing modes** — `horizontal-tb`, `vertical-rl`, `vertical-lr` with text orientation
47
47
  - **Auto-fit** — scale text proportionally to fit the container (`AutofitConfig`)
48
48
  - **Inline widgets** — embedded objects (icons, images) inside the text flow
49
+ - **`TextRun.data`** — an open-ended metadata bag the layout engine never interprets, for cross-cutting features like a hyperlink's `href` (see `@vyaz/converters`/`@vyaz/renderer`)
50
+ - **Tables** — `TableFrame` grid layout: measured column widths/row heights, `colSpan`/`rowSpan`, per-side borders (solid, dashed, rounded corners), `before`/`after` decorative slots, nested tables
49
51
  - **Office-compatible mode** — `mode: 'office'` for PowerPoint/DrawingML rendering
50
52
  - **Font metrics** — system font registry with fontkit-based metric extraction
51
53
  - **Compiler** — paragraph compilation with token preparation for external renderers
@@ -78,6 +80,40 @@ const result: TextFrameLayoutResult = layoutTextFrame(frame);
78
80
  // → { lines: Line[], frameWidth?, frameHeight?, contentWidth, contentHeight, fitHorizontal, fitVertical }
79
81
  ```
80
82
 
83
+ ### Tables
84
+
85
+ ```ts
86
+ import { layoutTableFrame } from '@vyaz/core';
87
+ import type { TableFrame, TableLayoutResult } from '@vyaz/core';
88
+
89
+ const cell = (text: string) => ({
90
+ content: {
91
+ wrap: true,
92
+ paragraphs: [{
93
+ style: { alignment: 'left', lineHeight: 1.3, spaceBefore: 0, spaceAfter: 0 },
94
+ children: [{ type: 'text', text, fontFamily: 'Arial', fontSize: 14, fontWeight: 'normal', fontStyle: 'normal', color: '#000' }],
95
+ }],
96
+ },
97
+ });
98
+
99
+ const table: TableFrame = {
100
+ defaultCellStyle: { paddings: 8, borderWidths: 1, borderColors: '#ccc' },
101
+ rows: [
102
+ { style: { bgColor: '#eee' }, cells: [cell('Name'), cell('Qty')] },
103
+ { cells: [cell('Widget'), cell('3')] },
104
+ ],
105
+ };
106
+
107
+ const result: TableLayoutResult = layoutTableFrame(table);
108
+ // → { width, height, contentBox, rows: [{ y, height, cells: [{ x, y, width, height, content, ... }] }] }
109
+ ```
110
+
111
+ Column widths and row heights are *measured* from cell content unless
112
+ `columnWidths`/`rowHeights`/`width`/`height` override them. A cell's
113
+ `content` can itself be a `TableFrame` (nested tables). `@vyaz/renderer`'s
114
+ `renderTableToSVG` paints the result — see its README, or the
115
+ [Tables guide](https://sedrew.github.io/vyaz/guide/tables).
116
+
81
117
  ### Autofit
82
118
 
83
119
  ```ts
@@ -19,8 +19,10 @@ export { groupLinesByParagraph } from './utils/groupLinesByParagraph.js';
19
19
  export { layoutTextFrame } from './layout/TextFrameLayoutEngine.js';
20
20
  export { createLayoutEngine } from './layout/create-engine.js';
21
21
  export type { LayoutEngine, LayoutEngineOptions } from './layout/create-engine.js';
22
- export type { LayoutOptions, TextFrameLayoutResult, AutofitOutcome } from './layout/TextFrameLayoutEngine.js';
22
+ export type { LayoutOptions, TextFrameLayoutResult, AutofitOutcome, FrameTransform } from './layout/TextFrameLayoutEngine.js';
23
23
  export type { OnMissingFont } from './layout/resolve-font.js';
24
+ export { layoutTableFrame } from './layout/TableLayoutEngine.js';
25
+ export type { TableLayoutResult, TableRowLayoutResult, TableCellLayoutResult, TableLayoutOptions, ResolvedBorder } from './layout/TableLayoutEngine.js';
24
26
  export { applyScale, findScale } from './layout/AutoFitEngine.js';
25
27
  export { compileParagraph, getParagraphText, makeFontToken, collapseSegmentWhitespace, splitParagraphByHardBreaks } from './compile/ParagraphCompiler.js';
26
28
  export { FontMetricsProvider, fontMetricsProvider } from './measure/FontMetricsProvider.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAEjG,gBAAgB;AAChB,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAI9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACnF,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9G,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAG1J,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAChI,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AACrG,YAAY,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAOnE,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnE,gBAAgB;AAChB,eAAO,MAAM,uBAAuB,EAAE,cAA4B,CAAC;AACnE,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,EAAE,OAAO,CAAC,OAAO,CAAe,CAAC;AAEhE,gBAAgB;AAChB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGzD,gBAAgB;AAChB,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAc,CAAC;AACpE,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAEjG,gBAAgB;AAChB,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAI9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAGzE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACnF,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAC9H,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,YAAY,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGxJ,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAG1J,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAChI,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AACrG,YAAY,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAOnE,OAAO,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnE,gBAAgB;AAChB,eAAO,MAAM,uBAAuB,EAAE,cAA4B,CAAC;AACnE,gBAAgB;AAChB,eAAO,MAAM,kBAAkB,EAAE,OAAO,CAAC,OAAO,CAAe,CAAC;AAEhE,gBAAgB;AAChB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGzD,gBAAgB;AAChB,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAc,CAAC;AACpE,gBAAgB;AAChB,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -20055,7 +20055,7 @@ function positionLines(pretextLines, items, fontMetricsFn, style, maxWidth, star
20055
20055
  const indent = isFirstLine ? effectiveLeftIndent + (style.indent || 0) : effectiveLeftIndent;
20056
20056
  const rightIndent = style.rightIndent || 0;
20057
20057
  const availableWidth = maxWidth - indent - rightIndent;
20058
- const slack = Math.max(0, availableWidth - effectiveLineWidth);
20058
+ const slack = Number.isFinite(availableWidth) ? Math.max(0, availableWidth - effectiveLineWidth) : 0;
20059
20059
  let xOffset = indent;
20060
20060
  if (style.alignment === "center") {
20061
20061
  xOffset = indent + slack / 2;
@@ -22776,7 +22776,16 @@ setProfileChangeHook(clearMeasurementCaches);
22776
22776
  function glyphCacheKey(text, fontSize, fontFamily, fontWeight, fontStyle) {
22777
22777
  return `${fontSize}_${fontFamily || ""}_${fontWeight || ""}_${fontStyle || ""}_${text}`;
22778
22778
  }
22779
+ function inlineWidgetMetrics(iw, fontSize) {
22780
+ const bo = iw.baselineOffset ?? 0;
22781
+ const ascent = Math.max(0, iw.height - bo);
22782
+ const descent = Math.max(0, bo);
22783
+ return { ascent, descent, capHeight: ascent, unitsPerEm: fontSize || 1, sourceTable: "fallback" };
22784
+ }
22779
22785
  function getFontMetricsForItem(item, mode) {
22786
+ if (item.metadata.inlineWidget) {
22787
+ return inlineWidgetMetrics(item.metadata.inlineWidget, item.metadata.effectiveFontSize);
22788
+ }
22780
22789
  return fontMetricsProvider.getMetrics(item.metadata.style.fontFamily, item.metadata.effectiveFontSize, String(item.metadata.style.fontWeight || 400), item.metadata.style.fontStyle || "normal", mode);
22781
22790
  }
22782
22791
  function preparedCacheKey(paragraph) {
@@ -22864,6 +22873,9 @@ class ParagraphLayoutEngine {
22864
22873
  return Math.round(total * 100) / 100;
22865
22874
  };
22866
22875
  const { lines, contentWidth } = positionLines(materializedLines, items, (item) => {
22876
+ if (item.metadata.inlineWidget) {
22877
+ return inlineWidgetMetrics(item.metadata.inlineWidget, item.metadata.effectiveFontSize);
22878
+ }
22867
22879
  if (fontProvider) {
22868
22880
  return fontProvider.getMetrics(item.metadata.style.fontFamily, item.metadata.effectiveFontSize, String(item.metadata.style.fontWeight || 400), item.metadata.style.fontStyle || "normal", renderMode);
22869
22881
  }
@@ -22978,6 +22990,10 @@ function findScale(doc, layoutFn, config, options) {
22978
22990
  }
22979
22991
 
22980
22992
  // src/layout/TextFrameLayoutEngine.ts
22993
+ function normalizeDeg(d) {
22994
+ const r = d % 360;
22995
+ return r < 0 ? r + 360 : r;
22996
+ }
22981
22997
  function getMarkerTextHelper(listStyle, listIndex) {
22982
22998
  if (listStyle.type === "bullet") {
22983
22999
  return listStyle.bulletChar ?? defaultBulletChar(listStyle.level ?? 0);
@@ -23038,11 +23054,13 @@ function runFlow(frame, options, engine) {
23038
23054
  const mode = options.mode;
23039
23055
  const onMissingFont = options.onMissingFont ?? "throw";
23040
23056
  const warnings = [];
23057
+ const writingMode = frame.writingMode ?? "horizontal-tb";
23058
+ const sideways = writingMode === "sideways-rl" || writingMode === "sideways-lr";
23041
23059
  const leftPad = frame.padding?.left ?? 0;
23042
23060
  const rightPad = frame.padding?.right ?? 0;
23043
23061
  const topPad = frame.padding?.top ?? 0;
23044
23062
  const bottomPad = frame.padding?.bottom ?? 0;
23045
- const hasColumns = frame.columns != null && frame.columns.count > 1 && frame.width != null;
23063
+ const hasColumns = !sideways && frame.columns != null && frame.columns.count > 1 && frame.width != null;
23046
23064
  let colWidth;
23047
23065
  let colCount = 1;
23048
23066
  let colGap = 0;
@@ -23133,14 +23151,14 @@ function runFlow(frame, options, engine) {
23133
23151
  for (let i2 = 0;i2 < frame.paragraphs.length; i2++) {
23134
23152
  const p = frame.paragraphs[i2];
23135
23153
  const subParagraphs = splitParagraphByHardBreaks(p);
23136
- const maxWidth = hasColumns ? colWidth : frame.width !== undefined ? frame.width - leftPad - rightPad : Infinity;
23137
- if (frame.wrap === false) {
23138
- p.style = { ...p.style, whiteSpace: "nowrap" };
23139
- }
23154
+ const inlineFrameSize = sideways ? frame.height : frame.width;
23155
+ const inlinePadStart = sideways ? topPad : leftPad;
23156
+ const inlinePadEnd = sideways ? bottomPad : rightPad;
23157
+ const maxWidth = hasColumns ? colWidth : inlineFrameSize !== undefined ? inlineFrameSize - inlinePadStart - inlinePadEnd : Infinity;
23140
23158
  const listIndex = listIndices[i2];
23141
23159
  const listMarkerWidth = listMarkerWidths[i2];
23142
23160
  for (let subIdx = 0;subIdx < subParagraphs.length; subIdx++) {
23143
- const subPara = subParagraphs[subIdx];
23161
+ const subPara = frame.wrap === false && subParagraphs[subIdx].style.whiteSpace !== "nowrap" ? { ...subParagraphs[subIdx], style: { ...subParagraphs[subIdx].style, whiteSpace: "nowrap" } } : subParagraphs[subIdx];
23144
23162
  if (subIdx === 0) {
23145
23163
  if (hasColumns)
23146
23164
  pendingColGap += p.style.spaceBefore;
@@ -23215,18 +23233,32 @@ function runFlow(frame, options, engine) {
23215
23233
  }
23216
23234
  const lastLine = allLines.length > 0 ? allLines[allLines.length - 1] : null;
23217
23235
  const contentHeight = lastLine ? lastLine.y + lastLine.height + bottomPad : bottomPad;
23236
+ const wmRotate = sideways ? writingMode === "sideways-rl" ? 90 : 270 : 0;
23237
+ const rotate = normalizeDeg(wmRotate + (frame.rotation ?? 0));
23238
+ const quarterTurned = rotate === 90 || rotate === 270;
23239
+ const visualContentWidth = quarterTurned ? contentHeight : contentWidth;
23240
+ const visualContentHeight = quarterTurned ? contentWidth : contentHeight;
23241
+ const transform = rotate === 0 ? undefined : {
23242
+ rotate,
23243
+ layoutBox: {
23244
+ width: (sideways ? frame.height : frame.width) ?? contentWidth,
23245
+ height: (sideways ? frame.width : frame.height) ?? contentHeight
23246
+ }
23247
+ };
23218
23248
  return {
23219
23249
  lines: allLines,
23220
- content: { width: contentWidth, height: contentHeight },
23250
+ content: { width: visualContentWidth, height: visualContentHeight },
23221
23251
  frame: { width: frame.width, height: frame.height },
23222
23252
  overflow: {
23223
- horizontal: frame.width !== undefined && contentWidth > frame.width + 0.01,
23224
- vertical: frame.height !== undefined && contentHeight > frame.height + 0.01
23253
+ horizontal: frame.width !== undefined && visualContentWidth > frame.width + 0.01,
23254
+ vertical: frame.height !== undefined && visualContentHeight > frame.height + 0.01
23225
23255
  },
23226
23256
  fit: {
23227
23257
  horizontal: frame.width !== undefined ? "frame" : "content",
23228
23258
  vertical: frame.height !== undefined ? "frame" : "content"
23229
23259
  },
23260
+ writingMode,
23261
+ ...transform ? { transform } : {},
23230
23262
  ...warnings.length ? { warnings } : {}
23231
23263
  };
23232
23264
  }
@@ -23271,6 +23303,382 @@ function createLayoutEngine(options = {}) {
23271
23303
  clearCache: () => pe.clearCache()
23272
23304
  };
23273
23305
  }
23306
+ // src/utils/sides.ts
23307
+ function resolveSide(v, side, fallback) {
23308
+ if (v === undefined)
23309
+ return fallback;
23310
+ if (!Array.isArray(v))
23311
+ return v;
23312
+ if (v.length === 2) {
23313
+ const [tb, lr] = v;
23314
+ return side === "top" || side === "bottom" ? tb : lr;
23315
+ }
23316
+ const [t, r, b, l] = v;
23317
+ return side === "top" ? t : side === "right" ? r : side === "bottom" ? b : l;
23318
+ }
23319
+ function resolveAllSides(v, fallback) {
23320
+ return {
23321
+ top: resolveSide(v, "top", fallback),
23322
+ right: resolveSide(v, "right", fallback),
23323
+ bottom: resolveSide(v, "bottom", fallback),
23324
+ left: resolveSide(v, "left", fallback)
23325
+ };
23326
+ }
23327
+ function resolveWidths(w, fallback = 0) {
23328
+ return resolveAllSides(w, fallback);
23329
+ }
23330
+ function resolveColors(c, fallback = "#000") {
23331
+ return resolveAllSides(c, fallback);
23332
+ }
23333
+ function resolvePatterns(p) {
23334
+ if (p === undefined)
23335
+ return { top: undefined, right: undefined, bottom: undefined, left: undefined };
23336
+ if (p.length === 0 || typeof p[0] === "number") {
23337
+ const flat = p;
23338
+ return { top: flat, right: flat, bottom: flat, left: flat };
23339
+ }
23340
+ const tuples = p;
23341
+ if (tuples.length === 2) {
23342
+ const [tb, lr] = tuples;
23343
+ return { top: tb, right: lr, bottom: tb, left: lr };
23344
+ }
23345
+ const [t, r, b, l] = tuples;
23346
+ return { top: t, right: r, bottom: b, left: l };
23347
+ }
23348
+ function resolveShapes(s, fallback = "butt") {
23349
+ return resolveAllSides(s, fallback);
23350
+ }
23351
+
23352
+ // src/layout/TableLayoutEngine.ts
23353
+ var MAX_NESTED_TABLE_DEPTH = 50;
23354
+ function isNestedTable(content) {
23355
+ return "rows" in content;
23356
+ }
23357
+ function placeholderContentFor(nested) {
23358
+ return {
23359
+ lines: [],
23360
+ content: { width: nested.width, height: nested.height },
23361
+ frame: { width: nested.width, height: nested.height },
23362
+ overflow: { horizontal: false, vertical: false },
23363
+ fit: { horizontal: "content", vertical: "content" },
23364
+ writingMode: "horizontal-tb"
23365
+ };
23366
+ }
23367
+ var DEFAULT_PADDING = 8;
23368
+ function resolveCellStyle(cell, table) {
23369
+ const d = table.defaultCellStyle ?? {};
23370
+ const s = cell.style ?? {};
23371
+ return {
23372
+ bgColor: s.bgColor ?? d.bgColor ?? "",
23373
+ paddings: s.paddings ?? d.paddings ?? DEFAULT_PADDING,
23374
+ verticalAlign: s.verticalAlign ?? d.verticalAlign ?? "top",
23375
+ cx: s.cx ?? d.cx ?? 0,
23376
+ cy: s.cy ?? d.cy ?? 0,
23377
+ allowOverflow: s.allowOverflow ?? d.allowOverflow ?? false,
23378
+ borderWidths: s.borderWidths ?? d.borderWidths,
23379
+ borderColors: s.borderColors ?? d.borderColors,
23380
+ borderPatterns: s.borderPatterns ?? d.borderPatterns,
23381
+ borderShapes: s.borderShapes ?? d.borderShapes,
23382
+ rx: s.rx ?? d.rx,
23383
+ ry: s.ry ?? d.ry
23384
+ };
23385
+ }
23386
+ function resolveRowStyle(row, table) {
23387
+ const d = table.defaultRowStyle ?? {};
23388
+ const s = row.style ?? {};
23389
+ return {
23390
+ height: s.height ?? d.height ?? 0,
23391
+ bgColor: s.bgColor ?? d.bgColor ?? "",
23392
+ borderWidths: s.borderWidths ?? d.borderWidths,
23393
+ borderColors: s.borderColors ?? d.borderColors,
23394
+ borderPatterns: s.borderPatterns ?? d.borderPatterns,
23395
+ borderShapes: s.borderShapes ?? d.borderShapes,
23396
+ rx: s.rx ?? d.rx,
23397
+ ry: s.ry ?? d.ry
23398
+ };
23399
+ }
23400
+ function resolveBorder(raw) {
23401
+ if (!raw)
23402
+ return;
23403
+ const widths = resolveWidths(raw.borderWidths, 0);
23404
+ if (widths.top === 0 && widths.right === 0 && widths.bottom === 0 && widths.left === 0)
23405
+ return;
23406
+ const colors = resolveColors(raw.borderColors, "#000");
23407
+ const border = { widths, colors };
23408
+ if (raw.borderPatterns !== undefined) {
23409
+ const patterns = resolvePatterns(raw.borderPatterns);
23410
+ if (patterns.top?.length || patterns.right?.length || patterns.bottom?.length || patterns.left?.length) {
23411
+ border.patterns = patterns;
23412
+ }
23413
+ }
23414
+ if (raw.borderShapes !== undefined)
23415
+ border.shapes = resolveShapes(raw.borderShapes);
23416
+ if (raw.rx !== undefined || raw.ry !== undefined) {
23417
+ border.rx = raw.rx ?? raw.ry;
23418
+ border.ry = raw.ry ?? raw.rx;
23419
+ }
23420
+ return border;
23421
+ }
23422
+ function verticalOffsetFor(align, available, content) {
23423
+ const extra = available - content;
23424
+ if (extra <= 0)
23425
+ return 0;
23426
+ if (align === "middle")
23427
+ return extra / 2;
23428
+ if (align === "bottom")
23429
+ return extra;
23430
+ return 0;
23431
+ }
23432
+ function sumSpan(arr, start, count, gap) {
23433
+ let sum = 0;
23434
+ for (let i = start;i < start + count; i++)
23435
+ sum += arr[i] ?? 0;
23436
+ return sum + gap * Math.max(0, count - 1);
23437
+ }
23438
+ function placeCells(rows) {
23439
+ const placed = [];
23440
+ const autoLastCell = [];
23441
+ const occupied = new Map;
23442
+ const isOccupied = (r, c) => occupied.get(r)?.has(c) ?? false;
23443
+ const occupy = (r, c) => {
23444
+ let set = occupied.get(r);
23445
+ if (!set)
23446
+ occupied.set(r, set = new Set);
23447
+ set.add(c);
23448
+ };
23449
+ let colCount = 0;
23450
+ for (let ri = 0;ri < rows.length; ri++) {
23451
+ let ci = 0;
23452
+ const cells = rows[ri].cells;
23453
+ for (let idx = 0;idx < cells.length; idx++) {
23454
+ const cell = cells[idx];
23455
+ while (isOccupied(ri, ci))
23456
+ ci++;
23457
+ const isAuto = cell.colSpan === "auto";
23458
+ const colSpan = cell.colSpan === "auto" ? 1 : Math.max(1, cell.colSpan ?? 1);
23459
+ const rowSpan = Math.max(1, cell.rowSpan ?? 1);
23460
+ const p = {
23461
+ cell,
23462
+ startRow: ri,
23463
+ startCol: ci,
23464
+ colSpan,
23465
+ rowSpan,
23466
+ cs: undefined,
23467
+ pad: undefined,
23468
+ inset: undefined,
23469
+ natural: 0,
23470
+ width: 0,
23471
+ content: undefined,
23472
+ cellHeight: 0
23473
+ };
23474
+ placed.push(p);
23475
+ if (isAuto && idx === cells.length - 1)
23476
+ autoLastCell.push(p);
23477
+ for (let dr = 1;dr < rowSpan; dr++) {
23478
+ for (let dc = 0;dc < colSpan; dc++)
23479
+ occupy(ri + dr, ci + dc);
23480
+ }
23481
+ colCount = Math.max(colCount, ci + colSpan);
23482
+ ci += colSpan;
23483
+ }
23484
+ }
23485
+ for (const p of autoLastCell) {
23486
+ if (p.startCol < colCount - 1)
23487
+ p.colSpan = colCount - p.startCol;
23488
+ }
23489
+ return { placed, colCount };
23490
+ }
23491
+ function layoutTableFrame(table, options = {}) {
23492
+ const depth = options._depth ?? 0;
23493
+ if (depth > MAX_NESTED_TABLE_DEPTH) {
23494
+ throw new Error(`layoutTableFrame: nested table depth exceeded ${MAX_NESTED_TABLE_DEPTH} — likely a cyclic or pathological TableCell.content structure, not a real document.`);
23495
+ }
23496
+ const style = table.style ?? {};
23497
+ const margins = resolveWidths(style.margins, 0);
23498
+ const colGaps = style.colGaps ?? 0;
23499
+ const rowGaps = style.rowGaps ?? 0;
23500
+ const rowCount = table.rows.length;
23501
+ const tableBorder = resolveBorder(style);
23502
+ const { placed, colCount } = placeCells(table.rows);
23503
+ if (colCount === 0 || rowCount === 0) {
23504
+ return {
23505
+ width: margins.left + margins.right,
23506
+ height: margins.top + margins.bottom,
23507
+ bgColor: style.bgColor,
23508
+ ...tableBorder ? { border: tableBorder } : {},
23509
+ contentBox: { x: margins.left, y: margins.top, width: 0, height: 0 },
23510
+ rows: []
23511
+ };
23512
+ }
23513
+ for (const p of placed) {
23514
+ p.cs = resolveCellStyle(p.cell, table);
23515
+ p.pad = resolveWidths(p.cs.paddings, DEFAULT_PADDING);
23516
+ p.border = resolveBorder(p.cs);
23517
+ const bw = p.border?.widths;
23518
+ p.inset = {
23519
+ top: p.pad.top + (bw?.top ?? 0),
23520
+ right: p.pad.right + (bw?.right ?? 0),
23521
+ bottom: p.pad.bottom + (bw?.bottom ?? 0),
23522
+ left: p.pad.left + (bw?.left ?? 0)
23523
+ };
23524
+ const naturalWidth = isNestedTable(p.cell.content) ? layoutTableFrame(p.cell.content, { mode: options.mode, onMissingFont: options.onMissingFont, _depth: depth + 1 }).width : layoutTextFrame({ ...p.cell.content, width: undefined, wrap: false }, { mode: options.mode, onMissingFont: options.onMissingFont }).content.width;
23525
+ p.natural = naturalWidth + p.inset.left + p.inset.right;
23526
+ }
23527
+ const colWidths = new Array(colCount).fill(0);
23528
+ if (table.columnWidths) {
23529
+ for (let c = 0;c < colCount; c++)
23530
+ colWidths[c] = table.columnWidths[c] ?? 0;
23531
+ } else {
23532
+ for (const p of placed)
23533
+ if (p.colSpan === 1)
23534
+ colWidths[p.startCol] = Math.max(colWidths[p.startCol], p.natural);
23535
+ for (const p of placed) {
23536
+ if (p.colSpan <= 1)
23537
+ continue;
23538
+ const covered = sumSpan(colWidths, p.startCol, p.colSpan, colGaps);
23539
+ if (p.natural > covered) {
23540
+ const extra = (p.natural - covered) / p.colSpan;
23541
+ for (let c = p.startCol;c < p.startCol + p.colSpan; c++)
23542
+ colWidths[c] += extra;
23543
+ }
23544
+ }
23545
+ }
23546
+ if (table.width !== undefined) {
23547
+ const budget = table.width - margins.left - margins.right - colGaps * Math.max(0, colCount - 1);
23548
+ const naturalSum = colWidths.reduce((a, b) => a + b, 0);
23549
+ if (naturalSum > 0 && budget > 0) {
23550
+ const scale = budget / naturalSum;
23551
+ for (let i = 0;i < colWidths.length; i++)
23552
+ colWidths[i] *= scale;
23553
+ }
23554
+ }
23555
+ for (const p of placed) {
23556
+ p.width = sumSpan(colWidths, p.startCol, p.colSpan, colGaps);
23557
+ const contentWidth = Math.max(0, p.width - p.inset.left - p.inset.right);
23558
+ if (isNestedTable(p.cell.content)) {
23559
+ const nested = layoutTableFrame({ ...p.cell.content, width: contentWidth }, { mode: options.mode, onMissingFont: options.onMissingFont, _depth: depth + 1 });
23560
+ p.nestedTable = nested;
23561
+ p.content = placeholderContentFor(nested);
23562
+ } else {
23563
+ p.content = layoutTextFrame({ ...p.cell.content, width: contentWidth, wrap: true }, { mode: options.mode, onMissingFont: options.onMissingFont });
23564
+ }
23565
+ p.cellHeight = p.content.content.height + p.inset.top + p.inset.bottom;
23566
+ }
23567
+ const rowHeights = new Array(rowCount).fill(0);
23568
+ if (table.rowHeights) {
23569
+ for (let r = 0;r < rowCount; r++)
23570
+ rowHeights[r] = table.rowHeights[r] ?? 0;
23571
+ } else {
23572
+ for (let ri = 0;ri < rowCount; ri++) {
23573
+ const explicitHeight = resolveRowStyle(table.rows[ri], table).height;
23574
+ if (explicitHeight > 0)
23575
+ rowHeights[ri] = explicitHeight;
23576
+ }
23577
+ for (const p of placed) {
23578
+ if (p.rowSpan === 1 && rowHeights[p.startRow] === 0)
23579
+ rowHeights[p.startRow] = p.cellHeight;
23580
+ else if (p.rowSpan === 1)
23581
+ rowHeights[p.startRow] = Math.max(rowHeights[p.startRow], p.cellHeight);
23582
+ }
23583
+ for (const p of placed) {
23584
+ if (p.rowSpan <= 1)
23585
+ continue;
23586
+ const covered = sumSpan(rowHeights, p.startRow, p.rowSpan, rowGaps);
23587
+ if (p.cellHeight > covered) {
23588
+ const extra = (p.cellHeight - covered) / p.rowSpan;
23589
+ for (let r = p.startRow;r < p.startRow + p.rowSpan; r++)
23590
+ rowHeights[r] += extra;
23591
+ }
23592
+ }
23593
+ }
23594
+ if (table.height !== undefined) {
23595
+ const budget = table.height - margins.top - margins.bottom - rowGaps * Math.max(0, rowCount - 1);
23596
+ const naturalSum = rowHeights.reduce((a, b) => a + b, 0);
23597
+ if (naturalSum > 0 && budget > 0) {
23598
+ const scale = budget / naturalSum;
23599
+ for (let i = 0;i < rowHeights.length; i++)
23600
+ rowHeights[i] *= scale;
23601
+ }
23602
+ }
23603
+ const colX = [];
23604
+ {
23605
+ let acc = margins.left;
23606
+ for (let c = 0;c < colCount; c++) {
23607
+ colX.push(acc);
23608
+ acc += colWidths[c] + colGaps;
23609
+ }
23610
+ }
23611
+ const rowY = [];
23612
+ {
23613
+ let acc = margins.top;
23614
+ for (let r = 0;r < rowCount; r++) {
23615
+ rowY.push(acc);
23616
+ acc += rowHeights[r] + rowGaps;
23617
+ }
23618
+ }
23619
+ const rows = table.rows.map((row, ri) => {
23620
+ const rs = resolveRowStyle(row, table);
23621
+ const rowBorder = resolveBorder(rs);
23622
+ const cells = placed.filter((p) => p.startRow === ri).map((p) => {
23623
+ const height = sumSpan(rowHeights, p.startRow, p.rowSpan, rowGaps);
23624
+ const available = height - p.inset.top - p.inset.bottom;
23625
+ const verticalOffset = verticalOffsetFor(p.cs.verticalAlign, available, p.content.content.height);
23626
+ const cellX = colX[p.startCol];
23627
+ const cellY = rowY[p.startRow];
23628
+ let before;
23629
+ if (p.cell.before) {
23630
+ const bc = layoutTextFrame({ ...p.cell.before, width: undefined, wrap: false }, { mode: options.mode, onMissingFont: options.onMissingFont });
23631
+ before = { content: bc, x: cellX + p.inset.left, y: cellY + (height - bc.content.height) / 2 };
23632
+ }
23633
+ let after;
23634
+ if (p.cell.after) {
23635
+ const ac = layoutTextFrame({ ...p.cell.after, width: undefined, wrap: false }, { mode: options.mode, onMissingFont: options.onMissingFont });
23636
+ after = { content: ac, x: cellX + p.width - p.inset.right - ac.content.width, y: cellY + (height - ac.content.height) / 2 };
23637
+ }
23638
+ return {
23639
+ x: cellX,
23640
+ y: cellY,
23641
+ width: p.width,
23642
+ height,
23643
+ padding: p.pad,
23644
+ verticalOffset,
23645
+ cx: p.cs.cx,
23646
+ cy: p.cs.cy,
23647
+ allowOverflow: p.cs.allowOverflow,
23648
+ ...p.cs.bgColor ? { bgColor: p.cs.bgColor } : {},
23649
+ ...p.border ? { border: p.border } : {},
23650
+ content: p.content,
23651
+ ...p.nestedTable ? { nestedTable: p.nestedTable } : {},
23652
+ ...before ? { before } : {},
23653
+ ...after ? { after } : {},
23654
+ colSpan: p.colSpan,
23655
+ rowSpan: p.rowSpan
23656
+ };
23657
+ });
23658
+ return {
23659
+ y: rowY[ri],
23660
+ height: rowHeights[ri],
23661
+ ...rs.bgColor ? { bgColor: rs.bgColor } : {},
23662
+ ...rowBorder ? { border: rowBorder } : {},
23663
+ cells
23664
+ };
23665
+ });
23666
+ const totalWidth = margins.left + colWidths.reduce((a, b) => a + b, 0) + colGaps * Math.max(0, colCount - 1) + margins.right;
23667
+ const totalHeight = margins.top + rowHeights.reduce((a, b) => a + b, 0) + rowGaps * Math.max(0, rowCount - 1) + margins.bottom;
23668
+ return {
23669
+ width: totalWidth,
23670
+ height: totalHeight,
23671
+ bgColor: style.bgColor,
23672
+ ...tableBorder ? { border: tableBorder } : {},
23673
+ contentBox: {
23674
+ x: margins.left,
23675
+ y: margins.top,
23676
+ width: totalWidth - margins.left - margins.right,
23677
+ height: totalHeight - margins.top - margins.bottom
23678
+ },
23679
+ rows
23680
+ };
23681
+ }
23274
23682
  // src/index.browser.ts
23275
23683
  var DEFAULT_PARAGRAPH_STYLE2 = { ...DEFAULT_PARAGRAPH_STYLE };
23276
23684
  var DEFAULT_TEXT_STYLE2 = { ...DEFAULT_TEXT_STYLE };
@@ -23285,6 +23693,7 @@ export {
23285
23693
  measurePx,
23286
23694
  makeFontToken,
23287
23695
  layoutTextFrame,
23696
+ layoutTableFrame,
23288
23697
  isFontEngineAvailable,
23289
23698
  groupLinesByParagraph,
23290
23699
  getParagraphText,
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@
13
13
  * - `index.browser.ts` (browser) — browser-safe subset (no node:fs)
14
14
  */
15
15
  export type { TextFrame, Paragraph, ParagraphStyle, TextRun, InlineWidget, AutofitConfig, TextAlignment, WritingMode, TextOrientation, VerticalAlignment, ScriptType, WhiteSpace, MultiColumnConfig, DominantBaseline, LineFitEdge, TextAlignLast, WordBreak, LineBreak, OverflowWrap, TextDecorationStyle, TextTransform, ListType, NumberFormat, ListStylePosition, ListStyle, ResolvedTextRun, } from './types/Document.js';
16
+ export type { TableFrame, TableRow, TableCell, TableStyle, TableRowStyle, TableCellStyle, BorderStyles, Widths, ColorsOnWidth, Sides, } from './types/TableTypes.js';
16
17
  import type { ParagraphStyle } from './types/Document.js';
17
18
  /** @internal */
18
19
  export declare const DEFAULT_PARAGRAPH_STYLE: ParagraphStyle;
@@ -29,7 +30,9 @@ export { positionLines } from './layout/PositioningEngine.js';
29
30
  export { layoutTextFrame } from './layout/TextFrameLayoutEngine.js';
30
31
  export { createLayoutEngine } from './layout/create-engine.js';
31
32
  export type { LayoutEngine, LayoutEngineOptions } from './layout/create-engine.js';
32
- export type { TextFrameLayoutResult, LayoutOptions, AutofitOutcome } from './layout/TextFrameLayoutEngine.js';
33
+ export type { TextFrameLayoutResult, LayoutOptions, AutofitOutcome, FrameTransform } from './layout/TextFrameLayoutEngine.js';
34
+ export { layoutTableFrame } from './layout/TableLayoutEngine.js';
35
+ export type { TableLayoutResult, TableRowLayoutResult, TableCellLayoutResult, TableLayoutOptions, ResolvedBorder } from './layout/TableLayoutEngine.js';
33
36
  export type { OnMissingFont } from './layout/resolve-font.js';
34
37
  export { applyScale, findScale } from './layout/AutoFitEngine.js';
35
38
  export type { AutoFitOptions, AutoFitResult } from './layout/AutoFitEngine.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}