@@ -32,4 +32,90 @@ Prism.languages.insertBefore('inside', 'attr-value',{
32
32
}
33
33
} , Prism . languages . jsx . tag ) ;
34
34
35
+ // The following will handle plain text inside tags
36
+ var stringifyToken = function ( token ) {
37
+ if ( typeof token === 'string' ) {
38
+ return token ;
39
+ }
40
+ if ( typeof token . content === 'string' ) {
41
+ return token . content ;
42
+ }
43
+ return token . content . map ( stringifyToken ) . join ( '' ) ;
44
+ } ;
45
+
46
+ var walkTokens = function ( tokens ) {
47
+ var openedTags = [ ] ;
48
+ for ( var i = 0 ; i < tokens . length ; i ++ ) {
49
+ var token = tokens [ i ] ;
50
+ var notTagNorBrace = false ;
51
+
52
+ if ( typeof token !== 'string' ) {
53
+ if ( token . type === 'tag' && token . content [ 0 ] && token . content [ 0 ] . type === 'tag' ) {
54
+ // We found a tag, now find its kind
55
+
56
+ if ( token . content [ 0 ] . content [ 0 ] . content === '</' ) {
57
+ // Closing tag
58
+ if ( openedTags . length > 0 && openedTags [ openedTags . length - 1 ] . tagName === stringifyToken ( token . content [ 0 ] . content [ 1 ] ) ) {
59
+ // Pop matching opening tag
60
+ openedTags . pop ( ) ;
61
+ }
62
+ } else {
63
+ if ( token . content [ token . content . length - 1 ] . content === '/>' ) {
64
+ // Autoclosed tag, ignore
65
+ } else {
66
+ // Opening tag
67
+ openedTags . push ( {
68
+ tagName : stringifyToken ( token . content [ 0 ] . content [ 1 ] ) ,
69
+ openedBraces : 0
70
+ } ) ;
71
+ }
72
+ }
73
+ } else if ( openedTags . length > 0 && token . type === 'punctuation' && token . content === '{' ) {
74
+
75
+ // Here we might have entered a JSX context inside a tag
76
+ openedTags [ openedTags . length - 1 ] . openedBraces ++ ;
77
+
78
+ } else if ( openedTags . length > 0 && openedTags [ openedTags . length - 1 ] . openedBraces > 0 && token . type === 'punctuation' && token . content === '}' ) {
79
+
80
+ // Here we might have left a JSX context inside a tag
81
+ openedTags [ openedTags . length - 1 ] . openedBraces -- ;
82
+
83
+ } else {
84
+ notTagNorBrace = true
85
+ }
86
+ }
87
+ if ( notTagNorBrace || typeof token === 'string' ) {
88
+ if ( openedTags . length > 0 && openedTags [ openedTags . length - 1 ] . openedBraces === 0 ) {
89
+ // Here we are inside a tag, and not inside a JSX context.
90
+ // That's plain text: drop any tokens matched.
91
+ var plainText = stringifyToken ( token ) ;
92
+
93
+ // And merge text with adjacent text
94
+ if ( i < tokens . length - 1 && ( typeof tokens [ i + 1 ] === 'string' || tokens [ i + 1 ] . type === 'plain-text' ) ) {
95
+ plainText += stringifyToken ( tokens [ i + 1 ] ) ;
96
+ tokens . splice ( i + 1 , 1 ) ;
97
+ }
98
+ if ( i > 0 && ( typeof tokens [ i - 1 ] === 'string' || tokens [ i - 1 ] . type === 'plain-text' ) ) {
99
+ plainText = stringifyToken ( tokens [ i - 1 ] ) + plainText ;
100
+ tokens . splice ( i - 1 , 1 ) ;
101
+ i -- ;
102
+ }
103
+
104
+ tokens [ i ] = new Prism . Token ( 'plain-text' , plainText , null , plainText ) ;
105
+ }
106
+ }
107
+
108
+ if ( token . content && typeof token . content !== 'string' ) {
109
+ walkTokens ( token . content ) ;
110
+ }
111
+ }
112
+ } ;
113
+
114
+ Prism . hooks . add ( 'after-tokenize' , function ( env ) {
115
+ if ( env . language !== 'jsx' && env . language !== 'tsx' ) {
116
+ return ;
117
+ }
118
+ walkTokens ( env . tokens ) ;
119
+ } ) ;
120
+
35
121
} ( Prism ) ) ;
0 commit comments