Skip to content

Commit

Permalink
Fix issue niklasvh#2739 allow for multiple bounding boxes in an element.
Browse files Browse the repository at this point in the history
  • Loading branch information
Chad Petersen committed Sep 6, 2022
1 parent 6020386 commit 8d5a45a
Show file tree
Hide file tree
Showing 14 changed files with 462 additions and 347 deletions.
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/css/layout/__mocks__/bounds.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const {Bounds} = jest.requireActual('../bounds');
export const parseBounds = (): typeof Bounds => {
return new Bounds(0, 0, 200, 50);
export const parseBounds = (): typeof Bounds[] => {
return [new Bounds(0, 0, 200, 50)];
};
25 changes: 15 additions & 10 deletions src/css/layout/bounds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ export class Bounds {
return new Bounds(this.left + x, this.top + y, this.width + w, this.height + h);
}

static fromClientRect(context: Context, clientRect: ClientRect): Bounds {
return new Bounds(
clientRect.left + context.windowBounds.left,
clientRect.top + context.windowBounds.top,
clientRect.width,
clientRect.height
);
static fromDomRect(context: Context, domRect: DOMRect): Bounds {
return domRect.width !== 0 && domRect.height !== 0
? new Bounds(
domRect.left + context.windowBounds.left,
domRect.top + context.windowBounds.top,
domRect.width,
domRect.height
)
: Bounds.EMPTY;
}

static fromDOMRectList(context: Context, domRectList: DOMRectList): Bounds {
const domRect = Array.from(domRectList).find((rect) => rect.width !== 0);
const domRect = Array.from(domRectList).find((rect) => rect.width !== 0 && rect.height !== 0);
return domRect
? new Bounds(
domRect.left + context.windowBounds.left,
Expand All @@ -30,9 +32,12 @@ export class Bounds {

static EMPTY = new Bounds(0, 0, 0, 0);
}
export const parseBound = (context: Context, node: Element): Bounds => {
return Bounds.fromDomRect(context, node.getBoundingClientRect());
};

export const parseBounds = (context: Context, node: Element): Bounds => {
return Bounds.fromClientRect(context, node.getBoundingClientRect());
export const parseBounds = (context: Context, node: Element): Bounds[] => {
return Array.from(node.getClientRects()).map((b) => Bounds.fromDomRect(context, b));
};

export const parseDocumentSize = (document: Document): Bounds => {
Expand Down
8 changes: 5 additions & 3 deletions src/css/layout/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ export const parseTextBounds = (
}
} else {
const replacementNode = node.splitText(text.length);
textBounds.push(new TextBounds(text, getWrapperBounds(context, node)));
getWrapperBounds(context, node).forEach((wrapperBound) => {
textBounds.push(new TextBounds(text, wrapperBound));
});
node = replacementNode;
}
} else if (!FEATURES.SUPPORT_RANGE_BOUNDS) {
Expand All @@ -61,7 +63,7 @@ export const parseTextBounds = (
return textBounds;
};

const getWrapperBounds = (context: Context, node: Text): Bounds => {
const getWrapperBounds = (context: Context, node: Text): Bounds[] => {
const ownerDocument = node.ownerDocument;
if (ownerDocument) {
const wrapper = ownerDocument.createElement('html2canvaswrapper');
Expand All @@ -77,7 +79,7 @@ const getWrapperBounds = (context: Context, node: Text): Bounds => {
}
}

return Bounds.EMPTY;
return [Bounds.EMPTY];
};

const createRange = (node: Text, offset: number, length: number): Range => {
Expand Down
2 changes: 1 addition & 1 deletion src/dom/element-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class ElementContainer {
readonly styles: CSSParsedDeclaration;
readonly textNodes: TextContainer[] = [];
readonly elements: ElementContainer[] = [];
bounds: Bounds;
bounds: Bounds[];
flags = 0;

constructor(protected readonly context: Context, element: Element) {
Expand Down
2 changes: 1 addition & 1 deletion src/dom/replaced-elements/input-element-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class InputElementContainer extends ElementContainer {
BORDER_STYLE.SOLID;
this.styles.backgroundClip = [BACKGROUND_CLIP.BORDER_BOX];
this.styles.backgroundOrigin = [BACKGROUND_ORIGIN.BORDER_BOX];
this.bounds = reformatInputBounds(this.bounds);
this.bounds = this.bounds.map(reformatInputBounds);
}

switch (this.type) {
Expand Down
4 changes: 2 additions & 2 deletions src/dom/replaced-elements/svg-element-container.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ElementContainer} from '../element-container';
import {parseBounds} from '../../css/layout/bounds';
import {parseBound} from '../../css/layout/bounds';
import {Context} from '../../core/context';

export class SVGElementContainer extends ElementContainer {
Expand All @@ -10,7 +10,7 @@ export class SVGElementContainer extends ElementContainer {
constructor(context: Context, img: SVGSVGElement) {
super(context, img);
const s = new XMLSerializer();
const bounds = parseBounds(context, img);
const bounds = parseBound(context, img);
img.setAttribute('width', `${bounds.width}px`);
img.setAttribute('height', `${bounds.height}px`);

Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Bounds, parseBounds, parseDocumentSize} from './css/layout/bounds';
import {Bounds, parseBound, parseDocumentSize} from './css/layout/bounds';
import {COLORS, isTransparent, parseColor} from './css/types/color';
import {CloneConfigurations, CloneOptions, DocumentCloner, WindowOptions} from './dom/document-cloner';
import {isBodyElement, isHTMLElement, parseTree} from './dom/node-parser';
Expand Down Expand Up @@ -98,7 +98,7 @@ const renderElement = async (element: HTMLElement, opts: Partial<Options>): Prom
const {width, height, left, top} =
isBodyElement(clonedElement) || isHTMLElement(clonedElement)
? parseDocumentSize(clonedElement.ownerDocument)
: parseBounds(context, clonedElement);
: parseBound(context, clonedElement);

const backgroundColor = parseBackgroundColor(context, clonedElement, opts.backgroundColor);

Expand Down
Loading

0 comments on commit 8d5a45a

Please sign in to comment.