Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional support for SVGO #167

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": 1706549368176
"version": 1706558057916
}
63 changes: 63 additions & 0 deletions build/config/svgo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @file Provides a custom configuration to optimize (but not minimize)
* individual SVG files.
*
* This configset will not work, as is, with spritesheets.
* You will need to remove the following plugins:
*
* - `cleanupIds`
* - `removeHiddenElems`
*/

export default {
multipass: true,
js2svg: {
indent: 4,
pretty: true,
},
plugins: [
'cleanupAttrs',
'cleanupEnableBackground',
'cleanupIds',
'cleanupListOfValues',
'cleanupNumericValues',
'collapseGroups',
'convertColors',
'convertEllipseToCircle',
'convertPathData',
'convertShapeToPath',
'convertStyleToAttrs',
'convertTransform',
'inlineStyles',
'mergePaths',
'mergeStyles',
'minifyStyles',
'moveElemsAttrsToGroup',
'moveGroupAttrsToElems',
'removeComments',
'removeDesc',
'removeDimensions',
'removeDoctype',
'removeEditorsNSData',
'removeEmptyAttrs',
'removeEmptyContainers',
'removeEmptyText',
'removeHiddenElems',
'removeMetadata',
'removeNonInheritableGroupAttrs',
'removeRasterImages',
'removeScriptElement',
'removeStyleElement',
'removeTitle',
'removeUnknownsAndDefaults',
'removeUnusedNS',
'removeUselessDefs',
'removeUselessStrokeAndFill',
'removeViewBox',
// 'removeXMLNS',
// 'removeXMLProcInst',
// 'reusePaths',
// 'sortAttrs',
'sortDefsChildren',
],
};
26 changes: 26 additions & 0 deletions build/helpers/svgo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* @file If available, returns the SVGO API.
*/

let createContentItem, extendDefaultPlugins, loadConfig, optimize;

try {
let svgo = await import('svgo');

({
createContentItem,
extendDefaultPlugins,
loadConfig,
optimize
} = svgo.default);
} catch (err) {
// do nothing
}

export default optimize;
export {
createContentItem,
extendDefaultPlugins,
loadConfig,
optimize
};
49 changes: 45 additions & 4 deletions build/tasks/svgs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import defaultSVGOOptions from '../config/svgo.js';
import loconfig from '../helpers/config.js';
import message from '../helpers/message.js';
import notification from '../helpers/notification.js';
import optimize from '../helpers/svgo.js';
import resolve from '../helpers/template.js';
import { merge } from '../utils/index.js';
import { basename } from 'node:path';
Expand All @@ -20,25 +22,48 @@ export const developmentMixerOptions = Object.assign({}, defaultMixerOptions);
export const productionMixerOptions = Object.assign({}, defaultMixerOptions);

/**
* @const {object} developmentSVGsArgs - The predefined `compileSVGs()` options for development.
* @const {object} productionSVGsArgs - The predefined `compileSVGs()` options for production.
* Exclude certain SVGO plugins for the purposes of building a spritesheet.
*/
const excludeSVGOPlugins = [
'cleanupIds',
'removeHiddenElems',
];
defaultSVGOOptions.plugins = defaultSVGOOptions.plugins.filter((plugin) => !excludeSVGOPlugins.includes(plugin));
defaultSVGOOptions.js2svg.pretty = false;

/**
* @const {object} defaultSVGOOptions - The default shared SVGO options.
* @const {object} developmentSVGOOptions - The predefined SVGO options for development.
* @const {object} productionSVGOOptions - The predefined SVGO options for production.
*/
export { defaultSVGOOptions };
export const developmentSVGOOptions = Object.assign({}, defaultSVGOOptions);
export const productionSVGOOptions = Object.assign({}, defaultSVGOOptions);

/**
* @const {object|boolean} developmentSVGsArgs - The predefined `compileSVGs()` options for development.
* @const {object|boolean} productionSVGsArgs - The predefined `compileSVGs()` options for production.
*/
export const developmentSVGsArgs = [
developmentMixerOptions,
false,
];
export const productionSVGsArgs = [
productionMixerOptions,
productionSVGOOptions,
];

/**
* Generates and transforms SVG spritesheets.
*
* @async
* @param {object} [mixerOptions=null] - Customize the Mixer API options.
* @param {object} [mixerOptions=null] - Customize the Mixer API options.
* If `null`, default production options are used.
* @param {object|boolean} [svgoOptions=null] - Customize the SVGO processor API options.
* If `null`, default production options are used.
* @return {Promise}
*/
export default async function compileSVGs(mixerOptions = null) {
export default async function compileSVGs(mixerOptions = null, svgoOptions = null) {
if (mixerOptions == null) {
mixerOptions = productionMixerOptions;
} else if (
Expand All @@ -48,6 +73,18 @@ export default async function compileSVGs(mixerOptions = null) {
mixerOptions = merge({}, defaultMixerOptions, mixerOptions);
}

if (optimize) {
if (svgoOptions == null) {
svgoOptions = productionSVGOOptions;
} else if (
svgoOptions !== false &&
svgoOptions !== developmentSVGOOptions &&
svgoOptions !== productionSVGOOptions
) {
svgoOptions = Object.assign({}, defaultSVGOOptions, svgoOptions);
}
}

/**
* @async
* @param {object} entry - The entrypoint to process.
Expand Down Expand Up @@ -79,6 +116,10 @@ export default async function compileSVGs(mixerOptions = null) {

const result = await mixer(includes, mixerOptions);

if (optimize && svgoOptions) {
result.content = optimize(result.content, svgoOptions).data;
}

await result.write(outfile);

message(`${label} compiled`, 'success', timeLabel);
Expand Down
6 changes: 5 additions & 1 deletion docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ npm start

# Compile and minify assets
npm run build

# Optimize individual SVG files
npm run optimize:svg -- -f ./assets/images ./assets/images
```

See [`build.js`](../build/build.js) and [`watch.js`](../build/watch.js)
Expand Down Expand Up @@ -306,7 +309,7 @@ See the [documentation on our Grid System](grid.md#build-tasks) for details.

### `svgs`

A wrapper around [SVG Mixer] for transforming and minifying SVG files
A wrapper around [SVG Mixer] and [SVGO] for transforming and minifying SVG files
and generating spritesheets.

Example:
Expand Down Expand Up @@ -429,4 +432,5 @@ See [`versions.js`](../build/tasks/versions.js) for details.
[PurgeCSS]: https://purgecss.com/
[RegExp]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
[SVG Mixer]: https://npmjs.com/package/svg-mixer
[SVGO]: https://npmjs.com/package/svgo
[tiny-glob]: https://npmjs.com/package/tiny-glob
Loading