Skip to content

Commit c71ca35

Browse files
sisouyyx990803
authored andcommitted
fix(compiler-sfc): only transform relative asset URLs (#628)
1 parent 787ac5f commit c71ca35

8 files changed

+67
-30
lines changed

packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap

+3-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ export function render() {
3333
return (openBlock(), createBlock(Fragment, null, [
3434
createVNode(\\"img\\", { src: _imports_0 }),
3535
createVNode(\\"img\\", { src: _imports_1 }),
36-
createVNode(\\"img\\", { src: _imports_1 })
36+
createVNode(\\"img\\", { src: _imports_1 }),
37+
createVNode(\\"img\\", { src: \\"http://example.com/fixtures/logo.png\\" }),
38+
createVNode(\\"img\\", { src: \\"/fixtures/logo.png\\" })
3739
], 64 /* STABLE_FRAGMENT */))
3840
}"
3941
`;

packages/compiler-sfc/__tests__/__snapshots__/templateTransformSrcset.spec.ts.snap

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const _hoisted_4 = _imports_0 + ', ' + _imports_0 + '2x'
1212
const _hoisted_5 = _imports_0 + '2x, ' + _imports_0
1313
const _hoisted_6 = _imports_0 + '2x, ' + _imports_0 + '3x'
1414
const _hoisted_7 = _imports_0 + ', ' + _imports_0 + '2x, ' + _imports_0 + '3x'
15+
const _hoisted_8 = \\"/logo.png\\" + ', ' + _imports_0 + '2x'
1516
1617
export function render() {
1718
const _ctx = this
@@ -43,6 +44,18 @@ export function render() {
4344
createVNode(\\"img\\", {
4445
src: \\"./logo.png\\",
4546
srcset: _hoisted_7
47+
}),
48+
createVNode(\\"img\\", {
49+
src: \\"/logo.png\\",
50+
srcset: \\"/logo.png, /logo.png 2x\\"
51+
}),
52+
createVNode(\\"img\\", {
53+
src: \\"https://example.com/logo.png\\",
54+
srcset: \\"https://example.com/logo.png, https://example.com/logo.png 2x\\"
55+
}),
56+
createVNode(\\"img\\", {
57+
src: \\"/logo.png\\",
58+
srcset: _hoisted_8
4659
})
4760
], 64 /* STABLE_FRAGMENT */))
4861
}"

packages/compiler-sfc/__tests__/compileTemplate.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ test('warn missing preprocessor', () => {
5050
})
5151

5252
test('transform asset url options', () => {
53-
const input = { source: `<foo bar="baz"/>`, filename: 'example.vue' }
53+
const input = { source: `<foo bar="~baz"/>`, filename: 'example.vue' }
5454
// Object option
5555
const { code: code1 } = compileTemplate({
5656
...input,

packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ describe('compiler sfc: transform asset url', () => {
2020
<img src="./logo.png"/>
2121
<img src="~fixtures/logo.png"/>
2222
<img src="~/fixtures/logo.png"/>
23+
<img src="http://example.com/fixtures/logo.png"/>
24+
<img src="/fixtures/logo.png"/>
2325
`)
2426

2527
expect(result.code).toMatchSnapshot()

packages/compiler-sfc/__tests__/templateTransformSrcset.spec.ts

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ describe('compiler sfc: transform srcset', () => {
2424
<img src="./logo.png" srcset="./logo.png 2x, ./logo.png"/>
2525
<img src="./logo.png" srcset="./logo.png 2x, ./logo.png 3x"/>
2626
<img src="./logo.png" srcset="./logo.png, ./logo.png 2x, ./logo.png 3x"/>
27+
<img src="/logo.png" srcset="/logo.png, /logo.png 2x"/>
28+
<img src="https://example.com/logo.png" srcset="https://example.com/logo.png, https://example.com/logo.png 2x"/>
29+
<img src="/logo.png" srcset="/logo.png, ./logo.png 2x"/>
2730
`)
2831

2932
expect(result.code).toMatchSnapshot()

packages/compiler-sfc/src/templateTransformAssetUrl.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
SourceLocation,
88
TransformContext
99
} from '@vue/compiler-core'
10-
import { parseUrl } from './templateUtils'
10+
import { isRelativeUrl, parseUrl } from './templateUtils'
1111

1212
export interface AssetURLOptions {
1313
[name: string]: string[]
@@ -46,6 +46,7 @@ export const transformAssetUrl: NodeTransform = (
4646
if (attr.type !== NodeTypes.ATTRIBUTE) return
4747
if (attr.name !== item) return
4848
if (!attr.value) return
49+
if (!isRelativeUrl(attr.value.content)) return
4950
const url = parseUrl(attr.value.content)
5051
const exp = getImportsExpressionExp(
5152
url.path,

packages/compiler-sfc/src/templateTransformSrcset.ts

+35-22
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
NodeTypes,
66
SimpleExpressionNode
77
} from '@vue/compiler-core'
8-
import { parseUrl } from './templateUtils'
8+
import { isRelativeUrl, parseUrl } from './templateUtils'
99

1010
const srcsetTags = ['img', 'source']
1111

@@ -36,31 +36,44 @@ export const transformSrcset: NodeTransform = (node, context) => {
3636
return { url, descriptor }
3737
})
3838

39+
// When srcset does not contain any relative URLs, skip transforming
40+
if (!imageCandidates.some(({ url }) => isRelativeUrl(url))) return
41+
3942
const compoundExpression = createCompoundExpression([], attr.loc)
4043
imageCandidates.forEach(({ url, descriptor }, index) => {
41-
const { path } = parseUrl(url)
42-
let exp: SimpleExpressionNode
43-
if (path) {
44-
const importsArray = Array.from(context.imports)
45-
const existingImportsIndex = importsArray.findIndex(
46-
i => i.path === path
47-
)
48-
if (existingImportsIndex > -1) {
49-
exp = createSimpleExpression(
50-
`_imports_${existingImportsIndex}`,
51-
false,
52-
attr.loc,
53-
true
44+
if (isRelativeUrl(url)) {
45+
const { path } = parseUrl(url)
46+
let exp: SimpleExpressionNode
47+
if (path) {
48+
const importsArray = Array.from(context.imports)
49+
const existingImportsIndex = importsArray.findIndex(
50+
i => i.path === path
5451
)
55-
} else {
56-
exp = createSimpleExpression(
57-
`_imports_${importsArray.length}`,
58-
false,
59-
attr.loc,
60-
true
61-
)
62-
context.imports.add({ exp, path })
52+
if (existingImportsIndex > -1) {
53+
exp = createSimpleExpression(
54+
`_imports_${existingImportsIndex}`,
55+
false,
56+
attr.loc,
57+
true
58+
)
59+
} else {
60+
exp = createSimpleExpression(
61+
`_imports_${importsArray.length}`,
62+
false,
63+
attr.loc,
64+
true
65+
)
66+
context.imports.add({ exp, path })
67+
}
68+
compoundExpression.children.push(exp)
6369
}
70+
} else {
71+
const exp = createSimpleExpression(
72+
`"${url}"`,
73+
false,
74+
attr.loc,
75+
true
76+
)
6477
compoundExpression.children.push(exp)
6578
}
6679
const isNotLast = imageCandidates.length - 1 > index

packages/compiler-sfc/src/templateUtils.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { UrlWithStringQuery, parse as uriParse } from 'url'
22
import { isString } from '@vue/shared'
33

4+
export function isRelativeUrl(url: string): boolean {
5+
const firstChar = url.charAt(0)
6+
return firstChar === '.' || firstChar === '~' || firstChar === '@'
7+
}
8+
49
// We need an extra transform context API for injecting arbitrary import
510
// statements.
611
export function parseUrl(url: string): UrlWithStringQuery {
712
const firstChar = url.charAt(0)
8-
if (firstChar === '.' || firstChar === '~' || firstChar === '@') {
9-
if (firstChar === '~') {
10-
const secondChar = url.charAt(1)
11-
url = url.slice(secondChar === '/' ? 2 : 1)
12-
}
13+
if (firstChar === '~') {
14+
const secondChar = url.charAt(1)
15+
url = url.slice(secondChar === '/' ? 2 : 1)
1316
}
1417
return parseUriParts(url)
1518
}

0 commit comments

Comments
 (0)