mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
feat: add support for data-html2canvas-debug property for debugging (#2658)
This commit is contained in:
parent
b482725994
commit
cd0d7258c3
29
src/core/debugger.ts
Normal file
29
src/core/debugger.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
const elementDebuggerAttribute = 'data-html2canvas-debug';
|
||||||
|
export const enum DebuggerType {
|
||||||
|
NONE,
|
||||||
|
ALL,
|
||||||
|
CLONE,
|
||||||
|
PARSE,
|
||||||
|
RENDER
|
||||||
|
}
|
||||||
|
|
||||||
|
const getElementDebugType = (element: Element): DebuggerType => {
|
||||||
|
const attribute = element.getAttribute(elementDebuggerAttribute);
|
||||||
|
switch (attribute) {
|
||||||
|
case 'all':
|
||||||
|
return DebuggerType.ALL;
|
||||||
|
case 'clone':
|
||||||
|
return DebuggerType.CLONE;
|
||||||
|
case 'parse':
|
||||||
|
return DebuggerType.PARSE;
|
||||||
|
case 'render':
|
||||||
|
return DebuggerType.RENDER;
|
||||||
|
default:
|
||||||
|
return DebuggerType.NONE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isDebugging = (element: Element, type: Omit<DebuggerType, DebuggerType.NONE>): boolean => {
|
||||||
|
const elementType = getElementDebugType(element);
|
||||||
|
return elementType === DebuggerType.ALL || type === elementType;
|
||||||
|
};
|
@ -20,6 +20,7 @@ import {LIST_STYLE_TYPE, listStyleType} from '../css/property-descriptors/list-s
|
|||||||
import {CSSParsedCounterDeclaration, CSSParsedPseudoDeclaration} from '../css/index';
|
import {CSSParsedCounterDeclaration, CSSParsedPseudoDeclaration} from '../css/index';
|
||||||
import {getQuote} from '../css/property-descriptors/quotes';
|
import {getQuote} from '../css/property-descriptors/quotes';
|
||||||
import {Context} from '../core/context';
|
import {Context} from '../core/context';
|
||||||
|
import {DebuggerType, isDebugging} from '../core/debugger';
|
||||||
|
|
||||||
export interface CloneOptions {
|
export interface CloneOptions {
|
||||||
ignoreElements?: (element: Element) => boolean;
|
ignoreElements?: (element: Element) => boolean;
|
||||||
@ -136,6 +137,9 @@ export class DocumentCloner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createElementClone<T extends HTMLElement | SVGElement>(node: T): HTMLElement | SVGElement {
|
createElementClone<T extends HTMLElement | SVGElement>(node: T): HTMLElement | SVGElement {
|
||||||
|
if (isDebugging(node, DebuggerType.CLONE)) {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
if (isCanvasElement(node)) {
|
if (isCanvasElement(node)) {
|
||||||
return this.createCanvasClone(node);
|
return this.createCanvasClone(node);
|
||||||
}
|
}
|
||||||
|
@ -3,24 +3,27 @@ import {TextContainer} from './text-container';
|
|||||||
import {Bounds, parseBounds} from '../css/layout/bounds';
|
import {Bounds, parseBounds} from '../css/layout/bounds';
|
||||||
import {isHTMLElementNode} from './node-parser';
|
import {isHTMLElementNode} from './node-parser';
|
||||||
import {Context} from '../core/context';
|
import {Context} from '../core/context';
|
||||||
|
import {DebuggerType, isDebugging} from '../core/debugger';
|
||||||
|
|
||||||
export const enum FLAGS {
|
export const enum FLAGS {
|
||||||
CREATES_STACKING_CONTEXT = 1 << 1,
|
CREATES_STACKING_CONTEXT = 1 << 1,
|
||||||
CREATES_REAL_STACKING_CONTEXT = 1 << 2,
|
CREATES_REAL_STACKING_CONTEXT = 1 << 2,
|
||||||
IS_LIST_OWNER = 1 << 3
|
IS_LIST_OWNER = 1 << 3,
|
||||||
|
DEBUG_RENDER = 1 << 4
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ElementContainer {
|
export class ElementContainer {
|
||||||
readonly styles: CSSParsedDeclaration;
|
readonly styles: CSSParsedDeclaration;
|
||||||
readonly textNodes: TextContainer[];
|
readonly textNodes: TextContainer[] = [];
|
||||||
readonly elements: ElementContainer[];
|
readonly elements: ElementContainer[] = [];
|
||||||
bounds: Bounds;
|
bounds: Bounds;
|
||||||
flags: number;
|
flags = 0;
|
||||||
|
|
||||||
constructor(protected readonly context: Context, element: Element) {
|
constructor(protected readonly context: Context, element: Element) {
|
||||||
|
if (isDebugging(element, DebuggerType.PARSE)) {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
this.styles = new CSSParsedDeclaration(context, window.getComputedStyle(element, null));
|
this.styles = new CSSParsedDeclaration(context, window.getComputedStyle(element, null));
|
||||||
this.textNodes = [];
|
|
||||||
this.elements = [];
|
|
||||||
|
|
||||||
if (isHTMLElementNode(element)) {
|
if (isHTMLElementNode(element)) {
|
||||||
if (this.styles.animationDuration.some((duration) => duration > 0)) {
|
if (this.styles.animationDuration.some((duration) => duration > 0)) {
|
||||||
@ -37,6 +40,9 @@ export class ElementContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.bounds = parseBounds(this.context, element);
|
this.bounds = parseBounds(this.context, element);
|
||||||
this.flags = 0;
|
|
||||||
|
if (isDebugging(element, DebuggerType.RENDER)) {
|
||||||
|
this.flags |= FLAGS.DEBUG_RENDER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {ElementPaint, parseStackingContexts, StackingContext} from '../stacking-context';
|
import {ElementPaint, parseStackingContexts, StackingContext} from '../stacking-context';
|
||||||
import {asString, Color, isTransparent} from '../../css/types/color';
|
import {asString, Color, isTransparent} from '../../css/types/color';
|
||||||
import {ElementContainer} from '../../dom/element-container';
|
import {ElementContainer, FLAGS} from '../../dom/element-container';
|
||||||
import {BORDER_STYLE} from '../../css/property-descriptors/border-style';
|
import {BORDER_STYLE} from '../../css/property-descriptors/border-style';
|
||||||
import {CSSParsedDeclaration} from '../../css/index';
|
import {CSSParsedDeclaration} from '../../css/index';
|
||||||
import {TextContainer} from '../../dom/text-container';
|
import {TextContainer} from '../../dom/text-container';
|
||||||
@ -135,6 +135,10 @@ export class CanvasRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async renderNode(paint: ElementPaint): Promise<void> {
|
async renderNode(paint: ElementPaint): Promise<void> {
|
||||||
|
if (contains(paint.container.flags, FLAGS.DEBUG_RENDER)) {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
|
||||||
if (paint.container.styles.isVisible()) {
|
if (paint.container.styles.isVisible()) {
|
||||||
await this.renderNodeBackgroundAndBorders(paint);
|
await this.renderNodeBackgroundAndBorders(paint);
|
||||||
await this.renderNodeContent(paint);
|
await this.renderNodeContent(paint);
|
||||||
@ -468,6 +472,9 @@ export class CanvasRenderer extends Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async renderStackContent(stack: StackingContext): Promise<void> {
|
async renderStackContent(stack: StackingContext): Promise<void> {
|
||||||
|
if (contains(stack.element.container.flags, FLAGS.DEBUG_RENDER)) {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
// https://www.w3.org/TR/css-position-3/#painting-order
|
// https://www.w3.org/TR/css-position-3/#painting-order
|
||||||
// 1. the background and borders of the element forming the stacking context.
|
// 1. the background and borders of the element forming the stacking context.
|
||||||
await this.renderNodeBackgroundAndBorders(stack.element);
|
await this.renderNodeBackgroundAndBorders(stack.element);
|
||||||
|
Loading…
Reference in New Issue
Block a user