@@ -3,45 +3,58 @@ import { NodePath, types as t } from '@babel/core'
3
3
4
4
const elements = [ 'svg' , 'Svg' ]
5
5
6
- const createTitleElement = (
6
+ type tag = 'title' | 'desc'
7
+
8
+ export interface Options {
9
+ tag : tag | null
10
+ }
11
+
12
+ interface State {
13
+ opts : Options
14
+ }
15
+
16
+ const createTagElement = (
17
+ tag : tag ,
7
18
children : t . JSXExpressionContainer [ ] = [ ] ,
8
19
attributes : ( t . JSXAttribute | t . JSXSpreadAttribute ) [ ] = [ ] ,
9
20
) => {
10
- const title = t . jsxIdentifier ( 'title' )
21
+ const eleName = t . jsxIdentifier ( tag )
11
22
return t . jsxElement (
12
- t . jsxOpeningElement ( title , attributes ) ,
13
- t . jsxClosingElement ( title ) ,
23
+ t . jsxOpeningElement ( eleName , attributes ) ,
24
+ t . jsxClosingElement ( eleName ) ,
14
25
children ,
15
26
)
16
27
}
17
28
18
- const createTitleIdAttribute = ( ) =>
29
+ const createTagIdAttribute = ( tag : tag ) =>
19
30
t . jsxAttribute (
20
31
t . jsxIdentifier ( 'id' ) ,
21
- t . jsxExpressionContainer ( t . identifier ( 'titleId' ) ) ,
32
+ t . jsxExpressionContainer ( t . identifier ( ` ${ tag } Id` ) ) ,
22
33
)
23
34
24
- const addTitleIdAttribute = (
35
+ const addTagIdAttribute = (
36
+ tag : tag ,
25
37
attributes : ( t . JSXAttribute | t . JSXSpreadAttribute ) [ ] ,
26
38
) => {
27
39
const existingId = attributes . find (
28
40
( attribute ) => t . isJSXAttribute ( attribute ) && attribute . name . name === 'id' ,
29
41
) as t . JSXAttribute | undefined
30
42
31
43
if ( ! existingId ) {
32
- return [ ...attributes , createTitleIdAttribute ( ) ]
44
+ return [ ...attributes , createTagIdAttribute ( tag ) ]
33
45
}
34
46
existingId . value = t . jsxExpressionContainer (
35
47
t . isStringLiteral ( existingId . value )
36
- ? t . logicalExpression ( '||' , t . identifier ( 'titleId' ) , existingId . value )
37
- : t . identifier ( 'titleId' ) ,
48
+ ? t . logicalExpression ( '||' , t . identifier ( ` ${ tag } Id` ) , existingId . value )
49
+ : t . identifier ( ` ${ tag } Id` ) ,
38
50
)
39
51
return attributes
40
52
}
41
53
42
54
const plugin = ( ) => ( {
43
55
visitor : {
44
- JSXElement ( path : NodePath < t . JSXElement > ) {
56
+ JSXElement ( path : NodePath < t . JSXElement > , state : State ) {
57
+ const tag = state . opts . tag || 'title'
45
58
if ( ! elements . length ) return
46
59
47
60
const openingElement = path . get ( 'openingElement' )
@@ -54,22 +67,24 @@ const plugin = () => ({
54
67
return
55
68
}
56
69
57
- const getTitleElement = (
70
+ const getTagElement = (
58
71
existingTitle ?: t . JSXElement ,
59
72
) : t . JSXExpressionContainer => {
60
- const titleExpression = t . identifier ( 'title' )
73
+ const tagExpression = t . identifier ( tag )
61
74
if ( existingTitle ) {
62
- existingTitle . openingElement . attributes = addTitleIdAttribute (
75
+ existingTitle . openingElement . attributes = addTagIdAttribute (
76
+ tag ,
63
77
existingTitle . openingElement . attributes ,
64
78
)
65
79
}
66
80
const conditionalTitle = t . conditionalExpression (
67
- titleExpression ,
68
- createTitleElement (
69
- [ t . jsxExpressionContainer ( titleExpression ) ] ,
81
+ tagExpression ,
82
+ createTagElement (
83
+ tag ,
84
+ [ t . jsxExpressionContainer ( tagExpression ) ] ,
70
85
existingTitle
71
86
? existingTitle . openingElement . attributes
72
- : [ createTitleIdAttribute ( ) ] ,
87
+ : [ createTagIdAttribute ( tag ) ] ,
73
88
) ,
74
89
t . nullLiteral ( ) ,
75
90
)
@@ -80,7 +95,7 @@ const plugin = () => ({
80
95
t . conditionalExpression (
81
96
t . binaryExpression (
82
97
'===' ,
83
- titleExpression ,
98
+ tagExpression ,
84
99
t . identifier ( 'undefined' ) ,
85
100
) ,
86
101
existingTitle ,
@@ -92,25 +107,25 @@ const plugin = () => ({
92
107
}
93
108
94
109
// store the title element
95
- let titleElement : t . JSXExpressionContainer | null = null
110
+ let tagElement : t . JSXExpressionContainer | null = null
96
111
97
112
const hasTitle = path . get ( 'children' ) . some ( ( childPath ) => {
98
- if ( childPath . node === titleElement ) return false
113
+ if ( childPath . node === tagElement ) return false
99
114
if ( ! childPath . isJSXElement ( ) ) return false
100
115
const name = childPath . get ( 'openingElement' ) . get ( 'name' )
101
116
if ( ! name . isJSXIdentifier ( ) ) return false
102
- if ( name . node . name !== 'title' ) return false
103
- titleElement = getTitleElement ( childPath . node )
104
- childPath . replaceWith ( titleElement )
117
+ if ( name . node . name !== tag ) return false
118
+ tagElement = getTagElement ( childPath . node )
119
+ childPath . replaceWith ( tagElement )
105
120
return true
106
121
} )
107
122
108
123
// create a title element if not already create
109
- titleElement = titleElement || getTitleElement ( )
124
+ tagElement = tagElement || getTagElement ( )
110
125
if ( ! hasTitle ) {
111
126
// path.unshiftContainer is not working well :(
112
127
// path.unshiftContainer('children', titleElement)
113
- path . node . children . unshift ( titleElement )
128
+ path . node . children . unshift ( tagElement )
114
129
path . replaceWith ( path . node )
115
130
}
116
131
} ,
1 commit comments
vercel[bot] commentedon Jun 19, 2022
Successfully deployed to the following URLs:
svgr – ./
svgr-gregberge.vercel.app
svgr-git-main-gregberge.vercel.app
api.react-svgr.com