Switch build to use browserify (#502)

This commit is contained in:
Niklas von Hertzen 2015-02-03 21:34:05 +02:00
parent 60619dca72
commit f3b6df267e
48 changed files with 4044 additions and 1234 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "src/fabric"]
path = src/fabric
url = https://github.com/kangax/fabric.js.git
[submodule "src/punycode"]
path = src/punycode
url = https://github.com/bestiejs/punycode.js.git

View File

@ -15,6 +15,5 @@
"globals": {
"jQuery": true
},
"predef": ["NodeParser", "NodeContainer", "Color", "StackingContext", "TextContainer", "PseudoElementContainer", "ImageLoader", "CanvasRenderer", "Renderer", "Support", "bind", "Promise", "getBounds", "offsetBounds", "XHR",
"ImageContainer", "ProxyImageContainer", "DummyImageContainer", "Font", "FontMetrics", "GradientContainer", "LinearGradientContainer", "WebkitGradientContainer", "SVGContainer", "SVGNodeContainer", "FrameContainer", "html2canvas", "log", "smallImage", "parseBackgrounds", "loadUrlDocument", "decode64", "Proxy", "ProxyURL"]
"predef": ["-Promise"]
}

View File

@ -8,9 +8,7 @@ module.exports = function(grunt) {
banner: '/*\n <%= pkg.title || pkg.name %> <%= pkg.version %>' +
'<%= pkg.homepage ? " <" + pkg.homepage + ">" : "" %>' + '\n' +
' Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>' +
'\n\n Released under <%= _.pluck(pkg.licenses, "type").join(", ") %> License\n*/\n',
pre: '\n(function(window, document, exports, global, define, undefined){\n\n',
post: '\n}).call({}, typeof(window) !== "undefined" ? window : undefined, typeof(document) !== "undefined" ? document : undefined);'
'\n\n Released under <%= _.pluck(pkg.licenses, "type").join(", ") %> License\n*/\n'
};
var browsers = {
@ -59,16 +57,15 @@ module.exports = function(grunt) {
pkg: grunt.file.readJSON('package.json'),
concat: {
browserify: {
dist: {
src: [
'src/promise.js', 'src/fallback.js', 'src/punycode/punycode.js', 'src/core.js', 'src/*.js', 'src/renderers/*.js'
],
nonull: true,
src: ['src/core.js'],
dest: 'dist/<%= pkg.name %>.js',
options:{
banner: meta.banner + meta.pre,
footer: meta.post
options: {
browserifyOptions: {
standalone: 'html2canvas'
},
banner: meta.banner
}
},
svg: {
@ -77,8 +74,10 @@ module.exports = function(grunt) {
],
dest: 'dist/<%= pkg.name %>.svg.js',
options:{
banner: meta.banner + '\n(function(window, document, exports, undefined){\n\n',
footer: '\n}).call({}, window, document, html2canvas);'
browserifyOptions: {
standalone: 'html2canvas.svg'
},
banner: meta.banner
}
}
},
@ -149,11 +148,11 @@ module.exports = function(grunt) {
},
uglify: {
dist: {
src: ['<%= concat.dist.dest %>'],
src: ['<%= browserify.dist.dest %>'],
dest: 'dist/<%= pkg.name %>.min.js'
},
svg: {
src: ['<%= concat.svg.dest %>'],
src: ['<%= browserify.svg.dest %>'],
dest: 'dist/<%= pkg.name %>.svg.min.js'
},
options: {
@ -165,7 +164,7 @@ module.exports = function(grunt) {
tasks: ['jshint', 'build']
},
jshint: {
all: ['src/*.js', 'src/renderers/*.js', '!src/promise.js'],
all: ['src/*.js', 'src/renderers/*.js'],
options: grunt.file.readJSON('./.jshintrc')
},
mochacli: {
@ -204,9 +203,9 @@ module.exports = function(grunt) {
});
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-mocha-phantomjs');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-connect');
@ -214,7 +213,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-mocha-cli');
grunt.registerTask('server', ['connect:cors', 'connect:proxy', 'connect:altServer', 'connect:server']);
grunt.registerTask('build', ['execute', 'concat', 'uglify']);
grunt.registerTask('build', ['execute', 'browserify', 'uglify']);
grunt.registerTask('default', ['jshint', 'build', 'mochacli', 'connect:altServer', 'mocha_phantomjs']);
grunt.registerTask('travis', ['jshint', 'build', 'connect:altServer', 'connect:ci', 'connect:proxy', 'connect:cors', 'mocha_phantomjs', 'webdriver']);

2456
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

1573
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

@ -1 +0,0 @@
module.exports = require('./dist/html2canvas').html2canvas;

View File

@ -2,7 +2,7 @@
"title": "html2canvas",
"name": "html2canvas",
"description": "Screenshots with JavaScript",
"main": "main.js",
"main": "src/core.js",
"version": "0.5.0-alpha1",
"author": {
"name": "Niklas von Hertzen",
@ -12,7 +12,9 @@
"engines": {
"node": ">=0.10.0"
},
"dependencies": {},
"dependencies": {
"es6-promise": "^2.0.1"
},
"repository": {
"type": "git",
"url": "git@github.com:niklasvh/html2canvas.git"
@ -25,7 +27,7 @@
"bluebird": "^2.7.1",
"bower": "^1.3.12",
"grunt": "^0.4.5",
"grunt-contrib-concat": "^0.5.0",
"grunt-browserify": "^3.3.0",
"grunt-contrib-connect": "^0.8.0",
"grunt-contrib-jshint": "^0.10.0",
"grunt-contrib-uglify": "^0.6.0",

125
src/clone.js Normal file
View File

@ -0,0 +1,125 @@
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)) {
ownerDocument.defaultView.scrollTo(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);
}
canvas.removeAttribute(html2canvasCanvasCloneAttribute);
});
}
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) {
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));
}
child = child.nextSibling;
}
return clone;
}
function isElementNode(node) {
return node.nodeType === Node.ELEMENT_NODE;
}
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 container = containerDocument.createElement("iframe");
container.className = "html2canvas-container";
container.style.visibility = "hidden";
container.style.position = "fixed";
container.style.left = "-10000px";
container.style.top = "0px";
container.style.border = "0";
container.width = width;
container.height = height;
container.scrolling = "no"; // ios won't scroll without it
containerDocument.body.appendChild(container);
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);
clearInterval(interval);
if (options.type === "view") {
container.contentWindow.scrollTo(x, y);
}
resolve(container);
}
}, 50);
};
documentClone.open();
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.close();
});
};

View File

@ -268,3 +268,4 @@ var colors = {
"yellowgreen": [154, 205, 50]
};
module.exports = Color;

View File

@ -1,9 +1,19 @@
var Promise = require('./promise');
var Support = require('./support');
var CanvasRenderer = require('./renderers/canvas');
var ImageLoader = require('./imageloader');
var NodeParser = require('./nodeparser');
var NodeContainer = require('./nodecontainer');
var log = require('./log');
var utils = require('./utils');
var createWindowClone = require('./clone');
var loadUrlDocument = require('./proxy').loadUrlDocument;
var getBounds = utils.getBounds;
var html2canvasNodeAttribute = "data-html2canvas-node";
var html2canvasCanvasCloneAttribute = "data-html2canvas-canvas-clone";
var html2canvasCanvasCloneIndex = 0;
var html2canvasCloneIndex = 0;
window.html2canvas = function(nodeList, options) {
function html2canvas(nodeList, options) {
var index = html2canvasCloneIndex++;
options = options || {};
if (options.logging) {
@ -39,10 +49,17 @@ window.html2canvas = function(nodeList, options) {
}
return canvas;
});
};
}
window.html2canvas.punycode = this.punycode;
window.html2canvas.proxy = {};
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() {
return Promise.reject("No canvas support");
} : html2canvas;
function renderDocument(document, options, windowWidth, windowHeight, html2canvasIndex) {
return createWindowClone(document, document, windowWidth, windowHeight, options, document.defaultView.pageXOffset, document.defaultView.pageYOffset).then(function(container) {
@ -122,164 +139,6 @@ function documentHeight (doc) {
);
}
function smallImage() {
return "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
}
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 child = node.firstChild;
while(child) {
if (javascriptEnabled === true || child.nodeType !== 1 || child.nodeName !== 'SCRIPT') {
clone.appendChild(cloneNodeIE9(child, javascriptEnabled));
}
child = child.nextSibling;
}
return clone;
}
function createWindowClone(ownerDocument, containerDocument, width, height, options, x ,y) {
labelCanvasElements(ownerDocument);
var documentElement = isIE9() ? cloneNodeIE9(ownerDocument.documentElement, options.javascriptEnabled) : ownerDocument.documentElement.cloneNode(true);
var container = containerDocument.createElement("iframe");
container.className = "html2canvas-container";
container.style.visibility = "hidden";
container.style.position = "fixed";
container.style.left = "-10000px";
container.style.top = "0px";
container.style.border = "0";
container.width = width;
container.height = height;
container.scrolling = "no"; // ios won't scroll without it
containerDocument.body.appendChild(container);
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);
clearInterval(interval);
if (options.type === "view") {
container.contentWindow.scrollTo(x, y);
}
resolve(container);
}
}, 50);
};
documentClone.open();
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.close();
});
}
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)) {
ownerDocument.defaultView.scrollTo(x, y);
}
}
function loadUrlDocument(src, proxy, document, width, height, options) {
return new Proxy(src, proxy, window.document).then(documentFromHTML(src)).then(function(doc) {
return createWindowClone(doc, document, width, height, options, 0, 0);
});
}
function documentFromHTML(src) {
return function(html) {
var parser = new DOMParser(), doc;
try {
doc = parser.parseFromString(html, "text/html");
} catch(e) {
log("DOMParser not supported, falling back to createHTMLDocument");
doc = document.implementation.createHTMLDocument("");
try {
doc.open();
doc.write(html);
doc.close();
} catch(ee) {
log("createHTMLDocument write not supported, falling back to document.body.innerHTML");
doc.body.innerHTML = html; // ie9 doesnt support writing to documentElement
}
}
var b = doc.querySelector("base");
if (!b || !b.href.host) {
var base = doc.createElement("base");
base.href = src;
doc.head.insertBefore(base, doc.head.firstChild);
}
return doc;
};
}
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);
}
canvas.removeAttribute(html2canvasCanvasCloneAttribute);
});
}
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 isElementNode(node) {
return node.nodeType === Node.ELEMENT_NODE;
}
function absoluteUrl(url) {
var link = document.createElement("a");
link.href = url;

View File

@ -1,3 +1,7 @@
var Promise = require('./promise');
var log = require('./log');
var smallImage = require('./utils').smallImage;
function DummyImageContainer(src) {
this.src = src;
log("DummyImageContainer for", src);
@ -15,3 +19,5 @@ function DummyImageContainer(src) {
});
}
}
module.exports = DummyImageContainer;

View File

@ -1,6 +0,0 @@
if (typeof(document) === "undefined" || typeof(Object.create) !== "function" || typeof(document.createElement("canvas").getContext) !== "function") {
(window || module.exports).html2canvas = function() {
return Promise.reject("No canvas support");
};
return;
}

View File

@ -1,3 +1,5 @@
var smallImage = require('./utils').smallImage;
function Font(family, size) {
var container = document.createElement('div'),
img = document.createElement('img'),
@ -46,3 +48,5 @@ function Font(family, size) {
this.lineWidth = 1;
this.middle = middle;
}
module.exports = Font;

View File

@ -1,3 +1,5 @@
var Font = require('./font');
function FontMetrics() {
this.data = {};
}
@ -8,3 +10,5 @@ FontMetrics.prototype.getMetrics = function(family, size) {
}
return this.data[family + "-" + size];
};
module.exports = FontMetrics;

View File

@ -1,3 +1,8 @@
var utils = require('./utils');
var Promise = require('./Promise');
var getBounds = utils.getBounds;
var loadUrlDocument = require('./proxy').loadUrlDocument;
function FrameContainer(container, sameOrigin, options) {
this.image = null;
this.src = container;
@ -12,6 +17,7 @@ function FrameContainer(container, sameOrigin, options) {
resolve(container);
}
})).then(function(container) {
var html2canvas = require('./core');
return html2canvas(container.contentWindow.document.documentElement, {type: 'view', width: container.width, height: container.height, proxy: options.proxy, javascriptEnabled: options.javascriptEnabled, removeContainer: options.removeContainer, allowTaint: options.allowTaint, imageTimeout: options.imageTimeout / 2});
}).then(function(canvas) {
return self.image = canvas;
@ -22,3 +28,5 @@ FrameContainer.prototype.proxyLoad = function(proxy, bounds, options) {
var container = this.src;
return loadUrlDocument(container.src, proxy, container.ownerDocument, bounds.width, bounds.height, options);
};
module.exports = FrameContainer;

View File

@ -1,3 +1,5 @@
var Promise = require('./promise');
function GradientContainer(imageData) {
this.src = imageData.value;
this.colorStops = [];
@ -13,3 +15,5 @@ GradientContainer.prototype.TYPES = {
LINEAR: 1,
RADIAL: 2
};
module.exports = GradientContainer;

View File

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

View File

@ -1,3 +1,15 @@
var Promise = require('./promise');
var log = require('./log');
var ImageContainer = require('./imagecontainer');
var DummyImageContainer = require('./dummyimagecontainer');
var ProxyImageContainer = require('./proxyimagecontainer');
var FrameContainer = require('./framecontainer');
var SVGContainer = require('./svgcontainer');
var SVGNodeContainer = require('./svgnodecontainer');
var LinearGradientContainer = require('./lineargradientcontainer');
var WebkitGradientContainer = require('./webkitgradientcontainer');
var bind = require('./utils').bind;
function ImageLoader(options, support) {
this.link = null;
this.options = options;
@ -142,3 +154,5 @@ ImageLoader.prototype.timeout = function(container, timeout) {
});
return promise;
};
module.exports = ImageLoader;

View File

@ -1,3 +1,6 @@
var GradientContainer = require('./gradientcontainer');
var Color = require('./color');
function LinearGradientContainer(imageData) {
GradientContainer.apply(this, arguments);
this.type = this.TYPES.LINEAR;
@ -71,3 +74,5 @@ function LinearGradientContainer(imageData) {
LinearGradientContainer.prototype = Object.create(GradientContainer.prototype);
LinearGradientContainer.prototype.stepRegExp = /((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/;
module.exports = LinearGradientContainer;

View File

@ -1,5 +1,5 @@
function log() {
module.exports = function() {
if (window.html2canvas.logging && window.console && window.console.log) {
Function.prototype.bind.call(window.console.log, (window.console)).apply(window.console, [(Date.now() - window.html2canvas.start) + "ms", "html2canvas:"].concat([].slice.call(arguments, 0)));
}
}
};

View File

@ -1,3 +1,9 @@
var Color = require('./color');
var utils = require('./utils');
var getBounds = utils.getBounds;
var parseBackgrounds = utils.parseBackgrounds;
var offsetBounds = utils.offsetBounds;
function NodeContainer(node, parent) {
this.node = node;
this.parent = parent;
@ -274,102 +280,6 @@ function isPercentage(value) {
return value.toString().indexOf("%") !== -1;
}
function parseBackgrounds(backgroundImage) {
var whitespace = ' \r\n\t',
method, definition, prefix, prefix_i, block, results = [],
mode = 0, numParen = 0, quote, args;
var appendResult = function() {
if(method) {
if (definition.substr(0, 1) === '"') {
definition = definition.substr(1, definition.length - 2);
}
if (definition) {
args.push(definition);
}
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1 ) + 1) > 0) {
prefix = method.substr(0, prefix_i);
method = method.substr(prefix_i);
}
results.push({
prefix: prefix,
method: method.toLowerCase(),
value: block,
args: args,
image: null
});
}
args = [];
method = prefix = definition = block = '';
};
args = [];
method = prefix = definition = block = '';
backgroundImage.split("").forEach(function(c) {
if (mode === 0 && whitespace.indexOf(c) > -1) {
return;
}
switch(c) {
case '"':
if(!quote) {
quote = c;
} else if(quote === c) {
quote = null;
}
break;
case '(':
if(quote) {
break;
} else if(mode === 0) {
mode = 1;
block += c;
return;
} else {
numParen++;
}
break;
case ')':
if (quote) {
break;
} else if(mode === 1) {
if(numParen === 0) {
mode = 0;
block += c;
appendResult();
return;
} else {
numParen--;
}
}
break;
case ',':
if (quote) {
break;
} else if(mode === 0) {
appendResult();
return;
} else if (mode === 1) {
if (numParen === 0 && !method.match(/^url$/i)) {
args.push(definition);
definition = '';
block += c;
return;
}
}
break;
}
block += c;
if (mode === 0) {
method += c;
} else {
definition += c;
}
});
appendResult();
return results;
}
function removePx(str) {
return str.replace("px", "");
}
@ -378,31 +288,4 @@ function asFloat(str) {
return parseFloat(str);
}
function getBounds(node) {
if (node.getBoundingClientRect) {
var clientRect = node.getBoundingClientRect();
var width = node.offsetWidth == null ? clientRect.width : node.offsetWidth;
return {
top: clientRect.top,
bottom: clientRect.bottom || (clientRect.top + clientRect.height),
right: clientRect.left + width,
left: clientRect.left,
width: width,
height: node.offsetHeight == null ? clientRect.height : node.offsetHeight
};
}
return {};
}
function offsetBounds(node) {
var parent = node.offsetParent ? offsetBounds(node.offsetParent) : {top: 0, left: 0};
return {
top: node.offsetTop + parent.top,
bottom: node.offsetTop + node.offsetHeight + parent.top,
right: node.offsetLeft + parent.left + node.offsetWidth,
left: node.offsetLeft + parent.left,
width: node.offsetWidth,
height: node.offsetHeight
};
}
module.exports = NodeContainer;

View File

@ -1,3 +1,18 @@
var log = require('./log');
var punycode = require('punycode');
var NodeContainer = require('./nodecontainer');
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;
var getBounds = utils.getBounds;
var parseBackgrounds = utils.parseBackgrounds;
var offsetBounds = utils.offsetBounds;
function NodeParser(element, renderer, support, imageLoader, options) {
log("Starting NodeParser");
this.renderer = renderer;
@ -418,9 +433,9 @@ NodeParser.prototype.paintFormValue = function(container) {
NodeParser.prototype.paintText = function(container) {
container.applyTextTransform();
var characters = window.html2canvas.punycode.ucs2.decode(container.node.data);
var characters = punycode.ucs2.decode(container.node.data);
var textList = (!this.options.letterRendering || noLetterSpacing(container)) && !hasUnicode(container.node.data) ? getWords(characters) : characters.map(function(character) {
return window.html2canvas.punycode.ucs2.encode([character]);
return punycode.ucs2.encode([character]);
});
var weight = container.parent.fontWeight();
@ -793,12 +808,6 @@ function hasOpacity(container) {
return container.getOpacity() < 1;
}
function bind(callback, context) {
return function() {
return callback.apply(context, arguments);
};
}
function asInt(value) {
return parseInt(value, 10);
}
@ -826,7 +835,7 @@ function getWords(characters) {
if (isWordBoundary(characters[i]) === onWordBoundary) {
word = characters.splice(0, i);
if (word.length) {
words.push(window.html2canvas.punycode.ucs2.encode(word));
words.push(punycode.ucs2.encode(word));
}
onWordBoundary =! onWordBoundary;
i = 0;
@ -837,7 +846,7 @@ function getWords(characters) {
if (i >= characters.length) {
word = characters.splice(0, i);
if (word.length) {
words.push(window.html2canvas.punycode.ucs2.encode(word));
words.push(punycode.ucs2.encode(word));
}
}
}
@ -857,3 +866,5 @@ function isWordBoundary(characterCode) {
function hasUnicode(string) {
return (/[^\u0000-\u00ff]/).test(string);
}
module.exports = NodeParser;

View File

@ -1,22 +1 @@
/*!
* @overview es6-promise - a tiny implementation of Promises/A+.
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
* @license Licensed under MIT license
* See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
* @version 2.0.1
*/
(function(){function r(a,b){n[l]=a;n[l+1]=b;l+=2;2===l&&A()}function s(a){return"function"===typeof a}function F(){return function(){process.nextTick(t)}}function G(){var a=0,b=new B(t),c=document.createTextNode("");b.observe(c,{characterData:!0});return function(){c.data=a=++a%2}}function H(){var a=new MessageChannel;a.port1.onmessage=t;return function(){a.port2.postMessage(0)}}function I(){return function(){setTimeout(t,1)}}function t(){for(var a=0;a<l;a+=2)(0,n[a])(n[a+1]),n[a]=void 0,n[a+1]=void 0;
l=0}function p(){}function J(a,b,c,d){try{a.call(b,c,d)}catch(e){return e}}function K(a,b,c){r(function(a){var e=!1,f=J(c,b,function(c){e||(e=!0,b!==c?q(a,c):m(a,c))},function(b){e||(e=!0,g(a,b))});!e&&f&&(e=!0,g(a,f))},a)}function L(a,b){1===b.a?m(a,b.b):2===a.a?g(a,b.b):u(b,void 0,function(b){q(a,b)},function(b){g(a,b)})}function q(a,b){if(a===b)g(a,new TypeError("You cannot resolve a promise with itself"));else if("function"===typeof b||"object"===typeof b&&null!==b)if(b.constructor===a.constructor)L(a,
b);else{var c;try{c=b.then}catch(d){v.error=d,c=v}c===v?g(a,v.error):void 0===c?m(a,b):s(c)?K(a,b,c):m(a,b)}else m(a,b)}function M(a){a.f&&a.f(a.b);x(a)}function m(a,b){void 0===a.a&&(a.b=b,a.a=1,0!==a.e.length&&r(x,a))}function g(a,b){void 0===a.a&&(a.a=2,a.b=b,r(M,a))}function u(a,b,c,d){var e=a.e,f=e.length;a.f=null;e[f]=b;e[f+1]=c;e[f+2]=d;0===f&&a.a&&r(x,a)}function x(a){var b=a.e,c=a.a;if(0!==b.length){for(var d,e,f=a.b,g=0;g<b.length;g+=3)d=b[g],e=b[g+c],d?C(c,d,e,f):e(f);a.e.length=0}}function D(){this.error=
null}function C(a,b,c,d){var e=s(c),f,k,h,l;if(e){try{f=c(d)}catch(n){y.error=n,f=y}f===y?(l=!0,k=f.error,f=null):h=!0;if(b===f){g(b,new TypeError("A promises callback cannot return that same promise."));return}}else f=d,h=!0;void 0===b.a&&(e&&h?q(b,f):l?g(b,k):1===a?m(b,f):2===a&&g(b,f))}function N(a,b){try{b(function(b){q(a,b)},function(b){g(a,b)})}catch(c){g(a,c)}}function k(a,b,c,d){this.n=a;this.c=new a(p,d);this.i=c;this.o(b)?(this.m=b,this.d=this.length=b.length,this.l(),0===this.length?m(this.c,
this.b):(this.length=this.length||0,this.k(),0===this.d&&m(this.c,this.b))):g(this.c,this.p())}function h(a){O++;this.b=this.a=void 0;this.e=[];if(p!==a){if(!s(a))throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");if(!(this instanceof h))throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");N(this,a)}}var E=Array.isArray?Array.isArray:function(a){return"[object Array]"===
Object.prototype.toString.call(a)},l=0,w="undefined"!==typeof window?window:{},B=w.MutationObserver||w.WebKitMutationObserver,w="undefined"!==typeof Uint8ClampedArray&&"undefined"!==typeof importScripts&&"undefined"!==typeof MessageChannel,n=Array(1E3),A;A="undefined"!==typeof process&&"[object process]"==={}.toString.call(process)?F():B?G():w?H():I();var v=new D,y=new D;k.prototype.o=function(a){return E(a)};k.prototype.p=function(){return Error("Array Methods must be provided an Array")};k.prototype.l=
function(){this.b=Array(this.length)};k.prototype.k=function(){for(var a=this.length,b=this.c,c=this.m,d=0;void 0===b.a&&d<a;d++)this.j(c[d],d)};k.prototype.j=function(a,b){var c=this.n;"object"===typeof a&&null!==a?a.constructor===c&&void 0!==a.a?(a.f=null,this.g(a.a,b,a.b)):this.q(c.resolve(a),b):(this.d--,this.b[b]=this.h(a))};k.prototype.g=function(a,b,c){var d=this.c;void 0===d.a&&(this.d--,this.i&&2===a?g(d,c):this.b[b]=this.h(c));0===this.d&&m(d,this.b)};k.prototype.h=function(a){return a};
k.prototype.q=function(a,b){var c=this;u(a,void 0,function(a){c.g(1,b,a)},function(a){c.g(2,b,a)})};var O=0;h.all=function(a,b){return(new k(this,a,!0,b)).c};h.race=function(a,b){function c(a){q(e,a)}function d(a){g(e,a)}var e=new this(p,b);if(!E(a))return (g(e,new TypeError("You must pass an array to race.")), e);for(var f=a.length,h=0;void 0===e.a&&h<f;h++)u(this.resolve(a[h]),void 0,c,d);return e};h.resolve=function(a,b){if(a&&"object"===typeof a&&a.constructor===this)return a;var c=new this(p,b);
q(c,a);return c};h.reject=function(a,b){var c=new this(p,b);g(c,a);return c};h.prototype={constructor:h,then:function(a,b){var c=this.a;if(1===c&&!a||2===c&&!b)return this;var d=new this.constructor(p),e=this.b;if(c){var f=arguments[c-1];r(function(){C(c,d,f,e)})}else u(this,d,a,b);return d},"catch":function(a){return this.then(null,a)}};var z={Promise:h,polyfill:function(){var a;a="undefined"!==typeof global?global:"undefined"!==typeof window&&window.document?window:self;"Promise"in a&&"resolve"in
a.Promise&&"reject"in a.Promise&&"all"in a.Promise&&"race"in a.Promise&&function(){var b;new a.Promise(function(a){b=a});return s(b)}()||(a.Promise=h)}};"function"===typeof define&&define.amd?define(function(){return z}):"undefined"!==typeof module&&module.exports?module.exports=z:"undefined"!==typeof this&&(this.ES6Promise=z);}).call(window);
if (window) {
window.ES6Promise.polyfill();
}
module.exports = require('es6-promise').Promise;

View File

@ -1,4 +1,12 @@
var Promise = require('./promise');
var XHR = require('./xhr');
var utils = require('./utils');
var log = require('./log');
var createWindowClone = require('./clone');
var decode64 = utils.decode64;
function Proxy(src, proxyUrl, document) {
var supportsCORS = ('withCredentials' in new XMLHttpRequest());
if (!proxyUrl) {
return Promise.reject("No proxy configured");
}
@ -11,10 +19,8 @@ function Proxy(src, proxyUrl, document) {
}
var proxyCount = 0;
var supportsCORS = ('withCredentials' in new XMLHttpRequest());
var supportsCORSImage = ('crossOrigin' in new Image());
function ProxyURL(src, proxyUrl, document) {
var supportsCORSImage = ('crossOrigin' in new Image());
var callback = createCallback(supportsCORSImage);
var url = createProxyUrl(proxyUrl, src, callback);
return (supportsCORSImage ? Promise.resolve(url) : jsonp(document, url, callback).then(function(response) {
@ -49,3 +55,42 @@ function createCallback(useCORS) {
function createProxyUrl(proxyUrl, src, callback) {
return proxyUrl + "?url=" + encodeURIComponent(src) + (callback.length ? "&callback=html2canvas.proxy." + callback : "");
}
function documentFromHTML(src) {
return function(html) {
var parser = new DOMParser(), doc;
try {
doc = parser.parseFromString(html, "text/html");
} catch(e) {
log("DOMParser not supported, falling back to createHTMLDocument");
doc = document.implementation.createHTMLDocument("");
try {
doc.open();
doc.write(html);
doc.close();
} catch(ee) {
log("createHTMLDocument write not supported, falling back to document.body.innerHTML");
doc.body.innerHTML = html; // ie9 doesnt support writing to documentElement
}
}
var b = doc.querySelector("base");
if (!b || !b.href.host) {
var base = doc.createElement("base");
base.href = src;
doc.head.insertBefore(base, doc.head.firstChild);
}
return doc;
};
}
function loadUrlDocument(src, proxy, document, width, height, options) {
return new Proxy(src, proxy, window.document).then(documentFromHTML(src)).then(function(doc) {
return createWindowClone(doc, document, width, height, options, 0, 0);
});
}
exports.Proxy = Proxy;
exports.ProxyURL = ProxyURL;
exports.loadUrlDocument = loadUrlDocument;

View File

@ -1,3 +1,6 @@
var ProxyURL = require('./proxy').ProxyURL;
var Promise = require('./promise');
function ProxyImageContainer(src, proxy) {
var link = document.createElement("a");
link.href = src;
@ -15,3 +18,5 @@ function ProxyImageContainer(src, proxy) {
})['catch'](reject);
});
}
module.exports = ProxyImageContainer;

View File

@ -1,3 +1,5 @@
var NodeContainer = require('./nodecontainer');
function PseudoElementContainer(node, parent, type) {
NodeContainer.call(this, node, parent);
this.isPseudoElement = true;
@ -32,3 +34,5 @@ PseudoElementContainer.prototype.getHideClass = function() {
PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE = "___html2canvas___pseudoelement_before";
PseudoElementContainer.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER = "___html2canvas___pseudoelement_after";
module.exports = PseudoElementContainer;

@ -1 +0,0 @@
Subproject commit 5c04e6fe9560bac8d38a0bcdf2d2c8581f5fc330

View File

@ -1,3 +1,5 @@
var log = require('./log');
function Renderer(width, height, images, options, document) {
this.width = width;
this.height = height;
@ -102,3 +104,5 @@ Renderer.prototype.renderBackgroundRepeating = function(container, bounds, image
break;
}
};
module.exports = Renderer;

View File

@ -1,3 +1,7 @@
var Renderer = require('../renderer');
var LinearGradientContainer = require('../lineargradientcontainer');
var log = require('../log');
function CanvasRenderer(width, height) {
Renderer.apply(this, arguments);
this.canvas = this.options.canvas || this.document.createElement("canvas");
@ -173,3 +177,5 @@ CanvasRenderer.prototype.resizeImage = function(imageContainer, size) {
function hasEntries(array) {
return array.length > 0;
}
module.exports = CanvasRenderer;

View File

@ -1,3 +1,5 @@
var NodeContainer = require('./nodecontainer');
function StackingContext(hasOwnStacking, opacity, element, parent) {
NodeContainer.call(this, element, parent);
this.ownStacking = hasOwnStacking;
@ -12,3 +14,5 @@ StackingContext.prototype.getParentStack = function(context) {
var parentStack = (this.parent) ? this.parent.stack : null;
return parentStack ? (parentStack.ownStacking ? parentStack : parentStack.getParentStack(context)) : context.stack;
};
module.exports = StackingContext;

View File

@ -47,3 +47,5 @@ Support.prototype.testSVG = function() {
}
return true;
};
module.exports = Support;

View File

@ -1,3 +1,7 @@
var Promise = require('./promise');
var XHR = require('./xhr');
var decode64 = require('./utils').decode64;
function SVGContainer(src) {
this.src = src;
this.image = null;
@ -7,13 +11,13 @@ function SVGContainer(src) {
return (self.isInline(src) ? Promise.resolve(self.inlineFormatting(src)) : XHR(src));
}).then(function(svg) {
return new Promise(function(resolve) {
html2canvas.fabric.loadSVGFromString(svg, self.createCanvas.call(self, resolve));
window.html2canvas.svg.fabric.loadSVGFromString(svg, self.createCanvas.call(self, resolve));
});
});
}
SVGContainer.prototype.hasFabric = function() {
return !html2canvas.fabric ? Promise.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg")) : Promise.resolve();
return !window.html2canvas.svg || !window.html2canvas.svg.fabric ? Promise.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg")) : Promise.resolve();
};
SVGContainer.prototype.inlineFormatting = function(src) {
@ -31,12 +35,12 @@ SVGContainer.prototype.isInline = function(src) {
SVGContainer.prototype.createCanvas = function(resolve) {
var self = this;
return function (objects, options) {
var canvas = new html2canvas.fabric.StaticCanvas('c');
var canvas = new window.html2canvas.svg.fabric.StaticCanvas('c');
self.image = canvas.lowerCanvasEl;
canvas
.setWidth(options.width)
.setHeight(options.height)
.add(html2canvas.fabric.util.groupSVGElements(objects, options))
.add(window.html2canvas.svg.fabric.util.groupSVGElements(objects, options))
.renderAll();
resolve(canvas.lowerCanvasEl);
};
@ -46,37 +50,4 @@ SVGContainer.prototype.decode64 = function(str) {
return (typeof(window.atob) === "function") ? window.atob(str) : decode64(str);
};
/*
* base64-arraybuffer
* https://github.com/niklasvh/base64-arraybuffer
*
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
function decode64(base64) {
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var len = base64.length, i, encoded1, encoded2, encoded3, encoded4, byte1, byte2, byte3;
var output = "";
for (i = 0; i < len; i+=4) {
encoded1 = chars.indexOf(base64[i]);
encoded2 = chars.indexOf(base64[i+1]);
encoded3 = chars.indexOf(base64[i+2]);
encoded4 = chars.indexOf(base64[i+3]);
byte1 = (encoded1 << 2) | (encoded2 >> 4);
byte2 = ((encoded2 & 15) << 4) | (encoded3 >> 2);
byte3 = ((encoded3 & 3) << 6) | encoded4;
if (encoded3 === 64) {
output += String.fromCharCode(byte1);
} else if (encoded4 === 64 || encoded4 === -1) {
output += String.fromCharCode(byte1, byte2);
} else{
output += String.fromCharCode(byte1, byte2, byte3);
}
}
return output;
}
module.exports = SVGContainer;

View File

@ -1,9 +1,12 @@
function SVGNodeContainer(node, native) {
var SVGContainer = require('./svgcontainer');
var Promise = require('./promise');
function SVGNodeContainer(node, _native) {
this.src = node;
this.image = null;
var self = this;
this.promise = native ? new Promise(function(resolve, reject) {
this.promise = _native ? new Promise(function(resolve, reject) {
self.image = new Image();
self.image.onload = resolve;
self.image.onerror = reject;
@ -13,9 +16,11 @@ function SVGNodeContainer(node, native) {
}
}) : this.hasFabric().then(function() {
return new Promise(function(resolve) {
html2canvas.fabric.parseSVGDocument(node, self.createCanvas.call(self, resolve));
window.html2canvas.svg.fabric.parseSVGDocument(node, self.createCanvas.call(self, resolve));
});
});
}
SVGNodeContainer.prototype = Object.create(SVGContainer.prototype);
module.exports = SVGNodeContainer;

View File

@ -1,3 +1,5 @@
var NodeContainer = require('./nodecontainer');
function TextContainer(node, parent) {
NodeContainer.call(this, node, parent);
}
@ -27,3 +29,5 @@ function capitalize(m, p1, p2) {
return p1 + p2.toUpperCase();
}
}
module.exports = TextContainer;

169
src/utils.js Normal file
View File

@ -0,0 +1,169 @@
exports.smallImage = function smallImage() {
return "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
};
exports.bind = function(callback, context) {
return function() {
return callback.apply(context, arguments);
};
};
/*
* base64-arraybuffer
* https://github.com/niklasvh/base64-arraybuffer
*
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
exports.decode64 = function(base64) {
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var len = base64.length, i, encoded1, encoded2, encoded3, encoded4, byte1, byte2, byte3;
var output = "";
for (i = 0; i < len; i+=4) {
encoded1 = chars.indexOf(base64[i]);
encoded2 = chars.indexOf(base64[i+1]);
encoded3 = chars.indexOf(base64[i+2]);
encoded4 = chars.indexOf(base64[i+3]);
byte1 = (encoded1 << 2) | (encoded2 >> 4);
byte2 = ((encoded2 & 15) << 4) | (encoded3 >> 2);
byte3 = ((encoded3 & 3) << 6) | encoded4;
if (encoded3 === 64) {
output += String.fromCharCode(byte1);
} else if (encoded4 === 64 || encoded4 === -1) {
output += String.fromCharCode(byte1, byte2);
} else{
output += String.fromCharCode(byte1, byte2, byte3);
}
}
return output;
};
exports.getBounds = function(node) {
if (node.getBoundingClientRect) {
var clientRect = node.getBoundingClientRect();
var width = node.offsetWidth == null ? clientRect.width : node.offsetWidth;
return {
top: clientRect.top,
bottom: clientRect.bottom || (clientRect.top + clientRect.height),
right: clientRect.left + width,
left: clientRect.left,
width: width,
height: node.offsetHeight == null ? clientRect.height : node.offsetHeight
};
}
return {};
};
exports.offsetBounds = function(node) {
var parent = node.offsetParent ? exports.offsetBounds(node.offsetParent) : {top: 0, left: 0};
return {
top: node.offsetTop + parent.top,
bottom: node.offsetTop + node.offsetHeight + parent.top,
right: node.offsetLeft + parent.left + node.offsetWidth,
left: node.offsetLeft + parent.left,
width: node.offsetWidth,
height: node.offsetHeight
};
};
exports.parseBackgrounds = function(backgroundImage) {
var whitespace = ' \r\n\t',
method, definition, prefix, prefix_i, block, results = [],
mode = 0, numParen = 0, quote, args;
var appendResult = function() {
if(method) {
if (definition.substr(0, 1) === '"') {
definition = definition.substr(1, definition.length - 2);
}
if (definition) {
args.push(definition);
}
if (method.substr(0, 1) === '-' && (prefix_i = method.indexOf('-', 1 ) + 1) > 0) {
prefix = method.substr(0, prefix_i);
method = method.substr(prefix_i);
}
results.push({
prefix: prefix,
method: method.toLowerCase(),
value: block,
args: args,
image: null
});
}
args = [];
method = prefix = definition = block = '';
};
args = [];
method = prefix = definition = block = '';
backgroundImage.split("").forEach(function(c) {
if (mode === 0 && whitespace.indexOf(c) > -1) {
return;
}
switch(c) {
case '"':
if(!quote) {
quote = c;
} else if(quote === c) {
quote = null;
}
break;
case '(':
if(quote) {
break;
} else if(mode === 0) {
mode = 1;
block += c;
return;
} else {
numParen++;
}
break;
case ')':
if (quote) {
break;
} else if(mode === 1) {
if(numParen === 0) {
mode = 0;
block += c;
appendResult();
return;
} else {
numParen--;
}
}
break;
case ',':
if (quote) {
break;
} else if(mode === 0) {
appendResult();
return;
} else if (mode === 1) {
if (numParen === 0 && !method.match(/^url$/i)) {
args.push(definition);
definition = '';
block += c;
return;
}
}
break;
}
block += c;
if (mode === 0) {
method += c;
} else {
definition += c;
}
});
appendResult();
return results;
};

View File

@ -1,6 +1,10 @@
var GradientContainer = require('./gradientcontainer');
function WebkitGradientContainer(imageData) {
GradientContainer.apply(this, arguments);
this.type = (imageData.args[0] === "linear") ? this.TYPES.LINEAR : this.TYPES.RADIAL;
}
WebkitGradientContainer.prototype = Object.create(GradientContainer.prototype);
module.exports = WebkitGradientContainer;

View File

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

View File

@ -1,144 +0,0 @@
<html>
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script type="text/javascript" src="../../src/color.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd')</script>
<script>
describe("Colors", function() {
describe("named colors", function() {
it("bisque", function () {
var c = new Color("bisque");
assertColor(c, 255, 228, 196, null);
expect(c.isTransparent()).to.equal(false);
});
it("BLUE", function () {
var c = new Color("BLUE");
assertColor(c, 0, 0, 255, null);
expect(c.isTransparent()).to.equal(false);
});
});
describe("rgb()", function() {
it("rgb(1,3,5)", function () {
var c = new Color("rgb(1,3,5)");
assertColor(c, 1, 3, 5, null);
expect(c.isTransparent()).to.equal(false);
});
it("rgb(222, 111, 50)", function () {
var c = new Color("rgb(222, 111, 50)");
assertColor(c, 222, 111, 50, null);
expect(c.isTransparent()).to.equal(false);
});
it("rgb( 222, 111 , 50)", function () {
var c = new Color("rgb(222 , 111 , 50)");
assertColor(c, 222, 111, 50, null);
expect(c.isTransparent()).to.equal(false);
});
});
describe("rgba()", function() {
it("rgba(200,3,5,1)", function () {
var c = new Color("rgba(200,3,5,1)");
assertColor(c, 200, 3, 5, 1);
expect(c.isTransparent()).to.equal(false);
});
it("rgba(222, 111, 50, 0.22)", function () {
var c = new Color("rgba(222, 111, 50, 0.22)");
assertColor(c, 222, 111, 50, 0.22);
expect(c.isTransparent()).to.equal(false);
});
it("rgba( 222, 111 , 50, 0.123 )", function () {
var c = new Color("rgba(222 , 111 , 50, 0.123)");
assertColor(c, 222, 111, 50, 0.123);
expect(c.isTransparent()).to.equal(false);
});
});
describe("hex", function() {
it("#7FFFD4", function () {
var c = new Color("#7FFFD4");
assertColor(c, 127, 255, 212, null);
expect(c.isTransparent()).to.equal(false);
});
it("#f0ffff", function () {
var c = new Color("#f0ffff");
assertColor(c, 240, 255, 255, null);
expect(c.isTransparent()).to.equal(false);
});
it("#fff", function () {
var c = new Color("#fff");
assertColor(c, 255, 255, 255, null);
expect(c.isTransparent()).to.equal(false);
});
});
describe("from array", function() {
it("[1,2,3]", function () {
var c = new Color([1,2,3]);
assertColor(c, 1, 2, 3, null);
expect(c.isTransparent()).to.equal(false);
});
it("[5,6,7,1]", function () {
var c = new Color([5,6,7, 1]);
assertColor(c, 5, 6, 7, 1);
expect(c.isTransparent()).to.equal(false);
});
it("[5,6,7,0]", function () {
var c = new Color([5,6,7, 0]);
assertColor(c, 5, 6, 7, 0);
expect(c.isTransparent()).to.equal(true);
});
});
describe("transparency", function() {
it("transparent", function () {
var c = new Color("transparent");
assertColor(c, 0, 0, 0, 0);
expect(c.isTransparent()).to.equal(true);
});
it("rgba(255,255,255,0)", function () {
var c = new Color("rgba(255,255,255,0)");
assertColor(c, 255, 255, 255, 0);
expect(c.isTransparent()).to.equal(true);
});
});
});
function assertColor(c, r, g, b, a) {
expect(c.r).to.equal(r);
expect(c.g).to.equal(g);
expect(c.b).to.equal(b);
expect(c.a).to.equal(a);
}
mocha.checkLeaks();
mocha.globals(['jQuery']);
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
}
else {
mocha.run();
}
mocha.suite.afterAll(function() {
document.body.setAttribute('data-complete', 'true');
});
</script>
</body>
</html>

View File

@ -1,3 +1,5 @@
var NodeContainer = html2canvas.NodeContainer;
describe('Borders', function() {
$('#borders div').each(function(i, node) {
it($(this).attr('style'), function() {
@ -41,7 +43,7 @@ describe('Background-position', function() {
var container = new NodeContainer(node, null);
var item = container.css(prop),
backgroundPosition = container.parseBackgroundPosition(getBounds(node), img),
backgroundPosition = container.parseBackgroundPosition(html2canvas.utils.getBounds(node), img),
split = (window.getComputedStyle) ? $(node).css(prop).split(" ") : [$(node).css(prop+"X"), $(node).css(prop+"Y")];
var testEl = $('<div />').css({
@ -210,7 +212,7 @@ describe('Background-image', function() {
function test_parse_background_image(value, expected, name) {
it(name, function() {
expect(parseBackgrounds(value)).to.eql(Array.isArray(expected) ? expected : [expected]);
expect(html2canvas.utils.parseBackgrounds(value)).to.eql(Array.isArray(expected) ? expected : [expected]);
});
}
});

View File

@ -4,9 +4,6 @@
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script src="../../dist/html2canvas.js"></script>
<script src="../../src/log.js"></script>
<script src="../../src/renderer.js"></script>
<script src="../../src/renderers/canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>
@ -44,6 +41,8 @@
<div id="green-block"></div>
<script>
var CanvasRenderer = html2canvas.CanvasRenderer;
describe("Rendering input values", function() {
it("uses default value for input[type='text']", function(done) {
CanvasRenderer.prototype.text = function(text) {

View File

@ -98,10 +98,10 @@ describe("Gradients", function() {
];
$('#backgroundGradients div').each(function(i, node) {
var container = new NodeContainer(node, null);
var container = new html2canvas.NodeContainer(node, null);
var value = container.css("backgroundImage");
it(value, function() {
var parsedBackground = parseBackgrounds(value);
var parsedBackground = html2canvas.utils.parseBackgrounds(value);
if (parsedBackground[0].args[0] === "0% 50%") {
parsedBackground[0].args[0] = 'left';
}

View File

@ -25,6 +25,7 @@
<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

@ -23,6 +23,7 @@
<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

@ -3,23 +3,7 @@
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="lib/mocha.css" />
<script type="text/javascript" src="../../src/log.js"></script>
<script type="text/javascript" src="../../src/color.js"></script>
<script type="text/javascript" src="../../src/nodecontainer.js"></script>
<script type="text/javascript" src="../../src/stackingcontext.js"></script>
<script type="text/javascript" src="../../src/textcontainer.js"></script>
<script type="text/javascript" src="../../src/support.js"></script>
<script type="text/javascript" src="../../src/imagecontainer.js"></script>
<script type="text/javascript" src="../../src/gradientcontainer.js"></script>
<script type="text/javascript" src="../../src/lineargradientcontainer.js"></script>
<script type="text/javascript" src="../../src/webkitgradientcontainer.js"></script>
<script type="text/javascript" src="../../src/imageloader.js"></script>
<script type="text/javascript" src="../../src/nodeparser.js"></script>
<script type="text/javascript" src="../../src/font.js"></script>
<script type="text/javascript" src="../../src/fontmetrics.js"></script>
<script type="text/javascript" src="../../src/renderer.js"></script>
<script type="text/javascript" src="../../src/promise.js"></script>
<script type="text/javascript" src="../../src/renderers/canvas.js"></script>
<script src="../../dist/html2canvas.js"></script>
<script src="../assets/jquery-1.6.2.js"></script>
<script src="lib/expect.js"></script>
<script src="lib/mocha.js"></script>

119
tests/node/color.js Normal file
View File

@ -0,0 +1,119 @@
var Color = require('../../src/color');
var assert = require('assert');
describe("Colors", function() {
describe("named colors", function() {
it("bisque", function () {
var c = new Color("bisque");
assertColor(c, 255, 228, 196, null);
assert.equal(c.isTransparent(), false);
});
it("BLUE", function () {
var c = new Color("BLUE");
assertColor(c, 0, 0, 255, null);
assert.equal(c.isTransparent(), false);
});
});
describe("rgb()", function() {
it("rgb(1,3,5)", function () {
var c = new Color("rgb(1,3,5)");
assertColor(c, 1, 3, 5, null);
assert.equal(c.isTransparent(), false);
});
it("rgb(222, 111, 50)", function () {
var c = new Color("rgb(222, 111, 50)");
assertColor(c, 222, 111, 50, null);
assert.equal(c.isTransparent(), false);
});
it("rgb( 222, 111 , 50)", function () {
var c = new Color("rgb(222 , 111 , 50)");
assertColor(c, 222, 111, 50, null);
assert.equal(c.isTransparent(), false);
});
});
describe("rgba()", function() {
it("rgba(200,3,5,1)", function () {
var c = new Color("rgba(200,3,5,1)");
assertColor(c, 200, 3, 5, 1);
assert.equal(c.isTransparent(), false);
});
it("rgba(222, 111, 50, 0.22)", function () {
var c = new Color("rgba(222, 111, 50, 0.22)");
assertColor(c, 222, 111, 50, 0.22);
assert.equal(c.isTransparent(), false);
});
it("rgba( 222, 111 , 50, 0.123 )", function () {
var c = new Color("rgba(222 , 111 , 50, 0.123)");
assertColor(c, 222, 111, 50, 0.123);
assert.equal(c.isTransparent(), false);
});
});
describe("hex", function() {
it("#7FFFD4", function () {
var c = new Color("#7FFFD4");
assertColor(c, 127, 255, 212, null);
assert.equal(c.isTransparent(), false);
});
it("#f0ffff", function () {
var c = new Color("#f0ffff");
assertColor(c, 240, 255, 255, null);
assert.equal(c.isTransparent(), false);
});
it("#fff", function () {
var c = new Color("#fff");
assertColor(c, 255, 255, 255, null);
assert.equal(c.isTransparent(), false);
});
});
describe("from array", function() {
it("[1,2,3]", function () {
var c = new Color([1,2,3]);
assertColor(c, 1, 2, 3, null);
assert.equal(c.isTransparent(), false);
});
it("[5,6,7,1]", function () {
var c = new Color([5,6,7, 1]);
assertColor(c, 5, 6, 7, 1);
assert.equal(c.isTransparent(), false);
});
it("[5,6,7,0]", function () {
var c = new Color([5,6,7, 0]);
assertColor(c, 5, 6, 7, 0);
assert.equal(c.isTransparent(), true);
});
});
describe("transparency", function() {
it("transparent", function () {
var c = new Color("transparent");
assertColor(c, 0, 0, 0, 0);
assert.equal(c.isTransparent(), true);
});
it("rgba(255,255,255,0)", function () {
var c = new Color("rgba(255,255,255,0)");
assertColor(c, 255, 255, 255, 0);
assert.equal(c.isTransparent(), true);
});
});
});
function assertColor(c, r, g, b, a) {
assert.equal(c.r, r);
assert.equal(c.g, g);
assert.equal(c.b, b);
assert.equal(c.a, a);
}

View File

@ -1,10 +1,3 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
Released under MIT License
*/
var h2cSelector, h2cOptions;
(function(document, window) {
function appendScript(src) {
@ -14,7 +7,7 @@ var h2cSelector, h2cOptions;
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'].concat(window.location.search === "?selenium" ? ['/dist/html2canvas'] : sources.map(function(src) { return '/src/' + src; })).forEach(appendScript);
['/tests/assets/jquery-1.6.2', '/dist/html2canvas'].forEach(appendScript);
if (typeof(noFabric) === "undefined") {
appendScript('/dist/html2canvas.svg');
@ -104,7 +97,7 @@ var h2cSelector, h2cOptions;
textDecoration:'none',
display:'none'
}).appendTo(document.body).fadeIn();
log(msg);
console.log(msg);
}
};
})(jQuery);