UNPKG

pagedjs

Version:

Chunks up a document into paged media flows and applies print styles

251 lines (232 loc) 8.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CSSValueToString = CSSValueToString; exports.UUID = UUID; exports.attr = attr; exports.defer = defer; exports.findCssSelector = findCssSelector; exports.getBoundingClientRect = getBoundingClientRect; exports.getClientRects = getClientRects; exports.positionInNodeList = positionInNodeList; exports.querySelectorEscape = querySelectorEscape; exports.requestIdleCallback = void 0; function getBoundingClientRect(element) { if (!element) { return; } var rect; if (typeof element.getBoundingClientRect !== "undefined") { rect = element.getBoundingClientRect(); } else { var range = document.createRange(); range.selectNode(element); rect = range.getBoundingClientRect(); } return rect; } function getClientRects(element) { if (!element) { return; } var rect; if (typeof element.getClientRects !== "undefined") { rect = element.getClientRects(); } else { var range = document.createRange(); range.selectNode(element); rect = range.getClientRects(); } return rect; } /** * Generates a UUID * based on: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript * @returns {string} uuid */ function UUID() { var d = new Date().getTime(); if (typeof performance !== "undefined" && typeof performance.now === "function") { d += performance.now(); //use high-precision timer if available } return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c === "x" ? r : r & 0x3 | 0x8).toString(16); }); } // From: https://hg.mozilla.org/mozilla-central/file/tip/toolkit/modules/css-selector.js#l52 /** * Find the position of [element] in [nodeList]. * @param {Element} element to check * @param {NodeList} nodeList to find in * @returns {int} an index of the match, or -1 if there is no match */ function positionInNodeList(element, nodeList) { for (var i = 0; i < nodeList.length; i++) { if (element === nodeList[i]) { return i; } } return -1; } /** * Find a unique CSS selector for a given element * @param {Element} ele to check * @returns {string} a string such that ele.ownerDocument.querySelector(reply) === ele * and ele.ownerDocument.querySelectorAll(reply).length === 1 */ function findCssSelector(ele) { var document = ele.ownerDocument; // Fred: commented out to allow for parsing in fragments // if (!document || !document.contains(ele)) { // throw new Error("findCssSelector received element not inside document"); // } var cssEscape = window.CSS.escape; // document.querySelectorAll("#id") returns multiple if elements share an ID if (ele.id && document.querySelectorAll("#" + cssEscape(ele.id)).length === 1) { return "#" + cssEscape(ele.id); } // Inherently unique by tag name var tagName = ele.localName; if (tagName === "html") { return "html"; } if (tagName === "head") { return "head"; } if (tagName === "body") { return "body"; } // We might be able to find a unique class name var selector, index, matches; if (ele.classList.length > 0) { for (var i = 0; i < ele.classList.length; i++) { // Is this className unique by itself? selector = "." + cssEscape(ele.classList.item(i)); matches = document.querySelectorAll(selector); if (matches.length === 1) { return selector; } // Maybe it's unique with a tag name? selector = cssEscape(tagName) + selector; matches = document.querySelectorAll(selector); if (matches.length === 1) { return selector; } // Maybe it's unique using a tag name and nth-child index = positionInNodeList(ele, ele.parentNode.children) + 1; selector = selector + ":nth-child(" + index + ")"; matches = document.querySelectorAll(selector); if (matches.length === 1) { return selector; } } } // Not unique enough yet. As long as it's not a child of the document, // continue recursing up until it is unique enough. if (ele.parentNode !== document && ele.parentNode.nodeType === 1) { index = positionInNodeList(ele, ele.parentNode.children) + 1; selector = findCssSelector(ele.parentNode) + " > " + cssEscape(tagName) + ":nth-child(" + index + ")"; } return selector; } function attr(element, attributes) { for (var i = 0; i < attributes.length; i++) { if (element.hasAttribute(attributes[i])) { return element.getAttribute(attributes[i]); } } } /* Based on by https://mths.be/cssescape v1.5.1 by @mathias | MIT license * Allows # and . */ function querySelectorEscape(value) { if (arguments.length == 0) { throw new TypeError("`CSS.escape` requires an argument."); } var string = String(value); var length = string.length; var index = -1; var codeUnit; var result = ""; var firstCodeUnit = string.charCodeAt(0); while (++index < length) { codeUnit = string.charCodeAt(index); // Note: there’s no need to special-case astral symbols, surrogate // pairs, or lone surrogates. // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER // (U+FFFD). if (codeUnit == 0x0000) { result += "\uFFFD"; continue; } if ( // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is // U+007F, […] codeUnit >= 0x0001 && codeUnit <= 0x001F || codeUnit == 0x007F || // If the character is the first character and is in the range [0-9] // (U+0030 to U+0039), […] index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039 || // If the character is the second character and is in the range [0-9] // (U+0030 to U+0039) and the first character is a `-` (U+002D), […] index == 1 && codeUnit >= 0x0030 && codeUnit <= 0x0039 && firstCodeUnit == 0x002D) { // https://drafts.csswg.org/cssom/#escape-a-character-as-code-point result += "\\" + codeUnit.toString(16) + " "; continue; } if ( // If the character is the first character and is a `-` (U+002D), and // there is no second character, […] index == 0 && length == 1 && codeUnit == 0x002D) { result += "\\" + string.charAt(index); continue; } // support for period character in id if (codeUnit == 0x002E) { if (string.charAt(0) == "#") { result += "\\."; continue; } } // If the character is not handled by one of the above rules and is // greater than or equal to U+0080, is `-` (U+002D) or `_` (U+005F), or // is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to // U+005A), or [a-z] (U+0061 to U+007A), […] if (codeUnit >= 0x0080 || codeUnit == 0x002D || codeUnit == 0x005F || codeUnit == 35 || // Allow # codeUnit == 46 || // Allow . codeUnit >= 0x0030 && codeUnit <= 0x0039 || codeUnit >= 0x0041 && codeUnit <= 0x005A || codeUnit >= 0x0061 && codeUnit <= 0x007A) { // the character itself result += string.charAt(index); continue; } // Otherwise, the escaped character. // https://drafts.csswg.org/cssom/#escape-a-character result += "\\" + string.charAt(index); } return result; } /** * Creates a new pending promise and provides methods to resolve or reject it. * From: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred#backwards_forwards_compatible * @returns {object} defered */ function defer() { var _this = this; this.resolve = null; this.reject = null; this.id = UUID(); this.promise = new Promise(function (resolve, reject) { _this.resolve = resolve; _this.reject = reject; }); Object.freeze(this); } var requestIdleCallback = typeof window !== "undefined" && ("requestIdleCallback" in window ? window.requestIdleCallback : window.requestAnimationFrame); exports.requestIdleCallback = requestIdleCallback; function CSSValueToString(obj) { return obj.value + (obj.unit || ""); }