fix(compiler-sfc): only transform relative asset URLs (#628)

This commit is contained in:
Sören Schwert
2020-01-20 15:57:17 +01:00
committed by Evan You
parent 787ac5f74e
commit c71ca354b9
8 changed files with 67 additions and 30 deletions

View File

@@ -7,7 +7,7 @@ import {
SourceLocation,
TransformContext
} from '@vue/compiler-core'
import { parseUrl } from './templateUtils'
import { isRelativeUrl, parseUrl } from './templateUtils'
export interface AssetURLOptions {
[name: string]: string[]
@@ -46,6 +46,7 @@ export const transformAssetUrl: NodeTransform = (
if (attr.type !== NodeTypes.ATTRIBUTE) return
if (attr.name !== item) return
if (!attr.value) return
if (!isRelativeUrl(attr.value.content)) return
const url = parseUrl(attr.value.content)
const exp = getImportsExpressionExp(
url.path,

View File

@@ -5,7 +5,7 @@ import {
NodeTypes,
SimpleExpressionNode
} from '@vue/compiler-core'
import { parseUrl } from './templateUtils'
import { isRelativeUrl, parseUrl } from './templateUtils'
const srcsetTags = ['img', 'source']
@@ -36,31 +36,44 @@ export const transformSrcset: NodeTransform = (node, context) => {
return { url, descriptor }
})
// When srcset does not contain any relative URLs, skip transforming
if (!imageCandidates.some(({ url }) => isRelativeUrl(url))) return
const compoundExpression = createCompoundExpression([], attr.loc)
imageCandidates.forEach(({ url, descriptor }, index) => {
const { path } = parseUrl(url)
let exp: SimpleExpressionNode
if (path) {
const importsArray = Array.from(context.imports)
const existingImportsIndex = importsArray.findIndex(
i => i.path === path
)
if (existingImportsIndex > -1) {
exp = createSimpleExpression(
`_imports_${existingImportsIndex}`,
false,
attr.loc,
true
if (isRelativeUrl(url)) {
const { path } = parseUrl(url)
let exp: SimpleExpressionNode
if (path) {
const importsArray = Array.from(context.imports)
const existingImportsIndex = importsArray.findIndex(
i => i.path === path
)
} else {
exp = createSimpleExpression(
`_imports_${importsArray.length}`,
false,
attr.loc,
true
)
context.imports.add({ exp, path })
if (existingImportsIndex > -1) {
exp = createSimpleExpression(
`_imports_${existingImportsIndex}`,
false,
attr.loc,
true
)
} else {
exp = createSimpleExpression(
`_imports_${importsArray.length}`,
false,
attr.loc,
true
)
context.imports.add({ exp, path })
}
compoundExpression.children.push(exp)
}
} else {
const exp = createSimpleExpression(
`"${url}"`,
false,
attr.loc,
true
)
compoundExpression.children.push(exp)
}
const isNotLast = imageCandidates.length - 1 > index

View File

@@ -1,15 +1,18 @@
import { UrlWithStringQuery, parse as uriParse } from 'url'
import { isString } from '@vue/shared'
export function isRelativeUrl(url: string): boolean {
const firstChar = url.charAt(0)
return firstChar === '.' || firstChar === '~' || firstChar === '@'
}
// We need an extra transform context API for injecting arbitrary import
// statements.
export function parseUrl(url: string): UrlWithStringQuery {
const firstChar = url.charAt(0)
if (firstChar === '.' || firstChar === '~' || firstChar === '@') {
if (firstChar === '~') {
const secondChar = url.charAt(1)
url = url.slice(secondChar === '/' ? 2 : 1)
}
if (firstChar === '~') {
const secondChar = url.charAt(1)
url = url.slice(secondChar === '/' ? 2 : 1)
}
return parseUriParts(url)
}