diff --git a/README.md b/README.md index d441999..ad9e215 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,24 @@ For more options, see [Terser](https://github.com/terser-js/terser). ---------- +``` yaml +neat_svg: + enable: true + include: + - '*.svg' + - '!*.min.svg' +``` +- **enable** - Enable the plugin. Defaults to `true`. +- **logger** - Verbose output. Defaults to `false`. +- **include** - Include files. Support wildcard pattern. + - Exclude `*.min.svg` by default. +- **plugin** - Plugin options. + - To retain comments, `plugins: [{removeComments: false}]`. + +For more options, see [svgo](https://github.com/svg/svgo). + +---------- + ``` yaml neat_gzip: enable: true diff --git a/index.js b/index.js index b03388b..e861da3 100644 --- a/index.js +++ b/index.js @@ -33,6 +33,14 @@ if (hexo.config.neat_enable === true) { compress: {} }, hexo.config.neat_js) + // SVG minifier + hexo.config.neat_svg = Object.assign({ + enable: true, + logger: false, + include: ['*.svg','!*.min.svg'], + plugin: [] + }, hexo.config.neat_svg) + // gzip compression hexo.config.neat_gzip = Object.assign({ enable: true, @@ -51,6 +59,7 @@ if (hexo.config.neat_enable === true) { hexo.extend.filter.register('after_render:html', filter.logicHtml) hexo.extend.filter.register('after_render:css', filter.logicCss) hexo.extend.filter.register('after_render:js', filter.logicJs) + hexo.extend.filter.register('after_generate', filter.logicSvg) hexo.extend.filter.register('after_generate', filter.logicGzip) hexo.extend.filter.register('after_generate', filter.logicBrotli) } diff --git a/lib/filter.js b/lib/filter.js index cc6d6a8..4b5557f 100644 --- a/lib/filter.js +++ b/lib/filter.js @@ -6,6 +6,7 @@ const Htmlminifier = require('html-minifier').minify const nanomatch = require('nanomatch') const zlib = require('zlib') const br = require('iltorb') +const svgo = require('svgo') function logicHtml (str, data) { const hexo = this @@ -86,6 +87,43 @@ function logicJs (str, data) { return result.code } +function logicSvg () { + const hexo = this + const options = hexo.config.neat_svg + // Return if disabled. + if (options.enable === false) return + + let route = hexo.route + let routeList = route.list() + let include = options.include + + return Promise.all((nanomatch(routeList, include, { matchBase: true })).map(path => { + return new Promise((resolve, reject) => { + // Grab all assets using hexo router + let assetPath = route.get(path) + let assetTxt = '' + // Extract the content + assetPath.on('data', (chunk) => (assetTxt += chunk)) + assetPath.on('end', () => { + if (assetTxt.length) { + // gzip compress using highest level + new svgo(options).optimize(assetTxt).then(function(result) { + // Save the compressed file to .gz + route.set(path, result.data) + // Logging + let saved = ((assetTxt.length - result.data.length) / assetTxt.length * 100).toFixed(2) + if (options.logger) { + let log = hexo.log || console.log + log.log('Minify the svg: %s [%s saved]', path, saved + '%') + } + resolve(assetTxt) + }) + } + }) + }) + })) +} + function logicGzip () { const hexo = this const options = hexo.config.neat_gzip @@ -174,6 +212,7 @@ module.exports = { logicHtml: logicHtml, logicCss: logicCss, logicJs: logicJs, + logicSvg: logicSvg, logicGzip: logicGzip, logicBrotli: logicBrotli } diff --git a/package.json b/package.json index a670d7c..3583e93 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,14 @@ "html-minifier": "^4.0.0", "iltorb": "^2.4.2", "nanomatch": "^1.2.13", + "svgo": "^1.2.2", "terser": "^3.17.0" }, "keywords": [ "html", "js", "css", + "svg", "minify", "compress", "gzip",