Compare commits

..

25 Commits

Author SHA1 Message Date
bebb353b3f Merge pull request #703 from niklasvh/travis-fix
Lower travis nodejs version back to 0.10
2015-10-20 23:37:35 +03:00
eb5ac1122c Lower travis nodejs version back to 0.10 2015-10-20 23:16:49 +03:00
ae97dd9a3d Remove npm bower dependency 2015-10-19 23:13:05 +03:00
11fdc501b1 Fix package dependency versions 2015-10-19 02:57:40 +03:00
4df19968b5 0.5.0-beta2 2015-10-19 01:49:34 +03:00
9ab7f8cdb1 Update travis npm deployment 2015-10-19 01:44:08 +03:00
5c5531fd47 Update node version for travis 2015-10-19 01:34:38 +03:00
e88ac871a3 Remove Promise polyfill 2015-10-19 01:25:03 +03:00
2a2ad9bb65 0.5.0-beta1 2015-10-19 01:00:58 +03:00
81e60975cc Update build/deploy workflow 2015-10-19 01:00:04 +03:00
a0669300c4 Update grunt-mocha-phantomjs to 2.0.0 2015-10-18 23:58:10 +03:00
ba9758cf14 Reformat mocha text shadow test names 2015-10-18 23:57:55 +03:00
aa05241ff8 Fix gradient tests 2015-10-18 23:57:41 +03:00
5b4a6c26ee Add another border-radius test 2015-10-18 23:15:51 +03:00
364a8aac1c Merge remote-tracking branch 'origin/pr/645' 2015-10-18 23:15:12 +03:00
46078acf71 Fix #688 fatal exception on unmatched color stop 2015-10-18 16:51:53 +03:00
4b37909f09 Fix support for requirejs/amd 2015-08-30 02:27:38 +03:00
90f9eeba83 Fix #599 2015-06-10 16:13:17 +09:00
98ee30643a Fix iOS scrolling issue on clone 2015-03-30 00:58:50 +03:00
a49c3a2320 Correctly handle named colors in gradients 2015-03-29 23:20:17 +03:00
4b80102e77 Merge pull request #545 from cornedor/ie-transforms
Transform matrix for IE
2015-03-08 01:03:22 +02:00
9201cf7e95 Accept matrix3d and convert it 2015-03-05 15:52:23 +01:00
c2baf42145 Fix fail on transparent colors in linear gradients 2015-03-01 17:43:18 +02:00
d9a9615ed7 Add acid2 test case 2015-03-01 17:12:09 +02:00
585a96a918 Preserve scrolling positions of nodes on clone (#511) 2015-02-28 16:51:52 +02:00
41 changed files with 362 additions and 23967 deletions

2
.gitignore vendored
View File

@ -1,6 +1,7 @@
/nbproject/
image.jpg
/.project
dist/
/.settings/
node_modules/
.envrc
@ -9,3 +10,4 @@ node_modules/
*.iml
.idea/
.DS_Store
npm-debug.log

View File

@ -15,5 +15,5 @@
"globals": {
"jQuery": true
},
"predef": ["-Promise"]
"predef": ["Promise", "define"]
}

10
.npmignore Normal file
View File

@ -0,0 +1,10 @@
tests/
examples/
Gruntfile.js
bower.json
src/
*.iml
.idea/
.npmignore
.jshintrc
.travis.yml

View File

@ -1,21 +1,29 @@
---
language: node_js
node_js:
- '0.10'
env:
global:
- secure: "eW41gIqOizwO4pTgWnAAbW75AP7F+CK9qfSed/fSh4sJ9HWMIY1YRIaY8gjr+6jV/f7XVHcXuym6ZxgINYSkVKbF1JKxBJNLOXtSgNbVHSic58pYFvUjwxIBI9aPig9uux1+DbnpWqXFDTcACJSevQZE0xwmjdrSkDLgB0G34v8="
- secure: "Y2Av+Gd3z9uQEB36GwdOOuGka0hx0/HeitASEo59z934O8RxnmN9eNTXS7dDT3XtKtwxIyLTOEpS7qlRdWahH28hr/dS4xJj6ao58C+1xMcDs6NAPGmDxUlcJWpcGEsnjmXjQCc3fBioSTdpIBrK/gdvgpNh77UKG74Sk7Z+YGk="
- secure: "YI+YbTOGf2x4fPMKW+KhJiZWswoXT6xOKGwLfsQsVwmFX1LerJouil5D5iYOQuL4FE3pNaoJSNakIsokJQuGKJMmnPc8rdhMZuBJBk6MRghurE2Xe9qBHfuUBPlfD61nARESm4WDcyMwM0QVYaOKeY6aIpZ91qbUbyc60EEx3C4="
- secure: eW41gIqOizwO4pTgWnAAbW75AP7F+CK9qfSed/fSh4sJ9HWMIY1YRIaY8gjr+6jV/f7XVHcXuym6ZxgINYSkVKbF1JKxBJNLOXtSgNbVHSic58pYFvUjwxIBI9aPig9uux1+DbnpWqXFDTcACJSevQZE0xwmjdrSkDLgB0G34v8=
- secure: Y2Av+Gd3z9uQEB36GwdOOuGka0hx0/HeitASEo59z934O8RxnmN9eNTXS7dDT3XtKtwxIyLTOEpS7qlRdWahH28hr/dS4xJj6ao58C+1xMcDs6NAPGmDxUlcJWpcGEsnjmXjQCc3fBioSTdpIBrK/gdvgpNh77UKG74Sk7Z+YGk=
- secure: YI+YbTOGf2x4fPMKW+KhJiZWswoXT6xOKGwLfsQsVwmFX1LerJouil5D5iYOQuL4FE3pNaoJSNakIsokJQuGKJMmnPc8rdhMZuBJBk6MRghurE2Xe9qBHfuUBPlfD61nARESm4WDcyMwM0QVYaOKeY6aIpZ91qbUbyc60EEx3C4=
addons:
sauce_connect: true
before_script:
- npm install -g grunt-cli
- npm install -g uglify-js
- npm install -g grunt-cli
- npm install -g uglify-js
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/2b007d4f86de89588804
- https://webhooks.gitter.im/e/2b007d4f86de89588804
on_success: always
on_failure: always
on_start: false
deploy:
- provider: npm
email: niklasvh@gmail.com
api_key:
secure: G/Szpr8q4/D6hp+H/Z9yyluUXtHAwf7LLa1Y07X59/Enlj1h7V5fQ7AW4/iAVM3XbIsrCPWR3dJU9g/ZxpxFg4OovIHVpS2Jr/mahtPYWdHR3pWuSmMW8QD+Twnq2VAFwSgg5Oumq3QxhX3YbCOnZox6+6Uviqk8FO7Z5B0RwW4=
on:
tags: true
branch: master
repo: niklasvh/html2canvas

4534
dist/html2canvas.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

19271
dist/html2canvas.svg.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -2,8 +2,8 @@
"title": "html2canvas",
"name": "html2canvas",
"description": "Screenshots with JavaScript",
"main": "src/core.js",
"version": "0.5.0-alpha2",
"main": "dist/html2canvas.js",
"version": "0.5.0-beta2",
"author": {
"name": "Niklas von Hertzen",
"email": "niklasvh@gmail.com",
@ -12,9 +12,6 @@
"engines": {
"node": ">=0.10.0"
},
"dependencies": {
"es6-promise": "^2.0.1"
},
"repository": {
"type": "git",
"url": "git@github.com:niklasvh/html2canvas.git"
@ -23,9 +20,8 @@
"url": "https://github.com/niklasvh/html2canvas/issues"
},
"devDependencies": {
"base64-arraybuffer": ">= 0.1.0",
"bluebird": "^2.7.1",
"bower": "^1.3.12",
"base64-arraybuffer": ">= 0.1.4",
"bluebird": "2.7.1",
"grunt": "^0.4.5",
"grunt-browserify": "^3.3.0",
"grunt-contrib-connect": "^0.8.0",
@ -34,16 +30,16 @@
"grunt-contrib-watch": "^0.6.1",
"grunt-execute": "^0.2.2",
"grunt-mocha-cli": "^1.12.0",
"grunt-mocha-phantomjs": "^0.6.0",
"grunt-mocha-phantomjs": "^2.0.0",
"html2canvas-proxy": "0.0.5",
"humanize-duration": "^2.0.1",
"lodash": "^2.4.1",
"png-js": ">= 0.1.1",
"requirejs": "^2.1.20",
"wd": "^0.2.21"
},
"scripts": {
"test": "grunt travis --verbose",
"postpublish": "bower register html2canvas git://github.com/niklasvh/html2canvas.git"
"test": "grunt travis --verbose"
},
"homepage": "http://html2canvas.hertzen.com",
"licenses": [

View File

@ -20,7 +20,7 @@ The script is still in a **very experimental state**, so I don't recommend using
###Browser compatibility###
The script should work fine on the following browsers:
The library should work fine on the following browsers (with `Promise` polyfill):
* Firefox 3.5+
* Google Chrome
@ -32,6 +32,10 @@ As each CSS property needs to be manually built to be supported, there are a num
### Usage ###
The html2canvas library utilizes `Promise`s and expects them to be available in the global context. If you wish to
support [older browsers](http://caniuse.com/#search=promise) that do not natively support `Promise`s, please include a polyfill such as
[es6-promise](https://github.com/jakearchibald/es6-promise) before including `html2canvas`.
**Note!** These instructions are for using the current dev version of 0.5, for the latest release version (0.4.1), checkout the [old readme](https://github.com/niklasvh/html2canvas/blob/v0.4/readme.md).
To render an `element` with html2canvas, simply call:

View File

@ -1,17 +1,4 @@
var log = require('./log');
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) {
if (ownerDocument.defaultView && (x !== ownerDocument.defaultView.pageXOffset || y !== ownerDocument.defaultView.pageYOffset)) {
@ -19,67 +6,57 @@ function restoreOwnerScroll(ownerDocument, x, y) {
}
}
function labelCanvasElements(ownerDocument) {
[].slice.call(ownerDocument.querySelectorAll("canvas"), 0).forEach(function(canvas) {
canvas.setAttribute(html2canvasCanvasCloneAttribute, "canvas-" + html2canvasCanvasCloneIndex++);
});
}
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);
function cloneCanvasContents(canvas, clonedCanvas) {
try {
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);
}
canvas.removeAttribute(html2canvasCanvasCloneAttribute);
});
} catch(e) {
log("Unable to copy canvas content from", canvas, e);
}
}
function removeScriptNodes(parent) {
[].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) {
function cloneNode(node, javascriptEnabled) {
var clone = node.nodeType === 3 ? document.createTextNode(node.nodeValue) : node.cloneNode(false);
var child = node.firstChild;
while(child) {
if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
clone.appendChild(cloneNodeIE9(child, javascriptEnabled));
clone.appendChild(cloneNode(child, javascriptEnabled));
}
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;
}
function initNode(node) {
if (node.nodeType === 1) {
node.scrollTop = node._scrollTop;
node.scrollLeft = node._scrollLeft;
function isElementNode(node) {
return node.nodeType === Node.ELEMENT_NODE;
var child = node.firstChild;
while(child) {
initNode(child);
child = child.nextSibling;
}
}
}
module.exports = function(ownerDocument, containerDocument, width, height, options, x ,y) {
labelCanvasElements(ownerDocument);
var documentElement = isIE9() ? cloneNodeIE9(ownerDocument.documentElement, options.javascriptEnabled) : ownerDocument.documentElement.cloneNode(true);
var documentElement = cloneNode(ownerDocument.documentElement, options.javascriptEnabled);
var container = containerDocument.createElement("iframe");
container.className = "html2canvas-container";
@ -96,19 +73,21 @@ module.exports = function(ownerDocument, containerDocument, width, height, optio
return new Promise(function(resolve) {
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
if window url is about:blank, we can assign the url to current by writing onto the document
*/
container.contentWindow.onload = container.onload = function() {
var interval = setInterval(function() {
if (documentClone.body.childNodes.length > 0) {
cloneCanvasContents(ownerDocument, documentClone);
initNode(documentClone.documentElement);
clearInterval(interval);
if (options.type === "view") {
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);
}
@ -119,7 +98,7 @@ module.exports = function(ownerDocument, containerDocument, width, height, optio
documentClone.write("<!DOCTYPE html><html></html>");
// Chrome scrolls the parent document for some reason after the write to the cloned window???
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();
});
};

View File

@ -1,4 +1,3 @@
var Promise = require('./promise');
var Support = require('./support');
var CanvasRenderer = require('./renderers/canvas');
var ImageLoader = require('./imageloader');
@ -51,16 +50,23 @@ function html2canvas(nodeList, options) {
});
}
html2canvas.Promise = Promise;
html2canvas.CanvasRenderer = CanvasRenderer;
html2canvas.NodeContainer = NodeContainer;
html2canvas.log = log;
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");
} : html2canvas;
module.exports = html2canvasExport;
if (typeof(define) === 'function' && define.amd) {
define('html2canvas', [], function() {
return html2canvasExport;
});
}
function renderDocument(document, options, windowWidth, windowHeight, html2canvasIndex) {
return createWindowClone(document, document, windowWidth, windowHeight, options, document.defaultView.pageXOffset, document.defaultView.pageYOffset).then(function(container) {
log("Document cloned");

View File

@ -1,4 +1,3 @@
var Promise = require('./promise');
var log = require('./log');
var smallImage = require('./utils').smallImage;

View File

@ -1,5 +1,4 @@
var utils = require('./utils');
var Promise = require('./promise');
var getBounds = utils.getBounds;
var loadUrlDocument = require('./proxy').loadUrlDocument;

View File

@ -1,5 +1,3 @@
var Promise = require('./promise');
function GradientContainer(imageData) {
this.src = imageData.value;
this.colorStops = [];

View File

@ -1,5 +1,3 @@
var Promise = require('./promise');
function ImageContainer(src, cors) {
this.src = src;
this.image = new Image();

View File

@ -1,4 +1,3 @@
var Promise = require('./promise');
var log = require('./log');
var ImageContainer = require('./imagecontainer');
var DummyImageContainer = require('./dummyimagecontainer');

View File

@ -1,6 +1,8 @@
var GradientContainer = require('./gradientcontainer');
var Color = require('./color');
var COLOR_STOP_REGEXP = /^\s*(.*)\s*(\d{1,3})?(%|px)?$/;
function LinearGradientContainer(imageData) {
GradientContainer.apply(this, arguments);
this.type = this.TYPES.LINEAR;
@ -41,13 +43,15 @@ function LinearGradientContainer(imageData) {
this.y1 = 1;
}
this.colorStops = imageData.args.slice(hasDirection ? 1 : 0).map(function(colorStop) {
var colorStopMatch = colorStop.match(this.stepRegExp);
return {
color: new Color(colorStopMatch[1]),
stop: colorStopMatch[3] === "%" ? colorStopMatch[2] / 100 : null
};
}, this);
this.colorStops = imageData.args.slice(hasDirection ? 1 : 0)
.map(function(colorStop) { return colorStop.match(COLOR_STOP_REGEXP);})
.filter(function(colorStopMatch) { return !!colorStopMatch;})
.map(function(colorStopMatch) {
return {
color: new Color(colorStopMatch[1]),
stop: colorStopMatch[3] === "%" ? colorStopMatch[2] / 100 : null
};
});
if (this.colorStops[0].stop === null) {
this.colorStops[0].stop = 0;

View File

@ -258,7 +258,7 @@ NodeContainer.prototype.getValue = function() {
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_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
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 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]];
}
}

View File

@ -5,7 +5,6 @@ var TextContainer = require('./textcontainer');
var PseudoElementContainer = require('./pseudoelementcontainer');
var FontMetrics = require('./fontmetrics');
var Color = require('./color');
var Promise = require('./promise');
var StackingContext = require('./stackingcontext');
var utils = require('./utils');
var bind = utils.bind;
@ -617,14 +616,14 @@ function calculateCurvePoints(bounds, borderRadius, borders) {
width = bounds.width,
height = bounds.height,
tlh = borderRadius[0][0],
tlv = borderRadius[0][1],
trh = borderRadius[1][0],
trv = borderRadius[1][1],
brh = borderRadius[2][0],
brv = borderRadius[2][1],
blh = borderRadius[3][0],
blv = borderRadius[3][1];
tlh = borderRadius[0][0] < width / 2 ? borderRadius[0][0] : width / 2,
tlv = borderRadius[0][1] < height / 2 ? borderRadius[0][1] : height / 2,
trh = borderRadius[1][0] < width / 2 ? borderRadius[1][0] : width / 2,
trv = borderRadius[1][1] < height / 2 ? borderRadius[1][1] : height / 2,
brh = borderRadius[2][0] < width / 2 ? borderRadius[2][0] : width / 2,
brv = borderRadius[2][1] < height / 2 ? borderRadius[2][1] : height / 2,
blh = borderRadius[3][0] < width / 2 ? borderRadius[3][0] : width / 2,
blv = borderRadius[3][1] < height / 2 ? borderRadius[3][1] : height / 2;
var topWidth = width - trh,
rightHeight = height - brv,

View File

@ -1 +0,0 @@
module.exports = require('es6-promise').Promise;

View File

@ -1,4 +1,3 @@
var Promise = require('./promise');
var XHR = require('./xhr');
var utils = require('./utils');
var log = require('./log');

View File

@ -1,5 +1,4 @@
var ProxyURL = require('./proxy').ProxyURL;
var Promise = require('./promise');
function ProxyImageContainer(src, proxy) {
var link = document.createElement("a");

View File

@ -1,4 +1,3 @@
var Promise = require('./promise');
var XHR = require('./xhr');
var decode64 = require('./utils').decode64;

View File

@ -1,5 +1,4 @@
var SVGContainer = require('./svgcontainer');
var Promise = require('./promise');
function SVGNodeContainer(node, _native) {
this.src = node;

View File

@ -1,5 +1,3 @@
var Promise = require('./promise');
function XHR(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();

141
tests/cases/acid2.html Normal file
View 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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</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>&nbsp;</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>

View File

@ -112,6 +112,10 @@
.linearGradient8 {
background: linear-gradient(to top left, #fff 0%, #00263c 100%);
}
.linearGradient9 {
background: linear-gradient(to top left, white 0%, black 100%);
}
</style>
</head>
@ -125,6 +129,7 @@
<div class="linearGradient6">&nbsp;</div>
<div class="linearGradient7">&nbsp;</div>
<div class="linearGradient8">&nbsp;</div>
<div class="linearGradient9">&nbsp;</div>
</div>
</body>
</html>

View File

@ -57,6 +57,12 @@
background-clip: padding-box;
}
.box6 {
height: 200px;
width: 200px;
border-radius: 200px;
}
html {
background: #3a84c3;
}
@ -69,5 +75,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

@ -3,6 +3,7 @@
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>

View File

@ -3,6 +3,7 @@
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>

View File

@ -67,26 +67,28 @@ describe('Text-shadow', function() {
var index = i + 1;
var container = new NodeContainer(node, null);
var shadows = container.parseTextShadows();
if (i === 0) {
expect(shadows.length).to.equal(0);
} else {
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)');
it(node.style.textShadow, function() {
if (i === 0) {
expect(shadows.length).to.equal(0);
} else {
var opacity = '0.2';
expect(shadows[0].color.toString()).to.match(/rgba\(2,2,2,(0.2|0\.199219)\)/);
}
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 {
var opacity = '0.2';
expect(shadows[0].color.toString()).to.match(/rgba\(2,2,2,(0.2|0\.199219)\)/);
}
// only testing blur once
if (i === 1) {
expect(shadows[0].blur).to.equal('1');
// only testing blur once
if (i === 1) {
expect(shadows[0].blur).to.equal('1');
}
}
}
});
});
});

View File

@ -3,6 +3,7 @@
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
@ -108,7 +109,7 @@
CanvasRenderer.prototype.text = function(text) {
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.height).to.equal(200);
done();
@ -138,7 +139,7 @@
CanvasRenderer.prototype.text = function(text) {
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.height).to.equal(200);
done();

View File

@ -35,6 +35,15 @@ describe("Gradients", function() {
" to(rgb(191, 110, 78))"
]
},
{
method: 'linear-gradient',
args: [
"0deg",
" rgb(221, 221, 221)",
" rgb(221, 221, 221) 50%",
" transparent 50%"
]
},
{
method: "radial-gradient",
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 value = container.css("backgroundImage");
it(value, function() {

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<title>Proxy tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>

View File

@ -3,6 +3,7 @@
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
@ -25,7 +26,6 @@
<div id="green-block"></div>
<script>mocha.setup('bdd')</script>
<script>
var Promise = html2canvas.Promise;
describe("Multiple renders", function() {
it("render correctly", function(done) {
this.timeout(10000);

View File

@ -3,6 +3,7 @@
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
@ -23,7 +24,6 @@
<div style="background: red; width: 200px; height:200px;" id="block"></div>
<div style="width: 200px; height:200px;" id="block2"></div>
<script>
var Promise = html2canvas.Promise;
describe("options.onclone", function() {
it("with a function", function(done) {
html2canvas(document.querySelector("#block"), {onclone: function(document) {

View File

@ -108,6 +108,12 @@
/* W3C */
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 {
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%);
@ -156,6 +162,7 @@
<div class="linearGradientSimple"></div>
<div class="linearGradientWithStops"></div>
<div class="linearGradient3"></div>
<div class="linearGradient4"></div>
<div class="radialGradient"></div>
<div class="radialGradient2"></div>
<div class="radialGradient3"></div>

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<title>Scrolling tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../node_modules/bluebird/js/browser/bluebird.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
@ -12,6 +13,12 @@
<body>
<div id="mocha"></div>
<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: 500px;background: green;"><a name="content">content</a></div>
<script>
@ -32,7 +39,7 @@
window.location.hash = "#content";
setTimeout(function() {
var top = $(window).scrollTop();
html2canvas(document.body, {type: 'view', removeContainer: false}).then(function () {
html2canvas(document.body, {type: 'view'}).then(function () {
var currentTop = $(window).scrollTop();
window.location.hash = "";
expect(currentTop).to.be.greaterThan(1500);
@ -45,8 +52,35 @@
});
}, 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() {
if (history) {
history.pushState("", document.title, window.location.pathname + window.location.search);

View File

@ -1,4 +1,5 @@
var assert = require('assert');
var path = require('path');
var html2canvas = require('../../');
describe("Package", function() {
@ -6,3 +7,18 @@ describe("Package", 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();
});
});
});

View File

@ -4,10 +4,7 @@ var h2cSelector, h2cOptions;
document.write('<script type="text/javascript" src="' + src + '.js?' + Math.random() + '"></script>');
}
var sources = ['log', 'punycode/punycode', 'core', 'nodecontainer', 'pseudoelementcontainer', 'stackingcontext', 'textcontainer', 'support', 'imagecontainer', 'dummyimagecontainer', 'proxyimagecontainer', 'gradientcontainer',
'lineargradientcontainer', 'webkitgradientcontainer', 'svgcontainer', 'svgnodecontainer', 'imageloader', 'nodeparser', 'font', 'fontmetrics', 'renderer', 'promise', 'xhr', 'framecontainer', 'proxy', 'color', 'renderers/canvas'];
['/tests/assets/jquery-1.6.2', '/dist/html2canvas'].forEach(appendScript);
['/node_modules/bluebird/js/browser/bluebird', '/tests/assets/jquery-1.6.2', '/dist/html2canvas'].forEach(appendScript);
if (typeof(noFabric) === "undefined") {
appendScript('/dist/html2canvas.svg');