postext 0.3.16 → 0.3.18

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.
Files changed (228) hide show
  1. package/dist/__tests__/columnBalancing.test.d.ts +2 -0
  2. package/dist/__tests__/columnBalancing.test.d.ts.map +1 -0
  3. package/dist/__tests__/columnBalancing.test.js +194 -0
  4. package/dist/__tests__/columnBalancing.test.js.map +1 -0
  5. package/dist/__tests__/createLayout.test.js +12 -13
  6. package/dist/__tests__/createLayout.test.js.map +1 -1
  7. package/dist/__tests__/defaults/resourceTypes.test.d.ts +2 -0
  8. package/dist/__tests__/defaults/resourceTypes.test.d.ts.map +1 -0
  9. package/dist/__tests__/defaults/resourceTypes.test.js +69 -0
  10. package/dist/__tests__/defaults/resourceTypes.test.js.map +1 -0
  11. package/dist/__tests__/exports.test.js +60 -0
  12. package/dist/__tests__/exports.test.js.map +1 -1
  13. package/dist/__tests__/parse/inlineRef.test.d.ts +2 -0
  14. package/dist/__tests__/parse/inlineRef.test.d.ts.map +1 -0
  15. package/dist/__tests__/parse/inlineRef.test.js +83 -0
  16. package/dist/__tests__/parse/inlineRef.test.js.map +1 -0
  17. package/dist/__tests__/parse/resourceDirective.test.d.ts +2 -0
  18. package/dist/__tests__/parse/resourceDirective.test.d.ts.map +1 -0
  19. package/dist/__tests__/parse/resourceDirective.test.js +55 -0
  20. package/dist/__tests__/parse/resourceDirective.test.js.map +1 -0
  21. package/dist/__tests__/pipeline/floatPlacement.test.d.ts +2 -0
  22. package/dist/__tests__/pipeline/floatPlacement.test.d.ts.map +1 -0
  23. package/dist/__tests__/pipeline/floatPlacement.test.js +262 -0
  24. package/dist/__tests__/pipeline/floatPlacement.test.js.map +1 -0
  25. package/dist/__tests__/pipeline/inlineRefRender.test.d.ts +2 -0
  26. package/dist/__tests__/pipeline/inlineRefRender.test.d.ts.map +1 -0
  27. package/dist/__tests__/pipeline/inlineRefRender.test.js +107 -0
  28. package/dist/__tests__/pipeline/inlineRefRender.test.js.map +1 -0
  29. package/dist/__tests__/pipeline/resourceNumbering.test.d.ts +2 -0
  30. package/dist/__tests__/pipeline/resourceNumbering.test.d.ts.map +1 -0
  31. package/dist/__tests__/pipeline/resourceNumbering.test.js +186 -0
  32. package/dist/__tests__/pipeline/resourceNumbering.test.js.map +1 -0
  33. package/dist/__tests__/singleInk.test.d.ts +2 -0
  34. package/dist/__tests__/singleInk.test.d.ts.map +1 -0
  35. package/dist/__tests__/singleInk.test.js +42 -0
  36. package/dist/__tests__/singleInk.test.js.map +1 -0
  37. package/dist/__tests__/table/model.test.d.ts +2 -0
  38. package/dist/__tests__/table/model.test.d.ts.map +1 -0
  39. package/dist/__tests__/table/model.test.js +187 -0
  40. package/dist/__tests__/table/model.test.js.map +1 -0
  41. package/dist/canvas-backend/blockRender.d.ts.map +1 -1
  42. package/dist/canvas-backend/blockRender.js +103 -66
  43. package/dist/canvas-backend/blockRender.js.map +1 -1
  44. package/dist/canvas-backend/decorations.d.ts +4 -1
  45. package/dist/canvas-backend/decorations.d.ts.map +1 -1
  46. package/dist/canvas-backend/decorations.js +14 -6
  47. package/dist/canvas-backend/decorations.js.map +1 -1
  48. package/dist/canvas-backend/headerFooter.d.ts +2 -2
  49. package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
  50. package/dist/canvas-backend/headerFooter.js +62 -2
  51. package/dist/canvas-backend/headerFooter.js.map +1 -1
  52. package/dist/canvas-backend/index.d.ts +2 -0
  53. package/dist/canvas-backend/index.d.ts.map +1 -1
  54. package/dist/canvas-backend/index.js +20 -10
  55. package/dist/canvas-backend/index.js.map +1 -1
  56. package/dist/canvas-backend/renderResourceBlock.d.ts +28 -0
  57. package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -0
  58. package/dist/canvas-backend/renderResourceBlock.js +146 -0
  59. package/dist/canvas-backend/renderResourceBlock.js.map +1 -0
  60. package/dist/defaults/bodyText.d.ts.map +1 -1
  61. package/dist/defaults/bodyText.js +30 -0
  62. package/dist/defaults/bodyText.js.map +1 -1
  63. package/dist/defaults/captionStyle.d.ts +9 -0
  64. package/dist/defaults/captionStyle.d.ts.map +1 -0
  65. package/dist/defaults/captionStyle.js +74 -0
  66. package/dist/defaults/captionStyle.js.map +1 -0
  67. package/dist/defaults/debug.d.ts.map +1 -1
  68. package/dist/defaults/debug.js +6 -0
  69. package/dist/defaults/debug.js.map +1 -1
  70. package/dist/defaults/diagramStyle.d.ts +5 -0
  71. package/dist/defaults/diagramStyle.d.ts.map +1 -0
  72. package/dist/defaults/diagramStyle.js +29 -0
  73. package/dist/defaults/diagramStyle.js.map +1 -0
  74. package/dist/defaults/headerFooter.d.ts +20 -18
  75. package/dist/defaults/headerFooter.d.ts.map +1 -1
  76. package/dist/defaults/headerFooter.js +269 -165
  77. package/dist/defaults/headerFooter.js.map +1 -1
  78. package/dist/defaults/headings.d.ts +4 -0
  79. package/dist/defaults/headings.d.ts.map +1 -1
  80. package/dist/defaults/headings.js +65 -9
  81. package/dist/defaults/headings.js.map +1 -1
  82. package/dist/defaults/index.d.ts +5 -1
  83. package/dist/defaults/index.d.ts.map +1 -1
  84. package/dist/defaults/index.js +29 -1
  85. package/dist/defaults/index.js.map +1 -1
  86. package/dist/defaults/resourceTypes.d.ts +8 -0
  87. package/dist/defaults/resourceTypes.d.ts.map +1 -0
  88. package/dist/defaults/resourceTypes.js +43 -0
  89. package/dist/defaults/resourceTypes.js.map +1 -0
  90. package/dist/defaults/shared.d.ts.map +1 -1
  91. package/dist/defaults/shared.js +40 -0
  92. package/dist/defaults/shared.js.map +1 -1
  93. package/dist/defaults/tableStyle.d.ts +11 -0
  94. package/dist/defaults/tableStyle.d.ts.map +1 -0
  95. package/dist/defaults/tableStyle.js +114 -0
  96. package/dist/defaults/tableStyle.js.map +1 -0
  97. package/dist/design/layout.d.ts +94 -0
  98. package/dist/design/layout.d.ts.map +1 -0
  99. package/dist/design/layout.js +642 -0
  100. package/dist/design/layout.js.map +1 -0
  101. package/dist/design/placeholders.d.ts +29 -0
  102. package/dist/design/placeholders.d.ts.map +1 -0
  103. package/dist/design/placeholders.js +126 -0
  104. package/dist/design/placeholders.js.map +1 -0
  105. package/dist/html-backend.d.ts +6 -0
  106. package/dist/html-backend.d.ts.map +1 -1
  107. package/dist/html-backend.js +274 -10
  108. package/dist/html-backend.js.map +1 -1
  109. package/dist/index.d.ts +14 -5
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +8 -2
  112. package/dist/index.js.map +1 -1
  113. package/dist/knuthPlass/breakpoints.d.ts.map +1 -1
  114. package/dist/knuthPlass/breakpoints.js +41 -98
  115. package/dist/knuthPlass/breakpoints.js.map +1 -1
  116. package/dist/knuthPlass/richAdapter.d.ts +1 -0
  117. package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
  118. package/dist/knuthPlass/richAdapter.js +2 -1
  119. package/dist/knuthPlass/richAdapter.js.map +1 -1
  120. package/dist/measure/cache.js +1 -1
  121. package/dist/measure/cache.js.map +1 -1
  122. package/dist/measure/canvas.d.ts +3 -0
  123. package/dist/measure/canvas.d.ts.map +1 -1
  124. package/dist/measure/canvas.js +40 -2
  125. package/dist/measure/canvas.js.map +1 -1
  126. package/dist/measure/font.d.ts +3 -2
  127. package/dist/measure/font.d.ts.map +1 -1
  128. package/dist/measure/font.js +5 -2
  129. package/dist/measure/font.js.map +1 -1
  130. package/dist/measure/plain.d.ts.map +1 -1
  131. package/dist/measure/plain.js +14 -7
  132. package/dist/measure/plain.js.map +1 -1
  133. package/dist/measure/rich.d.ts +7 -0
  134. package/dist/measure/rich.d.ts.map +1 -1
  135. package/dist/measure/rich.js +34 -7
  136. package/dist/measure/rich.js.map +1 -1
  137. package/dist/numbering.d.ts +16 -0
  138. package/dist/numbering.d.ts.map +1 -1
  139. package/dist/numbering.js +28 -18
  140. package/dist/numbering.js.map +1 -1
  141. package/dist/parse/blockParser.d.ts.map +1 -1
  142. package/dist/parse/blockParser.js +37 -9
  143. package/dist/parse/blockParser.js.map +1 -1
  144. package/dist/parse/injectSpans.d.ts +9 -0
  145. package/dist/parse/injectSpans.d.ts.map +1 -0
  146. package/dist/parse/injectSpans.js +35 -0
  147. package/dist/parse/injectSpans.js.map +1 -0
  148. package/dist/parse/inlineFormatting.d.ts +38 -0
  149. package/dist/parse/inlineFormatting.d.ts.map +1 -1
  150. package/dist/parse/inlineFormatting.js +58 -0
  151. package/dist/parse/inlineFormatting.js.map +1 -1
  152. package/dist/parse/inlineMath.d.ts.map +1 -1
  153. package/dist/parse/inlineMath.js +26 -43
  154. package/dist/parse/inlineMath.js.map +1 -1
  155. package/dist/parse/sourceMapping.d.ts.map +1 -1
  156. package/dist/parse/sourceMapping.js +34 -7
  157. package/dist/parse/sourceMapping.js.map +1 -1
  158. package/dist/parse/types.d.ts +20 -1
  159. package/dist/parse/types.d.ts.map +1 -1
  160. package/dist/pipeline/build.d.ts.map +1 -1
  161. package/dist/pipeline/build.js +521 -28
  162. package/dist/pipeline/build.js.map +1 -1
  163. package/dist/pipeline/buildBlockKind.d.ts +14 -0
  164. package/dist/pipeline/buildBlockKind.d.ts.map +1 -1
  165. package/dist/pipeline/buildBlockKind.js +16 -1
  166. package/dist/pipeline/buildBlockKind.js.map +1 -1
  167. package/dist/pipeline/buildHelpers.d.ts.map +1 -1
  168. package/dist/pipeline/buildHelpers.js +7 -1
  169. package/dist/pipeline/buildHelpers.js.map +1 -1
  170. package/dist/pipeline/buildMeasurement.d.ts +17 -1
  171. package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
  172. package/dist/pipeline/buildMeasurement.js +32 -0
  173. package/dist/pipeline/buildMeasurement.js.map +1 -1
  174. package/dist/pipeline/columnBalancing.d.ts +75 -0
  175. package/dist/pipeline/columnBalancing.d.ts.map +1 -0
  176. package/dist/pipeline/columnBalancing.js +125 -0
  177. package/dist/pipeline/columnBalancing.js.map +1 -0
  178. package/dist/pipeline/config.d.ts +4 -1
  179. package/dist/pipeline/config.d.ts.map +1 -1
  180. package/dist/pipeline/config.js +12 -1
  181. package/dist/pipeline/config.js.map +1 -1
  182. package/dist/pipeline/floatPlacement.d.ts +45 -0
  183. package/dist/pipeline/floatPlacement.d.ts.map +1 -0
  184. package/dist/pipeline/floatPlacement.js +68 -0
  185. package/dist/pipeline/floatPlacement.js.map +1 -0
  186. package/dist/pipeline/headerFooter.d.ts +23 -7
  187. package/dist/pipeline/headerFooter.d.ts.map +1 -1
  188. package/dist/pipeline/headerFooter.js +260 -100
  189. package/dist/pipeline/headerFooter.js.map +1 -1
  190. package/dist/pipeline/lists.d.ts +4 -9
  191. package/dist/pipeline/lists.d.ts.map +1 -1
  192. package/dist/pipeline/lists.js +24 -42
  193. package/dist/pipeline/lists.js.map +1 -1
  194. package/dist/pipeline/placeholders.d.ts +6 -0
  195. package/dist/pipeline/placeholders.d.ts.map +1 -1
  196. package/dist/pipeline/placeholders.js +18 -5
  197. package/dist/pipeline/placeholders.js.map +1 -1
  198. package/dist/pipeline/placement.d.ts +15 -2
  199. package/dist/pipeline/placement.d.ts.map +1 -1
  200. package/dist/pipeline/placement.js +38 -3
  201. package/dist/pipeline/placement.js.map +1 -1
  202. package/dist/pipeline/resourceLayout.d.ts +58 -0
  203. package/dist/pipeline/resourceLayout.d.ts.map +1 -0
  204. package/dist/pipeline/resourceLayout.js +338 -0
  205. package/dist/pipeline/resourceLayout.js.map +1 -0
  206. package/dist/pipeline/resourceNumbering.d.ts +54 -0
  207. package/dist/pipeline/resourceNumbering.d.ts.map +1 -0
  208. package/dist/pipeline/resourceNumbering.js +218 -0
  209. package/dist/pipeline/resourceNumbering.js.map +1 -0
  210. package/dist/pipeline/styles.d.ts +6 -0
  211. package/dist/pipeline/styles.d.ts.map +1 -1
  212. package/dist/pipeline/styles.js +1 -1
  213. package/dist/pipeline/styles.js.map +1 -1
  214. package/dist/svg/singleInk.d.ts +10 -0
  215. package/dist/svg/singleInk.d.ts.map +1 -0
  216. package/dist/svg/singleInk.js +86 -0
  217. package/dist/svg/singleInk.js.map +1 -0
  218. package/dist/table/model.d.ts +53 -0
  219. package/dist/table/model.d.ts.map +1 -0
  220. package/dist/table/model.js +253 -0
  221. package/dist/table/model.js.map +1 -0
  222. package/dist/types.d.ts +429 -41
  223. package/dist/types.d.ts.map +1 -1
  224. package/dist/vdt.d.ts +181 -18
  225. package/dist/vdt.d.ts.map +1 -1
  226. package/dist/vdt.js +34 -0
  227. package/dist/vdt.js.map +1 -1
  228. package/package.json +6 -6
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Resource block layout (issue #49 §7 — Measurement).
3
+ *
4
+ * Turns a `Resource` + its computed number into a measured, placement-ready
5
+ * {@link ResolvedResourceBlock}. The result is fully self-contained so the
6
+ * canvas / PDF renderers can draw it synchronously without touching the parser
7
+ * or numbering pipeline again.
8
+ *
9
+ * Layout rules for v1 (kept intentionally simple — see the issue plan):
10
+ * - bitmap / svg: scale to the column width, preserving aspect ratio. The
11
+ * height follows from the intrinsic dimensions; svgs without intrinsic
12
+ * dimensions fall back to a 4:3 box at column width.
13
+ * - table: equal column split; each cell measured via the shared rich-text
14
+ * measurer; row height = max cell height (rowspans distribute across rows).
15
+ * - caption: measured via the rich-text measurer with the caption font, with
16
+ * the type's caption prefix + number prepended. Inline `:ref` spans resolve
17
+ * to their computed label and are tagged so renderers can colour / link them.
18
+ *
19
+ * Resource + caption are measured as one group; `totalHeight` is what goes to
20
+ * placement (resources paginate atomically — no mid-split for v1).
21
+ */
22
+ import { createBoundingBox } from '../vdt';
23
+ import { measureRichBlock, buildFontString } from '../measure';
24
+ import { dimensionToPx } from '../units';
25
+ import { extractInlineRefs, injectRefSpans, parseInlineFormatting } from '../parse/inlineFormatting';
26
+ import { resolveBodyStyle } from './styles';
27
+ /** Non-breaking space used to glue a resolved `:ref` label into a single
28
+ * atomic text token, so a post-measurement pass can tag it reliably. */
29
+ const NBSP = ' ';
30
+ /** Build a label for an inline `:ref` to a resource, honouring its `style` and
31
+ * optional override `text`. Mirrors the caption-prefix conventions. */
32
+ export function resolveRefLabel(ref, resourceNumbering, resourceTypes, resources) {
33
+ if (ref.text !== undefined && ref.text.length > 0)
34
+ return ref.text;
35
+ const entry = resourceNumbering[ref.resourceId];
36
+ const number = entry?.number ?? '?';
37
+ if (ref.style === 'number')
38
+ return number;
39
+ const resource = resources.find((r) => r.id === ref.resourceId);
40
+ const type = resource ? resourceTypes.find((t) => t.id === resource.typeId) : undefined;
41
+ if (ref.style === 'full') {
42
+ const name = type?.name ?? type?.shortLabel ?? '';
43
+ return name ? `${name}${NBSP}${number}` : number;
44
+ }
45
+ // default: short label + number (e.g. "Fig. 1.7")
46
+ const short = type?.shortLabel ?? type?.name ?? '';
47
+ return short ? `${short}${NBSP}${number}` : number;
48
+ }
49
+ /** Parse caption / table-cell content into inline spans, recognising the same
50
+ * inline `:ref{…}` microformat as body text so references inside captions and
51
+ * cells resolve to their computed labels (the cell/caption is self-contained,
52
+ * so source offsets are irrelevant here). */
53
+ function parseRefAwareSpans(content) {
54
+ const { cleaned, refs } = extractInlineRefs(content, 0);
55
+ return injectRefSpans(parseInlineFormatting(cleaned), refs);
56
+ }
57
+ /** Resolve inline `:ref` spans to their computed label, keeping the `ref`
58
+ * metadata so the rich-text measurer treats each label as one atomic,
59
+ * non-breaking token and tags the produced segment with `refResourceId`. */
60
+ export function resolveRefSpans(spans, resourceNumbering, resourceTypes, resources, refStyle) {
61
+ if (!spans.some((s) => s.ref))
62
+ return spans;
63
+ return spans.map((span) => {
64
+ if (!span.ref)
65
+ return span;
66
+ return {
67
+ ...span,
68
+ text: resolveRefLabel(span.ref, resourceNumbering, resourceTypes, resources),
69
+ // Reference labels carry their own emphasis (bold/italic) so the measurer
70
+ // selects the matching font; colour is applied by renderers via
71
+ // `refResourceId`.
72
+ bold: refStyle?.bold ?? span.bold,
73
+ italic: refStyle?.italic ?? span.italic,
74
+ };
75
+ });
76
+ }
77
+ /** Offset every line's bbox / baseline by `dy` (block-relative → block-relative
78
+ * shifted). Returns new line objects (FP-first). */
79
+ function shiftLines(lines, dx, dy) {
80
+ return lines.map((line) => ({
81
+ ...line,
82
+ bbox: createBoundingBox(line.bbox.x + dx, line.bbox.y + dy, line.bbox.width, line.bbox.height),
83
+ baseline: line.baseline + dy,
84
+ }));
85
+ }
86
+ /** Compute the displayed (column-fitted, aspect-preserved) size of a bitmap. */
87
+ function fitWidth(intrinsicW, intrinsicH, columnWidth) {
88
+ if (intrinsicW <= 0 || intrinsicH <= 0) {
89
+ // No intrinsic dims — default to a 4:3 box at column width.
90
+ return { width: columnWidth, height: columnWidth * 0.75 };
91
+ }
92
+ const width = Math.min(intrinsicW, columnWidth);
93
+ const height = (intrinsicH / intrinsicW) * width;
94
+ return { width, height };
95
+ }
96
+ /** Lay out an HTML-table resource: equal column split, per-cell rich-text
97
+ * measurement, row height = max measured cell height. Rowspans reserve their
98
+ * primary cell's full vertical extent. */
99
+ function layoutTable(model, columnWidth, style, resourceNumbering, resourceTypes, resources, refStyle) {
100
+ const { body, header, borderColor, borderWidthPx, cellPaddingPx } = style;
101
+ const rowCount = model.rows.length;
102
+ const colCount = rowCount > 0 ? Math.max(...model.rows.map((r) => r.length)) : 0;
103
+ const colWidth = colCount > 0 ? columnWidth / colCount : columnWidth;
104
+ const columnEdges = [];
105
+ for (let c = 0; c <= colCount; c++)
106
+ columnEdges.push(c * colWidth);
107
+ const measured = [];
108
+ const rowMinHeight = new Array(rowCount).fill(body.lineHeightPx);
109
+ for (let r = 0; r < rowCount; r++) {
110
+ const row = model.rows[r];
111
+ for (let c = 0; c < row.length; c++) {
112
+ const cell = row[c];
113
+ if (cell.hiddenBy)
114
+ continue;
115
+ const colSpan = Math.max(1, cell.colSpan ?? 1);
116
+ const rowSpan = Math.max(1, cell.rowSpan ?? 1);
117
+ const isHeader = cell.isHeader ?? r < (model.headerRowCount ?? 0);
118
+ const set = isHeader ? header : body;
119
+ const cellWidth = colSpan * colWidth - cellPaddingPx * 2;
120
+ const spans = resolveRefSpans(parseRefAwareSpans(cell.content), resourceNumbering, resourceTypes, resources, refStyle);
121
+ const m = measureRichBlock(spans, set.fontString, set.boldFontString, set.italicFontString, set.boldItalicFontString, Math.max(1, cellWidth), set.lineHeightPx, { textAlign: cell.align === 'center' ? 'center' : cell.align === 'right' ? 'left' : 'left' });
122
+ const contentHeight = Math.max(set.lineHeightPx, m.totalHeight) + cellPaddingPx * 2;
123
+ measured.push({
124
+ row: r,
125
+ col: c,
126
+ colSpan,
127
+ rowSpan,
128
+ isHeader,
129
+ align: cell.align ?? 'left',
130
+ verticalAlign: cell.verticalAlign ?? 'top',
131
+ lines: m.lines,
132
+ contentHeight,
133
+ });
134
+ // Single-row cells drive their row's minimum height directly.
135
+ if (rowSpan === 1) {
136
+ rowMinHeight[r] = Math.max(rowMinHeight[r], contentHeight);
137
+ }
138
+ }
139
+ }
140
+ // Distribute rowspan cells: ensure the spanned rows together fit the content.
141
+ for (const m of measured) {
142
+ if (m.rowSpan <= 1)
143
+ continue;
144
+ let spannedHeight = 0;
145
+ for (let r = m.row; r < m.row + m.rowSpan && r < rowCount; r++) {
146
+ spannedHeight += rowMinHeight[r];
147
+ }
148
+ if (m.contentHeight > spannedHeight) {
149
+ const lastRow = Math.min(m.row + m.rowSpan - 1, rowCount - 1);
150
+ rowMinHeight[lastRow] = rowMinHeight[lastRow] + (m.contentHeight - spannedHeight);
151
+ }
152
+ }
153
+ const rowEdges = [0];
154
+ for (let r = 0; r < rowCount; r++)
155
+ rowEdges.push(rowEdges[r] + rowMinHeight[r]);
156
+ const tableHeight = rowEdges[rowCount] ?? 0;
157
+ const cells = measured.map((m) => {
158
+ const x0 = columnEdges[m.col] ?? 0;
159
+ const x1 = columnEdges[Math.min(m.col + m.colSpan, colCount)] ?? columnWidth;
160
+ const y0 = rowEdges[m.row] ?? 0;
161
+ const y1 = rowEdges[Math.min(m.row + m.rowSpan, rowCount)] ?? tableHeight;
162
+ const rect = createBoundingBox(x0, y0, x1 - x0, y1 - y0);
163
+ // Place lines inside the cell with padding; horizontal alignment is applied
164
+ // by the renderer via the cell rect + align flag.
165
+ const placed = shiftLines(m.lines, x0 + cellPaddingPx, y0 + cellPaddingPx);
166
+ return {
167
+ row: m.row,
168
+ col: m.col,
169
+ colSpan: m.colSpan,
170
+ rowSpan: m.rowSpan,
171
+ isHeader: m.isHeader,
172
+ align: m.align,
173
+ verticalAlign: m.verticalAlign,
174
+ rect,
175
+ lines: placed,
176
+ };
177
+ });
178
+ const layout = {
179
+ fontString: body.fontString,
180
+ boldFontString: body.boldFontString,
181
+ italicFontString: body.italicFontString,
182
+ boldItalicFontString: body.boldItalicFontString,
183
+ color: body.color,
184
+ headerFontString: header.fontString,
185
+ headerBoldFontString: header.boldFontString,
186
+ headerItalicFontString: header.italicFontString,
187
+ headerBoldItalicFontString: header.boldItalicFontString,
188
+ headerColor: header.color,
189
+ borderColor,
190
+ borderWidthPx,
191
+ headerBackground: style.headerBackground,
192
+ bodyBackground: style.bodyBackground,
193
+ cells,
194
+ columnEdges,
195
+ rowEdges,
196
+ };
197
+ return { layout, height: tableHeight };
198
+ }
199
+ /**
200
+ * Measure a resource block (image / svg / table) plus its caption into a
201
+ * placement-ready {@link ResolvedResourceBlock}. Returns the block and its
202
+ * combined height (figure body + gap + caption) — the value placement uses to
203
+ * decide whether the group fits the remaining column space.
204
+ */
205
+ export function layoutResourceBlock(input) {
206
+ const { resource, resourceType, number, resolved, columnWidth, resourceNumbering, resourceTypes, resources, } = input;
207
+ const bodyStyle = resolveBodyStyle(resolved);
208
+ const dpi = resolved.page.dpi;
209
+ // Normal / bold weights reused for table + caption font sets.
210
+ const normalWeight = resolved.bodyText.fontWeight.toString();
211
+ const boldWeight = resolved.bodyText.boldFontWeight.toString();
212
+ // Line-height ratio of the body text — applied to any custom table/caption
213
+ // font size so a resized run keeps a proportional leading (and reproduces the
214
+ // previous heights exactly when the size is left at the body default).
215
+ const lineHeightRatio = bodyStyle.lineHeightPx / bodyStyle.fontSizePx;
216
+ // Inline `:ref` emphasis (bold/italic), applied to refs in captions + cells.
217
+ const refStyle = { bold: resolved.bodyText.referenceBold, italic: resolved.bodyText.referenceItalic };
218
+ // --- Figure body -------------------------------------------------------
219
+ let bodyWidth = columnWidth;
220
+ let bodyHeight = 0;
221
+ let table;
222
+ let fileId;
223
+ let format;
224
+ if (resource.kind === 'bitmap' && resource.bitmap) {
225
+ fileId = resource.bitmap.fileId;
226
+ format = resource.bitmap.format;
227
+ const fit = fitWidth(resource.bitmap.width, resource.bitmap.height, columnWidth);
228
+ bodyWidth = fit.width;
229
+ bodyHeight = fit.height;
230
+ }
231
+ else if (resource.kind === 'svg' && resource.svg) {
232
+ fileId = resource.svg.fileId;
233
+ // SVGs are vector: fill the column width and derive height from the
234
+ // intrinsic aspect ratio (viewBox / width:height). Fall back to a 4:3 box
235
+ // only when no intrinsic size was captured.
236
+ const iw = resource.svg.width ?? 0;
237
+ const ih = resource.svg.height ?? 0;
238
+ bodyWidth = columnWidth;
239
+ bodyHeight = iw > 0 && ih > 0 ? columnWidth * (ih / iw) : columnWidth * 0.75;
240
+ }
241
+ else if (resource.kind === 'table' && resource.table) {
242
+ const ts = resolved.tableStyle;
243
+ const bodyFontPx = dimensionToPx(ts.bodyFontSize, dpi);
244
+ const headerFontPx = dimensionToPx(ts.headerFontSize, dpi);
245
+ // Header weight/slant: the header's base run is bold (and/or italic) by
246
+ // default; inline markup still toggles relative to that base, mirroring the
247
+ // blockquote/heading italic-flip convention.
248
+ const hWeight = ts.headerBold ? boldWeight : normalWeight;
249
+ const hBase = ts.headerItalic ? 'italic' : 'normal';
250
+ const hFlip = ts.headerItalic ? 'normal' : 'italic';
251
+ const style = {
252
+ body: {
253
+ fontString: buildFontString(ts.bodyFontFamily, bodyFontPx, normalWeight),
254
+ boldFontString: buildFontString(ts.bodyFontFamily, bodyFontPx, boldWeight),
255
+ italicFontString: buildFontString(ts.bodyFontFamily, bodyFontPx, normalWeight, 'italic'),
256
+ boldItalicFontString: buildFontString(ts.bodyFontFamily, bodyFontPx, boldWeight, 'italic'),
257
+ color: ts.bodyColor.hex,
258
+ lineHeightPx: bodyFontPx * lineHeightRatio,
259
+ },
260
+ header: {
261
+ fontString: buildFontString(ts.headerFontFamily, headerFontPx, hWeight, hBase),
262
+ boldFontString: buildFontString(ts.headerFontFamily, headerFontPx, boldWeight, hBase),
263
+ italicFontString: buildFontString(ts.headerFontFamily, headerFontPx, hWeight, hFlip),
264
+ boldItalicFontString: buildFontString(ts.headerFontFamily, headerFontPx, boldWeight, hFlip),
265
+ color: ts.headerColor.hex,
266
+ lineHeightPx: headerFontPx * lineHeightRatio,
267
+ },
268
+ borderColor: ts.borderColor.hex,
269
+ borderWidthPx: ts.borders ? Math.max(1, Math.round(dimensionToPx(ts.borderWidth, dpi))) : 0,
270
+ cellPaddingPx: dimensionToPx(ts.cellPadding, dpi, bodyFontPx),
271
+ headerBackground: ts.headerBackgroundEnabled ? ts.headerBackground.hex : undefined,
272
+ bodyBackground: ts.bodyBackgroundEnabled ? ts.bodyBackground.hex : undefined,
273
+ };
274
+ const { layout, height } = layoutTable(resource.table.model, columnWidth, style, resourceNumbering, resourceTypes, resources, refStyle);
275
+ table = layout;
276
+ bodyWidth = columnWidth;
277
+ bodyHeight = height;
278
+ }
279
+ const bodyRect = createBoundingBox(0, 0, bodyWidth, bodyHeight);
280
+ // --- Caption -----------------------------------------------------------
281
+ const cs = resolved.captionStyle;
282
+ const captionFontPx = dimensionToPx(cs.fontSize, dpi);
283
+ const captionLineHeightPx = captionFontPx * lineHeightRatio;
284
+ const captionGapPx = dimensionToPx(cs.gap, dpi, captionFontPx);
285
+ // Caption font set (label + description share one typeface/size; weight and
286
+ // slant vary per span).
287
+ const captionFontString = buildFontString(cs.fontFamily, captionFontPx, normalWeight);
288
+ const captionBoldFontString = buildFontString(cs.fontFamily, captionFontPx, boldWeight);
289
+ const captionItalicFontString = buildFontString(cs.fontFamily, captionFontPx, normalWeight, 'italic');
290
+ const captionBoldItalicFontString = buildFontString(cs.fontFamily, captionFontPx, boldWeight, 'italic');
291
+ const captionPrefix = resourceType?.captionPrefix ?? '';
292
+ // Inline `:ref` labels render in the configured reference colour (defaults to
293
+ // the emphasis/bold colour).
294
+ const linkColor = resolved.bodyText.referenceColor.hex;
295
+ let captionLines = [];
296
+ const captionText = resource.caption ?? '';
297
+ const hasCaption = captionText.trim().length > 0 || captionPrefix.length > 0;
298
+ if (hasCaption) {
299
+ // Prefix span: "<captionPrefix> <number>. " (non-breaking inside the label).
300
+ const prefixText = captionPrefix.length > 0
301
+ ? `${captionPrefix}${NBSP}${number}.${number ? ' ' : ''}`
302
+ : '';
303
+ const resolvedSpans = resolveRefSpans(parseRefAwareSpans(captionText), resourceNumbering, resourceTypes, resources, refStyle);
304
+ // Description spans pick up the configured slant on top of their own markup.
305
+ const descSpans = cs.descriptionItalic
306
+ ? resolvedSpans.map((s) => ({ ...s, italic: s.italic || true }))
307
+ : resolvedSpans;
308
+ const allSpans = prefixText.length > 0
309
+ ? [{ text: prefixText, bold: cs.labelBold, italic: cs.labelItalic, captionLabel: true }, ...descSpans]
310
+ : descSpans;
311
+ const measured = measureRichBlock(allSpans, captionFontString, captionBoldFontString, captionItalicFontString, captionBoldItalicFontString, Math.max(1, columnWidth), captionLineHeightPx, { textAlign: cs.align });
312
+ captionLines = shiftLines(measured.lines, 0, bodyHeight + captionGapPx);
313
+ }
314
+ const captionHeight = captionLines.length > 0
315
+ ? captionLines.length * captionLineHeightPx + captionGapPx
316
+ : 0;
317
+ const totalHeight = bodyHeight + captionHeight;
318
+ const block = {
319
+ resource,
320
+ kind: resource.kind,
321
+ number,
322
+ captionPrefix,
323
+ bodyRect,
324
+ fileId,
325
+ format,
326
+ captionLines,
327
+ captionFontString,
328
+ captionBoldFontString,
329
+ captionItalicFontString,
330
+ captionBoldItalicFontString,
331
+ captionColor: cs.color.hex,
332
+ captionLabelColor: cs.labelColor.hex,
333
+ linkColor,
334
+ table,
335
+ };
336
+ return { block, totalHeight };
337
+ }
338
+ //# sourceMappingURL=resourceLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceLayout.js","sourceRoot":"","sources":["../../src/pipeline/resourceLayout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Resource numbering pipeline (issue #49 §3).
3
+ *
4
+ * Assigns a rendered number string (e.g. `"1.7"`) to every resource referenced
5
+ * in the document. Numbering follows **order of first reference** in reading
6
+ * order — a resource is numbered the first time it is encountered, whether via
7
+ * a `::resource{…}` block embed or an inline `:ref{…}`. Inserting a new
8
+ * reference earlier in the document therefore auto-renumbers the rest.
9
+ *
10
+ * The renderer is shared with heading numbering through
11
+ * {@link renderCounterTemplate}; only the template syntax differs. Resource
12
+ * templates use `{n}` for the per-type counter and `{h1}`..`{h6}` for the
13
+ * heading numbers in effect at the point of first reference.
14
+ */
15
+ import type { ContentBlock } from '../parse';
16
+ import type { Resource, ResourceType } from '../types';
17
+ /** Heading counters (1-indexed by level) in effect at a given point in the
18
+ * document. `h1`..`h6` carry the running heading number for each level. */
19
+ export interface HeadingContext {
20
+ h1: number;
21
+ h2: number;
22
+ h3: number;
23
+ h4: number;
24
+ h5: number;
25
+ h6: number;
26
+ }
27
+ export interface ResourceNumberEntry {
28
+ /** The rendered number string (e.g. `"1.7"`). */
29
+ number: string;
30
+ /** The `ResourceType.id` this number was computed for. */
31
+ typeId: string;
32
+ /** The heading counters in effect at the point of first reference. */
33
+ heading: HeadingContext;
34
+ }
35
+ /** Maps each referenced `Resource.id` to its computed numbering entry. */
36
+ export type ResourceNumberingMap = Record<string, ResourceNumberEntry>;
37
+ /** Walk `blocks` and produce, for each block index, the heading counters in
38
+ * effect at that block. A heading at index `i` is reflected in
39
+ * `result[i]` (i.e. the heading counts itself). Mirrors the counter logic in
40
+ * `computeHeadingNumbers` but exposes the raw per-level values rather than the
41
+ * rendered prefix. */
42
+ export declare function computeHeadingContext(blocks: ContentBlock[]): HeadingContext[];
43
+ /**
44
+ * Compute the numbering map for every resource referenced in `blocks`.
45
+ *
46
+ * @param blocks parsed content blocks in reading order
47
+ * @param resourceTypes user-defined resource types (drives template + reset)
48
+ * @param resources known resources (maps `resourceId → typeId`)
49
+ * @param headingContext per-block heading counters (see
50
+ * {@link computeHeadingContext}); must align with
51
+ * `blocks` by index
52
+ */
53
+ export declare function computeResourceNumbering(blocks: ContentBlock[], resourceTypes: ResourceType[], resources: Resource[], headingContext: HeadingContext[]): ResourceNumberingMap;
54
+ //# sourceMappingURL=resourceNumbering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceNumbering.d.ts","sourceRoot":"","sources":["../../src/pipeline/resourceNumbering.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAyB,MAAM,UAAU,CAAC;AAQ9E;4EAC4E;AAC5E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,OAAO,EAAE,cAAc,CAAC;CACzB;AAED,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;AAsBvE;;;;uBAIuB;AACvB,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAoB9E;AAoGD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EAAE,EACtB,aAAa,EAAE,YAAY,EAAE,EAC7B,SAAS,EAAE,QAAQ,EAAE,EACrB,cAAc,EAAE,cAAc,EAAE,GAC/B,oBAAoB,CAwEtB"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Resource numbering pipeline (issue #49 §3).
3
+ *
4
+ * Assigns a rendered number string (e.g. `"1.7"`) to every resource referenced
5
+ * in the document. Numbering follows **order of first reference** in reading
6
+ * order — a resource is numbered the first time it is encountered, whether via
7
+ * a `::resource{…}` block embed or an inline `:ref{…}`. Inserting a new
8
+ * reference earlier in the document therefore auto-renumbers the rest.
9
+ *
10
+ * The renderer is shared with heading numbering through
11
+ * {@link renderCounterTemplate}; only the template syntax differs. Resource
12
+ * templates use `{n}` for the per-type counter and `{h1}`..`{h6}` for the
13
+ * heading numbers in effect at the point of first reference.
14
+ */
15
+ import { formatNumeral, renderCounterTemplate, } from '../numbering';
16
+ const EMPTY_HEADING = { h1: 0, h2: 0, h3: 0, h4: 0, h5: 0, h6: 0 };
17
+ /** Translate a resource `counterFormat` to the shared `NumeralStyle` used by
18
+ * {@link formatNumeral}. The resource model uses `'roman-lower'` style names
19
+ * whereas the numeral formatter uses `'lower-roman'`. */
20
+ function counterFormatToStyle(format) {
21
+ switch (format) {
22
+ case 'decimal':
23
+ return 'decimal';
24
+ case 'roman-lower':
25
+ return 'lower-roman';
26
+ case 'roman-upper':
27
+ return 'upper-roman';
28
+ case 'alpha-lower':
29
+ return 'lower-alpha';
30
+ case 'alpha-upper':
31
+ return 'upper-alpha';
32
+ }
33
+ }
34
+ /** Walk `blocks` and produce, for each block index, the heading counters in
35
+ * effect at that block. A heading at index `i` is reflected in
36
+ * `result[i]` (i.e. the heading counts itself). Mirrors the counter logic in
37
+ * `computeHeadingNumbers` but exposes the raw per-level values rather than the
38
+ * rendered prefix. */
39
+ export function computeHeadingContext(blocks) {
40
+ const counters = [0, 0, 0, 0, 0, 0, 0]; // index 1..6 used
41
+ const out = new Array(blocks.length);
42
+ for (let i = 0; i < blocks.length; i++) {
43
+ const b = blocks[i];
44
+ if (b.type === 'heading' && b.level && b.level >= 1 && b.level <= 6) {
45
+ const lvl = b.level;
46
+ counters[lvl] = (counters[lvl] ?? 0) + 1;
47
+ for (let k = lvl + 1; k <= 6; k++)
48
+ counters[k] = 0;
49
+ }
50
+ out[i] = {
51
+ h1: counters[1] ?? 0,
52
+ h2: counters[2] ?? 0,
53
+ h3: counters[3] ?? 0,
54
+ h4: counters[4] ?? 0,
55
+ h5: counters[5] ?? 0,
56
+ h6: counters[6] ?? 0,
57
+ };
58
+ }
59
+ return out;
60
+ }
61
+ /** Parse a resource numbering template into tokens. Recognizes `{n}` (the
62
+ * per-type counter) and `{h1}`..`{h6}` (heading numbers). Backslash escapes a
63
+ * literal `{`, `}`, or `\`. Unknown `{…}` groups are kept as literal text. */
64
+ function parseResourceTemplate(tpl) {
65
+ const tokens = [];
66
+ let buf = '';
67
+ let i = 0;
68
+ const flush = () => {
69
+ if (buf.length > 0) {
70
+ tokens.push({ kind: 'literal', text: buf });
71
+ buf = '';
72
+ }
73
+ };
74
+ while (i < tpl.length) {
75
+ const ch = tpl[i];
76
+ if (ch === '\\' && i + 1 < tpl.length) {
77
+ const next = tpl[i + 1];
78
+ if (next === '{' || next === '}' || next === '\\') {
79
+ buf += next;
80
+ i += 2;
81
+ continue;
82
+ }
83
+ }
84
+ if (ch === '{') {
85
+ const end = tpl.indexOf('}', i + 1);
86
+ if (end !== -1) {
87
+ const body = tpl.slice(i + 1, end).trim();
88
+ if (body === 'n') {
89
+ flush();
90
+ tokens.push({ kind: 'counter' });
91
+ i = end + 1;
92
+ continue;
93
+ }
94
+ const hMatch = /^h([1-6])$/.exec(body);
95
+ if (hMatch) {
96
+ flush();
97
+ tokens.push({ kind: 'heading', level: Number(hMatch[1]) });
98
+ i = end + 1;
99
+ continue;
100
+ }
101
+ }
102
+ }
103
+ buf += ch;
104
+ i++;
105
+ }
106
+ flush();
107
+ return tokens;
108
+ }
109
+ /** Render a resource template against a per-type counter value and the heading
110
+ * context in effect. Empty heading counters collapse their adjacent separators
111
+ * via {@link renderCounterTemplate} (so `{h1}.{n}` with no h1 renders as the
112
+ * bare counter). */
113
+ function renderResourceNumber(tokens, counterValue, style, heading) {
114
+ const pieces = tokens.map((t) => {
115
+ if (t.kind === 'literal')
116
+ return { kind: 'literal', text: t.text };
117
+ if (t.kind === 'counter') {
118
+ return { kind: 'counter', text: formatNumeral(counterValue, style) };
119
+ }
120
+ const value = heading[`h${t.level}`];
121
+ return { kind: 'counter', text: value > 0 ? formatNumeral(value, 'decimal') : '' };
122
+ });
123
+ return renderCounterTemplate(pieces);
124
+ }
125
+ /** Returns true when the heading context crossed a `resetOn` boundary relative
126
+ * to the previous reference — i.e. the heading number at `resetOn`'s level (or
127
+ * any ancestor level) changed. */
128
+ function shouldResetCounter(prev, cur, resetLevel) {
129
+ if (!prev)
130
+ return false;
131
+ // A reset at level L fires whenever the L-level heading number changed, which
132
+ // also covers ancestor changes (ancestors reset descendants' counters to 0,
133
+ // changing them too).
134
+ for (let lvl = 1; lvl <= resetLevel; lvl = (lvl + 1)) {
135
+ const key = `h${lvl}`;
136
+ if (prev[key] !== cur[key])
137
+ return true;
138
+ }
139
+ return false;
140
+ }
141
+ /**
142
+ * Compute the numbering map for every resource referenced in `blocks`.
143
+ *
144
+ * @param blocks parsed content blocks in reading order
145
+ * @param resourceTypes user-defined resource types (drives template + reset)
146
+ * @param resources known resources (maps `resourceId → typeId`)
147
+ * @param headingContext per-block heading counters (see
148
+ * {@link computeHeadingContext}); must align with
149
+ * `blocks` by index
150
+ */
151
+ export function computeResourceNumbering(blocks, resourceTypes, resources, headingContext) {
152
+ const typeById = new Map();
153
+ for (const t of resourceTypes)
154
+ typeById.set(t.id, t);
155
+ const resourceById = new Map();
156
+ for (const r of resources)
157
+ resourceById.set(r.id, r);
158
+ const firstOccurrences = [];
159
+ const seen = new Set();
160
+ const record = (resourceId, blockIdx) => {
161
+ if (seen.has(resourceId))
162
+ return;
163
+ seen.add(resourceId);
164
+ firstOccurrences.push({
165
+ resourceId,
166
+ heading: headingContext[blockIdx] ?? EMPTY_HEADING,
167
+ });
168
+ };
169
+ for (let i = 0; i < blocks.length; i++) {
170
+ const b = blocks[i];
171
+ if (b.type === 'resourceBlock' && b.resourceId) {
172
+ record(b.resourceId, i);
173
+ }
174
+ for (const span of b.spans) {
175
+ if (span.ref?.resourceId)
176
+ record(span.ref.resourceId, i);
177
+ }
178
+ }
179
+ // Partition by typeId (resolved via the resource), preserving first-reference
180
+ // order. Resources with an unknown id or unknown type are skipped.
181
+ const byType = new Map();
182
+ for (const occ of firstOccurrences) {
183
+ const resource = resourceById.get(occ.resourceId);
184
+ if (!resource)
185
+ continue;
186
+ const type = typeById.get(resource.typeId);
187
+ if (!type)
188
+ continue;
189
+ const list = byType.get(type.id);
190
+ if (list)
191
+ list.push(occ);
192
+ else
193
+ byType.set(type.id, [occ]);
194
+ }
195
+ const map = {};
196
+ for (const [typeId, occurrences] of byType) {
197
+ const type = typeById.get(typeId);
198
+ const tokens = parseResourceTemplate(type.numberingTemplate);
199
+ const style = counterFormatToStyle(type.counterFormat);
200
+ const resetLevel = type.resetOn === 'never' ? null : Number(type.resetOn.slice(1));
201
+ let counter = 0;
202
+ let prevHeading = null;
203
+ for (const occ of occurrences) {
204
+ if (resetLevel !== null && shouldResetCounter(prevHeading, occ.heading, resetLevel)) {
205
+ counter = 0;
206
+ }
207
+ counter += 1;
208
+ prevHeading = occ.heading;
209
+ map[occ.resourceId] = {
210
+ number: renderResourceNumber(tokens, counter, style, occ.heading),
211
+ typeId,
212
+ heading: occ.heading,
213
+ };
214
+ }
215
+ }
216
+ return map;
217
+ }
218
+ //# sourceMappingURL=resourceNumbering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceNumbering.js","sourceRoot":"","sources":["../../src/pipeline/resourceNumbering.ts"],"names":[],"mappings":"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"}