mirror of https://github.com/curbengh/hexo-yam
feat: add source map supports
This commit is contained in:
parent
83f62ea518
commit
2528fcc394
|
@ -90,6 +90,8 @@ minify:
|
|||
- **verbose** - Verbose output. Defaults to `false`.
|
||||
- **exclude** - Exclude files. Support [wildcard](http://www.globtester.com/) pattern(s) in a string or array.
|
||||
- **level** - Optimization level. Defaults to `2`.
|
||||
- **sourceMap** - Source map options. Defaults to `false`.
|
||||
- **mapIncludeSources** - Include sources in map, Defaults to `false`.
|
||||
- **globOptions** - See [globbing](#globbing) section.
|
||||
|
||||
For more options, see [clean-css](https://github.com/jakubpawlowicz/clean-css).
|
||||
|
@ -112,6 +114,8 @@ minify:
|
|||
- **mangle** - Mangle variable names. Defaults to `true`. Pass an object to specify [mangle options](https://github.com/terser-js/terser#mangle-options).
|
||||
- **output** - Output options.
|
||||
- To retain comments, `output: {comments: true}`.
|
||||
- **sourceMap** - Source map options. Defaults to `false`.
|
||||
- To include sources in map, `sourceMap: { includeSources: true }`
|
||||
- **globOptions** - See [globbing](#globbing) section.
|
||||
|
||||
For more options, see [Terser](https://github.com/terser-js/terser).
|
||||
|
|
13
index.js
13
index.js
|
@ -32,6 +32,8 @@ hexo.config.minify.css = {
|
|||
verbose: false,
|
||||
exclude: ['*.min.css'],
|
||||
level: 2,
|
||||
sourceMap: false,
|
||||
mapIncludeSources: false,
|
||||
globOptions: { basename: true },
|
||||
...hexo.config.minify.css
|
||||
}
|
||||
|
@ -44,6 +46,7 @@ hexo.config.minify.js = {
|
|||
compress: {},
|
||||
mangle: true,
|
||||
output: {},
|
||||
sourceMap: false,
|
||||
globOptions: { basename: true },
|
||||
...hexo.config.minify.js
|
||||
}
|
||||
|
@ -109,11 +112,21 @@ if (hexo.config.minify.enable === true && !(hexo.config.minify.previewServer ===
|
|||
hexo.extend.filter.register('after_render:html', require('./lib/html').minifyHtml, hexo.config.minify.html.priority)
|
||||
}
|
||||
if (hexo.config.minify.css.enable === true) {
|
||||
if (hexo.config.minify.css.sourceMap) {
|
||||
hexo.extend.filter.register('after_generate', require('./lib/css').minifyCssWithMap, hexo.config.minify.js.priority)
|
||||
}
|
||||
else {
|
||||
hexo.extend.filter.register('after_render:css', require('./lib/css').minifyCss, hexo.config.minify.css.priority)
|
||||
}
|
||||
}
|
||||
if (hexo.config.minify.js.enable === true) {
|
||||
if (hexo.config.minify.js.sourceMap) {
|
||||
hexo.extend.filter.register('after_generate', require('./lib/js').minifyJsWithMap, hexo.config.minify.js.priority)
|
||||
}
|
||||
else {
|
||||
hexo.extend.filter.register('after_render:js', require('./lib/js').minifyJs, hexo.config.minify.js.priority)
|
||||
}
|
||||
}
|
||||
if (hexo.config.minify.svg.enable === true) {
|
||||
hexo.extend.filter.register('after_generate', require('./lib/svg').minifySvg, hexo.config.minify.svg.priority)
|
||||
}
|
||||
|
|
49
lib/css.js
49
lib/css.js
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
const CleanCSS = require('clean-css')
|
||||
const { isMatch, logFn } = require('./tools')
|
||||
const { isMatch, match, logFn } = require('./tools')
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
|
@ -13,6 +13,7 @@ async function minifyCss(str, data) {
|
|||
|
||||
const path = data.path
|
||||
const { exclude, globOptions, verbose } = options
|
||||
options.returnPromise = true
|
||||
|
||||
if (isMatch(path, exclude, globOptions)) return str
|
||||
|
||||
|
@ -25,6 +26,48 @@ async function minifyCss(str, data) {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
minifyCss
|
||||
function minifyCssWithMap() {
|
||||
const hexo = this
|
||||
const options = hexo.config.minify.css
|
||||
const { parse } = require('path')
|
||||
|
||||
const route = hexo.route
|
||||
const routeList = route.list()
|
||||
/** @type {{ exclude: string[] }} */
|
||||
const { exclude, globOptions, verbose } = options
|
||||
const include = ['*.css', ...exclude.map(x => `!${x}`)]
|
||||
options.returnPromise = true
|
||||
const cleanCSS = new CleanCSS(options)
|
||||
|
||||
return Promise.all((match(routeList, include, globOptions)).map(path => {
|
||||
return new Promise((/** @type {(value: void) => void} */ resolve, reject) => {
|
||||
const assetPath = route.get(path)
|
||||
let assetTxt = ''
|
||||
assetPath.on('data', chunk => (assetTxt += chunk))
|
||||
assetPath.on('end', async () => {
|
||||
if (assetTxt.length) {
|
||||
try {
|
||||
const { base, ext, name } = parse(path)
|
||||
const { styles, sourceMap } = await cleanCSS.minify(assetTxt)
|
||||
if (verbose) logFn.call(this, assetTxt, result, path, 'css')
|
||||
route.set(path, `${styles}\n/*# sourceMappingURL=${base}.map */`)
|
||||
const map = sourceMap.toJSON()
|
||||
map.sources = [`${name}.source${ext}`]
|
||||
if (options.mapIncludeSources === true) {
|
||||
map.sourcesContent = [assetTxt]
|
||||
}
|
||||
route.set(`${path}.map`, JSON.stringify(map))
|
||||
} catch (err) {
|
||||
reject(new Error(`Path: ${path}\n${err}`))
|
||||
}
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
minifyCss,
|
||||
minifyCssWithMap
|
||||
}
|
54
lib/js.js
54
lib/js.js
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
const { minify: terserMinify } = require('terser')
|
||||
const { isMatch, logFn } = require('./tools')
|
||||
const { isMatch, match, logFn } = require('./tools')
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
|
@ -31,6 +31,54 @@ async function minifyJs(str, data) {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
minifyJs
|
||||
function minifyJsWithMap() {
|
||||
const hexo = this
|
||||
const options = hexo.config.minify.js
|
||||
const { parse } = require('path')
|
||||
|
||||
const route = hexo.route
|
||||
const routeList = route.list()
|
||||
/** @type {{ exclude: string[] }} */
|
||||
const { exclude, globOptions, verbose, ...jsOptions } = options
|
||||
const include = ['*.js', ...exclude.map(x => `!${x}`)]
|
||||
|
||||
// Terser doesn't like unsupported options
|
||||
delete jsOptions.enable
|
||||
delete jsOptions.priority
|
||||
// Old option, retained to avoid crash when upgrading to v4
|
||||
delete jsOptions.logger
|
||||
|
||||
return Promise.all((match(routeList, include, globOptions)).map(path => {
|
||||
return new Promise((/** @type {(value: void) => void} */ resolve, reject) => {
|
||||
const assetPath = route.get(path)
|
||||
let assetTxt = ''
|
||||
assetPath.on('data', chunk => (assetTxt += chunk))
|
||||
assetPath.on('end', async () => {
|
||||
if (assetTxt.length) {
|
||||
try {
|
||||
const { base, ext, name } = parse(path)
|
||||
jsOptions.sourceMap = {
|
||||
...jsOptions.sourceMap,
|
||||
filename: base,
|
||||
asObject: true,
|
||||
url: `${base}.map`
|
||||
}
|
||||
const { code, map } = await terserMinify(assetTxt, { ...jsOptions })
|
||||
if (verbose) logFn.call(this, assetTxt, result, path, 'js')
|
||||
route.set(path, code)
|
||||
map.sources = [`${name}.source${ext}`]
|
||||
route.set(`${path}.map`, JSON.stringify(map))
|
||||
} catch (err) {
|
||||
reject(new Error(`Path: ${path}\n${err}`))
|
||||
}
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
minifyJs,
|
||||
minifyJsWithMap
|
||||
}
|
|
@ -10,7 +10,7 @@ function gzipFn() {
|
|||
const options = hexo.config.minify.gzip
|
||||
|
||||
const route = hexo.route
|
||||
/** @type {string} */
|
||||
/** @type {string[]} */
|
||||
const routeList = route.list()
|
||||
const { globOptions, include, verbose } = options
|
||||
let level = options.level
|
||||
|
@ -43,6 +43,7 @@ function brotliFn() {
|
|||
const options = hexo.config.minify.brotli
|
||||
|
||||
const route = hexo.route
|
||||
/** @type {string[]} */
|
||||
const routeList = route.list()
|
||||
const { globOptions, include, verbose } = options
|
||||
let level = options.level
|
||||
|
|
Loading…
Reference in New Issue