├── .nvmrc ├── .jshintrc ├── .gitignore ├── .travis.yml ├── src ├── parse.js ├── transform.js ├── lib.js ├── flatten.js └── pathify.js ├── LICENSE ├── package.json ├── test ├── lib-samples.spec.js ├── flatten.spec.js ├── samples │ ├── sample2_result.svg │ ├── sample2.svg │ ├── sample1_result.svg │ ├── sample1.svg │ ├── sample3.svg │ └── sample3_result.svg ├── transform.spec.js ├── lib.spec.js ├── pathify.spec.js └── parse.spec.js └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 8 -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 6 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directories 2 | node_modules 3 | jspm_packages 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - 8 5 | - 14 6 | - lts/* 7 | 8 | scripts: 9 | - npm test 10 | - npm run lint 11 | -------------------------------------------------------------------------------- /src/parse.js: -------------------------------------------------------------------------------- 1 | var xmldoc = require('xmldoc'); 2 | 3 | module.exports = function (source) { 4 | try { 5 | return new xmldoc.XmlDocument(source); 6 | } catch (exception) { 7 | var dom = new xmldoc.XmlDocument(''); 8 | dom.attr.reason = exception.toString(); 9 | 10 | return dom; 11 | } 12 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2016 StadLine 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 | OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svg-flatten", 3 | "version": "1.0.1", 4 | "description": "Turns SVG shapes (polygon, polyline, rect, g) into SVG paths. It can merge groups and apply transforms.", 5 | "main": "src/lib.js", 6 | "dependencies": { 7 | "svgpath": "^2.1.6", 8 | "xmldoc": "^0.5.0" 9 | }, 10 | "devDependencies": { 11 | "chai": "^3.5.0", 12 | "jshint": "^2.9.1", 13 | "mocha": "^2.4.5", 14 | "proxyquire": "^1.7.9", 15 | "sinon": "^1.17.4" 16 | }, 17 | "scripts": { 18 | "test": "mocha", 19 | "lint": "jshint **/*.js" 20 | }, 21 | "keywords": [ 22 | "svg", 23 | "flatten", 24 | "flattener", 25 | "shape", 26 | "circle", 27 | "ellipse", 28 | "line", 29 | "path", 30 | "polygon", 31 | "polyline", 32 | "rect", 33 | "g", 34 | "transform" 35 | ], 36 | "author": "alex-pex", 37 | "license": "ISC", 38 | "repository": "stadline/svg-flatten" 39 | } 40 | -------------------------------------------------------------------------------- /src/transform.js: -------------------------------------------------------------------------------- 1 | var svgpath = require('svgpath'); 2 | 3 | function transformGroup(dom) { 4 | var newChildren = []; 5 | 6 | dom.children.forEach(function (child) { 7 | newChildren.push(transform(child)); 8 | }); 9 | 10 | dom.children = newChildren; 11 | 12 | if (newChildren.length > 0) { 13 | dom.firstChild = newChildren[0]; 14 | dom.lastChild = newChildren[newChildren.length - 1]; 15 | } 16 | 17 | return dom; 18 | } 19 | 20 | function transformPath(dom) { 21 | dom.attr.d = svgpath(dom.attr.d).transform(dom.attr.transform) 22 | .round(10) 23 | .toString(); 24 | 25 | delete dom.attr.transform; 26 | 27 | return dom; 28 | } 29 | 30 | function transform(dom) { 31 | if (dom.name === 'path' && dom.attr.transform) { 32 | return transformPath(dom); 33 | } else if (dom.name === 'svg' || dom.name === 'g') { 34 | return transformGroup(dom); 35 | } else { 36 | return dom; 37 | } 38 | } 39 | 40 | module.exports = transform; -------------------------------------------------------------------------------- /src/lib.js: -------------------------------------------------------------------------------- 1 | var parseFn = require('./parse.js'); 2 | var pathifyFn = require('./pathify.js'); 3 | var transformFn = require('./transform.js'); 4 | var flattenFn = require('./flatten.js'); 5 | 6 | function Wrapper(source) { 7 | if (typeof source === "string") { 8 | this._value = parseFn(source); 9 | } else { 10 | this._value = source; 11 | } 12 | 13 | this.pathify = function() { 14 | this._value = pathifyFn(this._value); 15 | return this; 16 | }; 17 | 18 | this.transform = function() { 19 | this._value = transformFn(this._value); 20 | return this; 21 | }; 22 | 23 | this.flatten = function() { 24 | this._value = flattenFn(this._value); 25 | return this; 26 | }; 27 | 28 | this.value = function() { 29 | if (typeof source === "string") { 30 | var meta = source.substr(0, source.indexOf("<" + this._value.name)); 31 | return meta + this._value.toString(); 32 | } else { 33 | return this._value; 34 | } 35 | }; 36 | } 37 | 38 | module.exports = function(source) { 39 | return new Wrapper(source); 40 | }; 41 | -------------------------------------------------------------------------------- /src/flatten.js: -------------------------------------------------------------------------------- 1 | var transform = require('./transform.js'); 2 | var xmldoc = require('xmldoc'); 3 | 4 | function flattenSvg(dom) { 5 | var newChildren = []; 6 | 7 | dom.children.forEach(function (child) { 8 | newChildren.push(flatten(child)); 9 | }); 10 | 11 | dom.children = newChildren; 12 | 13 | if (newChildren.length > 0) { 14 | dom.firstChild = newChildren[0]; 15 | dom.lastChild = newChildren[newChildren.length - 1]; 16 | } 17 | 18 | return dom; 19 | } 20 | 21 | function flattenGroup(dom) { 22 | var path = new xmldoc.XmlDocument(''); 23 | 24 | path.attr = dom.attr; 25 | path.attr.d = ""; 26 | 27 | dom.children.forEach(function (child) { 28 | var flatChild = transform(flatten(child)); 29 | 30 | if (flatChild.attr.d) { 31 | var prefix = path.attr.d.length ? " " : ""; 32 | path.attr.d += prefix + flatChild.attr.d; 33 | } 34 | }); 35 | 36 | return path; 37 | } 38 | 39 | function flatten(dom) { 40 | if (dom.name === 'svg') { 41 | return flattenSvg(dom); 42 | } else if (dom.name === 'g') { 43 | return flattenGroup(dom); 44 | } else { 45 | return dom; 46 | } 47 | } 48 | 49 | module.exports = flatten; -------------------------------------------------------------------------------- /test/lib-samples.spec.js: -------------------------------------------------------------------------------- 1 | /*jshint mocha: true*/ 2 | 3 | var expect = require('chai').expect; 4 | var fs = require('fs'); 5 | var svgflatten = require('../src/lib.js'); 6 | var xmldoc = require('xmldoc'); 7 | 8 | // test 9 | describe('svg-flatten: test samples', function () { 10 | var samples = ["sample1", "sample2", "sample3"]; 11 | 12 | samples.forEach(function(basename) { 13 | it('should give accurate results (' + basename + ')', function () { 14 | var sample = fs.readFileSync(__dirname + '/samples/' + basename + '.svg', 'utf8'); 15 | var expectedResult = fs.readFileSync(__dirname + '/samples/' + basename + '_result.svg', 'utf8'); 16 | 17 | // test with string 18 | var result = svgflatten(sample) 19 | .pathify() 20 | .flatten() 21 | .transform() 22 | .value(); 23 | 24 | expect(result).to.be.equal(expectedResult); 25 | 26 | // test with dom 27 | var sampleDom = new xmldoc.XmlDocument(sample); 28 | var expectedResultDom = new xmldoc.XmlDocument(expectedResult); 29 | 30 | var resultDom = svgflatten(sampleDom) 31 | .pathify() 32 | .flatten() 33 | .transform() 34 | .value(); 35 | 36 | expect(resultDom.toString()).to.be.equal(expectedResultDom.toString()); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/flatten.spec.js: -------------------------------------------------------------------------------- 1 | /*jshint mocha: true*/ 2 | 3 | var expect = require('chai').expect; 4 | var xmldoc = require('xmldoc'); 5 | var flattenFn = require('../src/flatten.js'); 6 | 7 | // test 8 | describe('svg-flatten: flatten function', function() { 9 | it('should flatten path groups', function() { 10 | var source = new xmldoc.XmlDocument(''); 11 | var target = new xmldoc.XmlDocument(''); 12 | 13 | // test 14 | expect(flattenFn(source).toString()).to.be.equal(target.toString()); 15 | }); 16 | 17 | it('should flatten nested path groups', function() { 18 | var source = new xmldoc.XmlDocument(''); 19 | var target = new xmldoc.XmlDocument(''); 20 | 21 | // test 22 | expect(flattenFn(source).toString()).to.be.equal(target.toString()); 23 | }); 24 | 25 | it('should work with complex groups', function() { 26 | var source = new xmldoc.XmlDocument(''); 27 | var target = new xmldoc.XmlDocument(''); 28 | 29 | // test 30 | expect(flattenFn(source).toString()).to.be.equal(target.toString()); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | svg-flatten 2 | ========================================================================================== 3 | 4 | Turns SVG shapes (polygon, polyline, rect, g) into SVG paths. It can merge groups and apply transforms. 5 | 6 | How to use? 7 | ----------- 8 | 9 | ```js 10 | const svgFlatten = require('svg-flatten') 11 | const fs = require('fs') 12 | 13 | let flattendSvgPath = 'tmp-flattened.svg' 14 | 15 | // read SVG file into string 16 | let svgString = fs.readFileSync('circle-rect.svg', 'utf8') 17 | // convert all objects to paths 18 | let modifiedSvgString = svgFlatten(svgString).pathify().value() 19 | // write SVG string to disk 20 | fs.writeFileSync(flattendSvgPath,modifiedSvgString) 21 | ``` 22 | 23 | API 24 | --- 25 | 26 | ### svgFlatten(content: string): SvgFlatten 27 | 28 | Reads SVG content and creates a SvgFlatten instance. 29 | 30 | ### .pathify(): SvgFlatten 31 | 32 | Turns SVG shapes (polygon, polyline, rect, g) into SVG paths. It is **needed** before other transformations. 33 | 34 | ### .flatten(): SvgFlatten 35 | 36 | Converts groups of paths to a fat path, combining all child paths into one. 37 | 38 | **Be careful: it tries to squash the xml structure, information can be lost.** 39 | 40 | Some example of the limitations: 41 | - duplicate attributes cannot be safely squashed, like the id in `` 42 | - style rules based on the structure like `#g1 > circle` 43 | - [`use`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use) directive may not apply 44 | 45 | ### .transform(): SvgFlatten 46 | 47 | Apply [SVG transformations](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform) to paths. It doesn't apply clipPath. 48 | 49 | ### .value(): string 50 | 51 | Returns the final result as SVG content. 52 | 53 | Need more info? 54 | --------------- 55 | 56 | Sadly, I wrote this lib for an old project (2016) and didn't need to tweak it since. It is not actively maintened, but I'll try to watch pull-requests. 57 | -------------------------------------------------------------------------------- /test/samples/sample2_result.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /test/samples/sample2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/samples/sample1_result.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/samples/sample1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/transform.spec.js: -------------------------------------------------------------------------------- 1 | /*jshint mocha: true*/ 2 | 3 | var expect = require('chai').expect; 4 | var xmldoc = require('xmldoc'); 5 | var transformFn = require('../src/transform.js'); 6 | 7 | // test 8 | describe('svg-flatten: transform function', function() { 9 | it('should apply translate transformation', function() { 10 | var source = new xmldoc.XmlDocument(''); 11 | var target = new xmldoc.XmlDocument(''); 12 | 13 | // test 14 | expect(transformFn(source).toString()).to.be.equal(target.toString()); 15 | }); 16 | 17 | it('should apply rotate transformation', function() { 18 | var source = new xmldoc.XmlDocument(''); 19 | var target = new xmldoc.XmlDocument(''); 20 | 21 | // test 22 | expect(transformFn(source).toString()).to.be.equal(target.toString()); 23 | }); 24 | 25 | it('should apply chained transformation', function() { 26 | var source = new xmldoc.XmlDocument(''); 27 | var target = new xmldoc.XmlDocument(''); 28 | 29 | // test 30 | expect(transformFn(source).toString()).to.be.equal(target.toString()); 31 | }); 32 | 33 | it('should work with complex paths', function() { 34 | var circle = new xmldoc.XmlDocument(''); 35 | var ellipse = new xmldoc.XmlDocument(''); 36 | var line = new xmldoc.XmlDocument(''); 37 | var polygon = new xmldoc.XmlDocument(''); 38 | var polyline = new xmldoc.XmlDocument(''); 39 | var rect = new xmldoc.XmlDocument(''); 40 | var shape = new xmldoc.XmlDocument(''); 41 | 42 | // test 43 | expect(transformFn(circle).toString()).to.be.equal(''); 44 | expect(transformFn(ellipse).toString()).to.be.equal(''); 45 | expect(transformFn(line).toString()).to.be.equal(''); 46 | expect(transformFn(polygon).toString()).to.be.equal(''); 47 | expect(transformFn(polyline).toString()).to.be.equal(''); 48 | expect(transformFn(rect).toString()).to.be.equal(''); 49 | expect(transformFn(shape).toString()).to.be.equal(''); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/samples/sample3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/pathify.js: -------------------------------------------------------------------------------- 1 | /*jshint singleGroups: false*/ 2 | 3 | function _convertEllipse(cx = 0, cy = 0, rx = 0, ry = 0) { 4 | return "M" + (cx - rx) + "," + cy + "a" + rx + "," + ry + " 0 1,0 " + (rx * 2) + ",0a" + rx + "," + ry + " 0 1,0 " + (rx * -2) + ",0"; 5 | } 6 | 7 | function _convertPoints(points) { 8 | var path = ""; 9 | 10 | for (var i=0; i 0) { 28 | dom.firstChild = newChildren[0]; 29 | dom.lastChild = newChildren[newChildren.length - 1]; 30 | } 31 | 32 | return dom; 33 | } 34 | 35 | function convertCircle(dom) { 36 | var path = _convertEllipse(dom.attr.cx, dom.attr.cy, dom.attr.r, dom.attr.r); 37 | 38 | delete dom.attr.cx; 39 | delete dom.attr.cy; 40 | delete dom.attr.r; 41 | 42 | dom.name = 'path'; 43 | dom.attr.d = path; 44 | 45 | return dom; 46 | } 47 | 48 | function convertEllipse(dom) { 49 | var path = _convertEllipse(dom.attr.cx, dom.attr.cy, dom.attr.rx, dom.attr.ry); 50 | 51 | delete dom.attr.cx; 52 | delete dom.attr.cy; 53 | delete dom.attr.rx; 54 | delete dom.attr.ry; 55 | 56 | dom.name = 'path'; 57 | dom.attr.d = path; 58 | 59 | return dom; 60 | } 61 | 62 | function convertLine(dom) { 63 | var path = _convertPoints([dom.attr.x1, dom.attr.y1, dom.attr.x2, dom.attr.y2]); 64 | 65 | delete dom.attr.x1; 66 | delete dom.attr.y1; 67 | delete dom.attr.x2; 68 | delete dom.attr.y2; 69 | 70 | dom.name = 'path'; 71 | dom.attr.d = path; 72 | 73 | return dom; 74 | } 75 | 76 | function convertPolygon(dom) { 77 | var points = dom.attr.points.trim().split(/[\s,]+/); 78 | var path = _convertPoints(points) + "z"; 79 | 80 | delete dom.attr.points; 81 | 82 | dom.name = 'path'; 83 | dom.attr.d = path; 84 | 85 | return dom; 86 | } 87 | 88 | function convertPolyline(dom) { 89 | var points = dom.attr.points.trim().split(/[\s,]+/); 90 | var path = _convertPoints(points); 91 | 92 | delete dom.attr.points; 93 | 94 | dom.name = 'path'; 95 | dom.attr.d = path; 96 | 97 | return dom; 98 | } 99 | 100 | function convertRect(dom) { 101 | var x = parseFloat(dom.attr.x || 0); 102 | var y = parseFloat(dom.attr.y || 0); 103 | var width = parseFloat(dom.attr.width); 104 | var height = parseFloat(dom.attr.height); 105 | 106 | var points = []; 107 | points.push(x, y); 108 | points.push(x + width, y); 109 | points.push(x + width, y + height); 110 | points.push(x, y + height); 111 | var path = _convertPoints(points) + "z"; 112 | 113 | delete dom.attr.x; 114 | delete dom.attr.y; 115 | delete dom.attr.width; 116 | delete dom.attr.height; 117 | 118 | dom.name = 'path'; 119 | dom.attr.d = path; 120 | 121 | return dom; 122 | } 123 | 124 | function pathify(dom) { 125 | if (dom.name === 'svg') { 126 | return convertGroup(dom); 127 | } else if (dom.name === 'circle') { 128 | return convertCircle(dom); 129 | } else if (dom.name === 'ellipse') { 130 | return convertEllipse(dom); 131 | } else if (dom.name === 'line') { 132 | return convertLine(dom); 133 | } else if (dom.name === 'polygon') { 134 | return convertPolygon(dom); 135 | } else if (dom.name === 'polyline') { 136 | return convertPolyline(dom); 137 | } else if (dom.name === 'rect') { 138 | return convertRect(dom); 139 | } else if (dom.name === 'g') { 140 | return convertGroup(dom); 141 | } else { 142 | return dom; 143 | } 144 | } 145 | 146 | module.exports = pathify; 147 | -------------------------------------------------------------------------------- /test/lib.spec.js: -------------------------------------------------------------------------------- 1 | /*jshint mocha: true*/ 2 | /*jshint expr: true*/ 3 | /*jshint multistr: true*/ 4 | 5 | var expect = require('chai').expect; 6 | var sinon = require('sinon'); 7 | var proxyquire = require('proxyquire'); 8 | 9 | // sample file 10 | var file = ' \ 11 | \ 12 | \ 13 | \ 14 | \ 15 | '; 16 | 17 | // test 18 | describe('svg-flatten lib', function() { 19 | var parse; 20 | var pathify; 21 | var transform; 22 | var flatten; 23 | var lib; 24 | 25 | beforeEach(function () { 26 | parse = sinon.stub(); 27 | pathify = sinon.stub(); 28 | transform = sinon.stub(); 29 | flatten = sinon.stub(); 30 | 31 | parse.withArgs(file).returns(file); 32 | 33 | // inject stubs into library 34 | lib = proxyquire('../src/lib.js', { 35 | './parse.js': parse, 36 | './pathify.js': pathify, 37 | './transform.js': transform, 38 | './flatten.js': flatten 39 | }); 40 | }); 41 | 42 | it('should wrap the source', function() { 43 | var wrapper = lib(file); 44 | 45 | // test 46 | expect(wrapper).to.be.an('object'); 47 | expect(wrapper._value).to.be.equal(file); 48 | }); 49 | 50 | it('should apply the parse filter', function() { 51 | // init mocks 52 | var parsedFile = { 53 | parsed: true 54 | }; 55 | 56 | parse.withArgs(file).returns(parsedFile); 57 | 58 | // test 59 | expect(lib(file)._value).to.be.equal(parsedFile); 60 | expect(parse.calledOnce).to.be.true; 61 | }); 62 | 63 | it('should apply the pathify filter', function() { 64 | var wrapper = lib(file); 65 | 66 | // init mocks 67 | var pathifiedFile = { 68 | pathified: true 69 | }; 70 | 71 | pathify.withArgs(file).returns(pathifiedFile); 72 | 73 | // test 74 | expect(wrapper.pathify()._value).to.be.equal(pathifiedFile); 75 | expect(pathify.calledOnce).to.be.true; 76 | }); 77 | 78 | it('should apply the transform filter', function() { 79 | var wrapper = lib(file); 80 | 81 | // init mocks 82 | var transformedFile = { 83 | transformed: true 84 | }; 85 | 86 | transform.withArgs(file).returns(transformedFile); 87 | 88 | // test 89 | expect(wrapper.transform()._value).to.be.equal(transformedFile); 90 | expect(transform.calledOnce).to.be.true; 91 | }); 92 | 93 | it('should apply the flatten filter', function() { 94 | var wrapper = lib(file); 95 | 96 | // init mocks 97 | var flatFile = { 98 | flat: true 99 | }; 100 | 101 | flatten.withArgs(file).returns(flatFile); 102 | 103 | // test 104 | expect(wrapper.flatten()._value).to.be.equal(flatFile); 105 | expect(flatten.calledOnce).to.be.true; 106 | }); 107 | 108 | it('should chain filters', function() { 109 | var wrapper = lib(file); 110 | 111 | // init mocks 112 | var pathifiedFile = { 113 | pathified: true 114 | }; 115 | 116 | var flatFile = { 117 | flat: true 118 | }; 119 | 120 | pathify.withArgs(file).returns(pathifiedFile); 121 | flatten.withArgs(pathifiedFile).returns(flatFile); 122 | 123 | // test 124 | expect(wrapper.pathify().flatten()._value).to.be.equal(flatFile); 125 | expect(parse.calledOnce).to.be.true; 126 | expect(pathify.calledOnce).to.be.true; 127 | expect(flatten.calledOnce).to.be.true; 128 | }); 129 | }); 130 | -------------------------------------------------------------------------------- /test/pathify.spec.js: -------------------------------------------------------------------------------- 1 | /*jshint mocha: true*/ 2 | 3 | var expect = require('chai').expect; 4 | var xmldoc = require('xmldoc'); 5 | var pathifyFn = require('../src/pathify.js'); 6 | 7 | // test 8 | describe('svg-flatten: pathify function', function() { 9 | it('should convert circle', function() { 10 | var source = new xmldoc.XmlDocument(''); 11 | var target = new xmldoc.XmlDocument(''); 12 | 13 | // test 14 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 15 | }); 16 | 17 | it('should convert circle without center point', function() { 18 | var source = new xmldoc.XmlDocument(''); 19 | var target = new xmldoc.XmlDocument(''); 20 | 21 | // test 22 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 23 | }); 24 | 25 | it('should convert circle without radius', function() { 26 | var source = new xmldoc.XmlDocument(''); 27 | var target = new xmldoc.XmlDocument(''); 28 | 29 | // test 30 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 31 | }); 32 | 33 | it('should convert ellipse', function() { 34 | var source = new xmldoc.XmlDocument(''); 35 | var target = new xmldoc.XmlDocument(''); 36 | 37 | // test 38 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 39 | }); 40 | 41 | it('should convert line', function() { 42 | var source = new xmldoc.XmlDocument(''); 43 | var target = new xmldoc.XmlDocument(''); 44 | 45 | // test 46 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 47 | }); 48 | 49 | it('should convert polygons', function() { 50 | var source = new xmldoc.XmlDocument(''); 51 | var target = new xmldoc.XmlDocument(''); 52 | 53 | // test 54 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 55 | }); 56 | 57 | it('should convert polyline', function() { 58 | var source = new xmldoc.XmlDocument(''); 59 | var target = new xmldoc.XmlDocument(''); 60 | 61 | // test 62 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 63 | }); 64 | 65 | it('should convert polyline with extra whitespaces', function() { 66 | var source = new xmldoc.XmlDocument(''); 67 | var target = new xmldoc.XmlDocument(''); 68 | 69 | // test 70 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 71 | }); 72 | 73 | it('should convert rect', function() { 74 | var source = new xmldoc.XmlDocument(''); 75 | var target = new xmldoc.XmlDocument(''); 76 | 77 | // test 78 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 79 | }); 80 | 81 | it('should preserve groups', function() { 82 | var source = new xmldoc.XmlDocument(''); 83 | 84 | // test 85 | expect(pathifyFn(source)).to.be.equal(source); 86 | }); 87 | it('should preserve nested groups', function() { 88 | var source = new xmldoc.XmlDocument(''); 89 | var target = new xmldoc.XmlDocument(''); 90 | 91 | // test 92 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 93 | }); 94 | 95 | it('should should convert group children', function() { 96 | var source = new xmldoc.XmlDocument(''); 97 | var target = new xmldoc.XmlDocument(''); 98 | 99 | // test 100 | expect(pathifyFn(source).toString()).to.be.equal(target.toString()); 101 | }); 102 | }); 103 | -------------------------------------------------------------------------------- /test/parse.spec.js: -------------------------------------------------------------------------------- 1 | /*jshint mocha: true*/ 2 | /*jshint expr: true*/ 3 | /*jshint multistr: true*/ 4 | 5 | var expect = require('chai').expect; 6 | var parseFn = require('../src/parse.js'); 7 | 8 | // sample files 9 | var file1 = ' \ 10 | \ 11 | \ 12 | \ 13 | \ 14 | '; 15 | 16 | var file2 = ' \ 17 | \ 18 | \ 19 | \ 20 | \ 23 | \ 24 | \ 25 | \ 26 | \ 27 | \ 28 | \ 29 | \ 30 | \ 31 | \ 32 | \ 33 | \ 34 | \ 35 | '; 36 | 37 | // test 38 | describe('svg-flatten: parse function', function() { 39 | it('should successfully parse a simple svg', function() { 40 | var dom = parseFn(file1); 41 | 42 | // test root node 43 | expect(dom.name).to.be.equal('svg'); 44 | expect(dom.attr.viewBox).to.be.equal('0 0 1920.7 1133.7'); 45 | 46 | // test child nodes 47 | expect(dom.children.length).to.be.equal(1); 48 | expect(dom.children[0].name).to.be.equal('rect'); 49 | }); 50 | 51 | it('should successfully parse a complex svg', function() { 52 | var dom = parseFn(file2); 53 | 54 | // test root node 55 | expect(dom.name).to.be.equal('svg'); 56 | expect(dom.attr.viewBox).to.be.equal('0 0 1920.7 1133.7'); 57 | 58 | // test child nodes 59 | expect(dom.children.length).to.be.equal(10); 60 | expect(dom.children[0].name).to.be.equal('style'); 61 | expect(dom.children[1].name).to.be.equal('rect'); 62 | expect(dom.children[7].attr.transform).to.be.equal('translate(0, 100)'); 63 | }); 64 | 65 | it('should not fail when the source is invalid', function() { 66 | var dom = parseFn("invalid input"); 67 | 68 | // test root node 69 | expect(dom.name).to.be.equal('invalid'); 70 | expect(dom.attr.reason).not.to.be.empty; 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /test/samples/sample3_result.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | --------------------------------------------------------------------------------