+7
-0
@@ -7,2 +7,9 @@ # Changelog | ||
| ## [2.0.0-alpha.8] - 2018-05-13 | ||
| ### Added | ||
| - Document outline support | ||
| ### Removed | ||
| - creating AFM fonts from JSON (`new Font(require('pdfjs/font/Helvetica.json'))` - instead, load the font directly: `require('pdfjs/font/Helvetica')`) | ||
| ## [2.0.0-alpha.7] - 2018-05-03 | ||
@@ -9,0 +16,0 @@ ### Deprecated |
+90
-0
@@ -106,2 +106,5 @@ 'use strict' | ||
| // init outlines hierarchy | ||
| this._outlines = [] | ||
| // init color space | ||
@@ -500,2 +503,16 @@ this._colorSpace = new PDF.Object() | ||
| _updateOutlinesCount(id) { | ||
| if (this._outlines[id].data.count < 1) { | ||
| this._outlines[id].data.count -= 1 | ||
| this._outlines[id].prop('Count', this._outlines[id].data.count) | ||
| } else { | ||
| this._outlines[id].data.count = -1 | ||
| this._outlines[id].prop('Count', this._outlines[id].data.count) | ||
| } | ||
| const nextParent = this._outlines[id].data.parentIndex | ||
| if(nextParent !== undefined) { | ||
| this._updateOutlinesCount(nextParent) | ||
| } | ||
| } | ||
| // public API | ||
@@ -538,2 +555,9 @@ | ||
| } | ||
| //Write outlines hierarchy if there are outlines | ||
| if(this._outlines.length > 0) { | ||
| for (let i = 0; i < this._outlines.length; i += 1) { | ||
| await this._writeObject(this._outlines[i]) | ||
| } | ||
| catalog.prop('Outlines', this._outlines[0].toReference()) | ||
| } | ||
| await this._writeObject(catalog) | ||
@@ -630,2 +654,68 @@ | ||
| } | ||
| outline(title, destination, parent) { | ||
| // Skip empty titles and/or destination | ||
| if (title === undefined || destination === undefined) return | ||
| // Create the root outline the first time this method is called | ||
| if (this._outlines.length === 0 ){ | ||
| this._outlines[0] = new PDF.Object('Outlines') | ||
| this._outlines[0].data = {type: 'Outlines'} | ||
| this._registerObject(this._outlines[0]) | ||
| } | ||
| // Find parent item | ||
| let parentIndex | ||
| if (parent === undefined || parent === '') { | ||
| parentIndex = 0 | ||
| } else { | ||
| parentIndex = this._outlines.findIndex( | ||
| (item, index) => (item.data.title === parent) | ||
| ) | ||
| if (parentIndex === -1) parentIndex = this.outline(parent, destination) | ||
| } | ||
| // Find siblings | ||
| let siblingsIndexes = this._outlines.reduce((result, item, index) => { | ||
| if (index !== 0 && item.data.parentIndex === parentIndex) result.push(index) | ||
| return result | ||
| }, []) | ||
| // Create item | ||
| const outline = new PDF.Object() | ||
| outline.data = {title, destination, parent} | ||
| outline.prop('Title', new PDF.String(title)) | ||
| outline.prop('Parent', this._outlines[parentIndex].toReference()) | ||
| outline.prop('A', new PDF.Dictionary({ | ||
| S: 'GoTo', | ||
| D: new PDF.String(destination), | ||
| })) | ||
| this._registerObject(outline) | ||
| const outlineIndex = this._outlines.push(outline)-1 | ||
| // Chain to siblings | ||
| const prevSiblingIndex = siblingsIndexes[siblingsIndexes.length-1] | ||
| if (prevSiblingIndex > 0) { | ||
| // Next | ||
| this._outlines[prevSiblingIndex].data.nextId = outlineIndex | ||
| this._outlines[prevSiblingIndex].prop('Next', this._outlines[outlineIndex].toReference()) | ||
| // Prev | ||
| this._outlines[outlineIndex].data.prevId = prevSiblingIndex | ||
| this._outlines[outlineIndex].prop('Prev', this._outlines[prevSiblingIndex].toReference()) | ||
| } | ||
| // Chain to parents | ||
| this._outlines[outlineIndex].data.parentIndex = parentIndex | ||
| if (siblingsIndexes.length === 0) { | ||
| // First | ||
| this._outlines[parentIndex].data.firstIndex = outlineIndex | ||
| this._outlines[parentIndex].prop('First', this._outlines[outlineIndex].toReference()) | ||
| } | ||
| // Last | ||
| this._outlines[parentIndex].data.lastIndex = outlineIndex | ||
| this._outlines[parentIndex].prop('Last', this._outlines[outlineIndex].toReference()) | ||
| // Count(s) | ||
| this._updateOutlinesCount(parentIndex) | ||
| return outlineIndex | ||
| } | ||
| } | ||
@@ -632,0 +722,0 @@ |
+1
-1
@@ -6,3 +6,3 @@ 'use strict' | ||
| exports.Document = require('./document') | ||
| exports.Font = require('./font') | ||
| exports.Font = require('./font/otf') | ||
@@ -9,0 +9,0 @@ const PDFImage = require('./image/pdf') |
+1
-1
| { | ||
| "name": "pdfjs", | ||
| "author": "Markus Ast <npm.m@rkusa.st>", | ||
| "version": "2.0.0-alpha.7", | ||
| "version": "2.0.0-alpha.8", | ||
| "description": "A Portable Document Format (PDF) generation library targeting both the server- and client-side.", | ||
@@ -6,0 +6,0 @@ "keywords": [ |
+3
-4
@@ -12,3 +12,3 @@  | ||
| ```bash | ||
| npm install pdfjs@2.0.0-alpha.3 | ||
| npm install pdfjs@2.0.0-alpha.8 | ||
| ``` | ||
@@ -32,2 +32,3 @@ | ||
| - Add existing PDFs (merge them or add them as page templates) | ||
| - Document outline | ||
@@ -40,5 +41,3 @@ A lot of examples can be found in the [test folder](https://github.com/rkusa/pdfjs/tree/master/test/pdfs). | ||
| - *v2.x* - streaming layouting with smart content chunking | ||
| - *v1.x* - calculate whole document layout upfront | ||
| - *v0.x* - in-memory layouting with rollbacks | ||
| See [CHANGELOG](https://github.com/rkusa/pdfjs/blob/master/CHANGELOG.md). | ||
@@ -45,0 +44,0 @@ ## MIT License |
+8
-0
@@ -124,2 +124,10 @@ declare module "pdfjs" { | ||
| setTemplate(external: ExternalDocument): void; | ||
| /** | ||
| * Add an outline to the document outlines of this document | ||
| * @param title The title of the outline that should be added | ||
| * @param destination The name of the destination that the outline to be added points to | ||
| * @param parent The title of the parent outline of the outline that should be added | ||
| */ | ||
| outline(title: string, destination: string, parent?: string): void; | ||
| } | ||
@@ -126,0 +134,0 @@ |
+27
-0
@@ -1450,2 +1450,29 @@ import * as pdf from "pdfjs"; | ||
| { // Outlines | ||
| doc.outline('1. An outline', 'Text') | ||
| // Outlines can be set to any kind of destinations | ||
| doc.outline('2. Works with any kind of dest', 'Doc') | ||
| doc.outline('2.1. Image', 'Image', '2. Works with any kind of dest') | ||
| doc.outline('2.2. Text', 'Text', '2. Works with any kind of dest') | ||
| doc.outline('2.3. Doc', 'Doc', '2. Works with any kind of dest') | ||
| // Outlines can be deeply nested | ||
| doc.outline('3. Can be deeply nested', 'Text') | ||
| doc.outline('3.1 Level 1', 'Image', '3. Can be deeply nested') | ||
| doc.outline('3.1.1 Level 2', 'Text', '3.1 Level 1') | ||
| // An outline with an unknown or empty destination is added to the outlines but is not reactive | ||
| doc.outline('4. Empty/Unknown destinations', '') | ||
| doc.outline('4.1. Can have children', 'Unknown', '4. Empty/Unknown destinations') | ||
| doc.outline('4.2. But are not reactive', 'Unknown', '4. Empty/Unknown destinations') | ||
| // If an outline is defined with a parent that has not already been declared, then the parent is added to the root with the same destination before the child outline is added | ||
| doc.outline('5.1. Can have children', 'Image', '5. Undeclared parents') | ||
| // An outline with an empty or undefined parent is attached to the root | ||
| doc.outline('6. An outline with an undefined parent is added to the root', 'Text') | ||
| doc.outline('7. So is an outline with an empty parent', 'Doc', '') | ||
| } | ||
| // from real usage | ||
@@ -1452,0 +1479,0 @@ |
-15
| 'use strict' | ||
| const AFMFont = require('./font/afm') | ||
| const OTFFont = require('./font/otf') | ||
| module.exports = class Font { | ||
| constructor(arg) { | ||
| if (arg instanceof Buffer) { | ||
| return new OTFFont(arg) | ||
| } else { | ||
| console.warn("Manual construction of AFM fonts will be removed in the next version (use `require('pdfjs/font/Helvetica')` instead of `new Font(require('pdfjs/font/Helvetica.json'))`") | ||
| return new AFMFont(arg) | ||
| } | ||
| } | ||
| } |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
326619
1.49%6274
1.55%75
-1.32%48
-2.04%