jspdf-md-renderer 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,173 +1,83 @@
1
1
  # jsPDF Markdown Renderer
2
2
 
3
- A jsPDF utility to render Markdown directly into formatted PDFs with custom designs.
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`).
3
+ A utility to render Markdown directly into formatted PDFs using `jsPDF`.
13
4
 
14
5
  [![npm version](https://img.shields.io/npm/v/jspdf-md-renderer.svg)](https://www.npmjs.com/package/jspdf-md-renderer)
15
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
16
7
  [![Downloads](https://img.shields.io/npm/dm/jspdf-md-renderer.svg)](https://www.npmjs.com/package/jspdf-md-renderer)
17
8
 
18
- ## Table of Contents
9
+ ## Highlights
19
10
 
20
- - [Installation](#installation)
21
- - [Usage](#usage)
22
- - [Browser Runtime Usage](#browser-runtime-usage)
23
- - [API](#api)
24
- - [Examples](#examples)
25
- - [Contributing](#contributing)
26
- - [License](#license)
11
+ - Rich markdown support (headings, lists, tables, images, code, blockquotes, links)
12
+ - Configurable typography, spacing, and block styling
13
+ - Header/footer and page-number support
14
+ - Safe inline layout and long-token wrapping
15
+ - Optional security enforcement for untrusted markdown
27
16
 
28
17
  ## Installation
29
18
 
30
- To install the library, you can use npm:
31
-
32
19
  ```sh
33
20
  npm install jspdf-md-renderer
34
21
  ```
35
22
 
36
- ## Usage
37
-
38
- ### Basic Example
39
-
40
- Here is a basic example of how to use the library to generate a PDF from Markdown content:
23
+ ## Quick Start
41
24
 
42
25
  ```ts
43
- import { jsPDF } from 'jspdf';
44
- import { MdTextRender } from 'jspdf-md-renderer';
45
-
46
- const mdString = `
47
- # Main Title
48
-
49
- This is a brief introduction paragraph. It sets the tone for the document and introduces the main topic in a concise manner.
50
-
51
- ## Section 1: Overview
52
-
53
- Here is a medium-length paragraph that goes into more detail about the first section. It explains the context, provides background information, and sets up the discussion for the subsections.
54
-
55
- ## Section 2: Lists and Examples
26
+ import { jsPDF } from 'jspdf'
27
+ import { MdTextRender } from 'jspdf-md-renderer'
56
28
 
57
- This section showcases how to create simple and nested lists.
29
+ const markdown = `
30
+ # Project Report
58
31
 
59
- ### Simple List
32
+ This report includes **formatted markdown** content.
60
33
 
61
34
  - Item 1
62
35
  - Item 2
63
- - Item 3
64
-
65
- ### Nested List
66
-
67
- 1. First Level 1
68
- - First Level 2
69
- - First Level 3
70
- 2. Second Level 1
71
- - Second Level 2
72
- - Another Second Level 2
73
- - Nested deeper
74
-
75
- ### Mixed List Example
76
-
77
- - Topic 1
78
- 1. Subtopic 1.1
79
- 2. Subtopic 1.2
80
- - Topic 2
81
- - Subtopic 2.1
82
- - Subtopic 2.2
83
- 1. Nested Subtopic 2.2.1
84
- 2. Nested Subtopic 2.2.2
85
-
86
- ### Emphasis and Strong Emphasis
87
- - *Italic* text using asterisks.
88
- - _Italic_ text using underscores.
89
- - **Bold** text using double asterisks.
90
- - __Bold__ text using double underscores.
91
- - ***Bold and Italic*** text using triple asterisks.
92
- - ___Bold and Italic___ text using triple underscores.
93
-
94
- `;
95
-
96
- const generatePDF = async () => {
97
- const doc = new jsPDF({
98
- unit: 'mm',
99
- format: 'a4',
100
- orientation: 'portrait',
101
- });
102
-
103
- const options = {
104
- cursor: { x: 10, y: 10 },
105
- page: {
106
- format: 'a4',
107
- unit: 'mm',
108
- orientation: 'portrait',
109
- maxContentWidth: 190,
110
- maxContentHeight: 277,
111
- lineSpace: 1.5,
112
- defaultLineHeightFactor: 1.2,
113
- defaultFontSize: 12,
114
- defaultTitleFontSize: 14,
115
- topmargin: 10,
116
- xpading: 10,
117
- xmargin: 10,
118
- indent: 10,
119
- },
120
- font: {
121
- bold: { name: 'helvetica', style: 'bold' },
122
- regular: { name: 'helvetica', style: 'normal' },
123
- light: { name: 'helvetica', style: 'light' },
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
- },
144
- endCursorYHandler: (y) => {
145
- console.log('End cursor Y position:', y);
146
- },
147
- };
148
-
149
- await MdTextRender(doc, mdString, options);
150
- doc.save('example.pdf');
151
- };
152
-
153
- generatePDF();
154
- ```
36
+ `
37
+
38
+ const doc = new jsPDF({ unit: 'mm', format: 'a4', orientation: 'portrait' })
39
+
40
+ await MdTextRender(doc, markdown, {
41
+ cursor: { x: 10, y: 10 },
42
+ page: {
43
+ format: 'a4',
44
+ unit: 'mm',
45
+ orientation: 'portrait',
46
+ maxContentWidth: 190,
47
+ maxContentHeight: 277,
48
+ lineSpace: 1.5,
49
+ defaultLineHeightFactor: 1.2,
50
+ defaultFontSize: 12,
51
+ defaultTitleFontSize: 14,
52
+ topmargin: 10,
53
+ xpading: 10,
54
+ xmargin: 10,
55
+ indent: 10,
56
+ },
57
+ font: {
58
+ bold: { name: 'helvetica', style: 'bold' },
59
+ regular: { name: 'helvetica', style: 'normal' },
60
+ light: { name: 'helvetica', style: 'light' },
61
+ },
62
+ endCursorYHandler: (y) => {
63
+ console.log('Final Y:', y)
64
+ },
65
+ })
155
66
 
156
- ## Browser Runtime Usage
67
+ doc.save('report.pdf')
68
+ ```
157
69
 
158
- ### Option 1: Use with your app bundler (Vite/Webpack/Rollup)
70
+ ## Browser Usage
159
71
 
160
- Install dependencies and import from modules as usual:
72
+ ### Bundler (Vite/Webpack/Rollup)
161
73
 
162
74
  ```ts
163
- import { jsPDF } from 'jspdf';
164
- import autoTable from 'jspdf-autotable';
165
- import { MdTextRender } from 'jspdf-md-renderer';
75
+ import { jsPDF } from 'jspdf'
76
+ import 'jspdf-autotable'
77
+ import { MdTextRender } from 'jspdf-md-renderer'
166
78
  ```
167
79
 
168
- ### Option 2: Use directly via script tags (UMD)
169
-
170
- Load dependencies first, then load `jspdf-md-renderer` UMD bundle.
80
+ ### Script Tag (UMD)
171
81
 
172
82
  ```html
173
83
  <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
@@ -177,127 +87,48 @@ Load dependencies first, then load `jspdf-md-renderer` UMD bundle.
177
87
  <script>
178
88
  const { jsPDF } = window.jspdf;
179
89
  const { MdTextRender } = window.JspdfMdRenderer;
180
-
181
- (async () => {
182
- const doc = new jsPDF();
183
- await MdTextRender(doc, '# Hello from browser runtime');
184
- doc.save('browser-runtime.pdf');
185
- })();
186
90
  </script>
187
91
  ```
188
92
 
189
- > Note: For script-tag usage you must include `marked`, `jspdf`, and `jspdf-autotable` before the renderer bundle.
190
-
191
- ## API
192
-
193
- ### `MdTextRender`
194
-
195
- Renders parsed markdown text into a jsPDF document.
196
-
197
- #### Parameters
198
-
199
- - `doc`: The jsPDF document instance.
200
- - `text`: The markdown content to render.
201
- - `options`: The render options (fonts, page margins, etc.).
202
-
203
- ### `MdTextParser`
204
-
205
- Parses markdown into tokens and converts to a custom parsed structure.
206
-
207
- #### Parameters
208
-
209
- - `text`: The markdown content to parse.
210
-
211
- #### Returns
212
-
213
- - `Promise<ParsedElement[]>`: Parsed markdown elements.
214
-
215
- ## Supported Markdown Elements
216
-
217
- The following Markdown elements are currently supported by `jspdf-md-renderer`:
218
-
219
- - **Headings**: `#`, `##`, `###`, etc.
220
- - **Paragraphs**
221
- - **Lists**:
222
- - Unordered lists: `-`, `*`, `+`
223
- - Ordered lists: `1.`, `2.`, `3.`, etc.
224
- - **Horizontal Rules**: `---`, `***`, `___`
225
- - **Text Styles**:
226
- - Bold: `**bold**` or `__bold__`
227
- - Italic: `*italic*` or `_italic_`
228
- - Bold Italic: `***bold italic***` or `___bold italic___`
229
- - **Code Blocks** (fenced and indented):
230
- ````markdown
231
- ```js
232
- console.log('Hello, world!');
233
- ```
234
- ````
235
- - **Links**:
236
- ```markdown
237
- [GitHub](https://github.com)
238
- ```
239
- - **Blockquotes**:
240
- ```markdown
241
- > This is a blockquote.
242
- ```
243
- - **Images**:
244
- ```markdown
245
- ![Alt text](https://example.com/image.png)
246
- ```
247
- Images render at their **intrinsic (original) size** by default and scale down automatically if they exceed the available page width. You can control image dimensions and alignment using an optional attribute block `{...}` after the image syntax:
248
-
249
- **Custom Attributes:**
250
- | Attribute | Description | Example |
251
- |-----------|-------------|---------|
252
- | `width` or `w` | Image width in px | `{width=200}` or `{w=200}` |
253
- | `height` or `h` | Image height in px | `{height=150}` or `{h=150}` |
254
- | `align` | Alignment: `left`, `center`, `right` | `{align=center}` |
255
-
256
- **Sizing Rules:**
257
- - If only `width` is given, height is auto-calculated from aspect ratio
258
- - If only `height` is given, width is auto-calculated from aspect ratio
259
- - If both are given, the image uses exact dimensions (may distort if ratio differs)
260
- - Images that exceed page bounds are always scaled down proportionally
261
-
262
- **Examples:**
263
- ```markdown
264
- ![photo](https://example.com/photo.png)
265
- ![photo](https://example.com/photo.png){width=200}
266
- ![photo](https://example.com/photo.png){h=150 align=center}
267
- ![photo](https://example.com/photo.png){width=200 height=150 align=right}
268
- ```
269
-
270
- **Global Default Alignment:**
271
- You can set a default alignment for all images via the `image` option:
272
- ```ts
273
- const options = {
274
- // ...other options
275
- image: {
276
- defaultAlign: 'center', // 'left' (default) | 'center' | 'right'
277
- },
278
- };
279
- ```
280
-
281
- - **Inline Code**:
282
- ```markdown
283
- This is an `inline code` example.
284
- ```
285
- - **Tables**:
286
- ```markdown
287
- | Header 1 | Header 2 | Header 3 |
288
- | -------- | -------- | -------- |
289
- | Row 1 | Data | Value |
290
- | Row 2 | Data | Value |
291
- ```
292
-
293
- ## New Options (v4 quick reference)
93
+ ## Supported Markdown
94
+
95
+ - Headings (`#` to `######`)
96
+ - Paragraphs
97
+ - Ordered/unordered/task lists
98
+ - Links
99
+ - Images (with optional `{width,height,align}` attributes)
100
+ - Tables
101
+ - Code blocks and inline code
102
+ - Blockquotes
103
+ - Horizontal rules
104
+ - Inline styles (bold/italic)
105
+
106
+ ## Key Render Options
294
107
 
295
108
  ```ts
296
109
  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 },
110
+ heading: {
111
+ bold: true,
112
+ h1: 26,
113
+ h2: 22,
114
+ h3: 18,
115
+ bottomSpacing: 3,
116
+ },
117
+ list: {
118
+ bulletChar: '\u2022 ',
119
+ indentSize: 8,
120
+ itemSpacing: 0,
121
+ },
122
+ paragraph: {
123
+ bottomSpacing: 3,
124
+ color: '#111827',
125
+ },
126
+ blockquote: {
127
+ barColor: '#4A90D9',
128
+ barWidth: 2,
129
+ paddingLeft: 6,
130
+ backgroundColor: '#F8FAFC',
131
+ },
301
132
  codeBlock: {
302
133
  backgroundColor: '#F6F8FA',
303
134
  borderColor: '#E1E4E8',
@@ -317,27 +148,104 @@ const options = {
317
148
  afterList: 3,
318
149
  afterTable: 3,
319
150
  },
320
- header: { text: 'My Report', align: 'center', color: '#6b7280', fontSize: 9 },
321
- footer: { showPageNumbers: true, align: 'right' },
151
+ header: {
152
+ text: 'My Report',
153
+ align: 'center',
154
+ color: '#6b7280',
155
+ fontSize: 9,
156
+ },
157
+ footer: {
158
+ showPageNumbers: true,
159
+ align: 'right',
160
+ },
322
161
  }
323
162
  ```
324
163
 
325
- ## Examples
164
+ Behavior notes:
165
+ - Heading size fallback: `heading.hN` -> `page.defaultTitleFontSize`
166
+ - `heading.bold` defaults to `true`
167
+ - List spacing precedence: `spacing.betweenListItems` > `list.itemSpacing`
168
+ - Table width follows `page.maxContentWidth` for consistent block layout
326
169
 
327
- You can explore complete rendered examples in the documentation site:
328
- - [Resume example](https://jeelgajera.github.io/jspdf-md-renderer/examples/resume)
329
- - [Invoice example](https://jeelgajera.github.io/jspdf-md-renderer/examples/invoice)
330
- - [Technical report example](https://jeelgajera.github.io/jspdf-md-renderer/examples/report)
331
- - [Custom fonts guide](https://jeelgajera.github.io/jspdf-md-renderer/examples/custom-fonts)
170
+ ## Security Controls (opt-in)
332
171
 
333
- ## Contributing
172
+ Security is disabled by default for backward compatibility.
334
173
 
335
- Contributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) first.
174
+ ```ts
175
+ const options = {
176
+ // ...other options
177
+ security: {
178
+ enabled: true,
179
+ violationMode: 'skip', // 'skip' | 'throw' | 'placeholder'
180
+ placeholderText: '[blocked]',
181
+ placeholderImageText: '[blocked image]',
182
+
183
+ // Link controls
184
+ allowedLinkProtocols: ['https:', 'http:', 'mailto:', 'tel:'],
185
+ disablePdfLinks: false,
186
+
187
+ // Image controls
188
+ allowRemoteImages: true,
189
+ allowedImageProtocols: ['https:', 'http:'],
190
+ allowedImageDomains: ['cdn.example.com'],
191
+ allowDataUrls: true,
192
+ allowSvgImages: true,
193
+
194
+ // SSRF controls
195
+ blockLocalhost: true,
196
+ blockPrivateIPs: true,
197
+ blockLinkLocalIPs: true,
198
+ blockMetadataIPs: true,
199
+
200
+ // Limits
201
+ maxMarkdownLength: 500000,
202
+ maxImageCount: 200,
203
+ maxImageSizeBytes: 10 * 1024 * 1024,
204
+ maxNestedDepth: 20,
205
+ renderTimeoutMs: 30000,
206
+
207
+ // Hooks
208
+ validateUrl: async (url, type) => true,
209
+ onSecurityViolation: (violation) => console.warn(violation),
210
+ },
211
+ }
212
+ ```
213
+
214
+ ### Security Details
215
+
216
+ - URL classes:
217
+ - explicit scheme (`https://...`) -> full protocol/domain/IP checks
218
+ - protocol-relative (`//host/path`) -> treated as external absolute URL
219
+ - relative path (`/a`, `./a`, `?q=1`, `#id`) -> allowed by default unless custom validator rejects
220
+ - `allowedImageDomains` semantics:
221
+ - `undefined` -> allow all domains
222
+ - `[]` -> deny all domains
223
+ - `maxImageSizeBytes` uses decoded bytes for data URLs
224
+ - `SecurityViolationError` is exported for throw-mode handling
225
+
226
+ Browser caveat:
227
+ - IP-level SSRF checks are best-effort in browser runtime due to DNS API limitations.
228
+ - For strict SSRF policy, fetch remote images through a trusted server-side proxy.
229
+
230
+ ## API Exports
336
231
 
337
- ## Support
232
+ - `MdTextRender`
233
+ - `MdTextParser`
234
+ - `SecurityViolationError`
235
+ - `validateOptions`
236
+ - Types: `RenderOption`, `RenderSecurityOptions`, `SecurityViolation`, `ViolationMode`, and others
237
+
238
+ ## Examples and Docs
239
+
240
+ - Docs site: [https://jeelgajera.github.io/jspdf-md-renderer/](https://jeelgajera.github.io/jspdf-md-renderer/)
241
+ - Resume example: [https://jeelgajera.github.io/jspdf-md-renderer/examples/resume](https://jeelgajera.github.io/jspdf-md-renderer/examples/resume)
242
+ - Invoice example: [https://jeelgajera.github.io/jspdf-md-renderer/examples/invoice](https://jeelgajera.github.io/jspdf-md-renderer/examples/invoice)
243
+ - Technical report example: [https://jeelgajera.github.io/jspdf-md-renderer/examples/report](https://jeelgajera.github.io/jspdf-md-renderer/examples/report)
244
+
245
+ ## Contributing
338
246
 
339
- If you find this library useful, please consider giving it a ⭐ on GitHub! It helps others find the project and motivates continued development.
247
+ Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md).
340
248
 
341
249
  ## License
342
250
 
343
- This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
251
+ MIT. See [LICENSE](LICENSE).
package/dist/index.d.mts CHANGED
@@ -27,6 +27,94 @@
27
27
  import { UserOptions } from "jspdf-autotable";
28
28
  import jsPDF, { jsPDFOptions } from "jspdf";
29
29
 
30
+ //#region src/types/security.d.ts
31
+ type ViolationMode = 'skip' | 'throw' | 'placeholder';
32
+ type ViolationAction = 'skip' | 'placeholder';
33
+ type SecurityViolationType = 'link' | 'image' | 'markdown' | 'render';
34
+ type SecurityViolationCode = 'MARKDOWN_TOO_LARGE' | 'MAX_NESTED_DEPTH_EXCEEDED' | 'MAX_IMAGE_COUNT_EXCEEDED' | 'RENDER_TIMEOUT_EXCEEDED' | 'INVALID_URL' | 'LINK_PROTOCOL_BLOCKED' | 'IMAGE_PROTOCOL_BLOCKED' | 'IMAGE_DOMAIN_BLOCKED' | 'DATA_URL_BLOCKED' | 'SVG_BLOCKED' | 'LOCALHOST_BLOCKED' | 'PRIVATE_IP_BLOCKED' | 'LINK_LOCAL_IP_BLOCKED' | 'METADATA_IP_BLOCKED' | 'IMAGE_SIZE_EXCEEDED' | 'CUSTOM_VALIDATOR_BLOCKED';
35
+ interface SecurityViolation {
36
+ /** Machine-readable violation code. */
37
+ code: SecurityViolationCode;
38
+ /** High-level category of the violating input. */
39
+ type: SecurityViolationType;
40
+ /** Human-readable explanation of the violation. */
41
+ message: string;
42
+ /** Raw value that triggered the violation (URL, length, etc.). */
43
+ value?: string;
44
+ /** Optional execution context to help debugging (e.g. 'markdown-link'). */
45
+ context?: string;
46
+ /** ISO timestamp when the violation was recorded. */
47
+ timestamp: string;
48
+ }
49
+ declare class SecurityViolationError extends Error {
50
+ /** Structured violation payload used to construct this error. */
51
+ readonly violation: SecurityViolation;
52
+ constructor(violation: SecurityViolation);
53
+ }
54
+ interface RenderSecurityOptions {
55
+ /** Enables all built-in security checks. Default: false (opt-in). */
56
+ enabled?: boolean;
57
+ /** Allowed URI protocols for markdown links. Example: ['https:', 'mailto:']. */
58
+ allowedLinkProtocols?: string[];
59
+ /** If true, link text is rendered but PDF link actions are disabled. */
60
+ disablePdfLinks?: boolean;
61
+ /** Whether remote image fetching is allowed (http/https). */
62
+ allowRemoteImages?: boolean;
63
+ /** Allowed protocols for image URLs. Example: ['https:', 'http:']. */
64
+ allowedImageProtocols?: string[];
65
+ /**
66
+ * Optional domain allowlist for remote image hosts.
67
+ * - `undefined` (default): all domains are allowed.
68
+ * - `[]` (empty array): no domains are allowed.
69
+ * - `['example.com']`: only `example.com` and its subdomains are allowed.
70
+ */
71
+ allowedImageDomains?: string[];
72
+ /** Whether inline data: image URLs are allowed. */
73
+ allowDataUrls?: boolean;
74
+ /** Whether SVG images are allowed. */
75
+ allowSvgImages?: boolean;
76
+ /** Blocks localhost image/link destinations when true. */
77
+ blockLocalhost?: boolean;
78
+ /**
79
+ * Blocks private IPv4 ranges (10/8, 172.16/12, 192.168/16) when true.
80
+ * NOTE: In browser environments, IP-based checks cannot be enforced due to
81
+ * lack of DNS resolution APIs. Use a trusted server-side proxy for strict enforcement.
82
+ */
83
+ blockPrivateIPs?: boolean;
84
+ /**
85
+ * Blocks link-local IPv4 ranges (169.254/16) when true.
86
+ * NOTE: In browser environments, IP-based checks cannot be enforced due to
87
+ * lack of DNS resolution APIs. Use a trusted server-side proxy for strict enforcement.
88
+ */
89
+ blockLinkLocalIPs?: boolean;
90
+ /**
91
+ * Blocks known cloud metadata endpoints when true.
92
+ * NOTE: In browser environments, IP-based checks cannot be enforced due to
93
+ * lack of DNS resolution APIs. Use a trusted server-side proxy for strict enforcement.
94
+ */
95
+ blockMetadataIPs?: boolean;
96
+ /** Maximum markdown input length in characters. */
97
+ maxMarkdownLength?: number;
98
+ /** Maximum number of markdown images allowed per render. */
99
+ maxImageCount?: number;
100
+ /** Maximum image payload size in bytes (fetched blob size or decoded data URL bytes). */
101
+ maxImageSizeBytes?: number;
102
+ /** Maximum supported markdown nesting depth. */
103
+ maxNestedDepth?: number;
104
+ /** Maximum total render time in milliseconds. */
105
+ renderTimeoutMs?: number;
106
+ /** Action taken when a violation occurs. */
107
+ violationMode?: ViolationMode;
108
+ /** Placeholder text used for blocked text-like content in placeholder mode. */
109
+ placeholderText?: string;
110
+ /** Placeholder text used for blocked images in placeholder mode. */
111
+ placeholderImageText?: string;
112
+ /** Optional custom URL validator. Return false to reject the URL. */
113
+ validateUrl?: (url: URL, type: 'link' | 'image') => boolean | Promise<boolean>;
114
+ /** Callback fired for every security violation, regardless of mode. */
115
+ onSecurityViolation?: (violation: SecurityViolation) => void;
116
+ }
117
+ //#endregion
30
118
  //#region src/types/renderOption.d.ts
31
119
  type RenderOption = {
32
120
  cursor: {
@@ -52,10 +140,13 @@ type RenderOption = {
52
140
  bold: FontItem;
53
141
  regular: FontItem;
54
142
  light: FontItem;
143
+ italic?: FontItem;
144
+ boldItalic?: FontItem;
55
145
  code?: FontItem;
56
146
  };
57
147
  heading?: {
58
- /** Font size for h1-h6. Values are absolute (e.g. 22, 20, 18, 16, 14, 12). */h1?: number;
148
+ /** Whether headings should use bold font. Default: true */bold?: boolean; /** Font size for h1-h6. Values are absolute (e.g. 22, 20, 18, 16, 14, 12). */
149
+ h1?: number;
59
150
  h2?: number;
60
151
  h3?: number;
61
152
  h4?: number;
@@ -72,7 +163,7 @@ type RenderOption = {
72
163
  };
73
164
  list?: {
74
165
  /** 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 */
166
+ indentSize?: number; /** Vertical space between list items. Used when spacing.betweenListItems is not provided. */
76
167
  itemSpacing?: number;
77
168
  };
78
169
  paragraph?: {
@@ -140,6 +231,7 @@ type RenderOption = {
140
231
  };
141
232
  pageBreakHandler?: (doc: jsPDF) => void;
142
233
  endCursorYHandler: (y: number) => void;
234
+ security?: RenderSecurityOptions;
143
235
  };
144
236
  type Cursor = {
145
237
  x: number;
@@ -332,4 +424,4 @@ declare enum MdTokenType {
332
424
  //#region src/utils/options-validation.d.ts
333
425
  declare const validateOptions: (options: RenderOption) => RenderOption;
334
426
  //#endregion
335
- export { MdTextParser, MdTextRender, MdTokenType, type ParsedElement, type RenderOption, type StyledLine, type StyledWordInfo, type TextStyle, renderInlineContent, renderPlainText, validateOptions };
427
+ export { MdTextParser, MdTextRender, MdTokenType, type ParsedElement, type RenderOption, type RenderSecurityOptions, type SecurityViolation, type SecurityViolationCode, SecurityViolationError, type StyledLine, type StyledWordInfo, type TextStyle, type ViolationAction, type ViolationMode, renderInlineContent, renderPlainText, validateOptions };