pagyra-js 0.0.21 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +283 -264
  2. package/dist/browser/pagyra.min.js +18 -18
  3. package/dist/browser/pagyra.min.js.map +3 -3
  4. package/dist/src/layout/inline/run-placer.js +1 -1
  5. package/dist/src/layout/strategies/grid.js +0 -3
  6. package/dist/src/pdf/font/embedder.js +3 -3
  7. package/dist/src/pdf/font/font-subset.js +1 -3
  8. package/dist/src/pdf/font/to-unicode.js +16 -16
  9. package/dist/src/pdf/utils/node-text-run-factory.js +1 -27
  10. package/dist/tests/environment/path-resolution.spec.js +2 -1
  11. package/dist/tests/helpers/ai-layout-diagnostics.js +6 -6
  12. package/dist/tests/layout/container-query-units.spec.js +0 -7
  13. package/dist/tests/layout/inline-background-alignment.spec.js +6 -6
  14. package/dist/tests/pdf/alignments.spec.js +12 -12
  15. package/dist/tests/pdf/svg-stroke-dash.spec.js +8 -8
  16. package/dist/tests/pdf/text-transform-matrix.spec.js +1 -1
  17. package/dist/tests/pdf/xref-integrity.spec.js +1 -1
  18. package/dist/tests/verify-subset-multi.spec.js +14 -14
  19. package/dist/tests/verify-subset.spec.js +12 -12
  20. package/package.json +89 -71
  21. package/dist/src/image/js-png-backend.d.ts +0 -7
  22. package/dist/src/image/js-png-backend.js +0 -9
  23. package/dist/src/image/png-backend.d.ts +0 -5
  24. package/dist/src/image/png-backend.js +0 -1
  25. package/dist/src/image/png-wasm-loader.d.ts +0 -5
  26. package/dist/src/image/png-wasm-loader.js +0 -59
  27. package/dist/src/image/wasm/png_decoder_wasm.d.ts +0 -8
  28. package/dist/src/image/wasm/png_decoder_wasm.js +0 -24
  29. package/dist/src/image/wasm/png_decoder_wasm_bg.js +0 -16
  30. package/dist/src/image/wasm-png-backend.d.ts +0 -6
  31. package/dist/src/image/wasm-png-backend.js +0 -17
  32. package/dist/tests/image/png-backend.spec.d.ts +0 -1
  33. package/dist/tests/image/png-backend.spec.js +0 -34
  34. package/dist/tests/pdf/font-subset-registry-key.spec.d.ts +0 -1
  35. package/dist/tests/pdf/font-subset-registry-key.spec.js +0 -66
  36. package/dist/tests/pdf/header-footer.spec.d.ts +0 -1
  37. package/dist/tests/pdf/header-footer.spec.js +0 -46
package/README.md CHANGED
@@ -1,114 +1,116 @@
1
- # Pagyra-js
2
-
3
- A TypeScript-based HTML to PDF converter library with comprehensive CSS 3 support and advanced layout capabilities.
4
-
5
- ## Features
6
-
7
- ### Core Capabilities
8
- - **HTML to PDF Conversion**: Convert HTML content to PDF with precise layout control
9
- - **Comprehensive CSS Support**: Full CSS parsing, inheritance, and layout support
10
- - **Advanced Text Handling**: Complete text layout with overflow wrapping, justification, and text transformation
11
- - **Font Management**: Built-in font support with custom font embedding via `@font-face`
12
- - **Cross-Platform**: Works in both Node.js and browser environments
13
-
14
- ### Recent Additions (from CHANGELOG)
15
- - **Overflow Wrapping**: Full `overflow-wrap` / `word-wrap` parsing and layout support
16
- - **Relative Units**: Support for `em`/`rem` units using inherited/root font sizes
17
- - **Text Transformation**: `text-transform` parsing and rendering (uppercase/lowercase/capitalize)
18
- - **SVG Stroke Support**: `stroke-dasharray` and `stroke-dashoffset` for dashed line rendering
19
- - **CSS Variables**: Custom properties with inheritance and `var()` function resolution
20
- - **Justified Text**: Consistent justified spacing across all inline fragments
21
-
22
- ## Installation
23
-
24
- ```bash
25
- npm install pagyra-js
26
- ```
27
-
28
- ## Usage
29
-
30
- ### Minimal Example (HTML only)
31
-
32
- ```typescript
33
- import { renderHtmlToPdf } from 'pagyra-js';
34
-
35
- // Minimal usage - only HTML is required
36
- // Other parameters will use sensible defaults (A4 size, standard margins)
37
- const pdfBytes = await renderHtmlToPdf({
38
- html: '<h1>Hello World</h1><p>This is a PDF generated from HTML!</p>'
39
- });
40
- ```
41
-
42
- ### Basic Example with Full Control
43
-
44
- ```typescript
45
- import { renderHtmlToPdf } from 'pagyra-js';
46
-
47
- const pdfBytes = await renderHtmlToPdf({
48
- html: '<h1>Hello World</h1><p>This is a PDF generated from HTML!</p>',
49
- css: 'body { font-family: Arial; } h1 { color: blue; }',
50
- viewportWidth: 800,
51
- viewportHeight: 600,
52
- pageWidth: 800,
53
- pageHeight: 1100,
54
- margins: { top: 20, right: 20, bottom: 20, left: 20 }
55
- });
56
-
57
- // Save or use the PDF bytes
58
- fs.writeFileSync('output.pdf', Buffer.from(pdfBytes));
59
- ```
60
-
1
+ # Pagyra-js
2
+
3
+ A TypeScript-based HTML to PDF converter library with comprehensive CSS 3 support and advanced layout capabilities.
4
+
5
+ > [▶ Test here using our playground](https://celsowm.github.io/pagyra-js/)
6
+
7
+ ## Features
8
+
9
+ ### Core Capabilities
10
+ - **HTML to PDF Conversion**: Convert HTML content to PDF with precise layout control
11
+ - **Comprehensive CSS Support**: Full CSS parsing, inheritance, and layout support
12
+ - **Advanced Text Handling**: Complete text layout with overflow wrapping, justification, and text transformation
13
+ - **Font Management**: Built-in font support with custom font embedding via `@font-face`
14
+ - **Cross-Platform**: Works in both Node.js and browser environments
15
+
16
+ ### Recent Additions (from CHANGELOG)
17
+ - **Overflow Wrapping**: Full `overflow-wrap` / `word-wrap` parsing and layout support
18
+ - **Relative Units**: Support for `em`/`rem` units using inherited/root font sizes
19
+ - **Text Transformation**: `text-transform` parsing and rendering (uppercase/lowercase/capitalize)
20
+ - **SVG Stroke Support**: `stroke-dasharray` and `stroke-dashoffset` for dashed line rendering
21
+ - **CSS Variables**: Custom properties with inheritance and `var()` function resolution
22
+ - **Justified Text**: Consistent justified spacing across all inline fragments
23
+
24
+ ## 📦 Installation
25
+
26
+ ```bash
27
+ npm install pagyra-js
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Minimal Example (HTML only)
33
+
34
+ ```typescript
35
+ import { renderHtmlToPdf } from 'pagyra-js';
36
+
37
+ // Minimal usage - only HTML is required
38
+ // Other parameters will use sensible defaults (A4 size, standard margins)
39
+ const pdfBytes = await renderHtmlToPdf({
40
+ html: '<h1>Hello World</h1><p>This is a PDF generated from HTML!</p>'
41
+ });
42
+ ```
43
+
44
+ ### Basic Example with Full Control
45
+
46
+ ```typescript
47
+ import { renderHtmlToPdf } from 'pagyra-js';
48
+
49
+ const pdfBytes = await renderHtmlToPdf({
50
+ html: '<h1>Hello World</h1><p>This is a PDF generated from HTML!</p>',
51
+ css: 'body { font-family: Arial; } h1 { color: blue; }',
52
+ viewportWidth: 800,
53
+ viewportHeight: 600,
54
+ pageWidth: 800,
55
+ pageHeight: 1100,
56
+ margins: { top: 20, right: 20, bottom: 20, left: 20 }
57
+ });
58
+
59
+ // Save or use the PDF bytes
60
+ fs.writeFileSync('output.pdf', Buffer.from(pdfBytes));
61
+ ```
62
+
61
63
  ### Advanced Example with Custom Fonts
62
64
 
63
65
  ```typescript
64
66
  import { renderHtmlToPdf } from 'pagyra-js';
65
-
66
- const pdfBytes = await renderHtmlToPdf({
67
- html: `
68
- <div class="container">
69
- <h1>Advanced PDF Example</h1>
70
- <p class="justified">This text will be justified and use custom fonts.</p>
71
- <div class="box">Styled box with border-radius</div>
72
- </div>
73
- `,
74
- css: `
75
- @font-face {
76
- font-family: 'CustomFont';
77
- src: url('/path/to/font.woff2') format('woff2');
78
- font-weight: normal;
79
- }
80
- body {
81
- font-family: 'CustomFont', Arial;
82
- font-size: 14px;
83
- }
84
- .justified {
85
- text-align: justify;
86
- overflow-wrap: break-word;
87
- }
88
- .box {
89
- width: 200px;
90
- height: 100px;
91
- background-color: #f0f0f0;
92
- border-radius: 8px;
93
- border: 1px solid #ccc;
94
- }
95
- `,
96
- viewportWidth: 1000,
97
- viewportHeight: 800,
98
- pageWidth: 1000,
99
- pageHeight: 1400,
100
- margins: { top: 30, right: 30, bottom: 30, left: 30 },
101
- fontConfig: {
102
- fontFaceDefs: [
103
- {
104
- name: 'CustomFont',
105
- family: 'CustomFont',
106
- src: '/path/to/font.woff2',
107
- weight: 400,
108
- style: 'normal'
109
- }
110
- ]
111
- }
67
+
68
+ const pdfBytes = await renderHtmlToPdf({
69
+ html: `
70
+ <div class="container">
71
+ <h1>Advanced PDF Example</h1>
72
+ <p class="justified">This text will be justified and use custom fonts.</p>
73
+ <div class="box">Styled box with border-radius</div>
74
+ </div>
75
+ `,
76
+ css: `
77
+ @font-face {
78
+ font-family: 'CustomFont';
79
+ src: url('/path/to/font.woff2') format('woff2');
80
+ font-weight: normal;
81
+ }
82
+ body {
83
+ font-family: 'CustomFont', Arial;
84
+ font-size: 14px;
85
+ }
86
+ .justified {
87
+ text-align: justify;
88
+ overflow-wrap: break-word;
89
+ }
90
+ .box {
91
+ width: 200px;
92
+ height: 100px;
93
+ background-color: #f0f0f0;
94
+ border-radius: 8px;
95
+ border: 1px solid #ccc;
96
+ }
97
+ `,
98
+ viewportWidth: 1000,
99
+ viewportHeight: 800,
100
+ pageWidth: 1000,
101
+ pageHeight: 1400,
102
+ margins: { top: 30, right: 30, bottom: 30, left: 30 },
103
+ fontConfig: {
104
+ fontFaceDefs: [
105
+ {
106
+ name: 'CustomFont',
107
+ family: 'CustomFont',
108
+ src: '/path/to/font.woff2',
109
+ weight: 400,
110
+ style: 'normal'
111
+ }
112
+ ]
113
+ }
112
114
  });
113
115
  ```
114
116
 
@@ -214,28 +216,28 @@ Notes:
214
216
  ## API Reference
215
217
 
216
218
  ### Main Functions
217
-
218
- #### `renderHtmlToPdf(options: RenderHtmlOptions): Promise<Uint8Array>`
219
-
220
- Converts HTML to PDF and returns the PDF as a Uint8Array.
221
-
222
- **Parameters:**
223
-
224
- **Mandatory Parameters:**
225
- - `html`: HTML content string (the only truly required parameter)
226
-
227
- **Optional Parameters (with sensible defaults available):**
228
- - `css`: CSS styles string (defaults to empty string)
229
- - `viewportWidth`: Viewport width in pixels (can be calculated from page size)
230
- - `viewportHeight`: Viewport height in pixels (can be calculated from page size)
231
- - `pageWidth`: Page width in pixels (defaults to A4 width: ~595pt/8.27in)
232
- - `pageHeight`: Page height in pixels (defaults to A4 height: ~841pt/11.69in)
233
- - `margins`: Page margins in pixels (defaults to standard A4 margins: ~36pt/0.5in all sides)
234
- - `debug`: Enable debug logging (optional, defaults to false)
235
- - `debugLevel`: Debug log level (optional)
236
- - `debugCats`: Debug categories (optional)
237
- - `fontConfig`: Font configuration (optional, loads built-in fonts by default)
238
- - `resourceBaseDir`: Base directory for resource resolution (optional)
219
+
220
+ #### `renderHtmlToPdf(options: RenderHtmlOptions): Promise<Uint8Array>`
221
+
222
+ Converts HTML to PDF and returns the PDF as a Uint8Array.
223
+
224
+ **Parameters:**
225
+
226
+ **Mandatory Parameters:**
227
+ - `html`: HTML content string (the only truly required parameter)
228
+
229
+ **Optional Parameters (with sensible defaults available):**
230
+ - `css`: CSS styles string (defaults to empty string)
231
+ - `viewportWidth`: Viewport width in pixels (can be calculated from page size)
232
+ - `viewportHeight`: Viewport height in pixels (can be calculated from page size)
233
+ - `pageWidth`: Page width in pixels (defaults to A4 width: ~595pt/8.27in)
234
+ - `pageHeight`: Page height in pixels (defaults to A4 height: ~841pt/11.69in)
235
+ - `margins`: Page margins in pixels (defaults to standard A4 margins: ~36pt/0.5in all sides)
236
+ - `debug`: Enable debug logging (optional, defaults to false)
237
+ - `debugLevel`: Debug log level (optional)
238
+ - `debugCats`: Debug categories (optional)
239
+ - `fontConfig`: Font configuration (optional, loads built-in fonts by default)
240
+ - `resourceBaseDir`: Base directory for resource resolution (optional)
239
241
  - `assetRootDir`: Asset root directory (optional)
240
242
  - `headerFooter`: Header/footer configuration (optional)
241
243
  - `environment`: Environment abstraction (Node/browser, optional - defaults to Node environment)
@@ -248,138 +250,155 @@ Converts HTML to PDF and returns the PDF as a Uint8Array.
248
250
  - `maxHeaderHeightPx`, `maxFooterHeightPx`: reserved space in pixels (optional, auto-measured if omitted)
249
251
  - `layerMode`: `"under"` (default) or `"over"`
250
252
  - `clipOverflow`, `fontFamily`, `placeholders` (advanced)
251
-
252
- **Note:** While the TypeScript interface requires all parameters, in practice only `html` is truly mandatory. The playground server demonstrates how to compute reasonable defaults for other parameters using helper functions like `sanitizeDimension()` and `resolvePageMarginsPx()`.
253
-
254
- #### `prepareHtmlRender(options: RenderHtmlOptions): Promise<PreparedRender>`
255
-
256
- Prepares HTML for rendering without generating the final PDF. Useful for debugging layout.
257
-
258
- **Returns:**
259
- - `layoutRoot`: Root layout node
260
- - `renderTree`: Render tree structure
261
- - `pageSize`: Page dimensions in points
262
- - `margins`: Applied margins
263
-
264
- ### CSS Support
265
-
266
- Pagyra-js supports a comprehensive set of CSS properties:
267
-
268
- - **Layout**: `display`, `position`, `float`, `clear`, `z-index`
269
- - **Box Model**: `width`, `height`, `margin`, `padding`, `border`, `box-sizing`
270
- - **Flexbox**: `flex-direction`, `flex-wrap`, `justify-content`, `align-items`, etc.
271
- - **Grid**: `grid-template`, `grid-gap`, `grid-auto-flow`
272
- - **Text**: `font-family`, `font-size`, `font-weight`, `line-height`, `text-align`, `text-transform`, `overflow-wrap`
273
- - **Colors**: `color`, `background-color`, `opacity`
274
- - **Spacing**: `gap`, `margin-block`, `margin-inline`
275
- - **Units**: `px`, `em`, `rem`, `pt`, `mm`, `cm`, `in`, `%`
276
- - **Custom Properties**: CSS variables with `var()`
277
-
278
- ### Font Configuration
279
-
280
- ```typescript
281
- interface FontConfig {
282
- fontFaceDefs: Array<{
283
- name: string;
284
- family: string;
285
- src: string;
286
- data?: ArrayBuffer; // Font data (required for browser environment)
287
- weight: number;
288
- style: 'normal' | 'italic';
289
- }>;
290
- }
291
- ```
292
-
293
- For a detailed guide on how to work with custom fonts in Vite and browser environments, see [Embedding Fonts](docs/font-embedding.md).
294
-
295
- ## Development
296
-
297
- ### Project Structure
298
-
299
- ```
300
- src/
301
- ├── core.ts # Core exports and types
302
- ├── html-to-pdf.ts # Main HTML to PDF conversion logic
303
- ├── index.ts # Main entry point
304
- ├── browser-entry.ts # Browser-specific entry point
305
- ├── css/ # CSS parsing and styling
306
- ├── dom/ # DOM node handling
307
- ├── html/ # HTML parsing and conversion
308
- ├── layout/ # Layout calculation engine
309
- ├── pdf/ # PDF generation and rendering
310
- ├── svg/ # SVG support
311
- ├── units/ # Unit conversion utilities
312
- └── ... (other modules)
313
- ```
314
-
315
- ### Build Process
316
-
317
- ```bash
318
- # Install dependencies
319
- npm install
320
-
321
- # Build the project
322
- npm run build
323
-
324
- # Run tests
325
- npm test
326
-
327
- # Run linter
328
- npm run lint
329
-
330
- # Run playground (Node environment)
331
- npm run playground
332
-
333
- # Run browser playground
334
- npm run playground:browser
335
- ```
336
-
337
- ### Development Scripts
338
-
339
- - `npm run build`: Compile TypeScript to JavaScript
340
- - `npm run clean`: Remove build artifacts
341
- - `npm run test`: Run test suite
342
- - `npm run lint`: Run ESLint
343
- - `npm run playground`: Interactive development environment
344
- - `npm run playground:browser`: Browser-based playground
345
- - `npm run build:browser`: Build browser bundle
346
-
347
- ## Browser Support
348
-
349
- Pagyra-js can run in browser environments with some configuration:
350
-
351
- ```typescript
352
- import { renderHtmlToPdfBrowser } from 'pagyra-js/browser-entry';
353
-
354
- // Use the browser-specific entry point
355
- const pdfBytes = await renderHtmlToPdfBrowser({
356
- html: '<p>Browser PDF generation</p>',
357
- css: 'body { font-family: Arial; }',
358
- // ... other options
359
- environment: new BrowserEnvironment() // Provide browser environment
360
- });
361
- ```
362
-
363
- ## Examples
364
-
365
- Check the `playground/public/examples/` directory for various usage examples:
366
- - Basic HTML to PDF conversion
367
- - CSS layout demonstrations
368
- - SVG rendering examples
369
- - Advanced text formatting
370
- - Custom font usage
371
-
372
- ## Contributing
373
-
374
- Contributions are welcome! Please follow these guidelines:
375
-
376
- 1. Fork the repository
377
- 2. Create a feature branch
378
- 3. Implement your changes
379
- 4. Add tests for new functionality
380
- 5. Run `npm run lint` and `npm test`
381
- 6. Submit a pull request
382
-
383
- ## License
384
-
385
- MIT License
253
+
254
+ **Note:** While the TypeScript interface requires all parameters, in practice only `html` is truly mandatory. The playground server demonstrates how to compute reasonable defaults for other parameters using helper functions like `sanitizeDimension()` and `resolvePageMarginsPx()`.
255
+
256
+ #### `prepareHtmlRender(options: RenderHtmlOptions): Promise<PreparedRender>`
257
+
258
+ Prepares HTML for rendering without generating the final PDF. Useful for debugging layout.
259
+
260
+ **Returns:**
261
+ - `layoutRoot`: Root layout node
262
+ - `renderTree`: Render tree structure
263
+ - `pageSize`: Page dimensions in points
264
+ - `margins`: Applied margins
265
+
266
+ ### CSS Support
267
+
268
+ Pagyra-js supports a comprehensive set of CSS properties:
269
+
270
+ - **Layout**: `display`, `position`, `float`, `clear`, `z-index`
271
+ - **Box Model**: `width`, `height`, `margin`, `padding`, `border`, `box-sizing`
272
+ - **Flexbox**: `flex-direction`, `flex-wrap`, `justify-content`, `align-items`, etc.
273
+ - **Grid**: `grid-template`, `grid-gap`, `grid-auto-flow`
274
+ - **Text**: `font-family`, `font-size`, `font-weight`, `line-height`, `text-align`, `text-transform`, `overflow-wrap`
275
+ - **Colors**: `color`, `background-color`, `opacity`
276
+ - **Spacing**: `gap`, `margin-block`, `margin-inline`
277
+ - **Units**: `px`, `em`, `rem`, `pt`, `mm`, `cm`, `in`, `%`
278
+ - **Custom Properties**: CSS variables with `var()`
279
+
280
+ ### Font Configuration
281
+
282
+ ```typescript
283
+ interface FontConfig {
284
+ fontFaceDefs: Array<{
285
+ name: string;
286
+ family: string;
287
+ src: string;
288
+ data?: ArrayBuffer; // Font data (required for browser environment)
289
+ weight: number;
290
+ style: 'normal' | 'italic';
291
+ }>;
292
+ }
293
+ ```
294
+
295
+ For a detailed guide on how to work with custom fonts in Vite and browser environments, see [Embedding Fonts](docs/font-embedding.md).
296
+
297
+ ## Development
298
+
299
+ ### Project Structure
300
+
301
+ ```
302
+ src/
303
+ ├── core.ts # Core exports and types
304
+ ├── html-to-pdf.ts # Main HTML to PDF conversion logic
305
+ ├── index.ts # Main entry point
306
+ ├── browser-entry.ts # Browser-specific entry point
307
+ ├── css/ # CSS parsing and styling
308
+ ├── dom/ # DOM node handling
309
+ ├── html/ # HTML parsing and conversion
310
+ ├── layout/ # Layout calculation engine
311
+ ├── pdf/ # PDF generation and rendering
312
+ ├── svg/ # SVG support
313
+ ├── units/ # Unit conversion utilities
314
+ └── ... (other modules)
315
+ ```
316
+
317
+ ### Build Process
318
+
319
+ ```bash
320
+ # Install dependencies
321
+ npm install
322
+
323
+ # Build the project
324
+ npm run build
325
+
326
+ # Run tests
327
+ npm test
328
+
329
+ # Run linter
330
+ npm run lint
331
+
332
+ # Run playground (Node environment)
333
+ npm run playground
334
+
335
+ # Run browser playground
336
+ npm run playground:browser
337
+ ```
338
+
339
+ ### Development Scripts
340
+
341
+ - `npm run build`: Compile TypeScript to JavaScript
342
+ - `npm run clean`: Remove build artifacts
343
+ - `npm run test`: Run test suite
344
+ - `npm run lint`: Run ESLint
345
+ - `npm run playground`: Interactive development environment
346
+ - `npm run playground:browser`: Browser-based playground
347
+ - `npm run build:browser`: Build browser bundle
348
+
349
+ ## 🌐 Browser Support
350
+
351
+ Pagyra-js can run in browser environments with some configuration:
352
+
353
+ ```typescript
354
+ import { renderHtmlToPdfBrowser } from 'pagyra-js/browser';
355
+
356
+ // Use the browser-specific entry point
357
+ const pdfBytes = await renderHtmlToPdfBrowser({
358
+ html: '<p>Browser PDF generation</p>',
359
+ css: 'body { font-family: Arial; }',
360
+ // ... other options supported by the browser entrypoint
361
+ });
362
+ ```
363
+
364
+ ### CDN
365
+
366
+ The minified browser bundle is published at:
367
+
368
+ ```text
369
+ https://cdn.jsdelivr.net/npm/pagyra-js@latest/dist/browser/pagyra.min.js
370
+ ```
371
+
372
+ Use it from a module script:
373
+
374
+ ```html
375
+ <script type="module">
376
+ import { renderHtmlToPdfBrowser } from "https://cdn.jsdelivr.net/npm/pagyra-js@latest/dist/browser/pagyra.min.js";
377
+
378
+ // ...
379
+ </script>
380
+ ```
381
+
382
+ ## 🧪 Examples
383
+
384
+ Check the `playground/public/examples/` directory for various usage examples:
385
+ - Basic HTML to PDF conversion
386
+ - CSS layout demonstrations
387
+ - SVG rendering examples
388
+ - Advanced text formatting
389
+ - Custom font usage
390
+
391
+ ## Contributing
392
+
393
+ Contributions are welcome! Please follow these guidelines:
394
+
395
+ 1. Fork the repository
396
+ 2. Create a feature branch
397
+ 3. Implement your changes
398
+ 4. Add tests for new functionality
399
+ 5. Run `npm run lint` and `npm test`
400
+ 6. Submit a pull request
401
+
402
+ ## License
403
+
404
+ MIT License