-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
63 lines (53 loc) · 1.59 KB
/
index.ts
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
import webpack from 'webpack'
import HTMLPlugin from 'html-webpack-plugin'
// replace lodash `_.escape()`
function escapeHTML(t: string): string {
if (!t) {
return ''
}
const escapes: Record<string, string> = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
}
return t.replace(/[&<>"']/g, (c) => escapes[c])
}
export interface TagAttributes {
[attributeName: string]: string | boolean
}
export class AssetAttributesPlugin {
private readonly scriptAttribs: TagAttributes
private readonly styleAttribs: TagAttributes
constructor({scriptAttribs = {}, styleAttribs = {}}: {scriptAttribs: TagAttributes; styleAttribs: TagAttributes}) {
this.scriptAttribs = scriptAttribs
this.styleAttribs = styleAttribs
}
apply(compiler: webpack.Compiler): void {
compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {
HTMLPlugin.getHooks(compilation).alterAssetTags.tapAsync(this.constructor.name, (data, cb) => {
function e(v: string | boolean): string | boolean {
if (typeof v === 'boolean') {
return v
}
return escapeHTML(v)
}
const scriptAttribs: TagAttributes[] = Object.entries(this.scriptAttribs).map(([k, v]) => ({
[k]: e(v),
}))
const styleAttribs: TagAttributes[] = Object.entries(this.styleAttribs).map(([k, v]) => ({
[k]: e(v),
}))
const {scripts, styles} = data.assetTags
scripts.forEach((s): void => {
Object.assign(s.attributes, ...scriptAttribs)
})
styles.forEach((s): void => {
Object.assign(s.attributes, ...styleAttribs)
})
cb(null, data)
})
})
}
}