-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
76 lines (68 loc) · 2.32 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import babelParser from '@babel/parser'
import babelGenerator from '@babel/generator'
import babelTraverse from '@babel/traverse'
import babelTypes from '@babel/types'
import { minify } from 'html-minifier-terser'
import { readFile } from 'fs/promises'
const { default: generator } = babelGenerator
const { default: traverse } = babelTraverse
const wrapperTag = {
opening: '<html>',
closing: '</html>',
}
function uuid() {
return Math.random()
.toString(36)
.replace(/^0\.\d*/, '')
}
async function minifyTaggedTemplate(quasiNode) {
const quasis = quasiNode.node.quasis.map((quasi) => quasi.value.raw)
const expressionPlaceholder = uuid()
let template = wrapperTag.opening + quasis.join(expressionPlaceholder) + wrapperTag.closing
try {
template = await minify(template, {
caseSensitive: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
})
if (!template.startsWith(wrapperTag.opening) || !template.endsWith(wrapperTag.closing)) {
throw 'unexpected html structure after minified'
}
const minifiedQuasis = template
.slice(wrapperTag.opening.length, -wrapperTag.closing.length)
.split(expressionPlaceholder)
if (minifiedQuasis.length !== quasis.length) {
throw 'fragment number is wrong after minified'
}
minifiedQuasis.forEach((quasis, index, itself) => {
quasiNode.node.quasis[index] = babelTypes.templateElement({ raw: quasis }, index === itself.length - 1)
})
} catch (error) {
console.error(error.message)
}
}
export default function () {
return {
name: 'lit-minify-html',
setup(build) {
build.onLoad({ filter: /\.(js|ts)$/ }, async (args) => {
const content = await readFile(args.path, { encoding: 'utf-8' })
const ast = babelParser.parse(content, { sourceType: 'module', plugins: ['decorators', 'typescript'] })
const minifyProcessings = []
traverse(ast, {
TaggedTemplateExpression(path) {
if (path.node.tag.name === 'html') {
minifyProcessings.push(minifyTaggedTemplate(path.get('quasi')))
}
},
})
await Promise.all(minifyProcessings)
const contents = generator(ast).code
return {
contents,
loader: args.path.match(/(?<=\.)\w+$/).toString(),
}
})
},
}
}