UNPKG

pdfmake

Version:

Client/server side PDF printing in pure JavaScript

176 lines (147 loc) 4.63 kB
import { isString, isValue } from './helpers/variableType'; /** * 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 = {}) { 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 = 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 = {}) { // TODO: default style to source for (let key in source) { if (key != 'text' && source.hasOwnProperty(key)) { destination[key] = source[key]; } } return destination; } } export default StyleContextStack;