Skip to content

Commit 817ad5e

Browse files
committed
supports uri fragment in static style transformed require
fix vuejs/vue-loader#646
1 parent c494c69 commit 817ad5e

File tree

4 files changed

+108
-5
lines changed

4 files changed

+108
-5
lines changed

Diff for: lib/templateCompilerModules/assetUrl.ts

+52-5
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,26 @@ export default (userOptions?: AssetURLOptions) => {
2626
}
2727

2828
function transform(node: ASTNode, options: AssetURLOptions) {
29+
if (node.__assetUrlTransformed) {
30+
return
31+
}
2932
for (const tag in options) {
30-
if ((tag === '*' || node.tag === tag) && node.attrs) {
31-
const attributes = options[tag]
33+
if (tag === '*' || node.tag === tag) {
34+
let attributes = options[tag]
3235
if (typeof attributes === 'string') {
33-
node.attrs.some(attr => rewrite(attr, attributes))
34-
} else if (Array.isArray(attributes)) {
35-
attributes.forEach(item => node.attrs.some(attr => rewrite(attr, item)))
36+
attributes = [attributes]
37+
}
38+
if (node.staticStyle && attributes.indexOf('style') > -1) {
39+
node.staticStyle = rewriteStaticStyle(node.staticStyle)
40+
}
41+
if (node.attrs) {
42+
attributes.filter(attr => attr !== 'style').forEach(attrName => {
43+
node.attrs.some(attr => rewrite(attr, attrName))
44+
})
3645
}
3746
}
3847
}
48+
node.__assetUrlTransformed = true
3949
}
4050

4151
function rewrite(attr: Attr, name: string) {
@@ -49,3 +59,40 @@ function rewrite(attr: Attr, name: string) {
4959
}
5060
return false
5161
}
62+
63+
function rewriteStaticStyle(style: string): string {
64+
const styleObj = JSON.parse(style)
65+
66+
// A marker which won't appear in target string
67+
let MARKER: string = Math.random()
68+
.toString(16)
69+
.slice(2, 10)
70+
while (style.indexOf(MARKER) !== -1) {
71+
MARKER = `$${MARKER}$`
72+
}
73+
let id = -1
74+
const expressions: string[] = []
75+
76+
let result: string = JSON.stringify(styleObj, (key, value) => {
77+
if (typeof value !== 'string') {
78+
return value
79+
}
80+
let transformed: string = value.replace(
81+
/url\((['"])?(.*?)\1\)/g,
82+
(_0, _1, url) => {
83+
// outer quotes would be added latter
84+
return `url(' + ${urlToRequire(url)} + ')`
85+
}
86+
)
87+
if (transformed !== value) {
88+
transformed = `'${transformed}'`
89+
expressions.push(transformed)
90+
id++
91+
return MARKER + id
92+
}
93+
return value
94+
})
95+
const MARKER_RE = new RegExp(`"${MARKER}(\\d)"`, 'g')
96+
result = result.replace(MARKER_RE, (_, id) => expressions[id])
97+
return result
98+
}

Diff for: lib/templateCompilerModules/utils.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ export interface Attr {
66
export interface ASTNode {
77
tag: string
88
attrs: Attr[]
9+
staticStyle?: string
10+
__assetUrlTransformed?: boolean
911
}
1012

1113
import { UrlWithStringQuery, parse as uriParse } from 'url'

Diff for: test/__snapshots__/compileTemplate.spec.ts.snap

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`supports uri fragment in static style transformed require 1`] = `
4+
"var render = function() {
5+
var _vm = this
6+
var _h = _vm.$createElement
7+
var _c = _vm._self._c || _h
8+
return _c(\\"div\\", [
9+
_c(\\"img\\", { attrs: { src: require(\\"./image.jpg\\") } }),
10+
_c(\\"div\\", {
11+
staticStyle: {
12+
color: \\"yellow\\",
13+
background: \\"#f00 url(\\" + require(\\"./image/bg0.jpg\\") + \\") repeat\\"
14+
}
15+
}),
16+
_c(\\"div\\", {
17+
staticStyle: {
18+
background:
19+
\\"url(\\" +
20+
require(\\"./image/bg1.jpg\\") +
21+
\\"), url(\\" +
22+
require(\\"@/image/bg2.jpg\\") +
23+
\\")\\"
24+
}
25+
})
26+
])
27+
}
28+
var staticRenderFns = []
29+
render._withStripped = true
30+
"
31+
`;

Diff for: test/compileTemplate.spec.ts

+23
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,29 @@ test('when too short uri then empty require', () => {
101101
expect(result.code).toMatch(/href: require\(""\)/)
102102
})
103103

104+
/**
105+
* Support uri fragment in static style in transformed require
106+
*/
107+
test('supports uri fragment in static style transformed require', () => {
108+
const source =
109+
'<div>' +
110+
'<img src="./image.jpg"/>' +
111+
'<div style="color: yellow;background: #f00 url(./image/bg0.jpg) repeat"></div>' +
112+
'<div style="background: url(./image/bg1.jpg), url(~@/image/bg2.jpg)"></div>' +
113+
'</div>'
114+
const result = compileTemplate({
115+
filename: 'inline-style.html',
116+
source: source,
117+
transformAssetUrls: {
118+
use: 'href',
119+
'*': 'style'
120+
},
121+
compiler: compiler
122+
})
123+
expect(result.errors.length).toBe(0)
124+
expect(result.code).toMatchSnapshot()
125+
})
126+
104127
test('warn missing preprocessor', () => {
105128
const template = parse({
106129
source: '<template lang="unknownLang">\n' + '</template>\n',

0 commit comments

Comments
 (0)