]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-dom): stringify eligible svg content
authorEvan You <yyx990803@gmail.com>
Mon, 9 Aug 2021 18:39:40 +0000 (14:39 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 9 Aug 2021 18:39:50 +0000 (14:39 -0400)
fix #4282

packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts
packages/compiler-dom/src/transforms/stringifyStatic.ts
packages/shared/src/domAttrConfig.ts

index b9e7d81208f5c5ef1615a391ae1126e61948f15e..0923f0816c5a78b8b502adc37895d38a2c27aa54 100644 (file)
@@ -360,4 +360,28 @@ describe('stringify static html', () => {
       ]
     })
   })
+
+  test('should stringify svg', () => {
+    const svg = `<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">`
+    const repeated = `<rect width="50" height="50" fill="#C4C4C4"></rect>`
+    const { ast } = compileWithStringify(
+      `<div>${svg}${repeat(
+        repeated,
+        StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
+      )}</svg></div>`
+    )
+    expect(ast.hoists[0]).toMatchObject({
+      type: NodeTypes.JS_CALL_EXPRESSION,
+      callee: CREATE_STATIC,
+      arguments: [
+        JSON.stringify(
+          `${svg}${repeat(
+            repeated,
+            StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
+          )}</svg>`
+        ),
+        '1'
+      ]
+    })
+  })
 })
index c3e8d9419b98a0205ca3c13b055383bd730ef002..ac818ed83943b5d6fad7f781708cd9cc50ec6f91 100644 (file)
@@ -20,14 +20,16 @@ import {
   isVoidTag,
   isString,
   isSymbol,
-  isKnownAttr,
+  isKnownHtmlAttr,
   escapeHtml,
   toDisplayString,
   normalizeClass,
   normalizeStyle,
   stringifyStyle,
-  makeMap
+  makeMap,
+  isKnownSvgAttr
 } from '@vue/shared'
+import { DOMNamespaces } from '../parserOptions'
 
 export const enum StringifyThresholds {
   ELEMENT_WITH_BINDING_COUNT = 5,
@@ -138,8 +140,14 @@ const getHoistedNode = (node: TemplateChildNode) =>
   node.codegenNode.hoisted
 
 const dataAriaRE = /^(data|aria)-/
-const isStringifiableAttr = (name: string) => {
-  return isKnownAttr(name) || dataAriaRE.test(name)
+const isStringifiableAttr = (name: string, ns: DOMNamespaces) => {
+  return (
+    (ns === DOMNamespaces.HTML
+      ? isKnownHtmlAttr(name)
+      : ns === DOMNamespaces.SVG
+      ? isKnownSvgAttr(name)
+      : false) || dataAriaRE.test(name)
+  )
 }
 
 const replaceHoist = (
@@ -175,6 +183,7 @@ function analyzeNode(node: StringifiableNode): [number, number] | false {
   let ec = node.props.length > 0 ? 1 : 0 // element w/ binding count
   let bailed = false
   const bail = (): false => {
+    debugger
     bailed = true
     return false
   }
@@ -187,7 +196,10 @@ function analyzeNode(node: StringifiableNode): [number, number] | false {
     for (let i = 0; i < node.props.length; i++) {
       const p = node.props[i]
       // bail on non-attr bindings
-      if (p.type === NodeTypes.ATTRIBUTE && !isStringifiableAttr(p.name)) {
+      if (
+        p.type === NodeTypes.ATTRIBUTE &&
+        !isStringifiableAttr(p.name, node.ns)
+      ) {
         return bail()
       }
       if (p.type === NodeTypes.DIRECTIVE && p.name === 'bind') {
@@ -195,7 +207,7 @@ function analyzeNode(node: StringifiableNode): [number, number] | false {
         if (
           p.arg &&
           (p.arg.type === NodeTypes.COMPOUND_EXPRESSION ||
-            (p.arg.isStatic && !isStringifiableAttr(p.arg.content)))
+            (p.arg.isStatic && !isStringifiableAttr(p.arg.content, node.ns)))
         ) {
           return bail()
         }
index 689533dd92cc7f97a983d4b17ffde8bfb1bacea2..93f1b36d327968e72f262dbc5c6e1f0149bdd253 100644 (file)
@@ -66,7 +66,7 @@ export const isNoUnitNumericStyleProp = /*#__PURE__*/ makeMap(
  * Don't also forget to allow `data-*` and `aria-*`!
  * Generated from https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes
  */
-export const isKnownAttr = /*#__PURE__*/ makeMap(
+export const isKnownHtmlAttr = /*#__PURE__*/ makeMap(
   `accept,accept-charset,accesskey,action,align,allow,alt,async,` +
     `autocapitalize,autocomplete,autofocus,autoplay,background,bgcolor,` +
     `border,buffered,capture,challenge,charset,checked,cite,class,code,` +
@@ -83,3 +83,48 @@ export const isKnownAttr = /*#__PURE__*/ makeMap(
     `start,step,style,summary,tabindex,target,title,translate,type,usemap,` +
     `value,width,wrap`
 )
+
+/**
+ * Generated from https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
+ */
+export const isKnownSvgAttr = /*#__PURE__*/ makeMap(
+  `xmlns,accent-height,accumulate,additive,alignment-baseline,alphabetic,amplitude,` +
+    `arabic-form,ascent,attributeName,attributeType,azimuth,baseFrequency,` +
+    `baseline-shift,baseProfile,bbox,begin,bias,by,calcMode,cap-height,class,` +
+    `clip,clipPathUnits,clip-path,clip-rule,color,color-interpolation,` +
+    `color-interpolation-filters,color-profile,color-rendering,` +
+    `contentScriptType,contentStyleType,crossorigin,cursor,cx,cy,d,decelerate,` +
+    `descent,diffuseConstant,direction,display,divisor,dominant-baseline,dur,dx,` +
+    `dy,edgeMode,elevation,enable-background,end,exponent,fill,fill-opacity,` +
+    `fill-rule,filter,filterRes,filterUnits,flood-color,flood-opacity,` +
+    `font-family,font-size,font-size-adjust,font-stretch,font-style,` +
+    `font-variant,font-weight,format,from,fr,fx,fy,g1,g2,glyph-name,` +
+    `glyph-orientation-horizontal,glyph-orientation-vertical,glyphRef,` +
+    `gradientTransform,gradientUnits,hanging,height,href,hreflang,horiz-adv-x,` +
+    `horiz-origin-x,id,ideographic,image-rendering,in,in2,intercept,k,k1,k2,k3,` +
+    `k4,kernelMatrix,kernelUnitLength,kerning,keyPoints,keySplines,keyTimes,` +
+    `lang,lengthAdjust,letter-spacing,lighting-color,limitingConeAngle,local,` +
+    `marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,` +
+    `mask,maskContentUnits,maskUnits,mathematical,max,media,method,min,mode,` +
+    `name,numOctaves,offset,opacity,operator,order,orient,orientation,origin,` +
+    `overflow,overline-position,overline-thickness,panose-1,paint-order,path,` +
+    `pathLength,patternContentUnits,patternTransform,patternUnits,ping,` +
+    `pointer-events,points,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,` +
+    `preserveAspectRatio,primitiveUnits,r,radius,referrerPolicy,refX,refY,rel,` +
+    `rendering-intent,repeatCount,repeatDur,requiredExtensions,requiredFeatures,` +
+    `restart,result,rotate,rx,ry,scale,seed,shape-rendering,slope,spacing,` +
+    `specularConstant,specularExponent,speed,spreadMethod,startOffset,` +
+    `stdDeviation,stemh,stemv,stitchTiles,stop-color,stop-opacity,` +
+    `strikethrough-position,strikethrough-thickness,string,stroke,` +
+    `stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,` +
+    `stroke-miterlimit,stroke-opacity,stroke-width,style,surfaceScale,` +
+    `systemLanguage,tabindex,tableValues,target,targetX,targetY,text-anchor,` +
+    `text-decoration,text-rendering,textLength,to,transform,transform-origin,` +
+    `type,u1,u2,underline-position,underline-thickness,unicode,unicode-bidi,` +
+    `unicode-range,units-per-em,v-alphabetic,v-hanging,v-ideographic,` +
+    `v-mathematical,values,vector-effect,version,vert-adv-y,vert-origin-x,` +
+    `vert-origin-y,viewBox,viewTarget,visibility,width,widths,word-spacing,` +
+    `writing-mode,x,x-height,x1,x2,xChannelSelector,xlink:actuate,xlink:arcrole,` +
+    `xlink:href,xlink:role,xlink:show,xlink:title,xlink:type,xml:base,xml:lang,` +
+    `xml:space,y,y1,y2,yChannelSelector,z,zoomAndPan`
+)