@@ -113,6 +113,24 @@ export function svg(name, size = 16, className = '') {
113
113
return serializer . serializeToString ( svgNode ) ;
114
114
}
115
115
116
+ export function svgParseOuterInner ( name ) {
117
+ const svgStr = svgs [ name ] ;
118
+ if ( ! svgStr ) throw new Error ( `Unknown SVG icon: ${ name } ` ) ;
119
+
120
+ // parse the SVG string to 2 parts
121
+ // * svgInnerHtml: the inner part of the SVG, will be used as the content of the <svg> VNode
122
+ // * svgOuter: the outer part of the SVG, including attributes
123
+ // the builtin SVG contents are clean, so it's safe to use `indexOf` to split the content:
124
+ // eg: <svg outer-attributes>${svgInnerHtml}</svg>
125
+ const p1 = svgStr . indexOf ( '>' ) , p2 = svgStr . lastIndexOf ( '<' ) ;
126
+ if ( p1 === - 1 || p2 === - 1 ) throw new Error ( `Invalid SVG icon: ${ name } ` ) ;
127
+ const svgInnerHtml = svgStr . slice ( p1 + 1 , p2 ) ;
128
+ const svgOuterHtml = svgStr . slice ( 0 , p1 + 1 ) + svgStr . slice ( p2 ) ;
129
+ const svgDoc = parser . parseFromString ( svgOuterHtml , 'image/svg+xml' ) ;
130
+ const svgOuter = svgDoc . firstChild ;
131
+ return { svgOuter, svgInnerHtml} ;
132
+ }
133
+
116
134
export const SvgIcon = {
117
135
name : 'SvgIcon' ,
118
136
props : {
@@ -121,21 +139,7 @@ export const SvgIcon = {
121
139
className : { type : String , default : '' } ,
122
140
} ,
123
141
render ( ) {
124
- const svgStr = svgs [ this . name ] ;
125
- if ( ! svgStr ) throw new Error ( `Unknown SVG icon: ${ this . name } ` ) ;
126
-
127
- // parse the SVG string to 2 parts
128
- // * svgInnerHtml: the inner part of the SVG, will be used as the content of the <svg> VNode
129
- // * svgOuter: the outer part of the SVG, including attributes
130
- // the builtin SVG contents are clean, so it's safe to use `indexOf` to split the content:
131
- // eg: <svg outer-attributes>${svgInnerHtml}</svg>
132
- const p1 = svgStr . indexOf ( '>' ) , p2 = svgStr . lastIndexOf ( '<' ) ;
133
- if ( p1 === - 1 || p2 === - 1 ) throw new Error ( `Invalid SVG icon: ${ this . name } ` ) ;
134
- const svgInnerHtml = svgStr . slice ( p1 + 1 , p2 ) ;
135
- const svgOuterHtml = svgStr . slice ( 0 , p1 + 1 ) + svgStr . slice ( p2 ) ;
136
- const svgDoc = parser . parseFromString ( svgOuterHtml , 'image/svg+xml' ) ;
137
- const svgOuter = svgDoc . firstChild ;
138
-
142
+ const { svgOuter, svgInnerHtml} = svgParseOuterInner ( this . name ) ;
139
143
// https://vuejs.org/guide/extras/render-function.html#creating-vnodes
140
144
// the `^` is used for attr, set SVG attributes like 'width', `aria-hidden`, `viewBox`, etc
141
145
const attrs = { } ;
@@ -151,6 +155,7 @@ export const SvgIcon = {
151
155
for ( const cls of svgOuter . classList ) {
152
156
classes . push ( cls ) ;
153
157
}
158
+ // TODO: drop the `className/class-name` prop in the future, only use "class" prop
154
159
if ( this . className ) {
155
160
classes . push ( ...this . className . split ( / \s + / ) . filter ( Boolean ) ) ;
156
161
}
0 commit comments