@@ -5,9 +5,10 @@ var htmlParser = require('htmlparser2'),
55
66module . exports = convert ;
77
8- var tplAnnotations = / \/ \* + \ s* @ j s x \- t p l \s + ( [ \w \- ] + ) \s * \* \/ / g,
8+ var tplAnnotations = / [ " ' ] \ s* @ j s x \- t p l \s + ( [ \w \- ] + ) \s * [ ' " ] / g,
99 tplAttr = 'jsx-tpl' ,
10- renderAnnotations = / < ! - - \s * @ r e n d e r \s + ( [ \w \- ] + ) \s * - - > / g,
10+ renderAnnotation = / @ r e n d e r \s + ( [ \w \- ] + ) / ,
11+ renderAnnotationComments = / < ! - - \s * @ r e n d e r \s + ( [ \w \- ] + ) \s * - - > / g,
1112 spreadAttr = / j s x \- s p r e a d = " ( [ \$ \w ] + ) " / g,
1213 renderReturnSelector =
1314 'call[callee.object.name="React"][callee.property.name="createClass"]' +
@@ -19,45 +20,55 @@ function convert(js, html, callback) {
1920 return callback ( err ) ;
2021 }
2122
22- var templates = { } ;
23-
2423 prepareAttr ( body ) ;
2524
26- domUtils . findAll ( function ( node ) {
27- return domUtils . hasAttrib ( node , tplAttr ) ;
28- } , body . children ) . forEach ( function ( node ) {
25+ removeComments ( body ) ;
26+
27+ var tplList = findNodesByAttr ( body , tplAttr ) ;
28+
29+ var templates = { } ;
30+ tplList . forEach ( function ( node ) {
2931 var name = node . attribs [ tplAttr ] ;
3032 delete node . attribs [ tplAttr ] ;
31-
3233 templates [ name ] = clearAttrQuotes ( domUtils . getOuterHTML ( node ) ) ;
33-
34- domUtils . removeElement ( node ) ;
3534 } ) ;
3635
36+ removeNodes ( tplList ) ;
37+
3738 var _return = search ( renderReturnSelector , js ) ,
3839 _props = search ( renderReturnSelector + ' > obj > prop' , js ) ,
3940 props = { } ;
4041
41- _props . forEach ( function ( prop ) {
42- var name = prop . key . name ,
43- body = prop . value . body ,
44- value = js . slice ( body . start , body . end ) ;
42+ try {
43+ _props . forEach ( function ( prop ) {
44+ var name = prop . key . name ,
45+ body = prop . value . body ,
46+ value = js . slice ( body . start , body . end ) ;
47+
48+ value = value . replace ( tplAnnotations , function ( x , name ) {
49+ if ( ! templates . hasOwnProperty ( name ) ) {
50+ throw new Error ( 'JSX template "' + name + '" not exists' ) ;
51+ }
4552
46- value = value . replace ( tplAnnotations , function ( x , name ) {
47- return format ( '(%s)' , templates [ name ] ) ;
48- } ) ;
53+ return format ( '(%s)' , templates [ name ] ) ;
54+ } ) ;
4955
50- props [ name ] = value ;
51- } ) ;
56+ props [ name ] = value ;
57+ } ) ;
58+ }
59+ catch ( e ) {
60+ return callback ( e ) ;
61+ }
5262
5363 var template = clearAttrQuotes ( domUtils . getOuterHTML ( body ) ) ;
5464
5565 try {
5666 template = template
57- . replace ( renderAnnotations , function ( x , name ) {
67+ . replace ( renderAnnotationComments , function ( x , name ) {
5868 if ( ! props . hasOwnProperty ( name ) ) {
59- throw new Error ( 'Template "' + name + '" not exists' ) ;
69+ throw new Error ( 'Render template "' + name + '" not exists' ) ;
6070 }
71+
6172 return props [ name ] ;
6273 } )
6374 ;
@@ -69,8 +80,8 @@ function convert(js, html, callback) {
6980 if ( _return . length === 0 ) {
7081 return callback ( new Error ( 'React.createClass return: option not found' ) ) ;
7182 }
72- else if ( _return . length > 2 ) {
73- return callback ( new Error ( 'More then one React.createClass return: option' ) ) ;
83+ else if ( _return . length > 1 ) {
84+ return callback ( new Error ( 'More then one React.createClass return: option found, should be only one ' ) ) ;
7485 }
7586 else {
7687 js = insert ( js , _return [ 0 ] . start , _return [ 0 ] . end , format ( 'return (%s);' , template ) ) ;
@@ -199,4 +210,27 @@ function clearAttrQuotes(html) {
199210 . replace ( / = " ~ ~ ~ \{ / g, '={' ) . replace ( / } ~ ~ ~ " / g, '}' )
200211 . replace ( spreadAttr , '{...$1}' )
201212 ;
213+ }
214+
215+ function findNodesByAttr ( body , attrName ) {
216+ return domUtils . findAll ( function ( node ) {
217+ return domUtils . hasAttrib ( node , attrName ) ;
218+ } , body . children ) ;
219+ }
220+
221+ function removeNodes ( nodeArray ) {
222+ nodeArray . forEach ( function ( node ) {
223+ domUtils . removeElement ( node ) ;
224+ } ) ;
225+ }
226+
227+ function removeComments ( node ) {
228+ if ( node . type === 'comment' && ! renderAnnotation . test ( node . data ) ) {
229+ domUtils . removeElement ( node ) ;
230+ }
231+ else if ( node . type === 'tag' && node . children ) {
232+ for ( var i = 0 ; i < node . children . length ; i ++ ) {
233+ removeComments ( node . children [ i ] ) ;
234+ }
235+ }
202236}
0 commit comments