Skip to content

Commit 7d4ab91

Browse files
feat(compiler-vapor): handle asset imports (#13630)
1 parent f4b3613 commit 7d4ab91

File tree

13 files changed

+604
-41
lines changed

13 files changed

+604
-41
lines changed

packages/compiler-core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export {
2121
type NodeTransform,
2222
type StructuralDirectiveTransform,
2323
type DirectiveTransform,
24+
type ImportItem,
2425
} from './transform'
2526
export {
2627
generate,

packages/compiler-core/src/transform.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export type StructuralDirectiveTransform = (
7777
) => void | (() => void)
7878

7979
export interface ImportItem {
80-
exp: string | ExpressionNode
80+
exp: SimpleExpressionNode
8181
path: string
8282
}
8383

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@ export function ssrRender(_ctx, _push, _parent, _attrs) {
6565
} else {
6666
return [
6767
_createVNode("picture", null, [
68-
_createVNode("source", {
69-
srcset: _imports_1
70-
}),
68+
_createVNode("source", { srcset: _imports_1 }),
7169
_createVNode("img", { src: _imports_1 })
7270
])
7371
]

packages/compiler-sfc/src/template/transformSrcset.ts

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import path from 'path'
22
import {
33
ConstantTypes,
4-
type ExpressionNode,
54
type NodeTransform,
65
NodeTypes,
7-
type SimpleExpressionNode,
8-
createCompoundExpression,
96
createSimpleExpression,
107
} from '@vue/compiler-core'
118
import {
@@ -106,55 +103,52 @@ export const transformSrcset: NodeTransform = (
106103
}
107104
}
108105

109-
const compoundExpression = createCompoundExpression([], attr.loc)
106+
let content = ''
110107
imageCandidates.forEach(({ url, descriptor }, index) => {
111108
if (shouldProcessUrl(url)) {
112109
const { path } = parseUrl(url)
113-
let exp: SimpleExpressionNode
114110
if (path) {
111+
let exp = ''
115112
const existingImportsIndex = context.imports.findIndex(
116113
i => i.path === path,
117114
)
118115
if (existingImportsIndex > -1) {
119-
exp = createSimpleExpression(
120-
`_imports_${existingImportsIndex}`,
121-
false,
122-
attr.loc,
123-
ConstantTypes.CAN_STRINGIFY,
124-
)
116+
exp = `_imports_${existingImportsIndex}`
125117
} else {
126-
exp = createSimpleExpression(
127-
`_imports_${context.imports.length}`,
128-
false,
129-
attr.loc,
130-
ConstantTypes.CAN_STRINGIFY,
131-
)
132-
context.imports.push({ exp, path })
118+
exp = `_imports_${context.imports.length}`
119+
context.imports.push({
120+
exp: createSimpleExpression(
121+
exp,
122+
false,
123+
attr.loc,
124+
ConstantTypes.CAN_STRINGIFY,
125+
),
126+
path,
127+
})
133128
}
134-
compoundExpression.children.push(exp)
129+
content += exp
135130
}
136131
} else {
137-
const exp = createSimpleExpression(
138-
`"${url}"`,
139-
false,
140-
attr.loc,
141-
ConstantTypes.CAN_STRINGIFY,
142-
)
143-
compoundExpression.children.push(exp)
132+
content += `"${url}"`
144133
}
145134
const isNotLast = imageCandidates.length - 1 > index
146-
if (descriptor && isNotLast) {
147-
compoundExpression.children.push(` + ' ${descriptor}, ' + `)
148-
} else if (descriptor) {
149-
compoundExpression.children.push(` + ' ${descriptor}'`)
135+
if (descriptor) {
136+
content += ` + ' ${descriptor}${isNotLast ? ', ' : ''}'${
137+
isNotLast ? ' + ' : ''
138+
}`
150139
} else if (isNotLast) {
151-
compoundExpression.children.push(` + ', ' + `)
140+
content += ` + ', ' + `
152141
}
153142
})
154143

155-
let exp: ExpressionNode = compoundExpression
144+
let exp = createSimpleExpression(
145+
content,
146+
false,
147+
attr.loc,
148+
ConstantTypes.CAN_STRINGIFY,
149+
)
156150
if (context.hoistStatic) {
157-
exp = context.hoist(compoundExpression)
151+
exp = context.hoist(exp)
158152
exp.constType = ConstantTypes.CAN_STRINGIFY
159153
}
160154

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`compiler sfc: transform asset url > should allow for full base URLs, with paths 1`] = `
4+
"import { template as _template } from 'vue';
5+
const t0 = _template("<img src=\\"http://localhost:3000/src/logo.png\\">", true)
6+
7+
export function render(_ctx) {
8+
const n0 = t0()
9+
return n0
10+
}"
11+
`;
12+
13+
exports[`compiler sfc: transform asset url > should allow for full base URLs, without paths 1`] = `
14+
"import { template as _template } from 'vue';
15+
const t0 = _template("<img src=\\"http://localhost:3000/logo.png\\">", true)
16+
17+
export function render(_ctx) {
18+
const n0 = t0()
19+
return n0
20+
}"
21+
`;
22+
23+
exports[`compiler sfc: transform asset url > should allow for full base URLs, without port 1`] = `
24+
"import { template as _template } from 'vue';
25+
const t0 = _template("<img src=\\"http://localhost/logo.png\\">", true)
26+
27+
export function render(_ctx) {
28+
const n0 = t0()
29+
return n0
30+
}"
31+
`;
32+
33+
exports[`compiler sfc: transform asset url > should allow for full base URLs, without protocol 1`] = `
34+
"import { template as _template } from 'vue';
35+
const t0 = _template("<img src=\\"//localhost/logo.png\\">", true)
36+
37+
export function render(_ctx) {
38+
const n0 = t0()
39+
return n0
40+
}"
41+
`;
42+
43+
exports[`compiler sfc: transform asset url > support uri fragment 1`] = `
44+
"import { template as _template } from 'vue';
45+
import _imports_0 from '@svg/file.svg';
46+
const t0 = _template("<use href=\\"" + _imports_0 + '#fragment' + "\\"></use>", false, 1)
47+
48+
export function render(_ctx) {
49+
const n0 = t0()
50+
const n1 = t0()
51+
return [n0, n1]
52+
}"
53+
`;
54+
55+
exports[`compiler sfc: transform asset url > support uri is empty 1`] = `
56+
"import { template as _template } from 'vue';
57+
const t0 = _template("<use href=\\"\\"></use>", true, 1)
58+
59+
export function render(_ctx) {
60+
const n0 = t0()
61+
return n0
62+
}"
63+
`;
64+
65+
exports[`compiler sfc: transform asset url > transform assetUrls 1`] = `
66+
"import { template as _template } from 'vue';
67+
import _imports_0 from './logo.png';
68+
import _imports_1 from 'fixtures/logo.png';
69+
import _imports_2 from '/fixtures/logo.png';
70+
const t0 = _template("<img src=\\"" + _imports_0 + "\\">")
71+
const t1 = _template("<img src=\\"" + _imports_1 + "\\">")
72+
const t2 = _template("<img src=\\"http://example.com/fixtures/logo.png\\">")
73+
const t3 = _template("<img src=\\"//example.com/fixtures/logo.png\\">")
74+
const t4 = _template("<img src=\\"" + _imports_2 + "\\">")
75+
const t5 = _template("<img src=\\"data:image/png;base64,i\\">")
76+
77+
export function render(_ctx) {
78+
const n0 = t0()
79+
const n1 = t1()
80+
const n2 = t1()
81+
const n3 = t2()
82+
const n4 = t3()
83+
const n5 = t4()
84+
const n6 = t5()
85+
return [n0, n1, n2, n3, n4, n5, n6]
86+
}"
87+
`;
88+
89+
exports[`compiler sfc: transform asset url > transform with stringify 1`] = `
90+
"import { template as _template } from 'vue';
91+
import _imports_0 from './bar.png';
92+
import _imports_1 from '/bar.png';
93+
const t0 = _template("<div><img src=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_1 + "\\"><img src=\\"https://foo.bar/baz.png\\"><img src=\\"//foo.bar/baz.png\\"><img src=\\"" + _imports_0 + "\\"></div>", true)
94+
95+
export function render(_ctx) {
96+
const n0 = t0()
97+
return n0
98+
}"
99+
`;
100+
101+
exports[`compiler sfc: transform asset url > with explicit base 1`] = `
102+
"import { template as _template } from 'vue';
103+
import _imports_0 from 'bar.png';
104+
import _imports_1 from '@theme/bar.png';
105+
const t0 = _template("<img src=\\"/foo/bar.png\\">")
106+
const t1 = _template("<img src=\\"" + _imports_0 + "\\">")
107+
const t2 = _template("<img src=\\"" + _imports_1 + "\\">")
108+
109+
export function render(_ctx) {
110+
const n0 = t0()
111+
const n1 = t1()
112+
const n2 = t1()
113+
const n3 = t2()
114+
return [n0, n1, n2, n3]
115+
}"
116+
`;
117+
118+
exports[`compiler sfc: transform asset url > with includeAbsolute: true 1`] = `
119+
"import { template as _template } from 'vue';
120+
import _imports_0 from './bar.png';
121+
import _imports_1 from '/bar.png';
122+
const t0 = _template("<img src=\\"" + _imports_0 + "\\">")
123+
const t1 = _template("<img src=\\"" + _imports_1 + "\\">")
124+
const t2 = _template("<img src=\\"https://foo.bar/baz.png\\">")
125+
const t3 = _template("<img src=\\"//foo.bar/baz.png\\">")
126+
127+
export function render(_ctx) {
128+
const n0 = t0()
129+
const n1 = t1()
130+
const n2 = t2()
131+
const n3 = t3()
132+
return [n0, n1, n2, n3]
133+
}"
134+
`;
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2+
3+
exports[`compiler sfc: transform srcset > srcset w/ explicit base option 1`] = `
4+
"import { template as _template } from 'vue';
5+
import _imports_0 from '@/logo.png';
6+
import _imports_1 from '/foo/logo.png';
7+
const t0 = _template("<img srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\">")
8+
const t1 = _template("<img srcset=\\"" + _imports_0 + ' 1x, ' + _imports_1 + ' 2x' + "\\">")
9+
10+
export function render(_ctx) {
11+
const n0 = t0()
12+
const n1 = t1()
13+
return [n0, n1]
14+
}"
15+
`;
16+
17+
exports[`compiler sfc: transform srcset > transform srcset 1`] = `
18+
"import { template as _template } from 'vue';
19+
import _imports_0 from './logo.png';
20+
import _imports_1 from '/logo.png';
21+
const t0 = _template("<img src=\\"" + _imports_0 + "\\" srcset>")
22+
const t1 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + "\\">")
23+
const t2 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x' + "\\">")
24+
const t3 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\">")
25+
const t4 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + "\\">")
26+
const t5 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\">")
27+
const t6 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\">")
28+
const t7 = _template("<img src=\\"" + _imports_1 + "\\" srcset=\\"" + _imports_1 + ', ' + _imports_1 + ' 2x' + "\\">")
29+
const t8 = _template("<img src=\\"https://example.com/logo.png\\" srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\">")
30+
const t9 = _template("<img src=\\"" + _imports_1 + "\\" srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\">")
31+
const t10 = _template("<img src=\\"data:image/png;base64,i\\" srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
32+
33+
export function render(_ctx) {
34+
const n0 = t0()
35+
const n1 = t1()
36+
const n2 = t2()
37+
const n3 = t2()
38+
const n4 = t3()
39+
const n5 = t4()
40+
const n6 = t5()
41+
const n7 = t6()
42+
const n8 = t7()
43+
const n9 = t8()
44+
const n10 = t9()
45+
const n11 = t10()
46+
return [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11]
47+
}"
48+
`;
49+
50+
exports[`compiler sfc: transform srcset > transform srcset w/ base 1`] = `
51+
"import { template as _template } from 'vue';
52+
import _imports_0 from '/logo.png';
53+
import _imports_1 from '/foo/logo.png';
54+
const t0 = _template("<img src=\\"/foo/logo.png\\" srcset>")
55+
const t1 = _template("<img src=\\"/foo/logo.png\\" srcset=\\"/foo/logo.png\\">")
56+
const t2 = _template("<img src=\\"/foo/logo.png\\" srcset=\\"/foo/logo.png 2x\\">")
57+
const t3 = _template("<img src=\\"/foo/logo.png\\" srcset=\\"/foo/logo.png, /foo/logo.png 2x\\">")
58+
const t4 = _template("<img src=\\"/foo/logo.png\\" srcset=\\"/foo/logo.png 2x, /foo/logo.png\\">")
59+
const t5 = _template("<img src=\\"/foo/logo.png\\" srcset=\\"/foo/logo.png 2x, /foo/logo.png 3x\\">")
60+
const t6 = _template("<img src=\\"/foo/logo.png\\" srcset=\\"/foo/logo.png, /foo/logo.png 2x, /foo/logo.png 3x\\">")
61+
const t7 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\">")
62+
const t8 = _template("<img src=\\"https://example.com/logo.png\\" srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\">")
63+
const t9 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_1 + ' 2x' + "\\">")
64+
const t10 = _template("<img src=\\"data:image/png;base64,i\\" srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
65+
66+
export function render(_ctx) {
67+
const n0 = t0()
68+
const n1 = t1()
69+
const n2 = t2()
70+
const n3 = t2()
71+
const n4 = t3()
72+
const n5 = t4()
73+
const n6 = t5()
74+
const n7 = t6()
75+
const n8 = t7()
76+
const n9 = t8()
77+
const n10 = t9()
78+
const n11 = t10()
79+
return [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11]
80+
}"
81+
`;
82+
83+
exports[`compiler sfc: transform srcset > transform srcset w/ includeAbsolute: true 1`] = `
84+
"import { template as _template } from 'vue';
85+
import _imports_0 from './logo.png';
86+
import _imports_1 from '/logo.png';
87+
const t0 = _template("<img src=\\"" + _imports_0 + "\\" srcset>")
88+
const t1 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + "\\">")
89+
const t2 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x' + "\\">")
90+
const t3 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\">")
91+
const t4 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + "\\">")
92+
const t5 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\">")
93+
const t6 = _template("<img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\">")
94+
const t7 = _template("<img src=\\"" + _imports_1 + "\\" srcset=\\"" + _imports_1 + ', ' + _imports_1 + ' 2x' + "\\">")
95+
const t8 = _template("<img src=\\"https://example.com/logo.png\\" srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\">")
96+
const t9 = _template("<img src=\\"" + _imports_1 + "\\" srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\">")
97+
const t10 = _template("<img src=\\"data:image/png;base64,i\\" srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\">")
98+
99+
export function render(_ctx) {
100+
const n0 = t0()
101+
const n1 = t1()
102+
const n2 = t2()
103+
const n3 = t2()
104+
const n4 = t3()
105+
const n5 = t4()
106+
const n6 = t5()
107+
const n7 = t6()
108+
const n8 = t7()
109+
const n9 = t8()
110+
const n10 = t9()
111+
const n11 = t10()
112+
return [n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11]
113+
}"
114+
`;
115+
116+
exports[`compiler sfc: transform srcset > transform srcset w/ stringify 1`] = `
117+
"import { template as _template } from 'vue';
118+
import _imports_0 from './logo.png';
119+
import _imports_1 from '/logo.png';
120+
const t0 = _template("<div><img src=\\"" + _imports_0 + "\\" srcset><img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + "\\"><img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x' + "\\"><img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + "\\"><img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\"><img src=\\"" + _imports_0 + "\\" srcset=\\"" + _imports_0 + ', ' + _imports_0 + ' 2x, ' + _imports_0 + ' 3x' + "\\"><img src=\\"" + _imports_1 + "\\" srcset=\\"" + _imports_1 + ', ' + _imports_1 + ' 2x' + "\\"><img src=\\"https://example.com/logo.png\\" srcset=\\"https://example.com/logo.png, https://example.com/logo.png 2x\\"><img src=\\"" + _imports_1 + "\\" srcset=\\"" + _imports_1 + ', ' + _imports_0 + ' 2x' + "\\"><img src=\\"data:image/png;base64,i\\" srcset=\\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\"></div>", true)
121+
122+
export function render(_ctx) {
123+
const n0 = t0()
124+
return n0
125+
}"
126+
`;

0 commit comments

Comments
 (0)