Compare commits

...

9 Commits

Author SHA1 Message Date
CI
99f105cb66 chore(release): 1.0.0-rc.4 2019-09-22 05:11:36 +00:00
7d3456b78c fix: null backgroundColor option as transparent (#2012) 2019-09-21 21:45:05 -07:00
00555cf1ef fix: nested z-index ordering (#2011)
* fix zindex bug

* test: add z-index reftest for #1978

* fix: z-index ordering early exit
2019-09-21 21:12:36 -07:00
eedb81ef9e fix: correctly render partial borders (fix #1920) (#2010) 2019-09-21 20:33:54 -07:00
d4b58960dc Update canvas-renderer.ts (#2004)
* Update canvas-renderer.ts

Fixed an issue were a page wouldn't render.

Line 581 (now 582) threw exception: "Uncaught (in promise) DOMException: Failed to execute 'createPattern' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0."

* Update canvas-renderer.ts
2019-09-21 19:33:48 -07:00
ee3ca35636 add missing -ms-grid display property to support IE grid layouts (#1926) 2019-09-21 19:32:42 -07:00
9a63797aa7 docs: fix typo (#1864) 2019-06-17 21:24:34 -07:00
81dcf7b6be fix: zero size iframe rendering (#1863) 2019-06-17 21:23:45 -07:00
61f4819e02 feat: ignore unsupported image functions (#1873) 2019-06-17 21:22:05 -07:00
18 changed files with 147 additions and 36 deletions

View File

@ -2,6 +2,26 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
# [1.0.0-rc.4](https://github.com/niklasvh/html2canvas/compare/v1.0.0-rc.3...v1.0.0-rc.4) (2019-09-22)
### docs
* fix typo (#1864) ([9a63797aa7fb81454008745d2a1c069ca24339a4](https://github.com/niklasvh/html2canvas/commit/9a63797aa7fb81454008745d2a1c069ca24339a4)), closes [#1864](https://github.com/niklasvh/html2canvas/issues/1864)
### feat
* ignore unsupported image functions (#1873) ([61f4819e02102b112513d57b16ec7d37e989af20](https://github.com/niklasvh/html2canvas/commit/61f4819e02102b112513d57b16ec7d37e989af20)), closes [#1873](https://github.com/niklasvh/html2canvas/issues/1873)
### fix
* correctly render partial borders (fix #1920) (#2010) ([eedb81ef9e114366a7e286e975659360cf9d0983](https://github.com/niklasvh/html2canvas/commit/eedb81ef9e114366a7e286e975659360cf9d0983)), closes [#1920](https://github.com/niklasvh/html2canvas/issues/1920) [#2010](https://github.com/niklasvh/html2canvas/issues/2010)
* nested z-index ordering (#2011) ([00555cf1efddfed5877811d8a03a326f9943ab06](https://github.com/niklasvh/html2canvas/commit/00555cf1efddfed5877811d8a03a326f9943ab06)), closes [#2011](https://github.com/niklasvh/html2canvas/issues/2011) [#1978](https://github.com/niklasvh/html2canvas/issues/1978)
* null backgroundColor option as transparent (#2012) ([7d3456b78c37e7333db087601805b32ec7ca0253](https://github.com/niklasvh/html2canvas/commit/7d3456b78c37e7333db087601805b32ec7ca0253)), closes [#2012](https://github.com/niklasvh/html2canvas/issues/2012)
* zero size iframe rendering (#1863) ([81dcf7b6be66920260a60908aa4b86e7530f6e17](https://github.com/niklasvh/html2canvas/commit/81dcf7b6be66920260a60908aa4b86e7530f6e17)), closes [#1863](https://github.com/niklasvh/html2canvas/issues/1863)
# [1.0.0-rc.3](https://github.com/niklasvh/html2canvas/compare/v1.0.0-rc.2...v1.0.0-rc.3) (2019-05-30)

View File

@ -42,7 +42,7 @@ support [older browsers](http://caniuse.com/#search=promise) that do not nativel
To render an `element` with html2canvas, simply call:
` html2canvas(element[, options]);`
The function returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) containing the `<canvas>` element. Simply add a promise fullfillment handler to the promise using `then`:
The function returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) containing the `<canvas>` element. Simply add a promise fulfillment handler to the promise using `then`:
html2canvas(document.body).then(function(canvas) {
document.body.appendChild(canvas);

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "html2canvas",
"version": "1.0.0-rc.3",
"version": "1.0.0-rc.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -6,7 +6,7 @@
"module": "dist/html2canvas.esm.js",
"typings": "dist/types/index.d.ts",
"browser": "dist/html2canvas.js",
"version": "1.0.0-rc.3",
"version": "1.0.0-rc.4",
"author": {
"name": "Niklas von Hertzen",
"email": "niklasvh@gmail.com",

View File

@ -1,7 +1,7 @@
import {TokenType} from '../syntax/tokenizer';
import {ICSSImage, image} from '../types/image';
import {ICSSImage, image, isSupportedImage} from '../types/image';
import {IPropertyListDescriptor, PropertyDescriptorParsingType} from '../IPropertyDescriptor';
import {CSSValue, nonFunctionArgSeperator} from '../syntax/parser';
import {CSSValue, nonFunctionArgSeparator} from '../syntax/parser';
export const backgroundImage: IPropertyListDescriptor<ICSSImage[]> = {
name: 'background-image',
@ -19,6 +19,6 @@ export const backgroundImage: IPropertyListDescriptor<ICSSImage[]> = {
return [];
}
return tokens.filter(nonFunctionArgSeperator).map(image.parse);
return tokens.filter(value => nonFunctionArgSeparator(value) && isSupportedImage(value)).map(image.parse);
}
};

View File

@ -65,6 +65,7 @@ const parseDisplayValue = (display: string): Display => {
case '-webkit-flex':
return DISPLAY.FLEX;
case 'grid':
case '-ms-grid':
return DISPLAY.GRID;
case 'ruby':
return DISPLAY.RUBY;

View File

@ -149,7 +149,7 @@ export const isIdentWithValue = (token: CSSValue, value: string): boolean =>
isIdentToken(token) && token.value === value;
export const nonWhiteSpace = (token: CSSValue) => token.type !== TokenType.WHITESPACE_TOKEN;
export const nonFunctionArgSeperator = (token: CSSValue) =>
export const nonFunctionArgSeparator = (token: CSSValue) =>
token.type !== TokenType.WHITESPACE_TOKEN && token.type !== TokenType.COMMA_TOKEN;
export const parseFunctionArgs = (tokens: CSSValue[]): CSSValue[][] => {

View File

@ -696,7 +696,7 @@ export class Tokenizer {
}
}
}
i++;
} while (true);
}

View File

@ -1,4 +1,4 @@
import {CSSValue, nonFunctionArgSeperator} from '../syntax/parser';
import {CSSValue, nonFunctionArgSeparator} from '../syntax/parser';
import {TokenType} from '../syntax/tokenizer';
import {ITypeDescriptor} from '../ITypeDescriptor';
import {angle, deg} from './angle';
@ -86,7 +86,7 @@ const getTokenColorValue = (token: CSSValue, i: number): number => {
};
const rgb = (args: CSSValue[]): number => {
const tokens = args.filter(nonFunctionArgSeperator);
const tokens = args.filter(nonFunctionArgSeparator);
if (tokens.length === 3) {
const [r, g, b] = tokens.map(getTokenColorValue);
@ -121,7 +121,7 @@ function hue2rgb(t1: number, t2: number, hue: number): number {
}
const hsl = (args: CSSValue[]): number => {
const tokens = args.filter(nonFunctionArgSeperator);
const tokens = args.filter(nonFunctionArgSeparator);
const [hue, saturation, lightness, alpha] = tokens;
const h = (hue.type === TokenType.NUMBER_TOKEN ? deg(hue.number) : angle.parse(hue)) / (Math.PI * 2);

View File

@ -1,4 +1,4 @@
import {CSSValue, isIdentToken, isNumberToken, nonFunctionArgSeperator, parseFunctionArgs} from '../../syntax/parser';
import {CSSValue, isIdentToken, isNumberToken, nonFunctionArgSeparator, parseFunctionArgs} from '../../syntax/parser';
import {
CSSImageType,
CSSLinearGradientImage,
@ -40,7 +40,7 @@ export const webkitGradient = (tokens: CSSValue[]): CSSLinearGradientImage | CSS
const color = colorType.parse(firstToken.values[0]);
stops.push({stop: HUNDRED_PERCENT, color});
} else if (firstToken.name === 'color-stop') {
const values = firstToken.values.filter(nonFunctionArgSeperator);
const values = firstToken.values.filter(nonFunctionArgSeparator);
if (values.length === 2) {
const color = colorType.parse(values[1]);
const stop = values[0];

View File

@ -98,9 +98,11 @@ export const image: ITypeDescriptor<ICSSImage> = {
}
};
const SUPPORTED_IMAGE_FUNCTIONS: {
[key: string]: (args: CSSValue[]) => ICSSImage;
} = {
export function isSupportedImage(value: CSSValue) {
return value.type !== TokenType.FUNCTION || SUPPORTED_IMAGE_FUNCTIONS[value.name];
}
const SUPPORTED_IMAGE_FUNCTIONS: Record<string, (args: CSSValue[]) => ICSSImage> = {
'linear-gradient': linearGradient,
'-moz-linear-gradient': prefixLinearGradient,
'-ms-linear-gradient': prefixLinearGradient,

View File

@ -12,7 +12,7 @@ import {
isTextNode
} from './node-parser';
import {Logger} from '../core/logger';
import {isIdentToken, nonFunctionArgSeperator} from '../css/syntax/parser';
import {isIdentToken, nonFunctionArgSeparator} from '../css/syntax/parser';
import {TokenType} from '../css/syntax/tokenizer';
import {CounterState, createCounterText} from '../css/types/functions/counter';
import {LIST_STYLE_TYPE, listStyleType} from '../css/property-descriptors/list-style-type';
@ -355,7 +355,7 @@ export class DocumentCloner {
);
}
} else if (token.name === 'counter') {
const [counter, counterStyle] = token.values.filter(nonFunctionArgSeperator);
const [counter, counterStyle] = token.values.filter(nonFunctionArgSeparator);
if (counter && isIdentToken(counter)) {
const counterState = this.counters.getCounterValue(counter.value);
const counterType =
@ -368,7 +368,7 @@ export class DocumentCloner {
);
}
} else if (token.name === 'counters') {
const [counter, delim, counterStyle] = token.values.filter(nonFunctionArgSeperator);
const [counter, delim, counterStyle] = token.values.filter(nonFunctionArgSeparator);
if (counter && isIdentToken(counter)) {
const counterStates = this.counters.getCounterValues(counter.value);
const counterType =

View File

@ -15,8 +15,8 @@ export class IFrameElementContainer extends ElementContainer {
constructor(iframe: HTMLIFrameElement) {
super(iframe);
this.src = iframe.src;
this.width = parseInt(iframe.width, 10);
this.height = parseInt(iframe.height, 10);
this.width = parseInt(iframe.width, 10) || 0;
this.height = parseInt(iframe.height, 10) || 0;
this.backgroundColor = this.styles.backgroundColor;
try {
if (

View File

@ -101,7 +101,7 @@ const renderElement = async (element: HTMLElement, opts: Partial<Options>): Prom
: COLORS.TRANSPARENT;
const bgColor = opts.backgroundColor;
const defaultBackgroundColor = typeof bgColor === 'string' ? parseColor(bgColor) : 0xffffffff;
const defaultBackgroundColor = typeof bgColor === 'string' ? parseColor(bgColor) : bgColor === null ? COLORS.TRANSPARENT : 0xffffffff;
const backgroundColor =
element === ownerDocument.documentElement

View File

@ -306,17 +306,19 @@ export class CanvasRenderer {
});
const canvas = await iframeRenderer.render(container.tree);
this.ctx.drawImage(
canvas,
0,
0,
container.width,
container.width,
container.bounds.left,
container.bounds.top,
container.bounds.width,
container.bounds.height
);
if (container.width && container.height) {
this.ctx.drawImage(
canvas,
0,
0,
container.width,
container.height,
container.bounds.left,
container.bounds.top,
container.bounds.width,
container.bounds.height
);
}
}
if (container instanceof InputElementContainer) {
@ -576,8 +578,10 @@ export class CanvasRenderer {
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, width, height);
const pattern = this.ctx.createPattern(canvas, 'repeat') as CanvasPattern;
this.renderRepeat(path, pattern, x, y);
if ((width > 0) && (height > 0)) {
const pattern = this.ctx.createPattern(canvas, 'repeat') as CanvasPattern;
this.renderRepeat(path, pattern, x, y);
}
} else if (isRadialGradient(backgroundImage)) {
const [path, left, top, width, height] = calculateBackgroundRendering(container, index, [
null,
@ -697,8 +701,9 @@ export class CanvasRenderer {
let side = 0;
for (const border of borders) {
if (border.style !== BORDER_STYLE.NONE && !isTransparent(border.color)) {
await this.renderBorder(border.color, side++, paint.curves);
await this.renderBorder(border.color, side, paint.curves);
}
side++;
}
}

View File

@ -104,8 +104,11 @@ const parseStackTree = (
parentStack.negativeZIndex.some((current, i) => {
if (order > current.element.container.styles.zIndex.order) {
index = i;
return false;
} else if (index > 0) {
return true;
}
return false;
});
parentStack.negativeZIndex.splice(index, 0, stack);
@ -114,6 +117,8 @@ const parseStackTree = (
parentStack.positiveZIndex.some((current, i) => {
if (order > current.element.container.styles.zIndex.order) {
index = i + 1;
return false;
} else if (index > 0) {
return true;
}

View File

@ -40,6 +40,12 @@
border-bottom-width: 50px;
}
.box6 {
border-style: none solid none solid;
border-color: #807d32;
border-width: 50px;
}
html {
background: #3a84c3;
}
@ -51,5 +57,6 @@
<div class="box3">&nbsp;</div>
<div class="box4">&nbsp;</div>
<div class="box5">&nbsp;</div>
<div class="box6">&nbsp;</div>
</body>
</html>

View File

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>z-index19</title>
<style>
.canvas-view {
display: flex;
flex-direction: row;
}
.main {
position: relative;
width: 500px;
height: 500px;
margin-right: 50px;
}
.div1 {
position: absolute;
z-index: 1;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: red;
}
.div2 {
position: absolute;
z-index: 2;
top: 100px;
left: 100px;
bottom: 0;
right: 0;
background-color: green;
}
.div3 {
position: absolute;
z-index: 3;
top: 200px;
left: 200px;
bottom: 0;
right: 0;
background-color: blue;
}
.div4 {
position: absolute;
z-index: 4;
top: 300px;
left: 300px;
bottom: 0;
right: 0;
background-color: white;
}
</style>
<script type="text/javascript" src="../../test.js"></script>
</head>
<body>
<div class="canvas-view" id="my-home">
<div class="main" id="my-div">
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
<div class="div4"></div>
</div>
</div>
</body>
</html>