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