Skip to content

Commit ad83bdf

Browse files
authored
feat: asset handling for support vite dev. (#90)
1 parent f7bfc16 commit ad83bdf

File tree

5 files changed

+105
-24
lines changed

5 files changed

+105
-24
lines changed

lib/compileTemplate.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
} from './types'
66

77
import assetUrlsModule, {
8-
AssetURLOptions
8+
AssetURLOptions,
9+
TransformAssetUrlsOptions
910
} from './templateCompilerModules/assetUrl'
1011
import srcsetModule from './templateCompilerModules/srcset'
1112

@@ -18,6 +19,7 @@ export interface TemplateCompileOptions {
1819
compiler: VueTemplateCompiler
1920
compilerOptions?: VueTemplateCompilerOptions
2021
transformAssetUrls?: AssetURLOptions | boolean
22+
transformAssetUrlsOptions?: TransformAssetUrlsOptions
2123
preprocessLang?: string
2224
preprocessOptions?: any
2325
transpileOptions?: any
@@ -103,6 +105,7 @@ function actuallyCompile(
103105
compilerOptions = {},
104106
transpileOptions = {},
105107
transformAssetUrls,
108+
transformAssetUrlsOptions,
106109
isProduction = process.env.NODE_ENV === 'production',
107110
isFunctional = false,
108111
optimizeSSR = false,
@@ -116,9 +119,9 @@ function actuallyCompile(
116119
if (transformAssetUrls) {
117120
const builtInModules = [
118121
transformAssetUrls === true
119-
? assetUrlsModule()
120-
: assetUrlsModule(transformAssetUrls),
121-
srcsetModule()
122+
? assetUrlsModule(undefined, transformAssetUrlsOptions)
123+
: assetUrlsModule(transformAssetUrls, transformAssetUrlsOptions),
124+
srcsetModule(transformAssetUrlsOptions)
122125
]
123126
finalCompilerOptions = Object.assign({}, compilerOptions, {
124127
modules: [...builtInModules, ...(compilerOptions.modules || [])],

lib/templateCompilerModules/assetUrl.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ export interface AssetURLOptions {
66
[name: string]: string | string[]
77
}
88

9+
export interface TransformAssetUrlsOptions {
10+
/**
11+
* If base is provided, instead of transforming relative asset urls into
12+
* imports, they will be directly rewritten to absolute urls.
13+
*/
14+
base?: string
15+
}
16+
917
const defaultOptions: AssetURLOptions = {
1018
audio: 'src',
1119
video: ['src', 'poster'],
@@ -15,37 +23,52 @@ const defaultOptions: AssetURLOptions = {
1523
use: ['xlink:href', 'href']
1624
}
1725

18-
export default (userOptions?: AssetURLOptions) => {
26+
export default (
27+
userOptions?: AssetURLOptions,
28+
transformAssetUrlsOption?: TransformAssetUrlsOptions
29+
) => {
1930
const options = userOptions
2031
? Object.assign({}, defaultOptions, userOptions)
2132
: defaultOptions
2233

2334
return {
2435
postTransformNode: (node: ASTNode) => {
25-
transform(node, options)
36+
transform(node, options, transformAssetUrlsOption)
2637
}
2738
}
2839
}
2940

30-
function transform(node: ASTNode, options: AssetURLOptions) {
41+
function transform(
42+
node: ASTNode,
43+
options: AssetURLOptions,
44+
transformAssetUrlsOption?: TransformAssetUrlsOptions
45+
) {
3146
for (const tag in options) {
3247
if ((tag === '*' || node.tag === tag) && node.attrs) {
3348
const attributes = options[tag]
3449
if (typeof attributes === 'string') {
35-
node.attrs.some(attr => rewrite(attr, attributes))
50+
node.attrs.some(attr =>
51+
rewrite(attr, attributes, transformAssetUrlsOption)
52+
)
3653
} else if (Array.isArray(attributes)) {
37-
attributes.forEach(item => node.attrs.some(attr => rewrite(attr, item)))
54+
attributes.forEach(item =>
55+
node.attrs.some(attr => rewrite(attr, item, transformAssetUrlsOption))
56+
)
3857
}
3958
}
4059
}
4160
}
4261

43-
function rewrite(attr: Attr, name: string) {
62+
function rewrite(
63+
attr: Attr,
64+
name: string,
65+
transformAssetUrlsOption?: TransformAssetUrlsOptions
66+
) {
4467
if (attr.name === name) {
4568
const value = attr.value
4669
// only transform static URLs
4770
if (value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
48-
attr.value = urlToRequire(value.slice(1, -1))
71+
attr.value = urlToRequire(value.slice(1, -1), transformAssetUrlsOption)
4972
return true
5073
}
5174
}

lib/templateCompilerModules/srcset.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
// vue compiler module for transforming `img:srcset` to a number of `require`s
22

33
import { urlToRequire, ASTNode } from './utils'
4+
import { TransformAssetUrlsOptions } from './assetUrl'
45

56
interface ImageCandidate {
67
require: string
78
descriptor: string
89
}
910

10-
export default () => ({
11+
export default (transformAssetUrlsOptions?: TransformAssetUrlsOptions) => ({
1112
postTransformNode: (node: ASTNode) => {
12-
transform(node)
13+
transform(node, transformAssetUrlsOptions)
1314
}
1415
})
1516

1617
// http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5
1718
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g
1819

19-
function transform(node: ASTNode) {
20+
function transform(
21+
node: ASTNode,
22+
transformAssetUrlsOptions?: TransformAssetUrlsOptions
23+
) {
2024
const tags = ['img', 'source']
2125

2226
if (tags.indexOf(node.tag) !== -1 && node.attrs) {
@@ -40,7 +44,10 @@ function transform(node: ASTNode) {
4044
.replace(escapedSpaceCharacters, ' ')
4145
.trim()
4246
.split(' ', 2)
43-
return { require: urlToRequire(url), descriptor }
47+
return {
48+
require: urlToRequire(url, transformAssetUrlsOptions),
49+
descriptor
50+
}
4451
})
4552

4653
// "require(url1)"

lib/templateCompilerModules/utils.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { TransformAssetUrlsOptions } from './assetUrl'
2+
import { UrlWithStringQuery, parse as uriParse } from 'url'
3+
import path from 'path'
4+
15
export interface Attr {
26
name: string
37
value: string
@@ -8,20 +12,36 @@ export interface ASTNode {
812
attrs: Attr[]
913
}
1014

11-
import { UrlWithStringQuery, parse as uriParse } from 'url'
12-
13-
export function urlToRequire(url: string): string {
15+
export function urlToRequire(
16+
url: string,
17+
transformAssetUrlsOption: TransformAssetUrlsOptions = {}
18+
): string {
1419
const returnValue = `"${url}"`
1520
// same logic as in transform-require.js
1621
const firstChar = url.charAt(0)
17-
if (firstChar === '.' || firstChar === '~' || firstChar === '@') {
18-
if (firstChar === '~') {
19-
const secondChar = url.charAt(1)
20-
url = url.slice(secondChar === '/' ? 2 : 1)
21-
}
22+
if (firstChar === '~') {
23+
const secondChar = url.charAt(1)
24+
url = url.slice(secondChar === '/' ? 2 : 1)
25+
}
2226

23-
const uriParts = parseUriParts(url)
27+
const uriParts = parseUriParts(url)
2428

29+
if (transformAssetUrlsOption.base) {
30+
// explicit base - directly rewrite the url into absolute url
31+
// does not apply to absolute urls or urls that start with `@`
32+
// since they are aliases
33+
if (firstChar === '.' || firstChar === '~') {
34+
// when packaged in the browser, path will be using the posix-
35+
// only version provided by rollup-plugin-node-builtins.
36+
return `"${(path.posix || path).join(
37+
transformAssetUrlsOption.base,
38+
uriParts.path + (uriParts.hash || '')
39+
)}"`
40+
}
41+
return returnValue
42+
}
43+
44+
if (firstChar === '.' || firstChar === '~' || firstChar === '@') {
2545
if (!uriParts.hash) {
2646
return `require("${url}")`
2747
} else {

test/compileTemplate.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,31 @@ test('transform srcset', () => {
204204
)
205205
expect(vnode.children[18].data.attrs.srcset).toBe('test-url 2x, test-url 3x')
206206
})
207+
208+
test('transform assetUrls and srcset with base option', () => {
209+
const source = `
210+
<div>
211+
<img src="./logo.png">
212+
<img src="~fixtures/logo.png">
213+
<img src="~/fixtures/logo.png">
214+
<img src="./logo.png" srcset="./logo.png 2x, ./logo.png 3x">
215+
</div>
216+
`
217+
const result = compileTemplate({
218+
compiler: compiler as VueTemplateCompiler,
219+
filename: 'example.vue',
220+
source,
221+
transformAssetUrls: true,
222+
transformAssetUrlsOptions: { base: '/base/' }
223+
})
224+
225+
expect(result.errors.length).toBe(0)
226+
227+
const vnode = mockRender(result.code)
228+
expect(vnode.children[0].data.attrs.src).toBe('/base/logo.png')
229+
expect(vnode.children[2].data.attrs.src).toBe('/base/fixtures/logo.png')
230+
expect(vnode.children[4].data.attrs.src).toBe('/base/fixtures/logo.png')
231+
expect(vnode.children[6].data.attrs.srcset).toBe(
232+
'/base/logo.png 2x, /base/logo.png 3x'
233+
)
234+
})

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy