mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Compare commits
17 Commits
0.5.0-alph
...
v0.5.0-bet
Author | SHA1 | Date | |
---|---|---|---|
2a2ad9bb65 | |||
81e60975cc | |||
a0669300c4 | |||
ba9758cf14 | |||
aa05241ff8 | |||
5b4a6c26ee | |||
364a8aac1c | |||
46078acf71 | |||
4b37909f09 | |||
90f9eeba83 | |||
98ee30643a | |||
a49c3a2320 | |||
4b80102e77 | |||
9201cf7e95 | |||
c2baf42145 | |||
d9a9615ed7 | |||
585a96a918 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
/nbproject/
|
/nbproject/
|
||||||
image.jpg
|
image.jpg
|
||||||
/.project
|
/.project
|
||||||
|
dist/
|
||||||
/.settings/
|
/.settings/
|
||||||
node_modules/
|
node_modules/
|
||||||
.envrc
|
.envrc
|
||||||
@ -9,3 +10,4 @@ node_modules/
|
|||||||
*.iml
|
*.iml
|
||||||
.idea/
|
.idea/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
npm-debug.log
|
||||||
|
@ -15,5 +15,5 @@
|
|||||||
"globals": {
|
"globals": {
|
||||||
"jQuery": true
|
"jQuery": true
|
||||||
},
|
},
|
||||||
"predef": ["-Promise"]
|
"predef": ["-Promise", "define"]
|
||||||
}
|
}
|
||||||
|
5
.npmignore
Normal file
5
.npmignore
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
tests/
|
||||||
|
examples/
|
||||||
|
Gruntfile.js
|
||||||
|
bower.json
|
||||||
|
src/
|
22
.travis.yml
22
.travis.yml
@ -1,21 +1,29 @@
|
|||||||
---
|
|
||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '0.10'
|
- '0.10'
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- secure: "eW41gIqOizwO4pTgWnAAbW75AP7F+CK9qfSed/fSh4sJ9HWMIY1YRIaY8gjr+6jV/f7XVHcXuym6ZxgINYSkVKbF1JKxBJNLOXtSgNbVHSic58pYFvUjwxIBI9aPig9uux1+DbnpWqXFDTcACJSevQZE0xwmjdrSkDLgB0G34v8="
|
- secure: eW41gIqOizwO4pTgWnAAbW75AP7F+CK9qfSed/fSh4sJ9HWMIY1YRIaY8gjr+6jV/f7XVHcXuym6ZxgINYSkVKbF1JKxBJNLOXtSgNbVHSic58pYFvUjwxIBI9aPig9uux1+DbnpWqXFDTcACJSevQZE0xwmjdrSkDLgB0G34v8=
|
||||||
- secure: "Y2Av+Gd3z9uQEB36GwdOOuGka0hx0/HeitASEo59z934O8RxnmN9eNTXS7dDT3XtKtwxIyLTOEpS7qlRdWahH28hr/dS4xJj6ao58C+1xMcDs6NAPGmDxUlcJWpcGEsnjmXjQCc3fBioSTdpIBrK/gdvgpNh77UKG74Sk7Z+YGk="
|
- secure: Y2Av+Gd3z9uQEB36GwdOOuGka0hx0/HeitASEo59z934O8RxnmN9eNTXS7dDT3XtKtwxIyLTOEpS7qlRdWahH28hr/dS4xJj6ao58C+1xMcDs6NAPGmDxUlcJWpcGEsnjmXjQCc3fBioSTdpIBrK/gdvgpNh77UKG74Sk7Z+YGk=
|
||||||
- secure: "YI+YbTOGf2x4fPMKW+KhJiZWswoXT6xOKGwLfsQsVwmFX1LerJouil5D5iYOQuL4FE3pNaoJSNakIsokJQuGKJMmnPc8rdhMZuBJBk6MRghurE2Xe9qBHfuUBPlfD61nARESm4WDcyMwM0QVYaOKeY6aIpZ91qbUbyc60EEx3C4="
|
- secure: YI+YbTOGf2x4fPMKW+KhJiZWswoXT6xOKGwLfsQsVwmFX1LerJouil5D5iYOQuL4FE3pNaoJSNakIsokJQuGKJMmnPc8rdhMZuBJBk6MRghurE2Xe9qBHfuUBPlfD61nARESm4WDcyMwM0QVYaOKeY6aIpZ91qbUbyc60EEx3C4=
|
||||||
addons:
|
addons:
|
||||||
sauce_connect: true
|
sauce_connect: true
|
||||||
before_script:
|
before_script:
|
||||||
- npm install -g grunt-cli
|
- npm install -g grunt-cli
|
||||||
- npm install -g uglify-js
|
- npm install -g uglify-js
|
||||||
notifications:
|
notifications:
|
||||||
webhooks:
|
webhooks:
|
||||||
urls:
|
urls:
|
||||||
- https://webhooks.gitter.im/e/2b007d4f86de89588804
|
- https://webhooks.gitter.im/e/2b007d4f86de89588804
|
||||||
on_success: always
|
on_success: always
|
||||||
on_failure: always
|
on_failure: always
|
||||||
on_start: false
|
on_start: false
|
||||||
|
deploy:
|
||||||
|
- provider: npm
|
||||||
|
email: niklasvh@gmail.com
|
||||||
|
api_key:
|
||||||
|
secure: dot+HzIe3thKep5mz5pyNYQV1ZYiGlVQAWScmfYh75AtOCJQJGvvw1alwRZDL0Ykn/7LeftZik845INn8Al8h4OEUQyuq2WmybZ5zn7PsLXRes7FtlJeYERO79bV5P3aV4vq4QoaZkPB5jQ98CmgQ2/9xPB+1ogNd7fRfUpSvSI=
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
branch: master
|
||||||
|
repo: niklasvh/html2canvas
|
||||||
|
149
dist/html2canvas.js
vendored
149
dist/html2canvas.js
vendored
@ -1542,85 +1542,63 @@ process.umask = function() { return 0; };
|
|||||||
var log = require('./log');
|
var log = require('./log');
|
||||||
var Promise = require('./promise');
|
var Promise = require('./promise');
|
||||||
|
|
||||||
var html2canvasCanvasCloneAttribute = "data-html2canvas-canvas-clone";
|
|
||||||
var html2canvasCanvasCloneIndex = 0;
|
|
||||||
|
|
||||||
function cloneNodeValues(document, clone, nodeName) {
|
|
||||||
var originalNodes = document.getElementsByTagName(nodeName);
|
|
||||||
var clonedNodes = clone.getElementsByTagName(nodeName);
|
|
||||||
var count = originalNodes.length;
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
clonedNodes[i].value = originalNodes[i].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function restoreOwnerScroll(ownerDocument, x, y) {
|
function restoreOwnerScroll(ownerDocument, x, y) {
|
||||||
if (ownerDocument.defaultView && (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
|
if (ownerDocument.defaultView && (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
|
||||||
ownerDocument.defaultView.scrollTo(x, y);
|
ownerDocument.defaultView.scrollTo(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function labelCanvasElements(ownerDocument) {
|
function cloneCanvasContents(canvas, clonedCanvas) {
|
||||||
[].slice.call(ownerDocument.querySelectorAll("canvas"), 0).forEach(function(canvas) {
|
try {
|
||||||
canvas.setAttribute(html2canvasCanvasCloneAttribute, "canvas-" + html2canvasCanvasCloneIndex++);
|
if (clonedCanvas) {
|
||||||
});
|
clonedCanvas.width = canvas.width;
|
||||||
}
|
clonedCanvas.height = canvas.height;
|
||||||
|
clonedCanvas.getContext("2d").putImageData(canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height), 0, 0);
|
||||||
function cloneCanvasContents(ownerDocument, documentClone) {
|
|
||||||
[].slice.call(ownerDocument.querySelectorAll("[" + html2canvasCanvasCloneAttribute + "]"), 0).forEach(function(canvas) {
|
|
||||||
try {
|
|
||||||
var clonedCanvas = documentClone.querySelector('[' + html2canvasCanvasCloneAttribute + '="' + canvas.getAttribute(html2canvasCanvasCloneAttribute) + '"]');
|
|
||||||
if (clonedCanvas) {
|
|
||||||
clonedCanvas.width = canvas.width;
|
|
||||||
clonedCanvas.height = canvas.height;
|
|
||||||
clonedCanvas.getContext("2d").putImageData(canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height), 0, 0);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
log("Unable to copy canvas content from", canvas, e);
|
|
||||||
}
|
}
|
||||||
canvas.removeAttribute(html2canvasCanvasCloneAttribute);
|
} catch(e) {
|
||||||
});
|
log("Unable to copy canvas content from", canvas, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeScriptNodes(parent) {
|
function cloneNode(node, javascriptEnabled) {
|
||||||
[].slice.call(parent.childNodes, 0).filter(isElementNode).forEach(function(node) {
|
|
||||||
if (node.tagName === "SCRIPT") {
|
|
||||||
parent.removeChild(node);
|
|
||||||
} else {
|
|
||||||
removeScriptNodes(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isIE9() {
|
|
||||||
return document.documentMode && document.documentMode <= 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/niklasvh/html2canvas/issues/503
|
|
||||||
function cloneNodeIE9(node, javascriptEnabled) {
|
|
||||||
var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
|
var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
|
||||||
|
|
||||||
var child = node.firstChild;
|
var child = node.firstChild;
|
||||||
while(child) {
|
while(child) {
|
||||||
if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
|
if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
|
||||||
clone.appendChild(cloneNodeIE9(child, javascriptEnabled));
|
clone.appendChild(cloneNode(child, javascriptEnabled));
|
||||||
}
|
}
|
||||||
child = child.nextSibling;
|
child = child.nextSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.nodeType === 1) {
|
||||||
|
clone._scrollTop = node.scrollTop;
|
||||||
|
clone._scrollLeft = node.scrollLeft;
|
||||||
|
if (node.nodeName === "CANVAS") {
|
||||||
|
cloneCanvasContents(node, clone);
|
||||||
|
} else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") {
|
||||||
|
clone.value = node.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initNode(node) {
|
||||||
|
if (node.nodeType === 1) {
|
||||||
|
node.scrollTop = node._scrollTop;
|
||||||
|
node.scrollLeft = node._scrollLeft;
|
||||||
|
|
||||||
|
var child = node.firstChild;
|
||||||
function isElementNode(node) {
|
while(child) {
|
||||||
return node.nodeType === Node.ELEMENT_NODE;
|
initNode(child);
|
||||||
|
child = child.nextSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(ownerDocument, containerDocument, width, height, options, x ,y) {
|
module.exports = function(ownerDocument, containerDocument, width, height, options, x ,y) {
|
||||||
labelCanvasElements(ownerDocument);
|
var documentElement = cloneNode(ownerDocument.documentElement, options.javascriptEnabled);
|
||||||
var documentElement = isIE9() ? cloneNodeIE9(ownerDocument.documentElement, options.javascriptEnabled) : ownerDocument.documentElement.cloneNode(true);
|
|
||||||
var container = containerDocument.createElement("iframe");
|
var container = containerDocument.createElement("iframe");
|
||||||
|
|
||||||
container.className = "html2canvas-container";
|
container.className = "html2canvas-container";
|
||||||
@ -1637,19 +1615,21 @@ module.exports = function(ownerDocument, containerDocument, width, height, optio
|
|||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
var documentClone = container.contentWindow.document;
|
var documentClone = container.contentWindow.document;
|
||||||
|
|
||||||
cloneNodeValues(ownerDocument.documentElement, documentElement, "textarea");
|
|
||||||
cloneNodeValues(ownerDocument.documentElement, documentElement, "select");
|
|
||||||
|
|
||||||
/* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
|
/* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
|
||||||
if window url is about:blank, we can assign the url to current by writing onto the document
|
if window url is about:blank, we can assign the url to current by writing onto the document
|
||||||
*/
|
*/
|
||||||
container.contentWindow.onload = container.onload = function() {
|
container.contentWindow.onload = container.onload = function() {
|
||||||
var interval = setInterval(function() {
|
var interval = setInterval(function() {
|
||||||
if (documentClone.body.childNodes.length > 0) {
|
if (documentClone.body.childNodes.length > 0) {
|
||||||
cloneCanvasContents(ownerDocument, documentClone);
|
initNode(documentClone.documentElement);
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
if (options.type === "view") {
|
if (options.type === "view") {
|
||||||
container.contentWindow.scrollTo(x, y);
|
container.contentWindow.scrollTo(x, y);
|
||||||
|
if ((/(iPad|iPhone|iPod)/g).test(navigator.userAgent) && (container.contentWindow.scrollY !== y || container.contentWindow.scrollX !== x)) {
|
||||||
|
documentClone.documentElement.style.top = (-y) + "px";
|
||||||
|
documentClone.documentElement.style.left = (-x) + "px";
|
||||||
|
documentClone.documentElement.style.position = 'absolute';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resolve(container);
|
resolve(container);
|
||||||
}
|
}
|
||||||
@ -1660,7 +1640,7 @@ module.exports = function(ownerDocument, containerDocument, width, height, optio
|
|||||||
documentClone.write("<!DOCTYPE html><html></html>");
|
documentClone.write("<!DOCTYPE html><html></html>");
|
||||||
// Chrome scrolls the parent document for some reason after the write to the cloned window???
|
// Chrome scrolls the parent document for some reason after the write to the cloned window???
|
||||||
restoreOwnerScroll(ownerDocument, x, y);
|
restoreOwnerScroll(ownerDocument, x, y);
|
||||||
documentClone.replaceChild(options.javascriptEnabled === true ? documentClone.adoptNode(documentElement) : removeScriptNodes(documentClone.adoptNode(documentElement)), documentClone.documentElement);
|
documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);
|
||||||
documentClone.close();
|
documentClone.close();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1998,10 +1978,18 @@ html2canvas.NodeContainer = NodeContainer;
|
|||||||
html2canvas.log = log;
|
html2canvas.log = log;
|
||||||
html2canvas.utils = utils;
|
html2canvas.utils = utils;
|
||||||
|
|
||||||
module.exports = (typeof(document) === "undefined" || typeof(Object.create) !== "function" || typeof(document.createElement("canvas").getContext) !== "function") ? function() {
|
var html2canvasExport = (typeof(document) === "undefined" || typeof(Object.create) !== "function" || typeof(document.createElement("canvas").getContext) !== "function") ? function() {
|
||||||
return Promise.reject("No canvas support");
|
return Promise.reject("No canvas support");
|
||||||
} : html2canvas;
|
} : html2canvas;
|
||||||
|
|
||||||
|
module.exports = html2canvasExport;
|
||||||
|
|
||||||
|
if (typeof(define) === 'function' && define.amd) {
|
||||||
|
define('html2canvas', [], function() {
|
||||||
|
return html2canvasExport;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderDocument(document, options, windowWidth, windowHeight, html2canvasIndex) {
|
function renderDocument(document, options, windowWidth, windowHeight, html2canvasIndex) {
|
||||||
return createWindowClone(document, document, windowWidth, windowHeight, options, document.defaultView.pageXOffset, document.defaultView.pageYOffset).then(function(container) {
|
return createWindowClone(document, document, windowWidth, windowHeight, options, document.defaultView.pageXOffset, document.defaultView.pageYOffset).then(function(container) {
|
||||||
log("Document cloned");
|
log("Document cloned");
|
||||||
@ -2424,6 +2412,8 @@ module.exports = ImageLoader;
|
|||||||
var GradientContainer = require('./gradientcontainer');
|
var GradientContainer = require('./gradientcontainer');
|
||||||
var Color = require('./color');
|
var Color = require('./color');
|
||||||
|
|
||||||
|
var COLOR_STOP_REGEXP = /^\s*(.*)\s*(\d{1,3})?(%|px)?$/;
|
||||||
|
|
||||||
function LinearGradientContainer(imageData) {
|
function LinearGradientContainer(imageData) {
|
||||||
GradientContainer.apply(this, arguments);
|
GradientContainer.apply(this, arguments);
|
||||||
this.type = this.TYPES.LINEAR;
|
this.type = this.TYPES.LINEAR;
|
||||||
@ -2464,13 +2454,15 @@ function LinearGradientContainer(imageData) {
|
|||||||
this.y1 = 1;
|
this.y1 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.colorStops = imageData.args.slice(hasDirection ? 1 : 0).map(function(colorStop) {
|
this.colorStops = imageData.args.slice(hasDirection ? 1 : 0)
|
||||||
var colorStopMatch = colorStop.match(this.stepRegExp);
|
.map(function(colorStop) { return colorStop.match(COLOR_STOP_REGEXP);})
|
||||||
return {
|
.filter(function(colorStopMatch) { return !!colorStopMatch;})
|
||||||
color: new Color(colorStopMatch[1]),
|
.map(function(colorStopMatch) {
|
||||||
stop: colorStopMatch[3] === "%" ? colorStopMatch[2] / 100 : null
|
return {
|
||||||
};
|
color: new Color(colorStopMatch[1]),
|
||||||
}, this);
|
stop: colorStopMatch[3] === "%" ? colorStopMatch[2] / 100 : null
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
if (this.colorStops[0].stop === null) {
|
if (this.colorStops[0].stop === null) {
|
||||||
this.colorStops[0].stop = 0;
|
this.colorStops[0].stop = 0;
|
||||||
@ -2768,7 +2760,7 @@ NodeContainer.prototype.getValue = function() {
|
|||||||
return value.length === 0 ? (this.node.placeholder || "") : value;
|
return value.length === 0 ? (this.node.placeholder || "") : value;
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeContainer.prototype.MATRIX_PROPERTY = /(matrix)\((.+)\)/;
|
NodeContainer.prototype.MATRIX_PROPERTY = /(matrix|matrix3d)\((.+)\)/;
|
||||||
NodeContainer.prototype.TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
|
NodeContainer.prototype.TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
|
||||||
NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
|
NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
|
||||||
NodeContainer.prototype.CLIP = /^rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)$/;
|
NodeContainer.prototype.CLIP = /^rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)$/;
|
||||||
@ -2783,6 +2775,11 @@ function parseMatrix(match) {
|
|||||||
return match[2].split(",").map(function(s) {
|
return match[2].split(",").map(function(s) {
|
||||||
return parseFloat(s.trim());
|
return parseFloat(s.trim());
|
||||||
});
|
});
|
||||||
|
} else if (match && match[1] === "matrix3d") {
|
||||||
|
var matrix3d = match[2].split(",").map(function(s) {
|
||||||
|
return parseFloat(s.trim());
|
||||||
|
});
|
||||||
|
return [matrix3d[0], matrix3d[1], matrix3d[4], matrix3d[5], matrix3d[12], matrix3d[13]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3420,14 +3417,14 @@ function calculateCurvePoints(bounds, borderRadius, borders) {
|
|||||||
width = bounds.width,
|
width = bounds.width,
|
||||||
height = bounds.height,
|
height = bounds.height,
|
||||||
|
|
||||||
tlh = borderRadius[0][0],
|
tlh = borderRadius[0][0] < width / 2 ? borderRadius[0][0] : width / 2,
|
||||||
tlv = borderRadius[0][1],
|
tlv = borderRadius[0][1] < height / 2 ? borderRadius[0][1] : height / 2,
|
||||||
trh = borderRadius[1][0],
|
trh = borderRadius[1][0] < width / 2 ? borderRadius[1][0] : width / 2,
|
||||||
trv = borderRadius[1][1],
|
trv = borderRadius[1][1] < height / 2 ? borderRadius[1][1] : height / 2,
|
||||||
brh = borderRadius[2][0],
|
brh = borderRadius[2][0] < width / 2 ? borderRadius[2][0] : width / 2,
|
||||||
brv = borderRadius[2][1],
|
brv = borderRadius[2][1] < height / 2 ? borderRadius[2][1] : height / 2,
|
||||||
blh = borderRadius[3][0],
|
blh = borderRadius[3][0] < width / 2 ? borderRadius[3][0] : width / 2,
|
||||||
blv = borderRadius[3][1];
|
blv = borderRadius[3][1] < height / 2 ? borderRadius[3][1] : height / 2;
|
||||||
|
|
||||||
var topWidth = width - trh,
|
var topWidth = width - trh,
|
||||||
rightHeight = height - brv,
|
rightHeight = height - brv,
|
||||||
|
6
dist/html2canvas.min.js
vendored
6
dist/html2canvas.min.js
vendored
File diff suppressed because one or more lines are too long
@ -2,8 +2,8 @@
|
|||||||
"title": "html2canvas",
|
"title": "html2canvas",
|
||||||
"name": "html2canvas",
|
"name": "html2canvas",
|
||||||
"description": "Screenshots with JavaScript",
|
"description": "Screenshots with JavaScript",
|
||||||
"main": "src/core.js",
|
"main": "dist/html2canvas.js",
|
||||||
"version": "0.5.0-alpha2",
|
"version": "0.5.0-beta1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Niklas von Hertzen",
|
"name": "Niklas von Hertzen",
|
||||||
"email": "niklasvh@gmail.com",
|
"email": "niklasvh@gmail.com",
|
||||||
@ -34,11 +34,12 @@
|
|||||||
"grunt-contrib-watch": "^0.6.1",
|
"grunt-contrib-watch": "^0.6.1",
|
||||||
"grunt-execute": "^0.2.2",
|
"grunt-execute": "^0.2.2",
|
||||||
"grunt-mocha-cli": "^1.12.0",
|
"grunt-mocha-cli": "^1.12.0",
|
||||||
"grunt-mocha-phantomjs": "^0.6.0",
|
"grunt-mocha-phantomjs": "^2.0.0",
|
||||||
"html2canvas-proxy": "0.0.5",
|
"html2canvas-proxy": "0.0.5",
|
||||||
"humanize-duration": "^2.0.1",
|
"humanize-duration": "^2.0.1",
|
||||||
"lodash": "^2.4.1",
|
"lodash": "^2.4.1",
|
||||||
"png-js": ">= 0.1.1",
|
"png-js": ">= 0.1.1",
|
||||||
|
"requirejs": "^2.1.20",
|
||||||
"wd": "^0.2.21"
|
"wd": "^0.2.21"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
98
src/clone.js
98
src/clone.js
@ -1,85 +1,63 @@
|
|||||||
var log = require('./log');
|
var log = require('./log');
|
||||||
var Promise = require('./promise');
|
var Promise = require('./promise');
|
||||||
|
|
||||||
var html2canvasCanvasCloneAttribute = "data-html2canvas-canvas-clone";
|
|
||||||
var html2canvasCanvasCloneIndex = 0;
|
|
||||||
|
|
||||||
function cloneNodeValues(document, clone, nodeName) {
|
|
||||||
var originalNodes = document.getElementsByTagName(nodeName);
|
|
||||||
var clonedNodes = clone.getElementsByTagName(nodeName);
|
|
||||||
var count = originalNodes.length;
|
|
||||||
for (var i = 0; i < count; i++) {
|
|
||||||
clonedNodes[i].value = originalNodes[i].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function restoreOwnerScroll(ownerDocument, x, y) {
|
function restoreOwnerScroll(ownerDocument, x, y) {
|
||||||
if (ownerDocument.defaultView && (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
|
if (ownerDocument.defaultView && (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
|
||||||
ownerDocument.defaultView.scrollTo(x, y);
|
ownerDocument.defaultView.scrollTo(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function labelCanvasElements(ownerDocument) {
|
function cloneCanvasContents(canvas, clonedCanvas) {
|
||||||
[].slice.call(ownerDocument.querySelectorAll("canvas"), 0).forEach(function(canvas) {
|
try {
|
||||||
canvas.setAttribute(html2canvasCanvasCloneAttribute, "canvas-" + html2canvasCanvasCloneIndex++);
|
if (clonedCanvas) {
|
||||||
});
|
clonedCanvas.width = canvas.width;
|
||||||
}
|
clonedCanvas.height = canvas.height;
|
||||||
|
clonedCanvas.getContext("2d").putImageData(canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height), 0, 0);
|
||||||
function cloneCanvasContents(ownerDocument, documentClone) {
|
|
||||||
[].slice.call(ownerDocument.querySelectorAll("[" + html2canvasCanvasCloneAttribute + "]"), 0).forEach(function(canvas) {
|
|
||||||
try {
|
|
||||||
var clonedCanvas = documentClone.querySelector('[' + html2canvasCanvasCloneAttribute + '="' + canvas.getAttribute(html2canvasCanvasCloneAttribute) + '"]');
|
|
||||||
if (clonedCanvas) {
|
|
||||||
clonedCanvas.width = canvas.width;
|
|
||||||
clonedCanvas.height = canvas.height;
|
|
||||||
clonedCanvas.getContext("2d").putImageData(canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height), 0, 0);
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
log("Unable to copy canvas content from", canvas, e);
|
|
||||||
}
|
}
|
||||||
canvas.removeAttribute(html2canvasCanvasCloneAttribute);
|
} catch(e) {
|
||||||
});
|
log("Unable to copy canvas content from", canvas, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeScriptNodes(parent) {
|
function cloneNode(node, javascriptEnabled) {
|
||||||
[].slice.call(parent.childNodes, 0).filter(isElementNode).forEach(function(node) {
|
|
||||||
if (node.tagName === "SCRIPT") {
|
|
||||||
parent.removeChild(node);
|
|
||||||
} else {
|
|
||||||
removeScriptNodes(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isIE9() {
|
|
||||||
return document.documentMode && document.documentMode <= 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/niklasvh/html2canvas/issues/503
|
|
||||||
function cloneNodeIE9(node, javascriptEnabled) {
|
|
||||||
var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
|
var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
|
||||||
|
|
||||||
var child = node.firstChild;
|
var child = node.firstChild;
|
||||||
while(child) {
|
while(child) {
|
||||||
if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
|
if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
|
||||||
clone.appendChild(cloneNodeIE9(child, javascriptEnabled));
|
clone.appendChild(cloneNode(child, javascriptEnabled));
|
||||||
}
|
}
|
||||||
child = child.nextSibling;
|
child = child.nextSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.nodeType === 1) {
|
||||||
|
clone._scrollTop = node.scrollTop;
|
||||||
|
clone._scrollLeft = node.scrollLeft;
|
||||||
|
if (node.nodeName === "CANVAS") {
|
||||||
|
cloneCanvasContents(node, clone);
|
||||||
|
} else if (node.nodeName === "TEXTAREA" || node.nodeName === "SELECT") {
|
||||||
|
clone.value = node.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initNode(node) {
|
||||||
|
if (node.nodeType === 1) {
|
||||||
|
node.scrollTop = node._scrollTop;
|
||||||
|
node.scrollLeft = node._scrollLeft;
|
||||||
|
|
||||||
|
var child = node.firstChild;
|
||||||
function isElementNode(node) {
|
while(child) {
|
||||||
return node.nodeType === Node.ELEMENT_NODE;
|
initNode(child);
|
||||||
|
child = child.nextSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(ownerDocument, containerDocument, width, height, options, x ,y) {
|
module.exports = function(ownerDocument, containerDocument, width, height, options, x ,y) {
|
||||||
labelCanvasElements(ownerDocument);
|
var documentElement = cloneNode(ownerDocument.documentElement, options.javascriptEnabled);
|
||||||
var documentElement = isIE9() ? cloneNodeIE9(ownerDocument.documentElement, options.javascriptEnabled) : ownerDocument.documentElement.cloneNode(true);
|
|
||||||
var container = containerDocument.createElement("iframe");
|
var container = containerDocument.createElement("iframe");
|
||||||
|
|
||||||
container.className = "html2canvas-container";
|
container.className = "html2canvas-container";
|
||||||
@ -96,19 +74,21 @@ module.exports = function(ownerDocument, containerDocument, width, height, optio
|
|||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
var documentClone = container.contentWindow.document;
|
var documentClone = container.contentWindow.document;
|
||||||
|
|
||||||
cloneNodeValues(ownerDocument.documentElement, documentElement, "textarea");
|
|
||||||
cloneNodeValues(ownerDocument.documentElement, documentElement, "select");
|
|
||||||
|
|
||||||
/* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
|
/* Chrome doesn't detect relative background-images assigned in inline <style> sheets when fetched through getComputedStyle
|
||||||
if window url is about:blank, we can assign the url to current by writing onto the document
|
if window url is about:blank, we can assign the url to current by writing onto the document
|
||||||
*/
|
*/
|
||||||
container.contentWindow.onload = container.onload = function() {
|
container.contentWindow.onload = container.onload = function() {
|
||||||
var interval = setInterval(function() {
|
var interval = setInterval(function() {
|
||||||
if (documentClone.body.childNodes.length > 0) {
|
if (documentClone.body.childNodes.length > 0) {
|
||||||
cloneCanvasContents(ownerDocument, documentClone);
|
initNode(documentClone.documentElement);
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
if (options.type === "view") {
|
if (options.type === "view") {
|
||||||
container.contentWindow.scrollTo(x, y);
|
container.contentWindow.scrollTo(x, y);
|
||||||
|
if ((/(iPad|iPhone|iPod)/g).test(navigator.userAgent) && (container.contentWindow.scrollY !== y || container.contentWindow.scrollX !== x)) {
|
||||||
|
documentClone.documentElement.style.top = (-y) + "px";
|
||||||
|
documentClone.documentElement.style.left = (-x) + "px";
|
||||||
|
documentClone.documentElement.style.position = 'absolute';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resolve(container);
|
resolve(container);
|
||||||
}
|
}
|
||||||
@ -119,7 +99,7 @@ module.exports = function(ownerDocument, containerDocument, width, height, optio
|
|||||||
documentClone.write("<!DOCTYPE html><html></html>");
|
documentClone.write("<!DOCTYPE html><html></html>");
|
||||||
// Chrome scrolls the parent document for some reason after the write to the cloned window???
|
// Chrome scrolls the parent document for some reason after the write to the cloned window???
|
||||||
restoreOwnerScroll(ownerDocument, x, y);
|
restoreOwnerScroll(ownerDocument, x, y);
|
||||||
documentClone.replaceChild(options.javascriptEnabled === true ? documentClone.adoptNode(documentElement) : removeScriptNodes(documentClone.adoptNode(documentElement)), documentClone.documentElement);
|
documentClone.replaceChild(documentClone.adoptNode(documentElement), documentClone.documentElement);
|
||||||
documentClone.close();
|
documentClone.close();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
10
src/core.js
10
src/core.js
@ -57,10 +57,18 @@ html2canvas.NodeContainer = NodeContainer;
|
|||||||
html2canvas.log = log;
|
html2canvas.log = log;
|
||||||
html2canvas.utils = utils;
|
html2canvas.utils = utils;
|
||||||
|
|
||||||
module.exports = (typeof(document) === "undefined" || typeof(Object.create) !== "function" || typeof(document.createElement("canvas").getContext) !== "function") ? function() {
|
var html2canvasExport = (typeof(document) === "undefined" || typeof(Object.create) !== "function" || typeof(document.createElement("canvas").getContext) !== "function") ? function() {
|
||||||
return Promise.reject("No canvas support");
|
return Promise.reject("No canvas support");
|
||||||
} : html2canvas;
|
} : html2canvas;
|
||||||
|
|
||||||
|
module.exports = html2canvasExport;
|
||||||
|
|
||||||
|
if (typeof(define) === 'function' && define.amd) {
|
||||||
|
define('html2canvas', [], function() {
|
||||||
|
return html2canvasExport;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderDocument(document, options, windowWidth, windowHeight, html2canvasIndex) {
|
function renderDocument(document, options, windowWidth, windowHeight, html2canvasIndex) {
|
||||||
return createWindowClone(document, document, windowWidth, windowHeight, options, document.defaultView.pageXOffset, document.defaultView.pageYOffset).then(function(container) {
|
return createWindowClone(document, document, windowWidth, windowHeight, options, document.defaultView.pageXOffset, document.defaultView.pageYOffset).then(function(container) {
|
||||||
log("Document cloned");
|
log("Document cloned");
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
var GradientContainer = require('./gradientcontainer');
|
var GradientContainer = require('./gradientcontainer');
|
||||||
var Color = require('./color');
|
var Color = require('./color');
|
||||||
|
|
||||||
|
var COLOR_STOP_REGEXP = /^\s*(.*)\s*(\d{1,3})?(%|px)?$/;
|
||||||
|
|
||||||
function LinearGradientContainer(imageData) {
|
function LinearGradientContainer(imageData) {
|
||||||
GradientContainer.apply(this, arguments);
|
GradientContainer.apply(this, arguments);
|
||||||
this.type = this.TYPES.LINEAR;
|
this.type = this.TYPES.LINEAR;
|
||||||
@ -41,13 +43,15 @@ function LinearGradientContainer(imageData) {
|
|||||||
this.y1 = 1;
|
this.y1 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.colorStops = imageData.args.slice(hasDirection ? 1 : 0).map(function(colorStop) {
|
this.colorStops = imageData.args.slice(hasDirection ? 1 : 0)
|
||||||
var colorStopMatch = colorStop.match(this.stepRegExp);
|
.map(function(colorStop) { return colorStop.match(COLOR_STOP_REGEXP);})
|
||||||
return {
|
.filter(function(colorStopMatch) { return !!colorStopMatch;})
|
||||||
color: new Color(colorStopMatch[1]),
|
.map(function(colorStopMatch) {
|
||||||
stop: colorStopMatch[3] === "%" ? colorStopMatch[2] / 100 : null
|
return {
|
||||||
};
|
color: new Color(colorStopMatch[1]),
|
||||||
}, this);
|
stop: colorStopMatch[3] === "%" ? colorStopMatch[2] / 100 : null
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
if (this.colorStops[0].stop === null) {
|
if (this.colorStops[0].stop === null) {
|
||||||
this.colorStops[0].stop = 0;
|
this.colorStops[0].stop = 0;
|
||||||
|
@ -258,7 +258,7 @@ NodeContainer.prototype.getValue = function() {
|
|||||||
return value.length === 0 ? (this.node.placeholder || "") : value;
|
return value.length === 0 ? (this.node.placeholder || "") : value;
|
||||||
};
|
};
|
||||||
|
|
||||||
NodeContainer.prototype.MATRIX_PROPERTY = /(matrix)\((.+)\)/;
|
NodeContainer.prototype.MATRIX_PROPERTY = /(matrix|matrix3d)\((.+)\)/;
|
||||||
NodeContainer.prototype.TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
|
NodeContainer.prototype.TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
|
||||||
NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
|
NodeContainer.prototype.TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
|
||||||
NodeContainer.prototype.CLIP = /^rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)$/;
|
NodeContainer.prototype.CLIP = /^rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)$/;
|
||||||
@ -273,6 +273,11 @@ function parseMatrix(match) {
|
|||||||
return match[2].split(",").map(function(s) {
|
return match[2].split(",").map(function(s) {
|
||||||
return parseFloat(s.trim());
|
return parseFloat(s.trim());
|
||||||
});
|
});
|
||||||
|
} else if (match && match[1] === "matrix3d") {
|
||||||
|
var matrix3d = match[2].split(",").map(function(s) {
|
||||||
|
return parseFloat(s.trim());
|
||||||
|
});
|
||||||
|
return [matrix3d[0], matrix3d[1], matrix3d[4], matrix3d[5], matrix3d[12], matrix3d[13]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,14 +617,14 @@ function calculateCurvePoints(bounds, borderRadius, borders) {
|
|||||||
width = bounds.width,
|
width = bounds.width,
|
||||||
height = bounds.height,
|
height = bounds.height,
|
||||||
|
|
||||||
tlh = borderRadius[0][0],
|
tlh = borderRadius[0][0] < width / 2 ? borderRadius[0][0] : width / 2,
|
||||||
tlv = borderRadius[0][1],
|
tlv = borderRadius[0][1] < height / 2 ? borderRadius[0][1] : height / 2,
|
||||||
trh = borderRadius[1][0],
|
trh = borderRadius[1][0] < width / 2 ? borderRadius[1][0] : width / 2,
|
||||||
trv = borderRadius[1][1],
|
trv = borderRadius[1][1] < height / 2 ? borderRadius[1][1] : height / 2,
|
||||||
brh = borderRadius[2][0],
|
brh = borderRadius[2][0] < width / 2 ? borderRadius[2][0] : width / 2,
|
||||||
brv = borderRadius[2][1],
|
brv = borderRadius[2][1] < height / 2 ? borderRadius[2][1] : height / 2,
|
||||||
blh = borderRadius[3][0],
|
blh = borderRadius[3][0] < width / 2 ? borderRadius[3][0] : width / 2,
|
||||||
blv = borderRadius[3][1];
|
blv = borderRadius[3][1] < height / 2 ? borderRadius[3][1] : height / 2;
|
||||||
|
|
||||||
var topWidth = width - trh,
|
var topWidth = width - trh,
|
||||||
rightHeight = height - brv,
|
rightHeight = height - brv,
|
||||||
|
141
tests/cases/acid2.html
Normal file
141
tests/cases/acid2.html
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>The Second Acid Test</title>
|
||||||
|
<style type="text/css">
|
||||||
|
/* section numbers refer to CSS2.1 */
|
||||||
|
|
||||||
|
/* page setup */
|
||||||
|
html { font: 12px sans-serif; margin: 0; padding: 0; overflow: hidden; /* hides scrollbars on viewport, see 11.1.1:3 */ background: white; color: red; }
|
||||||
|
body { margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
/* introduction message */
|
||||||
|
.intro { font: 2em sans-serif; margin: 3.5em 2em; padding: 0.5em; border: solid thin; background: white; color: black; position: relative; z-index: 2; /* should cover the black and red bars that are fixed-positioned */ }
|
||||||
|
.intro * { font: inherit; margin: 0; padding: 0; }
|
||||||
|
.intro h1 { font-size: 1em; font-weight: bolder; margin: 0; padding: 0; }
|
||||||
|
.intro :link { color: blue; }
|
||||||
|
.intro :visited { color: purple; }
|
||||||
|
|
||||||
|
/* picture setup */
|
||||||
|
#top { margin: 100em 3em 0; padding: 2em 0 0 .5em; text-align: left; font: 2em/24px sans-serif; color: navy; white-space: pre; } /* "Hello World!" text */
|
||||||
|
.picture { position: relative; border: 1em solid transparent; margin: 0 0 100em 3em; } /* containing block for face */
|
||||||
|
.picture { background: red; } /* overriden by preferred stylesheet below */
|
||||||
|
|
||||||
|
/* top line of face (scalp): fixed positioning and min/max height/width */
|
||||||
|
.picture p { position: fixed; margin: 0; padding: 0; border: 0; top: 9em; left: 11em; width: 140%; max-width: 4em; height: 8px; min-height: 1em; max-height: 2mm; /* min-height overrides max-height, see 10.7 */ background: black; border-bottom: 0.5em yellow solid; }
|
||||||
|
|
||||||
|
/* bits that shouldn't be part of the top line (and shouldn't be visible at all): HTML parsing, "+" combinator, stacking order */
|
||||||
|
.picture p.bad { border-bottom: red solid; /* shouldn't matter, because the "p + table + p" rule below should match it too, thus hiding it */ }
|
||||||
|
.picture p + p { background: maroon; z-index: 1; } /* shouldn't match anything */
|
||||||
|
.picture p + table + p { margin-top: 3em; /* should end up under the absolutely positioned table below, and thus not be visible */ }
|
||||||
|
|
||||||
|
/* second line of face: attribute selectors, float positioning */
|
||||||
|
[class~=one].first.one { position: absolute; top: 0; margin: 36px 0 0 60px; padding: 0; border: black 2em; border-style: none solid; /* shrink wraps around float */ }
|
||||||
|
[class~=one][class~=first] [class=second\ two][class="second two"] { float: right; width: 48px; height: 12px; background: yellow; margin: 0; padding: 0; } /* only content of abs pos block */
|
||||||
|
|
||||||
|
/* third line of face: width and overflow */
|
||||||
|
.forehead { margin: 4em; width: 8em; border-left: solid black 1em; border-right: solid black 1em; background: red url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4%2F58BAAT%2FAf9jgNErAAAAAElFTkSuQmCC); /* that's a 1x1 yellow pixel PNG */ }
|
||||||
|
.forehead * { width: 12em; line-height: 1em; }
|
||||||
|
|
||||||
|
/* class selectors headache */
|
||||||
|
.two.error.two { background: maroon; } /* shouldn't match */
|
||||||
|
.forehead.error.forehead { background: red; } /* shouldn't match */
|
||||||
|
[class=second two] { background: red; } /* this should be ignored (invalid selector -- grammar says it only accepts IDENTs or STRINGs) */
|
||||||
|
|
||||||
|
/* fourth and fifth lines of face, with eyes: paint order test (see appendix E) and fixed backgrounds */
|
||||||
|
/* the two images are identical: 2-by-2 squares with the top left
|
||||||
|
and bottom right pixels set to yellow and the other two set to
|
||||||
|
transparent. Since they are offset by one pixel from each other,
|
||||||
|
the second one paints exactly over the transparent parts of the
|
||||||
|
first one, thus creating a solid yellow block. */
|
||||||
|
.eyes { position: absolute; top: 5em; left: 3em; margin: 0; padding: 0; background: red; }
|
||||||
|
#eyes-a { height: 0; line-height: 2em; text-align: right; } /* contents should paint top-most because they're inline */
|
||||||
|
#eyes-a object { display: inline; vertical-align: bottom; }
|
||||||
|
#eyes-a object[type] { width: 7.5em; height: 2.5em; } /* should have no effect since that object should fallback to being inline (height/width don't apply to inlines) */
|
||||||
|
#eyes-a object object object { border-right: solid 1em black; padding: 0 12px 0 11px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAABnRSTlMAAAAAAABupgeRAAAABmJLR0QA%2FwD%2FAP%2BgvaeTAAAAEUlEQVR42mP4%2F58BCv7%2FZwAAHfAD%2FabwPj4AAAAASUVORK5CYII%3D) fixed 1px 0; }
|
||||||
|
#eyes-b { float: left; width: 10em; height: 2em; background: fixed url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAIAAAD91JpzAAAABnRSTlMAAAAAAABupgeRAAAABmJLR0QA%2FwD%2FAP%2BgvaeTAAAAEUlEQVR42mP4%2F58BCv7%2FZwAAHfAD%2FabwPj4AAAAASUVORK5CYII%3D); border-left: solid 1em black; border-right: solid 1em red; } /* should paint in the middle layer because it is a float */
|
||||||
|
#eyes-c { display: block; background: red; border-left: 2em solid yellow; width: 10em; height: 2em; } /* should paint bottom most because it is a block */
|
||||||
|
|
||||||
|
/* lines six to nine, with nose: auto margins */
|
||||||
|
.nose { float: left; margin: -2em 2em -1em; border: solid 1em black; border-top: 0; min-height: 80%; height: 60%; max-height: 3em; /* percentages become auto (see 10.5 and 10.7) and intrinsic height is more than 3em, so 3em wins */ padding: 0; width: 12em; }
|
||||||
|
.nose > div { padding: 1em 1em 3em; height: 0; background: yellow; }
|
||||||
|
.nose div div { width: 2em; height: 2em; background: red; margin: auto; }
|
||||||
|
.nose :hover div { border-color: blue; }
|
||||||
|
.nose div:hover :before { border-bottom-color: inherit; }
|
||||||
|
.nose div:hover :after { border-top-color: inherit; }
|
||||||
|
.nose div div:before { display: block; border-style: none solid solid; border-color: red yellow black yellow; border-width: 1em; content: ''; height: 0; }
|
||||||
|
.nose div :after { display: block; border-style: solid solid none; border-color: black yellow red yellow; border-width: 1em; content: ''; height: 0; }
|
||||||
|
|
||||||
|
/* between lines nine and ten: margin collapsing with 'float' and 'clear' */
|
||||||
|
.empty { margin: 6.25em; height: 10%; /* computes to auto which makes it empty per 8.3.1:7 (own margins) */ }
|
||||||
|
.empty div { margin: 0 2em -6em 4em; }
|
||||||
|
.smile { margin: 5em 3em; clear: both; /* clearance is negative (see 8.3.1 and 9.5.1) */ }
|
||||||
|
|
||||||
|
/* line ten and eleven: containing block for abs pos */
|
||||||
|
.smile div { margin-top: 0.25em; background: black; width: 12em; height: 2em; position: relative; bottom: -1em; }
|
||||||
|
.smile div div { position: absolute; top: 0; right: 1em; width: auto; height: 0; margin: 0; border: yellow solid 1em; }
|
||||||
|
|
||||||
|
/* smile (over lines ten and eleven): backgrounds behind borders, inheritance of 'float', nested floats, negative heights */
|
||||||
|
.smile div div span { display: inline; margin: -1em 0 0 0; border: solid 1em transparent; border-style: none solid; float: right; background: black; height: 1em; }
|
||||||
|
.smile div div span em { float: inherit; border-top: solid yellow 1em; border-bottom: solid black 1em; } /* zero-height block; width comes from (zero-height) child. */
|
||||||
|
.smile div div span em strong { width: 6em; display: block; margin-bottom: -1em; /* should have no effect, since parent has top&bottom borders, so this margin doesn't collapse */ }
|
||||||
|
|
||||||
|
/* line twelve: line-height */
|
||||||
|
.chin { margin: -4em 4em 0; width: 8em; line-height: 1em; border-left: solid 1em black; border-right: solid 1em black; background: yellow url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAFSDNYfAAAAaklEQVR42u3XQQrAIAwAQeP%2F%2F6wf8CJBJTK9lnQ7FpHGaOurt1I34nfH9pMMZAZ8BwMGEvvh%2BBsJCAgICLwIOA8EBAQEBAQEBAQEBK79H5RfIQAAAAAAAAAAAAAAAAAAAAAAAAAAAID%2FABMSqAfj%2FsLmvAAAAABJRU5ErkJggg%3D%3D) /* 64x64 red square */ no-repeat fixed /* shouldn't be visible unless the smiley is moved to the top left of the viewport */; }
|
||||||
|
.chin div { display: inline; font: 2px/4px serif; }
|
||||||
|
|
||||||
|
/* line thirteen: cascade and selector tests */
|
||||||
|
.parser-container div { color: maroon; border: solid; color: orange; } /* setup */
|
||||||
|
div.parser-container * { border-color: black; /* overrides (implied) border-color on previous line */ } /* setup */
|
||||||
|
* div.parser { border-width: 0 2em; /* overrides (implied) declarations on earlier line */ } /* setup */
|
||||||
|
|
||||||
|
/* line thirteen continued: parser tests */
|
||||||
|
.parser { /* comment parsing test -- comment ends before the end of this line, the backslash should have no effect: \*/ }
|
||||||
|
.parser { margin: 0 5em 1em; padding: 0 1em; width: 2em; height: 1em; error: \}; background: yellow; } /* setup with parsing test */
|
||||||
|
* html .parser { background: gray; }
|
||||||
|
\.parser { padding: 2em; }
|
||||||
|
.parser { m\argin: 2em; };
|
||||||
|
.parser { height: 3em; }
|
||||||
|
.parser { width: 200; }
|
||||||
|
.parser { border: 5em solid red ! error; }
|
||||||
|
.parser { background: red pink; }
|
||||||
|
|
||||||
|
/* line fourteen (last line of face): table */
|
||||||
|
ul { display: table; padding: 0; margin: -1em 7em 0; background: red; }
|
||||||
|
ul li { padding: 0; margin: 0; }
|
||||||
|
ul li.first-part { display: table-cell; height: 1em; width: 1em; background: black; }
|
||||||
|
ul li.second-part { display: table; height: 1em; width: 1em; background: black; } /* anonymous table cell wraps around this */
|
||||||
|
ul li.third-part { display: table-cell; height: 0.5em; /* gets stretched to fit row */ width: 1em; background: black; }
|
||||||
|
ul li.fourth-part { list-style: none; height: 1em; width: 1em; background: black; } /* anonymous table cell wraps around this */
|
||||||
|
|
||||||
|
/* bits that shouldn't appear: inline alignment in cells */
|
||||||
|
.image-height-test { height: 10px; overflow: hidden; font: 20em serif; } /* only the area between the top of the line box and the top of the image should be visible */
|
||||||
|
table { margin: 0; border-spacing: 0; }
|
||||||
|
td { padding: 0; }
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<link rel="appendix stylesheet" href="data:text/css,.picture%20%7B%20background%3A%20none%3B%20%7D"> <!-- this stylesheet should be applied by default -->
|
||||||
|
<script type="text/javascript" src="../test.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="margin: 70px;"></div>
|
||||||
|
<div class="picture">
|
||||||
|
<p><table><tr><td></table><p class="bad"> <!-- <table> closes <p> per the HTML4 DTD -->
|
||||||
|
<blockquote class="first one"><address class="second two"></address></blockquote>
|
||||||
|
<div class="forehead"><div> </div></div>
|
||||||
|
<div class="eyes"><div id="eyes-a"><object data="data:application/x-unknown,ERROR"><object data="http://www.damowmow.com/404/" type="text/html"><object data="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAAYCAYAAAFy7sgCAAAGsUlEQVRo3u2ZbWwcZxHHf3s%2B7LNbO3ZjXBtowprGODRX0qpNQCjmJKuVKhMl1P2AkCwhFOIKkCBSm9IXavGFKAixIAECwkmWo5MrhRI3Ub40IEwQgp6aIDg3Cd6eEqyIHEteah%2B1E69vhw%2BZtTaX8704ZzkKjHS6271nZ56ZZ%2BY%2F%2F%2BdZKF%2FCwYshx3EkkggLsD1v4FQkEZZYLCbAKyG9%2Ba9EIsG6hnUAf8x74K3aUC3j4%2BM54HcsR2oAIomwZOezkv%2FnSHpYNh%2BNCmAE7xv94zvFdd1bHsjMZmQkPSxAJP%2B%2FfuBLwK54PC7JZFKAVJmzXLBt2w%2FMvcDLwIb8QS8CeJ4nkURYIomw7J%2FYJ8BvSiiXptGGxWds2%2Fa9%2Bnaxh%2BYAD%2Bgt04NDgABTpQY2cvvSFLzw86gWeBVwC8SzlOSv2YeBPfmDBoBHgKmR9LBEEmHZfDTqGykqfkUE0nA78BzQGfSgUeP3wNeTXwXg7MwZDhw4UHL6ra2ti79%2FOvljgG8AZ4H64Lhm4MvAocxsRppGG%2FxcXihlwLIs6R%2FfKV2HO%2F26uA94pdDYUKUZUU7W1RQYXA98Gnhaf5%2FXWX0HeAHYoQonqa4sZSOsSWMCWeC9Yko%2BCQwBe4E6oNc0Tc91XTl1%2BaTsn9gnI%2Blhyc5nZWxsrBIkKSbl2tiic3tW53YDEwOKaoFBrcOfqKee53lG9xsPMjV784r%2F4lO%2FpPvyJ9iyZcuvFSaXK5XYeAZ4CDgGvB3MS4B54LQuWYPeuy4iRFsevsXqpuYoqVQKIH2bK1CuDQNo11o4XUzh%2FcDWYIe1LEtyuZx4niee54njOGKapgfsqlL%2Bl2OjEXg8nxrc1dJ0h3hbtL%2BGCtz7KPBF4CuBe9uB15VafE8hr9qylI3HgG8C2%2FK7VyHZoJj7MrBRm30qFotJMpkU27YlHo%2F7Ha5a%2BV%2FKRkSJ4KuKRLVLKapTjB1SzAVIjY2NSXY%2BKyPpYdk%2FsU9OXT4pruv6BdZbBQfKsVGnvWlIe1VB6VQO8JxC1vZYLCbZ%2BaxsPhpdZDyRRFhG0sPiOE6ldKBg2lRg4xF1YCDIIIKN7DGgD3gH%2BBXwejKZfPrs2tPs%2FvPN2bKuYR1nd7xLKBSSJeqoXKnERjPwNWAG%2BLn2rZuM%2B4Tpml6vaWlp4eLcxVusZq5lCgVgOVKJjRqdX86ffL4D5wIoZACnTpw4wRMdT96i%2FImOJxERAs4uVyqxUacF%2FPdiCj%2BjdRBRGFtwXVdG0sPSdbhTmkYbpH98p2RmM2JZlig1vl0GWo4NQ%2Fn%2Bs5pKRXfwjweaxy7TND3HcRZbfC6X8xVPVQlGy7WxVWlO5XRXFXm6EZmrQuSXYyPE3SiVoEhE6Wyr0u2rumO6zv%2B21AFdQAswC1wCMuUCXCmyWQus103Qg8qlDO0lxwOb%2Fl4FiK3AB3VS%2FuKKLtK%2FgbeAnwG%2FvUODuRw%2FFrR0H1UC75fwu8oJ%2FhFsW5VIG%2FBUgEIN6Y65O4AHu4Ap0zQ9y7LEcZyb9lRBUHQcRyzL8unZVBW5bFWAvAp%2BhDQ2g4F47dUYtlU6obXA54DnVdFLekjUGGifh4AFy7LEdV3xj3X9I66m0QZpGm2QrsOd0j%2B%2BU0bSw5KZzYjrun6HWlAd961i4FfCj0aN1Usau%2Bc1lmuXPFwvAEumUut7tQQvAb%2FXb%2FT0bCAej9cODg7yt%2Bm%2F8q2%2F7OUHZ76PnZ1k2p0mJzlykmPancbOTnL0whHs7CQfb%2B5mx2d3sH79%2BtCRI0c6FeaOr9ICrIQfLvA%2B8BGNXxi4R6HrisJVUWrxAVW2oMFf0Aczim8o3kV6enowDIPjF9%2Fk%2BMU3S3rrjzMMg56eHr%2BxP7qKFbASfojG6kpeDGs1tiW53RxwWT%2Bin5q8w4xpQK5evQpAR30H7ZH2khNvj7TTUd8BgD4rqmu1ZKX8qNeY%2BfHz4zlXDgT5E8tpCTUq7XSBC4Euv8227TV9fX1E73%2BYtvo27BmbS9cvFVTY3bSRFza9yOcf6Gfmygy7d%2B%2Fm%2FPnzF4DvrsBLhnJlJfwIKXxv1PheAE4qK6p4H9AGbNKTuhngBPBPXYRe4IemaT5kWZbR19fHNbmGnZ1k4r3U4glDR30Hm5qjbGjsImJEOHbsGHv27JFz5869o0eFq01Jq%2BmHAXwI6FFKagMTgHM7GzFDS%2BoeLSMv7zjzC9x4Y7gxFovVDAwMEI1GaWlpWSzRVCrFwYMH%2FXfxZ4AfAa8B%2F7lDaGg1%2FQgp43lfK0yqtRMuJa3ceKe5DfgYsCYAZ2ngD8CfAkzqTpW7xY%2F%2FSznyX%2FVeUb2kVmX4AAAAAElFTkSuQmCC">ERROR</object></object></object></div><div id="eyes-b"></div><div id="eyes-c"></div></div> <!-- that's a PNG with 8bit alpha containing two eyes -->
|
||||||
|
<div class="nose"><div><div></div></div></div>
|
||||||
|
<div class="empty"><div></div></div>
|
||||||
|
<div class="smile"><div><div><span><em><strong></strong></em></span></div></div></div>
|
||||||
|
<div class="chin"><div> </div></div>
|
||||||
|
<div class="parser-container"><div class="parser"><!-- ->ERROR<!- --></div></div> <!-- two dashes is what delimits a comment, so the text "->ERROR<!-" earlier on this line is actually part of a comment -->
|
||||||
|
<ul>
|
||||||
|
<li class="first-part"></li>
|
||||||
|
<li class="second-part"></li>
|
||||||
|
<li class="third-part"></li>
|
||||||
|
<li class="fourth-part"></li>
|
||||||
|
</ul>
|
||||||
|
<div class="image-height-test"><table><tr><td><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAFSDNYfAAAAaklEQVR42u3XQQrAIAwAQeP%2F%2F6wf8CJBJTK9lnQ7FpHGaOurt1I34nfH9pMMZAZ8BwMGEvvh%2BBsJCAgICLwIOA8EBAQEBAQEBAQEBK79H5RfIQAAAAAAAAAAAAAAAAAAAAAAAAAAAID%2FABMSqAfj%2FsLmvAAAAABJRU5ErkJggg%3D%3D" alt=""></td></tr></table></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -112,6 +112,10 @@
|
|||||||
.linearGradient8 {
|
.linearGradient8 {
|
||||||
background: linear-gradient(to top left, #fff 0%, #00263c 100%);
|
background: linear-gradient(to top left, #fff 0%, #00263c 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.linearGradient9 {
|
||||||
|
background: linear-gradient(to top left, white 0%, black 100%);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
@ -125,6 +129,7 @@
|
|||||||
<div class="linearGradient6"> </div>
|
<div class="linearGradient6"> </div>
|
||||||
<div class="linearGradient7"> </div>
|
<div class="linearGradient7"> </div>
|
||||||
<div class="linearGradient8"> </div>
|
<div class="linearGradient8"> </div>
|
||||||
|
<div class="linearGradient9"> </div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -57,6 +57,12 @@
|
|||||||
background-clip: padding-box;
|
background-clip: padding-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.box6 {
|
||||||
|
height: 200px;
|
||||||
|
width: 200px;
|
||||||
|
border-radius: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
background: #3a84c3;
|
background: #3a84c3;
|
||||||
}
|
}
|
||||||
@ -69,5 +75,6 @@
|
|||||||
<div class="box3"> </div>
|
<div class="box3"> </div>
|
||||||
<div class="box4"> </div>
|
<div class="box4"> </div>
|
||||||
<div class="box5"> </div>
|
<div class="box5"> </div>
|
||||||
|
<div class="box6"> </div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -67,26 +67,28 @@ describe('Text-shadow', function() {
|
|||||||
var index = i + 1;
|
var index = i + 1;
|
||||||
var container = new NodeContainer(node, null);
|
var container = new NodeContainer(node, null);
|
||||||
var shadows = container.parseTextShadows();
|
var shadows = container.parseTextShadows();
|
||||||
if (i === 0) {
|
it(node.style.textShadow, function() {
|
||||||
expect(shadows.length).to.equal(0);
|
if (i === 0) {
|
||||||
} else {
|
expect(shadows.length).to.equal(0);
|
||||||
expect(shadows.length).to.equal(i >= 6 ? 2 : 1);
|
|
||||||
expect(shadows[0].offsetX).to.equal(i);
|
|
||||||
expect(shadows[0].offsetY).to.equal(i);
|
|
||||||
if (i < 2) {
|
|
||||||
expect(shadows[0].color.toString()).to.equal('rgba(0,0,0,0)');
|
|
||||||
} else if (i % 2 === 0) {
|
|
||||||
expect(shadows[0].color.toString()).to.equal('rgb(2,2,2)');
|
|
||||||
} else {
|
} else {
|
||||||
var opacity = '0.2';
|
expect(shadows.length).to.equal(i >= 6 ? 2 : 1);
|
||||||
expect(shadows[0].color.toString()).to.match(/rgba\(2,2,2,(0.2|0\.199219)\)/);
|
expect(shadows[0].offsetX).to.equal(i);
|
||||||
}
|
expect(shadows[0].offsetY).to.equal(i);
|
||||||
|
if (i < 2) {
|
||||||
|
expect(shadows[0].color.toString()).to.equal('rgba(0,0,0,0)');
|
||||||
|
} else if (i % 2 === 0) {
|
||||||
|
expect(shadows[0].color.toString()).to.equal('rgb(2,2,2)');
|
||||||
|
} else {
|
||||||
|
var opacity = '0.2';
|
||||||
|
expect(shadows[0].color.toString()).to.match(/rgba\(2,2,2,(0.2|0\.199219)\)/);
|
||||||
|
}
|
||||||
|
|
||||||
// only testing blur once
|
// only testing blur once
|
||||||
if (i === 1) {
|
if (i === 1) {
|
||||||
expect(shadows[0].blur).to.equal('1');
|
expect(shadows[0].blur).to.equal('1');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@
|
|||||||
CanvasRenderer.prototype.text = function(text) {
|
CanvasRenderer.prototype.text = function(text) {
|
||||||
expect(text).to.equal('updated');
|
expect(text).to.equal('updated');
|
||||||
};
|
};
|
||||||
html2canvas(document.querySelector("#block4"), {renderer: CanvasRenderer, strict: true, logging: true, removeContainer: false}).then(function(canvas) {
|
html2canvas(document.querySelector("#block4"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
|
||||||
expect(canvas.width).to.equal(200);
|
expect(canvas.width).to.equal(200);
|
||||||
expect(canvas.height).to.equal(200);
|
expect(canvas.height).to.equal(200);
|
||||||
done();
|
done();
|
||||||
@ -138,7 +138,7 @@
|
|||||||
CanvasRenderer.prototype.text = function(text) {
|
CanvasRenderer.prototype.text = function(text) {
|
||||||
expect(text).to.equal('3');
|
expect(text).to.equal('3');
|
||||||
};
|
};
|
||||||
html2canvas(document.querySelector("#block5"), {renderer: CanvasRenderer, strict: true, logging: true, removeContainer: false}).then(function(canvas) {
|
html2canvas(document.querySelector("#block5"), {renderer: CanvasRenderer, strict: true}).then(function(canvas) {
|
||||||
expect(canvas.width).to.equal(200);
|
expect(canvas.width).to.equal(200);
|
||||||
expect(canvas.height).to.equal(200);
|
expect(canvas.height).to.equal(200);
|
||||||
done();
|
done();
|
||||||
|
@ -35,6 +35,15 @@ describe("Gradients", function() {
|
|||||||
" to(rgb(191, 110, 78))"
|
" to(rgb(191, 110, 78))"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
method: 'linear-gradient',
|
||||||
|
args: [
|
||||||
|
"0deg",
|
||||||
|
" rgb(221, 221, 221)",
|
||||||
|
" rgb(221, 221, 221) 50%",
|
||||||
|
" transparent 50%"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
method: "radial-gradient",
|
method: "radial-gradient",
|
||||||
args: [
|
args: [
|
||||||
@ -97,7 +106,7 @@ describe("Gradients", function() {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
$('#backgroundGradients div').each(function(i, node) {
|
[].slice.call(document.querySelectorAll('#backgroundGradients div'), 0).forEach(function(node, i) {
|
||||||
var container = new html2canvas.NodeContainer(node, null);
|
var container = new html2canvas.NodeContainer(node, null);
|
||||||
var value = container.css("backgroundImage");
|
var value = container.css("backgroundImage");
|
||||||
it(value, function() {
|
it(value, function() {
|
||||||
|
@ -108,6 +108,12 @@
|
|||||||
/* W3C */
|
/* W3C */
|
||||||
background: linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
|
background: linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.linearGradient4 {
|
||||||
|
background: -webkit-linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%);
|
||||||
|
background: linear-gradient(0deg, #ddd, #ddd 50%, transparent 50%);
|
||||||
|
}
|
||||||
|
|
||||||
.radialGradient {
|
.radialGradient {
|
||||||
background: -moz-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
|
background: -moz-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
|
||||||
background: -webkit-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
|
background: -webkit-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
|
||||||
@ -156,6 +162,7 @@
|
|||||||
<div class="linearGradientSimple"></div>
|
<div class="linearGradientSimple"></div>
|
||||||
<div class="linearGradientWithStops"></div>
|
<div class="linearGradientWithStops"></div>
|
||||||
<div class="linearGradient3"></div>
|
<div class="linearGradient3"></div>
|
||||||
|
<div class="linearGradient4"></div>
|
||||||
<div class="radialGradient"></div>
|
<div class="radialGradient"></div>
|
||||||
<div class="radialGradient2"></div>
|
<div class="radialGradient2"></div>
|
||||||
<div class="radialGradient3"></div>
|
<div class="radialGradient3"></div>
|
||||||
|
@ -12,6 +12,12 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="mocha"></div>
|
<div id="mocha"></div>
|
||||||
<script>mocha.setup('bdd')</script>
|
<script>mocha.setup('bdd')</script>
|
||||||
|
<div id="scroll-render" style="height: 200px; width: 200px;">
|
||||||
|
<div style="height: 500px; width: 400px;overflow: scroll;" id="scrollable">
|
||||||
|
<div style="height: 500px;background: red;"></div>
|
||||||
|
<div style="height: 650px; background: green"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div style="height: 2200px;"></div>
|
<div style="height: 2200px;"></div>
|
||||||
<div style="height: 500px;background: green;"><a name="content">content</a></div>
|
<div style="height: 500px;background: green;"><a name="content">content</a></div>
|
||||||
<script>
|
<script>
|
||||||
@ -32,7 +38,7 @@
|
|||||||
window.location.hash = "#content";
|
window.location.hash = "#content";
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var top = $(window).scrollTop();
|
var top = $(window).scrollTop();
|
||||||
html2canvas(document.body, {type: 'view', removeContainer: false}).then(function () {
|
html2canvas(document.body, {type: 'view'}).then(function () {
|
||||||
var currentTop = $(window).scrollTop();
|
var currentTop = $(window).scrollTop();
|
||||||
window.location.hash = "";
|
window.location.hash = "";
|
||||||
expect(currentTop).to.be.greaterThan(1500);
|
expect(currentTop).to.be.greaterThan(1500);
|
||||||
@ -45,8 +51,35 @@
|
|||||||
});
|
});
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("with content scroll", function (done) {
|
||||||
|
$("#scrollable").scrollTop(500);
|
||||||
|
setTimeout(function() {
|
||||||
|
html2canvas(document.querySelector("#scroll-render")).then(function (canvas) {
|
||||||
|
expect($("#scrollable").scrollTop()).to.equal(500);
|
||||||
|
document.body.appendChild(canvas);
|
||||||
|
expect(canvas.width).to.equal(200);
|
||||||
|
expect(canvas.height).to.equal(200);
|
||||||
|
validCanvasPixels(canvas);
|
||||||
|
done();
|
||||||
|
}).catch(function (error) {
|
||||||
|
done(error);
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function validCanvasPixels(canvas) {
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
var data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
|
||||||
|
for (var i = 0, len = 200*199*4; i < len; i+=4) {
|
||||||
|
if (data[i] !== 0 || data[i+1] !== 128 || data[i+2] !== 0 || data[i+3] !== 255) {
|
||||||
|
console.log(i, data[i], data[i+1], data[i+2], data[i+3]);
|
||||||
|
expect().fail("Invalid canvas data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
after(function() {
|
after(function() {
|
||||||
if (history) {
|
if (history) {
|
||||||
history.pushState("", document.title, window.location.pathname + window.location.search);
|
history.pushState("", document.title, window.location.pathname + window.location.search);
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var path = require('path');
|
||||||
var html2canvas = require('../../');
|
var html2canvas = require('../../');
|
||||||
|
|
||||||
describe("Package", function() {
|
describe("Package", function() {
|
||||||
@ -6,3 +7,18 @@ describe("Package", function() {
|
|||||||
assert.equal(typeof(html2canvas), "function");
|
assert.equal(typeof(html2canvas), "function");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe.only("requirejs", function() {
|
||||||
|
var requirejs = require('requirejs');
|
||||||
|
|
||||||
|
requirejs.config({
|
||||||
|
baseUrl: path.resolve(__dirname, '../../dist')
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should have html2canvas defined", function(done) {
|
||||||
|
requirejs(['html2canvas'], function(h2c) {
|
||||||
|
assert.equal(typeof(h2c), "function");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user