├── .editorconfig
├── .github
├── CONTRIBUTING.md
└── workflows
│ └── node.js.yml
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.json
├── build-examples.js
├── build-vfs.js
├── build
├── fonts
│ ├── Roboto.js
│ └── Roboto
│ │ ├── Roboto-Italic.ttf
│ │ ├── Roboto-Medium.ttf
│ │ ├── Roboto-MediumItalic.ttf
│ │ └── Roboto-Regular.ttf
├── pdfmake.js
├── pdfmake.js.map
├── pdfmake.min.js
├── pdfmake.min.js.map
├── standard-fonts
│ ├── Courier.js
│ ├── Helvetica.js
│ ├── Symbol.js
│ ├── Times.js
│ └── ZapfDingbats.js
└── vfs_fonts.js
├── dev-playground
├── README.md
├── package.json
├── public
│ ├── ace.js
│ ├── index.html
│ ├── mode-javascript.js
│ ├── pdfmake.css
│ ├── playground.js
│ ├── samples
│ │ ├── attachments
│ │ ├── basics
│ │ ├── columns
│ │ ├── images
│ │ ├── inline-styling
│ │ ├── lists
│ │ ├── margins
│ │ ├── named-styles
│ │ ├── style-overrides
│ │ ├── svgs
│ │ └── tables
│ ├── theme-monokai.js
│ └── worker-javascript.js
└── server.js
├── eslint.config.mjs
├── examples
├── absolute.js
├── attachments.js
├── background.js
├── basics.js
├── columns_simple.js
├── fonts
│ ├── Roboto-Italic.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-MediumItalic.ttf
│ ├── Roboto-Regular.ttf
│ └── sampleImage.jpg
├── images.js
├── links.js
├── lists.js
├── margins.js
├── pageReference.js
├── pdfa.js
├── pdfs
│ ├── absolute.pdf
│ ├── attachments.pdf
│ ├── background.pdf
│ ├── basics.pdf
│ ├── columns_simple.pdf
│ ├── images.pdf
│ ├── links.pdf
│ ├── lists.pdf
│ ├── margins.pdf
│ ├── named_styles.pdf
│ ├── named_styles_with_overrides.pdf
│ ├── pageReference.pdf
│ ├── pdfa.pdf
│ ├── qrCode.pdf
│ ├── relative.pdf
│ ├── sections.pdf
│ ├── security.pdf
│ ├── standardfonts.pdf
│ ├── styling_inlines.pdf
│ ├── styling_properties.pdf
│ ├── svgs.pdf
│ ├── tables.pdf
│ ├── textDecorations.pdf
│ ├── toc.pdf
│ ├── vectors.pdf
│ └── watermark.pdf
├── qrCode.js
├── relative.js
├── sections.js
├── security.js
├── standardfonts.js
├── styling_inlines.js
├── styling_named_styles.js
├── styling_named_styles_with_overrides.js
├── styling_properties.js
├── svgs.js
├── tables.js
├── textDecorations.js
├── toc.js
├── vectors.js
└── watermark.js
├── fonts
├── Roboto.js
└── Roboto
│ ├── Roboto-Italic.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-MediumItalic.ttf
│ └── Roboto-Regular.ttf
├── package.json
├── src
├── 3rd-party
│ ├── svg-to-pdfkit.js
│ └── svg-to-pdfkit
│ │ ├── LICENSE
│ │ └── source.js
├── DocMeasure.js
├── DocPreprocessor.js
├── DocumentContext.js
├── ElementWriter.js
├── LayoutBuilder.js
├── Line.js
├── OutputDocument.js
├── OutputDocumentServer.js
├── PDFDocument.js
├── PageElementWriter.js
├── PageSize.js
├── Printer.js
├── Renderer.js
├── SVGMeasure.js
├── StyleContextStack.js
├── TableProcessor.js
├── TextBreaker.js
├── TextDecorator.js
├── TextInlines.js
├── URLResolver.js
├── base.js
├── browser-extensions
│ ├── OutputDocumentBrowser.js
│ ├── URLBrowserResolver.js
│ ├── fonts
│ │ └── Roboto.js
│ ├── index.js
│ ├── pdfMake.js
│ ├── standard-fonts
│ │ ├── Courier.js
│ │ ├── Helvetica.js
│ │ ├── Symbol.js
│ │ ├── Times.js
│ │ └── ZapfDingbats.js
│ └── virtual-fs-cjs.js
├── columnCalculator.js
├── helpers
│ ├── node.js
│ ├── tools.js
│ └── variableType.js
├── index.js
├── qrEnc.js
├── standardPageSizes.js
├── tableLayouts.js
└── virtual-fs.js
├── standard-fonts
├── Courier.js
├── Helvetica.js
├── Symbol.js
├── Times.js
└── ZapfDingbats.js
├── tests
├── browser
│ └── polyfills.spec.js
├── fonts
│ ├── Roboto-Italic.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-MediumItalic.ttf
│ ├── Roboto-Regular.ttf
│ └── sampleImage.jpg
├── integration
│ ├── alignment.spec.js
│ ├── background.spec.js
│ ├── basics.spec.js
│ ├── columns.spec.js
│ ├── images.spec.js
│ ├── integrationTestHelper.js
│ ├── lists.spec.js
│ ├── svgs.spec.js
│ └── tables.spec.js
└── unit
│ ├── DocMeasure.spec.js
│ ├── DocPreprocessor.spec.js
│ ├── DocumentContext.spec.js
│ ├── ElementWriter.spec.js
│ ├── LayoutBuilder.spec.js
│ ├── Line.spec.js
│ ├── Node-interface.spec.js
│ ├── PDFDocument.spec.js
│ ├── PageElementWriter.spec.js
│ ├── Printer.spec.js
│ ├── SVGMeasure.spec.js
│ ├── StyleContextStack.spec.js
│ ├── TableProcessor.spec.js
│ ├── TextBreaker.spec.js
│ ├── TextDecorator.spec.js
│ ├── TextInlines.spec.js
│ ├── columnCalculator.spec.js
│ └── helpers
│ ├── node.spec.js
│ ├── tools.spec.js
│ └── variableType.spec.js
└── webpack.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | indent_style = tab
7 | indent_size = 2
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 |
13 | [{*.json,*.yml}]
14 | indent_style = space
15 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Thank you for your interest in contributing to this library!
2 |
3 | ## Using the issue tracker
4 |
5 | The issue tracker on GitHub is the preferred channel for bug reports, feature requests, and discussions about pdfmake library.
6 |
7 | Bug reports require example for reproduce issue runnable on [playground](http://pdfmake.org/playground.html) or https://jsfiddle.net/ or a similar service.
8 |
9 | ## Pull requests
10 |
11 | **Please do not commit changes in `build` folder.**
12 |
13 | **Please do not commit changes in `package.json` file if is not related to the pull request changes.**
14 |
15 | Use [EditorConfig](https://editorconfig.org/) in your IDE for keep code style. Do not make code style changes unless it is related to the pull request.
16 |
--------------------------------------------------------------------------------
/.github/workflows/node.js.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Node.js CI
5 |
6 | on: [push, pull_request]
7 |
8 | jobs:
9 | build:
10 |
11 | runs-on: ${{ matrix.os }}
12 |
13 | strategy:
14 | fail-fast: false
15 | matrix:
16 | os: [ubuntu-latest, windows-latest, macos-latest]
17 | node-version: [18.x, 20.x, 22.x]
18 |
19 | steps:
20 | - uses: actions/checkout@v2
21 | - name: Use Node.js ${{ matrix.node-version }}
22 | uses: actions/setup-node@v2
23 | with:
24 | node-version: ${{ matrix.node-version }}
25 | - run: npm install
26 | - run: npm test
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | npm-debug.log
2 | node_modules
3 | doc
4 | .DS_Store
5 | .idea
6 | *.iml
7 | *.ipr
8 | *.iws
9 | nbproject
10 | package-lock.json
11 | yarn.lock
12 | /js
13 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .git*
2 | .idea/
3 | dev-playground/
4 | docs/
5 | examples/
6 | tests/
7 | build/fonts/
8 | package-lock.json
9 | yarn.lock
10 | .editorconfig
11 | eslint.config.mjs
12 | build-fonts.js
13 | build-examples.js
14 | babel.config.json
15 | webpack.config.js
16 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 0.3.0-beta.18 - 2025-05-09
4 |
5 | - Added `section` node
6 | - Fixed crash that occurred when using automatic page height
7 | - Fixed text overflow with some non-wrappable texts
8 |
9 | ## 0.3.0-beta.17 - 2025-04-29
10 |
11 | - Fixed DoS via repeatedly redirect URL in file embedding
12 |
13 | ## 0.3.0-beta.16 - 2025-04-26
14 |
15 | - Update pdfkit to 0.17.0
16 | - Update Roboto font (version 3.011)
17 | - Fixed URL resolving for same URL in browser
18 | - Fixed sharing URL resolver for not available URLs
19 |
20 | ## 0.3.0-beta.15 - 2025-01-01
21 |
22 | - Reverted to the original `pdfkit` package, moving away from `@foliojs-fork`
23 | - Update pdfkit to 0.16.0
24 | - Fixed a potential issue in the minimized library when detecting the orientation of JPEG images
25 |
26 | ## 0.3.0-beta.14 - 2024-12-23
27 |
28 | - Fixed big size pdfmake bundle for browser
29 |
30 | ## 0.3.0-beta.13 - 2024-12-15
31 |
32 | - Update pdfkit to 0.15.2
33 | - Fixed speed in Node.js if is fetching URL for image or font redirected
34 | - Fixed aspect ratio for image with exif orientation tag
35 | - Fixed font size calculation for watermark if is page orientation is changed
36 |
37 | ## 0.3.0-beta.12 - 2024-11-03
38 |
39 | - Added support PDF/A and PDF/UA (see [documentation](https://pdfmake.github.io/docs/0.3/document-definition-object/pdfa/))
40 | - Added support `link`, `linkToPage` and `linkToDestination` for SVG
41 | - Update pdfkit to 0.15.1
42 | - Fixed bug with how page breaks provoked by cells with rowspan were handled
43 | - Fixed find where previous cell started with row span and col span combination
44 | - Fixed calculating correctly the 'y' at the end of a rowSpan with dontBreakRows
45 |
46 | ## 0.3.0-beta.11 - 2024-10-09
47 |
48 | - Fixed drawing top horizontal line of the table with page break
49 |
50 | ## 0.3.0-beta.10 - 2024-09-22
51 |
52 | - Drop support Internet Explorer 11 (Microsoft will not support from 2022)
53 | - Minimal supported version Node.js 18 LTS
54 | - Update Roboto font (version 3.010)
55 | - Fixed page break in a column group
56 | - Fixed saving margins in an unbreakable block
57 | - Fixed fillColor items in unbreakable blocks
58 | - Fixed calculating correctly the 'y' at the end of a rowSpan with dontBreakRows
59 | - Fixed margins (top/bottom) of nodes and row height are considered for breaking page
60 | - Fixed margins after page break
61 | - Fixed margins of nodes with relativePosition or absolutePosition are ignored and don't interfere with the regular flow of the layout
62 |
63 | ## 0.3.0-beta.9 - 2024-08-09
64 |
65 | - Fixed and validates input values headerRows and keepWithHeaderRows
66 | - Fixed numbering nested ordered lists
67 | - Speed up StyleContextStack.autopush() for large tables
68 | - Fixed widths of table columns with percentages
69 | - Fixed storing the correct context in the ending cell of a row span when there were nested column groups (columns or tables)
70 |
71 | ## 0.3.0-beta.8 - 2024-03-07
72 |
73 | - Removed unused brfs dependency
74 |
75 | ## 0.3.0-beta.7 - 2024-01-01
76 |
77 | - Minimal supported version Node.js 16 LTS
78 | - Added padding option for QR code
79 | - Allow the document language to be specified
80 | - Fixed cover image size inside table
81 | - Fixed "Cannot read properties of undefined (reading 'bottomMost')" if table contains too few rows
82 | - Fixed invalid source-maps in built js file
83 |
84 | ## 0.3.0-beta.6 - 2023-11-09
85 |
86 | - Update pdfkit to 0.14.0
87 | - Update Roboto font (version 3.008)
88 |
89 | ## 0.3.0-beta.5 - 2023-02-19
90 |
91 | - Fixed document buffer size. Node.js 18+ allow max 1 GiB.
92 |
93 | ## 0.3.0-beta.4 - 2022-12-17
94 |
95 | - Minimal supported version Node.js 14 LTS
96 | - Fixed theoretical vulnerability CVE-2022-46161 (**It was never part of version released as npm package or cdnjs or bower or packagist!**)
97 |
98 | ## 0.3.0-beta.3 - 2022-10-09
99 |
100 | - Updated Roboto font (version 3.005)
101 | - Fixed calculating auto page height
102 | - Fixed TrueType Collection loading from URL
103 | - Fixed refetching fonts from URL
104 |
105 | ## 0.3.0-beta.2 - 2022-04-01
106 |
107 | - Attachments embedding
108 | - Support passing headers to request for loading font files and images via URL addresses
109 |
110 | ## 0.3.0-beta.1 - 2022-01-01
111 |
112 | - Port code base to ES6+
113 | - Unify interface for node and browser **(breaking change)**
114 | - All methods return promise instead of using callback **(breaking change)**
115 | - Change including virtual font storage in client-side **(breaking change)**
116 | - Change parameters of `pageBreakBefore` function **(breaking change)**
117 | - Support for loading font files and images via URL adresses (https:// or http:// protocol) in Node.js (client and server side now)
118 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014-2015 bpampuch
4 | 2016-2025 liborm85
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pdfmake [![Node.js CI][githubactions_img]][githubactions_url] [![GitHub][github_img]][github_url] [![npm][npm_img]][npm_url] [![CDNJS][cdnjs_img]][cndjs_url]
2 |
3 | [githubactions_img]: https://github.com/bpampuch/pdfmake/actions/workflows/node.js.yml/badge.svg?branch=master
4 | [githubactions_url]: https://github.com/bpampuch/pdfmake/actions
5 |
6 | [github_img]: https://img.shields.io/github/release/bpampuch/pdfmake.svg?colorB=0E7FBF
7 | [github_url]: https://github.com/bpampuch/pdfmake/releases/latest
8 |
9 | [npm_img]: https://img.shields.io/npm/v/pdfmake.svg?colorB=0E7FBF
10 | [npm_url]: https://www.npmjs.com/package/pdfmake
11 |
12 | [cdnjs_img]: https://img.shields.io/cdnjs/v/pdfmake.svg?colorB=0E7FBF
13 | [cndjs_url]: https://cdnjs.com/libraries/pdfmake
14 |
15 |
16 | PDF document generation library for server-side and client-side in pure JavaScript.
17 |
18 | Check out [the playground](http://bpampuch.github.io/pdfmake/playground.html) and [examples](https://github.com/bpampuch/pdfmake/tree/master/examples).
19 |
20 | #### This is unstable master branch for version 0.3.x, for stable use version 0.2.x see [branch 0.2](https://github.com/bpampuch/pdfmake/tree/0.2) or older version 0.1.x see [branch 0.1](https://github.com/bpampuch/pdfmake/tree/0.1).
21 |
22 | ### Features
23 |
24 | * line-wrapping,
25 | * text-alignments (left, right, centered, justified),
26 | * numbered and bulleted lists,
27 | * tables and columns
28 | * auto/fixed/star-sized widths,
29 | * col-spans and row-spans,
30 | * headers automatically repeated in case of a page-break,
31 | * images and vector graphics,
32 | * convenient styling and style inheritance,
33 | * page headers and footers:
34 | * static or dynamic content,
35 | * access to current page number and page count,
36 | * background-layer,
37 | * page dimensions and orientations,
38 | * margins,
39 | * document sections,
40 | * custom page breaks,
41 | * font embedding,
42 | * support for complex, multi-level (nested) structures,
43 | * table of contents,
44 | * helper methods for opening/printing/downloading the generated PDF,
45 | * setting of PDF metadata (e.g. author, subject).
46 |
47 | ## Documentation
48 |
49 | **Documentation URL: https://pdfmake.github.io/docs/**
50 |
51 | Source of documentation: https://github.com/pdfmake/docs **Improvements are welcome!**
52 |
53 | ## Building from sources
54 |
55 | using npm:
56 | ```
57 | git clone https://github.com/bpampuch/pdfmake.git
58 | cd pdfmake
59 | npm install
60 | npm run build
61 | ```
62 |
63 | using yarn:
64 | ```
65 | git clone https://github.com/bpampuch/pdfmake.git
66 | cd pdfmake
67 | yarn
68 | yarn run build
69 | ```
70 |
71 | ## License
72 | MIT
73 |
74 | ## Authors
75 | * [@bpampuch](https://github.com/bpampuch) (founder)
76 | * [@liborm85](https://github.com/liborm85)
77 |
78 | pdfmake is based on a truly amazing library [pdfkit](https://github.com/devongovett/pdfkit) (credits to [@devongovett](https://github.com/devongovett)).
79 |
80 | Thanks to all contributors.
81 |
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": {
7 | "node": "18.12"
8 | },
9 | "loose": true
10 | }
11 | ]
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/build-examples.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const exec = require('child_process').exec;
3 |
4 | var errCount = 0;
5 | var position = 0;
6 | process.chdir('examples');
7 |
8 | const items = fs.readdirSync('.');
9 | const files = items.filter(file => file.substring(file.length - 3, file.length) === '.js');
10 |
11 | files.forEach(function (file) {
12 | exec(`node ${file}`, function (err, stdout, stderr) {
13 | position++;
14 | console.log('FILE: ', file, ` (${position}/${files.length})`);
15 | console.log(stdout);
16 |
17 | if (stderr) {
18 | errCount++;
19 | console.error(stderr);
20 | } else if (err) {
21 | errCount++;
22 | console.error(err);
23 | }
24 |
25 | if (position === files.length) {
26 | if (errCount) {
27 | console.error('Errors count: ', errCount);
28 | }
29 | }
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/build-vfs.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | const vfsBefore = "var vfs = ";
4 | const vfsAfter = "; var _global = typeof window === 'object' ? window : typeof global === 'object' ? global : typeof self === 'object' ? self : this; if (typeof _global.pdfMake !== 'undefined' && typeof _global.pdfMake.addVirtualFileSystem !== 'undefined') { _global.pdfMake.addVirtualFileSystem(vfs); } if (typeof module !== 'undefined') { module.exports = vfs; }";
5 | const sourcePath = process.argv[2];
6 | const vfsFilename = process.argv[3] ? process.argv[3] : './build/vfs_fonts.js';
7 |
8 | var vfs = {};
9 |
10 | if (sourcePath === undefined) {
11 | console.error('Usage: node build-vfs.js path [filename]');
12 | console.log('');
13 | console.log('Parameters:');
14 | console.log(' path Source path with fonts.');
15 | console.log(' filename Optional. Output vfs file. Default: ./build/vfs_fonts.js');
16 | console.log('');
17 | console.log('Examples:');
18 | console.log(' node build-vfs.js "examples/fonts"');
19 | console.log(' node build-vfs.js "examples/fonts" "./build/vfs_fonts.js"');
20 | return;
21 | }
22 |
23 | if (!fs.existsSync(sourcePath)) {
24 | console.error('Source path "' + sourcePath + '" not found.');
25 | return;
26 | }
27 |
28 | console.log('Source path:', sourcePath);
29 | console.log('');
30 |
31 | var files = fs.readdirSync(sourcePath);
32 |
33 | files.forEach(function (file) {
34 | var fileBase64 = fs.readFileSync(sourcePath + '/' + file).toString('base64');
35 | console.log('FILE:', file);
36 |
37 | vfs[file] = fileBase64;
38 | });
39 |
40 | const vfsFileContent = vfsBefore + JSON.stringify(vfs, null, 2) + vfsAfter;
41 | fs.writeFileSync(vfsFilename, vfsFileContent);
42 |
43 | console.log('');
44 | console.log('Builded ' + files.length + ' files to ' + vfsFilename + '.');
45 |
--------------------------------------------------------------------------------
/build/fonts/Roboto/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/build/fonts/Roboto/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/build/fonts/Roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/build/fonts/Roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/build/fonts/Roboto/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/build/fonts/Roboto/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/build/fonts/Roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/build/fonts/Roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/dev-playground/README.md:
--------------------------------------------------------------------------------
1 | ## Dev Playground
2 |
3 | Start from pdfmake ROOT directory with nodemon if you want server to restart with every change you make in pdfmake/src:
4 |
5 | ```
6 | cd dev-playground
7 | npm install # or: yarn
8 | npm install -g nodemon
9 | cd ..
10 | nodemon ./dev-playground/server.js
11 | ```
12 |
--------------------------------------------------------------------------------
/dev-playground/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pdfmake-server-playground",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "body-parser": "^1.20.2",
6 | "express": "^4.18.2"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/dev-playground/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
31 |
32 |
40 |
41 |
42 |
43 |
44 |
Playground does not make too much sense when horizontal resolution is below 300px
45 |
46 |
47 |
52 |
53 |
54 |
55 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/dev-playground/public/pdfmake.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Open Sans', sans-serif;
3 | color: #666;
4 | background: white !important;
5 | }
6 | .navbar {
7 | margin-bottom: 0;
8 | background-color: white;
9 | border-bottom: 0;
10 | }
11 | #top.navbar-default a {
12 | color: #0074c1;
13 | }
14 | #top.navbar-default .navbar-nav a{
15 | text-transform: uppercase;
16 | }
17 | #top.navbar-default li:hover {
18 | background: rgb(249,249,249);
19 | }
20 | h2 {
21 | font-weight: 300;
22 | color: #0074c1;
23 | font-size: 24px;
24 | }
25 | .keyDescription {
26 | padding-bottom: 80px;
27 | }
28 |
29 | h4 {
30 | opacity: 0.9;
31 | }
32 | .subtitle {
33 | color: white;
34 | margin-top: 30px;
35 | }
36 | .header, .playground {
37 | background: #0074c1;
38 | color: white;
39 | }
40 | .header p {
41 | opacity: 0.7;
42 | font-weight: 300;
43 | font-size: 18px;
44 | }
45 | h1 {
46 | font-size: 36px;
47 | font-weight: 300;
48 | }
49 |
50 | .playground ul {
51 | list-style: none;
52 | padding: 0;
53 | margin-left: -8px;
54 | margin-bottom: 0;
55 | }
56 |
57 | .playground li {
58 | display: none;
59 | padding: 8px;
60 | text-transform: uppercase;
61 | cursor: pointer;
62 | font-size: 12px;
63 | text-overflow: ellipsis;
64 | }
65 |
66 | .playground li:hover {
67 | background: rgba(0,0,0,0.1);
68 | }
69 |
70 | #pdfeViewer {
71 | background-color: #404040;
72 | }
73 |
74 | @media(min-width: 768px) {
75 | h1 {
76 | font-size: 60px;
77 | }
78 | .header {
79 | padding-top: 20px;
80 | padding-bottom: 40px;
81 | margin-bottom: 30px;
82 | height: 400px;
83 | }
84 | .header p {
85 | font-size: 24px;
86 | line-height: 1.4;
87 | }
88 | .page h1 {
89 | font-size: 40px;
90 | }
91 | h2 {
92 | font-size: 30px;
93 |
94 | }
95 |
96 | .subtitle {
97 | margin-top: 90px;
98 | }
99 | }
100 | .pdf {
101 | font-weight: 300;
102 | }
103 | .make {
104 | font-weight: 600
105 | }
106 |
107 | .playgroundBody .content {
108 | display: none;
109 | }
110 |
111 |
112 | #editor {
113 | position: absolute;
114 | top: 0px;
115 | right: 50%;
116 | left: 0;
117 | width: 50%;
118 | height: 100%;
119 | }
120 |
121 |
122 | #stats {
123 | display: none;
124 | float: right;
125 | position: relative;
126 | top: 6px;
127 | opacity: 0.5;
128 | }
129 | #printThis {
130 | float: right;
131 | top:0;
132 | }
133 |
134 |
135 | @media(min-width: 300px) and (max-width: 1000px) {
136 | .playground .container li {
137 | display: inline-block;
138 | }
139 |
140 | #exampleList li {
141 | width: 60px;
142 | overflow: hidden;
143 | text-overflow: ellipsis;
144 | }
145 |
146 | .playgroundBody .content {
147 | position: fixed;
148 | display: block;
149 | bottom: 0;
150 | left: 0;
151 | right: 0;
152 | top: 83px;
153 | }
154 |
155 | #editor {
156 | position: absolute;
157 | right: 0;
158 | left: 0;
159 | width: 100%;
160 | height: 50%;
161 | top: 0;
162 | bottom: 50%;
163 | }
164 |
165 | #pdfV {
166 | left: 0;
167 | right: 0;
168 | bottom: 0;
169 | top: 50%;
170 | height: 50%;
171 | width: 100%;
172 | position: absolute;
173 | }
174 |
175 | .playgroundBody .notEnoughSpace, #stats {
176 | display: none;
177 | }
178 | }
179 |
180 |
181 | .subpage {
182 | margin-top: 50px;
183 | margin-bottom: 100px;
184 | }
185 | .subpage h1 {
186 | font-size: 48px;
187 | color: #0074c1;
188 | }
189 |
190 | @media(max-width: 767px) {
191 | .banner {
192 | display: none;
193 | }
194 |
195 | .subpage {
196 | margin-top: 40px;
197 | }
198 | .subpage h1 {
199 | font-size: 30px;
200 | font-weight: 400;
201 | }
202 | }
203 |
204 | @media(min-width: 1001px) {
205 | .playground .container li {
206 | display: inline-block;
207 | }
208 | .playgroundBody .content {
209 | position: fixed;
210 | display: block;
211 | bottom: 0;
212 | left: 0;
213 | right: 0;
214 | top: 83px;
215 | }
216 |
217 | #pdfV {
218 | left: 50%;
219 | width: 50%;
220 | height: 100%;
221 | right: 0;
222 | top: 0;
223 | bottom: 0;
224 | position: absolute;
225 | }
226 | .playgroundBody .notEnoughSpace {
227 | display: none;
228 | }
229 |
230 | #stats {
231 | display: block;
232 | }
233 | }
234 |
235 | #pdfeViewer {
236 | position: absolute;
237 | top: 0px;
238 | left: 50%;
239 | bottom: 0;
240 | right: 0;
241 | }
242 |
243 | #toolbarViewerRight, #sidebarToggle, .toolbarButtonSpacer, #viewFind {
244 | display:none;
245 | }
246 |
247 | #toolbarViewerLeft {
248 | width: 100%
249 | }
250 |
251 | .playground {
252 | position: relative;
253 | }
254 |
255 | .banner small {
256 | color: white;
257 | opacity: 0.4;
258 | }
259 |
--------------------------------------------------------------------------------
/dev-playground/public/playground.js:
--------------------------------------------------------------------------------
1 | var app = angular.module('pdfmake', ['ngRoute']);
2 |
3 | app.config(function ($routeProvider) {
4 | $routeProvider
5 | .when('/', {
6 | templateUrl: 'index.html',
7 | controller: 'PlaygroundController'
8 | })
9 | .otherwise({ redirectTo: '/' });
10 | });
11 |
--------------------------------------------------------------------------------
/dev-playground/public/samples/basics:
--------------------------------------------------------------------------------
1 | content: [
2 | 'First paragraph',
3 | 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
4 | ]
5 |
--------------------------------------------------------------------------------
/dev-playground/public/samples/inline-styling:
--------------------------------------------------------------------------------
1 | content: [
2 | {
3 | text: 'This is a header (whole paragraph uses the same header style)\n\n',
4 | style: 'header'
5 | },
6 | {
7 | text: [
8 | 'It is however possible to provide an array of texts ',
9 | 'to the paragraph (instead of a single string) and have ',
10 | {text: 'a better ', fontSize: 15, bold: true},
11 | 'control over it. \nEach inline can be ',
12 | {text: 'styled ', fontSize: 20},
13 | {text: 'independently ', italics: true, fontSize: 40},
14 | 'then.\n\n'
15 | ]
16 | },
17 | {text: 'Mixing named styles and style-overrides', style: 'header'},
18 | {
19 | style: 'bigger',
20 | italics: false,
21 | text: [
22 | 'We can also mix named-styles and style-overrides at both paragraph and inline level. ',
23 | 'For example, this paragraph uses the "bigger" style, which changes fontSize to 15 and sets italics to true. ',
24 | 'Texts are not italics though. It\'s because we\'ve overriden italics back to false at ',
25 | 'the paragraph level. \n\n',
26 | 'We can also change the style of a single inline. Let\'s use a named style called header: ',
27 | {text: 'like here.\n', style: 'header'},
28 | 'It got bigger and bold.\n\n',
29 | 'OK, now we\'re going to mix named styles and style-overrides at the inline level. ',
30 | 'We\'ll use header style (it makes texts bigger and bold), but we\'ll override ',
31 | 'bold back to false: ',
32 | {text: 'wow! it works!', style: 'header', bold: false},
33 | '\n\nMake sure to take a look into the sources to understand what\'s going on here.'
34 | ]
35 | }
36 | ],
37 | styles: {
38 | header: {
39 | fontSize: 18,
40 | bold: true
41 | },
42 | bigger: {
43 | fontSize: 15,
44 | italics: true
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/dev-playground/public/samples/margins:
--------------------------------------------------------------------------------
1 | content: [
2 | {
3 | stack: [
4 | 'This header has both top and bottom margins defined',
5 | {text: 'This is a subheader', style: 'subheader'},
6 | ],
7 | style: 'header'
8 | },
9 | {
10 | text: [
11 | 'Margins have slightly different behavior than other layout properties. They are not inherited, unlike anything else. They\'re applied only to those nodes which explicitly ',
12 | 'set margin or style property.\n',
13 | ]
14 | },
15 | {
16 | text: 'This paragraph (consisting of a single line) directly sets top and bottom margin to 20',
17 | margin: [0, 20],
18 | },
19 | {
20 | stack: [
21 | {text: [
22 | 'This line begins a stack of paragraphs. The whole stack uses a ',
23 | {text: 'superMargin', italics: true},
24 | ' style (with margin and fontSize properties).',
25 | ]
26 | },
27 | {text: ['When you look at the', {text: ' document definition', italics: true}, ', you will notice that fontSize is inherited by all paragraphs inside the stack.']},
28 | 'Margin however is only applied once (to the whole stack).'
29 | ],
30 | style: 'superMargin'
31 | },
32 | {
33 | stack: [
34 | 'I\'m not sure yet if this is the desired behavior. I find it a better approach however. One thing to be considered in the future is an explicit layout property called inheritMargin which could opt-in the inheritance.\n\n',
35 | {
36 | fontSize: 15,
37 | text: [
38 | 'Currently margins for ',
39 | /* the following margin definition doesn't change anything */
40 | {text: 'inlines', margin: 20},
41 | ' are ignored\n\n'
42 | ],
43 | },
44 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n',
45 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n',
46 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n',
47 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n',
48 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n',
49 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n',
50 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n',
51 | ],
52 | margin: [0, 20, 0, 0],
53 | alignment: 'justify'
54 | }
55 | ],
56 | styles: {
57 | header: {
58 | fontSize: 18,
59 | bold: true,
60 | alignment: 'right',
61 | margin: [0, 190, 0, 80]
62 | },
63 | subheader: {
64 | fontSize: 14
65 | },
66 | superMargin: {
67 | margin: [20, 0, 40, 0],
68 | fontSize: 15
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/dev-playground/public/samples/named-styles:
--------------------------------------------------------------------------------
1 | content: [
2 | {
3 | text: 'This is a header, using header style',
4 | style: 'header'
5 | },
6 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.\n\n',
7 | {
8 | text: 'Subheader 1 - using subheader style',
9 | style: 'subheader'
10 | },
11 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
12 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
13 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n',
14 | {
15 | text: 'Subheader 2 - using subheader style',
16 | style: 'subheader'
17 | },
18 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
19 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n',
20 | {
21 | text: 'It is possible to apply multiple styles, by passing an array. This paragraph uses two styles: quote and small. When multiple styles are provided, they are evaluated in the specified order which is important in case they define the same properties',
22 | style: ['quote', 'small']
23 | }
24 | ],
25 | styles: {
26 | header: {
27 | fontSize: 18,
28 | bold: true
29 | },
30 | subheader: {
31 | fontSize: 15,
32 | bold: true
33 | },
34 | quote: {
35 | italics: true
36 | },
37 | small: {
38 | fontSize: 8
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/dev-playground/public/samples/style-overrides:
--------------------------------------------------------------------------------
1 | content: [
2 | {
3 | text: 'This paragraph uses header style and extends the alignment property',
4 | style: 'header',
5 | alignment: 'center'
6 | },
7 | {
8 | text: [
9 | 'This paragraph uses header style and overrides bold value setting it back to false.\n',
10 | 'Header style in this example sets alignment to justify, so this paragraph should be rendered \n',
11 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.'
12 | ],
13 | style: 'header',
14 | bold: false
15 | }
16 | ],
17 | styles: {
18 | header: {
19 | fontSize: 18,
20 | bold: true,
21 | alignment: 'justify'
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/dev-playground/public/theme-monokai.js:
--------------------------------------------------------------------------------
1 | ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-monokai",t.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})
2 |
--------------------------------------------------------------------------------
/dev-playground/server.js:
--------------------------------------------------------------------------------
1 |
2 | var http = require('http');
3 | var express = require('express');
4 | var path = require('path');
5 | var bodyParser = require('body-parser');
6 |
7 | var pdfmake = require('../js/index');
8 |
9 | var app = express();
10 |
11 | app.use(express.static(path.join(__dirname, 'public')));
12 | app.use(bodyParser.json({ limit: '50mb' }));
13 | app.use(bodyParser.urlencoded({ extended: false }));
14 |
15 | function createPdfBinary(docDefinition) {
16 | var fonts = {
17 | Roboto: {
18 | normal: path.join(__dirname, '..', 'examples', '/fonts/Roboto-Regular.ttf'),
19 | bold: path.join(__dirname, '..', 'examples', '/fonts/Roboto-Medium.ttf'),
20 | italics: path.join(__dirname, '..', 'examples', '/fonts/Roboto-Italic.ttf'),
21 | bolditalics: path.join(__dirname, '..', 'examples', '/fonts/Roboto-MediumItalic.ttf')
22 | }
23 | };
24 |
25 | pdfmake.setFonts(fonts);
26 |
27 | var pdf = pdfmake.createPdf(docDefinition);
28 | return pdf.getDataUrl();
29 | }
30 |
31 | app.post('/pdf', function (req, res) {
32 | const dd = new Function(req.body.content + '; return dd;')();
33 |
34 | createPdfBinary(dd).then(function (binary) {
35 | res.contentType('application/pdf');
36 | res.send(binary);
37 | }, function (error) {
38 | res.send('ERROR:' + error);
39 | });
40 |
41 | });
42 |
43 | var server = http.createServer(app);
44 | var port = process.env.PORT || 1234;
45 | server.listen(port);
46 |
47 | console.log('http server listening on port %d', port);
48 | console.log('dev-playground is available at http://localhost:%d', port);
49 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import jsdoc from "eslint-plugin-jsdoc";
2 | import globals from "globals";
3 | import js from "@eslint/js";
4 |
5 | export default [
6 | {
7 | ignores: ["src/3rd-party/svg-to-pdfkit/*"],
8 | },
9 |
10 | js.configs.recommended,
11 |
12 | {
13 | plugins: {
14 | jsdoc,
15 | },
16 |
17 | languageOptions: {
18 | globals: {
19 | ...globals.browser,
20 | ...globals.node,
21 | ...globals.mocha,
22 | },
23 |
24 | ecmaVersion: 9,
25 | sourceType: "module",
26 | },
27 |
28 | rules: {
29 | semi: 2,
30 | "no-throw-literal": 2,
31 | "no-prototype-builtins": 0,
32 | "jsdoc/check-examples": 0,
33 | "jsdoc/check-param-names": 1,
34 | "jsdoc/check-tag-names": 1,
35 | "jsdoc/check-types": 1,
36 | "jsdoc/no-undefined-types": 1,
37 | "jsdoc/require-description": 0,
38 | "jsdoc/require-description-complete-sentence": 0,
39 | "jsdoc/require-example": 0,
40 | "jsdoc/require-hyphen-before-param-description": 0,
41 | "jsdoc/require-param": 1,
42 | "jsdoc/require-param-description": 0,
43 | "jsdoc/require-param-name": 1,
44 | "jsdoc/require-param-type": 1,
45 | "jsdoc/require-returns": 1,
46 | "jsdoc/require-returns-check": 1,
47 | "jsdoc/require-returns-description": 0,
48 | "jsdoc/require-returns-type": 1,
49 | "jsdoc/valid-types": 1,
50 | },
51 | }
52 | ];
53 |
--------------------------------------------------------------------------------
/examples/basics.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | // or you can define the font manually:
8 | /*
9 | pdfmake.addFonts({
10 | Roboto: {
11 | normal: '../fonts/Roboto/Roboto-Regular.ttf',
12 | bold: '../fonts/Roboto/Roboto-Medium.ttf',
13 | italics: '../fonts/Roboto/Roboto-Italic.ttf',
14 | bolditalics: '../fonts/Roboto/Roboto-MediumItalic.ttf'
15 | }
16 | });
17 | */
18 |
19 | var docDefinition = {
20 | content: [
21 | 'First paragraph',
22 | 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
23 | ]
24 | };
25 |
26 | var now = new Date();
27 |
28 | var pdf = pdfmake.createPdf(docDefinition);
29 | pdf.write('pdfs/basics.pdf').then(() => {
30 | console.log(new Date() - now);
31 | }, err => {
32 | console.error(err);
33 | });
34 |
--------------------------------------------------------------------------------
/examples/fonts/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/fonts/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/examples/fonts/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/fonts/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/examples/fonts/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/fonts/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/examples/fonts/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/fonts/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/examples/fonts/sampleImage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/fonts/sampleImage.jpg
--------------------------------------------------------------------------------
/examples/links.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var docDefinition = {
8 | content: [
9 | {
10 | text: [
11 | 'Link to ',
12 | { text: 'pdfmake website', link: 'http://pdfmake.org', decoration: 'underline' },
13 | ' and ',
14 | { text: 'documentation', link: 'https://pdfmake.github.io/docs/', decoration: 'underline' },
15 | '.'
16 | ]
17 | },
18 | { text: 'Go to page 2', linkToPage: 2, decoration: 'underline' },
19 | { text: 'Link to header 2', linkToDestination: 'header2', decoration: 'underline' },
20 | 'Links are also supported with images:',
21 | { image: 'fonts/sampleImage.jpg', width: 150, link: 'http://pdfmake.org' },
22 | 'With link to page',
23 | { image: 'fonts/sampleImage.jpg', width: 150, linkToPage: 2 },
24 | 'And link to header 2',
25 | { image: 'fonts/sampleImage.jpg', width: 150, linkToDestination: 'header2' },
26 | { text: 'Header on page 2', fontSize: 18, bold: true, pageBreak: 'before' },
27 | { text: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sollicitudin. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Suspendisse nisl. Mauris elementum mauris vitae tortor. Phasellus et lorem id felis nonummy placerat. Aliquam erat volutpat. In laoreet, magna id viverra tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Donec ipsum massa, ullamcorper in, auctor et, scelerisque sed, est. Etiam bibendum elit eget erat. Nullam rhoncus aliquam metus. Proin mattis lacinia justo. Nullam sit amet magna in magna gravida vehicula. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Integer lacinia. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor.' },
28 | '\n\n',
29 | { text: 'Header 2', id: 'header2', fontSize: 18, bold: true },
30 | { text: 'Go to page 1', linkToPage: 1, decoration: 'underline' },
31 | ]
32 | };
33 |
34 | var now = new Date();
35 |
36 | var pdf = pdfmake.createPdf(docDefinition);
37 | pdf.write('pdfs/links.pdf').then(() => {
38 | console.log(new Date() - now);
39 | }, err => {
40 | console.error(err);
41 | });
42 |
--------------------------------------------------------------------------------
/examples/pdfa.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var docDefinition = {
8 | version: '1.5', // PDF version
9 | subset: 'PDF/A-3a', // Subset types: // PDF/A-1, PDF/A-1a, PDF/A-1b, PDF/A-2, PDF/A-2a, PDF/A-2b, PDF/A-3, PDF/A-3a, PDF/A-3b, PDF/UA
10 | tagged: true, // Mark document as Tagged PDF
11 | displayTitle: true, // Display of document title in window title
12 | info: {
13 | title: 'Awesome PDF document from pdfmake'
14 | },
15 | content: [
16 | 'PDF/A document for archive'
17 | ]
18 | };
19 |
20 | var now = new Date();
21 |
22 | var pdf = pdfmake.createPdf(docDefinition);
23 | pdf.write('pdfs/pdfa.pdf').then(() => {
24 | console.log(new Date() - now);
25 | }, err => {
26 | console.error(err);
27 | });
28 |
--------------------------------------------------------------------------------
/examples/pdfs/absolute.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/absolute.pdf
--------------------------------------------------------------------------------
/examples/pdfs/attachments.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/attachments.pdf
--------------------------------------------------------------------------------
/examples/pdfs/background.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/background.pdf
--------------------------------------------------------------------------------
/examples/pdfs/basics.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/basics.pdf
--------------------------------------------------------------------------------
/examples/pdfs/columns_simple.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/columns_simple.pdf
--------------------------------------------------------------------------------
/examples/pdfs/images.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/images.pdf
--------------------------------------------------------------------------------
/examples/pdfs/links.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/links.pdf
--------------------------------------------------------------------------------
/examples/pdfs/lists.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/lists.pdf
--------------------------------------------------------------------------------
/examples/pdfs/margins.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/margins.pdf
--------------------------------------------------------------------------------
/examples/pdfs/named_styles.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/named_styles.pdf
--------------------------------------------------------------------------------
/examples/pdfs/named_styles_with_overrides.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/named_styles_with_overrides.pdf
--------------------------------------------------------------------------------
/examples/pdfs/pageReference.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/pageReference.pdf
--------------------------------------------------------------------------------
/examples/pdfs/pdfa.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/pdfa.pdf
--------------------------------------------------------------------------------
/examples/pdfs/qrCode.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/qrCode.pdf
--------------------------------------------------------------------------------
/examples/pdfs/relative.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/relative.pdf
--------------------------------------------------------------------------------
/examples/pdfs/sections.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/sections.pdf
--------------------------------------------------------------------------------
/examples/pdfs/security.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/security.pdf
--------------------------------------------------------------------------------
/examples/pdfs/standardfonts.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/standardfonts.pdf
--------------------------------------------------------------------------------
/examples/pdfs/styling_inlines.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/styling_inlines.pdf
--------------------------------------------------------------------------------
/examples/pdfs/styling_properties.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/styling_properties.pdf
--------------------------------------------------------------------------------
/examples/pdfs/svgs.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/svgs.pdf
--------------------------------------------------------------------------------
/examples/pdfs/tables.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/tables.pdf
--------------------------------------------------------------------------------
/examples/pdfs/textDecorations.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/textDecorations.pdf
--------------------------------------------------------------------------------
/examples/pdfs/toc.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/toc.pdf
--------------------------------------------------------------------------------
/examples/pdfs/vectors.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/vectors.pdf
--------------------------------------------------------------------------------
/examples/pdfs/watermark.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/examples/pdfs/watermark.pdf
--------------------------------------------------------------------------------
/examples/qrCode.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var greeting = 'Can you see me';
8 | var url = 'http://pdfmake.org';
9 | var longText = 'The amount of data that can be stored in the QR code symbol depends on the datatype (mode, or input character set), version (1, …, 40, indicating the overall dimensions of the symbol), and error correction level. The maximum storage capacities occur for 40-L symbols (version 40, error correction level L):';
10 |
11 |
12 | function header(text) {
13 | return { text: text, margins: [0, 0, 0, 8] };
14 | }
15 |
16 | var docDefinition = {
17 | pageMargins: [10, 10, 10, 10],
18 | content: [
19 | header(greeting),
20 | { qr: greeting },
21 | '\n',
22 |
23 | header('Colored QR'),
24 | { qr: greeting, foreground: 'red', background: 'yellow' },
25 | '\n',
26 |
27 | header(url),
28 | { qr: url },
29 | '\n',
30 |
31 | header('A very long text (' + longText.length + ' chars)'),
32 | { qr: longText },
33 | '\n',
34 |
35 | header('same long text with fit = 100 and alignment = right'),
36 | { qr: longText, fit: 150, alignment: 'right' },
37 | '\n',
38 |
39 | header('same long text with fit = 100 and padding = 1 modules in pixel'),
40 | { qr: longText, fit: 150, padding: 1 },
41 | ]
42 | };
43 |
44 | var now = new Date();
45 |
46 | var pdf = pdfmake.createPdf(docDefinition);
47 | pdf.write('pdfs/qrCode.pdf').then(() => {
48 | console.log(new Date() - now);
49 | }, err => {
50 | console.error(err);
51 | });
52 |
--------------------------------------------------------------------------------
/examples/relative.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var left = 20;
8 | var width = 130;
9 | var top = 20;
10 | var height = 130;
11 | var yAxisWidth = 30;
12 | var xAxisHeight = 30;
13 | var tickSize = 5;
14 |
15 | var chartLines = [];
16 | var chartText = [];
17 | var chart = [{ stack: chartText }, { canvas: chartLines }];
18 |
19 | buildXAxis();
20 | buildYAxis();
21 |
22 | var docDefinition = {
23 | content: [
24 | { text: 'We sometimes don\'t know the absolute position of text', margin: [10, 0, 0, 50] },
25 | {
26 | columns: [
27 | { width: '50%', text: 'horizontal position is not known either' },
28 | { width: '50%', stack: chart }
29 | ]
30 | },
31 | { text: 'We can position relative with center and right alignment', margin: [0, 50, 0, 50] },
32 | {
33 | table: {
34 | widths: [100, 100, 100],
35 | body: [
36 | ['Column with a lot of text. Column with a lot of text. Column with a lot of text. Column with a lot of text.',
37 | {
38 | text: 'I\'m aligned center',
39 | style: {
40 | alignment: 'center',
41 | },
42 | relativePosition: {
43 | x: 0,
44 | y: 25,
45 | }
46 | },
47 | {
48 | text: 'I\'m aligned right',
49 | style: {
50 | alignment: 'right',
51 | },
52 | relativePosition: {
53 | x: 0,
54 | y: 25,
55 | }
56 | }]
57 | ]
58 | }
59 | }
60 | ]
61 | };
62 |
63 | var now = new Date();
64 |
65 | var pdf = pdfmake.createPdf(docDefinition);
66 | pdf.write('pdfs/relative.pdf').then(() => {
67 | console.log(new Date() - now);
68 | }, err => {
69 | console.error(err);
70 | });
71 |
72 | function buildXAxis() {
73 | var xTicks = [
74 | { t: '2016', x: 0, y: 0 },
75 | { t: '2017', x: 25, y: 0 },
76 | { t: '2018', x: 50, y: 0 },
77 | { t: '2019', x: 75, y: 0 },
78 | { t: '2020', x: 100, y: 0 }
79 | ];
80 |
81 | chartLines.push(horizontalLine(left + yAxisWidth - 1, top + height - xAxisHeight, width - yAxisWidth + 1));
82 |
83 | xTicks.forEach(function (tick) {
84 | chartLines.push(verticalLine(left + yAxisWidth + tick.x - 0.5, top + height - xAxisHeight, tickSize));
85 | chartText.push({ text: tick.t, fontSize: 8, relativePosition: { x: left + yAxisWidth + tick.x - 9, y: top + height - xAxisHeight + tickSize + 2 } });
86 | });
87 | }
88 |
89 | function buildYAxis() {
90 | var yTicks = [
91 | { t: '5', y: 0, x: 0 },
92 | { t: '4', y: 25, x: 0 },
93 | { t: '3', y: 50, x: 0 },
94 | { t: '2', y: 75, x: 0 },
95 | { t: '1', y: 100, x: 0 }
96 | ];
97 |
98 | chartLines.push(verticalLine(left + yAxisWidth - 0.5, top - 0.5, height - xAxisHeight));
99 |
100 | yTicks.forEach(function (tick) {
101 | chartLines.push(horizontalLine(left + yAxisWidth - tickSize - 1, top + tick.y, tickSize));
102 | chartText.push({ text: tick.t, fontSize: 8, relativePosition: { x: left + yAxisWidth - tickSize - 8, y: top + tick.y - 5 } });
103 | });
104 | }
105 |
106 | function horizontalLine(x, y, length) {
107 | return { type: 'line', x1: x, y1: y, x2: x + length, y2: y };
108 | }
109 |
110 | function verticalLine(x, y, height) {
111 | return { type: 'line', x1: x, y1: y, x2: x, y2: y + height };
112 | }
113 |
--------------------------------------------------------------------------------
/examples/sections.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var docDefinition = {
8 | header: function () { return 'default header'; },
9 | footer: function () { return 'default footer'; },
10 | background: function() { return { text:'global background', alignment: 'right' }; },
11 | watermark: 'default watermark',
12 | content: [
13 | {
14 | section: [
15 | 'SECTION 1',
16 | 'Text in section.'
17 | ]
18 | },
19 | {
20 | header: function (currentPage, pageCount) { return 'header: ' + currentPage.toString() + ' of ' + pageCount; },
21 | footer: function (currentPage, pageCount) { return 'footer: ' + currentPage.toString() + ' of ' + pageCount; },
22 | background: function() { return { text:'SECTION 2 background', alignment: 'right' }; },
23 | watermark: 'SECTION 2 watermark',
24 | pageOrientation: 'landscape',
25 | section: [
26 | 'SECTION 2',
27 | 'Text in section as landscape page.'
28 | ]
29 | },
30 | {
31 | header: null,
32 | footer: null,
33 | background: null,
34 | watermark: null,
35 | pageSize: 'A7',
36 | pageOrientation: 'portrait',
37 | section: [
38 | 'SECTION 3',
39 | 'Text in section as A7 page.'
40 | ]
41 | },
42 | {
43 | watermark: 'inherit',
44 | pageSize: 'A6',
45 | pageOrientation: 'portrait',
46 | pageMargins: 5,
47 | section: [
48 | 'SECTION 4',
49 | 'Text in section as A6 page with margin.'
50 | ]
51 | },
52 | {
53 | watermark: 'watermark for inherit',
54 | pageSize: 'A6',
55 | pageOrientation: 'landscape',
56 | pageMargins: 10,
57 | section: [
58 | 'SECTION 5',
59 | 'Text in section as A6 landscape page with margin.'
60 | ]
61 | },
62 | {
63 | watermark: 'inherit',
64 | pageSize: 'inherit',
65 | pageOrientation: 'inherit',
66 | pageMargins: 'inherit',
67 | section: [
68 | 'SECTION 6',
69 | 'Text in section with page definition as previous page. Page size, orientation and margins are inherited.'
70 | ]
71 | },
72 | {
73 | header: function (currentPage, pageCount) { return 'header in section 8: ' + currentPage.toString() + ' of ' + pageCount; },
74 | footer: function (currentPage, pageCount) { return 'footer in section 8: ' + currentPage.toString() + ' of ' + pageCount; },
75 | section: [
76 | 'SECTION 7',
77 | 'Text in section with page definition as defined in document.'
78 | ]
79 | }
80 | ]
81 | };
82 |
83 | var now = new Date();
84 |
85 | var pdf = pdfmake.createPdf(docDefinition);
86 | pdf.write('pdfs/sections.pdf').then(() => {
87 | console.log(new Date() - now);
88 | }, err => {
89 | console.error(err);
90 | });
91 |
--------------------------------------------------------------------------------
/examples/security.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var docDefinition = {
8 | //userPassword: '123',
9 | ownerPassword: '123456',
10 | permissions: {
11 | printing: 'highResolution', //'lowResolution'
12 | modifying: false,
13 | copying: false,
14 | annotating: true,
15 | fillingForms: true,
16 | contentAccessibility: true,
17 | documentAssembly: true
18 | },
19 | content: [
20 | 'Document content with security',
21 | 'For details see to source or documentation.'
22 | ]
23 | };
24 |
25 | var now = new Date();
26 |
27 | var pdf = pdfmake.createPdf(docDefinition);
28 | pdf.write('pdfs/security.pdf').then(() => {
29 | console.log(new Date() - now);
30 | }, err => {
31 | console.error(err);
32 | });
33 |
--------------------------------------------------------------------------------
/examples/standardfonts.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Courier = require('../standard-fonts/Courier');
5 | pdfmake.addFonts(Courier);
6 |
7 | var Helvetica = require('../standard-fonts/Helvetica');
8 | pdfmake.addFonts(Helvetica);
9 |
10 | var Times = require('../standard-fonts/Times');
11 | pdfmake.addFonts(Times);
12 |
13 | //var Symbol = require('../standard-fonts/Symbol');
14 | //pdfmake.addFonts(Symbol);
15 |
16 | //var ZapfDingbats = require('../standard-fonts/ZapfDingbats');
17 | //pdfmake.addFonts(ZapfDingbats);
18 |
19 |
20 | var docDefinition = {
21 | content: [
22 | { text: 'Standard fonts supports only ANSI code page (only english characters)!', bold: true },
23 | ' ',
24 | { text: 'Courier font', font: 'Courier' },
25 | { text: 'Helvetica font', font: 'Helvetica' },
26 | { text: 'Times font', font: 'Times' },
27 | //{ text: 'Symbol font', font: 'Symbol' },
28 | //{ text: 'ZapfDingbats font', font: 'ZapfDingbats' },
29 |
30 | ],
31 | defaultStyle: {
32 | font: 'Helvetica'
33 | },
34 | language: "en-AU"
35 | };
36 |
37 | var now = new Date();
38 |
39 | var pdf = pdfmake.createPdf(docDefinition);
40 | pdf.write('pdfs/standardfonts.pdf').then(() => {
41 | console.log(new Date() - now);
42 | }, err => {
43 | console.error(err);
44 | });
45 |
--------------------------------------------------------------------------------
/examples/styling_inlines.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var docDefinition = {
8 | content: [
9 | {
10 | text: 'This is a header (whole paragraph uses the same header style)\n\n',
11 | style: 'header'
12 | },
13 | {
14 | text: [
15 | 'It is however possible to provide an array of texts ',
16 | 'to the paragraph (instead of a single string) and have ',
17 | { text: 'a better ', fontSize: 15, bold: true },
18 | 'control over it. \nEach inline can be ',
19 | { text: 'styled ', fontSize: 20 },
20 | { text: 'independently ', italics: true, fontSize: 40 },
21 | 'then.\n\n'
22 | ]
23 | },
24 | { text: 'Mixing named styles and style-overrides', style: 'header' },
25 | {
26 | style: 'bigger',
27 | italics: false,
28 | text: [
29 | 'We can also mix named-styles and style-overrides at both paragraph and inline level. ',
30 | 'For example, this paragraph uses the "bigger" style, which changes fontSize to 15 and sets italics to true. ',
31 | 'Texts are not italics though. It\'s because we\'ve overriden italics back to false at ',
32 | 'the paragraph level. \n\n',
33 | 'We can also change the style of a single inline. Let\'s use a named style called header: ',
34 | { text: 'like here.\n', style: 'header' },
35 | 'It got bigger and bold.\n\n',
36 | 'OK, now we\'re going to mix named styles and style-overrides at the inline level. ',
37 | 'We\'ll use header style (it makes texts bigger and bold), but we\'ll override ',
38 | 'bold back to false: ',
39 | { text: 'wow! it works!', style: 'header', bold: false },
40 | '\n\nMake sure to take a look into the sources to understand what\'s going on here.'
41 | ]
42 | }
43 | ],
44 | styles: {
45 | header: {
46 | fontSize: 18,
47 | bold: true
48 | },
49 | bigger: {
50 | fontSize: 15,
51 | italics: true
52 | }
53 | }
54 | };
55 |
56 | var now = new Date();
57 |
58 | var pdf = pdfmake.createPdf(docDefinition);
59 | pdf.write('pdfs/styling_inlines.pdf').then(() => {
60 | console.log(new Date() - now);
61 | }, err => {
62 | console.error(err);
63 | });
64 |
--------------------------------------------------------------------------------
/examples/styling_named_styles.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 | var docDefinition = {
8 | content: [
9 | {
10 | text: 'This is a header, using header style',
11 | style: 'header'
12 | },
13 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.\n\n',
14 | {
15 | text: 'Subheader 1 - using subheader style',
16 | style: 'subheader'
17 | },
18 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
19 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
20 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n',
21 | {
22 | text: 'Subheader 2 - using subheader style',
23 | style: 'subheader'
24 | },
25 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
26 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n',
27 | {
28 | text: 'It is possible to apply multiple styles, by passing an array. This paragraph uses two styles: quote and small. When multiple styles are provided, they are evaluated in the specified order which is important in case they define the same properties',
29 | style: ['quote', 'small']
30 | }
31 | ],
32 | styles: {
33 | header: {
34 | fontSize: 18,
35 | bold: true
36 | },
37 | subheader: {
38 | fontSize: 15,
39 | bold: true
40 | },
41 | quote: {
42 | italics: true
43 | },
44 | small: {
45 | fontSize: 8
46 | }
47 | }
48 | };
49 |
50 | var now = new Date();
51 |
52 | var pdf = pdfmake.createPdf(docDefinition);
53 | pdf.write('pdfs/named_styles.pdf').then(() => {
54 | console.log(new Date() - now);
55 | }, err => {
56 | console.error(err);
57 | });
58 |
--------------------------------------------------------------------------------
/examples/styling_named_styles_with_overrides.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 |
8 | var docDefinition = {
9 | content: [
10 | {
11 | text: 'This paragraph uses header style and extends the alignment property',
12 | style: 'header',
13 | alignment: 'center'
14 | },
15 | {
16 | text: [
17 | 'This paragraph uses header style and overrides bold value setting it back to false.\n',
18 | 'Header style in this example sets alignment to justify, so this paragraph should be rendered \n',
19 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.'
20 | ],
21 | style: 'header',
22 | bold: false
23 | }
24 | ],
25 | styles: {
26 | header: {
27 | fontSize: 18,
28 | bold: true,
29 | alignment: 'justify'
30 | }
31 | },
32 | };
33 |
34 | var now = new Date();
35 |
36 | var pdf = pdfmake.createPdf(docDefinition);
37 | pdf.write('pdfs/named_styles_with_overrides.pdf').then(() => {
38 | console.log(new Date() - now);
39 | }, err => {
40 | console.error(err);
41 | });
42 |
--------------------------------------------------------------------------------
/examples/styling_properties.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 |
8 | var docDefinition = {
9 | content: [
10 | {
11 | text: 'Paragraphs can also by styled without using named-styles (this one sets fontSize to 25)',
12 | fontSize: 25
13 | },
14 | 'Another paragraph, using default style, this time a little bit longer to make sure, this line will be divided into at least two lines\n\n',
15 | {
16 | text: 'This paragraph does not use a named-style and sets fontSize to 8 and italics to true',
17 | fontSize: 8,
18 | italics: true
19 | },
20 | '\n\nFor preserving leading spaces use preserveLeadingSpaces property:',
21 | { text: ' This is a paragraph with preserved leading spaces.', preserveLeadingSpaces: true },
22 | { text: '{', preserveLeadingSpaces: true },
23 | { text: ' "sample": {', preserveLeadingSpaces: true },
24 | { text: ' "json": "nested"', preserveLeadingSpaces: true },
25 | { text: ' }', preserveLeadingSpaces: true },
26 | { text: '}', preserveLeadingSpaces: true },
27 | '\n\nfontFeatures property:',
28 | { text: 'Hello World 1234567890', fontFeatures: ['smcp'] },
29 | { text: 'Hello World 1234567890', fontFeatures: ['c2sc'] },
30 | { text: 'Hello World 1234567890', fontFeatures: ['onum'] },
31 | { text: 'Hello World 1234567890', fontFeatures: ['onum', 'c2sc'] },
32 | '\n\nText opacity:',
33 | { text: 'Hello World', opacity: 0.8 },
34 | { text: 'Hello World', opacity: 0.6 },
35 | { text: 'Hello World', opacity: 0.4 },
36 | { text: 'Hello World', opacity: 0.2 },
37 | { text: 'Hello World', opacity: 0.1 },
38 | '\n\n Subscript, superscript:',
39 | {
40 | text: [
41 | 'Hello World.',
42 | {
43 | text: '1, 2',
44 | sup: true,
45 | },
46 | ' Let\'s continue our sentence. Notice the leading space.'
47 | ]
48 | },
49 | {
50 | text: [
51 | 'Hello',
52 | {
53 | text: '1, 2',
54 | sub: true,
55 | },
56 | ' World'
57 | ]
58 | },
59 | '\n\n',
60 | {
61 | text: 'Text background pattern', background: ['stripe45d', 'gray']
62 | }
63 | ],
64 | patterns: {
65 | stripe45d: {
66 | boundingBox: [1, 1, 4, 4],
67 | xStep: 3,
68 | yStep: 3,
69 | pattern: '1 w 0 1 m 4 5 l s 2 0 m 5 3 l s'
70 | }
71 | }
72 | };
73 |
74 | var now = new Date();
75 |
76 | var pdf = pdfmake.createPdf(docDefinition);
77 | pdf.write('pdfs/styling_properties.pdf').then(() => {
78 | console.log(new Date() - now);
79 | }, err => {
80 | console.error(err);
81 | });
82 |
--------------------------------------------------------------------------------
/examples/textDecorations.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 |
8 | var ct = [];
9 |
10 | ct.push({ text: 'Higlighted text', fontSize: 18, background: 'yellow' });
11 | ct.push(' ');
12 | ct.push({
13 | columns: [
14 | { text: 'Underline decoration', decoration: 'underline' },
15 | { text: 'Line Through decoration', decoration: 'lineThrough' },
16 | { text: 'Overline decoration', decoration: 'overline' }
17 | ]
18 | });
19 | ct.push(' ');
20 | ct.push({
21 | columns: [
22 | { text: 'Dashed style', decoration: 'underline', decorationStyle: 'dashed' },
23 | { text: 'Dotted style', decoration: 'underline', decorationStyle: 'dotted' },
24 | { text: 'Double style', decoration: 'underline', decorationStyle: 'double' },
25 | { text: 'Wavy style', decoration: 'underline', decorationStyle: 'wavy' }
26 | ]
27 | });
28 | ct.push(' ');
29 | ct.push({
30 | columns: [
31 | { text: 'Using colors', decoration: 'underline', decorationColor: 'blue' },
32 | { text: 'Using colors', decoration: 'lineThrough', decorationColor: 'red' },
33 | { text: 'Using colors', decoration: 'underline', decorationStyle: 'wavy', decorationColor: 'green' }
34 | ]
35 | });
36 |
37 |
38 |
39 | var docDefinition = {
40 | content: ct
41 | };
42 |
43 | var now = new Date();
44 |
45 | var pdf = pdfmake.createPdf(docDefinition);
46 | pdf.write('pdfs/textDecorations.pdf').then(() => {
47 | console.log(new Date() - now);
48 | }, err => {
49 | console.error(err);
50 | });
51 |
--------------------------------------------------------------------------------
/examples/toc.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 |
8 | var docDefinition = {
9 | content: [
10 | {
11 | text: 'This is a TOC example. Text elements marked with tocItem: true will be located in the toc. See below.',
12 | pageBreak: 'after'
13 | },
14 | {
15 | toc: {
16 | title: { text: 'INDEX', style: 'header' },
17 | //textMargin: [0, 0, 0, 0],
18 | //textStyle: {italics: true},
19 | numberStyle: { bold: true }
20 | }
21 | },
22 | {
23 | text: 'This is a header, using header style',
24 | style: 'header',
25 | tocItem: true,
26 | tocStyle: { italics: true },
27 | tocMargin: [0, 10, 0, 0],
28 | tocNumberStyle: { italics: true, decoration: 'underline' },
29 | pageBreak: 'before'
30 | },
31 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.\n\n',
32 | {
33 | text: 'Subheader 1 - using subheader style',
34 | style: 'subheader',
35 | tocItem: true,
36 | pageBreak: 'before'
37 | },
38 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
39 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
40 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n',
41 | {
42 | text: 'Subheader 2 - using subheader style',
43 | style: 'subheader',
44 | tocItem: true,
45 | pageBreak: 'before'
46 | },
47 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.',
48 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n',
49 | {
50 | text: 'It is possible to apply multiple styles, by passing an array. This paragraph uses two styles: quote and small. When multiple styles are provided, they are evaluated in the specified order which is important in case they define the same properties',
51 | style: ['quote', 'small']
52 | },
53 | {
54 | text: [
55 | {
56 | text: 'Subheader 3 - using inline text',
57 | style: 'subheader',
58 | tocItem: true
59 | },
60 | {
61 | text: '; and this text not be displayed in ToC',
62 | italics: true
63 | }
64 | ],
65 | pageBreak: 'before'
66 | },
67 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.'
68 | ],
69 | styles: {
70 | header: {
71 | fontSize: 18,
72 | bold: true
73 | },
74 | subheader: {
75 | fontSize: 15,
76 | bold: true
77 | },
78 | quote: {
79 | italics: true
80 | },
81 | small: {
82 | fontSize: 8
83 | }
84 | }
85 | };
86 |
87 | var now = new Date();
88 |
89 | var pdf = pdfmake.createPdf(docDefinition);
90 | pdf.write('pdfs/toc.pdf').then(() => {
91 | console.log(new Date() - now);
92 | }, err => {
93 | console.error(err);
94 | });
95 |
--------------------------------------------------------------------------------
/examples/vectors.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 |
8 | var docDefinition = {
9 | content: [
10 | {
11 | text: [
12 | 'This ',
13 | { text: 'is', color: 'green' },
14 | ' the first ',
15 | { text: 'paragraph', color: 'red' }
16 | ]
17 | },
18 | {
19 | canvas: [
20 | {
21 | type: 'rect',
22 | x: 0,
23 | y: 0,
24 | w: 310,
25 | h: 290,
26 | r: 5,
27 | dash: { length: 5 },
28 | // lineWidth: 10,
29 | lineColor: 'blue',
30 | },
31 | {
32 | type: 'rect',
33 | x: 1,
34 | y: 1,
35 | w: 308,
36 | h: 288,
37 | r: 4,
38 | lineColor: 'red',
39 | color: '#ffffe0',
40 | },
41 | {
42 | type: 'polyline',
43 | lineWidth: 3,
44 | closePath: true,
45 | points: [{ x: 10, y: 10 }, { x: 35, y: 40 }, { x: 100, y: 40 }, { x: 125, y: 10 }]
46 | },
47 | {
48 | type: 'polyline',
49 | lineWidth: 2,
50 | color: 'blue',
51 | lineColor: 'red',
52 | points: [{ x: 10, y: 110 }, { x: 35, y: 140 }, { x: 100, y: 140 }, { x: 125, y: 110 }, { x: 10, y: 110 }]
53 | },
54 | {
55 | type: 'line',
56 | x1: 40, y1: 60,
57 | x2: 260, y2: 60,
58 | lineWidth: 3
59 | },
60 | {
61 | type: 'line',
62 | x1: 40, y1: 80,
63 | x2: 260, y2: 80,
64 | lineWidth: 10,
65 | lineCap: 'round'
66 | },
67 | {
68 | type: 'line',
69 | x1: 40, y1: 100,
70 | x2: 260, y2: 100,
71 | lineWidth: 10,
72 | lineCap: 'square'
73 | },
74 | {
75 | type: 'ellipse',
76 | x: 150, y: 140,
77 | color: 'red',
78 | fillOpacity: 0.5,
79 | r1: 80, r2: 60
80 | },
81 | {
82 | type: 'rect',
83 | x: 150,
84 | y: 200,
85 | w: 150,
86 | h: 50,
87 | },
88 | {
89 | type: 'rect',
90 | x: 10, y: 200, w: 100, h: 10,
91 | linearGradient: ['red', 'blue']
92 | },
93 | {
94 | type: 'rect',
95 | x: 10, y: 215, w: 100, h: 10,
96 | linearGradient: ['red', 'green', 'blue']
97 | },
98 | {
99 | type: 'rect',
100 | x: 10, y: 230, w: 100, h: 10,
101 | linearGradient: ['red', 'yellow', 'green', 'blue']
102 | },
103 | {
104 | type: 'ellipse',
105 | x: 260, y: 140,
106 | r1: 30, r2: 20,
107 | linearGradient: ['red', 'green', 'blue', 'red'],
108 | },
109 | {
110 | type: 'rect',
111 | x: 10, y: 250, w: 50, h: 30,
112 | color: ['stripe45d', 'blue'],
113 | }
114 | ]
115 | },
116 | 'This text should be rendered under canvas',
117 | {
118 | color: 'black',
119 |
120 | text: [
121 | 'This should be black ',
122 | ]
123 | }
124 | ],
125 | defaultStyle: {
126 | color: 'gray',
127 | },
128 | patterns: {
129 | stripe45d: {
130 | boundingBox: [1, 1, 4, 4],
131 | xStep: 3,
132 | yStep: 3,
133 | pattern: '1 w 0 1 m 4 5 l s 2 0 m 5 3 l s'
134 | }
135 | }
136 | };
137 |
138 | var now = new Date();
139 |
140 | var pdf = pdfmake.createPdf(docDefinition);
141 | pdf.write('pdfs/vectors.pdf').then(() => {
142 | console.log(new Date() - now);
143 | }, err => {
144 | console.error(err);
145 | });
146 |
--------------------------------------------------------------------------------
/examples/watermark.js:
--------------------------------------------------------------------------------
1 | var pdfmake = require('../js/index'); // only during development, otherwise use the following line
2 | //var pdfmake = require('pdfmake');
3 |
4 | var Roboto = require('../fonts/Roboto');
5 | pdfmake.addFonts(Roboto);
6 |
7 |
8 | var lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec id semper massa, nec dapibus mauris. Mauris in mattis nibh. Aenean feugiat volutpat aliquam. Donec sed tellus feugiat, dignissim lectus id, eleifend tortor. Ut at mauris vel dui euismod accumsan. Cras sodales, ante sit amet varius dapibus, dolor neque finibus justo, vel ornare arcu dolor vitae tellus. Aenean faucibus egestas urna in interdum. Mauris convallis dolor a condimentum sagittis. Suspendisse non laoreet nisl. Curabitur sed pharetra ipsum. Curabitur aliquet purus vitae pharetra tincidunt. Cras aliquam tempor justo sit amet euismod. Praesent risus magna, lobortis eget dictum sit amet, tristique vel enim. Duis aliquet, urna maximus sollicitudin lobortis, mi nunc dignissim ligula, et lacinia magna leo non sem.';
9 |
10 | var docDefinition = {
11 | //watermark: 'test watermark',
12 | watermark: { text: 'test watermark', color: 'blue', opacity: 0.3, bold: true, italics: false },
13 | content: [
14 | 'Test page of watermark.\n\n',
15 | lorem
16 | ]
17 | };
18 |
19 | var now = new Date();
20 |
21 | var pdf = pdfmake.createPdf(docDefinition);
22 | pdf.write('pdfs/watermark.pdf').then(() => {
23 | console.log(new Date() - now);
24 | }, err => {
25 | console.error(err);
26 | });
27 |
--------------------------------------------------------------------------------
/fonts/Roboto.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | Roboto: {
3 | normal: __dirname + '/Roboto/Roboto-Regular.ttf',
4 | bold: __dirname + '/Roboto/Roboto-Medium.ttf',
5 | italics: __dirname + '/Roboto/Roboto-Italic.ttf',
6 | bolditalics: __dirname + '/Roboto/Roboto-MediumItalic.ttf'
7 | }
8 | };
9 |
--------------------------------------------------------------------------------
/fonts/Roboto/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/fonts/Roboto/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/fonts/Roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/fonts/Roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/fonts/Roboto/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/fonts/Roboto/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/fonts/Roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bpampuch/pdfmake/4395ebdb4e1ec52a60af8fbc52a758c9939fba97/fonts/Roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pdfmake",
3 | "version": "0.3.0-beta.18",
4 | "description": "Client/server side PDF printing in pure JavaScript",
5 | "main": "js/index.js",
6 | "esnext": "src/index.js",
7 | "browser": "build/pdfmake.js",
8 | "directories": {
9 | "test": "tests"
10 | },
11 | "dependencies": {
12 | "linebreak": "^1.1.0",
13 | "pdfkit": "^0.17.1",
14 | "xmldoc": "^2.0.1"
15 | },
16 | "devDependencies": {
17 | "@babel/cli": "^7.27.2",
18 | "@babel/core": "^7.27.1",
19 | "@babel/plugin-transform-modules-commonjs": "^7.27.1",
20 | "@babel/preset-env": "^7.27.2",
21 | "@eslint/js": "^9.26.0",
22 | "assert": "^2.1.0",
23 | "babel-loader": "^10.0.0",
24 | "brfs": "^2.0.2",
25 | "browserify-zlib": "^0.2.0",
26 | "buffer": "^6.0.3",
27 | "core-js": "^3.42.0",
28 | "eslint": "^9.26.0",
29 | "eslint-plugin-jsdoc": "^50.6.11",
30 | "expose-loader": "^5.0.1",
31 | "file-saver": "^2.0.5",
32 | "globals": "^16.1.0",
33 | "mocha": "^11.2.2",
34 | "npm-run-all": "^4.1.5",
35 | "process": "^0.11.10",
36 | "rewire": "^7.0.0",
37 | "shx": "^0.4.0",
38 | "sinon": "^20.0.0",
39 | "source-map-loader": "^5.0.0",
40 | "stream-browserify": "^3.0.0",
41 | "string-replace-webpack-plugin": "^0.1.3",
42 | "svg-to-pdfkit": "^0.1.8",
43 | "terser-webpack-plugin": "^5.3.14",
44 | "transform-loader": "^0.2.4",
45 | "util": "^0.12.5",
46 | "webpack": "^5.99.8",
47 | "webpack-cli": "^6.0.1"
48 | },
49 | "engines": {
50 | "node": ">=18"
51 | },
52 | "scripts": {
53 | "test": "run-s build mocha lint",
54 | "build": "run-s build:clean build:3rdparty build:node build:browser build:standard-fonts build:fonts build:vfs",
55 | "build:clean": "shx rm -rf js build",
56 | "build:3rdparty": "shx cp node_modules/svg-to-pdfkit/source.js src/3rd-party/svg-to-pdfkit/source.js && shx cp node_modules/svg-to-pdfkit/LICENSE src/3rd-party/svg-to-pdfkit/LICENSE",
57 | "build:node": "babel src --out-dir js",
58 | "build:browser": "webpack",
59 | "build:vfs": "node build-vfs.js \"./examples/fonts\"",
60 | "build:examples": "node build-examples.js",
61 | "build:standard-fonts": "shx mkdir -p build/standard-fonts && brfs \"./src/browser-extensions/standard-fonts/Courier.js\" > build/standard-fonts/Courier.js && brfs \"./src/browser-extensions/standard-fonts/Helvetica.js\" > build/standard-fonts/Helvetica.js && brfs \"./src/browser-extensions/standard-fonts/Times.js\" > build/standard-fonts/Times.js && brfs \"./src/browser-extensions/standard-fonts/Symbol.js\" > build/standard-fonts/Symbol.js && brfs \"./src/browser-extensions/standard-fonts/ZapfDingbats.js\" > build/standard-fonts/ZapfDingbats.js",
62 | "build:fonts": "shx mkdir -p build/fonts && shx mkdir -p build/fonts/Roboto && shx cp -r fonts/Roboto/*.* build/fonts/Roboto && brfs \"./src/browser-extensions/fonts/Roboto.js\" > build/fonts/Roboto.js",
63 | "lint": "eslint \"./src/**/*.js\" \"./tests/**/*.js\" \"./examples/**/*.js\" \"./standard-fonts/**/*.js\" \"./fonts/**/*.js\"",
64 | "mocha": "mocha --reporter spec \"./tests/**/*.spec.js\"",
65 | "playground": "node dev-playground/server.js"
66 | },
67 | "repository": {
68 | "type": "git",
69 | "url": "git://github.com/bpampuch/pdfmake.git"
70 | },
71 | "keywords": [
72 | "pdf",
73 | "javascript",
74 | "printing",
75 | "layout"
76 | ],
77 | "author": "Bartek Pampuch ",
78 | "license": "MIT",
79 | "bugs": {
80 | "url": "https://github.com/bpampuch/pdfmake/issues"
81 | },
82 | "homepage": "http://pdfmake.org",
83 | "config": {
84 | "blanket": {
85 | "pattern": "src",
86 | "data-cover-never": [
87 | "node_modules",
88 | "tests"
89 | ]
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/3rd-party/svg-to-pdfkit.js:
--------------------------------------------------------------------------------
1 | import SVGtoPDF from './svg-to-pdfkit/source.js';
2 |
3 | export default SVGtoPDF;
4 |
--------------------------------------------------------------------------------
/src/3rd-party/svg-to-pdfkit/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019 SVG-to-PDFKit contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/src/Line.js:
--------------------------------------------------------------------------------
1 | class Line {
2 | /**
3 | * @param {number} maxWidth Maximum width this line can have
4 | */
5 | constructor(maxWidth) {
6 | this.maxWidth = maxWidth;
7 | this.leadingCut = 0;
8 | this.trailingCut = 0;
9 | this.inlineWidths = 0;
10 | this.inlines = [];
11 | }
12 |
13 | /**
14 | * @param {object} inline
15 | */
16 | addInline(inline) {
17 | if (this.inlines.length === 0) {
18 | this.leadingCut = inline.leadingCut || 0;
19 | }
20 | this.trailingCut = inline.trailingCut || 0;
21 |
22 | inline.x = this.inlineWidths - this.leadingCut;
23 |
24 | this.inlines.push(inline);
25 | this.inlineWidths += inline.width;
26 |
27 | if (inline.lineEnd) {
28 | this.newLineForced = true;
29 | }
30 | }
31 |
32 | /**
33 | * @returns {number}
34 | */
35 | getHeight() {
36 | let max = 0;
37 |
38 | this.inlines.forEach(item => {
39 | max = Math.max(max, item.height || 0);
40 | });
41 |
42 | return max;
43 | }
44 |
45 | /**
46 | * @returns {number}
47 | */
48 | getAscenderHeight() {
49 | let y = 0;
50 |
51 | this.inlines.forEach(inline => {
52 | y = Math.max(y, inline.font.ascender / 1000 * inline.fontSize);
53 | });
54 |
55 | return y;
56 | }
57 |
58 | /**
59 | * @returns {number}
60 | */
61 | getWidth() {
62 | return this.inlineWidths - this.leadingCut - this.trailingCut;
63 | }
64 |
65 | /**
66 | * @returns {number}
67 | */
68 | getAvailableWidth() {
69 | return this.maxWidth - this.getWidth();
70 | }
71 |
72 | /**
73 | * @param {object} inline
74 | * @param {Array} nextInlines
75 | * @returns {boolean}
76 | */
77 | hasEnoughSpaceForInline(inline, nextInlines = []) {
78 | if (this.inlines.length === 0) {
79 | return true;
80 | }
81 | if (this.newLineForced) {
82 | return false;
83 | }
84 |
85 | let inlineWidth = inline.width;
86 | let inlineTrailingCut = inline.trailingCut || 0;
87 | if (inline.noNewLine) {
88 | for (let i = 0, l = nextInlines.length; i < l; i++) {
89 | let nextInline = nextInlines[i];
90 | inlineWidth += nextInline.width;
91 | inlineTrailingCut += nextInline.trailingCut || 0;
92 | if (!nextInline.noNewLine) {
93 | break;
94 | }
95 | }
96 | }
97 |
98 | return (this.inlineWidths + inlineWidth - this.leadingCut - inlineTrailingCut) <= this.maxWidth;
99 | }
100 |
101 | clone() {
102 | let result = new Line(this.maxWidth);
103 |
104 | for (let key in this) {
105 | if (this.hasOwnProperty(key)) {
106 | result[key] = this[key];
107 | }
108 | }
109 |
110 | return result;
111 | }
112 | }
113 |
114 | export default Line;
115 |
--------------------------------------------------------------------------------
/src/OutputDocument.js:
--------------------------------------------------------------------------------
1 | class OutputDocument {
2 |
3 | /**
4 | * @param {Promise