-
Notifications
You must be signed in to change notification settings - Fork 78
/
Copy pathassetUrl.ts
99 lines (89 loc) · 2.53 KB
/
assetUrl.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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// vue compiler module for transforming `<tag>:<attribute>` to `require`
import { urlToRequire, ASTNode, Attr } from './utils'
export interface AssetURLOptions {
[name: string]: string | string[]
}
const defaultOptions: AssetURLOptions = {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: ['xlink:href', 'href']
}
export default (userOptions?: AssetURLOptions) => {
const options = userOptions
? Object.assign({}, defaultOptions, userOptions)
: defaultOptions
return {
postTransformNode: (node: ASTNode) => {
transform(node, options)
}
}
}
function transform(node: ASTNode, options: AssetURLOptions) {
if (node.__assetUrlTransformed) {
return
}
for (const tag in options) {
if (tag === '*' || node.tag === tag) {
let attributes = options[tag]
if (typeof attributes === 'string') {
attributes = [attributes]
}
if (node.staticStyle && attributes.indexOf('style') > -1) {
node.staticStyle = rewriteStaticStyle(node.staticStyle)
}
if (node.attrs) {
attributes.filter(attr => attr !== 'style').forEach(attrName => {
node.attrs.some(attr => rewrite(attr, attrName))
})
}
}
}
node.__assetUrlTransformed = true
}
function rewrite(attr: Attr, name: string) {
if (attr.name === name) {
const value = attr.value
// only transform static URLs
if (value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
attr.value = urlToRequire(value.slice(1, -1))
return true
}
}
return false
}
function rewriteStaticStyle(style: string): string {
const styleObj = JSON.parse(style)
// A marker which won't appear in target string
let MARKER: string = Math.random()
.toString(16)
.slice(2, 10)
while (style.indexOf(MARKER) !== -1) {
MARKER = `$${MARKER}$`
}
let id = -1
const expressions: string[] = []
let result: string = JSON.stringify(styleObj, (key, value) => {
if (typeof value !== 'string') {
return value
}
let transformed: string = value.replace(
/url\((['"])?(.*?)\1\)/g,
(_0, _1, url) => {
// outer quotes would be added later
return `url(' + ${urlToRequire(url)} + ')`
}
)
if (transformed !== value) {
// add outer quotes
transformed = `'${transformed}'`
expressions.push(transformed)
id++
return MARKER + id
}
return value
})
const MARKER_RE = new RegExp(`"${MARKER}(\\d+)"`, 'g')
result = result.replace(MARKER_RE, (_, id) => expressions[id])
return result
}