├── .gitignore ├── tests ├── test-svgs │ ├── translate-2-integers.svg │ ├── non-path-elements.svg │ └── multipath.svg ├── qunit-test.html ├── comparison-tests.html └── qunit-tests.js ├── test.css ├── README.md ├── LICENSE ├── scripts ├── SVG-data.js ├── interface.js ├── SVG-elements.js ├── optimise-functions.js └── optimiseSVG.js └── test.html /.gitignore: -------------------------------------------------------------------------------- 1 | examples 2 | lib 3 | 4 | *.DS_Store 5 | -------------------------------------------------------------------------------- /tests/test-svgs/translate-2-integers.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test.css: -------------------------------------------------------------------------------- 1 | #optimise-container > div { 2 | display: inline-block; 3 | background: #e8e8e8; 4 | margin: 5px; 5 | padding: 5px; 6 | } 7 | 8 | #input-svg { 9 | width:800px; 10 | height:200px; 11 | border: 1px solid #888; 12 | } 13 | 14 | #options-container { 15 | -webkit-columns: 300px 3; 16 | -moz-columns: 300px 3; 17 | columns: 300px 3; 18 | } 19 | 20 | #output-container { 21 | white-space: pre-wrap; 22 | font-family: Fixed, 'Courier New', monospace; 23 | font-size: 12px; 24 | } -------------------------------------------------------------------------------- /tests/test-svgs/non-path-elements.svg: -------------------------------------------------------------------------------- 1 | 2 | SVG with a path contain each of the possible path commands. 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/test-svgs/multipath.svg: -------------------------------------------------------------------------------- 1 | 2 | SVG with a path contain each of the possible path commands. 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/qunit-test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | QUnit Tests for svg-optimiser.js 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SVG-optimiser.js 2 | ================ 3 | 4 | An online SVG optimiser using Javascript and jQuery 5 | 6 | ##Using optimise-functions.js and SVG-elements.js 7 | 8 | ###Create an SVG_Root object 9 | The `SVG_Root` object is what parses the SVG and allows you to access the optimisation functions. You can pass it either a complete SVG or an SVG element (which can have child elements). 10 | 11 | You can pass it a string with: 12 | `var SVGObject = SVG_Root('');` 13 | 14 | Or a JQuery object with: 15 | `var SVGObject = SVG_Root($('#my-svg'));` 16 | 17 | ###Optimise the SVG 18 | Optimisation is done with: `svg.optimise();` 19 | 20 | There are many options which I will have to write about at some point. 21 | 22 | ###Write the SVG 23 | You can get the SVG as a string with: 24 | `SVGObject.write();` 25 | 26 | Or as a DOM element with: 27 | `SVGObject.createSVGObject();` 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Peter Collingridge 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /scripts/SVG-data.js: -------------------------------------------------------------------------------- 1 | // Information about SVGs 2 | 3 | // We can remove any style given a default value 4 | var defaultStyles = { 5 | 'clip': 'auto', 6 | 'clip-path': 'none', 7 | 'clip-rule': 'nonzero', 8 | 'cursor': 'auto', 9 | 'display': 'inline', 10 | 'visibility': 'visible', 11 | 'opacity': '1', 12 | 'enable-background': 'accumulate', 13 | 'fill': '#000', 14 | 'fill-opacity': 1, 15 | 'fill-rule': 'nonzero', 16 | 'marker': 'none', 17 | 'marker-start': 'none', 18 | 'marker-mid': 'none', 19 | 'marker-end': 'none', 20 | 'stroke': 'none', 21 | 'stroke-width': 1, 22 | 'stroke-opacity': 1, 23 | 'stroke-miterlimit': 4, 24 | 'stroke-linecap': 'butt', 25 | 'stroke-linejoin': 'miter', 26 | 'stroke-dasharray': 'none', 27 | 'stroke-dashoffset': 0, 28 | 'stop-opacity': 1, 29 | 'font-anchor': 'start', 30 | 'font-style': 'normal', 31 | 'font-weight': 'normal', 32 | 'font-stretch': 'normal', 33 | 'font-variant': 'normal', 34 | 'text-anchor': 'start', 35 | 'writing-mode': 'lr-tb', 36 | 'pointer-events': 'visiblePainted' 37 | }; 38 | 39 | // Attributes that can probably be removed 40 | var nonEssentialStyles = { 41 | 'color' : true, 42 | 'display' : true, 43 | 'overflow' : true, 44 | 'fill-rule' : true, 45 | 'clip-rule' : true, 46 | 'nodetypes' : true, 47 | 'stroke-miterlimit' : true, 48 | 'enable-background': true, 49 | 'baseProfile': true, 50 | 'version': true 51 | }; 52 | 53 | // Attributes that are required otherwise no shape is drawn 54 | var essentialAttributes = { 55 | 'path': ['d'], 56 | 'polygon': ['points'], 57 | 'polyline': ['points'], 58 | 'rect': ['width', 'height'], 59 | 'circle': ['r'], 60 | 'ellipse': ['r'], 61 | }; 62 | 63 | // Attribute which determine the size or position of elements 64 | // The default value of these is 0 65 | var positionAttributes = [ 66 | 'x', 'y', 'width', 'height', 'rx', 'ry', 67 | 'cx', 'cy', 'r', 68 | 'x1', 'x2', 'y1', 'y2' 69 | ]; -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SVG optimisation 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

SVG optimiser

16 | 17 |
18 |

Upload

19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 |
30 |
31 | 32 |
33 |

Optimise

34 |
35 |
36 |
37 |
38 |

Original

39 |
40 |
41 |
42 |
43 |
44 |
45 |

Optimised

46 |
47 |
48 |
49 |
50 |

Options

51 |
52 |
53 | 54 |
55 |

Output

56 |
57 |
58 | 59 | -------------------------------------------------------------------------------- /scripts/interface.js: -------------------------------------------------------------------------------- 1 | // http://stackoverflow.com/questions/6507293/convert-xml-to-string-with-jquery 2 | function xmlToString(xmlData) { 3 | var xmlString; 4 | if (window.ActiveXObject){ 5 | // IE 6 | xmlString = xmlData.xml; 7 | } else { 8 | // Mozilla, Firefox, Opera, etc. 9 | xmlString = (new XMLSerializer()).serializeToString(xmlData); 10 | } 11 | return xmlString; 12 | } 13 | 14 | // Parse an SVG string as XML 15 | function stringToXML(svgString) { 16 | // Replace any leading whitespace which will mess up XML parsing 17 | svgString = svgString.replace(/^[\s\n]*/, ""); 18 | 19 | if (!svgString) { return; } 20 | 21 | // Parse SVG as XML 22 | var svgDoc; 23 | try { 24 | svgDoc = $.parseXML(svgString); 25 | } catch (err) { 26 | alert("Unable to parse SVG"); 27 | } 28 | 29 | return svgDoc; 30 | } 31 | 32 | // Get an SVG from the server and add a string version to textarea 33 | // Quite inefficient as we're going to convert it back to a XML object later. 34 | function getExampleSVG(filename) { 35 | $.get("examples/" + filename + ".svg", function(data) { 36 | $("#input-svg").val(xmlToString(data)); 37 | }); 38 | } 39 | 40 | // Convert string into filesize 41 | function getFileSize(str) { 42 | var size = str.length / 1000; 43 | if (size > 1000) { 44 | return (Math.round(size / 100) / 10) + " MB"; 45 | } else { 46 | return (Math.round(size * 10) / 10) + " kB"; 47 | } 48 | } 49 | 50 | // Clear element with given selector and add contents 51 | function addContentsToDiv(contents, selector) { 52 | var div = $(selector); 53 | 54 | if (div.length === 1) { 55 | div.empty(); 56 | div.append(contents); 57 | } 58 | } 59 | 60 | function addSVGStats(selector, filesize, numElements) { 61 | var div = $(selector); 62 | if (div.length === 1) { 63 | div.empty(); 64 | var ul = $('