Skip to content

Commit 04a25c4

Browse files
authored
Merge pull request #6 from vadymshymko/move-all-options-to-loader
Move all options to loader
2 parents 98a63a3 + 6d40215 commit 04a25c4

File tree

6 files changed

+59
-75
lines changed

6 files changed

+59
-75
lines changed

README.md

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Webpack loader for generating external svg symbol sprite files
77

88
## How it works?
99

10-
svg-sprite-generation-loader is a webpack-loader that takes a multiple svg files, transform them (parse and return as an object with `symbolId`, `attributes` and `content` (disabled by default) keys), optimizes and put them back in one file.
10+
svg-sprite-generation-loader is a webpack-loader that takes a multiple svg files, optimize them (using [svgo.optimize](https://github.com/svg/svgo#optimize)), transform (parse and return as an object with `symbolId`, `attributes` and `content` (disabled by default) keys) and put them back in one file.
1111

1212
Input multiple svg files, e.g:
1313

@@ -62,20 +62,12 @@ yarn add svg-sprite-generation-loader --dev
6262

6363
## Options
6464

65-
Plugin options:
66-
67-
| Name | Type | Default value | Description |
68-
| -------------- | -------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
69-
| spriteFilePath | `string` | `sprite.svg` | Path to sprite file.<br /> `webpack.output.path` <br /> is included |
70-
| svgo | object | default preset with disabled `removeUselessDefs`, `removeViewBox` and `cleanupIDs` plugins | [svgo](https://github.com/svg/svgo) config object |
71-
72-
Loader options:
73-
74-
| Name | Type | Default value | Description |
75-
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
76-
| symbolId | `string`&nbsp;\|&nbsp;`function(iconPath)` - function that takes the file path of the original icon as an argument and returns the symbolId value<br /> In both cases you can use [interpolateName](https://github.com/webpack/loader-utils#interpolatename) patterns | `"[name]"` which is equal to icon filename (without extension). For example, by default symbolId for `file1.svg` file will be `file1` | `<symbol>`&nbsp;`id` attribute value. |
77-
| addContent | `boolean` | `false` | Add svg content as property to transformed svg object (may increase bundle size when enabled) |
78-
| attributes | `string[]` | | What attributes of the original svg need to be added to transformed svg object (By default - all) |
65+
| Name | Type | Default value | Description |
66+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
67+
| symbolId | `string`&nbsp;\|&nbsp;`function(iconPath)` - function that takes the file path of the original icon as an argument and returns the symbolId value<br /> In both cases you can use [interpolateName](https://github.com/webpack/loader-utils#interpolatename) patterns | `"[name]"` which is equal to icon filename (without extension). For example, by default symbolId for `file1.svg` file will be `file1` | `<symbol>`&nbsp;`id` attribute value. |
68+
| spriteFilePath | `string` | `sprite.svg` | Path to sprite file.<br /> `webpack.output.path` <br /> is included |
69+
| svgoOptimize | `boolean` \| `object` | `true` | Enable/Disable/Customize source svg file optimization with [svgo.optimize](https://github.com/svg/svgo#optimize). The following options are used by default: <br /><pre>`{`<br />&nbsp;&nbsp;`plugins: [`<br />&nbsp;&nbsp;&nbsp;&nbsp;`{`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`name: 'preset-default',`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`params: {`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`overrides: {`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`removeViewBox: false,`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`},`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`},`<br />&nbsp;&nbsp;&nbsp;&nbsp;`},`<br />&nbsp;&nbsp;&nbsp;&nbsp;`'removeXMLNS',`<br />&nbsp;&nbsp;`],`<br />`}`</pre> You can disable it completely (by passing `false`) or use your own configuration (see [svgo docs](https://github.com/svg/svgo#optimize)) |
70+
| addContent | `boolean` | `false` | Add svg content as property to transformed svg object (may increase bundle size when enabled) |
7971

8072
## Usage:
8173

@@ -85,11 +77,7 @@ In your webpack config:
8577
const SvgSpriteGenerationPlugin = require('svg-sprite-generation-loader/plugin.js');
8678

8779
module.exports = {
88-
plugins: [
89-
new SvgSpriteGenerationPlugin.Plugin({
90-
spriteFilePath: 'path/to/sprite/filename.svg',
91-
}),
92-
],
80+
plugins: [new SvgSpriteGenerationPlugin.Plugin()],
9381
module: {
9482
rules: [
9583
{
@@ -105,7 +93,9 @@ In some source code:
10593

10694
```jsx
10795
import iconData from 'path/to/some/icon-file-name.svg';
108-
// by default iconData will include symbolId and attributes keys. If you enable the addContent loader option, the `content` key will also be added
96+
97+
// by default iconData will include symbolId and attributes keys.
98+
// If you enable the addContent loader option, the `content` key will also be added
10999

110100
<svg {...iconData.attributes}>
111101
<use href={`path/to/sprite/filename.svg#${iconData.symbolId}`} />

index.js

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,41 @@
11
const loaderUtils = require('loader-utils');
2+
const { optimize } = require('svgo');
23

34
const svgSpriteState = require('./utils/spriteState');
45
const transformSvg = require('./utils/transformSvg');
56

67
function svgSpriteGenerationLoader(source) {
78
const options = {
89
symbolId: '[name]',
10+
spriteFilePath: 'sprite.svg',
11+
svgoOptimize: true,
12+
addContent: false,
913
...this.getOptions(),
1014
};
1115

12-
const { attributes: parsedAttributes, content } = transformSvg(source);
16+
const isSvgoOptimizeEnabled = !!options.svgoOptimize;
17+
const svgoOptimizeConfig =
18+
options.svgoOptimize === true
19+
? {
20+
plugins: [
21+
{
22+
name: 'preset-default',
23+
params: {
24+
overrides: {
25+
removeViewBox: false,
26+
},
27+
},
28+
},
29+
'removeXMLNS',
30+
],
31+
}
32+
: options.svgoOptimize;
33+
34+
const iconSource = isSvgoOptimizeEnabled
35+
? optimize(source, svgoOptimizeConfig).data
36+
: source;
37+
38+
const { attributes, content } = transformSvg(iconSource);
1339

1440
const symbolId = loaderUtils.interpolateName(
1541
this,
@@ -18,16 +44,11 @@ function svgSpriteGenerationLoader(source) {
1844
: options.symbolId(this.resourcePath)
1945
);
2046

21-
const attributes = options.attributes
22-
? options.attributes.reduce((result, attrName) => {
23-
// eslint-disable-next-line no-param-reassign
24-
result[attrName] = parsedAttributes[attrName];
25-
return result;
26-
}, {})
27-
: parsedAttributes;
28-
2947
if (this.target === 'web') {
30-
svgSpriteState.addSpriteIcon({ symbolId, attributes, content });
48+
svgSpriteState.addSpriteIcon(
49+
{ symbolId, attributes, content },
50+
options.spriteFilePath
51+
);
3152
}
3253

3354
return `

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "svg-sprite-generation-loader",
3-
"version": "1.1.0",
3+
"version": "2.0.0",
44
"description": "Webpack loader for generating external svg symbol sprite files",
55
"main": "index.js",
66
"scripts": {

plugin.js

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,7 @@
1-
const { optimize } = require('svgo');
2-
31
const svgSpriteState = require('./utils/spriteState');
42

53
class SvgSpriteGeneratorPlugin {
6-
static defaultOptions = {
7-
spriteFilePath: 'sprite.svg',
8-
svgo: {
9-
plugins: [
10-
{
11-
name: 'preset-default',
12-
params: {
13-
overrides: {
14-
removeUselessDefs: false,
15-
removeViewBox: false,
16-
cleanupIDs: false,
17-
},
18-
},
19-
},
20-
],
21-
},
22-
};
23-
24-
constructor(options = {}) {
25-
this.options = { ...SvgSpriteGeneratorPlugin.defaultOptions, ...options };
26-
}
27-
4+
// eslint-disable-next-line class-methods-use-this
285
apply(compiler) {
296
// webpack module instance can be accessed from the compiler object,
307
// this ensures that correct version of the module is used
@@ -42,15 +19,12 @@ class SvgSpriteGeneratorPlugin {
4219
SvgSpriteGeneratorPlugin.name,
4320
() => {
4421
if (compilation.options.loader.target === 'web') {
45-
compilation.emitAsset(
46-
`${this.options.spriteFilePath}`,
47-
new RawSource(
48-
optimize(
49-
svgSpriteState.getSpriteContent(),
50-
this.options.svgo
51-
).data
52-
)
53-
);
22+
Object.keys(svgSpriteState.sprites).forEach((spriteFilePath) => {
23+
compilation.emitAsset(
24+
spriteFilePath,
25+
new RawSource(svgSpriteState.getSpriteContent(spriteFilePath))
26+
);
27+
});
5428
}
5529
}
5630
);

utils/spriteState.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
class SvgSpriteGenerationState {
22
constructor() {
3-
this.spriteIcons = {};
3+
this.sprites = {};
44
}
55

6-
addSpriteIcon(icon) {
7-
this.spriteIcons[icon.symbolId] = icon;
6+
addSpriteIcon(icon, spriteFilePath) {
7+
this.sprites[spriteFilePath] = this.sprites[spriteFilePath] || {};
8+
this.sprites[spriteFilePath][icon.symbolId] = icon;
89
}
910

10-
getSpriteContent() {
11-
return `${Object.keys(this.spriteIcons).reduce(
11+
getSpriteContent(spriteFilePath) {
12+
return `${Object.keys(this.sprites[spriteFilePath]).reduce(
1213
(result, iconId) =>
13-
`${result}<symbol viewBox="${this.spriteIcons[iconId].attributes.viewBox}" fill="none" id="${iconId}">${this.spriteIcons[iconId].content}</symbol>`,
14+
`${result}<symbol viewBox="${this.sprites[spriteFilePath][iconId].attributes.viewBox}" fill="none" id="${iconId}">${this.sprites[spriteFilePath][iconId].content}</symbol>`,
1415
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
1516
)}</svg>`;
1617
}

utils/transformSvg.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
function transformSvg(source) {
2-
const [, parsedAttributes, parsedContent] = source.match(
3-
/<svg(.{0,})>([\s\S]+)<\/svg>/i
4-
);
2+
const [, parsedAttributes, content] = source.match(/<svg(.*?)>(.*?)<\/svg>/i);
53

64
const attributes = parsedAttributes
75
.match(/([\w-:]+)(=)?("[^<>"]*"|'[^<>']*'|[\w-:]+)/g)
@@ -18,7 +16,7 @@ function transformSvg(source) {
1816

1917
return {
2018
attributes,
21-
content: parsedContent.replace(/\n/g, ' ').trim(),
19+
content,
2220
};
2321
}
2422

0 commit comments

Comments
 (0)