2
0
Эх сурвалжийг харах

fix(compiler-sfc): transformAssetUrl should ignore inline data url (#1431)

underfin 6 жил өмнө
parent
commit
90c285c5c8

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

@@ -32,7 +32,8 @@ export function render(_ctx, _cache) {
     _createVNode(\\"img\\", { src: _imports_1 }),
     _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: \\"http://example.com/fixtures/logo.png\\" }),
-    _createVNode(\\"img\\", { src: \\"/fixtures/logo.png\\" })
+    _createVNode(\\"img\\", { src: \\"/fixtures/logo.png\\" }),
+    _createVNode(\\"img\\", { src: \\"data:image/png;base64,i\\" })
   ], 64 /* STABLE_FRAGMENT */))
   ], 64 /* STABLE_FRAGMENT */))
 }"
 }"
 `;
 `;

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

@@ -55,6 +55,10 @@ export function render(_ctx, _cache) {
     _createVNode(\\"img\\", {
     _createVNode(\\"img\\", {
       src: \\"/logo.png\\",
       src: \\"/logo.png\\",
       srcset: _hoisted_8
       srcset: _hoisted_8
+    }),
+    _createVNode(\\"img\\", {
+      src: \\"data:image/png;base64,i\\",
+      srcset: \\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\"
     })
     })
   ], 64 /* STABLE_FRAGMENT */))
   ], 64 /* STABLE_FRAGMENT */))
 }"
 }"
@@ -104,6 +108,10 @@ export function render(_ctx, _cache) {
     _createVNode(\\"img\\", {
     _createVNode(\\"img\\", {
       src: \\"/logo.png\\",
       src: \\"/logo.png\\",
       srcset: \\"/logo.png, /foo/logo.png 2x\\"
       srcset: \\"/logo.png, /foo/logo.png 2x\\"
+    }),
+    _createVNode(\\"img\\", {
+      src: \\"data:image/png;base64,i\\",
+      srcset: \\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\"
     })
     })
   ], 64 /* STABLE_FRAGMENT */))
   ], 64 /* STABLE_FRAGMENT */))
 }"
 }"
@@ -125,6 +133,7 @@ const _hoisted_7 = _imports_0 + ', ' + _imports_0 + '2x, ' + _imports_0 + '3x'
 const _hoisted_8 = _imports_1 + ', ' + _imports_1 + '2x'
 const _hoisted_8 = _imports_1 + ', ' + _imports_1 + '2x'
 const _hoisted_9 = \\"https://example.com/logo.png\\" + ', ' + \\"https://example.com/logo.png\\" + '2x'
 const _hoisted_9 = \\"https://example.com/logo.png\\" + ', ' + \\"https://example.com/logo.png\\" + '2x'
 const _hoisted_10 = _imports_1 + ', ' + _imports_0 + '2x'
 const _hoisted_10 = _imports_1 + ', ' + _imports_0 + '2x'
+const _hoisted_11 = \\"data:image/png;base64,i\\" + '1x, ' + \\"data:image/png;base64,i\\" + '2x'
 
 
 export function render(_ctx, _cache) {
 export function render(_ctx, _cache) {
   return (_openBlock(), _createBlock(_Fragment, null, [
   return (_openBlock(), _createBlock(_Fragment, null, [
@@ -167,6 +176,10 @@ export function render(_ctx, _cache) {
     _createVNode(\\"img\\", {
     _createVNode(\\"img\\", {
       src: \\"/logo.png\\",
       src: \\"/logo.png\\",
       srcset: _hoisted_10
       srcset: _hoisted_10
+    }),
+    _createVNode(\\"img\\", {
+      src: \\"data:image/png;base64,i\\",
+      srcset: _hoisted_11
     })
     })
   ], 64 /* STABLE_FRAGMENT */))
   ], 64 /* STABLE_FRAGMENT */))
 }"
 }"

+ 1 - 0
packages/compiler-sfc/__tests__/templateTransformAssetUrl.spec.ts

@@ -30,6 +30,7 @@ describe('compiler sfc: transform asset url', () => {
 			<img src="~/fixtures/logo.png"/>
 			<img src="~/fixtures/logo.png"/>
 			<img src="http://example.com/fixtures/logo.png"/>
 			<img src="http://example.com/fixtures/logo.png"/>
 			<img src="/fixtures/logo.png"/>
 			<img src="/fixtures/logo.png"/>
+			<img src="data:image/png;base64,i"/>
 		`)
 		`)
 
 
     expect(result.code).toMatchSnapshot()
     expect(result.code).toMatchSnapshot()

+ 1 - 0
packages/compiler-sfc/__tests__/templateTransformSrcset.spec.ts

@@ -35,6 +35,7 @@ const src = `
 <img src="/logo.png" srcset="/logo.png, /logo.png 2x"/>
 <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="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"/>
 <img src="/logo.png" srcset="/logo.png, ./logo.png 2x"/>
+<img src="data:image/png;base64,i" srcset="data:image/png;base64,i 1x, data:image/png;base64,i 2x"/>
 `
 `
 
 
 describe('compiler sfc: transform srcset', () => {
 describe('compiler sfc: transform srcset', () => {

+ 16 - 1
packages/compiler-sfc/__tests__/templateUtils.spec.ts

@@ -1,6 +1,7 @@
 import {
 import {
   isRelativeUrl,
   isRelativeUrl,
-  isExternalUrl
+  isExternalUrl,
+  isDataUrl
 } from '../../compiler-sfc/src/templateUtils'
 } from '../../compiler-sfc/src/templateUtils'
 
 
 describe('compiler sfc:templateUtils isRelativeUrl', () => {
 describe('compiler sfc:templateUtils isRelativeUrl', () => {
@@ -36,3 +37,17 @@ describe('compiler sfc:templateUtils isExternalUrl', () => {
     expect(result).toBe(true)
     expect(result).toBe(true)
   })
   })
 })
 })
+
+describe('compiler sfc:templateUtils isDataUrl', () => {
+  test('should return true w/ hasn`t media type and encode', () => {
+    expect(isDataUrl('data:,i')).toBe(true)
+  })
+
+  test('should return true w/ media type + encode', () => {
+    expect(isDataUrl('data:image/png;base64,i')).toBe(true)
+  })
+
+  test('should return true w/ media type + hasn`t encode', () => {
+    expect(isDataUrl('data:image/png,i')).toBe(true)
+  })
+})

+ 7 - 1
packages/compiler-sfc/src/templateTransformAssetUrl.ts

@@ -7,7 +7,12 @@ import {
   SourceLocation,
   SourceLocation,
   TransformContext
   TransformContext
 } from '@vue/compiler-core'
 } from '@vue/compiler-core'
-import { isRelativeUrl, parseUrl, isExternalUrl } from './templateUtils'
+import {
+  isRelativeUrl,
+  parseUrl,
+  isExternalUrl,
+  isDataUrl
+} from './templateUtils'
 import { isArray } from '@vue/shared'
 import { isArray } from '@vue/shared'
 
 
 export interface AssetURLTagConfig {
 export interface AssetURLTagConfig {
@@ -99,6 +104,7 @@ export const transformAssetUrl: NodeTransform = (
         !assetAttrs.includes(attr.name) ||
         !assetAttrs.includes(attr.name) ||
         !attr.value ||
         !attr.value ||
         isExternalUrl(attr.value.content) ||
         isExternalUrl(attr.value.content) ||
+        isDataUrl(attr.value.content) ||
         attr.value.content[0] === '#' ||
         attr.value.content[0] === '#' ||
         (!options.includeAbsolute && !isRelativeUrl(attr.value.content))
         (!options.includeAbsolute && !isRelativeUrl(attr.value.content))
       ) {
       ) {

+ 16 - 1
packages/compiler-sfc/src/templateTransformSrcset.ts

@@ -6,7 +6,12 @@ import {
   NodeTypes,
   NodeTypes,
   SimpleExpressionNode
   SimpleExpressionNode
 } from '@vue/compiler-core'
 } from '@vue/compiler-core'
-import { isRelativeUrl, parseUrl, isExternalUrl } from './templateUtils'
+import {
+  isRelativeUrl,
+  parseUrl,
+  isExternalUrl,
+  isDataUrl
+} from './templateUtils'
 import {
 import {
   AssetURLOptions,
   AssetURLOptions,
   defaultAssetUrlOptions
   defaultAssetUrlOptions
@@ -51,6 +56,15 @@ export const transformSrcset: NodeTransform = (
             return { url, descriptor }
             return { url, descriptor }
           })
           })
 
 
+          // for data url need recheck url
+          for (let i = 0; i < imageCandidates.length; i++) {
+            if (imageCandidates[i].url.trim().startsWith('data:')) {
+              imageCandidates[i + 1].url =
+                imageCandidates[i].url + ',' + imageCandidates[i + 1].url
+              imageCandidates.splice(i, 1)
+            }
+          }
+
           // When srcset does not contain any relative URLs, skip transforming
           // When srcset does not contain any relative URLs, skip transforming
           if (
           if (
             !options.includeAbsolute &&
             !options.includeAbsolute &&
@@ -78,6 +92,7 @@ export const transformSrcset: NodeTransform = (
           imageCandidates.forEach(({ url, descriptor }, index) => {
           imageCandidates.forEach(({ url, descriptor }, index) => {
             if (
             if (
               !isExternalUrl(url) &&
               !isExternalUrl(url) &&
+              !isDataUrl(url) &&
               (options.includeAbsolute || isRelativeUrl(url))
               (options.includeAbsolute || isRelativeUrl(url))
             ) {
             ) {
               const { path } = parseUrl(url)
               const { path } = parseUrl(url)

+ 5 - 0
packages/compiler-sfc/src/templateUtils.ts

@@ -11,6 +11,11 @@ export function isExternalUrl(url: string): boolean {
   return externalRE.test(url)
   return externalRE.test(url)
 }
 }
 
 
+const dataUrlRE = /^\s*data:/i
+export function isDataUrl(url: string): boolean {
+  return dataUrlRE.test(url)
+}
+
 /**
 /**
  * Parses string url into URL object.
  * Parses string url into URL object.
  */
  */