@tomasvn/svgstore 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.editorconfig ADDED
@@ -0,0 +1,16 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_size = 4
7
+ indent_style = tab
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.json]
12
+ indent_size = 2
13
+ indent_style = space
14
+
15
+ [*.md]
16
+ indent_style = space
package/.gitattributes ADDED
@@ -0,0 +1 @@
1
+ * text=auto
@@ -0,0 +1,26 @@
1
+ name: CI
2
+ on:
3
+ - push
4
+ - pull_request
5
+ jobs:
6
+ test:
7
+ name: Node.js ${{ matrix.node-version }} on ${{ matrix.os }}
8
+ runs-on: ${{ matrix.os }}
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ node-version:
13
+ - 16
14
+ - 14
15
+ - 12
16
+ os:
17
+ - ubuntu-latest
18
+ - macos-latest
19
+ - windows-latest
20
+ steps:
21
+ - uses: actions/checkout@v2
22
+ - uses: actions/setup-node@v2
23
+ with:
24
+ node-version: ${{ matrix.node-version }}
25
+ - run: npm install
26
+ - run: npm test
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
6
+ <g>
7
+ <g>
8
+ <path fill="#FF6666" d="M62,6.503V2C35.034,2,13.172,23.776,13.172,50.638h4.521C17.692,26.264,37.532,6.503,62,6.503z"/>
9
+ <path fill="#FFFB80" d="M17.692,50.638h4.521c0-21.884,17.814-39.631,39.786-39.631V6.503
10
+ C37.532,6.503,17.692,26.264,17.692,50.638z"/>
11
+ <path fill="#A3E66F" d="M62,15.51v-4.503c-21.972,0-39.786,17.747-39.786,39.631h4.521C26.735,31.238,42.525,15.51,62,15.51z"/>
12
+ <path fill="#66C2FF" d="M26.735,50.638h4.521c0-16.911,13.766-30.624,30.743-30.624V15.51
13
+ C42.525,15.51,26.735,31.238,26.735,50.638z"/>
14
+ <path fill="#9180FF" d="M62,24.518v-4.504c-16.978,0-30.743,13.713-30.743,30.624h4.521C35.777,36.212,47.52,24.518,62,24.518z"/>
15
+ </g>
16
+ <g>
17
+ <path fill="#FFFFFF" d="M10.137,60.652c-0.724,0-1.44-0.116-2.129-0.344c-2.781-0.913-4.651-3.484-4.651-6.398
18
+ c0-1.946,0.848-3.796,2.326-5.078c0.382-0.332,0.796-0.619,1.24-0.856L6.9,47.975l0.45-1.56c1.123-3.894,4.75-6.613,8.819-6.613
19
+ c0.405,0,0.821,0.032,1.311,0.103c0.375,0.054,0.742,0.13,1.102,0.226l0.18-0.323c1.644-2.945,4.766-4.775,8.146-4.775
20
+ c5.135,0,9.312,4.154,9.312,9.261c0,0.25-0.017,0.492-0.036,0.736l-0.015,0.182c0.396,0.15,0.782,0.332,1.155,0.547
21
+ c2.482,1.422,4.025,4.072,4.025,6.912c0,3.74-2.56,6.938-6.225,7.774c-0.598,0.138-1.205,0.209-1.801,0.209H10.137z"/>
22
+ <path fill="#75D6FF" d="M26.907,36.38c4.394,0,7.955,3.544,7.955,7.912c0,0.213-0.015,0.42-0.032,0.627
23
+ c-1.839,0.141-3.509,0.869-4.821,2.002c0.977-0.558,2.105-0.882,3.313-0.882c0.447,0,0.884,0.045,1.306,0.128
24
+ c0.723,0.143,1.4,0.403,2.017,0.757c1.999,1.146,3.347,3.286,3.347,5.745c0,3.149-2.209,5.784-5.17,6.461
25
+ c-0.482,0.11-0.982,0.174-1.498,0.174c0,0,0,0-0.001,0H10.137l0,0c-0.595,0-1.165-0.099-1.7-0.274
26
+ c-2.162-0.711-3.723-2.733-3.723-5.119c0-1.623,0.722-3.074,1.861-4.062c0.516-0.45,1.117-0.8,1.776-1.029
27
+ c0.56-0.193,1.159-0.306,1.786-0.306c1.749,0,3.299,0.826,4.292,2.105l0.048-0.001c-1.151-2.108-3.304-3.595-5.823-3.833
28
+ c0.937-3.25,3.944-5.635,7.514-5.635c0.382,0,0.752,0.036,1.118,0.089c0.725,0.104,1.417,0.302,2.063,0.588
29
+ c2.405,1.068,4.163,3.305,4.555,5.984c0-0.014,0-0.031,0-0.046c0-3.052-1.573-5.738-3.957-7.305
30
+ C21.306,38.03,23.912,36.38,26.907,36.38 M26.907,33.684c-3.658,0-7.053,1.869-9.004,4.92c-0.075-0.011-0.151-0.022-0.227-0.035
31
+ c-0.559-0.078-1.036-0.114-1.507-0.114c-4.671,0-8.834,3.12-10.123,7.589l-0.307,1.063c-0.333,0.212-0.651,0.451-0.952,0.712
32
+ C3.017,49.354,2,51.575,2,53.91c0,3.497,2.245,6.582,5.585,7.679C8.407,61.862,9.268,62,10.137,62h23.185
33
+ c0.7,0,1.41-0.081,2.112-0.244c4.278-0.977,7.271-4.715,7.271-9.087c0-3.321-1.804-6.418-4.706-8.081
34
+ c-0.14-0.08-0.281-0.156-0.425-0.229c0-0.022,0-0.044,0-0.066C37.575,38.442,32.79,33.684,26.907,33.684L26.907,33.684z"/>
35
+ </g>
36
+ </g>
37
+ </svg>
@@ -0,0 +1,77 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
6
+ <g>
7
+ <g>
8
+ <g>
9
+ <path fill="#E5BE7A" d="M12.645,19.666C12,12.56,16.381,11.69,18.766,12.197c2.385,0.506,4.349,6.39,1.712,13.026
10
+ c-3.631,9.127-10.542,10.65-10.542,10.65S13.489,28.984,12.645,19.666z"/>
11
+ <path fill="#E5BE7A" d="M14.893,27.481c-0.645-7.105,3.736-7.976,6.121-7.469c2.385,0.506,4.35,6.391,1.712,13.027
12
+ C19.095,42.167,9.553,44.716,9.553,44.716S15.737,36.799,14.893,27.481z"/>
13
+ <path fill="#E5BE7A" d="M16.481,37.437c-0.644-7.105,3.736-7.975,6.123-7.468c2.385,0.507,4.347,6.39,1.709,13.027
14
+ C20.685,52.124,8.658,55.69,8.658,55.69S17.325,46.755,16.481,37.437z"/>
15
+ </g>
16
+ <g>
17
+ <path fill="#E5BE7A" d="M53.813,19.893c-1.36-7.006-6.227-8.203-8.611-7.696c-2.383,0.506-4.347,6.39-1.71,13.026
18
+ c3.629,9.127,4.065,15.049,4.065,15.049S55.979,31.065,53.813,19.893z"/>
19
+ </g>
20
+ </g>
21
+ <g>
22
+ <g>
23
+ <path fill="#C1875D" d="M57.98,2.01c0.16,5.134-0.616,9.349-2.302,11.872c-2.545,1.584-6.93,2.396-12.362,2.276
24
+ c-0.159-5.134,0.614-9.352,2.302-11.874C48.164,2.701,52.548,1.888,57.98,2.01z"/>
25
+ </g>
26
+ <g>
27
+ <path fill="#3E4347" d="M54.746,5.131c0.091,2.867-0.344,5.224-1.285,6.635c-1.423,0.887-3.876,1.339-6.912,1.272
28
+ c-0.088-2.87,0.346-5.226,1.287-6.637C49.263,5.514,51.711,5.062,54.746,5.131z"/>
29
+ </g>
30
+ </g>
31
+ <g>
32
+ <g>
33
+ <path fill="#C1875D" d="M20.817,16.152c-5.371,0.151-9.783-0.59-12.423-2.201c-1.66-2.435-2.507-6.623-2.379-11.815
34
+ c5.369-0.151,9.777,0.586,12.417,2.198C20.094,6.773,20.94,10.958,20.817,16.152z"/>
35
+ </g>
36
+ <g>
37
+ <path fill="#3E4347" d="M17.583,13.092c-3.023,0.084-5.509-0.331-6.997-1.24C9.649,10.48,9.173,8.121,9.243,5.193
38
+ c3.028-0.087,5.511,0.33,6.998,1.239C17.176,7.807,17.659,10.167,17.583,13.092z"/>
39
+ </g>
40
+ </g>
41
+ <g>
42
+ <path fill="#C1875D" d="M48.585,28.956c0,3.673-4.128,16.411-4.128,21.752c0,0-5.146,0.514-12.477,0.514
43
+ c-7.188,0-12.299-0.246-12.299-0.246c0-5.477-4.304-18.336-4.304-22.02c0-4.886-0.53-10.083,4.589-16.834
44
+ c1.201-1.585,1.538-3.644,12.014-3.644c10.39,0,11.147,1.664,12.233,3.014C49.226,17.707,48.585,22.492,48.585,28.956z"/>
45
+ </g>
46
+ <g>
47
+ <path fill="#FFE2B3" d="M44.771,54.88c0,4.885-2.998,7.119-12.787,7.119c-9.792,0-12.788-2.234-12.788-7.119
48
+ c0-4.887,0.271-10.57,12.788-10.57C44.502,44.31,44.771,49.993,44.771,54.88z"/>
49
+ </g>
50
+ <g>
51
+ <g>
52
+ <path fill="#3E4347" d="M48.98,26.744c0,2.209-1.458,4-3.25,4c-1.797,0-3.25-1.791-3.25-4s1.453-4,3.25-4
53
+ C47.522,22.744,48.98,24.534,48.98,26.744z"/>
54
+ </g>
55
+ </g>
56
+ <g>
57
+ <g>
58
+ <ellipse fill="#3E4347" cx="18.231" cy="26.744" rx="3.25" ry="4"/>
59
+ </g>
60
+ </g>
61
+ <path fill="#FFE2B3" d="M40.549,43.339c-2.143-1.385-5.175,1.119-6.774,5.592c-1.6,4.482-1.155,9.236,0.993,10.621
62
+ c2.146,1.391,5.181-1.113,6.774-5.59C43.137,49.485,42.693,44.728,40.549,43.339z"/>
63
+ <path fill="#FFE2B3" d="M23.42,43.339c-2.146,1.393-2.591,6.146-0.992,10.625c1.597,4.475,4.629,6.979,6.774,5.59
64
+ c2.144-1.387,2.589-6.141,0.989-10.619C28.601,44.458,25.566,41.952,23.42,43.339z"/>
65
+ <path fill="#FFFFFF" d="M27.57,19.22c0-8.426,1.976-10.126,4.415-10.126c2.439,0,4.414,1.7,4.414,10.126
66
+ c0,8.428-4.414,20.39-4.414,20.39S27.57,27.648,27.57,19.22z"/>
67
+ <g>
68
+ <path fill="#3E4347" d="M39.776,45.974c-1.57-1.016-3.79,0.82-4.964,4.098c-1.173,3.281-0.844,6.766,0.729,7.781
69
+ c1.573,1.02,3.796-0.816,4.965-4.096C41.674,50.476,41.349,46.991,39.776,45.974z"/>
70
+ <path fill="#3E4347" d="M24.196,45.974c-1.573,1.02-1.9,4.502-0.729,7.783c1.169,3.279,3.391,5.115,4.963,4.096
71
+ c1.57-1.016,1.896-4.5,0.726-7.779C27.987,46.794,25.766,44.958,24.196,45.974z"/>
72
+ </g>
73
+ <path fill="#E5BE7A" d="M45.73,9.555C38.439-0.789,9.623,2.571,9.623,26.513c0,0,6.883-8.836,18.46-11.407
74
+ c0,0-4.606,5.271-10.041,9.45c0,0,11.297-2.86,18.275-9.357c0,0,0.815,4.672-8.524,7.768C27.792,22.966,54.687,22.269,45.73,9.555z
75
+ "/>
76
+ </g>
77
+ </svg>
@@ -0,0 +1,43 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+
5
+ <meta charset="utf-8" />
6
+ <title>Example</title>
7
+ <style>
8
+ body {
9
+ font-family: sans-serif;
10
+ padding: 12%;
11
+ text-align: center;
12
+ }
13
+ svg, img {
14
+ display: inline-block;
15
+ height: 12em;
16
+ width: 12em;
17
+ }
18
+ </style>
19
+
20
+ <!--
21
+ ! IE and Safari need a little bit of help.
22
+ ! https://jonathantneal.github.io/svg4everybody/
23
+ !-->
24
+ <meta http-equiv="x-ua-compatible" content="ie=edge" />
25
+ <script src="./vendor/svg4everybody.js"></script>
26
+ <script>svg4everybody();</script>
27
+
28
+ </head>
29
+ <body>
30
+ <svg role="img">
31
+ <use href="./sprites.svg#unicorn" />
32
+ </svg>
33
+ <svg role="img">
34
+ <use href="./sprites.svg#rainbow" />
35
+ </svg>
36
+ <br>
37
+ <img src="./sprites.svg#view-unicorn">
38
+ <img src="./sprites.svg#view-rainbow">
39
+
40
+ <p><small>Icons by <a href="http://emojione.com/">Emoji One</a></small></p>
41
+
42
+ </body>
43
+ </html>
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ var svgstore = require('../../src/svgstore');
4
+ var fs = require('fs');
5
+
6
+ var sprites = svgstore({ fragmentIdentifier: (id) => `view-${id}` })
7
+ .add('unicorn', fs.readFileSync('./assets/unicorn.svg', 'utf8'))
8
+ .add('rainbow', fs.readFileSync('./assets/rainbow.svg', 'utf8'));
9
+
10
+ fs.writeFileSync('./sprites.svg', sprites.toString());
@@ -0,0 +1,105 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs/><symbol id="unicorn" viewBox="0 0 64 64">
2
+ <g>
3
+ <g>
4
+ <g>
5
+ <path fill="#E5BE7A" d="M12.645,19.666C12,12.56,16.381,11.69,18.766,12.197c2.385,0.506,4.349,6.39,1.712,13.026
6
+ c-3.631,9.127-10.542,10.65-10.542,10.65S13.489,28.984,12.645,19.666z"/>
7
+ <path fill="#E5BE7A" d="M14.893,27.481c-0.645-7.105,3.736-7.976,6.121-7.469c2.385,0.506,4.35,6.391,1.712,13.027
8
+ C19.095,42.167,9.553,44.716,9.553,44.716S15.737,36.799,14.893,27.481z"/>
9
+ <path fill="#E5BE7A" d="M16.481,37.437c-0.644-7.105,3.736-7.975,6.123-7.468c2.385,0.507,4.347,6.39,1.709,13.027
10
+ C20.685,52.124,8.658,55.69,8.658,55.69S17.325,46.755,16.481,37.437z"/>
11
+ </g>
12
+ <g>
13
+ <path fill="#E5BE7A" d="M53.813,19.893c-1.36-7.006-6.227-8.203-8.611-7.696c-2.383,0.506-4.347,6.39-1.71,13.026
14
+ c3.629,9.127,4.065,15.049,4.065,15.049S55.979,31.065,53.813,19.893z"/>
15
+ </g>
16
+ </g>
17
+ <g>
18
+ <g>
19
+ <path fill="#C1875D" d="M57.98,2.01c0.16,5.134-0.616,9.349-2.302,11.872c-2.545,1.584-6.93,2.396-12.362,2.276
20
+ c-0.159-5.134,0.614-9.352,2.302-11.874C48.164,2.701,52.548,1.888,57.98,2.01z"/>
21
+ </g>
22
+ <g>
23
+ <path fill="#3E4347" d="M54.746,5.131c0.091,2.867-0.344,5.224-1.285,6.635c-1.423,0.887-3.876,1.339-6.912,1.272
24
+ c-0.088-2.87,0.346-5.226,1.287-6.637C49.263,5.514,51.711,5.062,54.746,5.131z"/>
25
+ </g>
26
+ </g>
27
+ <g>
28
+ <g>
29
+ <path fill="#C1875D" d="M20.817,16.152c-5.371,0.151-9.783-0.59-12.423-2.201c-1.66-2.435-2.507-6.623-2.379-11.815
30
+ c5.369-0.151,9.777,0.586,12.417,2.198C20.094,6.773,20.94,10.958,20.817,16.152z"/>
31
+ </g>
32
+ <g>
33
+ <path fill="#3E4347" d="M17.583,13.092c-3.023,0.084-5.509-0.331-6.997-1.24C9.649,10.48,9.173,8.121,9.243,5.193
34
+ c3.028-0.087,5.511,0.33,6.998,1.239C17.176,7.807,17.659,10.167,17.583,13.092z"/>
35
+ </g>
36
+ </g>
37
+ <g>
38
+ <path fill="#C1875D" d="M48.585,28.956c0,3.673-4.128,16.411-4.128,21.752c0,0-5.146,0.514-12.477,0.514
39
+ c-7.188,0-12.299-0.246-12.299-0.246c0-5.477-4.304-18.336-4.304-22.02c0-4.886-0.53-10.083,4.589-16.834
40
+ c1.201-1.585,1.538-3.644,12.014-3.644c10.39,0,11.147,1.664,12.233,3.014C49.226,17.707,48.585,22.492,48.585,28.956z"/>
41
+ </g>
42
+ <g>
43
+ <path fill="#FFE2B3" d="M44.771,54.88c0,4.885-2.998,7.119-12.787,7.119c-9.792,0-12.788-2.234-12.788-7.119
44
+ c0-4.887,0.271-10.57,12.788-10.57C44.502,44.31,44.771,49.993,44.771,54.88z"/>
45
+ </g>
46
+ <g>
47
+ <g>
48
+ <path fill="#3E4347" d="M48.98,26.744c0,2.209-1.458,4-3.25,4c-1.797,0-3.25-1.791-3.25-4s1.453-4,3.25-4
49
+ C47.522,22.744,48.98,24.534,48.98,26.744z"/>
50
+ </g>
51
+ </g>
52
+ <g>
53
+ <g>
54
+ <ellipse fill="#3E4347" cx="18.231" cy="26.744" rx="3.25" ry="4"/>
55
+ </g>
56
+ </g>
57
+ <path fill="#FFE2B3" d="M40.549,43.339c-2.143-1.385-5.175,1.119-6.774,5.592c-1.6,4.482-1.155,9.236,0.993,10.621
58
+ c2.146,1.391,5.181-1.113,6.774-5.59C43.137,49.485,42.693,44.728,40.549,43.339z"/>
59
+ <path fill="#FFE2B3" d="M23.42,43.339c-2.146,1.393-2.591,6.146-0.992,10.625c1.597,4.475,4.629,6.979,6.774,5.59
60
+ c2.144-1.387,2.589-6.141,0.989-10.619C28.601,44.458,25.566,41.952,23.42,43.339z"/>
61
+ <path fill="#FFFFFF" d="M27.57,19.22c0-8.426,1.976-10.126,4.415-10.126c2.439,0,4.414,1.7,4.414,10.126
62
+ c0,8.428-4.414,20.39-4.414,20.39S27.57,27.648,27.57,19.22z"/>
63
+ <g>
64
+ <path fill="#3E4347" d="M39.776,45.974c-1.57-1.016-3.79,0.82-4.964,4.098c-1.173,3.281-0.844,6.766,0.729,7.781
65
+ c1.573,1.02,3.796-0.816,4.965-4.096C41.674,50.476,41.349,46.991,39.776,45.974z"/>
66
+ <path fill="#3E4347" d="M24.196,45.974c-1.573,1.02-1.9,4.502-0.729,7.783c1.169,3.279,3.391,5.115,4.963,4.096
67
+ c1.57-1.016,1.896-4.5,0.726-7.779C27.987,46.794,25.766,44.958,24.196,45.974z"/>
68
+ </g>
69
+ <path fill="#E5BE7A" d="M45.73,9.555C38.439-0.789,9.623,2.571,9.623,26.513c0,0,6.883-8.836,18.46-11.407
70
+ c0,0-4.606,5.271-10.041,9.45c0,0,11.297-2.86,18.275-9.357c0,0,0.815,4.672-8.524,7.768C27.792,22.966,54.687,22.269,45.73,9.555z
71
+ "/>
72
+ </g>
73
+ </symbol><view id="view-unicorn" viewBox="0 0 64 64"/><use xlink:href="#unicorn" width="64" height="64" x="0" y="0"/><symbol id="rainbow" viewBox="0 0 64 64">
74
+ <g>
75
+ <g>
76
+ <path fill="#FF6666" d="M62,6.503V2C35.034,2,13.172,23.776,13.172,50.638h4.521C17.692,26.264,37.532,6.503,62,6.503z"/>
77
+ <path fill="#FFFB80" d="M17.692,50.638h4.521c0-21.884,17.814-39.631,39.786-39.631V6.503
78
+ C37.532,6.503,17.692,26.264,17.692,50.638z"/>
79
+ <path fill="#A3E66F" d="M62,15.51v-4.503c-21.972,0-39.786,17.747-39.786,39.631h4.521C26.735,31.238,42.525,15.51,62,15.51z"/>
80
+ <path fill="#66C2FF" d="M26.735,50.638h4.521c0-16.911,13.766-30.624,30.743-30.624V15.51
81
+ C42.525,15.51,26.735,31.238,26.735,50.638z"/>
82
+ <path fill="#9180FF" d="M62,24.518v-4.504c-16.978,0-30.743,13.713-30.743,30.624h4.521C35.777,36.212,47.52,24.518,62,24.518z"/>
83
+ </g>
84
+ <g>
85
+ <path fill="#FFFFFF" d="M10.137,60.652c-0.724,0-1.44-0.116-2.129-0.344c-2.781-0.913-4.651-3.484-4.651-6.398
86
+ c0-1.946,0.848-3.796,2.326-5.078c0.382-0.332,0.796-0.619,1.24-0.856L6.9,47.975l0.45-1.56c1.123-3.894,4.75-6.613,8.819-6.613
87
+ c0.405,0,0.821,0.032,1.311,0.103c0.375,0.054,0.742,0.13,1.102,0.226l0.18-0.323c1.644-2.945,4.766-4.775,8.146-4.775
88
+ c5.135,0,9.312,4.154,9.312,9.261c0,0.25-0.017,0.492-0.036,0.736l-0.015,0.182c0.396,0.15,0.782,0.332,1.155,0.547
89
+ c2.482,1.422,4.025,4.072,4.025,6.912c0,3.74-2.56,6.938-6.225,7.774c-0.598,0.138-1.205,0.209-1.801,0.209H10.137z"/>
90
+ <path fill="#75D6FF" d="M26.907,36.38c4.394,0,7.955,3.544,7.955,7.912c0,0.213-0.015,0.42-0.032,0.627
91
+ c-1.839,0.141-3.509,0.869-4.821,2.002c0.977-0.558,2.105-0.882,3.313-0.882c0.447,0,0.884,0.045,1.306,0.128
92
+ c0.723,0.143,1.4,0.403,2.017,0.757c1.999,1.146,3.347,3.286,3.347,5.745c0,3.149-2.209,5.784-5.17,6.461
93
+ c-0.482,0.11-0.982,0.174-1.498,0.174c0,0,0,0-0.001,0H10.137l0,0c-0.595,0-1.165-0.099-1.7-0.274
94
+ c-2.162-0.711-3.723-2.733-3.723-5.119c0-1.623,0.722-3.074,1.861-4.062c0.516-0.45,1.117-0.8,1.776-1.029
95
+ c0.56-0.193,1.159-0.306,1.786-0.306c1.749,0,3.299,0.826,4.292,2.105l0.048-0.001c-1.151-2.108-3.304-3.595-5.823-3.833
96
+ c0.937-3.25,3.944-5.635,7.514-5.635c0.382,0,0.752,0.036,1.118,0.089c0.725,0.104,1.417,0.302,2.063,0.588
97
+ c2.405,1.068,4.163,3.305,4.555,5.984c0-0.014,0-0.031,0-0.046c0-3.052-1.573-5.738-3.957-7.305
98
+ C21.306,38.03,23.912,36.38,26.907,36.38 M26.907,33.684c-3.658,0-7.053,1.869-9.004,4.92c-0.075-0.011-0.151-0.022-0.227-0.035
99
+ c-0.559-0.078-1.036-0.114-1.507-0.114c-4.671,0-8.834,3.12-10.123,7.589l-0.307,1.063c-0.333,0.212-0.651,0.451-0.952,0.712
100
+ C3.017,49.354,2,51.575,2,53.91c0,3.497,2.245,6.582,5.585,7.679C8.407,61.862,9.268,62,10.137,62h23.185
101
+ c0.7,0,1.41-0.081,2.112-0.244c4.278-0.977,7.271-4.715,7.271-9.087c0-3.321-1.804-6.418-4.706-8.081
102
+ c-0.14-0.08-0.281-0.156-0.425-0.229c0-0.022,0-0.044,0-0.066C37.575,38.442,32.79,33.684,26.907,33.684L26.907,33.684z"/>
103
+ </g>
104
+ </g>
105
+ </symbol><view id="view-rainbow" viewBox="0 64 64 64"/><use xlink:href="#rainbow" width="64" height="64" x="0" y="64"/></svg>
@@ -0,0 +1,2 @@
1
+ !function(a,b){"function"==typeof define&&define.amd?define([],function(){return a.svg4everybody=b()}):"object"==typeof exports?module.exports=b():a.svg4everybody=b()}(this,function(){/*! svg4everybody v2.0.0 | github.com/jonathantneal/svg4everybody */
2
+ function a(a,b){if(b){var c=!a.getAttribute("viewBox")&&b.getAttribute("viewBox"),d=document.createDocumentFragment(),e=b.cloneNode(!0);for(c&&a.setAttribute("viewBox",c);e.childNodes.length;)d.appendChild(e.firstChild);a.appendChild(d)}}function b(b){b.onreadystatechange=function(){if(4===b.readyState){var c=document.createElement("x");c.innerHTML=b.responseText,b.s.splice(0).map(function(b){a(b[0],c.querySelector("#"+b[1].replace(/(\W)/g,"\\$1")))})}},b.onreadystatechange()}function c(c){function d(){for(var c;c=e[0];){var j=c.parentNode;if(j&&/svg/i.test(j.nodeName)){var k=c.getAttribute("xlink:href");if(f&&(!g||g(k,j,c))){var l=k.split("#"),m=l[0],n=l[1];if(j.removeChild(c),m.length){var o=i[m]=i[m]||new XMLHttpRequest;o.s||(o.s=[],o.open("GET",m),o.send()),o.s.push([j,n]),b(o)}else a(j,document.getElementById(n))}}}h(d,17)}c=c||{};var e=document.getElementsByTagName("use"),f="shim"in c?c.shim:/\bEdge\/12\b|\bTrident\/[567]\b|\bVersion\/7.0 Safari\b/.test(navigator.userAgent)||(navigator.userAgent.match(/AppleWebKit\/(\d+)/)||[])[1]<537,g=c.validate,h=window.requestAnimationFrame||setTimeout,i={};f&&d()}return c});
package/license ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Shannon Moeller <me@shannonmoeller.com> (shannonmoeller.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ 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, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@tomasvn/svgstore",
3
+ "version": "3.1.0",
4
+ "description": "Combines mulitple svg files into one.",
5
+ "scripts": {
6
+ "lint": "npx eslint --fix \"{src,test}/**/*.js\" && npx prettier --write \"{src,test}/**/*.js\"",
7
+ "test": "node test/svgstore.js",
8
+ "cover": "npx c8 npm test"
9
+ },
10
+ "keywords": [
11
+ "concat",
12
+ "join",
13
+ "merge",
14
+ "pack",
15
+ "path",
16
+ "sprite",
17
+ "svg",
18
+ "svgs",
19
+ "svgstore",
20
+ "symbol",
21
+ "symbols"
22
+ ],
23
+ "author": "Shannon Moeller <me@shannonmoeller.com> (http://shannonmoeller.com)",
24
+ "maintainers": [
25
+ {
26
+ "name": "Shannon Moeller",
27
+ "email": "me@shannonmoeller.com",
28
+ "url": "https://github.com/shannonmoeller"
29
+ },
30
+ {
31
+ "name": "Brian Sipple",
32
+ "email": "bsipple57@gmail.com",
33
+ "url": "https://github.com/BrianSipple"
34
+ }
35
+ ],
36
+ "homepage": "https://github.com/svgstore/svgstore#readme",
37
+ "repository": "svgstore/svgstore",
38
+ "license": "MIT",
39
+ "main": "src/svgstore.js",
40
+ "dependencies": {
41
+ "cheerio": "v1.0.0-rc.10",
42
+ "@resvg/resvg-js": "^2.1.0"
43
+ },
44
+ "engines": {
45
+ "node": ">= 12"
46
+ },
47
+ "eslintConfig": {
48
+ "extends": "eslint:recommended",
49
+ "env": {
50
+ "node": true
51
+ },
52
+ "parserOptions": {
53
+ "ecmaVersion": 8
54
+ }
55
+ },
56
+ "prettier": {
57
+ "singleQuote": true
58
+ }
59
+ }
package/readme.md ADDED
@@ -0,0 +1,99 @@
1
+ # svgstore
2
+
3
+ [![NPM version][npm-img]][npm-url] [![Downloads][downloads-img]][npm-url]
4
+
5
+ Combines multiple SVG files into one using `<symbol>` elements which you may [`<use>` in your markup](https://css-tricks.com/svg-sprites-use-better-icon-fonts/). Heavily inspired by [`grunt-svgstore`](https://github.com/FWeinb/grunt-svgstore) and [`gulp-svgstore`](https://github.com/w0rm/gulp-svgstore), this is a standalone module that may be [used in any asset pipeline](#future-goals).
6
+
7
+ ## Install
8
+
9
+ $ npm install --save svgstore
10
+
11
+ ## Usage
12
+
13
+ ```js
14
+ var svgstore = require('svgstore');
15
+ var fs = require('fs');
16
+
17
+ var sprites = svgstore()
18
+ .add('unicorn', fs.readFileSync('./unicorn.svg', 'utf8'))
19
+ .add('rainbow', fs.readFileSync('./rainbow.svg', 'utf8'));
20
+
21
+ fs.writeFileSync('./sprites.svg', sprites);
22
+ ```
23
+
24
+ The resulting file may be consumed in markup as external content.
25
+
26
+ ```html
27
+ <body>
28
+ <svg role="img"><use xlink:href="./sprites.svg#unicorn" /></svg>
29
+ <svg role="img"><use xlink:href="./sprites.svg#rainbow" /></svg>
30
+ </body>
31
+ ```
32
+
33
+ See the [examples directory](https://github.com/shannonmoeller/svgstore/tree/master/docs/examples) for more detail.
34
+
35
+ ## API
36
+
37
+ ### svgstore([options]): SvgStore
38
+
39
+ - `options` `{Object}`: [Options for converting SVGs to symbols](#svgstore-options)
40
+
41
+ Creates a container SVG sprites document.
42
+
43
+ ### .element
44
+
45
+ The current [cheerio](https://github.com/cheeriojs/cheerio) instance.
46
+
47
+ ### .add(id, svg [, options]): SvgStore
48
+
49
+ - `id` `{String}` Unique `id` for this SVG file.
50
+ - `svg` `{String}` Raw source of the SVG file.
51
+ - `options` `{Object}` Same as the [options of `svgstore()`](#svgstore-options), but will only apply to this SVG file's `<symbol>`.
52
+
53
+ Appends a file to the sprite with the given `id`.
54
+
55
+ ### .toString([options]): String
56
+
57
+ - `options` `{Object}`
58
+ - `inline` `{Boolean}` (default: `false`) Don't output `<?xml ?>`, `DOCTYPE`, and the `xmlns` attribute.
59
+
60
+ Outputs sprite as a string of XML.
61
+
62
+ ## <a name="svgstore-options"></a>Options
63
+
64
+ - `cleanDefs` `{Boolean|Array}` (default: `false`) Remove `style` attributes from SVG definitions, or a list of attributes to remove.
65
+ - `cleanSymbols` `{Boolean|Array}` (default: `false`) Remove `style` attributes from SVG objects, or a list of attributes to remove.
66
+ - `svgAttrs` `{Boolean|Object}` (default: `false`) A map of attributes to set on the root `<svg>` element. If you set an attribute's value to null, you remove that attribute. Values may be functions like jQuery.
67
+ - `symbolAttrs` `{Boolean|Object}` (default: `false`) A map of attributes to set on each `<symbol>` element. If you set an attribute's value to null, you remove that attribute. Values may be functions like jQuery.
68
+ - `copyAttrs` `{Boolean|Array}` (default: `false`) Attributes to have `svgstore` attempt to copy to the newly created `<symbol>` tag from it's source `<svg>` tag. The `viewBox`, `aria-labelledby`, and `role` attributes are always copied.
69
+ - `renameDefs` `{Boolean}` (default: `false`) Rename `defs` content ids to make them inherit files' names so that it would help to avoid defs with same ids in the output file.
70
+ - `fragmentIdentifier` `{Function}` (default: `null`) Enable [SVG Fragment Identifiers](https://css-tricks.com/svg-fragment-identifiers-work/) to allow the use of `<img src="icons.svg#unicorn-view" />`. You can custom fragment ID like `(id) => 'view-' + id`
71
+
72
+ ## Contributing
73
+
74
+ Standards for this project, including tests, code coverage, and semantics are enforced with a build tool. Pull requests must include passing tests with 100% code coverage and no linting errors.
75
+
76
+ ### Test
77
+
78
+ $ npm test
79
+
80
+ ## Future Goals
81
+
82
+ The svgstore organization began after it was noticed that the common [build task of converting an `<svg>` into a `<symbol>` tag](https://css-tricks.com/svg-symbol-good-choice-icons/) was being implemented in a similar manner by many different projects across the JavaScript ecosystem.
83
+
84
+ The long-term goal for this project, in particular, is to provide a single standalone module that can be plugged in to any asset pipeline, thus allowing pipeline tools to focus on providing clean APIs and interfaces related to their build process integration, rather than implementing/duplicating SVG conversion logic directly.
85
+
86
+ #### Current build tools using `svgstore`:
87
+
88
+ - [broccoli-svgstore][broccoli-svgstore]
89
+ - [svgstore-cli][svgstore-cli]
90
+
91
+ ---
92
+
93
+ MIT © [Shannon Moeller](http://shannonmoeller.com)
94
+
95
+ [downloads-img]: http://img.shields.io/npm/dm/svgstore.svg?style=flat-square
96
+ [npm-img]: http://img.shields.io/npm/v/svgstore.svg?style=flat-square
97
+ [npm-url]: https://npmjs.org/package/svgstore
98
+ [broccoli-svgstore]: https://github.com/svgstore/broccoli-svgstore
99
+ [svgstore-cli]: https://github.com/svgstore/svgstore-cli
@@ -0,0 +1,148 @@
1
+ 'use strict';
2
+
3
+ var copyAttributes = require('./utils/copy-attributes');
4
+ var loadXml = require('./utils/load-xml');
5
+ var removeAttributes = require('./utils/remove-attributes');
6
+ var setAttributes = require('./utils/set-attributes');
7
+ var svgToSymbol = require('./utils/svg-to-symbol');
8
+ var getSvgRect = require('./utils/get-svg-rect');
9
+
10
+ var SELECTOR_SVG = 'svg';
11
+ var SELECTOR_DEFS = 'defs';
12
+
13
+ var TEMPLATE_SVG = '<svg><defs/></svg>';
14
+ var TEMPLATE_DOCTYPE =
15
+ '<?xml version="1.0" encoding="UTF-8"?>' +
16
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ' +
17
+ '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
18
+
19
+ var DEFAULT_OPTIONS = {
20
+ cleanDefs: false,
21
+ cleanSymbols: false,
22
+ inline: false,
23
+ svgAttrs: false,
24
+ symbolAttrs: false,
25
+ copyAttrs: false,
26
+ renameDefs: false,
27
+ fragmentIdentifier: null,
28
+ };
29
+
30
+ function svgstore(options) {
31
+ var svgstoreOptions = Object.assign({}, DEFAULT_OPTIONS, options);
32
+
33
+ // <svg>
34
+ var parent = loadXml(TEMPLATE_SVG);
35
+ var parentSvg = parent(SELECTOR_SVG);
36
+ var parentDefs = parent(SELECTOR_DEFS);
37
+
38
+ let currentY = 0;
39
+
40
+ return {
41
+ element: parent,
42
+
43
+ add: function (id, file, options) {
44
+ var child = loadXml(file);
45
+ var addOptions = Object.assign({}, svgstoreOptions, options);
46
+
47
+ // <defs>
48
+ var childDefs = child(SELECTOR_DEFS);
49
+
50
+ removeAttributes(childDefs, addOptions.cleanDefs);
51
+
52
+ /* rename defs ids */
53
+ if (addOptions.renameDefs) {
54
+ childDefs.children().each(function (i, _elem) {
55
+ var elem = child(_elem);
56
+ var oldDefId = elem.attr('id');
57
+ var newDefId = id + '_' + oldDefId;
58
+ elem.attr('id', newDefId);
59
+
60
+ /* process use tags */
61
+ child('use').each(function (i, use) {
62
+ var hrefLink = '#' + oldDefId;
63
+ var checkableProperties = ['xlink:href', 'href'];
64
+ var foundProperty;
65
+ for (var j = 0; j < checkableProperties.length; j++) {
66
+ var currentProperty = checkableProperties[j];
67
+ if (child(use).prop(currentProperty) === hrefLink) {
68
+ foundProperty = currentProperty;
69
+ break;
70
+ }
71
+ }
72
+ if (!foundProperty) {
73
+ return;
74
+ }
75
+ child(use).attr(foundProperty, '#' + newDefId);
76
+ });
77
+
78
+ /* process fill attributes */
79
+ child('[fill="url(#' + oldDefId + ')"]').each(function (
80
+ i,
81
+ use
82
+ ) {
83
+ child(use).attr('fill', 'url(#' + newDefId + ')');
84
+ });
85
+ });
86
+ }
87
+
88
+ parentDefs.append(childDefs.contents());
89
+ childDefs.remove();
90
+
91
+ // <symbol>
92
+ var childSvg = child(SELECTOR_SVG);
93
+ var childSymbol = svgToSymbol(id, child, addOptions);
94
+
95
+ removeAttributes(childSymbol, addOptions.cleanSymbols);
96
+ copyAttributes(childSymbol, childSvg, addOptions.copyAttrs);
97
+ setAttributes(childSymbol, addOptions.symbolAttrs);
98
+ parentSvg.append(childSymbol);
99
+
100
+ if (typeof svgstoreOptions.fragmentIdentifier === 'function') {
101
+ const { width, height } = getSvgRect(file);
102
+ const childView = child('<view/>');
103
+ childView.attr('id', svgstoreOptions.fragmentIdentifier(id));
104
+ childView.attr('viewBox', `0 ${currentY} ${width} ${height}`);
105
+ const childUse = child('<use/>');
106
+ childUse.attr('xlink:href', `#${id}`);
107
+ childUse.attr('width', width);
108
+ childUse.attr('height', height);
109
+ childUse.attr('x', 0);
110
+ childUse.attr('y', currentY);
111
+ currentY += height;
112
+ parentSvg.append(childView);
113
+ parentSvg.append(childUse);
114
+ }
115
+
116
+ return this;
117
+ },
118
+
119
+ toString: function (options) {
120
+ // Create a clone so we don't modify the parent document.
121
+ var clone = loadXml(parent.xml());
122
+ var toStringOptions = Object.assign({}, svgstoreOptions, options);
123
+
124
+ // <svg>
125
+ var svg = clone(SELECTOR_SVG);
126
+
127
+ setAttributes(svg, toStringOptions.svgAttrs);
128
+
129
+ // output inline
130
+ if (toStringOptions.inline) {
131
+ return clone.xml();
132
+ }
133
+
134
+ // output standalone
135
+ svg.attr('xmlns', function (val) {
136
+ return val || 'http://www.w3.org/2000/svg';
137
+ });
138
+
139
+ svg.attr('xmlns:xlink', function (val) {
140
+ return val || 'http://www.w3.org/1999/xlink';
141
+ });
142
+
143
+ return TEMPLATE_DOCTYPE + clone.xml();
144
+ },
145
+ };
146
+ }
147
+
148
+ module.exports = svgstore;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Utility to copy specific attributes from one node to another.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ var ALWAYS_COPY_ATTRS = ['viewBox', 'aria-labelledby', 'role'];
8
+
9
+ function copyAttributes(a, b, attrs) {
10
+ var attrsToCopy = ALWAYS_COPY_ATTRS.concat(attrs || []);
11
+ var copiedAttrs = Object.create(null);
12
+
13
+ attrsToCopy.forEach(function (attr) {
14
+ if (!attr || copiedAttrs[attr]) {
15
+ return;
16
+ }
17
+
18
+ copiedAttrs[attr] = true;
19
+
20
+ var bAttr = b.attr(attr);
21
+
22
+ if (bAttr != null) {
23
+ a.attr(attr, b.attr(attr));
24
+ }
25
+ });
26
+
27
+ return a;
28
+ }
29
+
30
+ module.exports = copyAttributes;
@@ -0,0 +1,11 @@
1
+ const { Resvg } = require('@resvg/resvg-js');
2
+
3
+ function getSvgRect(svg) {
4
+ const { width, height } = new Resvg(svg, {
5
+ logLevel: 'error',
6
+ font: { loadSystemFonts: false },
7
+ });
8
+ return { width, height };
9
+ }
10
+
11
+ module.exports = getSvgRect;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Utility method to create an XML document object with a jQuery-like
3
+ * interface for node manipulation.
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ var cheerio = require('cheerio');
9
+
10
+ function loadXml(text) {
11
+ return cheerio.load(text, {
12
+ xmlMode: true,
13
+ });
14
+ }
15
+
16
+ module.exports = loadXml;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Utility to remove specific attributes from all
3
+ * child nodes of a given node.
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ function removeAttributes(el, attrs) {
9
+ var localAttrs = attrs;
10
+
11
+ if (localAttrs === true) {
12
+ localAttrs = ['style'];
13
+ }
14
+
15
+ if (!localAttrs || !localAttrs.length) {
16
+ return el;
17
+ }
18
+
19
+ var els = el.find('*');
20
+
21
+ els.each(function (i) {
22
+ localAttrs.forEach(function (attr) {
23
+ els.eq(i).removeAttr(attr);
24
+ });
25
+ });
26
+
27
+ return el;
28
+ }
29
+
30
+ module.exports = removeAttributes;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Utility function to set the attributes of an element. Allows values to be
3
+ * passed as functions so existing values may be manipulated or left untouched.
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ function setAttributes(el, attrs) {
9
+ if (!attrs || typeof attrs !== 'object') {
10
+ return el;
11
+ }
12
+
13
+ Object.keys(attrs).forEach(function (attr) {
14
+ var value = attrs[attr];
15
+
16
+ // Handle function values directly as cherrio passes an unhelpful index
17
+ // as the first argument in the native function handler.
18
+ if (typeof value === 'function') {
19
+ value = value(el.attr(attr));
20
+ }
21
+
22
+ el.attr(attr, value);
23
+ });
24
+
25
+ return el;
26
+ }
27
+
28
+ module.exports = setAttributes;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Utility for cloning an <svg/> as a <symbol/> within
3
+ * the composition of svgstore output.
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ var SELECTOR_SVG = 'svg';
9
+ var TEMPLATE_SYMBOL = '<symbol/>';
10
+ var ATTRIBUTE_ID = 'id';
11
+
12
+ /**
13
+ * @param {string} id The id to be applied to the symbol tag
14
+ * @param {string} child An object created by loading the content of the current file via the cheerio#load function.
15
+ * @return {object} symbol The final cheerio-aware object created by cloning the SVG contents
16
+ * @see <a href="https://github.com/cheeriojs/cheerio">The Cheerio Project</a>
17
+ */
18
+ function svgToSymbol(id, child) {
19
+ var svgElem = child(SELECTOR_SVG);
20
+
21
+ // initialize a new <symbol> element
22
+ var symbol = child(TEMPLATE_SYMBOL);
23
+
24
+ symbol.attr(ATTRIBUTE_ID, id);
25
+ symbol.append(svgElem.contents());
26
+
27
+ return symbol;
28
+ }
29
+
30
+ module.exports = svgToSymbol;
@@ -0,0 +1,255 @@
1
+ 'use strict';
2
+
3
+ const svgstore = require('../src/svgstore.js');
4
+ const test = require('./utils/test.js');
5
+
6
+ const doctype =
7
+ '<?xml version="1.0" encoding="UTF-8"?>' +
8
+ '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ' +
9
+ '"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
10
+
11
+ const svgNs =
12
+ '<svg xmlns="http://www.w3.org/2000/svg" ' +
13
+ 'xmlns:xlink="http://www.w3.org/1999/xlink">';
14
+
15
+ const FIXTURE_SVGS = {
16
+ foo: '<svg viewBox="0 0 100 100"><defs><linear-gradient style="fill: red;"/></defs><path style="fill: red;"/></svg>',
17
+ bar: '<svg viewBox="0 0 200 200"><defs><radial-gradient style="stroke: red;"/></defs><rect style="stroke: red;"/></svg>',
18
+ baz: '<svg viewBox="0 0 200 200"><defs><linear-gradient style="fill: red;"/></defs><path style="fill: red;"/></svg>',
19
+ qux: '<svg viewBox="0 0 200 200"><defs><radial-gradient style="stroke: red;" fill="blue"/></defs><rect style="stroke: red;" fill="blue"/></svg>',
20
+ quux: '<svg viewBox="0 0 200 200" aria-labelledby="titleId" role="img"><title id="titleId">A boxy shape</title><rect/></svg>',
21
+ corge:
22
+ '<svg viewBox="0 0 200 200" aria-labelledby="titleId" role="img" preserveAspectRatio="xMinYMax" take-me-too="foo" count-me-out="bar">' +
23
+ '<title id="titleId">A boxy shape</title><rect/></svg>',
24
+ defsWithId:
25
+ '<svg><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="a"><stop stop-color="#FFF" offset="0%"/><stop stop-color="#F0F0F0" offset="100%"/></linearGradient><path id="b" d=""/></defs><path fill="url(#a)" fill-rule="nonzero" d=""/><use xlink:href="#b"></use><use fill-rule="nonzero" xlink:href="#b"></use><path fill="url(#a)" fill-rule="nonzero" d=""/></svg>',
26
+ };
27
+
28
+ test('should create an svg document', async (t) => {
29
+ const store = svgstore();
30
+ const svg = store.toString();
31
+
32
+ t.strictEqual(svg.slice(0, 5), '<?xml');
33
+ });
34
+
35
+ test('should create an svg element', async (t) => {
36
+ const store = svgstore();
37
+ const svg = store.toString({ inline: true });
38
+
39
+ t.strictEqual(svg.slice(0, 4), '<svg');
40
+ });
41
+
42
+ test('should combine svgs', async (t) => {
43
+ const store = svgstore()
44
+ .add('foo', doctype + FIXTURE_SVGS.foo)
45
+ .add('bar', doctype + FIXTURE_SVGS.bar);
46
+
47
+ const expected =
48
+ doctype +
49
+ svgNs +
50
+ '<defs>' +
51
+ '<linear-gradient style="fill: red;"/>' +
52
+ '<radial-gradient style="stroke: red;"/>' +
53
+ '</defs>' +
54
+ '<symbol id="foo" viewBox="0 0 100 100"><path style="fill: red;"/></symbol>' +
55
+ '<symbol id="bar" viewBox="0 0 200 200"><rect style="stroke: red;"/></symbol>' +
56
+ '</svg>';
57
+
58
+ t.strictEqual(store.toString(), expected);
59
+ });
60
+
61
+ test('should clean defs', async (t) => {
62
+ const store = svgstore({ cleanDefs: true })
63
+ .add('foo', doctype + FIXTURE_SVGS.foo)
64
+ .add('bar', doctype + FIXTURE_SVGS.bar)
65
+ .add('baz', doctype + FIXTURE_SVGS.baz, {
66
+ cleanDefs: [],
67
+ })
68
+ .add('qux', doctype + FIXTURE_SVGS.qux, {
69
+ cleanDefs: ['fill'],
70
+ });
71
+
72
+ const expected =
73
+ doctype +
74
+ svgNs +
75
+ '<defs>' +
76
+ '<linear-gradient/><radial-gradient/>' +
77
+ '<linear-gradient style="fill: red;"/>' +
78
+ '<radial-gradient style="stroke: red;"/>' +
79
+ '</defs>' +
80
+ '<symbol id="foo" viewBox="0 0 100 100"><path style="fill: red;"/></symbol>' +
81
+ '<symbol id="bar" viewBox="0 0 200 200"><rect style="stroke: red;"/></symbol>' +
82
+ '<symbol id="baz" viewBox="0 0 200 200"><path style="fill: red;"/></symbol>' +
83
+ '<symbol id="qux" viewBox="0 0 200 200"><rect style="stroke: red;" fill="blue"/></symbol>' +
84
+ '</svg>';
85
+
86
+ t.strictEqual(store.toString(), expected);
87
+ });
88
+
89
+ test('should clean symbols', async (t) => {
90
+ const store = svgstore({ cleanSymbols: true })
91
+ .add('foo', doctype + FIXTURE_SVGS.foo)
92
+ .add('bar', doctype + FIXTURE_SVGS.bar)
93
+ .add('baz', doctype + FIXTURE_SVGS.baz, {
94
+ cleanSymbols: [],
95
+ })
96
+ .add('qux', doctype + FIXTURE_SVGS.qux, {
97
+ cleanSymbols: ['fill'],
98
+ });
99
+
100
+ const expected =
101
+ doctype +
102
+ svgNs +
103
+ '<defs>' +
104
+ '<linear-gradient style="fill: red;"/>' +
105
+ '<radial-gradient style="stroke: red;"/>' +
106
+ '<linear-gradient style="fill: red;"/>' +
107
+ '<radial-gradient style="stroke: red;" fill="blue"/>' +
108
+ '</defs>' +
109
+ '<symbol id="foo" viewBox="0 0 100 100"><path/></symbol>' +
110
+ '<symbol id="bar" viewBox="0 0 200 200"><rect/></symbol>' +
111
+ '<symbol id="baz" viewBox="0 0 200 200"><path style="fill: red;"/></symbol>' +
112
+ '<symbol id="qux" viewBox="0 0 200 200"><rect style="stroke: red;"/></symbol>' +
113
+ '</svg>';
114
+
115
+ t.strictEqual(store.toString(), expected);
116
+ });
117
+
118
+ test('should attempt to preserve the `viewBox`, `aria-labelledby`, and `role` attributes of the root SVG by default', async (t) => {
119
+ const store = svgstore().add('quux', FIXTURE_SVGS.quux);
120
+
121
+ const expected =
122
+ doctype +
123
+ svgNs +
124
+ '<defs/>' +
125
+ '<symbol id="quux" viewBox="0 0 200 200" aria-labelledby="titleId" role="img">' +
126
+ '<title id="titleId">A boxy shape</title><rect/>' +
127
+ '</symbol>' +
128
+ '</svg>';
129
+
130
+ t.strictEqual(store.toString(), expected);
131
+ });
132
+
133
+ test('should support custom attribute preservation, on top of the defaults', async (t) => {
134
+ const copyAttrs = ['preserveAspectRatio', 'take-me-too', 'role'];
135
+ const store = svgstore({ copyAttrs }).add('corge', FIXTURE_SVGS.corge);
136
+
137
+ const expected =
138
+ doctype +
139
+ svgNs +
140
+ '<defs/>' +
141
+ '<symbol id="corge" viewBox="0 0 200 200" aria-labelledby="titleId" role="img" preserveAspectRatio="xMinYMax" take-me-too="foo">' +
142
+ '<title id="titleId">A boxy shape</title><rect/>' +
143
+ '</symbol>' +
144
+ '</svg>';
145
+
146
+ t.strictEqual(store.toString(), expected);
147
+ });
148
+
149
+ test('should set symbol attributes', async (t) => {
150
+ const options = {
151
+ inline: true,
152
+ symbolAttrs: {
153
+ viewBox: null,
154
+ id: function (id) {
155
+ return 'icon-' + id;
156
+ },
157
+ },
158
+ };
159
+
160
+ const store = svgstore(options)
161
+ .add('foo', doctype + FIXTURE_SVGS.foo)
162
+ .add('bar', doctype + FIXTURE_SVGS.bar);
163
+
164
+ const expected =
165
+ '<svg>' +
166
+ '<defs>' +
167
+ '<linear-gradient style="fill: red;"/>' +
168
+ '<radial-gradient style="stroke: red;"/>' +
169
+ '</defs>' +
170
+ '<symbol id="icon-foo"><path style="fill: red;"/></symbol>' +
171
+ '<symbol id="icon-bar"><rect style="stroke: red;"/></symbol>' +
172
+ '</svg>';
173
+
174
+ t.strictEqual(store.toString(), expected);
175
+ });
176
+
177
+ test('should set svg attributes', async (t) => {
178
+ const options = {
179
+ inline: true,
180
+ svgAttrs: {
181
+ id: 'spritesheet',
182
+ style: 'display: none',
183
+ },
184
+ };
185
+
186
+ const store = svgstore(options)
187
+ .add('foo', doctype + FIXTURE_SVGS.foo)
188
+ .add('bar', doctype + FIXTURE_SVGS.bar);
189
+
190
+ const expected =
191
+ '<svg id="spritesheet" style="display: none">' +
192
+ '<defs>' +
193
+ '<linear-gradient style="fill: red;"/>' +
194
+ '<radial-gradient style="stroke: red;"/>' +
195
+ '</defs>' +
196
+ '<symbol id="foo" viewBox="0 0 100 100"><path style="fill: red;"/></symbol>' +
197
+ '<symbol id="bar" viewBox="0 0 200 200"><rect style="stroke: red;"/></symbol>' +
198
+ '</svg>';
199
+
200
+ t.strictEqual(store.toString(), expected);
201
+ });
202
+
203
+ test('should rename defs id', async (t) => {
204
+ const options = {
205
+ inline: true,
206
+ renameDefs: true,
207
+ };
208
+
209
+ const store = svgstore(options).add(
210
+ 'defs_with_id',
211
+ doctype + FIXTURE_SVGS.defsWithId
212
+ );
213
+
214
+ const expected =
215
+ '<svg>' +
216
+ '<defs>' +
217
+ '<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="defs_with_id_a">' +
218
+ '<stop stop-color="#FFF" offset="0%"/>' +
219
+ '<stop stop-color="#F0F0F0" offset="100%"/>' +
220
+ '</linearGradient>' +
221
+ '<path id="defs_with_id_b" d=""/>' +
222
+ '</defs>' +
223
+ '<symbol id="defs_with_id">' +
224
+ '<path fill="url(#defs_with_id_a)" fill-rule="nonzero" d=""/>' +
225
+ '<use xlink:href="#defs_with_id_b"/>' +
226
+ '<use fill-rule="nonzero" xlink:href="#defs_with_id_b"/>' +
227
+ '<path fill="url(#defs_with_id_a)" fill-rule="nonzero" d=""/>' +
228
+ '</symbol>' +
229
+ '</svg>';
230
+
231
+ t.strictEqual(store.toString(), expected);
232
+ });
233
+
234
+ test('should add <view/> and <use/> to enable SVG Fragment Identifiers', async (t) => {
235
+ const store = svgstore({ fragmentIdentifier: (id) => `view-${id}` })
236
+ .add('foo', doctype + FIXTURE_SVGS.foo.replace('<svg', svgNs.slice(0, -1)))
237
+ .add('bar', doctype + FIXTURE_SVGS.bar.replace('<svg', svgNs.slice(0, -1)));
238
+
239
+ const expected =
240
+ doctype +
241
+ svgNs +
242
+ '<defs>' +
243
+ '<linear-gradient style="fill: red;"/>' +
244
+ '<radial-gradient style="stroke: red;"/>' +
245
+ '</defs>' +
246
+ '<symbol id="foo" viewBox="0 0 100 100"><path style="fill: red;"/></symbol>' +
247
+ '<view id="view-foo" viewBox="0 0 100 100"/>' +
248
+ '<use xlink:href="#foo" width="100" height="100" x="0" y="0"/>' +
249
+ '<symbol id="bar" viewBox="0 0 200 200"><rect style="stroke: red;"/></symbol>' +
250
+ '<view id="view-bar" viewBox="0 100 200 200"/>' +
251
+ '<use xlink:href="#bar" width="200" height="200" x="0" y="100"/>' +
252
+ '</svg>';
253
+
254
+ t.strictEqual(store.toString(), expected);
255
+ });
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const tests = [];
5
+
6
+ function test(msg, fn) {
7
+ tests.push([msg, fn]);
8
+ }
9
+
10
+ process.nextTick(async function run() {
11
+ const total = tests.length;
12
+ let i = 0;
13
+
14
+ for (const [msg, fn] of tests) {
15
+ i++;
16
+
17
+ try {
18
+ await fn(assert);
19
+ console.log(`${i}/${total} pass - ${msg}`);
20
+ } catch (error) {
21
+ console.error(`${i}/${total} fail - ${msg}\n`, error);
22
+ process.exitCode = 1;
23
+ }
24
+ }
25
+ });
26
+
27
+ module.exports = test;