fix: typescript options type definition (#1861)

This commit is contained in:
Niklas von Hertzen 2019-05-29 21:11:50 -07:00 committed by GitHub
parent 28dc05c4a3
commit cae44a6f0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 54 deletions

View File

@ -61,7 +61,7 @@ export class CacheStorage {
} }
} }
interface ResourceOptions { export interface ResourceOptions {
imageTimeout: number; imageTimeout: number;
useCORS: boolean; useCORS: boolean;
allowTaint: boolean; allowTaint: boolean;

View File

@ -4,25 +4,22 @@ import {Parser} from './css/syntax/parser';
import {CloneOptions, DocumentCloner} from './dom/document-cloner'; import {CloneOptions, DocumentCloner} from './dom/document-cloner';
import {isBodyElement, isHTMLElement, parseTree} from './dom/node-parser'; import {isBodyElement, isHTMLElement, parseTree} from './dom/node-parser';
import {Logger} from './core/logger'; import {Logger} from './core/logger';
import {CacheStorage} from './core/cache-storage'; import {CacheStorage, ResourceOptions} from './core/cache-storage';
import {CanvasRenderer, RenderOptions} from './render/canvas/canvas-renderer'; import {CanvasRenderer, RenderOptions} from './render/canvas/canvas-renderer';
import {ForeignObjectRenderer} from './render/canvas/foreignobject-renderer'; import {ForeignObjectRenderer} from './render/canvas/foreignobject-renderer';
export type Options = CloneOptions & export type Options = CloneOptions &
RenderOptions & { RenderOptions &
allowTaint: boolean; ResourceOptions & {
backgroundColor: string; backgroundColor: string;
foreignObjectRendering: boolean; foreignObjectRendering: boolean;
imageTimeout: number;
logging: boolean; logging: boolean;
proxy?: string;
removeContainer?: boolean; removeContainer?: boolean;
useCORS: boolean;
}; };
const parseColor = (value: string): Color => color.parse(Parser.create(value).parseComponentValue()); const parseColor = (value: string): Color => color.parse(Parser.create(value).parseComponentValue());
const html2canvas = (element: HTMLElement, options: Options): Promise<HTMLCanvasElement> => { const html2canvas = (element: HTMLElement, options: Partial<Options> = {}): Promise<HTMLCanvasElement> => {
return renderElement(element, options); return renderElement(element, options);
}; };
@ -30,7 +27,7 @@ export default html2canvas;
CacheStorage.setContext(window); CacheStorage.setContext(window);
const renderElement = async (element: HTMLElement, opts: Options): Promise<HTMLCanvasElement> => { const renderElement = async (element: HTMLElement, opts: Partial<Options>): Promise<HTMLCanvasElement> => {
const ownerDocument = element.ownerDocument; const ownerDocument = element.ownerDocument;
if (!ownerDocument) { if (!ownerDocument) {
@ -43,50 +40,43 @@ const renderElement = async (element: HTMLElement, opts: Options): Promise<HTMLC
throw new Error(`Document is not attached to a Window`); throw new Error(`Document is not attached to a Window`);
} }
const defaultOptions = { const instanceName = (Math.round(Math.random() * 1000) + Date.now()).toString(16);
const {width, height, left, top} =
isBodyElement(element) || isHTMLElement(element) ? parseDocumentSize(ownerDocument) : parseBounds(element);
const defaultResourceOptions = {
allowTaint: false, allowTaint: false,
backgroundColor: '#ffffff',
imageTimeout: 15000, imageTimeout: 15000,
logging: true,
proxy: undefined, proxy: undefined,
useCORS: false
};
const resourceOptions: ResourceOptions = {...defaultResourceOptions, ...opts};
const defaultOptions = {
backgroundColor: '#ffffff',
cache: opts.cache ? opts.cache : CacheStorage.create(instanceName, resourceOptions),
logging: true,
removeContainer: true, removeContainer: true,
foreignObjectRendering: false, foreignObjectRendering: false,
scale: defaultView.devicePixelRatio || 1, scale: defaultView.devicePixelRatio || 1,
useCORS: false,
windowWidth: defaultView.innerWidth, windowWidth: defaultView.innerWidth,
windowHeight: defaultView.innerHeight, windowHeight: defaultView.innerHeight,
scrollX: defaultView.pageXOffset, scrollX: defaultView.pageXOffset,
scrollY: defaultView.pageYOffset scrollY: defaultView.pageYOffset,
x: left,
y: top,
width: Math.ceil(width),
height: Math.ceil(height),
id: instanceName
}; };
const options: Options = {...defaultOptions, ...opts}; const options: Options = {...defaultOptions, ...resourceOptions, ...opts};
const windowBounds = new Bounds(options.scrollX, options.scrollY, options.windowWidth, options.windowHeight); const windowBounds = new Bounds(options.scrollX, options.scrollY, options.windowWidth, options.windowHeight);
// http://www.w3.org/TR/css3-background/#special-backgrounds
const documentBackgroundColor = ownerDocument.documentElement
? parseColor(getComputedStyle(ownerDocument.documentElement).backgroundColor as string)
: COLORS.TRANSPARENT;
const bodyBackgroundColor = ownerDocument.body
? parseColor(getComputedStyle(ownerDocument.body).backgroundColor as string)
: COLORS.TRANSPARENT;
const backgroundColor =
element === ownerDocument.documentElement
? isTransparent(documentBackgroundColor)
? isTransparent(bodyBackgroundColor)
? options.backgroundColor
? parseColor(options.backgroundColor)
: null
: bodyBackgroundColor
: documentBackgroundColor
: options.backgroundColor
? parseColor(options.backgroundColor)
: null;
const instanceName = (Math.round(Math.random() * 1000) + Date.now()).toString(16);
Logger.create(instanceName); Logger.create(instanceName);
const cache = CacheStorage.create(instanceName, options);
Logger.getInstance(instanceName).debug(`Starting document clone`); Logger.getInstance(instanceName).debug(`Starting document clone`);
const documentCloner = new DocumentCloner(element, { const documentCloner = new DocumentCloner(element, {
id: instanceName, id: instanceName,
@ -102,22 +92,37 @@ const renderElement = async (element: HTMLElement, opts: Options): Promise<HTMLC
const container = await documentCloner.toIFrame(ownerDocument, windowBounds); const container = await documentCloner.toIFrame(ownerDocument, windowBounds);
const {width, height, left, top} = // http://www.w3.org/TR/css3-background/#special-backgrounds
isBodyElement(clonedElement) || isHTMLElement(clonedElement) const documentBackgroundColor = ownerDocument.documentElement
? parseDocumentSize(ownerDocument) ? parseColor(getComputedStyle(ownerDocument.documentElement).backgroundColor as string)
: parseBounds(clonedElement); : COLORS.TRANSPARENT;
const bodyBackgroundColor = ownerDocument.body
? parseColor(getComputedStyle(ownerDocument.body).backgroundColor as string)
: COLORS.TRANSPARENT;
const bgColor = opts.backgroundColor;
const defaultBackgroundColor = typeof bgColor === 'string' ? parseColor(bgColor) : 0xffffffff;
const backgroundColor =
element === ownerDocument.documentElement
? isTransparent(documentBackgroundColor)
? isTransparent(bodyBackgroundColor)
? defaultBackgroundColor
: bodyBackgroundColor
: documentBackgroundColor
: defaultBackgroundColor;
const renderOptions = { const renderOptions = {
id: instanceName, id: instanceName,
cache, cache: options.cache,
backgroundColor, backgroundColor,
scale: options.scale, scale: options.scale,
x: typeof options.x === 'number' ? options.x : left, x: options.x,
y: typeof options.y === 'number' ? options.y : top, y: options.y,
scrollX: options.scrollX, scrollX: options.scrollX,
scrollY: options.scrollY, scrollY: options.scrollY,
width: typeof options.width === 'number' ? options.width : Math.ceil(width), width: options.width,
height: typeof options.height === 'number' ? options.height : Math.ceil(height), height: options.height,
windowWidth: options.windowWidth, windowWidth: options.windowWidth,
windowHeight: options.windowHeight windowHeight: options.windowHeight
}; };
@ -131,7 +136,7 @@ const renderElement = async (element: HTMLElement, opts: Options): Promise<HTMLC
} else { } else {
Logger.getInstance(instanceName).debug(`Document cloned, using computed rendering`); Logger.getInstance(instanceName).debug(`Document cloned, using computed rendering`);
CacheStorage.attachInstance(cache); CacheStorage.attachInstance(options.cache);
Logger.getInstance(instanceName).debug(`Starting DOM parsing`); Logger.getInstance(instanceName).debug(`Starting DOM parsing`);
const root = parseTree(clonedElement); const root = parseTree(clonedElement);
CacheStorage.detachInstance(); CacheStorage.detachInstance();

View File

@ -39,11 +39,14 @@ import {SelectElementContainer} from '../../dom/elements/select-element-containe
import {IFrameElementContainer} from '../../dom/replaced-elements/iframe-element-container'; import {IFrameElementContainer} from '../../dom/replaced-elements/iframe-element-container';
import {TextShadow} from '../../css/property-descriptors/text-shadow'; import {TextShadow} from '../../css/property-descriptors/text-shadow';
export type RenderConfigurations = RenderOptions & {
backgroundColor: Color | null;
};
export interface RenderOptions { export interface RenderOptions {
id: string; id: string;
scale: number; scale: number;
canvas?: HTMLCanvasElement; canvas?: HTMLCanvasElement;
backgroundColor: Color | null;
x: number; x: number;
y: number; y: number;
scrollX: number; scrollX: number;
@ -60,11 +63,11 @@ const MASK_OFFSET = 10000;
export class CanvasRenderer { export class CanvasRenderer {
canvas: HTMLCanvasElement; canvas: HTMLCanvasElement;
ctx: CanvasRenderingContext2D; ctx: CanvasRenderingContext2D;
options: RenderOptions; options: RenderConfigurations;
private readonly _activeEffects: IElementEffect[] = []; private readonly _activeEffects: IElementEffect[] = [];
private readonly fontMetrics: FontMetrics; private readonly fontMetrics: FontMetrics;
constructor(options: RenderOptions) { constructor(options: RenderConfigurations) {
this.canvas = options.canvas ? options.canvas : document.createElement('canvas'); this.canvas = options.canvas ? options.canvas : document.createElement('canvas');
this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D; this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D;
this.options = options; this.options = options;

View File

@ -1,4 +1,4 @@
import {RenderOptions} from './canvas-renderer'; import {RenderConfigurations} from './canvas-renderer';
import {Logger} from '../../core/logger'; import {Logger} from '../../core/logger';
import {createForeignObjectSVG} from '../../core/features'; import {createForeignObjectSVG} from '../../core/features';
import {asString} from '../../css/types/color'; import {asString} from '../../css/types/color';
@ -6,9 +6,9 @@ import {asString} from '../../css/types/color';
export class ForeignObjectRenderer { export class ForeignObjectRenderer {
canvas: HTMLCanvasElement; canvas: HTMLCanvasElement;
ctx: CanvasRenderingContext2D; ctx: CanvasRenderingContext2D;
options: RenderOptions; options: RenderConfigurations;
constructor(options: RenderOptions) { constructor(options: RenderConfigurations) {
this.canvas = options.canvas ? options.canvas : document.createElement('canvas'); this.canvas = options.canvas ? options.canvas : document.createElement('canvas');
this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D; this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D;
this.options = options; this.options = options;