Skip to content

Commit

Permalink
feat(globbing): support disabling basename for each pattern in 'inclu…
Browse files Browse the repository at this point in the history
…de:' option
  • Loading branch information
curbengh committed Dec 28, 2019
1 parent 9d6b724 commit 50d80cc
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 35 deletions.
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,25 @@ minify:
- **globOptions** - [micromatch options](https://github.com/micromatch/micromatch#options) to customise how glob patterns match files.
- Defaults to `{ basename: true }`, unless the pattern has a slash.
- basename is disabled depending on each pattern.
- When specifying an array of patterns, e.g. `exclude: ['*foo.html', '**/bar.html']`, basename applies to `'*foo.html'`, but not `'**/bar.html'`.
- This means the following options would work,
``` yml
exclude:
- '*foo.html'
- '**/bar/*/*.html'
globOptions:
basename: true # default
```
- This behaviour doesn't apply to pattern that starts with `!` (negation).
- This limitation only applies to `include:` option used in svg, gzip and brotli.
- This means the following options would *not* work,
``` yml
include:
- '!foo.svg'
- '!**/bar/*/*.svg'
globOptions:
basename: true
```
- basename would stay disabled, if explicitly disabled in `globOptions:`.
- However, basename option applies to all patterns in `include:`

For more options, see [HTMLMinifier](https://github.com/kangax/html-minifier).

Expand Down
42 changes: 27 additions & 15 deletions lib/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@ const isMatch = (path = '', patterns = [], options = {}) => {
return false
}

const match = (paths = [], patterns = [], options = {}) => {
let input = paths
if (paths && patterns) {
if (paths.length && patterns.length) {
const output = []
if (typeof patterns === 'string') patterns = [patterns]
const exclude = patterns.filter((pattern) => pattern.startsWith('!'))
const include = patterns.filter((pattern) => !pattern.startsWith('!'))
if (exclude.length) input = micromatch(paths, exclude, options)
if (include.length) {
for (const pattern of include) {
let { basename } = options
basename = basename && !pattern.includes('/')
const tmp = micromatch(input, pattern, { ...options, basename })
if (tmp.length) output.push(...tmp)
}
return [...new Set(output)]
}
return input
}
}
return paths
}

function logFn (original, minified, path, ext) {
const saved = ((original.length - minified.length) / original.length * 100).toFixed(2)
const log = this.log || console
Expand Down Expand Up @@ -106,11 +130,7 @@ function minifySvg () {
const routeList = route.list()
const { globOptions, include, verbose } = options

let includeString = include || ''
if (include && Array.isArray(include)) includeString = include.join('')
if (includeString && includeString.includes('/')) globOptions.basename = false

return Promise.all((micromatch(routeList, include, globOptions)).map((path) => {
return Promise.all((match(routeList, include, globOptions)).map((path) => {
return new Promise((resolve, reject) => {
const assetPath = route.get(path)
let assetTxt = ''
Expand Down Expand Up @@ -141,11 +161,7 @@ function gzipFn () {
let { level } = options
if (typeof level !== 'number') level = zlib.constants.Z_BEST_COMPRESSION

let includeString = include || ''
if (include && Array.isArray(include)) includeString = include.join('')
if (includeString && includeString.includes('/')) globOptions.basename = false

return Promise.all((micromatch(routeList, include, globOptions)).map((path) => {
return Promise.all((match(routeList, include, globOptions)).map((path) => {
return new Promise((resolve, reject) => {
const assetPath = route.get(path)
let assetTxt = ''
Expand Down Expand Up @@ -176,11 +192,7 @@ function brotliFn () {
let { level } = options
if (typeof level !== 'number') level = zlib.constants.BROTLI_MAX_QUALITY

let includeString = include || ''
if (include && Array.isArray(include)) includeString = include.join('')
if (includeString && includeString.includes('/')) globOptions.basename = false

return Promise.all((micromatch(routeList, include, globOptions)).map((path) => {
return Promise.all((match(routeList, include, globOptions)).map((path) => {
return new Promise((resolve, reject) => {
const assetPath = route.get(path)
let assetTxt = ''
Expand Down
117 changes: 99 additions & 18 deletions test/filter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,12 +377,12 @@ describe('svg', () => {

test('include - basename', async () => {
hexo.config.minify.svg.include = 'bar.svg'
const fooPath = 'foo/bar.svg'
hexo.route.set(fooPath, input)
const path = 'foo/bar.svg'
hexo.route.set(path, input)
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)

const output = hexo.route.get(fooPath)
const output = hexo.route.get(path)
let result = ''
output.on('data', (chunk) => (result += chunk))
output.on('end', () => {
Expand All @@ -392,18 +392,99 @@ describe('svg', () => {

test('include - slash in pattern', async () => {
hexo.config.minify.svg.include = '**/foo/*.svg'
const fooPath = 'blog/site/example/foo/bar.svg'
hexo.route.set(fooPath, input)
const path = 'blog/site/example/foo/bar.svg'
hexo.route.set(path, input)
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)

const output = hexo.route.get(fooPath)
const output = hexo.route.get(path)
let result = ''
output.on('data', (chunk) => (result += chunk))
output.on('end', () => {
expect(result).toBe(data)
})
})

test('include - basename + slash', async () => {
hexo.route.remove(path)

const paths = [
'lorem/ipsum/dolor.svg',
'gravida/sociis/erat/ante.svg',
'aptent/elementum.svg',
'felis/blandit/cursus.svg'
]
hexo.config.minify.svg.include = [
'dolor.svg',
'**/sociis/**/*.svg'
]

paths.forEach((inpath) => {
hexo.route.set(inpath, input)
})
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)

const minPaths = paths.slice(0, 2)
const unminPaths = paths.slice(2)

minPaths.forEach((inpath) => {
const output = hexo.route.get(inpath)
let result = ''
output.on('data', (chunk) => (result += chunk))
output.on('end', () => {
expect(result).toBe(data)
})
})

unminPaths.forEach((inpath) => {
const output = hexo.route.get(inpath)
let result = ''
output.on('data', (chunk) => (result += chunk))
output.on('end', () => {
expect(result).toBe(input)
})
})
})

test('include - reverse pattern + basename disabled', async () => {
hexo.route.remove(path)

const paths = [
'lorem/ipsum/dolor.svg',
'gravida/sociis/erat/ante.svg',
'aptent/elementum.svg',
'felis/blandit/cursus.svg'
]
hexo.config.minify.svg.include = [
'!dolor.svg'
]
hexo.config.minify.svg.globOptions = {
basename: false
}

paths.forEach((inpath) => {
hexo.route.set(inpath, input)
})
await s()
const { data } = await new Svgo(hexo.config.minify.svg).optimize(input)

paths.forEach((inpath) => {
const output = hexo.route.get(inpath)
let result = ''
output.on('data', (chunk) => (result += chunk))
output.on('end', () => {
expect(result).toBe(data)
})
})
})

test('include - empty route', async () => {
hexo.route.remove(path)

const result = await s()
expect(result.length).toBe(0)
})
})

describe('gzip', () => {
Expand Down Expand Up @@ -506,22 +587,22 @@ describe('gzip', () => {

test('include - basename', async () => {
hexo.config.minify.gzip.include = 'bar.txt'
const fooPath = 'foo/bar.txt'
hexo.route.set(fooPath, input)
const path = 'foo/bar.txt'
hexo.route.set(path, input)
await g()

const result = hexo.route.get(fooPath.concat('.gz'))
const result = hexo.route.get(path.concat('.gz'))

expect(result).toBeDefined()
})

test('include - slash in pattern', async () => {
hexo.config.minify.gzip.include = '**/foo/*.txt'
const fooPath = 'blog/site/example/foo/bar.txt'
hexo.route.set(fooPath, input)
const path = 'blog/site/example/foo/bar.txt'
hexo.route.set(path, input)
await g()

const result = hexo.route.get(fooPath.concat('.gz'))
const result = hexo.route.get(path.concat('.gz'))

expect(result).toBeDefined()
})
Expand Down Expand Up @@ -623,22 +704,22 @@ describe('brotli', () => {

test('include - basename', async () => {
hexo.config.minify.brotli.include = 'bar.txt'
const fooPath = 'foo/bar.txt'
hexo.route.set(fooPath, input)
const path = 'foo/bar.txt'
hexo.route.set(path, input)
await b()

const result = hexo.route.get(fooPath.concat('.br'))
const result = hexo.route.get(path.concat('.br'))

expect(result).toBeDefined()
})

test('include - slash in pattern', async () => {
hexo.config.minify.brotli.include = '**/foo/*.txt'
const fooPath = 'blog/site/example/foo/bar.txt'
hexo.route.set(fooPath, input)
const path = 'blog/site/example/foo/bar.txt'
hexo.route.set(path, input)
await b()

const result = hexo.route.get(fooPath.concat('.br'))
const result = hexo.route.get(path.concat('.br'))

expect(result).toBeDefined()
})
Expand Down

0 comments on commit 50d80cc

Please sign in to comment.