]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): only transform relative asset URLs (#628)
authorSören Schwert <hello@soerenschwert.de>
Mon, 20 Jan 2020 14:57:17 +0000 (15:57 +0100)
committerEvan You <yyx990803@gmail.com>
Mon, 20 Jan 2020 14:57:17 +0000 (09:57 -0500)
packages/compiler-sfc/__tests__/__snapshots__/templateTransformAssetUrl.spec.ts.snap
packages/compiler-sfc/__tests__/__snapshots__/templateTransformSrcset.spec.ts.snap
packages/compiler-sfc/__tests__/compileTemplate.spec.ts
packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts
packages/compiler-sfc/__tests__/templateTransformSrcset.spec.ts
packages/compiler-sfc/src/templateTransformAssetUrl.ts
packages/compiler-sfc/src/templateTransformSrcset.ts
packages/compiler-sfc/src/templateUtils.ts

index d6d255caf55877a627c1fdbcb74173c0b2c1b3d8..5fc06681fe2739779cf29e2e357043953929f995 100644 (file)
@@ -33,7 +33,9 @@ export function render() {
   return (openBlock(), createBlock(Fragment, null, [
     createVNode(\\"img\\", { src: _imports_0 }),
     createVNode(\\"img\\", { src: _imports_1 }),
-    createVNode(\\"img\\", { src: _imports_1 })
+    createVNode(\\"img\\", { src: _imports_1 }),
+    createVNode(\\"img\\", { src: \\"http://example.com/fixtures/logo.png\\" }),
+    createVNode(\\"img\\", { src: \\"/fixtures/logo.png\\" })
   ], 64 /* STABLE_FRAGMENT */))
 }"
 `;
index 78c4bffabfd72e41c7158e40d530b90eaf137381..64801570ffe307a3b93557e54bff3d4cec45309b 100644 (file)
@@ -12,6 +12,7 @@ const _hoisted_4 = _imports_0 + ', ' + _imports_0 + '2x'
 const _hoisted_5 = _imports_0 + '2x, ' + _imports_0
 const _hoisted_6 = _imports_0 + '2x, ' + _imports_0 + '3x'
 const _hoisted_7 = _imports_0 + ', ' + _imports_0 + '2x, ' + _imports_0 + '3x'
+const _hoisted_8 = \\"/logo.png\\" + ', ' + _imports_0 + '2x'
 
 export function render() {
   const _ctx = this
@@ -43,6 +44,18 @@ export function render() {
     createVNode(\\"img\\", {
       src: \\"./logo.png\\",
       srcset: _hoisted_7
+    }),
+    createVNode(\\"img\\", {
+      src: \\"/logo.png\\",
+      srcset: \\"/logo.png, /logo.png 2x\\"
+    }),
+    createVNode(\\"img\\", {
+      src: \\"https://example.com/logo.png\\",
+      srcset: \\"https://example.com/logo.png, https://example.com/logo.png 2x\\"
+    }),
+    createVNode(\\"img\\", {
+      src: \\"/logo.png\\",
+      srcset: _hoisted_8
     })
   ], 64 /* STABLE_FRAGMENT */))
 }"
index fa86618b1869f11a150b27e7843f2b4bf32d5191..2217f069c0b9b0261bbbea079a5281a51b8b41ab 100644 (file)
@@ -50,7 +50,7 @@ test('warn missing preprocessor', () => {
 })
 
 test('transform asset url options', () => {
-  const input = { source: `<foo bar="baz"/>`, filename: 'example.vue' }
+  const input = { source: `<foo bar="~baz"/>`, filename: 'example.vue' }
   // Object option
   const { code: code1 } = compileTemplate({
     ...input,
index 9adbd1a623372e882501945fa9e24c2dbaaf6c47..40531d780b49b95a0ac0930faed798e790ccc254 100644 (file)
@@ -20,6 +20,8 @@ describe('compiler sfc: transform asset url', () => {
                        <img src="./logo.png"/>
                        <img src="~fixtures/logo.png"/>
                        <img src="~/fixtures/logo.png"/>
+                       <img src="http://example.com/fixtures/logo.png"/>
+                       <img src="/fixtures/logo.png"/>
                `)
 
     expect(result.code).toMatchSnapshot()
index 660242c931bb98d164a45c8fc522c0aff90f5d1b..7b2e365493d54d6e4361bc41a9063577562ac38f 100644 (file)
@@ -24,6 +24,9 @@ describe('compiler sfc: transform srcset', () => {
                        <img src="./logo.png" srcset="./logo.png 2x, ./logo.png"/>
                        <img src="./logo.png" srcset="./logo.png 2x, ./logo.png 3x"/>
                        <img src="./logo.png" srcset="./logo.png, ./logo.png 2x, ./logo.png 3x"/>
+                       <img src="/logo.png" srcset="/logo.png, /logo.png 2x"/>
+                       <img src="https://example.com/logo.png" srcset="https://example.com/logo.png, https://example.com/logo.png 2x"/>
+                       <img src="/logo.png" srcset="/logo.png, ./logo.png 2x"/>
                `)
 
     expect(result.code).toMatchSnapshot()
index a5e943b5fda2931a63e15895bd17a37f6491bf05..e6b0c49893acb4bd2cd02cbc69ef3d94dee44e38 100644 (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,
index cf557ec255fd816a0fc94e576cf3fc09ff679ba6..dccebd9e5c689affef51943a6052cc96171efb8d 100644 (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
index bbeafd153df80ea10d232c59429b113f33a8be5b..1040571afc95821680e77844bacca5191bea8bba 100644 (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)
 }