jspdf-md-renderer 3.5.1 → 4.0.1

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
@@ -2,6 +2,15 @@
2
2
 
3
3
  A jsPDF utility to render Markdown directly into formatted PDFs with custom designs.
4
4
 
5
+ ## What's New in v4
6
+
7
+ - Unified inline layout engine for consistent wrapping/alignment.
8
+ - Safe wrapping for long unbroken tokens (long URLs, long inline code).
9
+ - Heading scale controls (`heading.h1` ... `heading.h6`).
10
+ - Task list support (`- [x]` / `- [ ]`).
11
+ - Header/footer + page numbers.
12
+ - Spacing system (`spacing.*`) and richer style options (`codeBlock`, `blockquote`, `list`, `paragraph`).
13
+
5
14
  [![npm version](https://img.shields.io/npm/v/jspdf-md-renderer.svg)](https://www.npmjs.com/package/jspdf-md-renderer)
6
15
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
16
  [![Downloads](https://img.shields.io/npm/dm/jspdf-md-renderer.svg)](https://www.npmjs.com/package/jspdf-md-renderer)
@@ -113,6 +122,25 @@ const generatePDF = async () => {
113
122
  regular: { name: 'helvetica', style: 'normal' },
114
123
  light: { name: 'helvetica', style: 'light' },
115
124
  },
125
+ heading: {
126
+ h1: 24,
127
+ h2: 20,
128
+ h3: 17,
129
+ h4: 15,
130
+ h5: 13,
131
+ h6: 12,
132
+ color: '#1A365D',
133
+ },
134
+ spacing: {
135
+ afterParagraph: 4,
136
+ afterHeading: 2,
137
+ afterCodeBlock: 4,
138
+ betweenListItems: 1,
139
+ },
140
+ footer: {
141
+ showPageNumbers: true,
142
+ align: 'right',
143
+ },
116
144
  endCursorYHandler: (y) => {
117
145
  console.log('End cursor Y position:', y);
118
146
  },
@@ -262,6 +290,38 @@ The following Markdown elements are currently supported by `jspdf-md-renderer`:
262
290
  | Row 2 | Data | Value |
263
291
  ```
264
292
 
293
+ ## New Options (v4 quick reference)
294
+
295
+ ```ts
296
+ const options = {
297
+ heading: { h1: 26, h2: 22, h3: 18, bottomSpacing: 3 },
298
+ list: { bulletChar: '• ', indentSize: 8, itemSpacing: 0 },
299
+ paragraph: { bottomSpacing: 3, color: '#111827' },
300
+ blockquote: { barColor: '#4A90D9', barWidth: 2, paddingLeft: 6 },
301
+ codeBlock: {
302
+ backgroundColor: '#F6F8FA',
303
+ borderColor: '#E1E4E8',
304
+ borderRadius: 3,
305
+ padding: 5,
306
+ showLanguageLabel: true,
307
+ textColor: '#111827',
308
+ },
309
+ spacing: {
310
+ afterHeading: 2,
311
+ afterParagraph: 4,
312
+ afterCodeBlock: 4,
313
+ afterBlockquote: 3,
314
+ afterImage: 2,
315
+ afterHR: 2,
316
+ betweenListItems: 0,
317
+ afterList: 3,
318
+ afterTable: 3,
319
+ },
320
+ header: { text: 'My Report', align: 'center', color: '#6b7280', fontSize: 9 },
321
+ footer: { showPageNumbers: true, align: 'right' },
322
+ }
323
+ ```
324
+
265
325
  ## Examples
266
326
 
267
327
  You can explore complete rendered examples in the documentation site:
package/dist/index.d.mts CHANGED
@@ -35,7 +35,7 @@ type RenderOption = {
35
35
  };
36
36
  page: {
37
37
  format?: string | number[];
38
- unit?: jsPDFOptions['unit'];
38
+ unit: jsPDFOptions['unit'];
39
39
  orientation?: jsPDFOptions['orientation'];
40
40
  maxContentWidth: number;
41
41
  maxContentHeight: number;
@@ -52,8 +52,42 @@ type RenderOption = {
52
52
  bold: FontItem;
53
53
  regular: FontItem;
54
54
  light: FontItem;
55
+ italic?: FontItem;
56
+ boldItalic?: FontItem;
55
57
  code?: FontItem;
56
58
  };
59
+ heading?: {
60
+ /** Font size for h1-h6. Values are absolute (e.g. 22, 20, 18, 16, 14, 12). */h1?: number;
61
+ h2?: number;
62
+ h3?: number;
63
+ h4?: number;
64
+ h5?: number;
65
+ h6?: number; /** Space below heading before next element, in doc units. Default: 2 */
66
+ bottomSpacing?: number; /** Text color for all headings as hex. Default: '#000000' */
67
+ color?: string;
68
+ h1Color?: string;
69
+ h2Color?: string;
70
+ h3Color?: string;
71
+ h4Color?: string;
72
+ h5Color?: string;
73
+ h6Color?: string;
74
+ };
75
+ list?: {
76
+ /** Bullet character for unordered lists. Default: '\u2022 ' */bulletChar?: string; /** Extra indent per nesting level in doc units. Default: uses page.indent */
77
+ indentSize?: number; /** Vertical space between list items. Default: 0 */
78
+ itemSpacing?: number;
79
+ };
80
+ paragraph?: {
81
+ /** Space below each paragraph in doc units. Default: lineSpace */bottomSpacing?: number; /** Text color for paragraph text as hex. Default: '#000000' */
82
+ color?: string;
83
+ };
84
+ blockquote?: {
85
+ /** Left bar color as hex. Default: '#AAAAAA' */barColor?: string; /** Left bar width in doc units. Default: 1 */
86
+ barWidth?: number; /** Left padding from bar to text in doc units. Default: 4 */
87
+ paddingLeft?: number; /** Background color as hex. Default: undefined (transparent) */
88
+ backgroundColor?: string; /** Space below blockquote before next element, in doc units. Default: lineSpace */
89
+ bottomSpacing?: number;
90
+ };
57
91
  content?: {
58
92
  textAlignment: 'left' | 'right' | 'center' | 'justify';
59
93
  };
@@ -70,9 +104,49 @@ type RenderOption = {
70
104
  image?: {
71
105
  /** Default alignment for images: 'left' | 'center' | 'right'. Default: 'left' */defaultAlign?: 'left' | 'center' | 'right';
72
106
  };
107
+ codeBlock?: {
108
+ backgroundColor?: string;
109
+ borderColor?: string;
110
+ borderRadius?: number;
111
+ padding?: number;
112
+ fontSizeScale?: number; /** Whether to show language label. Default: true */
113
+ showLanguageLabel?: boolean; /** Text color for code content as hex. Default: '#000000' */
114
+ textColor?: string; /** Language label color as hex. Default: '#666666' */
115
+ labelColor?: string;
116
+ };
117
+ spacing?: {
118
+ /** Space below headings in doc units. Default: 2 */afterHeading?: number; /** Space below paragraphs in doc units. Default: 3 */
119
+ afterParagraph?: number; /** Space below code blocks in doc units. Default: 3 */
120
+ afterCodeBlock?: number; /** Space below blockquotes in doc units. Default: 3 */
121
+ afterBlockquote?: number; /** Space below images in doc units. Default: 2 */
122
+ afterImage?: number; /** Space below horizontal rules in doc units. Default: 2 */
123
+ afterHR?: number; /** Space between list items in doc units. Default: 0 */
124
+ betweenListItems?: number; /** Space below a complete list in doc units. Default: 3 */
125
+ afterList?: number; /** Space below tables in doc units. Default: 3 */
126
+ afterTable?: number;
127
+ };
128
+ header?: {
129
+ /** Text to render in header area of each page */text?: string | ((pageNumber: number, totalPages: number) => string); /** Y position of header text from top in doc units. Default: 5 */
130
+ y?: number; /** Font size for header text. Default: 9 */
131
+ fontSize?: number; /** Text color for header. Default: '#666666' */
132
+ color?: string; /** Alignment of header text. Default: 'center' */
133
+ align?: 'left' | 'center' | 'right';
134
+ };
135
+ footer?: {
136
+ /** Text to render in footer area of each page */text?: string | ((pageNumber: number, totalPages: number) => string); /** Y position from top of page in doc units. Default: pageHeight - 5 */
137
+ y?: number; /** Font size for footer text. Default: 9 */
138
+ fontSize?: number; /** Text color for footer. Default: '#666666' */
139
+ color?: string; /** Alignment of footer text. Default: 'right' */
140
+ align?: 'right' | 'left' | 'center'; /** Shortcut: render page numbers with format "Page X of Y" */
141
+ showPageNumbers?: boolean;
142
+ };
73
143
  pageBreakHandler?: (doc: jsPDF) => void;
74
144
  endCursorYHandler: (y: number) => void;
75
145
  };
146
+ type Cursor = {
147
+ x: number;
148
+ y: number;
149
+ };
76
150
  type FontItem = {
77
151
  name: string;
78
152
  style: string;
@@ -109,7 +183,9 @@ type ParsedElement = {
109
183
  height?: number;
110
184
  align?: 'left' | 'center' | 'right';
111
185
  naturalWidth?: number;
112
- naturalHeight?: number;
186
+ naturalHeight?: number; /** Whether this list item is a task (checkbox) item */
187
+ task?: boolean; /** Whether the task checkbox is checked */
188
+ checked?: boolean;
113
189
  };
114
190
  //#endregion
115
191
  //#region src/parser/MdTextParser.d.ts
@@ -121,4 +197,141 @@ type ParsedElement = {
121
197
  */
122
198
  declare const MdTextParser: (text: string) => Promise<ParsedElement[]>;
123
199
  //#endregion
124
- export { MdTextParser, MdTextRender, type RenderOption };
200
+ //#region src/types/styledWordInfo.d.ts
201
+ /**
202
+ * Enhanced word info types for styled text justification.
203
+ * These types allow tracking font styles per word for proper justified rendering.
204
+ */
205
+ type TextStyle = 'normal' | 'bold' | 'italic' | 'bolditalic' | 'codespan';
206
+ /**
207
+ * Information about a single styled word for justified text rendering.
208
+ */
209
+ interface StyledWordInfo {
210
+ /** The word text */
211
+ text: string;
212
+ /** Measured width in PDF points */
213
+ width: number;
214
+ /** Font style to apply when rendering */
215
+ style: TextStyle;
216
+ /** Whether this word is part of a link */
217
+ isLink?: boolean;
218
+ /** URL if this is a link */
219
+ href?: string;
220
+ /** Optional link color override */
221
+ linkColor?: number[];
222
+ /** Whether this is an inline image */
223
+ isImage?: boolean;
224
+ /** The image parsed element */
225
+ imageElement?: ParsedElement;
226
+ /** The height of the image to reserve */
227
+ imageHeight?: number;
228
+ /** Marks a hard line break */
229
+ isBr?: boolean;
230
+ /** Whether this word was followed by whitespace in the source Markdown */
231
+ hasTrailingSpace?: boolean;
232
+ }
233
+ /**
234
+ * Represents a line of styled words for justified rendering.
235
+ */
236
+ interface StyledLine {
237
+ /** Words in this line */
238
+ words: StyledWordInfo[];
239
+ /** Sum of word widths (without inter-word spacing) */
240
+ totalTextWidth: number;
241
+ /** Last line of paragraph shouldn't be fully justified */
242
+ isLastLine: boolean;
243
+ /** Line height (max of text height and inline image heights) */
244
+ lineHeight: number;
245
+ }
246
+ //#endregion
247
+ //#region src/store/renderStore.d.ts
248
+ declare class RenderStore {
249
+ private cursor;
250
+ private lastContentY_;
251
+ private options_;
252
+ private inlineLock;
253
+ constructor(options: RenderOption);
254
+ getCursor(): Cursor;
255
+ setCursor(newCursor: Cursor): void;
256
+ get options(): RenderOption;
257
+ get isInlineLockActive(): boolean;
258
+ activateInlineLock(): void;
259
+ deactivateInlineLock(): void;
260
+ /**
261
+ * Updates the x pointer of the cursor.
262
+ * @param value The value to set or add.
263
+ * @param operation 'set' to assign a new value, 'add' to increment the current value.
264
+ * @default operation = 'set'
265
+ */
266
+ updateX(value: number, operation?: 'set' | 'add'): void;
267
+ /**
268
+ * Updates the y pointer of the cursor.
269
+ * @param value The value to set or add.
270
+ * @param operation 'set' to assign a new value, 'add' to increment the current value.
271
+ * @default operation = 'set'
272
+ */
273
+ updateY(value: number, operation?: 'set' | 'add'): void;
274
+ /**
275
+ * Records a Y position as the bottom of rendered content.
276
+ * This is useful for container components (like blockquotes) to know
277
+ * where their actual text content ends, ignoring any trailing margins.
278
+ * @param specificY Optional Y value to record. Defaults to current cursor Y.
279
+ */
280
+ recordContentY(specificY?: number): void;
281
+ /**
282
+ * Gets the last Y position recorded as content bottom.
283
+ */
284
+ get lastContentY(): number;
285
+ get X(): number;
286
+ get Y(): number;
287
+ }
288
+ //#endregion
289
+ //#region src/layout/layoutEngine.d.ts
290
+ interface LayoutOptions {
291
+ alignment?: 'left' | 'right' | 'center' | 'justify';
292
+ /** When true, the last line advances Y by only the raw text height
293
+ * (no trailing inter-line spacing), so the caller's explicit
294
+ * bottomSpacing is the sole gap after the block. */
295
+ trimLastLine?: boolean;
296
+ }
297
+ /**
298
+ * THE single entry point for rendering any mixed inline content.
299
+ * All paragraph, heading, list item, and blockquote text must go through here.
300
+ *
301
+ * Handles: word splitting, line breaking, page breaks, styled rendering.
302
+ * Returns the final Y position after rendering.
303
+ */
304
+ declare const renderInlineContent: (doc: jsPDF, elements: ParsedElement[], x: number, y: number, maxWidth: number, store: RenderStore, opts?: LayoutOptions) => number;
305
+ /**
306
+ * Render a single string of plain (unstyled) text with wrapping and page breaks.
307
+ * Use this for simple text in list items and raw items where there are no inline styles.
308
+ */
309
+ declare const renderPlainText: (doc: jsPDF, text: string, x: number, y: number, maxWidth: number, store: RenderStore, opts?: LayoutOptions) => number;
310
+ //#endregion
311
+ //#region src/enums/mdTokenType.d.ts
312
+ declare enum MdTokenType {
313
+ Heading = "heading",
314
+ Paragraph = "paragraph",
315
+ List = "list",
316
+ ListItem = "list_item",
317
+ Blockquote = "blockquote",
318
+ Code = "code",
319
+ CodeSpan = "codespan",
320
+ Table = "table",
321
+ Html = "html",
322
+ Hr = "hr",
323
+ Image = "image",
324
+ Link = "link",
325
+ Strong = "strong",
326
+ Em = "em",
327
+ TableHeader = "table_header",
328
+ TableCell = "table_cell",
329
+ Raw = "raw",
330
+ Text = "text",
331
+ Br = "br"
332
+ }
333
+ //#endregion
334
+ //#region src/utils/options-validation.d.ts
335
+ declare const validateOptions: (options: RenderOption) => RenderOption;
336
+ //#endregion
337
+ export { MdTextParser, MdTextRender, MdTokenType, type ParsedElement, type RenderOption, type StyledLine, type StyledWordInfo, type TextStyle, renderInlineContent, renderPlainText, validateOptions };
package/dist/index.d.ts CHANGED
@@ -35,7 +35,7 @@ type RenderOption = {
35
35
  };
36
36
  page: {
37
37
  format?: string | number[];
38
- unit?: jsPDFOptions['unit'];
38
+ unit: jsPDFOptions['unit'];
39
39
  orientation?: jsPDFOptions['orientation'];
40
40
  maxContentWidth: number;
41
41
  maxContentHeight: number;
@@ -52,8 +52,42 @@ type RenderOption = {
52
52
  bold: FontItem;
53
53
  regular: FontItem;
54
54
  light: FontItem;
55
+ italic?: FontItem;
56
+ boldItalic?: FontItem;
55
57
  code?: FontItem;
56
58
  };
59
+ heading?: {
60
+ /** Font size for h1-h6. Values are absolute (e.g. 22, 20, 18, 16, 14, 12). */h1?: number;
61
+ h2?: number;
62
+ h3?: number;
63
+ h4?: number;
64
+ h5?: number;
65
+ h6?: number; /** Space below heading before next element, in doc units. Default: 2 */
66
+ bottomSpacing?: number; /** Text color for all headings as hex. Default: '#000000' */
67
+ color?: string;
68
+ h1Color?: string;
69
+ h2Color?: string;
70
+ h3Color?: string;
71
+ h4Color?: string;
72
+ h5Color?: string;
73
+ h6Color?: string;
74
+ };
75
+ list?: {
76
+ /** Bullet character for unordered lists. Default: '\u2022 ' */bulletChar?: string; /** Extra indent per nesting level in doc units. Default: uses page.indent */
77
+ indentSize?: number; /** Vertical space between list items. Default: 0 */
78
+ itemSpacing?: number;
79
+ };
80
+ paragraph?: {
81
+ /** Space below each paragraph in doc units. Default: lineSpace */bottomSpacing?: number; /** Text color for paragraph text as hex. Default: '#000000' */
82
+ color?: string;
83
+ };
84
+ blockquote?: {
85
+ /** Left bar color as hex. Default: '#AAAAAA' */barColor?: string; /** Left bar width in doc units. Default: 1 */
86
+ barWidth?: number; /** Left padding from bar to text in doc units. Default: 4 */
87
+ paddingLeft?: number; /** Background color as hex. Default: undefined (transparent) */
88
+ backgroundColor?: string; /** Space below blockquote before next element, in doc units. Default: lineSpace */
89
+ bottomSpacing?: number;
90
+ };
57
91
  content?: {
58
92
  textAlignment: 'left' | 'right' | 'center' | 'justify';
59
93
  };
@@ -70,9 +104,49 @@ type RenderOption = {
70
104
  image?: {
71
105
  /** Default alignment for images: 'left' | 'center' | 'right'. Default: 'left' */defaultAlign?: 'left' | 'center' | 'right';
72
106
  };
107
+ codeBlock?: {
108
+ backgroundColor?: string;
109
+ borderColor?: string;
110
+ borderRadius?: number;
111
+ padding?: number;
112
+ fontSizeScale?: number; /** Whether to show language label. Default: true */
113
+ showLanguageLabel?: boolean; /** Text color for code content as hex. Default: '#000000' */
114
+ textColor?: string; /** Language label color as hex. Default: '#666666' */
115
+ labelColor?: string;
116
+ };
117
+ spacing?: {
118
+ /** Space below headings in doc units. Default: 2 */afterHeading?: number; /** Space below paragraphs in doc units. Default: 3 */
119
+ afterParagraph?: number; /** Space below code blocks in doc units. Default: 3 */
120
+ afterCodeBlock?: number; /** Space below blockquotes in doc units. Default: 3 */
121
+ afterBlockquote?: number; /** Space below images in doc units. Default: 2 */
122
+ afterImage?: number; /** Space below horizontal rules in doc units. Default: 2 */
123
+ afterHR?: number; /** Space between list items in doc units. Default: 0 */
124
+ betweenListItems?: number; /** Space below a complete list in doc units. Default: 3 */
125
+ afterList?: number; /** Space below tables in doc units. Default: 3 */
126
+ afterTable?: number;
127
+ };
128
+ header?: {
129
+ /** Text to render in header area of each page */text?: string | ((pageNumber: number, totalPages: number) => string); /** Y position of header text from top in doc units. Default: 5 */
130
+ y?: number; /** Font size for header text. Default: 9 */
131
+ fontSize?: number; /** Text color for header. Default: '#666666' */
132
+ color?: string; /** Alignment of header text. Default: 'center' */
133
+ align?: 'left' | 'center' | 'right';
134
+ };
135
+ footer?: {
136
+ /** Text to render in footer area of each page */text?: string | ((pageNumber: number, totalPages: number) => string); /** Y position from top of page in doc units. Default: pageHeight - 5 */
137
+ y?: number; /** Font size for footer text. Default: 9 */
138
+ fontSize?: number; /** Text color for footer. Default: '#666666' */
139
+ color?: string; /** Alignment of footer text. Default: 'right' */
140
+ align?: 'right' | 'left' | 'center'; /** Shortcut: render page numbers with format "Page X of Y" */
141
+ showPageNumbers?: boolean;
142
+ };
73
143
  pageBreakHandler?: (doc: jsPDF) => void;
74
144
  endCursorYHandler: (y: number) => void;
75
145
  };
146
+ type Cursor = {
147
+ x: number;
148
+ y: number;
149
+ };
76
150
  type FontItem = {
77
151
  name: string;
78
152
  style: string;
@@ -109,7 +183,9 @@ type ParsedElement = {
109
183
  height?: number;
110
184
  align?: 'left' | 'center' | 'right';
111
185
  naturalWidth?: number;
112
- naturalHeight?: number;
186
+ naturalHeight?: number; /** Whether this list item is a task (checkbox) item */
187
+ task?: boolean; /** Whether the task checkbox is checked */
188
+ checked?: boolean;
113
189
  };
114
190
  //#endregion
115
191
  //#region src/parser/MdTextParser.d.ts
@@ -121,4 +197,141 @@ type ParsedElement = {
121
197
  */
122
198
  declare const MdTextParser: (text: string) => Promise<ParsedElement[]>;
123
199
  //#endregion
124
- export { MdTextParser, MdTextRender, type RenderOption };
200
+ //#region src/types/styledWordInfo.d.ts
201
+ /**
202
+ * Enhanced word info types for styled text justification.
203
+ * These types allow tracking font styles per word for proper justified rendering.
204
+ */
205
+ type TextStyle = 'normal' | 'bold' | 'italic' | 'bolditalic' | 'codespan';
206
+ /**
207
+ * Information about a single styled word for justified text rendering.
208
+ */
209
+ interface StyledWordInfo {
210
+ /** The word text */
211
+ text: string;
212
+ /** Measured width in PDF points */
213
+ width: number;
214
+ /** Font style to apply when rendering */
215
+ style: TextStyle;
216
+ /** Whether this word is part of a link */
217
+ isLink?: boolean;
218
+ /** URL if this is a link */
219
+ href?: string;
220
+ /** Optional link color override */
221
+ linkColor?: number[];
222
+ /** Whether this is an inline image */
223
+ isImage?: boolean;
224
+ /** The image parsed element */
225
+ imageElement?: ParsedElement;
226
+ /** The height of the image to reserve */
227
+ imageHeight?: number;
228
+ /** Marks a hard line break */
229
+ isBr?: boolean;
230
+ /** Whether this word was followed by whitespace in the source Markdown */
231
+ hasTrailingSpace?: boolean;
232
+ }
233
+ /**
234
+ * Represents a line of styled words for justified rendering.
235
+ */
236
+ interface StyledLine {
237
+ /** Words in this line */
238
+ words: StyledWordInfo[];
239
+ /** Sum of word widths (without inter-word spacing) */
240
+ totalTextWidth: number;
241
+ /** Last line of paragraph shouldn't be fully justified */
242
+ isLastLine: boolean;
243
+ /** Line height (max of text height and inline image heights) */
244
+ lineHeight: number;
245
+ }
246
+ //#endregion
247
+ //#region src/store/renderStore.d.ts
248
+ declare class RenderStore {
249
+ private cursor;
250
+ private lastContentY_;
251
+ private options_;
252
+ private inlineLock;
253
+ constructor(options: RenderOption);
254
+ getCursor(): Cursor;
255
+ setCursor(newCursor: Cursor): void;
256
+ get options(): RenderOption;
257
+ get isInlineLockActive(): boolean;
258
+ activateInlineLock(): void;
259
+ deactivateInlineLock(): void;
260
+ /**
261
+ * Updates the x pointer of the cursor.
262
+ * @param value The value to set or add.
263
+ * @param operation 'set' to assign a new value, 'add' to increment the current value.
264
+ * @default operation = 'set'
265
+ */
266
+ updateX(value: number, operation?: 'set' | 'add'): void;
267
+ /**
268
+ * Updates the y pointer of the cursor.
269
+ * @param value The value to set or add.
270
+ * @param operation 'set' to assign a new value, 'add' to increment the current value.
271
+ * @default operation = 'set'
272
+ */
273
+ updateY(value: number, operation?: 'set' | 'add'): void;
274
+ /**
275
+ * Records a Y position as the bottom of rendered content.
276
+ * This is useful for container components (like blockquotes) to know
277
+ * where their actual text content ends, ignoring any trailing margins.
278
+ * @param specificY Optional Y value to record. Defaults to current cursor Y.
279
+ */
280
+ recordContentY(specificY?: number): void;
281
+ /**
282
+ * Gets the last Y position recorded as content bottom.
283
+ */
284
+ get lastContentY(): number;
285
+ get X(): number;
286
+ get Y(): number;
287
+ }
288
+ //#endregion
289
+ //#region src/layout/layoutEngine.d.ts
290
+ interface LayoutOptions {
291
+ alignment?: 'left' | 'right' | 'center' | 'justify';
292
+ /** When true, the last line advances Y by only the raw text height
293
+ * (no trailing inter-line spacing), so the caller's explicit
294
+ * bottomSpacing is the sole gap after the block. */
295
+ trimLastLine?: boolean;
296
+ }
297
+ /**
298
+ * THE single entry point for rendering any mixed inline content.
299
+ * All paragraph, heading, list item, and blockquote text must go through here.
300
+ *
301
+ * Handles: word splitting, line breaking, page breaks, styled rendering.
302
+ * Returns the final Y position after rendering.
303
+ */
304
+ declare const renderInlineContent: (doc: jsPDF, elements: ParsedElement[], x: number, y: number, maxWidth: number, store: RenderStore, opts?: LayoutOptions) => number;
305
+ /**
306
+ * Render a single string of plain (unstyled) text with wrapping and page breaks.
307
+ * Use this for simple text in list items and raw items where there are no inline styles.
308
+ */
309
+ declare const renderPlainText: (doc: jsPDF, text: string, x: number, y: number, maxWidth: number, store: RenderStore, opts?: LayoutOptions) => number;
310
+ //#endregion
311
+ //#region src/enums/mdTokenType.d.ts
312
+ declare enum MdTokenType {
313
+ Heading = "heading",
314
+ Paragraph = "paragraph",
315
+ List = "list",
316
+ ListItem = "list_item",
317
+ Blockquote = "blockquote",
318
+ Code = "code",
319
+ CodeSpan = "codespan",
320
+ Table = "table",
321
+ Html = "html",
322
+ Hr = "hr",
323
+ Image = "image",
324
+ Link = "link",
325
+ Strong = "strong",
326
+ Em = "em",
327
+ TableHeader = "table_header",
328
+ TableCell = "table_cell",
329
+ Raw = "raw",
330
+ Text = "text",
331
+ Br = "br"
332
+ }
333
+ //#endregion
334
+ //#region src/utils/options-validation.d.ts
335
+ declare const validateOptions: (options: RenderOption) => RenderOption;
336
+ //#endregion
337
+ export { MdTextParser, MdTextRender, MdTokenType, type ParsedElement, type RenderOption, type StyledLine, type StyledWordInfo, type TextStyle, renderInlineContent, renderPlainText, validateOptions };