@tomasvn/svgstore 3.1.3 → 3.1.5

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.
@@ -0,0 +1,33 @@
1
+ name: Deploy documentation to GitHub Pages
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: pages
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ deploy:
18
+ environment:
19
+ name: github-pages
20
+ url: ${{ steps.deployment.outputs.page_url }}
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ pages: write
24
+ id-token: write
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: actions/configure-pages@v5
28
+ - uses: actions/upload-pages-artifact@v3
29
+ with:
30
+ path: docs
31
+ - name: Deploy to GitHub Pages
32
+ id: deployment
33
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,21 @@
1
+ name: Publish Package to npmjs
2
+ on:
3
+ release:
4
+ types: [published]
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ # Setup .npmrc file to publish to npm
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20.x'
17
+ registry-url: 'https://registry.npmjs.org'
18
+ - run: npm ci
19
+ - run: npm publish --provenance --access public
20
+ env:
21
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/CHANGELOG.md CHANGED
@@ -1,14 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ # 3.1.5
4
+
5
+ - Deployed docs site
6
+
7
+ # 3.1.4
8
+
9
+ - Closes [#36][https://github.com/svgstore/svgstore/issues/36]
10
+ - Fix failing test
11
+
3
12
  # 3.1.0
13
+
4
14
  - implements [PR #33](https://github.com/svgstore/svgstore/pull/33) from original work
5
15
 
6
16
  # 3.1.1
17
+
7
18
  - parsing of `linearGradient` elements
8
19
 
9
20
  # 3.1.2
21
+
10
22
  - update readme file
11
23
 
12
24
  # 3.1.3
25
+
13
26
  - add safe clean `def` util
14
- - passing `opts`, `cleanDefs: true` would break `linearGradient`
27
+ - passing `opts`, `cleanDefs: true` would break `linearGradient`
@@ -0,0 +1,76 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="description" content="Documentation and examples for svgstore, a tool for combining SVG files into a sprite.">
7
+ <title>svgstore documentation</title>
8
+ <style>
9
+ :root {
10
+ color-scheme: light;
11
+ font-family: system-ui, sans-serif;
12
+ color: #20232a;
13
+ background: #f7f8fa;
14
+ }
15
+ body {
16
+ box-sizing: border-box;
17
+ max-width: 760px;
18
+ margin: 0 auto;
19
+ padding: 4rem 1.5rem;
20
+ line-height: 1.6;
21
+ }
22
+ h1, h2 {
23
+ line-height: 1.2;
24
+ }
25
+ a {
26
+ color: #0969da;
27
+ }
28
+ code {
29
+ padding: 0.15rem 0.35rem;
30
+ border-radius: 4px;
31
+ background: #e9edf2;
32
+ }
33
+ pre {
34
+ overflow-x: auto;
35
+ padding: 1rem;
36
+ border-radius: 6px;
37
+ background: #20232a;
38
+ color: #f7f8fa;
39
+ }
40
+ pre code {
41
+ padding: 0;
42
+ background: none;
43
+ color: inherit;
44
+ }
45
+ nav {
46
+ display: flex;
47
+ flex-wrap: wrap;
48
+ gap: 1rem;
49
+ margin-top: 2rem;
50
+ }
51
+ </style>
52
+ </head>
53
+ <body>
54
+ <main>
55
+ <h1>svgstore</h1>
56
+ <p>Combine multiple SVG files into one sprite using <code>&lt;symbol&gt;</code> elements.</p>
57
+
58
+ <h2>Quick start</h2>
59
+ <p>Install the package and add SVG files to a sprite:</p>
60
+ <pre><code>npm install @tomasvn/svgstore</code></pre>
61
+ <pre><code>const svgstore = require('@tomasvn/svgstore');
62
+ const fs = require('fs');
63
+
64
+ const sprite = svgstore()
65
+ .add('icon', fs.readFileSync('./icon.svg', 'utf8'));
66
+
67
+ fs.writeFileSync('./sprite.svg', sprite);</code></pre>
68
+
69
+ <nav aria-label="Documentation links">
70
+ <a href="examples/">View the examples</a>
71
+ <a href="https://github.com/tomasvn/svgstore#api">API reference</a>
72
+ <a href="https://github.com/tomasvn/svgstore">GitHub repository</a>
73
+ </nav>
74
+ </main>
75
+ </body>
76
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomasvn/svgstore",
3
- "version": "3.1.3",
3
+ "version": "3.1.5",
4
4
  "description": "Combines mulitple svg files into one.",
5
5
  "scripts": {
6
6
  "lint": "npx eslint --fix \"{src,test}/**/*.js\" && npx prettier --write \"{src,test}/**/*.js\"",
package/readme.md CHANGED
@@ -6,9 +6,14 @@ Combines multiple SVG files into one using `<symbol>` elements which you may [`<
6
6
 
7
7
  ## NOTE
8
8
 
9
- - This is only a fork of original work, it implements this [PR #33](https://github.com/svgstore/svgstore/pull/33) from original work
10
- - Adds linear gradient proccessing
11
- - **NOT MAINTAINED**
9
+ <blockquote>
10
+ <strong>NOTE:</strong> This is a fork of original work, released with patched fixes <br />
11
+ SEE: <a href="./CHANGELOG.md">Changelog</a>
12
+ </blockquote>
13
+
14
+ ## Documentation
15
+
16
+ Visit the [svgstore documentation site](https://tomasvn.github.io/svgstore/) for a quick start and examples.
12
17
 
13
18
  ## Install
14
19
 
package/src/svgstore.js CHANGED
@@ -134,32 +134,33 @@ function svgstore(options) {
134
134
  var elem = child(_elem);
135
135
  var oldDefId = elem.attr('id');
136
136
  var newDefId = id + '_' + oldDefId;
137
+ var oldHref = '#' + oldDefId;
138
+ var newHref = '#' + newDefId;
139
+ var oldUrl = 'url(' + oldHref + ')';
140
+ var newUrl = 'url(' + newHref + ')';
137
141
  elem.attr('id', newDefId);
138
142
 
139
- /* process use tags */
140
- child('use').each(function (i, use) {
141
- var hrefLink = '#' + oldDefId;
142
- var checkableProperties = ['xlink:href', 'href'];
143
- var foundProperty;
144
- for (var j = 0; j < checkableProperties.length; j++) {
145
- var currentProperty = checkableProperties[j];
146
- if (child(use).prop(currentProperty) === hrefLink) {
147
- foundProperty = currentProperty;
148
- break;
143
+ child('*').each(function (i, refElem) {
144
+ var ref = child(refElem);
145
+ var attrs = refElem.attribs || {};
146
+ Object.keys(attrs).forEach(function (attr) {
147
+ var originalValue = attrs[attr];
148
+ var value = originalValue;
149
+ if (typeof value !== 'string') return;
150
+
151
+ if (
152
+ (attr === 'href' || attr === 'xlink:href') &&
153
+ value === oldHref
154
+ ) {
155
+ value = newHref;
156
+ }
157
+
158
+ if (value.indexOf(oldUrl) !== -1) {
159
+ value = value.split(oldUrl).join(newUrl);
149
160
  }
150
- }
151
- if (!foundProperty) {
152
- return;
153
- }
154
- child(use).attr(foundProperty, '#' + newDefId);
155
- });
156
161
 
157
- /* process fill attributes */
158
- child('[fill="url(#' + oldDefId + ')"]').each(function (
159
- i,
160
- use
161
- ) {
162
- child(use).attr('fill', 'url(#' + newDefId + ')');
162
+ if (value !== originalValue) ref.attr(attr, value);
163
+ });
163
164
  });
164
165
  });
165
166
  }
@@ -1,7 +1,6 @@
1
1
  function safeCleanDefsAttrs(attrs) {
2
2
  if (attrs === true) {
3
- // Default to removing 'style' only outside of defs, but skip inside defs
4
- return [];
3
+ return ['style'];
5
4
  }
6
5
  if (!Array.isArray(attrs)) return [];
7
6
  // Exclude 'style' to preserve gradient stops and fills
package/test/svgstore.js CHANGED
@@ -231,6 +231,71 @@ test('should rename defs id', async (t) => {
231
231
  t.strictEqual(store.toString(), expected);
232
232
  });
233
233
 
234
+ test('should update all references to renamed defs ids', async (t) => {
235
+ const svg =
236
+ '<svg><defs>' +
237
+ '<linearGradient id="paint0"/>' +
238
+ '<linearGradient id="paint1" href="#paint0"/>' +
239
+ '<clipPath id="clip0"/>' +
240
+ '<mask id="mask0"/>' +
241
+ '<filter id="filter0"/>' +
242
+ '<marker id="marker0"/>' +
243
+ '</defs>' +
244
+ '<g clip-path="url(#clip0)" mask="url(#mask0)" filter="url(#filter0)" ' +
245
+ 'marker-start="url(#marker0)" marker-mid="url(#marker0)" ' +
246
+ 'marker-end="url(#marker0)">' +
247
+ '<path fill="url(#paint0)" stroke="url(#paint0)" ' +
248
+ 'style="fill:url(#paint0);stroke:url(#paint0)"/>' +
249
+ '</g></svg>';
250
+ const output = svgstore({ inline: true, renameDefs: true })
251
+ .add('icon', svg)
252
+ .toString();
253
+
254
+ [
255
+ 'href="#icon_paint0"',
256
+ 'clip-path="url(#icon_clip0)"',
257
+ 'mask="url(#icon_mask0)"',
258
+ 'filter="url(#icon_filter0)"',
259
+ 'marker-start="url(#icon_marker0)"',
260
+ 'marker-mid="url(#icon_marker0)"',
261
+ 'marker-end="url(#icon_marker0)"',
262
+ 'fill="url(#icon_paint0)"',
263
+ 'stroke="url(#icon_paint0)"',
264
+ 'style="fill:url(#icon_paint0);stroke:url(#icon_paint0)"',
265
+ ].forEach((reference) => {
266
+ t.ok(output.includes(reference), `expected output to include ${reference}`);
267
+ });
268
+ });
269
+
270
+ test('should match the renameDefs issue reproduction', async (t) => {
271
+ const icon =
272
+ '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">' +
273
+ '<g clip-path="url(#clip0)"><path d="M0 12h24" stroke="url(#paint0)" stroke-width="4"/></g>' +
274
+ '<defs>' +
275
+ '<linearGradient id="paint0" x2="24" gradientUnits="userSpaceOnUse">' +
276
+ '<stop stop-color="red"/><stop offset="1" stop-color="blue"/>' +
277
+ '</linearGradient>' +
278
+ '<clipPath id="clip0"><rect width="12" height="24"/></clipPath>' +
279
+ '</defs></svg>';
280
+
281
+ const output = svgstore({ renameDefs: true })
282
+ .add('icon', icon)
283
+ .toString({ inline: true });
284
+
285
+ const expected =
286
+ '<svg><defs>' +
287
+ '<linearGradient id="icon_paint0" x2="24" gradientUnits="userSpaceOnUse">' +
288
+ '<stop stop-color="red"/><stop offset="1" stop-color="blue"/>' +
289
+ '</linearGradient>' +
290
+ '<clipPath id="icon_clip0"><rect width="12" height="24"/></clipPath>' +
291
+ '</defs>' +
292
+ '<symbol id="icon" viewBox="0 0 24 24">' +
293
+ '<g clip-path="url(#icon_clip0)"><path d="M0 12h24" stroke="url(#icon_paint0)" stroke-width="4"/></g>' +
294
+ '</symbol></svg>';
295
+
296
+ t.strictEqual(output, expected);
297
+ });
298
+
234
299
  test('should add <view/> and <use/> to enable SVG Fragment Identifiers', async (t) => {
235
300
  const store = svgstore({ fragmentIdentifier: (id) => `view-${id}` })
236
301
  .add('foo', doctype + FIXTURE_SVGS.foo.replace('<svg', svgNs.slice(0, -1)))