diff --git a/README.md b/README.md index e9f7faa..4d1fe80 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,24 @@ You should now be able to select your new example from playground.html or see it If you find a bug, or want to add functionality, please add a new test case and include it with your pull request. +Using with node.js +================== + +You can use `canvas2svg` with node.js using [jsdom](https://github.com/tmpvar/jsdom) with [node-canvas](https://github.com/Automattic/node-canvas). To do this first create a new document object, and then create a new instance of `C2S` based on that document: + +```javascript +var canvas = require('canvas'), + jsdom = require('jsdom'), + C2S = require('canvas2svg'); + +var document = jsdom.jsdom(); +var ctx = new C2S({document: document}); + +// ... drawing code goes here ... +``` + +N.B. You may not need node-canvas for some simple operations when using jsdom >= 6.3.0, but it's still recommended that you install it. + Updates ========== - v1.0.15 Setup travis, add testharness and debug playground, and fix regression for __createElement refactor @@ -103,6 +121,17 @@ Misc ========== Some canvas 2d context methods are not implemented yet. Watch out for setTransform and arcTo. +Releasing +========= + +To release a new version: + +* Run `gulp bump` to update the version number +* Add a new entry to the [Updates](#Updates) table +* `git commit -am v1.0.xx` +* `git push` +* `npm publish` + License ========== This library is licensed under the MIT license. diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..cae3554 --- /dev/null +++ b/bower.json @@ -0,0 +1,5 @@ +{ + "name": "canvas2svg", + "version": "1.0.14", + "main": "./canvas2svg.js" +} diff --git a/canvas2svg.js b/canvas2svg.js index ff09f8a..d79d6bc 100644 --- a/canvas2svg.js +++ b/canvas2svg.js @@ -72,29 +72,6 @@ return mapping[textBaseline] || mapping.alphabetic; } - /** - * Creates the specified svg element - * @private - */ - function createElement(elementName, properties, resetFill) { - if (typeof properties === "undefined") { - properties = {}; - } - - var element = document.createElementNS("http://www.w3.org/2000/svg", elementName), - keys = Object.keys(properties), i, key; - if(resetFill) { - //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black. - element.setAttribute("fill", "none"); - element.setAttribute("stroke", "none"); - } - for(i=0; i 1) { @@ -258,7 +237,8 @@ this.enableMirroring = options.enableMirroring !== undefined ? options.enableMirroring : defaultOptions.enableMirroring; this.canvas = this; ///point back to this instance! - this.__canvas = document.createElement("canvas"); + this.__document = options.document || document; + this.__canvas = this.__document.createElement("canvas"); this.__ctx = this.__canvas.getContext("2d"); this.__setDefaultStyles(); @@ -266,7 +246,7 @@ this.__groupStack = []; //the root svg element - this.__root = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + this.__root = this.__document.createElementNS("http://www.w3.org/2000/svg", "svg"); this.__root.setAttribute("version", 1.1); this.__root.setAttribute("xmlns", "http://www.w3.org/2000/svg"); this.__root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); @@ -277,14 +257,38 @@ this.__ids = {}; //defs tag - this.__defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); + this.__defs = this.__document.createElementNS("http://www.w3.org/2000/svg", "defs"); this.__root.appendChild(this.__defs); //also add a group child. the svg element can't use the transform attribute - this.__currentElement = document.createElementNS("http://www.w3.org/2000/svg", "g"); + this.__currentElement = this.__document.createElementNS("http://www.w3.org/2000/svg", "g"); this.__root.appendChild(this.__currentElement); }; + + /** + * Creates the specified svg element + * @private + */ + ctx.prototype.__createElement = function (elementName, properties, resetFill) { + if (typeof properties === "undefined") { + properties = {}; + } + + var element = this.__document.createElementNS("http://www.w3.org/2000/svg", elementName), + keys = Object.keys(properties), i, key; + if(resetFill) { + //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black. + element.setAttribute("fill", "none"); + element.setAttribute("stroke", "none"); + } + for(i=0; i 0) { - var group = createElement("g"); + var group = this.__createElement("g"); parent.appendChild(group); this.__currentElement = group; } @@ -509,7 +513,7 @@ this.__currentDefaultPath = ""; this.__currentPosition = {}; - path = createElement("path", {}, true); + path = this.__createElement("path", {}, true); parent = this.__closestGroupOrSvg(); parent.appendChild(path); this.__currentElement = path; @@ -732,7 +736,7 @@ */ ctx.prototype.fillRect = function(x, y, width, height){ var rect, parent; - rect = createElement("rect", { + rect = this.__createElement("rect", { x : x, y : y, width : width, @@ -753,7 +757,7 @@ */ ctx.prototype.strokeRect = function(x, y, width, height){ var rect, parent; - rect = createElement("rect", { + rect = this.__createElement("rect", { x : x, y : y, width : width, @@ -771,7 +775,7 @@ */ ctx.prototype.clearRect = function(x, y, width, height) { var rect, parent = this.__closestGroupOrSvg(); - rect = createElement("rect", { + rect = this.__createElement("rect", { x : x, y : y, width : width, @@ -786,7 +790,7 @@ * Returns a canvas gradient object that has a reference to it's parent def */ ctx.prototype.createLinearGradient = function(x1, y1, x2, y2){ - var grad = createElement("linearGradient", { + var grad = this.__createElement("linearGradient", { id : randomString(this.__ids), x1 : x1+"px", x2 : x2+"px", @@ -795,7 +799,7 @@ "gradientUnits" : "userSpaceOnUse" }, false); this.__defs.appendChild(grad); - return new CanvasGradient(grad); + return new CanvasGradient(grad, this); }; /** @@ -803,7 +807,7 @@ * Returns a canvas gradient object that has a reference to it's parent def */ ctx.prototype.createRadialGradient = function(x0, y0, r0, x1, y1, r1){ - var grad = createElement("radialGradient", { + var grad = this.__createElement("radialGradient", { id : randomString(this.__ids), cx : x1+"px", cy : y1+"px", @@ -813,7 +817,7 @@ "gradientUnits" : "userSpaceOnUse" }, false); this.__defs.appendChild(grad); - return new CanvasGradient(grad); + return new CanvasGradient(grad, this); }; @@ -855,7 +859,7 @@ */ ctx.prototype.__wrapTextLink = function(font, element) { if(font.href) { - var a = createElement("a"); + var a = this.__createElement("a"); a.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", font.href); a.appendChild(element); return a; @@ -874,7 +878,7 @@ ctx.prototype.__applyText = function(text, x, y, action) { var font = this.__parseFont(), parent = this.__closestGroupOrSvg(), - textElement = createElement("text", { + textElement = this.__createElement("text", { "font-family" : font.family, "font-size" : font.size, "font-style" : font.style, @@ -886,7 +890,7 @@ "dominant-baseline": getDominantBaseline(this.textBaseline) }, true); - textElement.appendChild(document.createTextNode(text)); + textElement.appendChild(this.__document.createTextNode(text)); this.__currentElement = textElement; this.__applyStyleToCurrentElement(action); parent.appendChild(this.__wrapTextLink(font,textElement)); @@ -963,9 +967,9 @@ */ ctx.prototype.clip = function(){ var group = this.__closestGroupOrSvg(), - clipPath = createElement("clipPath"), + clipPath = this.__createElement("clipPath"), id = randomString(this.__ids), - newGroup = createElement("g"); + newGroup = this.__createElement("g"); group.removeChild(this.__currentElement); clipPath.setAttribute("id", id); @@ -1043,14 +1047,14 @@ this.__currentElement = currentElement; } else if(image.nodeName === "CANVAS" || image.nodeName === "IMG") { //canvas or image - svgImage = createElement("image"); + svgImage = this.__createElement("image"); svgImage.setAttribute("width", dw); svgImage.setAttribute("height", dh); svgImage.setAttribute("preserveAspectRatio", "none"); if(sx || sy || sw !== image.width || sh !== image.height) { //crop the image using a temporary canvas - canvas = document.createElement("canvas"); + canvas = this.__document.createElement("canvas"); canvas.width = dw; canvas.height = dh; context = canvas.getContext("2d"); @@ -1071,13 +1075,13 @@ * Generates a pattern tag */ ctx.prototype.createPattern = function(image, repetition){ - var pattern = document.createElementNS("http://www.w3.org/2000/svg", "pattern"), id = randomString(this.__ids), + var pattern = this.__document.createElementNS("http://www.w3.org/2000/svg", "pattern"), id = randomString(this.__ids), img; pattern.setAttribute("id", id); pattern.setAttribute("width", image.width); pattern.setAttribute("height", image.height); if(image.nodeName === "CANVAS" || image.nodeName === "IMG") { - img = document.createElementNS("http://www.w3.org/2000/svg", "image"); + img = this.__document.createElementNS("http://www.w3.org/2000/svg", "image"); img.setAttribute("width", image.width); img.setAttribute("height", image.height); img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", @@ -1102,6 +1106,13 @@ ctx.prototype.setTransform = function(){}; //add options for alternative namespace - window.C2S = ctx; + if (typeof window === "object") { + window.C2S = ctx; + } + + // CommonJS/Browserify + if (typeof module === "object" && typeof module.exports === "object") { + module.exports = ctx; + } }()); diff --git a/gulpfile.js b/gulpfile.js index 324faed..35c3e12 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -4,6 +4,7 @@ var gulp = require('gulp'); var fs = require('fs'); var path = require('path'); var cheerio = require('cheerio'); +var bump = require('gulp-bump'); function updateExample(filename) { @@ -28,4 +29,10 @@ gulp.task('update_examples', function() { updateExample('test/testrunner.html'); }); -gulp.task('default', ['update_examples']); \ No newline at end of file +gulp.task('bump', function() { + gulp.src(["./package.json", "./bower.json"]) + .pipe(bump({type:'patch'})) + .pipe(gulp.dest('./')); +}); + +gulp.task('default', ['update_examples']); diff --git a/package.json b/package.json index a1e3c7c..6d4e567 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "chai": "^2.1.1", "cheerio": "^0.19.0", "gulp": "^3.9.0", + "gulp-bump": "^0.3.1", "karma": "^0.12.36", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^0.1.12", diff --git a/test/unit.spec.js b/test/unit.spec.js index fc3229d..e8f05a7 100644 --- a/test/unit.spec.js +++ b/test/unit.spec.js @@ -46,6 +46,12 @@ describe('canvas2svg', function() { }); + it("can be created on another document", function () { + var otherDoc = document.implementation.createHTMLDocument(); + var ctx = C2S({document: otherDoc}); + expect(ctx.getSvg().ownerDocument).to.equal(otherDoc); + }); + }); describe("can export to", function() {