├── .gitignore
├── .jshintrc
├── .nvmrc
├── .travis.yml
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── src
├── flatten.js
├── lib.js
├── parse.js
├── pathify.js
└── transform.js
└── test
├── flatten.spec.js
├── lib-samples.spec.js
├── lib.spec.js
├── parse.spec.js
├── pathify.spec.js
├── samples
├── sample1.svg
├── sample1_result.svg
├── sample2.svg
├── sample2_result.svg
├── sample3.svg
└── sample3_result.svg
└── transform.spec.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependency directories
2 | node_modules
3 | jspm_packages
4 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esversion": 6
3 | }
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 8
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "svg-flatten",
3 | "version": "1.0.1",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "assertion-error": {
8 | "version": "1.1.0",
9 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
10 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
11 | "dev": true
12 | },
13 | "available-typed-arrays": {
14 | "version": "1.0.5",
15 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
16 | "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
17 | "dev": true
18 | },
19 | "balanced-match": {
20 | "version": "1.0.2",
21 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
22 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
23 | "dev": true
24 | },
25 | "brace-expansion": {
26 | "version": "1.1.11",
27 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
28 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
29 | "dev": true,
30 | "requires": {
31 | "balanced-match": "^1.0.0",
32 | "concat-map": "0.0.1"
33 | }
34 | },
35 | "call-bind": {
36 | "version": "1.0.2",
37 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
38 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
39 | "dev": true,
40 | "requires": {
41 | "function-bind": "^1.1.1",
42 | "get-intrinsic": "^1.0.2"
43 | }
44 | },
45 | "chai": {
46 | "version": "3.5.0",
47 | "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
48 | "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=",
49 | "dev": true,
50 | "requires": {
51 | "assertion-error": "^1.0.1",
52 | "deep-eql": "^0.1.3",
53 | "type-detect": "^1.0.0"
54 | }
55 | },
56 | "cli": {
57 | "version": "1.0.1",
58 | "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz",
59 | "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=",
60 | "dev": true,
61 | "requires": {
62 | "exit": "0.1.2",
63 | "glob": "^7.1.1"
64 | },
65 | "dependencies": {
66 | "glob": {
67 | "version": "7.2.0",
68 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
69 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
70 | "dev": true,
71 | "requires": {
72 | "fs.realpath": "^1.0.0",
73 | "inflight": "^1.0.4",
74 | "inherits": "2",
75 | "minimatch": "^3.0.4",
76 | "once": "^1.3.0",
77 | "path-is-absolute": "^1.0.0"
78 | }
79 | },
80 | "minimatch": {
81 | "version": "3.1.2",
82 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
83 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
84 | "dev": true,
85 | "requires": {
86 | "brace-expansion": "^1.1.7"
87 | }
88 | }
89 | }
90 | },
91 | "commander": {
92 | "version": "2.3.0",
93 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz",
94 | "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=",
95 | "dev": true
96 | },
97 | "concat-map": {
98 | "version": "0.0.1",
99 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
100 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
101 | "dev": true
102 | },
103 | "console-browserify": {
104 | "version": "1.1.0",
105 | "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
106 | "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
107 | "dev": true,
108 | "requires": {
109 | "date-now": "^0.1.4"
110 | }
111 | },
112 | "core-util-is": {
113 | "version": "1.0.3",
114 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
115 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
116 | "dev": true
117 | },
118 | "date-now": {
119 | "version": "0.1.4",
120 | "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
121 | "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
122 | "dev": true
123 | },
124 | "debug": {
125 | "version": "2.2.0",
126 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
127 | "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
128 | "dev": true,
129 | "requires": {
130 | "ms": "0.7.1"
131 | }
132 | },
133 | "deep-eql": {
134 | "version": "0.1.3",
135 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
136 | "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
137 | "dev": true,
138 | "requires": {
139 | "type-detect": "0.1.1"
140 | },
141 | "dependencies": {
142 | "type-detect": {
143 | "version": "0.1.1",
144 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz",
145 | "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=",
146 | "dev": true
147 | }
148 | }
149 | },
150 | "define-properties": {
151 | "version": "1.1.4",
152 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
153 | "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
154 | "dev": true,
155 | "requires": {
156 | "has-property-descriptors": "^1.0.0",
157 | "object-keys": "^1.1.1"
158 | }
159 | },
160 | "diff": {
161 | "version": "1.4.0",
162 | "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz",
163 | "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=",
164 | "dev": true
165 | },
166 | "dom-serializer": {
167 | "version": "0.2.2",
168 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
169 | "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
170 | "dev": true,
171 | "requires": {
172 | "domelementtype": "^2.0.1",
173 | "entities": "^2.0.0"
174 | },
175 | "dependencies": {
176 | "domelementtype": {
177 | "version": "2.3.0",
178 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
179 | "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
180 | "dev": true
181 | },
182 | "entities": {
183 | "version": "2.2.0",
184 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
185 | "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
186 | "dev": true
187 | }
188 | }
189 | },
190 | "domelementtype": {
191 | "version": "1.3.1",
192 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
193 | "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
194 | "dev": true
195 | },
196 | "domhandler": {
197 | "version": "2.3.0",
198 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz",
199 | "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=",
200 | "dev": true,
201 | "requires": {
202 | "domelementtype": "1"
203 | }
204 | },
205 | "domutils": {
206 | "version": "1.5.1",
207 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
208 | "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
209 | "dev": true,
210 | "requires": {
211 | "dom-serializer": "0",
212 | "domelementtype": "1"
213 | }
214 | },
215 | "entities": {
216 | "version": "1.0.0",
217 | "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
218 | "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=",
219 | "dev": true
220 | },
221 | "es-abstract": {
222 | "version": "1.19.5",
223 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz",
224 | "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==",
225 | "dev": true,
226 | "requires": {
227 | "call-bind": "^1.0.2",
228 | "es-to-primitive": "^1.2.1",
229 | "function-bind": "^1.1.1",
230 | "get-intrinsic": "^1.1.1",
231 | "get-symbol-description": "^1.0.0",
232 | "has": "^1.0.3",
233 | "has-symbols": "^1.0.3",
234 | "internal-slot": "^1.0.3",
235 | "is-callable": "^1.2.4",
236 | "is-negative-zero": "^2.0.2",
237 | "is-regex": "^1.1.4",
238 | "is-shared-array-buffer": "^1.0.2",
239 | "is-string": "^1.0.7",
240 | "is-weakref": "^1.0.2",
241 | "object-inspect": "^1.12.0",
242 | "object-keys": "^1.1.1",
243 | "object.assign": "^4.1.2",
244 | "string.prototype.trimend": "^1.0.4",
245 | "string.prototype.trimstart": "^1.0.4",
246 | "unbox-primitive": "^1.0.1"
247 | }
248 | },
249 | "es-to-primitive": {
250 | "version": "1.2.1",
251 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
252 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
253 | "dev": true,
254 | "requires": {
255 | "is-callable": "^1.1.4",
256 | "is-date-object": "^1.0.1",
257 | "is-symbol": "^1.0.2"
258 | }
259 | },
260 | "escape-string-regexp": {
261 | "version": "1.0.2",
262 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz",
263 | "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=",
264 | "dev": true
265 | },
266 | "exit": {
267 | "version": "0.1.2",
268 | "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
269 | "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
270 | "dev": true
271 | },
272 | "fill-keys": {
273 | "version": "1.0.2",
274 | "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
275 | "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=",
276 | "dev": true,
277 | "requires": {
278 | "is-object": "~1.0.1",
279 | "merge-descriptors": "~1.0.0"
280 | }
281 | },
282 | "foreach": {
283 | "version": "2.0.5",
284 | "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
285 | "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
286 | "dev": true
287 | },
288 | "formatio": {
289 | "version": "1.1.1",
290 | "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz",
291 | "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=",
292 | "dev": true,
293 | "requires": {
294 | "samsam": "~1.1"
295 | }
296 | },
297 | "fs.realpath": {
298 | "version": "1.0.0",
299 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
300 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
301 | "dev": true
302 | },
303 | "function-bind": {
304 | "version": "1.1.1",
305 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
306 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
307 | "dev": true
308 | },
309 | "get-intrinsic": {
310 | "version": "1.1.1",
311 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
312 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
313 | "dev": true,
314 | "requires": {
315 | "function-bind": "^1.1.1",
316 | "has": "^1.0.3",
317 | "has-symbols": "^1.0.1"
318 | }
319 | },
320 | "get-symbol-description": {
321 | "version": "1.0.0",
322 | "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
323 | "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
324 | "dev": true,
325 | "requires": {
326 | "call-bind": "^1.0.2",
327 | "get-intrinsic": "^1.1.1"
328 | }
329 | },
330 | "glob": {
331 | "version": "3.2.11",
332 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
333 | "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
334 | "dev": true,
335 | "requires": {
336 | "inherits": "2",
337 | "minimatch": "0.3"
338 | }
339 | },
340 | "growl": {
341 | "version": "1.9.2",
342 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz",
343 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=",
344 | "dev": true
345 | },
346 | "has": {
347 | "version": "1.0.3",
348 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
349 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
350 | "dev": true,
351 | "requires": {
352 | "function-bind": "^1.1.1"
353 | }
354 | },
355 | "has-bigints": {
356 | "version": "1.0.1",
357 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
358 | "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
359 | "dev": true
360 | },
361 | "has-property-descriptors": {
362 | "version": "1.0.0",
363 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
364 | "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
365 | "dev": true,
366 | "requires": {
367 | "get-intrinsic": "^1.1.1"
368 | }
369 | },
370 | "has-symbols": {
371 | "version": "1.0.3",
372 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
373 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
374 | "dev": true
375 | },
376 | "has-tostringtag": {
377 | "version": "1.0.0",
378 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
379 | "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
380 | "dev": true,
381 | "requires": {
382 | "has-symbols": "^1.0.2"
383 | }
384 | },
385 | "htmlparser2": {
386 | "version": "3.8.3",
387 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
388 | "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
389 | "dev": true,
390 | "requires": {
391 | "domelementtype": "1",
392 | "domhandler": "2.3",
393 | "domutils": "1.5",
394 | "entities": "1.0",
395 | "readable-stream": "1.1"
396 | }
397 | },
398 | "inflight": {
399 | "version": "1.0.6",
400 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
401 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
402 | "dev": true,
403 | "requires": {
404 | "once": "^1.3.0",
405 | "wrappy": "1"
406 | }
407 | },
408 | "inherits": {
409 | "version": "2.0.4",
410 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
411 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
412 | "dev": true
413 | },
414 | "internal-slot": {
415 | "version": "1.0.3",
416 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
417 | "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
418 | "dev": true,
419 | "requires": {
420 | "get-intrinsic": "^1.1.0",
421 | "has": "^1.0.3",
422 | "side-channel": "^1.0.4"
423 | }
424 | },
425 | "is-arguments": {
426 | "version": "1.1.1",
427 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
428 | "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
429 | "dev": true,
430 | "requires": {
431 | "call-bind": "^1.0.2",
432 | "has-tostringtag": "^1.0.0"
433 | }
434 | },
435 | "is-bigint": {
436 | "version": "1.0.4",
437 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
438 | "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
439 | "dev": true,
440 | "requires": {
441 | "has-bigints": "^1.0.1"
442 | }
443 | },
444 | "is-boolean-object": {
445 | "version": "1.1.2",
446 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
447 | "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
448 | "dev": true,
449 | "requires": {
450 | "call-bind": "^1.0.2",
451 | "has-tostringtag": "^1.0.0"
452 | }
453 | },
454 | "is-callable": {
455 | "version": "1.2.4",
456 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
457 | "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
458 | "dev": true
459 | },
460 | "is-date-object": {
461 | "version": "1.0.5",
462 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
463 | "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
464 | "dev": true,
465 | "requires": {
466 | "has-tostringtag": "^1.0.0"
467 | }
468 | },
469 | "is-generator-function": {
470 | "version": "1.0.10",
471 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
472 | "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
473 | "dev": true,
474 | "requires": {
475 | "has-tostringtag": "^1.0.0"
476 | }
477 | },
478 | "is-negative-zero": {
479 | "version": "2.0.2",
480 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
481 | "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
482 | "dev": true
483 | },
484 | "is-number-object": {
485 | "version": "1.0.7",
486 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
487 | "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
488 | "dev": true,
489 | "requires": {
490 | "has-tostringtag": "^1.0.0"
491 | }
492 | },
493 | "is-object": {
494 | "version": "1.0.2",
495 | "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
496 | "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==",
497 | "dev": true
498 | },
499 | "is-regex": {
500 | "version": "1.1.4",
501 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
502 | "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
503 | "dev": true,
504 | "requires": {
505 | "call-bind": "^1.0.2",
506 | "has-tostringtag": "^1.0.0"
507 | }
508 | },
509 | "is-shared-array-buffer": {
510 | "version": "1.0.2",
511 | "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
512 | "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
513 | "dev": true,
514 | "requires": {
515 | "call-bind": "^1.0.2"
516 | }
517 | },
518 | "is-string": {
519 | "version": "1.0.7",
520 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
521 | "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
522 | "dev": true,
523 | "requires": {
524 | "has-tostringtag": "^1.0.0"
525 | }
526 | },
527 | "is-symbol": {
528 | "version": "1.0.4",
529 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
530 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
531 | "dev": true,
532 | "requires": {
533 | "has-symbols": "^1.0.2"
534 | }
535 | },
536 | "is-typed-array": {
537 | "version": "1.1.8",
538 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz",
539 | "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==",
540 | "dev": true,
541 | "requires": {
542 | "available-typed-arrays": "^1.0.5",
543 | "call-bind": "^1.0.2",
544 | "es-abstract": "^1.18.5",
545 | "foreach": "^2.0.5",
546 | "has-tostringtag": "^1.0.0"
547 | }
548 | },
549 | "is-weakref": {
550 | "version": "1.0.2",
551 | "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
552 | "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
553 | "dev": true,
554 | "requires": {
555 | "call-bind": "^1.0.2"
556 | }
557 | },
558 | "isarray": {
559 | "version": "0.0.1",
560 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
561 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
562 | "dev": true
563 | },
564 | "jade": {
565 | "version": "0.26.3",
566 | "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz",
567 | "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=",
568 | "dev": true,
569 | "requires": {
570 | "commander": "0.6.1",
571 | "mkdirp": "0.3.0"
572 | },
573 | "dependencies": {
574 | "commander": {
575 | "version": "0.6.1",
576 | "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz",
577 | "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=",
578 | "dev": true
579 | },
580 | "mkdirp": {
581 | "version": "0.3.0",
582 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
583 | "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=",
584 | "dev": true
585 | }
586 | }
587 | },
588 | "jshint": {
589 | "version": "2.13.4",
590 | "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.4.tgz",
591 | "integrity": "sha512-HO3bosL84b2qWqI0q+kpT/OpRJwo0R4ivgmxaO848+bo10rc50SkPnrtwSFXttW0ym4np8jbJvLwk5NziB7jIw==",
592 | "dev": true,
593 | "requires": {
594 | "cli": "~1.0.0",
595 | "console-browserify": "1.1.x",
596 | "exit": "0.1.x",
597 | "htmlparser2": "3.8.x",
598 | "lodash": "~4.17.21",
599 | "minimatch": "~3.0.2",
600 | "strip-json-comments": "1.0.x"
601 | },
602 | "dependencies": {
603 | "minimatch": {
604 | "version": "3.0.8",
605 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz",
606 | "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==",
607 | "dev": true,
608 | "requires": {
609 | "brace-expansion": "^1.1.7"
610 | }
611 | }
612 | }
613 | },
614 | "lodash": {
615 | "version": "4.17.21",
616 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
617 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
618 | "dev": true
619 | },
620 | "lolex": {
621 | "version": "1.3.2",
622 | "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz",
623 | "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=",
624 | "dev": true
625 | },
626 | "lru-cache": {
627 | "version": "2.7.3",
628 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
629 | "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
630 | "dev": true
631 | },
632 | "merge-descriptors": {
633 | "version": "1.0.1",
634 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
635 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
636 | "dev": true
637 | },
638 | "minimatch": {
639 | "version": "0.3.0",
640 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz",
641 | "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
642 | "dev": true,
643 | "requires": {
644 | "lru-cache": "2",
645 | "sigmund": "~1.0.0"
646 | }
647 | },
648 | "minimist": {
649 | "version": "0.0.8",
650 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
651 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
652 | "dev": true
653 | },
654 | "mkdirp": {
655 | "version": "0.5.1",
656 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
657 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
658 | "dev": true,
659 | "requires": {
660 | "minimist": "0.0.8"
661 | }
662 | },
663 | "mocha": {
664 | "version": "2.5.3",
665 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz",
666 | "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=",
667 | "dev": true,
668 | "requires": {
669 | "commander": "2.3.0",
670 | "debug": "2.2.0",
671 | "diff": "1.4.0",
672 | "escape-string-regexp": "1.0.2",
673 | "glob": "3.2.11",
674 | "growl": "1.9.2",
675 | "jade": "0.26.3",
676 | "mkdirp": "0.5.1",
677 | "supports-color": "1.2.0",
678 | "to-iso-string": "0.0.2"
679 | }
680 | },
681 | "module-not-found-error": {
682 | "version": "1.0.1",
683 | "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz",
684 | "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=",
685 | "dev": true
686 | },
687 | "ms": {
688 | "version": "0.7.1",
689 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
690 | "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
691 | "dev": true
692 | },
693 | "object-inspect": {
694 | "version": "1.12.0",
695 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
696 | "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
697 | "dev": true
698 | },
699 | "object-keys": {
700 | "version": "1.1.1",
701 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
702 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
703 | "dev": true
704 | },
705 | "object.assign": {
706 | "version": "4.1.2",
707 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
708 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
709 | "dev": true,
710 | "requires": {
711 | "call-bind": "^1.0.0",
712 | "define-properties": "^1.1.3",
713 | "has-symbols": "^1.0.1",
714 | "object-keys": "^1.1.1"
715 | }
716 | },
717 | "once": {
718 | "version": "1.4.0",
719 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
720 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
721 | "dev": true,
722 | "requires": {
723 | "wrappy": "1"
724 | }
725 | },
726 | "path-is-absolute": {
727 | "version": "1.0.1",
728 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
729 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
730 | "dev": true
731 | },
732 | "proxyquire": {
733 | "version": "1.8.0",
734 | "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-1.8.0.tgz",
735 | "integrity": "sha1-AtUUpb7ZhvBMuyCTrxZ0FTX3ntw=",
736 | "dev": true,
737 | "requires": {
738 | "fill-keys": "^1.0.2",
739 | "module-not-found-error": "^1.0.0",
740 | "resolve": "~1.1.7"
741 | }
742 | },
743 | "readable-stream": {
744 | "version": "1.1.14",
745 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
746 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
747 | "dev": true,
748 | "requires": {
749 | "core-util-is": "~1.0.0",
750 | "inherits": "~2.0.1",
751 | "isarray": "0.0.1",
752 | "string_decoder": "~0.10.x"
753 | }
754 | },
755 | "resolve": {
756 | "version": "1.1.7",
757 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
758 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
759 | "dev": true
760 | },
761 | "safe-buffer": {
762 | "version": "5.2.1",
763 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
764 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
765 | "dev": true
766 | },
767 | "samsam": {
768 | "version": "1.1.2",
769 | "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz",
770 | "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=",
771 | "dev": true
772 | },
773 | "sax": {
774 | "version": "1.1.6",
775 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.6.tgz",
776 | "integrity": "sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA="
777 | },
778 | "side-channel": {
779 | "version": "1.0.4",
780 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
781 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
782 | "dev": true,
783 | "requires": {
784 | "call-bind": "^1.0.0",
785 | "get-intrinsic": "^1.0.2",
786 | "object-inspect": "^1.9.0"
787 | }
788 | },
789 | "sigmund": {
790 | "version": "1.0.1",
791 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
792 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
793 | "dev": true
794 | },
795 | "sinon": {
796 | "version": "1.17.7",
797 | "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz",
798 | "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=",
799 | "dev": true,
800 | "requires": {
801 | "formatio": "1.1.1",
802 | "lolex": "1.3.2",
803 | "samsam": "1.1.2",
804 | "util": ">=0.10.3 <1"
805 | }
806 | },
807 | "string.prototype.trimend": {
808 | "version": "1.0.4",
809 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
810 | "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
811 | "dev": true,
812 | "requires": {
813 | "call-bind": "^1.0.2",
814 | "define-properties": "^1.1.3"
815 | }
816 | },
817 | "string.prototype.trimstart": {
818 | "version": "1.0.4",
819 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
820 | "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
821 | "dev": true,
822 | "requires": {
823 | "call-bind": "^1.0.2",
824 | "define-properties": "^1.1.3"
825 | }
826 | },
827 | "string_decoder": {
828 | "version": "0.10.31",
829 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
830 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
831 | "dev": true
832 | },
833 | "strip-json-comments": {
834 | "version": "1.0.4",
835 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
836 | "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=",
837 | "dev": true
838 | },
839 | "supports-color": {
840 | "version": "1.2.0",
841 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz",
842 | "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=",
843 | "dev": true
844 | },
845 | "svgpath": {
846 | "version": "2.5.0",
847 | "resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.5.0.tgz",
848 | "integrity": "sha512-o/vohwqjUO9nDAh4rcjE3KaW/v//At8UJu2LJMybXidf5QLQLVA4bxH0//4YCsr+1H4Gw1Wi/Jc62ynzSBYidw=="
849 | },
850 | "to-iso-string": {
851 | "version": "0.0.2",
852 | "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz",
853 | "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=",
854 | "dev": true
855 | },
856 | "type-detect": {
857 | "version": "1.0.0",
858 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz",
859 | "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=",
860 | "dev": true
861 | },
862 | "unbox-primitive": {
863 | "version": "1.0.1",
864 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
865 | "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
866 | "dev": true,
867 | "requires": {
868 | "function-bind": "^1.1.1",
869 | "has-bigints": "^1.0.1",
870 | "has-symbols": "^1.0.2",
871 | "which-boxed-primitive": "^1.0.2"
872 | }
873 | },
874 | "util": {
875 | "version": "0.12.4",
876 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz",
877 | "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==",
878 | "dev": true,
879 | "requires": {
880 | "inherits": "^2.0.3",
881 | "is-arguments": "^1.0.4",
882 | "is-generator-function": "^1.0.7",
883 | "is-typed-array": "^1.1.3",
884 | "safe-buffer": "^5.1.2",
885 | "which-typed-array": "^1.1.2"
886 | }
887 | },
888 | "which-boxed-primitive": {
889 | "version": "1.0.2",
890 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
891 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
892 | "dev": true,
893 | "requires": {
894 | "is-bigint": "^1.0.1",
895 | "is-boolean-object": "^1.1.0",
896 | "is-number-object": "^1.0.4",
897 | "is-string": "^1.0.5",
898 | "is-symbol": "^1.0.3"
899 | }
900 | },
901 | "which-typed-array": {
902 | "version": "1.1.7",
903 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz",
904 | "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==",
905 | "dev": true,
906 | "requires": {
907 | "available-typed-arrays": "^1.0.5",
908 | "call-bind": "^1.0.2",
909 | "es-abstract": "^1.18.5",
910 | "foreach": "^2.0.5",
911 | "has-tostringtag": "^1.0.0",
912 | "is-typed-array": "^1.1.7"
913 | }
914 | },
915 | "wrappy": {
916 | "version": "1.0.2",
917 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
918 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
919 | "dev": true
920 | },
921 | "xmldoc": {
922 | "version": "0.5.1",
923 | "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-0.5.1.tgz",
924 | "integrity": "sha1-kuQ36QDb/wRFDvrpDTyl8WVl9zg=",
925 | "requires": {
926 | "sax": "~1.1.1"
927 | }
928 | }
929 | }
930 | }
931 |
--------------------------------------------------------------------------------
/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/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;
--------------------------------------------------------------------------------
/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/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 | };
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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;
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 | ';
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/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 | ';
15 |
16 | var file2 = ' \
17 | \
18 | \
19 | ';
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/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/samples/sample1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
--------------------------------------------------------------------------------
/test/samples/sample1_result.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/test/samples/sample2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/test/samples/sample2_result.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/test/samples/sample3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
62 |
--------------------------------------------------------------------------------
/test/samples/sample3_result.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------