UNPKG

html2canvas-pro

Version:

Screenshots with JavaScript. Next generation!

128 lines 6.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.html2canvas = void 0; const bounds_1 = require("./css/layout/bounds"); const color_1 = require("./css/types/color"); const color_utilities_1 = require("./css/types/color-utilities"); const document_cloner_1 = require("./dom/document-cloner"); const node_parser_1 = require("./dom/node-parser"); const cache_storage_1 = require("./core/cache-storage"); const canvas_renderer_1 = require("./render/canvas/canvas-renderer"); const foreignobject_renderer_1 = require("./render/canvas/foreignobject-renderer"); const context_1 = require("./core/context"); const html2canvas = (element, options = {}) => { return renderElement(element, options); }; exports.html2canvas = html2canvas; exports.default = html2canvas; if (typeof window !== 'undefined') { cache_storage_1.CacheStorage.setContext(window); } const renderElement = async (element, opts) => { if (!element || typeof element !== 'object') { return Promise.reject('Invalid element provided as first argument'); } const ownerDocument = element.ownerDocument; if (!ownerDocument) { throw new Error(`Element is not attached to a Document`); } const defaultView = ownerDocument.defaultView; if (!defaultView) { throw new Error(`Document is not attached to a Window`); } const resourceOptions = { allowTaint: opts.allowTaint ?? false, imageTimeout: opts.imageTimeout ?? 15000, proxy: opts.proxy, useCORS: opts.useCORS ?? false, customIsSameOrigin: opts.customIsSameOrigin }; const contextOptions = { logging: opts.logging ?? true, cache: opts.cache, ...resourceOptions }; const windowOptions = { windowWidth: opts.windowWidth ?? defaultView.innerWidth, windowHeight: opts.windowHeight ?? defaultView.innerHeight, scrollX: opts.scrollX ?? defaultView.pageXOffset, scrollY: opts.scrollY ?? defaultView.pageYOffset }; const windowBounds = new bounds_1.Bounds(windowOptions.scrollX, windowOptions.scrollY, windowOptions.windowWidth, windowOptions.windowHeight); const context = new context_1.Context(contextOptions, windowBounds); const foreignObjectRendering = opts.foreignObjectRendering ?? false; const cloneOptions = { allowTaint: opts.allowTaint ?? false, onclone: opts.onclone, ignoreElements: opts.ignoreElements, inlineImages: foreignObjectRendering, copyStyles: foreignObjectRendering }; context.logger.debug(`Starting document clone with size ${windowBounds.width}x${windowBounds.height} scrolled to ${-windowBounds.left},${-windowBounds.top}`); const documentCloner = new document_cloner_1.DocumentCloner(context, element, cloneOptions); const clonedElement = documentCloner.clonedReferenceElement; if (!clonedElement) { return Promise.reject(`Unable to find element in cloned iframe`); } const container = await documentCloner.toIFrame(ownerDocument, windowBounds); const { width, height, left, top } = (0, node_parser_1.isBodyElement)(clonedElement) || (0, node_parser_1.isHTMLElement)(clonedElement) ? (0, bounds_1.parseDocumentSize)(clonedElement.ownerDocument) : (0, bounds_1.parseBounds)(context, clonedElement); const backgroundColor = parseBackgroundColor(context, clonedElement, opts.backgroundColor); const renderOptions = { canvas: opts.canvas, backgroundColor, scale: opts.scale ?? defaultView.devicePixelRatio ?? 1, x: (opts.x ?? 0) + left, y: (opts.y ?? 0) + top, width: opts.width ?? Math.ceil(width), height: opts.height ?? Math.ceil(height) }; let canvas; if (foreignObjectRendering) { context.logger.debug(`Document cloned, using foreign object rendering`); const renderer = new foreignobject_renderer_1.ForeignObjectRenderer(context, renderOptions); canvas = await renderer.render(clonedElement); } else { context.logger.debug(`Document cloned, element located at ${left},${top} with size ${width}x${height} using computed rendering`); context.logger.debug(`Starting DOM parsing`); const root = (0, node_parser_1.parseTree)(context, clonedElement); if (backgroundColor === root.styles.backgroundColor) { root.styles.backgroundColor = color_1.COLORS.TRANSPARENT; } context.logger.debug(`Starting renderer for element at ${renderOptions.x},${renderOptions.y} with size ${renderOptions.width}x${renderOptions.height}`); const renderer = new canvas_renderer_1.CanvasRenderer(context, renderOptions); canvas = await renderer.render(root); } if (opts.removeContainer ?? true) { if (!document_cloner_1.DocumentCloner.destroy(container)) { context.logger.error(`Cannot detach cloned iframe as it is not in the DOM anymore`); } } context.logger.debug(`Finished rendering`); return canvas; }; const parseBackgroundColor = (context, element, backgroundColorOverride) => { const ownerDocument = element.ownerDocument; // http://www.w3.org/TR/css3-background/#special-backgrounds const documentBackgroundColor = ownerDocument.documentElement ? (0, color_1.parseColor)(context, getComputedStyle(ownerDocument.documentElement).backgroundColor) : color_1.COLORS.TRANSPARENT; const bodyBackgroundColor = ownerDocument.body ? (0, color_1.parseColor)(context, getComputedStyle(ownerDocument.body).backgroundColor) : color_1.COLORS.TRANSPARENT; const defaultBackgroundColor = typeof backgroundColorOverride === 'string' ? (0, color_1.parseColor)(context, backgroundColorOverride) : backgroundColorOverride === null ? color_1.COLORS.TRANSPARENT : 0xffffffff; return element === ownerDocument.documentElement ? (0, color_utilities_1.isTransparent)(documentBackgroundColor) ? (0, color_utilities_1.isTransparent)(bodyBackgroundColor) ? defaultBackgroundColor : bodyBackgroundColor : documentBackgroundColor : defaultBackgroundColor; }; //# sourceMappingURL=index.js.map