js.documents 1.99.3 → 1.99.5

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.
@@ -11,8 +11,8 @@ declare const DocumentFormatSchema: z.ZodEnum<{
11
11
  odp: "odp";
12
12
  ods: "ods";
13
13
  odg: "odg";
14
- markdown: "markdown";
15
14
  odf: "odf";
15
+ markdown: "markdown";
16
16
  pdf: "pdf";
17
17
  }>;
18
18
  type DocumentFormat = z.infer<typeof DocumentFormatSchema>;
@@ -11,8 +11,8 @@ declare const DocumentFormatSchema: z.ZodEnum<{
11
11
  odp: "odp";
12
12
  ods: "ods";
13
13
  odg: "odg";
14
- markdown: "markdown";
15
14
  odf: "odf";
15
+ markdown: "markdown";
16
16
  pdf: "pdf";
17
17
  }>;
18
18
  type DocumentFormat = z.infer<typeof DocumentFormatSchema>;
@@ -5,7 +5,23 @@ const require_mathml_layout = require("../mathml/layout.cjs");
5
5
  const require_layout_text_layout = require("./text-layout.cjs");
6
6
  const require_layout_shared = require("./shared.cjs");
7
7
  let document_schema_js = require("document-schema.js");
8
+ let markdown_codec = require("markdown-codec");
8
9
  //#region src/layout/engine.ts
10
+ const LIST_INDENT_STEP_PT = 18;
11
+ const BULLET_GLYPHS = [
12
+ "•",
13
+ "-",
14
+ "*"
15
+ ];
16
+ function listMarkerText(list, counters) {
17
+ const info = (0, markdown_codec.parseListNumId)(list.numId);
18
+ if (info?.type === "ordered") {
19
+ const next = counters.get(list.numId) ?? info.start ?? 1;
20
+ counters.set(list.numId, next + 1);
21
+ return `${next}.`;
22
+ }
23
+ return BULLET_GLYPHS[list.level % BULLET_GLYPHS.length];
24
+ }
9
25
  function newFlowState(section) {
10
26
  return {
11
27
  items: [],
@@ -24,12 +40,13 @@ function flushPage(state, section, pages) {
24
40
  function ensureRoom(state, section, pages, neededHeightPt, contentBottomYDown) {
25
41
  if (state.items.length > 0 && state.cursorYDown + neededHeightPt > contentBottomYDown) flushPage(state, section, pages);
26
42
  }
27
- function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer) {
43
+ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters) {
28
44
  if (state.items.length > 0) state.cursorYDown += paragraph.spacingBeforePt ?? 0;
29
- const effectiveRuns = require_layout_shared.effectiveStyledRuns(paragraph.runs);
45
+ const effectiveRuns = require_layout_shared.effectiveStyledRuns(paragraph.runs, 1, require_layout_shared.headingStyleFor(paragraph.styleId));
30
46
  const fallbackRun = effectiveRuns[0];
31
- const paragraphLeftXDown = contentLeftXDown + (paragraph.indentLeftPt ?? 0);
32
- const paragraphWidthPt = Math.max(0, contentWidthPt - (paragraph.indentLeftPt ?? 0));
47
+ const listIndentPt = paragraph.list !== void 0 ? (paragraph.list.level + 1) * LIST_INDENT_STEP_PT : 0;
48
+ const paragraphLeftXDown = contentLeftXDown + (paragraph.indentLeftPt ?? 0) + listIndentPt;
49
+ const paragraphWidthPt = Math.max(0, contentWidthPt - (paragraph.indentLeftPt ?? 0) - listIndentPt);
33
50
  const lines = require_layout_text_layout.wrapRunsToWidth(effectiveRuns, measurer, paragraphWidthPt);
34
51
  lines.forEach((line, lineIndex) => {
35
52
  const lineHeightPt = require_layout_shared.lineNaturalHeightPt(line, measurer, fallbackRun) * (paragraph.lineSpacing ?? 1);
@@ -38,6 +55,16 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
38
55
  const firstLineIndentPt = lineIndex === 0 ? paragraph.indentFirstLinePt ?? 0 : 0;
39
56
  const alignOffsetPt = require_layout_shared.alignmentOffsetPt(paragraph.alignment, paragraphWidthPt, line.widthPt);
40
57
  const justifyGapsPt = paragraph.alignment === "justify" && lineIndex < lines.length - 1 ? require_layout_shared.justifyLineGapsPt(line, paragraphWidthPt, measurer) : void 0;
58
+ if (lineIndex === 0 && paragraph.list !== void 0) state.items.push({
59
+ kind: "text",
60
+ text: listMarkerText(paragraph.list, listCounters),
61
+ xPt: paragraphLeftXDown - LIST_INDENT_STEP_PT,
62
+ yPt: section.pageSize.heightPt - baselineYDown,
63
+ font: fallbackRun.font,
64
+ sizePt: fallbackRun.sizePt,
65
+ color: fallbackRun.color,
66
+ sourcePath: paragraph.sourcePath
67
+ });
41
68
  line.fragments.forEach((fragment, fragmentIndex) => {
42
69
  const xPt = paragraphLeftXDown + firstLineIndentPt + alignOffsetPt + fragment.xOffsetPt + (justifyGapsPt?.[fragmentIndex] ?? 0);
43
70
  const yPt = section.pageSize.heightPt - baselineYDown;
@@ -71,12 +98,13 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
71
98
  });
72
99
  state.cursorYDown += paragraph.spacingAfterPt ?? 0;
73
100
  }
74
- function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown, pageHeightPt, measurer, out) {
101
+ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown, pageHeightPt, measurer, out, listCounters) {
75
102
  let cursorYDown = startYDown + (paragraph.spacingBeforePt ?? 0);
76
- const effectiveRuns = require_layout_shared.effectiveStyledRuns(paragraph.runs);
103
+ const effectiveRuns = require_layout_shared.effectiveStyledRuns(paragraph.runs, 1, require_layout_shared.headingStyleFor(paragraph.styleId));
77
104
  const fallbackRun = effectiveRuns[0];
78
- const paragraphLeftXDown = cellLeftXDown + (paragraph.indentLeftPt ?? 0);
79
- const paragraphWidthPt = Math.max(0, cellWidthPt - (paragraph.indentLeftPt ?? 0));
105
+ const listIndentPt = paragraph.list !== void 0 ? (paragraph.list.level + 1) * LIST_INDENT_STEP_PT : 0;
106
+ const paragraphLeftXDown = cellLeftXDown + (paragraph.indentLeftPt ?? 0) + listIndentPt;
107
+ const paragraphWidthPt = Math.max(0, cellWidthPt - (paragraph.indentLeftPt ?? 0) - listIndentPt);
80
108
  const lines = require_layout_text_layout.wrapRunsToWidth(effectiveRuns, measurer, paragraphWidthPt);
81
109
  lines.forEach((line, lineIndex) => {
82
110
  const lineHeightPt = require_layout_shared.lineNaturalHeightPt(line, measurer, fallbackRun) * (paragraph.lineSpacing ?? 1);
@@ -84,6 +112,16 @@ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown
84
112
  const firstLineIndentPt = lineIndex === 0 ? paragraph.indentFirstLinePt ?? 0 : 0;
85
113
  const alignOffsetPt = require_layout_shared.alignmentOffsetPt(paragraph.alignment, paragraphWidthPt, line.widthPt);
86
114
  const justifyGapsPt = paragraph.alignment === "justify" && lineIndex < lines.length - 1 ? require_layout_shared.justifyLineGapsPt(line, paragraphWidthPt, measurer) : void 0;
115
+ if (lineIndex === 0 && paragraph.list !== void 0) out.push({
116
+ kind: "text",
117
+ text: listMarkerText(paragraph.list, listCounters),
118
+ xPt: paragraphLeftXDown - LIST_INDENT_STEP_PT,
119
+ yPt: pageHeightPt - baselineYDown,
120
+ font: fallbackRun.font,
121
+ sizePt: fallbackRun.sizePt,
122
+ color: fallbackRun.color,
123
+ sourcePath: paragraph.sourcePath
124
+ });
87
125
  line.fragments.forEach((fragment, fragmentIndex) => {
88
126
  out.push({
89
127
  kind: "text",
@@ -101,7 +139,7 @@ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown
101
139
  });
102
140
  return cursorYDown + (paragraph.spacingAfterPt ?? 0);
103
141
  }
104
- function layoutTableFlow(table, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer) {
142
+ function layoutTableFlow(table, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters) {
105
143
  const gridWidthPt = table.columnWidthsPt.reduce((sum, w) => sum + w, 0);
106
144
  const scale = gridWidthPt > 0 ? contentWidthPt / gridWidthPt : 1;
107
145
  for (const row of table.rows) {
@@ -133,7 +171,7 @@ function layoutTableFlow(table, section, pages, state, contentLeftXDown, content
133
171
  }
134
172
  if (cell.borders !== void 0) require_layout_shared.pushCellBorderLines(cell.borders, cellFrameYDown, section.pageSize.heightPt, cellSourcePath, state.items);
135
173
  let cellCursorYDown = state.cursorYDown;
136
- for (const block of cell.blocks) if (block.kind === "paragraph") cellCursorYDown = layoutParagraphInCell(block, cellXDown, cellWidthPt, cellCursorYDown, section.pageSize.heightPt, measurer, state.items);
174
+ for (const block of cell.blocks) if (block.kind === "paragraph") cellCursorYDown = layoutParagraphInCell(block, cellXDown, cellWidthPt, cellCursorYDown, section.pageSize.heightPt, measurer, state.items, listCounters);
137
175
  cellXDown += cellWidthPt;
138
176
  colIndex += span;
139
177
  }
@@ -161,18 +199,18 @@ function layoutImageFlow(block, section, pages, state, contentLeftXDown, content
161
199
  state.items.push(imageItem);
162
200
  state.cursorYDown += block.heightPt;
163
201
  }
164
- function layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer) {
202
+ function layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters) {
165
203
  const formula = require_model_formula.formulaOfBlock(block);
166
204
  if (formula === void 0) return;
167
205
  layoutParagraphFlow({
168
206
  kind: "paragraph",
169
207
  runs: [{ text: require_model_formula.formulaPlaceholderText(formula) }]
170
- }, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
208
+ }, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
171
209
  }
172
- function layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, mathMetricsAt, formulas) {
210
+ function layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, mathMetricsAt, formulas, listCounters) {
173
211
  const formula = require_model_formula.formulaOfBlock(block);
174
212
  if (formula === void 0 || formula.mathml.length === 0) {
175
- layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
213
+ layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
176
214
  return;
177
215
  }
178
216
  const sizePt = require_layout_shared.formulaSizePtForFrame(formula.mathml, block.frame, mathMetricsAt);
@@ -197,24 +235,25 @@ function layoutFormulaFlow(block, section, pages, state, contentLeftXDown, conte
197
235
  });
198
236
  state.cursorYDown += box.heightPt;
199
237
  }
200
- function paginateSection(section, measurer, images, pages, options, formulas) {
238
+ function paginateSection(section, measurer, images, pages, options, formulas, listCounters) {
201
239
  const contentLeftXDown = section.margins.leftPt;
202
240
  const contentWidthPt = Math.max(0, section.pageSize.widthPt - section.margins.leftPt - section.margins.rightPt);
203
241
  const contentBottomYDown = section.pageSize.heightPt - section.margins.bottomPt;
204
242
  const state = newFlowState(section);
205
243
  for (const block of section.blocks) if (block.kind === "pageBreak") {
206
244
  if (state.items.length > 0) flushPage(state, section, pages);
207
- } else if (block.kind === "paragraph") layoutParagraphFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
208
- else if (block.kind === "table") layoutTableFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
245
+ } else if (block.kind === "paragraph") layoutParagraphFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
246
+ else if (block.kind === "table") layoutTableFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
209
247
  else if (block.kind === "image") layoutImageFlow(block, section, pages, state, contentLeftXDown, contentBottomYDown, images);
210
- else if (block.kind === "embeddedObject" && block.objectKind === "formula") layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, options.mathMetricsAt, formulas);
248
+ else if (block.kind === "embeddedObject" && block.objectKind === "formula") layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, options.mathMetricsAt, formulas, listCounters);
211
249
  flushPage(state, section, pages);
212
250
  }
213
251
  function convertWordprocessingToLayout(doc, options) {
214
252
  const images = {};
215
253
  const pages = [];
216
254
  const formulas = [];
217
- for (const section of doc.sections) paginateSection(section, options.measurer, images, pages, options, formulas);
255
+ const listCounters = /* @__PURE__ */ new Map();
256
+ for (const section of doc.sections) paginateSection(section, options.measurer, images, pages, options, formulas, listCounters);
218
257
  return {
219
258
  document: {
220
259
  formatVersion: document_schema_js.LAYOUT_FORMAT_VERSION,
@@ -2,9 +2,25 @@ import { flipY } from "../model/geometry.js";
2
2
  import { formulaOfBlock, formulaPlaceholderText } from "../model/formula.js";
3
3
  import { layoutFormula } from "../mathml/layout.js";
4
4
  import { wrapRunsToWidth } from "./text-layout.js";
5
- import { alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, sumColumnWidthsPt } from "./shared.js";
5
+ import { alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, headingStyleFor, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, sumColumnWidthsPt } from "./shared.js";
6
6
  import { COLOR_BLACK, LAYOUT_FORMAT_VERSION } from "document-schema.js";
7
+ import { parseListNumId } from "markdown-codec";
7
8
  //#region src/layout/engine.ts
9
+ const LIST_INDENT_STEP_PT = 18;
10
+ const BULLET_GLYPHS = [
11
+ "•",
12
+ "-",
13
+ "*"
14
+ ];
15
+ function listMarkerText(list, counters) {
16
+ const info = parseListNumId(list.numId);
17
+ if (info?.type === "ordered") {
18
+ const next = counters.get(list.numId) ?? info.start ?? 1;
19
+ counters.set(list.numId, next + 1);
20
+ return `${next}.`;
21
+ }
22
+ return BULLET_GLYPHS[list.level % BULLET_GLYPHS.length];
23
+ }
8
24
  function newFlowState(section) {
9
25
  return {
10
26
  items: [],
@@ -23,12 +39,13 @@ function flushPage(state, section, pages) {
23
39
  function ensureRoom(state, section, pages, neededHeightPt, contentBottomYDown) {
24
40
  if (state.items.length > 0 && state.cursorYDown + neededHeightPt > contentBottomYDown) flushPage(state, section, pages);
25
41
  }
26
- function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer) {
42
+ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters) {
27
43
  if (state.items.length > 0) state.cursorYDown += paragraph.spacingBeforePt ?? 0;
28
- const effectiveRuns = effectiveStyledRuns(paragraph.runs);
44
+ const effectiveRuns = effectiveStyledRuns(paragraph.runs, 1, headingStyleFor(paragraph.styleId));
29
45
  const fallbackRun = effectiveRuns[0];
30
- const paragraphLeftXDown = contentLeftXDown + (paragraph.indentLeftPt ?? 0);
31
- const paragraphWidthPt = Math.max(0, contentWidthPt - (paragraph.indentLeftPt ?? 0));
46
+ const listIndentPt = paragraph.list !== void 0 ? (paragraph.list.level + 1) * LIST_INDENT_STEP_PT : 0;
47
+ const paragraphLeftXDown = contentLeftXDown + (paragraph.indentLeftPt ?? 0) + listIndentPt;
48
+ const paragraphWidthPt = Math.max(0, contentWidthPt - (paragraph.indentLeftPt ?? 0) - listIndentPt);
32
49
  const lines = wrapRunsToWidth(effectiveRuns, measurer, paragraphWidthPt);
33
50
  lines.forEach((line, lineIndex) => {
34
51
  const lineHeightPt = lineNaturalHeightPt(line, measurer, fallbackRun) * (paragraph.lineSpacing ?? 1);
@@ -37,6 +54,16 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
37
54
  const firstLineIndentPt = lineIndex === 0 ? paragraph.indentFirstLinePt ?? 0 : 0;
38
55
  const alignOffsetPt = alignmentOffsetPt(paragraph.alignment, paragraphWidthPt, line.widthPt);
39
56
  const justifyGapsPt = paragraph.alignment === "justify" && lineIndex < lines.length - 1 ? justifyLineGapsPt(line, paragraphWidthPt, measurer) : void 0;
57
+ if (lineIndex === 0 && paragraph.list !== void 0) state.items.push({
58
+ kind: "text",
59
+ text: listMarkerText(paragraph.list, listCounters),
60
+ xPt: paragraphLeftXDown - LIST_INDENT_STEP_PT,
61
+ yPt: section.pageSize.heightPt - baselineYDown,
62
+ font: fallbackRun.font,
63
+ sizePt: fallbackRun.sizePt,
64
+ color: fallbackRun.color,
65
+ sourcePath: paragraph.sourcePath
66
+ });
40
67
  line.fragments.forEach((fragment, fragmentIndex) => {
41
68
  const xPt = paragraphLeftXDown + firstLineIndentPt + alignOffsetPt + fragment.xOffsetPt + (justifyGapsPt?.[fragmentIndex] ?? 0);
42
69
  const yPt = section.pageSize.heightPt - baselineYDown;
@@ -70,12 +97,13 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
70
97
  });
71
98
  state.cursorYDown += paragraph.spacingAfterPt ?? 0;
72
99
  }
73
- function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown, pageHeightPt, measurer, out) {
100
+ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown, pageHeightPt, measurer, out, listCounters) {
74
101
  let cursorYDown = startYDown + (paragraph.spacingBeforePt ?? 0);
75
- const effectiveRuns = effectiveStyledRuns(paragraph.runs);
102
+ const effectiveRuns = effectiveStyledRuns(paragraph.runs, 1, headingStyleFor(paragraph.styleId));
76
103
  const fallbackRun = effectiveRuns[0];
77
- const paragraphLeftXDown = cellLeftXDown + (paragraph.indentLeftPt ?? 0);
78
- const paragraphWidthPt = Math.max(0, cellWidthPt - (paragraph.indentLeftPt ?? 0));
104
+ const listIndentPt = paragraph.list !== void 0 ? (paragraph.list.level + 1) * LIST_INDENT_STEP_PT : 0;
105
+ const paragraphLeftXDown = cellLeftXDown + (paragraph.indentLeftPt ?? 0) + listIndentPt;
106
+ const paragraphWidthPt = Math.max(0, cellWidthPt - (paragraph.indentLeftPt ?? 0) - listIndentPt);
79
107
  const lines = wrapRunsToWidth(effectiveRuns, measurer, paragraphWidthPt);
80
108
  lines.forEach((line, lineIndex) => {
81
109
  const lineHeightPt = lineNaturalHeightPt(line, measurer, fallbackRun) * (paragraph.lineSpacing ?? 1);
@@ -83,6 +111,16 @@ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown
83
111
  const firstLineIndentPt = lineIndex === 0 ? paragraph.indentFirstLinePt ?? 0 : 0;
84
112
  const alignOffsetPt = alignmentOffsetPt(paragraph.alignment, paragraphWidthPt, line.widthPt);
85
113
  const justifyGapsPt = paragraph.alignment === "justify" && lineIndex < lines.length - 1 ? justifyLineGapsPt(line, paragraphWidthPt, measurer) : void 0;
114
+ if (lineIndex === 0 && paragraph.list !== void 0) out.push({
115
+ kind: "text",
116
+ text: listMarkerText(paragraph.list, listCounters),
117
+ xPt: paragraphLeftXDown - LIST_INDENT_STEP_PT,
118
+ yPt: pageHeightPt - baselineYDown,
119
+ font: fallbackRun.font,
120
+ sizePt: fallbackRun.sizePt,
121
+ color: fallbackRun.color,
122
+ sourcePath: paragraph.sourcePath
123
+ });
86
124
  line.fragments.forEach((fragment, fragmentIndex) => {
87
125
  out.push({
88
126
  kind: "text",
@@ -100,7 +138,7 @@ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown
100
138
  });
101
139
  return cursorYDown + (paragraph.spacingAfterPt ?? 0);
102
140
  }
103
- function layoutTableFlow(table, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer) {
141
+ function layoutTableFlow(table, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters) {
104
142
  const gridWidthPt = table.columnWidthsPt.reduce((sum, w) => sum + w, 0);
105
143
  const scale = gridWidthPt > 0 ? contentWidthPt / gridWidthPt : 1;
106
144
  for (const row of table.rows) {
@@ -132,7 +170,7 @@ function layoutTableFlow(table, section, pages, state, contentLeftXDown, content
132
170
  }
133
171
  if (cell.borders !== void 0) pushCellBorderLines(cell.borders, cellFrameYDown, section.pageSize.heightPt, cellSourcePath, state.items);
134
172
  let cellCursorYDown = state.cursorYDown;
135
- for (const block of cell.blocks) if (block.kind === "paragraph") cellCursorYDown = layoutParagraphInCell(block, cellXDown, cellWidthPt, cellCursorYDown, section.pageSize.heightPt, measurer, state.items);
173
+ for (const block of cell.blocks) if (block.kind === "paragraph") cellCursorYDown = layoutParagraphInCell(block, cellXDown, cellWidthPt, cellCursorYDown, section.pageSize.heightPt, measurer, state.items, listCounters);
136
174
  cellXDown += cellWidthPt;
137
175
  colIndex += span;
138
176
  }
@@ -160,18 +198,18 @@ function layoutImageFlow(block, section, pages, state, contentLeftXDown, content
160
198
  state.items.push(imageItem);
161
199
  state.cursorYDown += block.heightPt;
162
200
  }
163
- function layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer) {
201
+ function layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters) {
164
202
  const formula = formulaOfBlock(block);
165
203
  if (formula === void 0) return;
166
204
  layoutParagraphFlow({
167
205
  kind: "paragraph",
168
206
  runs: [{ text: formulaPlaceholderText(formula) }]
169
- }, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
207
+ }, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
170
208
  }
171
- function layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, mathMetricsAt, formulas) {
209
+ function layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, mathMetricsAt, formulas, listCounters) {
172
210
  const formula = formulaOfBlock(block);
173
211
  if (formula === void 0 || formula.mathml.length === 0) {
174
- layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
212
+ layoutFormulaFallback(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
175
213
  return;
176
214
  }
177
215
  const sizePt = formulaSizePtForFrame(formula.mathml, block.frame, mathMetricsAt);
@@ -196,24 +234,25 @@ function layoutFormulaFlow(block, section, pages, state, contentLeftXDown, conte
196
234
  });
197
235
  state.cursorYDown += box.heightPt;
198
236
  }
199
- function paginateSection(section, measurer, images, pages, options, formulas) {
237
+ function paginateSection(section, measurer, images, pages, options, formulas, listCounters) {
200
238
  const contentLeftXDown = section.margins.leftPt;
201
239
  const contentWidthPt = Math.max(0, section.pageSize.widthPt - section.margins.leftPt - section.margins.rightPt);
202
240
  const contentBottomYDown = section.pageSize.heightPt - section.margins.bottomPt;
203
241
  const state = newFlowState(section);
204
242
  for (const block of section.blocks) if (block.kind === "pageBreak") {
205
243
  if (state.items.length > 0) flushPage(state, section, pages);
206
- } else if (block.kind === "paragraph") layoutParagraphFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
207
- else if (block.kind === "table") layoutTableFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer);
244
+ } else if (block.kind === "paragraph") layoutParagraphFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
245
+ else if (block.kind === "table") layoutTableFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, listCounters);
208
246
  else if (block.kind === "image") layoutImageFlow(block, section, pages, state, contentLeftXDown, contentBottomYDown, images);
209
- else if (block.kind === "embeddedObject" && block.objectKind === "formula") layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, options.mathMetricsAt, formulas);
247
+ else if (block.kind === "embeddedObject" && block.objectKind === "formula") layoutFormulaFlow(block, section, pages, state, contentLeftXDown, contentWidthPt, contentBottomYDown, measurer, options.mathMetricsAt, formulas, listCounters);
210
248
  flushPage(state, section, pages);
211
249
  }
212
250
  function convertWordprocessingToLayout(doc, options) {
213
251
  const images = {};
214
252
  const pages = [];
215
253
  const formulas = [];
216
- for (const section of doc.sections) paginateSection(section, options.measurer, images, pages, options, formulas);
254
+ const listCounters = /* @__PURE__ */ new Map();
255
+ for (const section of doc.sections) paginateSection(section, options.measurer, images, pages, options, formulas, listCounters);
217
256
  return {
218
257
  document: {
219
258
  formatVersion: LAYOUT_FORMAT_VERSION,
@@ -20,26 +20,59 @@ function formulaSizePtForFrame(mathml, frame, mathMetricsAt) {
20
20
  return Math.max(MIN_FORMULA_SIZE_PT, REFERENCE_FORMULA_SIZE_PT * Math.min(heightScale, widthScale));
21
21
  }
22
22
  const FALLBACK_ROW_HEIGHT_PT = 20;
23
- function runFont(run) {
23
+ const HEADING_STYLES = {
24
+ 1: {
25
+ bold: true,
26
+ sizePt: 28
27
+ },
28
+ 2: {
29
+ bold: true,
30
+ sizePt: 22
31
+ },
32
+ 3: {
33
+ bold: true,
34
+ sizePt: 18
35
+ },
36
+ 4: {
37
+ bold: true,
38
+ sizePt: 14
39
+ },
40
+ 5: {
41
+ bold: true,
42
+ sizePt: 12
43
+ },
44
+ 6: {
45
+ bold: true,
46
+ sizePt: 11
47
+ }
48
+ };
49
+ function headingStyleFor(styleId) {
50
+ if (styleId === void 0) return void 0;
51
+ const match = /^Heading([1-6])$/.exec(styleId);
52
+ if (match === null) return void 0;
53
+ return HEADING_STYLES[Number(match[1])];
54
+ }
55
+ function runFont(run, headingBold) {
56
+ const bold = run.bold ?? headingBold ?? false;
24
57
  return {
25
58
  family: run.fontFamily ?? document_schema_js.DEFAULT_LAYOUT_FONT.family,
26
- weight: run.bold === true ? "bold" : "normal",
59
+ weight: bold ? "bold" : "normal",
27
60
  style: run.italic === true ? "italic" : "normal"
28
61
  };
29
62
  }
30
- function toStyledRuns(runs, fontScale = 1) {
63
+ function toStyledRuns(runs, fontScale = 1, headingStyle) {
31
64
  return runs.map((run) => ({
32
65
  text: run.text,
33
- font: runFont(run),
34
- sizePt: (run.sizePt ?? 18) * fontScale,
66
+ font: runFont(run, headingStyle?.bold),
67
+ sizePt: (run.sizePt ?? headingStyle?.sizePt ?? 18) * fontScale,
35
68
  color: run.color ?? document_schema_js.COLOR_BLACK,
36
69
  underline: run.underline,
37
70
  hyperlink: run.hyperlink,
38
71
  sourcePath: run.sourcePath
39
72
  }));
40
73
  }
41
- function effectiveStyledRuns(runs, fontScale = 1) {
42
- const styled = toStyledRuns(runs, fontScale);
74
+ function effectiveStyledRuns(runs, fontScale = 1, headingStyle) {
75
+ const styled = toStyledRuns(runs, fontScale, headingStyle);
43
76
  return styled.length > 0 ? styled : [{
44
77
  text: "",
45
78
  font: document_schema_js.DEFAULT_LAYOUT_FONT,
@@ -150,7 +183,7 @@ function estimateRowHeightPt(row, measurer, columnWidthsPt, scale) {
150
183
  const cellWidthPt = sumColumnWidthsPt(columnWidthsPt, colIndex, span) * scale;
151
184
  for (const block of cell.blocks) {
152
185
  if (block.kind !== "paragraph") continue;
153
- const runs = effectiveStyledRuns(block.runs);
186
+ const runs = effectiveStyledRuns(block.runs, 1, headingStyleFor(block.styleId));
154
187
  const lines = require_layout_text_layout.wrapRunsToWidth(runs, measurer, cellWidthPt);
155
188
  for (const line of lines) max = Math.max(max, lineNaturalHeightPt(line, measurer, runs[0]));
156
189
  }
@@ -164,6 +197,7 @@ exports.alignmentOffsetPt = alignmentOffsetPt;
164
197
  exports.effectiveStyledRuns = effectiveStyledRuns;
165
198
  exports.estimateRowHeightPt = estimateRowHeightPt;
166
199
  exports.formulaSizePtForFrame = formulaSizePtForFrame;
200
+ exports.headingStyleFor = headingStyleFor;
167
201
  exports.justifyLineGapsPt = justifyLineGapsPt;
168
202
  exports.lineNaturalHeightPt = lineNaturalHeightPt;
169
203
  exports.pushCellBorderLines = pushCellBorderLines;
@@ -2,9 +2,19 @@ import { Alignment, Box, ContentCellBorders, ContentImageBlock, ContentRun, Cont
2
2
  //#region src/layout/shared.d.ts
3
3
  declare const NOMINAL_TEXT_SIZE_PT = 18;
4
4
  declare function formulaSizePtForFrame(mathml: readonly MathMlNode[], frame: Box, mathMetricsAt: (sizePt: number) => MathFontMetrics): number;
5
- declare function runFont(run: ContentRun): LayoutFont;
6
- declare function toStyledRuns(runs: readonly ContentRun[], fontScale?: number): StyledRun[];
7
- declare function effectiveStyledRuns(runs: readonly ContentRun[], fontScale?: number): StyledRun[];
5
+ declare function headingStyleFor(styleId: string | undefined): {
6
+ bold: boolean;
7
+ sizePt: number;
8
+ } | undefined;
9
+ declare function runFont(run: ContentRun, headingBold?: boolean): LayoutFont;
10
+ declare function toStyledRuns(runs: readonly ContentRun[], fontScale?: number, headingStyle?: {
11
+ bold: boolean;
12
+ sizePt: number;
13
+ }): StyledRun[];
14
+ declare function effectiveStyledRuns(runs: readonly ContentRun[], fontScale?: number, headingStyle?: {
15
+ bold: boolean;
16
+ sizePt: number;
17
+ }): StyledRun[];
8
18
  declare function lineNaturalHeightPt(line: WrappedLine, measurer: TextMeasurer, fallback: StyledRun): number;
9
19
  declare function alignmentOffsetPt(alignment: Alignment | undefined, contentWidthPt: number, lineWidthPt: number): number;
10
20
  declare function justifyLineGapsPt(line: WrappedLine, targetWidthPt: number, measurer: TextMeasurer): readonly number[];
@@ -13,4 +23,4 @@ declare function registerImage(block: ContentImageBlock, images: Record<string,
13
23
  declare function sumColumnWidthsPt(columnWidthsPt: readonly number[], startIndex: number, span: number): number;
14
24
  declare function estimateRowHeightPt(row: ContentTableRow, measurer: TextMeasurer, columnWidthsPt: readonly number[], scale: number): number;
15
25
  //#endregion
16
- export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
26
+ export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, headingStyleFor, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
@@ -2,9 +2,19 @@ import { Alignment, Box, ContentCellBorders, ContentImageBlock, ContentRun, Cont
2
2
  //#region src/layout/shared.d.ts
3
3
  declare const NOMINAL_TEXT_SIZE_PT = 18;
4
4
  declare function formulaSizePtForFrame(mathml: readonly MathMlNode[], frame: Box, mathMetricsAt: (sizePt: number) => MathFontMetrics): number;
5
- declare function runFont(run: ContentRun): LayoutFont;
6
- declare function toStyledRuns(runs: readonly ContentRun[], fontScale?: number): StyledRun[];
7
- declare function effectiveStyledRuns(runs: readonly ContentRun[], fontScale?: number): StyledRun[];
5
+ declare function headingStyleFor(styleId: string | undefined): {
6
+ bold: boolean;
7
+ sizePt: number;
8
+ } | undefined;
9
+ declare function runFont(run: ContentRun, headingBold?: boolean): LayoutFont;
10
+ declare function toStyledRuns(runs: readonly ContentRun[], fontScale?: number, headingStyle?: {
11
+ bold: boolean;
12
+ sizePt: number;
13
+ }): StyledRun[];
14
+ declare function effectiveStyledRuns(runs: readonly ContentRun[], fontScale?: number, headingStyle?: {
15
+ bold: boolean;
16
+ sizePt: number;
17
+ }): StyledRun[];
8
18
  declare function lineNaturalHeightPt(line: WrappedLine, measurer: TextMeasurer, fallback: StyledRun): number;
9
19
  declare function alignmentOffsetPt(alignment: Alignment | undefined, contentWidthPt: number, lineWidthPt: number): number;
10
20
  declare function justifyLineGapsPt(line: WrappedLine, targetWidthPt: number, measurer: TextMeasurer): readonly number[];
@@ -13,4 +23,4 @@ declare function registerImage(block: ContentImageBlock, images: Record<string,
13
23
  declare function sumColumnWidthsPt(columnWidthsPt: readonly number[], startIndex: number, span: number): number;
14
24
  declare function estimateRowHeightPt(row: ContentTableRow, measurer: TextMeasurer, columnWidthsPt: readonly number[], scale: number): number;
15
25
  //#endregion
16
- export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
26
+ export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, headingStyleFor, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
@@ -19,26 +19,59 @@ function formulaSizePtForFrame(mathml, frame, mathMetricsAt) {
19
19
  return Math.max(MIN_FORMULA_SIZE_PT, REFERENCE_FORMULA_SIZE_PT * Math.min(heightScale, widthScale));
20
20
  }
21
21
  const FALLBACK_ROW_HEIGHT_PT = 20;
22
- function runFont(run) {
22
+ const HEADING_STYLES = {
23
+ 1: {
24
+ bold: true,
25
+ sizePt: 28
26
+ },
27
+ 2: {
28
+ bold: true,
29
+ sizePt: 22
30
+ },
31
+ 3: {
32
+ bold: true,
33
+ sizePt: 18
34
+ },
35
+ 4: {
36
+ bold: true,
37
+ sizePt: 14
38
+ },
39
+ 5: {
40
+ bold: true,
41
+ sizePt: 12
42
+ },
43
+ 6: {
44
+ bold: true,
45
+ sizePt: 11
46
+ }
47
+ };
48
+ function headingStyleFor(styleId) {
49
+ if (styleId === void 0) return void 0;
50
+ const match = /^Heading([1-6])$/.exec(styleId);
51
+ if (match === null) return void 0;
52
+ return HEADING_STYLES[Number(match[1])];
53
+ }
54
+ function runFont(run, headingBold) {
55
+ const bold = run.bold ?? headingBold ?? false;
23
56
  return {
24
57
  family: run.fontFamily ?? DEFAULT_LAYOUT_FONT.family,
25
- weight: run.bold === true ? "bold" : "normal",
58
+ weight: bold ? "bold" : "normal",
26
59
  style: run.italic === true ? "italic" : "normal"
27
60
  };
28
61
  }
29
- function toStyledRuns(runs, fontScale = 1) {
62
+ function toStyledRuns(runs, fontScale = 1, headingStyle) {
30
63
  return runs.map((run) => ({
31
64
  text: run.text,
32
- font: runFont(run),
33
- sizePt: (run.sizePt ?? 18) * fontScale,
65
+ font: runFont(run, headingStyle?.bold),
66
+ sizePt: (run.sizePt ?? headingStyle?.sizePt ?? 18) * fontScale,
34
67
  color: run.color ?? COLOR_BLACK,
35
68
  underline: run.underline,
36
69
  hyperlink: run.hyperlink,
37
70
  sourcePath: run.sourcePath
38
71
  }));
39
72
  }
40
- function effectiveStyledRuns(runs, fontScale = 1) {
41
- const styled = toStyledRuns(runs, fontScale);
73
+ function effectiveStyledRuns(runs, fontScale = 1, headingStyle) {
74
+ const styled = toStyledRuns(runs, fontScale, headingStyle);
42
75
  return styled.length > 0 ? styled : [{
43
76
  text: "",
44
77
  font: DEFAULT_LAYOUT_FONT,
@@ -149,7 +182,7 @@ function estimateRowHeightPt(row, measurer, columnWidthsPt, scale) {
149
182
  const cellWidthPt = sumColumnWidthsPt(columnWidthsPt, colIndex, span) * scale;
150
183
  for (const block of cell.blocks) {
151
184
  if (block.kind !== "paragraph") continue;
152
- const runs = effectiveStyledRuns(block.runs);
185
+ const runs = effectiveStyledRuns(block.runs, 1, headingStyleFor(block.styleId));
153
186
  const lines = wrapRunsToWidth(runs, measurer, cellWidthPt);
154
187
  for (const line of lines) max = Math.max(max, lineNaturalHeightPt(line, measurer, runs[0]));
155
188
  }
@@ -158,4 +191,4 @@ function estimateRowHeightPt(row, measurer, columnWidthsPt, scale) {
158
191
  return max;
159
192
  }
160
193
  //#endregion
161
- export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
194
+ export { NOMINAL_TEXT_SIZE_PT, alignmentOffsetPt, effectiveStyledRuns, estimateRowHeightPt, formulaSizePtForFrame, headingStyleFor, justifyLineGapsPt, lineNaturalHeightPt, pushCellBorderLines, registerImage, runFont, sumColumnWidthsPt, toStyledRuns };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js.documents",
3
- "version": "1.99.3",
3
+ "version": "1.99.5",
4
4
  "description": "Bidirectional docx/pptx <-> PDF conversion and a read+write editable OOXML document model, built on ooxml.js and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {