Comparing version 0.5.4 to 1.0.0-alpha.1
'use strict' | ||
var PDFXObject = require('./objects/xobject') | ||
var PDFArray = require('./objects/array') | ||
var utils = require('./utils') | ||
var utils = require('./pdf/utils') | ||
var uuid = require('node-uuid') | ||
var Image = module.exports = function(id, buffer) { | ||
// GLOBAL[('Buffer').toString()] is used instead of Buffer to trick browserify | ||
// to not load a Buffer polyfill just for instance testing. The `toString()` part | ||
// is used to trick eslint to not throw | ||
var isArrayBuffer = buffer instanceof ArrayBuffer | ||
var isBuffer = typeof GLOBAL !== 'undefined' && buffer instanceof GLOBAL[('Buffer').toString()] | ||
if (!isArrayBuffer && !isBuffer) { | ||
throw new Error('Property `' + buffer + '` must be a Buffer or a Arraybuffer.') | ||
} | ||
module.exports = function(src) { | ||
this.uuid = uuid.v4() | ||
this.src = utils.toArrayBuffer(src) | ||
this.buffer = buffer instanceof ArrayBuffer ? buffer : utils.toArrayBuffer(buffer) | ||
this.type = parseType(this.src) | ||
this.id = id | ||
this.xobject = new PDFXObject | ||
this.xobject.prop('Subtype', 'Image') | ||
switch (this.type) { | ||
case 'jpeg': | ||
this.info = parseJpegInfo(this.src) | ||
this.width = this.info.width | ||
this.height = this.info.height | ||
var info = getJpegInfo(this.buffer) | ||
this.xobject.prop('Width', this.width = info.width) | ||
this.xobject.prop('Height', this.height = info.height) | ||
switch (info.colorSpace) { | ||
case 3: | ||
this.colorSpace = 'DeviceRGB' | ||
break | ||
case 1: | ||
this.colorSpace = 'DeviceGRAY' | ||
break | ||
default: | ||
break | ||
switch (this.info.colorSpace) { | ||
case 3: | ||
this.colorSpace = 'DeviceRGB' | ||
break | ||
case 1: | ||
this.colorSpace = 'DeviceGRAY' | ||
break | ||
default: | ||
break | ||
} | ||
break | ||
case 'pdf': | ||
this.info = parsePDFInfo(this.src) | ||
break | ||
} | ||
this.xobject.prop('ColorSpace', this.colorSpace) | ||
this.xobject.prop('BitsPerComponent', 8) | ||
} | ||
Image.prototype.embed = function(doc) { | ||
doc.addObject(this.xobject) | ||
function parseType(buffer) { | ||
var pdf = String.fromCharCode.apply(null, new Uint8Array(buffer, 0, 5)) | ||
if (pdf === '%PDF-') { | ||
return 'pdf' | ||
} | ||
var hex = utils.asHex(this.buffer) | ||
this.xobject.prop('Filter', new PDFArray(['/ASCIIHexDecode', '/DCTDecode'])) | ||
this.xobject.prop('Length', hex.length + 1) | ||
this.xobject.prop('Length1', this.buffer.byteLength) | ||
this.xobject.content.content = hex + '>\n' | ||
} | ||
var view = new DataView(buffer) | ||
if (view.getUint8(0) === 0xff || view.getUint8(1) === 0xd8) { | ||
return 'jpeg' | ||
} | ||
Image.prototype.addTo = function(page) { | ||
page.xobjects.add(this.id, this.xobject.toReference()) | ||
throw new TypeError('Unsupported image type') | ||
} | ||
function getJpegInfo(buffer) { | ||
function parseJpegInfo(buffer) { | ||
var view = new DataView(buffer) | ||
@@ -93,1 +86,19 @@ if (view.getUint8(0) !== 0xff || view.getUint8(1) !== 0xd8) { | ||
} | ||
var Parser = require('./pdf/parser/document') | ||
function parsePDFInfo(buffer) { | ||
var parser = new Parser(buffer) | ||
parser.parse() | ||
var catalog = parser.trailer.get('Root').object.properties | ||
var pages = catalog.get('Pages').object.properties | ||
var first = pages.get('Kids')[0].object.properties | ||
var mediaBox = first.get('MediaBox') || pages.get('MediaBox') | ||
return { | ||
page: first, | ||
width: mediaBox[2], | ||
height: mediaBox[3] | ||
} | ||
} |
@@ -7,3 +7,3 @@ { | ||
}, | ||
"version": "0.5.4", | ||
"version": "1.0.0-alpha.1", | ||
"homepage": "https://github.com/rkusa/pdfjs", | ||
@@ -16,19 +16,20 @@ "description": "A Portable Document Format (PDF) generation library targeting both the server- and client-side.", | ||
"license": "MIT", | ||
"main": "lib/document", | ||
"main": "lib/index", | ||
"scripts": { | ||
"test": "mocha", | ||
"prepublish": "npm run-script bundle", | ||
"bundle": "browserify lib/document.js --standalone Pdfjs --detect-globals false > pdfjs.js && npm run-script minify", | ||
"minify": "uglifyjs --source-map pdfjs.min.map -o pdfjs.min.js pdfjs.js" | ||
"test": "tap strict test/index.js", | ||
"prepublish": "browserify lib/index.js --debug --standalone pdfjs --detect-globals false | exorcist dist/pdfjs.js.map > dist/pdfjs.js" | ||
}, | ||
"dependencies": { | ||
"base-64": "^0.1.0", | ||
"ttfjs": "0.2.x", | ||
"node-uuid": "^1.4.1" | ||
"debug": "^2.2", | ||
"linebreak": "^0.3.0", | ||
"node-uuid": "^1.4", | ||
"ttfjs": "^0.3.0", | ||
"unorm": "^1.3" | ||
}, | ||
"devDependencies": { | ||
"browserify": "2.x.x", | ||
"chai": "1.8.x", | ||
"mocha": "1.13.x", | ||
"uglify-js": "2.x.x" | ||
"browserify": "^10.2", | ||
"exorcist": "^0.4.0", | ||
"glob": "^5.0", | ||
"tap": "^1.0" | ||
}, | ||
@@ -35,0 +36,0 @@ "bugs": "https://github.com/rkusa/pdfjs/issues", |
416
README.md
@@ -7,411 +7,30 @@ ![pdfjs](https://raw.githubusercontent.com/rkusa/pdfjs/master/logo/pdfjs.png) | ||
[![Dependency Status][deps]](https://david-dm.org/rkusa/pdfjs) | ||
[![Build Status][drone]](https://ci.rkusa.st/github.com/rkusa/pdfjs) | ||
#### Features | ||
[Documentation](docs) | ||
- Text (+ formatting) | ||
- Images (JPEGs) | ||
- Tables | ||
- Header & Footer | ||
- Automatic page breaks | ||
- Font embedding (as CID fonts, i.e., supports large character set fonts) | ||
## 1.0.0 Breaking Changes | ||
#### Missing Features | ||
pdfjs 1.0.0-alpha.1 (still in development; expected to be buggy) contains a rewritten layout engine (layout engine of pdfjs `<=0.5` reached its limits), i.e., both API and layout behavior has changed completely. Install with: | ||
AFM fonts and vector graphics are currently not implemented. If you are missing a feature, feel free to ask or to submit a PR. | ||
#### Contents | ||
1. [Document](#document) | ||
2. [Text](#text) | ||
3. [Image](#image) | ||
4. [Table](#table) | ||
5. [Font](#font) | ||
6. [License](#license) | ||
## Document | ||
```js | ||
var Document = require('pdfjs') | ||
```bash | ||
npm install pdfjs@1.0.0-alpha.1 | ||
``` | ||
### new Document(font) | ||
### Features | ||
**Arguments:** | ||
- Text (many formatting options) | ||
- Images (JPEGs, other **PDFs**) | ||
- Tables (fixed layout, header row, before page break rows) | ||
- Header & Footer | ||
- TTF Font embedding (as CID fonts, i.e., support for fonts with large character sets) | ||
- **font** - a font; will be used as default font | ||
**Missing:** AFM fonts are currently not implemented. | ||
**Example:** | ||
If you are missing a feature, feel free to submit a PR or to ask for it. | ||
```js | ||
var Document = require('pdfjs') | ||
fs.readFile('OpenSans-Regular.ttf', function(err, b) { | ||
if (err) throw err | ||
var doc = new Document(new Document.Font(b)) | ||
}) | ||
``` | ||
## MIT License | ||
### .text(text[, opts]) | ||
Copyright (c) 2013-2015 Markus Ast | ||
**Arguments:** | ||
- **text** - the text that should be rendered | ||
- **opts** - text options | ||
**Options:** | ||
- **bold** - whether the text should be rendered bold (default: false) | ||
- **italic** - whether the text should be rendered italic (default: false) | ||
- **light** - whether the text should be rendered light (default: false) | ||
- **align** - the text alignment (default: left, available: left, right, center or justify) | ||
- **lineSpacing** - this is a factor that could be used to increase or decrease the line spacing (default: 1) | ||
- **font** - the font that should be used | ||
- **size** - the font size | ||
**Example:** | ||
```js | ||
doc.text('Lorem ipsum dolor sit amet ...', { | ||
size: 12, | ||
align: 'justify', | ||
lineSpacing: 1.2 | ||
}) | ||
``` | ||
### .text([definition]) | ||
This text method can be used to render more advanced/complex text fragments. It allows to combine multiple text styles. **Returns** a [Text](#text) function. | ||
**Arguments:** | ||
- **definition** - a function describing the text to be rendered; it gets the `text` object described in [Text](#text) | ||
**Example:** | ||
```js | ||
doc.text(function(text) { | ||
// this === text | ||
this.opts.size = 12 | ||
this.opts.lineSpacing = 1.35 | ||
text('This is a header', { bold: true, size: 18 }).br() | ||
text('Content can be')('bold', { bold: true }) | ||
text(',')('italic', { italic: true }) | ||
text('or')('both', { italic: true, bold: true })('.') | ||
text('You`re also able to use')('light', { light: true }) | ||
text(', which could be')('italic', { italic: true, light: true })(', too.').br() | ||
text('If you want, you can also')('mixup different fonts', { font: sourceCodeProp }) | ||
text('or different')('font', { size: 10 })('sizes', { size: 16 })('.') | ||
}) | ||
``` | ||
**Result:** | ||
![Result](https://raw.github.com/rkusa/pdfjs/gh-pages/images/text-example.png) | ||
### .image(buffer, [opts]) | ||
This method can be used to render an image. | ||
**Arguments:** | ||
- **buffer** - a Buffer, ArrayBuffer or instance of [Image](#image) | ||
- **opts** - render options | ||
**Options:** | ||
- **width**, **height** - Image size. If neither `width` nor `height` are provided, the image is rendered to fit into the current context (e.g. page size). When either `width` or `height` is provided, the images is scaled proportionally; if both are provided, the image is stretched. | ||
- **wrap** - whether the image should wrap surrounding text (default: true) | ||
- **align** - when `wrap` is set to `true`, `align` can be used to set the horizontal positon (left, right, or center) | ||
- **x**, **y** - when `wrap` is set to `false`, `x` and `y` can be used to explicitly set the position if the image | ||
**Example:** | ||
```js | ||
fs.readFile('./picture.jpg', function(err, b) { | ||
if (err) throw err | ||
doc.image(b, { align: 'center' }) | ||
}) | ||
``` | ||
### .table([opts, ] [definition]) | ||
This method can be used to define tables. **Returns** a [Table](#table) object. | ||
**Arguments:** | ||
- **opts** - table options | ||
- **definition** - a function that contains the table definition | ||
**Options:** | ||
- **borderWidth** - | ||
- **width** - total width (absolute or relative) or an array of column widths | ||
- + [Text Options](#texttext-opts) | ||
**Example:** | ||
```js | ||
doc.table({ header: true, size: 11 }, function() { | ||
this.tr({ bold: true, borderWidth: { bottom: 1.5 } }, function() { | ||
this.td('#') | ||
this.td('Unit') | ||
this.td('Subject') | ||
this.td('Price', { align: 'right' }) | ||
this.td('Total', { align: 'right' }) | ||
}) | ||
this.tr({ borderWidth: { horizontal: 0.1 } }, function() { | ||
this.td('2') | ||
this.td('pc.') | ||
this.td(function() { | ||
this.text('Article A', { size: 11, bold: true }) | ||
this.text('Lorem ipsum ...', { size: 9, align: 'justify' }) | ||
}) | ||
this.td('500.00€', { align: 'right' }) | ||
this.td('1,000.00€', { align: 'right' }) | ||
}) | ||
this.tr({ borderWidth: { horizontal: 0.1 } }, function() { | ||
this.td('1') | ||
this.td('pc.') | ||
this.td(function() { | ||
this.text('Article B', { size: 11, bold: true }) | ||
this.text('Cum id fugiunt ...', { size: 9, align: 'justify' }) | ||
}) | ||
this.td('250.00€', { align: 'right' }) | ||
this.td('250.00€', { align: 'right' }) | ||
}) | ||
this.tr({ bold: true, align: 'right' }, function() { | ||
this.td('Total', { colspan: 4 }) | ||
this.td('1,250.00€') | ||
}) | ||
}) | ||
``` | ||
**Result:** | ||
![Result](https://raw.github.com/rkusa/pdfjs/gh-pages/images/table-example.png) | ||
### .toDataURL() | ||
Returns the document as [data URL](https://developer.mozilla.org/en-US/docs/data_URIs). | ||
**Example:** | ||
```html | ||
<iframe id="preview" width="100%" height="650" frameborder="0"> | ||
</iframe> | ||
``` | ||
```js | ||
document.querySelector('#preview') | ||
.setAttribute('src', doc.toDataURL()) | ||
``` | ||
### .toString() | ||
Returns the document as plain text. | ||
**Example:** | ||
```js | ||
var fs = require('fs') | ||
fs.writeFile(__dirname + '/test.pdf', doc.toString(), 'ascii') | ||
``` | ||
## Text | ||
This is a function itself and an alias for `.text()`. It is used to define more complex/advanced text fragments. **Returns** itself. | ||
### .text() | ||
Same as [doc.text(text[, opts])](#texttext-opts) | ||
### .br() | ||
Line Break. Returns the [Text](#text) function. | ||
### .pageNumber() | ||
Print the page number the text fragment is rendered on. Returns the [Text](#text) function. | ||
**Example:** | ||
```js | ||
doc.text(function(text) { | ||
text('Page').pageNumber() | ||
}) | ||
``` | ||
## Image | ||
The image object should be used, when adding an image multiple times. | ||
### doc.createImage(buffer) | ||
This method is used to create a new image from the given buffer. | ||
**Example:** | ||
```js | ||
var img = doc.createImage(buffer) | ||
doc.image(img, { align: 'right' }) | ||
``` | ||
## Table | ||
This table object is used to define its rows and its behaviour on page breaks. | ||
### .tr([opts,] definition) | ||
This method is used to define a table row. **Returns** a [Table Row](#table-row) object. | ||
**Arguments:** | ||
- **opts** - row options | ||
- **definition** - a function that contains the row definition | ||
**Options:** | ||
- **borderWidth** - | ||
- + [Text Options](#texttext-opts) | ||
### .beforeBreak([opts,] definition) | ||
Same as [.tr([opts,] definition)](#tropts-definition), but only rendered if the table is broken among two pages. This row is then rendered directly before the page break. | ||
```js | ||
table.beforeBreak(function() { | ||
this.td('Subtotal:', { colspan: 4, align: 'right' }) | ||
this.td(function() { | ||
this.text(function(text) { | ||
this.opts.align = 'right' | ||
this.opts.size = 11 | ||
text(function() { | ||
if (!this.table) return '' | ||
return items.subtotalUntil(this.table.row) | ||
}) | ||
}) | ||
}) | ||
}) | ||
``` | ||
### .afterBreak([opts,] definition) | ||
Same as [.tr([opts,] definition)](#tropts-definition), but only rendered if the table is broken among two pages. This row is then rendered directly after the header on the new page. | ||
**Example:** | ||
```js | ||
table.afterBreak(function() { | ||
this.td('Carryover:', { colspan: 4, align: 'right' }) | ||
this.td(function() { | ||
this.text(function(text) { | ||
this.opts.align = 'right' | ||
this.opts.size = 11 | ||
text(function() { | ||
if (!this.table) return '' | ||
return items.subtotalUntil(this.table.row) | ||
}) | ||
}) | ||
}) | ||
}) | ||
``` | ||
**Result:** | ||
![Result](https://raw.github.com/rkusa/pdfjs/gh-pages/images/table-pagebreak-example.png) | ||
## Table Row | ||
This table row object is used to define its cells. | ||
### .td(text[, opts]) | ||
This method is used to define a cell of the row. | ||
**Arguments:** | ||
- **text** - the text contained in the cell | ||
- **opts** - cell options | ||
**Options:** | ||
- **borderWidth** - | ||
- **colspan** - | ||
- + [Text Options](#texttext-opts) | ||
### .td([opts,] definition) | ||
This method is used to define a cell of the row. | ||
**Arguments:** | ||
- **opts** - cell options | ||
- **definition** - a function that contains the cell definition | ||
**Options:** | ||
- **borderWidth** - | ||
- **colspan** - | ||
- + [Text Options](#texttext-opts) | ||
## Font | ||
### new Font(buffer) | ||
Create a new font from the given buffer. | ||
### new Font(styles) | ||
Instead of just providing one font style (*regular*), you can also provide multiple styles. | ||
**Styles:** *normal*, *italic*, *bold*, *boldItalic*, *light*, *lightItalic* | ||
**Example:** | ||
```js | ||
new pdfjs.Font({ | ||
regular: fs.readFileSync(__dirname + '/open-sans/OpenSans-Regular.ttf'), | ||
bold: fs.readFileSync(__dirname + '/open-sans/OpenSans-Bold.ttf'), | ||
boldItalic: fs.readFileSync(__dirname + '/open-sans/OpenSans-BoldItalic.ttf'), | ||
light: fs.readFileSync(__dirname + '/open-sans/OpenSans-Italic.ttf'), | ||
italic: fs.readFileSync(__dirname + '/open-sans/OpenSans-LightItalic.ttf'), | ||
lightItalic: fs.readFileSync(__dirname + '/open-sans/OpenSans-LightItalic.ttf'), | ||
}) | ||
``` | ||
(the sync API is just used for presentation purpose and should not be used in production) | ||
In the browser, you can load fonts using AJAX requests, e.g.: | ||
```js | ||
function load(path, callback) { | ||
var request = new XMLHttpRequest() | ||
request.open('GET', path, true) | ||
request.responseType = 'arraybuffer' | ||
if (request.overrideMimeType) { | ||
request.overrideMimeType('text/plain; charset=x-user-defined') | ||
} else { | ||
request.setRequestHeader('Accept-Charset', 'x-user-defined') | ||
} | ||
request.onload = function() { | ||
if (request.status === 200) { | ||
callback(null, request.response) | ||
} else { | ||
callback(request.status) | ||
} | ||
} | ||
request.send(null) | ||
} | ||
load('path/to/font.ttf', function(err, buffer) { | ||
// ... | ||
}) | ||
``` | ||
## MIT License | ||
Copyright (c) 2013-2014 Markus Ast | ||
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: | ||
@@ -424,2 +43,3 @@ | ||
[npm]: http://img.shields.io/npm/v/pdfjs.svg?style=flat-square | ||
[deps]: http://img.shields.io/gemnasium/rkusa/pdfjs.svg?style=flat-square | ||
[deps]: http://img.shields.io/david/rkusa/pdfjs.svg?style=flat-square | ||
[drone]: http://ci.rkusa.st/api/badge/github.com/rkusa/pdfjs/status.svg?branch=master&style=flat-square |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
870001
69
10827
1
6
43
1
+ Addeddebug@^2.2
+ Addedlinebreak@^0.3.0
+ Addedunorm@^1.3
+ Addedacorn@7.4.1(transitive)
+ Addedbase64-js@0.0.8(transitive)
+ Addedbrfs@1.6.1(transitive)
+ Addedbuffer-equal@0.0.1(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedconcat-stream@1.6.2(transitive)
+ Addedconvert-source-map@1.9.0(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addeddebug@2.6.9(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addedduplexer2@0.1.4(transitive)
+ Addedescodegen@1.9.12.1.0(transitive)
+ Addedesprima@3.1.34.0.1(transitive)
+ Addedestraverse@4.3.05.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedfalafel@2.2.5(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedhas@1.0.4(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-core-module@2.15.1(transitive)
+ Addedisarray@1.0.02.0.5(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedlinebreak@0.3.0(transitive)
+ Addedmagic-string@0.22.5(transitive)
+ Addedmerge-source-map@1.0.4(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedms@2.0.0(transitive)
+ Addedobject-inspect@1.4.1(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedpako@0.2.9(transitive)
+ Addedpath-parse@1.0.7(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedquote-stream@1.0.2(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedresolve@1.22.8(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedshallow-copy@0.0.1(transitive)
+ Addedsource-map@0.5.70.6.1(transitive)
+ Addedstatic-eval@2.1.1(transitive)
+ Addedstatic-module@2.2.5(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedsupports-preserve-symlinks-flag@1.0.0(transitive)
+ Addedthrough2@2.0.5(transitive)
+ Addedtiny-inflate@1.0.3(transitive)
+ Addedttfjs@0.3.0(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addedtypedarray@0.0.6(transitive)
+ Addedunicode-trie@0.3.1(transitive)
+ Addedunorm@1.6.0(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedvlq@0.2.3(transitive)
+ Addedword-wrap@1.2.5(transitive)
+ Addedxtend@4.0.2(transitive)
- Removedttfjs@0.2.2(transitive)
Updatednode-uuid@^1.4
Updatedttfjs@^0.3.0