Skip to content

Commit

Permalink
Merge branch 'master' into bump-deps
Browse files Browse the repository at this point in the history
  • Loading branch information
liborm85 committed Nov 27, 2024
2 parents 3757918 + 4bad866 commit 224b137
Show file tree
Hide file tree
Showing 110 changed files with 5,029 additions and 3,850 deletions.
6 changes: 3 additions & 3 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{
"modules": false,
"targets": {
"node": "6.10"
"node": "18"
}
}
]
Expand All @@ -17,11 +17,11 @@
"@babel/preset-env",
{
"targets": {
"node": "6.10"
"node": "18"
}
}
]
]
}
}
}
}
25 changes: 12 additions & 13 deletions .github/workflows/lint-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,22 @@ on: [push, pull_request]

jobs:
build:

runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
node-version: [14.x, 16.x]
node-version: [18.x, 20.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Run ESLint
run: npm run lint
- name: Run tests
run: npm test
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Run ESLint
run: npm run lint
- name: Run tests
run: npm test
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
## pdfkit changelog

### Unreleased
### [v0.15.1] - 2024-10-30

- Fix browserify transform sRGB_IEC61966_2_1.icc file
- Fix time comparison check equality embedded files

### [v0.15.0] - 2024-03-23

- Add subset for PDF/UA
- Fix for line breaks in list items (#1486)
- Fix for soft hyphen not being replaced by visible hyphen if necessary (#457)
- Optimize output files by ignoring identity transforms
- Fix for Acroforms - setting an option to false will still apply the flag (#1495)
- Fix for text extraction in PDFium-based viewers due to invalid ToUnicodeMap (#1498)
- Remove deprecated `write` method
- Drop support for Node.js < 18 and for browsers released before 2020

### [v0.14.0] - 2023-11-09

- Add support for PDF/A-1b, PDF/A-1a, PDF/A-2b, PDF/A-2a, PDF/A-3b, PDF/A-3a
- Update crypto-js to v4.2.0 (properly fix security issue)

- Add support for EXIF orientation on JPEG images (#626 and #1353)

### [v0.13.0] - 2021-10-24

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Installation uses the [npm](http://npmjs.org/) package manager. Just type the fo
- Transformations
- Linear and radial gradients
- Text
- Line wrapping
- Line wrapping (with soft hyphen recognition)
- Text alignments
- Bulleted lists
- Font embedding
Expand Down Expand Up @@ -129,7 +129,7 @@ complex documents with a very small amount of code. For more, see the `demo` fol
There are three ways to use PDFKit in the browser:

- Use [Browserify](http://browserify.org/). See demo [source code](demo/browser.js) and [build script](https://github.com/foliojs/pdfkit/blob/master/package.json#L56)
- Use [webpack](https://webpack.js.org/). See [complete example](https://github.com/blikblum/pdfkit-webpack-example).
- Use [webpack](https://webpack.js.org/). See [complete example](examples/webpack).
- Use prebuilt version. Distributed as `pdfkit.standalone.js` file in the [releases](https://github.com/foliojs/pdfkit/releases) or in the package `js` folder.

In addition to PDFKit, you'll need somewhere to stream the output to. HTML5 has a
Expand Down
2 changes: 2 additions & 0 deletions docs/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Universal Accessibility) document (which is an extension of Tagged PDF):
* Pass the option `pdfVersion: '1.5'` (or a higher version) when creating your `PDFDocument`
(depending on the features you use, you may only need 1.4; refer to the PDF reference for
details).
* Pass the option `subset: 'PDF/UA'` when creating your `PDFDocument` (if you wish the PDF to
be identified as PDF/UA-1).
* Pass the option `tagged: true` when creating your `PDFDocument` (technically, this sets the
`Marked` property in the `Markings` dictionary to `true` in the PDF).
* Provide a `Title` in the `info` option, and pass `displayTitle: true` when creating your
Expand Down
32 changes: 31 additions & 1 deletion docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ in your JavaScript source file and create an instance of the
`PDFDocument` class.

const PDFDocument = require('pdfkit');
const doc = new PDFDocument;
const doc = new PDFDocument();

`PDFDocument` instances are readable Node streams. They don't get saved anywhere automatically,
but you can call the `pipe` method to send the output of the PDF document to another
Expand Down Expand Up @@ -259,6 +259,36 @@ Available options includes:
When using PDF version 1.7 ExtensionLevel 3, password is truncated to 127 bytes of its UTF-8 representation.
In older versions, password is truncated to 32 bytes, and only Latin-1 characters are allowed.

## PDF/A

PDF/A is a standard (ISO 19005-1:2005) which defines rules for electornic documents intended for long-term archiving.
The restrictions on PDF/A documents are:

- Cannot be encrypted
- Fonts must be embedded
- No JavaScript
- No audio content
- No video content
- Addition of XMP metadata
- Must define color spaces

Currently, PDFKit aims to support PDF/A-1b, PDF/A-2b, PDF/A-3b and PDF/A-1a, PDF/A-2a, PDF/A-3a standards, also known as level B conformance and level A conformance, respectively.

In order to create PDF/A documents, set `subset` to either `PDF/A-1` or `PDF/A-1b` for level B (basic) conformance, or `PDF/A-1a` for level A (accessible) conformance when creating the `PDFDocument` in `options` object.

Similary, use `PDF/A-2` or `PDF/A-2b` for PDF/A-2 level B conformance and `PDF/A-2a` for PDF/A-2 level A conformance. `PDF/A-3` or `PDF/A-3b` can be used for PDF/A-3 level B conformance and `PDF/A-3a` for PDF/A-3 level A conformance.

Futhermore, you will need to specify the other options relevant to the PDF/A subset you wish to use, for PDF/A-1 being:

- `pdfVersion` set to at least `1.4`
- `tagged` set to `true` for PDF/A-1a

For PDF/A-2 and PDF/A-3, the `pdfVersion` needs to be set to at least `1.7` and `tagged` needs to be `true` for level A conformance.

In order to verify the generated document for PDF/A and its subsets conformance, veraPDF is an excellent open source validator.

Please note that PDF/A requires fonts to be embedded, as such the standard fonts PDFKit comes with cannot be used because they are in AFM format, which only provides neccessary metrics, without the font data. You should use `registerFont()` and use embeddable fonts such as `ttf`.

### Adding content

Once you've created a `PDFDocument` instance, you can add content to the
Expand Down
29 changes: 15 additions & 14 deletions docs/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@ rendered at the current point in the text flow (below the last line of text).
Otherwise, it is positioned absolutely at the specified point. The image will
be scaled according to the following options.

* Neither `width` or `height` provided - image is rendered at full size
* `width` provided but not `height` - image is scaled proportionally to fit in the provided `width`
* `height` provided but not `width` - image is scaled proportionally to fit in the provided `height`
* Both `width` and `height` provided - image is stretched to the dimensions provided
* `scale` factor provided - image is scaled proportionally by the provided scale factor
* `fit` array provided - image is scaled proportionally to fit within the passed width and height
* `cover` array provided - image is scaled proportionally to completely cover the rectangle defined by the passed width and height
* `link` - a URL to link this image to (shortcut to create an annotation)
* `goTo` - go to anchor (shortcut to create an annotation)
* `destination` - create anchor to this image
- Neither `width` or `height` provided - image is rendered at full size
- `width` provided but not `height` - image is scaled proportionally to fit in the provided `width`
- `height` provided but not `width` - image is scaled proportionally to fit in the provided `height`
- Both `width` and `height` provided - image is stretched to the dimensions provided
- `scale` factor provided - image is scaled proportionally by the provided scale factor
- `fit` array provided - image is scaled proportionally to fit within the passed width and height
- `cover` array provided - image is scaled proportionally to completely cover the rectangle defined by the passed width and height
- `link` - a URL to link this image to (shortcut to create an annotation)
- `goTo` - go to anchor (shortcut to create an annotation)
- `destination` - create anchor to this image
- `ignoreOrientation` - (true/false) ignore JPEG EXIF orientation. By default, images with JPEG EXIF orientation are properly rotated and/or flipped. Defaults to `false`, unless `ignoreOrientation` option set to `true` when creating the `PDFDocument` object (e.g. `new PDFDocument({ignoreOrientation: true})`)

When a `fit` or `cover` array is provided, PDFKit accepts these additional options:

* `align` - horizontally align the image, the possible values are `'left'`, `'center'` and `'right'`
* `valign` - vertically align the image, the possible values are `'top'`, `'center'` and `'bottom'`
- `align` - horizontally align the image, the possible values are `'left'`, `'center'` and `'right'`
- `valign` - vertically align the image, the possible values are `'top'`, `'center'` and `'bottom'`

Here is an example showing some of these options.

Expand All @@ -48,11 +49,11 @@ Here is an example showing some of these options.
.rect(430, 15, 100, 100).stroke()
.text('Centered', 430, 0);

* * *
---

This example produces the following output:

![0](images/images.png "400")
![0](images/images.png '400')

That is all there is to adding images to your PDF documents with PDFKit. Now
let's look at adding outlines.
2 changes: 1 addition & 1 deletion examples/kitchen-sink.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var PDFDocument = require('../js/pdfkit');
var PDFDocument = require('../');
var tiger = require('./tiger');
var fs = require('fs');

Expand Down
14 changes: 7 additions & 7 deletions examples/webpack/package.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{
"license": "MIT",
"dependencies": {
"assert": "^2.0.0",
"assert": "^2.1.0",
"brace": "^0.11.1",
"browserify-zlib": "^0.2.0",
"buffer": "^6.0.3",
"pdfkit": "^0.12.3",
"pdfkit": "^0.15.0",
"process": "^0.11.10",
"readable-stream": "^3.6.0",
"util": "^0.12.4"
"readable-stream": "^4.5.2",
"util": "^0.12.5"
},
"devDependencies": {
"html-webpack-plugin": "^5.3.2",
"html-webpack-plugin": "^5.6.0",
"transform-loader": "^0.2.4",
"webpack": "^5.44.0",
"webpack-cli": "^4.7.2"
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
},
"scripts": {
"dev": "webpack --mode development",
Expand Down
32 changes: 16 additions & 16 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ By Devon Govett
*/

import stream from 'stream';
import fs from 'fs';
import PDFObject from './object';
import PDFReference from './reference';
import PDFPage from './page';
Expand All @@ -21,6 +20,8 @@ import MarkingsMixin from './mixins/markings';
import AcroFormMixin from './mixins/acroform';
import AttachmentsMixin from './mixins/attachments';
import LineWrapper from './line_wrapper';
import SubsetMixin from './mixins/subsets';
import MetadataMixin from './mixins/metadata';

class PDFDocument extends stream.Readable {
constructor(options = {}) {
Expand Down Expand Up @@ -83,13 +84,15 @@ class PDFDocument extends stream.Readable {
this.page = null;

// Initialize mixins
this.initMetadata();
this.initColor();
this.initVector();
this.initFonts(options.font);
this.initText();
this.initImages();
this.initOutline();
this.initMarkings(options);
this.initSubset(options);

// Initialize the metadata
this.info = {
Expand Down Expand Up @@ -216,7 +219,9 @@ class PDFDocument extends stream.Readable {
addNamedEmbeddedFile(name, ref) {
if (!this._root.data.Names.data.EmbeddedFiles) {
// disabling /Limits for this tree fixes attachments not showing in Adobe Reader
this._root.data.Names.data.EmbeddedFiles = new PDFNameTree({ limits: false });
this._root.data.Names.data.EmbeddedFiles = new PDFNameTree({
limits: false
});
}

// add filespec to EmbeddedFiles
Expand Down Expand Up @@ -266,22 +271,9 @@ class PDFDocument extends stream.Readable {
}
}

write(filename, fn) {
// print a deprecation warning with a stacktrace
const err = new Error(`\
PDFDocument#write is deprecated, and will be removed in a future version of PDFKit. \
Please pipe the document into a Node stream.\
`);

console.warn(err.stack);

this.pipe(fs.createWriteStream(filename));
this.end();
return this.once('end', fn);
}

end() {
this.flushPages();

this._info = this.ref();
for (let key in this.info) {
let val = this.info[key];
Expand All @@ -305,6 +297,12 @@ Please pipe the document into a Node stream.\
this.endOutline();
this.endMarkings();

if (this.subset) {
this.endSubset();
}

this.endMetadata();

this._root.end();
this._root.data.Pages.end();
this._root.data.Names.end();
Expand Down Expand Up @@ -368,6 +366,7 @@ const mixin = methods => {
Object.assign(PDFDocument.prototype, methods);
};

mixin(MetadataMixin);
mixin(ColorMixin);
mixin(VectorMixin);
mixin(FontsMixin);
Expand All @@ -378,6 +377,7 @@ mixin(OutlineMixin);
mixin(MarkingsMixin);
mixin(AcroFormMixin);
mixin(AttachmentsMixin);
mixin(SubsetMixin);

PDFDocument.LineWrapper = LineWrapper;

Expand Down
20 changes: 19 additions & 1 deletion lib/font/embedded.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ class EmbeddedFont extends PDFFont {
descriptor.data.FontFile2 = fontFile;
}

if (this.document.subset) {
const CIDSet = Buffer.from('FFFFFFFFC0', 'hex');
const CIDSetRef = this.document.ref();
CIDSetRef.write(CIDSet);
CIDSetRef.end();

descriptor.data.CIDSet = CIDSetRef;
}

descriptor.end();

const descendantFontData = {
Expand Down Expand Up @@ -240,6 +249,15 @@ class EmbeddedFont extends PDFFont {
entries.push(`<${encoded.join(' ')}>`);
}

const chunkSize = 256;
const chunks = Math.ceil(entries.length / chunkSize);
const ranges = [];
for (let i = 0; i < chunks; i++) {
const start = i * chunkSize;
const end = Math.min((i + 1) * chunkSize, entries.length);
ranges.push(`<${toHex(start)}> <${toHex(end - 1)}> [${entries.slice(start, end).join(' ')}]`);
}

cmap.end(`\
/CIDInit /ProcSet findresource begin
12 dict begin
Expand All @@ -255,7 +273,7 @@ begincmap
<0000><ffff>
endcodespacerange
1 beginbfrange
<0000> <${toHex(entries.length - 1)}> [${entries.join(' ')}]
${ranges.join('\n')}
endbfrange
endcmap
CMapName currentdict /CMap defineresource pop
Expand Down
2 changes: 1 addition & 1 deletion lib/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class PDFImage {
data = Buffer.from(new Uint8Array(src));
} else {
let match;
if ((match = /^data:.+;base64,(.*)$/.exec(src))) {
if ((match = /^data:.+?;base64,(.*)$/.exec(src))) {
data = Buffer.from(match[1], 'base64');
} else {
data = fs.readFileSync(src);
Expand Down
Loading

0 comments on commit 224b137

Please sign in to comment.