pdfmake
Version:
Client/server side PDF printing in pure JavaScript
1,549 lines (1,478 loc) • 2.51 MB
JavaScript
/*! pdfmake v0.3.0-beta.14, @license MIT, @link http://pdfmake.org */
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else {
var a = factory();
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})(typeof self !== 'undefined' ? self : this, () => {
return /******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ 428:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
"default": () => (/* binding */ browser_extensions)
});
// EXTERNAL MODULE: ./node_modules/@foliojs-fork/pdfkit/js/pdfkit.es.js
var pdfkit_es = __webpack_require__(6837);
;// ./src/PDFDocument.js
/* provided dependency */ var Buffer = __webpack_require__(783)["Buffer"];
const typeName = (bold, italics) => {
let type = 'normal';
if (bold && italics) {
type = 'bolditalics';
} else if (bold) {
type = 'bold';
} else if (italics) {
type = 'italics';
}
return type;
};
class PDFDocument extends pdfkit_es/* default */.A {
constructor(fonts, images, patterns, attachments, options, virtualfs) {
if (fonts === void 0) {
fonts = {};
}
if (images === void 0) {
images = {};
}
if (patterns === void 0) {
patterns = {};
}
if (attachments === void 0) {
attachments = {};
}
if (options === void 0) {
options = {};
}
if (virtualfs === void 0) {
virtualfs = null;
}
super(options);
this.fonts = {};
this.fontCache = {};
for (let font in fonts) {
if (fonts.hasOwnProperty(font)) {
let fontDef = fonts[font];
this.fonts[font] = {
normal: fontDef.normal,
bold: fontDef.bold,
italics: fontDef.italics,
bolditalics: fontDef.bolditalics
};
}
}
this.patterns = {};
for (let pattern in patterns) {
if (patterns.hasOwnProperty(pattern)) {
let patternDef = patterns[pattern];
this.patterns[pattern] = this.pattern(patternDef.boundingBox, patternDef.xStep, patternDef.yStep, patternDef.pattern, patternDef.colored);
}
}
this.images = images;
this.attachments = attachments;
this.virtualfs = virtualfs;
}
getFontType(bold, italics) {
return typeName(bold, italics);
}
getFontFile(familyName, bold, italics) {
let type = this.getFontType(bold, italics);
if (!this.fonts[familyName] || !this.fonts[familyName][type]) {
return null;
}
return this.fonts[familyName][type];
}
provideFont(familyName, bold, italics) {
let type = this.getFontType(bold, italics);
if (this.getFontFile(familyName, bold, italics) === null) {
throw new Error(`Font '${familyName}' in style '${type}' is not defined in the font section of the document definition.`);
}
this.fontCache[familyName] = this.fontCache[familyName] || {};
if (!this.fontCache[familyName][type]) {
let def = this.fonts[familyName][type];
if (!Array.isArray(def)) {
def = [def];
}
if (this.virtualfs && this.virtualfs.existsSync(def[0])) {
def[0] = this.virtualfs.readFileSync(def[0]);
}
this.fontCache[familyName][type] = this.font(...def)._font;
}
return this.fontCache[familyName][type];
}
provideImage(src) {
const realImageSrc = src => {
let image = this.images[src];
if (!image) {
return src;
}
if (this.virtualfs && this.virtualfs.existsSync(image)) {
return this.virtualfs.readFileSync(image);
}
let index = image.indexOf('base64,');
if (index < 0) {
return this.images[src];
}
return Buffer.from(image.substring(index + 7), 'base64');
};
if (this._imageRegistry[src]) {
return this._imageRegistry[src];
}
let image;
try {
image = this.openImage(realImageSrc(src));
if (!image) {
throw new Error('No image');
}
} catch (error) {
throw new Error(`Invalid image: ${error.toString()}\nImages dictionary should contain dataURL entries (or local file paths in node.js)`);
}
image.embed(this);
this._imageRegistry[src] = image;
return image;
}
/**
* @param {Array} color pdfmake format: [<pattern name>, <color>]
* @returns {Array} pdfkit format: [<pattern object>, <color>]
*/
providePattern(color) {
if (Array.isArray(color) && color.length === 2) {
return [this.patterns[color[0]], color[1]];
}
return null;
}
provideAttachment(src) {
const checkRequired = obj => {
if (!obj) {
throw new Error('No attachment');
}
if (!obj.src) {
throw new Error('The "src" key is required for attachments');
}
return obj;
};
if (typeof src === 'object') {
return checkRequired(src);
}
let attachment = checkRequired(this.attachments[src]);
if (this.virtualfs && this.virtualfs.existsSync(attachment.src)) {
return this.virtualfs.readFileSync(attachment.src);
}
return attachment;
}
setOpenActionAsPrint() {
let printActionRef = this.ref({
Type: 'Action',
S: 'Named',
N: 'Print'
});
this._root.data.OpenAction = printActionRef;
printActionRef.end();
}
}
/* harmony default export */ const src_PDFDocument = (PDFDocument);
;// ./src/helpers/variableType.js
/**
* @param {any} variable
* @returns {boolean}
*/
function isString(variable) {
return typeof variable === 'string' || variable instanceof String;
}
/**
* @param {any} variable
* @returns {boolean}
*/
function isNumber(variable) {
return typeof variable === 'number' || variable instanceof Number;
}
/**
* @param {any} variable
* @returns {boolean}
*/
function isPositiveInteger(variable) {
if (!isNumber(variable) || !Number.isInteger(variable) || variable <= 0) {
return false;
}
return true;
}
/**
* @param {any} variable
* @returns {boolean}
*/
function isObject(variable) {
return variable !== null && !Array.isArray(variable) && !isString(variable) && !isNumber(variable) && typeof variable === 'object';
}
/**
* @param {any} variable
* @returns {boolean}
*/
function isEmptyObject(variable) {
return isObject(variable) && Object.keys(variable).length === 0;
}
/**
* @param {any} variable
* @returns {boolean}
*/
function isValue(variable) {
return variable !== undefined && variable !== null;
}
;// ./src/helpers/node.js
function fontStringify(key, val) {
if (key === 'font') {
return 'font';
}
return val;
}
/**
* Convert node to readable string
*
* @param {object} node
* @returns {string}
*/
function stringifyNode(node) {
return JSON.stringify(node, fontStringify);
}
/**
* @param {object} node
* @returns {?string}
*/
function getNodeId(node) {
if (node.id) {
return node.id;
}
if (Array.isArray(node.text)) {
for (let n of node.text) {
let nodeId = getNodeId(n);
if (nodeId) {
return nodeId;
}
}
}
return null;
}
/**
* @param {object} node
* @param {object} styleStack object is instance of PDFDocument
* @returns {?Array}
*/
function getNodeMargin(node, styleStack) {
function processSingleMargins(node, currentMargin) {
if (node.marginLeft || node.marginTop || node.marginRight || node.marginBottom) {
return [node.marginLeft || currentMargin[0] || 0, node.marginTop || currentMargin[1] || 0, node.marginRight || currentMargin[2] || 0, node.marginBottom || currentMargin[3] || 0];
}
return currentMargin;
}
function flattenStyleArray(styleArray, styleStack) {
let flattenedStyles = {};
for (let i = styleArray.length - 1; i >= 0; i--) {
let styleName = styleArray[i];
let style = styleStack.styleDictionary[styleName];
for (let key in style) {
if (style.hasOwnProperty(key)) {
flattenedStyles[key] = style[key];
}
}
}
return flattenedStyles;
}
function convertMargin(margin) {
if (isNumber(margin)) {
margin = [margin, margin, margin, margin];
} else if (Array.isArray(margin)) {
if (margin.length === 2) {
margin = [margin[0], margin[1], margin[0], margin[1]];
}
}
return margin;
}
let margin = [undefined, undefined, undefined, undefined];
if (node.style) {
let styleArray = Array.isArray(node.style) ? node.style : [node.style];
let flattenedStyleArray = flattenStyleArray(styleArray, styleStack);
if (flattenedStyleArray) {
margin = processSingleMargins(flattenedStyleArray, margin);
}
if (flattenedStyleArray.margin) {
margin = convertMargin(flattenedStyleArray.margin);
}
}
margin = processSingleMargins(node, margin);
if (node.margin) {
margin = convertMargin(node.margin);
}
if (margin[0] === undefined && margin[1] === undefined && margin[2] === undefined && margin[3] === undefined) {
return null;
}
return margin;
}
;// ./src/DocPreprocessor.js
/* provided dependency */ var DocPreprocessor_Buffer = __webpack_require__(783)["Buffer"];
const convertValueToString = value => {
if (isString(value)) {
return value.replace(/\t/g, ' '); // expand tab as spaces
} else if (isNumber(value) || typeof value === 'boolean') {
return value.toString();
} else if (!isValue(value) || isEmptyObject(value)) {
return '';
}
// TODO: throw exception ?
return value;
};
class DocPreprocessor {
preprocessDocument(docStructure) {
this.parentNode = null;
this.tocs = [];
this.nodeReferences = [];
return this.preprocessNode(docStructure);
}
preprocessNode(node) {
// expand shortcuts and casting values
if (Array.isArray(node)) {
node = {
stack: node
};
} else if (isString(node) || isNumber(node) || typeof node === 'boolean' || !isValue(node) || isEmptyObject(node)) {
// text node defined as value
node = {
text: convertValueToString(node)
};
} else if ('text' in node) {
// cast value in text property
node.text = convertValueToString(node.text);
}
if (node.columns) {
return this.preprocessColumns(node);
} else if (node.stack) {
return this.preprocessVerticalContainer(node);
} else if (node.ul) {
return this.preprocessList(node);
} else if (node.ol) {
return this.preprocessList(node);
} else if (node.table) {
return this.preprocessTable(node);
} else if (node.text !== undefined) {
return this.preprocessText(node);
} else if (node.toc) {
return this.preprocessToc(node);
} else if (node.image) {
return this.preprocessImage(node);
} else if (node.svg) {
return this.preprocessSVG(node);
} else if (node.canvas) {
return this.preprocessCanvas(node);
} else if (node.qr) {
return this.preprocessQr(node);
} else if (node.attachment) {
return this.preprocessAttachment(node);
} else if (node.pageReference || node.textReference) {
return this.preprocessText(node);
} else {
throw new Error(`Unrecognized document structure: ${stringifyNode(node)}`);
}
}
preprocessColumns(node) {
let columns = node.columns;
for (let i = 0, l = columns.length; i < l; i++) {
columns[i] = this.preprocessNode(columns[i]);
}
return node;
}
preprocessVerticalContainer(node) {
let items = node.stack;
for (let i = 0, l = items.length; i < l; i++) {
items[i] = this.preprocessNode(items[i]);
}
return node;
}
preprocessList(node) {
let items = node.ul || node.ol;
for (let i = 0, l = items.length; i < l; i++) {
items[i] = this.preprocessNode(items[i]);
}
return node;
}
preprocessTable(node) {
let col;
let row;
let cols;
let rows;
for (col = 0, cols = node.table.body[0].length; col < cols; col++) {
for (row = 0, rows = node.table.body.length; row < rows; row++) {
let rowData = node.table.body[row];
let data = rowData[col];
if (data !== undefined) {
if (data === null) {
// transform to object
data = '';
}
if (!data._span) {
rowData[col] = this.preprocessNode(data);
}
}
}
}
return node;
}
preprocessText(node) {
if (node.tocItem) {
if (!Array.isArray(node.tocItem)) {
node.tocItem = [node.tocItem];
}
for (let i = 0, l = node.tocItem.length; i < l; i++) {
if (!isString(node.tocItem[i])) {
node.tocItem[i] = '_default_';
}
let tocItemId = node.tocItem[i];
if (!this.tocs[tocItemId]) {
this.tocs[tocItemId] = {
toc: {
_items: [],
_pseudo: true
}
};
}
if (!node.id) {
node.id = `toc-${tocItemId}-${this.tocs[tocItemId].toc._items.length}`;
}
let tocItemRef = {
_nodeRef: this._getNodeForNodeRef(node),
_textNodeRef: node
};
this.tocs[tocItemId].toc._items.push(tocItemRef);
}
}
if (node.id) {
if (this.nodeReferences[node.id]) {
if (!this.nodeReferences[node.id]._pseudo) {
throw new Error(`Node id '${node.id}' already exists`);
}
this.nodeReferences[node.id]._nodeRef = this._getNodeForNodeRef(node);
this.nodeReferences[node.id]._textNodeRef = node;
this.nodeReferences[node.id]._pseudo = false;
} else {
this.nodeReferences[node.id] = {
_nodeRef: this._getNodeForNodeRef(node),
_textNodeRef: node
};
}
}
if (node.pageReference) {
if (!this.nodeReferences[node.pageReference]) {
this.nodeReferences[node.pageReference] = {
_nodeRef: {},
_textNodeRef: {},
_pseudo: true
};
}
node.text = '00000';
node.linkToDestination = node.pageReference;
node._pageRef = this.nodeReferences[node.pageReference];
}
if (node.textReference) {
if (!this.nodeReferences[node.textReference]) {
this.nodeReferences[node.textReference] = {
_nodeRef: {},
_pseudo: true
};
}
node.text = '';
node.linkToDestination = node.textReference;
node._textRef = this.nodeReferences[node.textReference];
}
if (node.text && node.text.text) {
node.text = [this.preprocessNode(node.text)];
} else if (Array.isArray(node.text)) {
let isSetParentNode = false;
if (this.parentNode === null) {
this.parentNode = node;
isSetParentNode = true;
}
for (let i = 0, l = node.text.length; i < l; i++) {
node.text[i] = this.preprocessNode(node.text[i]);
}
if (isSetParentNode) {
this.parentNode = null;
}
}
return node;
}
preprocessToc(node) {
if (!node.toc.id) {
node.toc.id = '_default_';
}
node.toc.title = node.toc.title ? this.preprocessNode(node.toc.title) : null;
node.toc._items = [];
if (this.tocs[node.toc.id]) {
if (!this.tocs[node.toc.id].toc._pseudo) {
throw new Error(`TOC '${node.toc.id}' already exists`);
}
node.toc._items = this.tocs[node.toc.id].toc._items;
}
this.tocs[node.toc.id] = node;
return node;
}
preprocessImage(node) {
if (node.image.type !== undefined && node.image.data !== undefined && node.image.type === 'Buffer' && Array.isArray(node.image.data)) {
node.image = DocPreprocessor_Buffer.from(node.image.data);
}
return node;
}
preprocessCanvas(node) {
return node;
}
preprocessSVG(node) {
return node;
}
preprocessQr(node) {
return node;
}
preprocessAttachment(node) {
return node;
}
_getNodeForNodeRef(node) {
if (this.parentNode) {
return this.parentNode;
}
return node;
}
}
/* harmony default export */ const src_DocPreprocessor = (DocPreprocessor);
// EXTERNAL MODULE: ./node_modules/@foliojs-fork/linebreak/src/linebreaker.js
var linebreaker = __webpack_require__(9534);
var linebreaker_default = /*#__PURE__*/__webpack_require__.n(linebreaker);
;// ./src/StyleContextStack.js
/**
* Used for style inheritance and style overrides
*/
class StyleContextStack {
/**
* @param {object} styleDictionary named styles dictionary
* @param {object} defaultStyle optional default style definition
*/
constructor(styleDictionary, defaultStyle) {
if (defaultStyle === void 0) {
defaultStyle = {};
}
this.styleDictionary = styleDictionary;
this.defaultStyle = defaultStyle;
this.styleOverrides = [];
}
/**
* Creates cloned version of current stack
*
* @returns {StyleContextStack} current stack snapshot
*/
clone() {
let stack = new StyleContextStack(this.styleDictionary, this.defaultStyle);
this.styleOverrides.forEach(item => {
stack.styleOverrides.push(item);
});
return stack;
}
/**
* Pushes style-name or style-overrides-object onto the stack for future evaluation
*
* @param {string|object} styleNameOrOverride style-name (referring to styleDictionary) or
* a new dictionary defining overriding properties
*/
push(styleNameOrOverride) {
this.styleOverrides.push(styleNameOrOverride);
}
/**
* Removes last style-name or style-overrides-object from the stack
*
* @param {number} howMany optional number of elements to be popped (if not specified,
* one element will be removed from the stack)
*/
pop(howMany) {
if (howMany === void 0) {
howMany = 1;
}
while (howMany-- > 0) {
this.styleOverrides.pop();
}
}
/**
* Creates a set of named styles or/and a style-overrides-object based on the item,
* pushes those elements onto the stack for future evaluation and returns the number
* of elements pushed, so they can be easily poped then.
*
* @param {object} item - an object with optional style property and/or style overrides
* @returns {number} the number of items pushed onto the stack
*/
autopush(item) {
if (isString(item)) {
return 0;
}
let styleNames = [];
if (item.style) {
if (Array.isArray(item.style)) {
styleNames = item.style;
} else {
styleNames = [item.style];
}
}
for (let i = 0, l = styleNames.length; i < l; i++) {
this.push(styleNames[i]);
}
// rather than spend significant time making a styleOverrideObject, just add item
this.push(item);
return styleNames.length + 1;
}
/**
* Automatically pushes elements onto the stack, using autopush based on item,
* executes callback and then pops elements back. Returns value returned by callback
*
* @param {object} item - an object with optional style property and/or style overrides
* @param {Function} callback to be called between autopush and pop
* @returns {object} value returned by callback
*/
auto(item, callback) {
let pushedItems = this.autopush(item);
let result = callback();
if (pushedItems > 0) {
this.pop(pushedItems);
}
return result;
}
/**
* Evaluates stack and returns value of a named property
*
* @param {string} property - property name
* @returns {?any} property value or null if not found
*/
getProperty(property) {
if (this.styleOverrides) {
for (let i = this.styleOverrides.length - 1; i >= 0; i--) {
let item = this.styleOverrides[i];
if (isString(item)) {
// named-style-override
let style = this.styleDictionary[item];
if (style && isValue(style[property])) {
return style[property];
}
} else if (isValue(item[property])) {
// style-overrides-object
return item[property];
}
}
}
return this.defaultStyle && this.defaultStyle[property];
}
/**
* @param {object} item
* @param {StyleContextStack} styleContextStack
* @param {string} property
* @param {any} defaultValue
* @returns {any}
*/
static getStyleProperty(item, styleContextStack, property, defaultValue) {
let value;
if (isValue(item[property])) {
// item defines this property
return item[property];
}
if (!styleContextStack) {
return defaultValue;
}
styleContextStack.auto(item, () => {
value = styleContextStack.getProperty(property);
});
return isValue(value) ? value : defaultValue;
}
/**
* @param {object} source
* @param {object} destination
* @returns {object}
*/
static copyStyle(source, destination) {
if (source === void 0) {
source = {};
}
if (destination === void 0) {
destination = {};
}
// TODO: default style to source
for (let key in source) {
if (key != 'text' && source.hasOwnProperty(key)) {
destination[key] = source[key];
}
}
return destination;
}
}
/* harmony default export */ const src_StyleContextStack = (StyleContextStack);
;// ./src/TextBreaker.js
/**
* @param {string} text
* @param {boolean} noWrap
* @returns {Array}
*/
const splitWords = (text, noWrap) => {
let words = [];
if (noWrap) {
words.push({
text: text
});
return words;
}
let breaker = new (linebreaker_default())(text);
let last = 0;
let bk;
while (bk = breaker.nextBreak()) {
let word = text.slice(last, bk.position);
if (bk.required || word.match(/\r?\n$|\r$/)) {
// new line
word = word.replace(/\r?\n$|\r$/, '');
words.push({
text: word,
lineEnd: true
});
} else {
words.push({
text: word
});
}
last = bk.position;
}
return words;
};
/**
* @param {Array} words
* @param {boolean} noWrap
* @returns {?string}
*/
const getFirstWord = (words, noWrap) => {
let word = words[0];
if (word === undefined) {
return null;
}
if (noWrap) {
// text was not wrapped, we need only first word
let tmpWords = splitWords(word.text, false);
if (tmpWords[0] === undefined) {
return null;
}
word = tmpWords[0];
}
return word.text;
};
/**
* @param {Array} words
* @param {boolean} noWrap
* @returns {?string}
*/
const getLastWord = (words, noWrap) => {
let word = words[words.length - 1];
if (word === undefined) {
return null;
}
if (word.lineEnd) {
return null;
}
if (noWrap) {
// text was not wrapped, we need only last word
let tmpWords = splitWords(word.text, false);
if (tmpWords[tmpWords.length - 1] === undefined) {
return null;
}
word = tmpWords[tmpWords.length - 1];
}
return word.text;
};
class TextBreaker {
/**
* @param {string|Array} texts
* @param {StyleContextStack} styleContextStack
* @returns {Array}
*/
getBreaks(texts, styleContextStack) {
let results = [];
if (!Array.isArray(texts)) {
texts = [texts];
}
let lastWord = null;
for (let i = 0, l = texts.length; i < l; i++) {
let item = texts[i];
let style = null;
let words;
let noWrap = src_StyleContextStack.getStyleProperty(item || {}, styleContextStack, 'noWrap', false);
if (isObject(item)) {
if (item._textRef && item._textRef._textNodeRef.text) {
item.text = item._textRef._textNodeRef.text;
}
words = splitWords(item.text, noWrap);
style = src_StyleContextStack.copyStyle(item);
} else {
words = splitWords(item, noWrap);
}
if (lastWord && words.length) {
let firstWord = getFirstWord(words, noWrap);
let wrapWords = splitWords(lastWord + firstWord, false);
if (wrapWords.length === 1) {
results[results.length - 1].noNewLine = true;
}
}
for (let i2 = 0, l2 = words.length; i2 < l2; i2++) {
let result = {
text: words[i2].text
};
if (words[i2].lineEnd) {
result.lineEnd = true;
}
src_StyleContextStack.copyStyle(style, result);
results.push(result);
}
lastWord = null;
if (i + 1 < l) {
lastWord = getLastWord(words, noWrap);
}
}
return results;
}
}
/* harmony default export */ const src_TextBreaker = (TextBreaker);
;// ./src/TextInlines.js
const LEADING = /^(\s)+/g;
const TRAILING = /(\s)+$/g;
/**
* @param {Array} array
* @returns {Array}
*/
const flattenTextArray = array => {
function flatten(array) {
return array.reduce((prev, cur) => {
let current = Array.isArray(cur.text) ? flatten(cur.text) : cur;
let more = [].concat(current).some(Array.isArray);
return prev.concat(more ? flatten(current) : current);
}, []);
}
if (!Array.isArray(array)) {
array = [array];
}
// TODO: Styling in nested text (issue: https://github.com/bpampuch/pdfmake/issues/1174)
array = flatten(array);
return array;
};
/**
* Text measurement utility
*/
class TextInlines {
/**
* @param {object} pdfDocument object is instance of PDFDocument
*/
constructor(pdfDocument) {
this.pdfDocument = pdfDocument;
}
/**
* Converts an array of strings (or inline-definition-objects) into a collection
* of inlines and calculated minWidth/maxWidth and their min/max widths
*
* @param {Array|object} textArray an array of inline-definition-objects (or strings)
* @param {StyleContextStack} styleContextStack current style stack
* @returns {object} collection of inlines, minWidth, maxWidth
*/
buildInlines(textArray, styleContextStack) {
const getTrimmedWidth = item => {
return Math.max(0, item.width - item.leadingCut - item.trailingCut);
};
let minWidth = 0;
let maxWidth = 0;
let currentLineWidth;
let flattenedTextArray = flattenTextArray(textArray);
const textBreaker = new src_TextBreaker();
let breakedText = textBreaker.getBreaks(flattenedTextArray, styleContextStack);
let measuredText = this.measure(breakedText, styleContextStack);
measuredText.forEach(inline => {
minWidth = Math.max(minWidth, getTrimmedWidth(inline));
if (!currentLineWidth) {
currentLineWidth = {
width: 0,
leadingCut: inline.leadingCut,
trailingCut: 0
};
}
currentLineWidth.width += inline.width;
currentLineWidth.trailingCut = inline.trailingCut;
maxWidth = Math.max(maxWidth, getTrimmedWidth(currentLineWidth));
if (inline.lineEnd) {
currentLineWidth = null;
}
});
if (src_StyleContextStack.getStyleProperty({}, styleContextStack, 'noWrap', false)) {
minWidth = maxWidth;
}
return {
items: measuredText,
minWidth: minWidth,
maxWidth: maxWidth
};
}
measure(array, styleContextStack) {
if (array.length) {
let leadingIndent = src_StyleContextStack.getStyleProperty(array[0], styleContextStack, 'leadingIndent', 0);
if (leadingIndent) {
array[0].leadingCut = -leadingIndent;
array[0].leadingIndent = leadingIndent;
}
}
array.forEach(item => {
let font = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'font', 'Roboto');
let bold = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'bold', false);
let italics = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'italics', false);
item.font = this.pdfDocument.provideFont(font, bold, italics);
item.alignment = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'alignment', 'left');
item.fontSize = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'fontSize', 12);
item.fontFeatures = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'fontFeatures', null);
item.characterSpacing = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'characterSpacing', 0);
item.color = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'color', 'black');
item.decoration = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'decoration', null);
item.decorationColor = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'decorationColor', null);
item.decorationStyle = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'decorationStyle', null);
item.background = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'background', null);
item.link = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'link', null);
item.linkToPage = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'linkToPage', null);
item.linkToDestination = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'linkToDestination', null);
item.noWrap = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'noWrap', null);
item.opacity = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'opacity', 1);
item.sup = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'sup', false);
item.sub = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'sub', false);
if (item.sup || item.sub) {
// font size reduction taken from here: https://en.wikipedia.org/wiki/Subscript_and_superscript#Desktop_publishing
item.fontSize *= 0.58;
}
let lineHeight = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'lineHeight', 1);
item.width = this.widthOfText(item.text, item);
item.height = item.font.lineHeight(item.fontSize) * lineHeight;
if (!item.leadingCut) {
item.leadingCut = 0;
}
let preserveLeadingSpaces = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'preserveLeadingSpaces', false);
if (!preserveLeadingSpaces) {
let leadingSpaces = item.text.match(LEADING);
if (leadingSpaces) {
item.leadingCut += this.widthOfText(leadingSpaces[0], item);
}
}
item.trailingCut = 0;
let preserveTrailingSpaces = src_StyleContextStack.getStyleProperty(item, styleContextStack, 'preserveTrailingSpaces', false);
if (!preserveTrailingSpaces) {
let trailingSpaces = item.text.match(TRAILING);
if (trailingSpaces) {
item.trailingCut = this.widthOfText(trailingSpaces[0], item);
}
}
}, this);
return array;
}
/**
* Width of text
*
* @param {string} text
* @param {object} inline
* @returns {number}
*/
widthOfText(text, inline) {
return inline.font.widthOfString(text, inline.fontSize, inline.fontFeatures) + (inline.characterSpacing || 0) * (text.length - 1);
}
/**
* Returns size of the specified string (without breaking it) using the current style
*
* @param {string} text text to be measured
* @param {object} styleContextStack current style stack
* @returns {object} size of the specified string
*/
sizeOfText(text, styleContextStack) {
//TODO: refactor - extract from measure
let fontName = src_StyleContextStack.getStyleProperty({}, styleContextStack, 'font', 'Roboto');
let fontSize = src_StyleContextStack.getStyleProperty({}, styleContextStack, 'fontSize', 12);
let fontFeatures = src_StyleContextStack.getStyleProperty({}, styleContextStack, 'fontFeatures', null);
let bold = src_StyleContextStack.getStyleProperty({}, styleContextStack, 'bold', false);
let italics = src_StyleContextStack.getStyleProperty({}, styleContextStack, 'italics', false);
let lineHeight = src_StyleContextStack.getStyleProperty({}, styleContextStack, 'lineHeight', 1);
let characterSpacing = src_StyleContextStack.getStyleProperty({}, styleContextStack, 'characterSpacing', 0);
let font = this.pdfDocument.provideFont(fontName, bold, italics);
return {
width: this.widthOfText(text, {
font: font,
fontSize: fontSize,
characterSpacing: characterSpacing,
fontFeatures: fontFeatures
}),
height: font.lineHeight(fontSize) * lineHeight,
fontSize: fontSize,
lineHeight: lineHeight,
ascender: font.ascender / 1000 * fontSize,
descender: font.descender / 1000 * fontSize
};
}
/**
* Returns size of the specified rotated string (without breaking it) using the current style
*
* @param {string} text text to be measured
* @param {number} angle
* @param {object} styleContextStack current style stack
* @returns {object} size of the specified string
*/
sizeOfRotatedText(text, angle, styleContextStack) {
let angleRad = angle * Math.PI / -180;
let size = this.sizeOfText(text, styleContextStack);
return {
width: Math.abs(size.height * Math.sin(angleRad)) + Math.abs(size.width * Math.cos(angleRad)),
height: Math.abs(size.width * Math.sin(angleRad)) + Math.abs(size.height * Math.cos(angleRad))
};
}
}
/* harmony default export */ const src_TextInlines = (TextInlines);
;// ./src/columnCalculator.js
function buildColumnWidths(columns, availableWidth, offsetTotal, tableNode) {
if (offsetTotal === void 0) {
offsetTotal = 0;
}
let autoColumns = [];
let autoMin = 0;
let autoMax = 0;
let starColumns = [];
let starMaxMin = 0;
let starMaxMax = 0;
let fixedColumns = [];
let initial_availableWidth = availableWidth;
columns.forEach(column => {
if (isAutoColumn(column)) {
autoColumns.push(column);
autoMin += column._minWidth;
autoMax += column._maxWidth;
} else if (isStarColumn(column)) {
starColumns.push(column);
starMaxMin = Math.max(starMaxMin, column._minWidth);
starMaxMax = Math.max(starMaxMax, column._maxWidth);
} else {
fixedColumns.push(column);
}
});
fixedColumns.forEach((col, colIndex) => {
// width specified as %
if (isString(col.width) && /\d+%/.test(col.width)) {
// In tables we have to take into consideration the reserved width for paddings and borders
let reservedWidth = 0;
if (tableNode) {
const paddingLeft = tableNode._layout.paddingLeft(colIndex, tableNode);
const paddingRight = tableNode._layout.paddingRight(colIndex, tableNode);
const borderLeft = tableNode._layout.vLineWidth(colIndex, tableNode);
const borderRight = tableNode._layout.vLineWidth(colIndex + 1, tableNode);
if (colIndex === 0) {
// first column assumes whole borderLeft and half of border right
reservedWidth = paddingLeft + paddingRight + borderLeft + borderRight / 2;
} else if (colIndex === fixedColumns.length - 1) {
// last column assumes whole borderRight and half of border left
reservedWidth = paddingLeft + paddingRight + borderLeft / 2 + borderRight;
} else {
// Columns in the middle assume half of each border
reservedWidth = paddingLeft + paddingRight + borderLeft / 2 + borderRight / 2;
}
}
const totalAvailableWidth = initial_availableWidth + offsetTotal;
col.width = parseFloat(col.width) * totalAvailableWidth / 100 - reservedWidth;
}
if (col.width < col._minWidth && col.elasticWidth) {
col._calcWidth = col._minWidth;
} else {
col._calcWidth = col.width;
}
availableWidth -= col._calcWidth;
});
// http://www.freesoft.org/CIE/RFC/1942/18.htm
// http://www.w3.org/TR/CSS2/tables.html#width-layout
// http://dev.w3.org/csswg/css3-tables-algorithms/Overview.src.htm
let minW = autoMin + starMaxMin * starColumns.length;
let maxW = autoMax + starMaxMax * starColumns.length;
if (minW >= availableWidth) {
// case 1 - there's no way to fit all columns within available width
// that's actually pretty bad situation with PDF as we have no horizontal scroll
// no easy workaround (unless we decide, in the future, to split single words)
// currently we simply use minWidths for all columns
autoColumns.forEach(col => {
col._calcWidth = col._minWidth;
});
starColumns.forEach(col => {
col._calcWidth = starMaxMin; // starMaxMin already contains padding
});
} else {
if (maxW < availableWidth) {
// case 2 - we can fit rest of the table within available space
autoColumns.forEach(col => {
col._calcWidth = col._maxWidth;
availableWidth -= col._calcWidth;
});
} else {
// maxW is too large, but minW fits within available width
let W = availableWidth - minW;
let D = maxW - minW;
autoColumns.forEach(col => {
let d = col._maxWidth - col._minWidth;
col._calcWidth = col._minWidth + d * W / D;
availableWidth -= col._calcWidth;
});
}
if (starColumns.length > 0) {
let starSize = availableWidth / starColumns.length;
starColumns.forEach(col => {
col._calcWidth = starSize;
});
}
}
}
function isAutoColumn(column) {
return column.width === 'auto';
}
function isStarColumn(column) {
return column.width === null || column.width === undefined || column.width === '*' || column.width === 'star';
}
//TODO: refactor and reuse in measureTable
function measureMinMax(columns) {
let result = {
min: 0,
max: 0
};
let maxStar = {
min: 0,
max: 0
};
let starCount = 0;
for (let i = 0, l = columns.length; i < l; i++) {
let c = columns[i];
if (isStarColumn(c)) {
maxStar.min = Math.max(maxStar.min, c._minWidth);
maxStar.max = Math.max(maxStar.max, c._maxWidth);
starCount++;
} else if (isAutoColumn(c)) {
result.min += c._minWidth;
result.max += c._maxWidth;
} else {
result.min += c.width !== undefined && c.width || c._minWidth;
result.max += c.width !== undefined && c.width || c._maxWidth;
}
}
if (starCount) {
result.min += starCount * maxStar.min;
result.max += starCount * maxStar.max;
}
return result;
}
/**
* Calculates column widths
*/
/* harmony default export */ const columnCalculator = ({
buildColumnWidths: buildColumnWidths,
measureMinMax: measureMinMax,
isAutoColumn: isAutoColumn,
isStarColumn: isStarColumn
});
;// ./src/tableLayouts.js
/*eslint no-unused-vars: ["error", {"args": "none"}]*/
const tableLayouts = {
noBorders: {
hLineWidth(i) {
return 0;
},
vLineWidth(i) {
return 0;
},
paddingLeft(i) {
return i && 4 || 0;
},
paddingRight(i, node) {
return i < node.table.widths.length - 1 ? 4 : 0;
}
},
headerLineOnly: {
hLineWidth(i, node) {
if (i === 0 || i === node.table.body.length) {
return 0;
}
return i === node.table.headerRows ? 2 : 0;
},
vLineWidth(i) {
return 0;
},
paddingLeft(i) {
return i === 0 ? 0 : 8;
},
paddingRight(i, node) {
return i === node.table.widths.length - 1 ? 0 : 8;
}
},
lightHorizontalLines: {
hLineWidth(i, node) {
if (i === 0 || i === node.table.body.length) {
return 0;
}
return i === node.table.headerRows ? 2 : 1;
},
vLineWidth(i) {
return 0;
},
hLineColor(i) {
return i === 1 ? 'black' : '#aaa';
},
paddingLeft(i) {
return i === 0 ? 0 : 8;
},
paddingRight(i, node) {
return i === node.table.widths.length - 1 ? 0 : 8;
}
}
};
const defaultTableLayout = {
hLineWidth(i, node) {
return 1;
},
vLineWidth(i, node) {
return 1;
},
hLineColor(i, node) {
return 'black';
},
vLineColor(i, node) {
return 'black';
},
hLineStyle(i, node) {
return null;
},
vLineStyle(i, node) {
return null;
},
paddingLeft(i, node) {
return 4;
},
paddingRight(i, node) {
return 4;
},
paddingTop(i, node) {
return 2;
},
paddingBottom(i, node) {
return 2;
},
fillColor(i, node) {
return null;
},
fillOpacity(i, node) {
return 1;
},
defaultBorder: true
};
;// ./src/helpers/tools.js
function pack() {
let result = {};
for (let i = 0, l = arguments.length; i < l; i++) {
let obj = i < 0 || arguments.length <= i ? undefined : arguments[i];
if (obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = obj[key];
}
}
}
}
return result;
}
function offsetVector(vector, x, y) {
switch (vector.type) {
case 'ellipse':
case 'rect':
vector.x += x;
vector.y += y;
break;
case 'line':
vector.x1 += x;
vector.x2 += x;
vector.y1 += y;
vector.y2 += y;
break;
case 'polyline':
for (let i = 0, l = vector.points.length; i < l; i++) {
vector.points[i].x += x;
vector.points[i].y += y;
}
break;
}
}
function convertToDynamicContent(staticContent) {
return () =>
// copy to new object
JSON.parse(JSON.stringify(staticContent));
}
;// ./src/qrEnc.js
/*eslint no-unused-vars: ["error", {"args": "none"}]*/
/*eslint no-redeclare: "off"*/
/*eslint no-throw-literal: "off"*/
/* qr.js -- QR code generator in Javascript (revision 2011-01-19)
* Written by Kang Seonghoon <public+qrjs@mearie.org>.
*
* This source code is in the public domain; if your jurisdiction does not
* recognize the public domain the terms of Creative Commons CC0 license
* apply. In the other words, you can always do what you want.
*/
// per-version information (cf. JIS X 0510:2004 pp. 30--36, 71)
//
// [0]: the degree of generator polynomial by ECC levels
// [1]: # of code blocks by ECC levels
// [2]: left-top positions of alignment patterns
//
// the number in this table (in particular, [0]) does not exactly match with
// the numbers in the specficiation. see augumenteccs below for the reason.
var VERSIONS = [null, [[10, 7, 17, 13], [1, 1, 1, 1], []], [[16, 10, 28, 22], [1, 1, 1, 1], [4, 16]], [[26, 15, 22, 18], [1, 1, 2, 2], [4, 20]], [[18, 20, 16, 26], [2, 1, 4, 2], [4, 24]], [[24, 26, 22, 18], [2, 1, 4, 4], [4, 28]], [[16, 18, 28, 24], [4, 2, 4, 4], [4, 32]], [[18, 20, 26, 18], [4, 2, 5, 6], [4, 20, 36]], [[22, 24, 26, 22], [4, 2, 6, 6], [4, 22, 40]], [[22, 30, 24, 20], [5, 2, 8, 8], [4, 24, 44]], [[26, 18, 28, 24], [5, 4, 8, 8], [4, 26, 48]], [[30, 20, 24, 28], [5, 4, 11, 8], [4, 28, 52]], [[22, 24, 28, 26], [8, 4, 11, 10], [4, 30, 56]], [[22, 26, 22, 24], [9, 4, 16, 12], [4, 32, 60]], [[24, 30, 24, 20], [9, 4, 16, 16], [4, 24, 44, 64]], [[24, 22, 24, 30], [10, 6, 18, 12], [4, 24, 46, 68]], [[28, 24, 30, 24], [10, 6, 16, 17], [4, 24, 48, 72]], [[28, 28, 28, 28], [11, 6, 19, 16], [4, 28, 52, 76]], [[26, 30, 28, 28], [13, 6, 21, 18], [4, 28, 54, 80]], [[26, 28, 26, 26], [14, 7, 25, 21], [4, 28, 56, 84]], [[26, 28, 28, 30], [16, 8, 25, 20], [4, 32, 60, 88]], [[26, 28, 30, 28], [17, 8, 25, 23], [4, 26, 48, 70, 92]], [[28, 28, 24, 30], [17, 9, 34, 23], [4, 24, 48, 72, 96]], [[28, 30, 30, 30], [18, 9, 30, 25], [4, 28, 52, 76, 100]], [[28, 30, 30, 30], [20, 10, 32, 27], [4, 26, 52, 78, 104]], [[28, 26, 30, 30], [21, 12, 35, 29], [4, 30, 56, 82, 108]], [[28, 28, 30, 28], [23, 12, 37, 34], [4, 28, 56, 84, 112]], [[28, 30, 30, 30], [25, 12, 40, 34], [4, 32, 60, 88, 116]], [[28, 30, 30, 30], [26, 13, 42, 35], [4, 24, 48, 72, 96, 120]], [[28, 30, 30, 30], [28, 14, 45, 38], [4, 28, 52, 76, 100, 124]], [[28, 30, 30, 30], [29, 15, 48, 40], [4, 24, 50, 76, 102, 128]], [[28, 30, 30, 30], [31, 16, 51, 43], [4, 28, 54, 80, 106, 132]], [[28, 30, 30, 30], [33, 17, 54, 45], [4, 32, 58, 84, 110, 136]], [[28, 30, 30, 30], [35, 18, 57, 48], [4, 28, 56, 84, 112, 140]], [[28, 30, 30, 30], [37, 19, 60, 51], [4, 32, 60, 88, 116, 144]], [[28, 30, 30, 30], [38, 19, 63, 53], [4, 28, 52, 76, 100, 124, 148]], [[28, 30, 30, 30], [40, 20, 66, 56], [4, 22, 48, 74, 100, 126, 152]], [[28, 30, 30, 30], [43, 21, 70, 59], [4, 26, 52, 78, 104, 130, 156]], [[28, 30, 30, 30], [45, 22, 74, 62], [4, 30, 56, 82, 108, 134, 160]], [[28, 30, 30, 30], [47, 24, 77, 65], [4, 24, 52, 80, 108, 136, 164]], [[28, 30, 30, 30], [49, 25, 81, 68], [4, 28, 56, 84, 112, 140, 168]]];
// mode constants (cf. Table 2 in JIS X 0510:2004 p. 16)
var MODE_TERMINATOR = 0;
var MODE_NUMERIC = 1,
MODE_ALPHANUMERIC = 2,
MODE_OCTET = 4,
MODE_KANJI = 8;
// validation regexps
var NUMERIC_REGEXP = /^\d*$/;
var ALPHANUMERIC_REGEXP = /^[A-Za-z0-9 $%*+\-./:]*$/;
var ALPHANUMERIC_OUT_REGEXP = /^[A-Z0-9 $%*+\-./:]*$/;
// ECC levels (cf. Table 22 in JIS X 0510:2004 p. 45)
var ECCLEVEL_L = 1,
ECCLEVEL_M = 0,
ECCLEVEL_Q = 3,
ECCLEVEL_H = 2;
// GF(2^8)-to-integer mapping with a reducing polynomial x^8+x^4+x^3+x^2+1
// invariant: GF256_MAP[GF256_INVMAP[i]] == i for all i in [1,256)
var GF256_MAP = [],
GF256_INVMAP = [-1];
for (var i = 0, v = 1; i < 255; ++i) {
GF256_MAP.push(v);
GF256_INVMAP[v] = i;
v = v * 2 ^ (v >= 128 ? 0x11d : 0);
}
// generator polynomials up to degree 30
// (should match with polynomials in JIS X 0510:2004 Appendix A)
//
// generator polynomial of degree K is product of (x-\alpha^0), (x-\alpha^1),
// ..., (x-\alpha^(K-1)). by convention, we omit the K-th coefficient (always 1)
// from the result; also other coefficients are written in terms of the exponent
// to \alpha to avoid the redundant calculation. (see also calculateecc below.)
var GF256_GENPOLY = [[]];
for (var i = 0; i < 30; ++i) {
var prevpoly = GF256_GENPOLY[i],
poly = [];
for (var j = 0; j <= i; ++j) {
var a = j < i ? GF256_MAP[prevpoly[j]] : 0;
var b = GF256_MAP[(i + (prevpoly[j - 1] || 0)) % 255];
poly.push(GF256_INVMAP[a ^ b]);
}
GF256_GENPOLY.push(poly);
}
// alphanumeric character mapping (cf. Table 5 in JIS X 0510:2004 p. 19)
var ALPHANUMERIC_MAP = {};
for (var i = 0; i < 45; ++i) {
ALPHANUMERIC_MAP['0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.charAt(i)] = i;
}
// mask functions in terms of row # and column #
// (cf. Table 20 in JIS X 0510:2004 p. 42)
/*jshint unused: false */
var MASKFUNCS = [function (i, j) {
return (i + j) % 2 === 0;
}, function (i, j) {
return i % 2 === 0;
}, function (i, j) {
return j % 3 === 0;
}, function (i, j) {
return (i + j) % 3 === 0;
}, function (i, j) {
return ((i / 2 | 0) + (j / 3 | 0)) % 2 === 0;
}, function (i, j) {
return i * j % 2 + i * j % 3 === 0;
}, function (i, j) {
return (i * j % 2 + i * j % 3) % 2 === 0;
}, function (i, j) {
return ((i + j) % 2 + i * j % 3) % 2 === 0;
}];
// returns true when the version information has to be embeded.
var needsverinfo = function (ver) {
return ver > 6;
};
// returns the size of entire QR code for given version.
var getsizebyver = function (ver) {
return 4 * ver + 17;
};
// returns the number of bits available for code words in this version.
var nfullbits = function (ver) {
/*
* |<--------------- n --------------->|
* | |<----- n-17 ---->| |
* +-------+ ///+-------+ ----
* | | ///| | ^
* | 9x9 | @@@@@ ///| 9x8 | |
* | | # # # @5x5@ # # # | | |
* +-------+ @@@@@ +-------+ |
* # ---|
* ^ |
* # |
* @@@@@ @@@@@ @@@@@ | n
* @5x5@ @5x5@ @5x5@ n-17
* @@@@@ @@@@@ @@@@@ | |
* # | |
* ////// v |
* //////# ---|
* +-------+ @@@@@ @@@@@ |
* | | @5x5@ @5x5@ |
* | 8x9 | @@@@@ @@@@@ |
* | | v
* +-------+ ----
*
* when the entire code has n^2 modules and there are m^2-3 alignment
* patterns, we have:
* - 225 (= 9x9 + 9x8 + 8x9) modules for finder patterns and
* format information;
* - 2n-34 (= 2(n-17)) modules for timing patterns;
* - 36 (= 3x6 + 6x3) modules for version information, if any;
* - 25m^2-75 (= (m^2-3)(5x5)) modules for alignment patterns
* if any, but 10m-20 (= 2(m-2)x5) of them overlaps with
* timing patterns.
*/
var v = VERSIONS[ver];
var nbits = 16 * ver * ver + 128 * ver + 64; // finder, timing and format info.
if (needsverinfo(ver)) nbits -= 36; // version information
if (v[2].length) {
// alignment patterns
nbits -= 25 * v[2].length * v[2].length - 10 * v[2].length - 55;
}
return nbits;
};
// returns the number of bits available for data portions (i.e. excludes ECC
// bits but includes mode and length bits) in this version and ECC level.
var ndatabits = function (ver, ecclevel) {
var nbits = nfullbits(ver) & ~7; // no sub-octet code words
var v = VERSIONS[ver];
nbits -= 8 * v[0][ecclevel] * v[1][ecclevel]; // ecc bits
return nbits;
};
// returns the number of bits required for the length of data.
// (cf. Table 3 in JIS X 0510:2004 p. 16)
var ndatalenbits = function (ver, mode) {
switch (mode) {
case MODE_NUMERIC:
return ver < 10 ? 10 : ver < 27 ? 12 : 14;
case MODE_ALPHANUMERIC:
return ver < 10 ? 9 : ver < 27 ? 11 : 13;
case MODE_OCTET:
return ver < 10 ? 8 : 16;
case MODE_KANJI:
return ver < 10 ? 8 : ver < 27 ? 10 : 12;
}
};
// returns the maximum length of data possible in given configuration.
var getmaxdatalen = function (ver, mode, ecclevel) {
var nbits = ndatabits(ver, ecclevel) - 4 - ndatalenbits(ver, mode); // 4 for mode bits
switch (mode) {
case MODE_NUMERIC: