1414const CACHE = { } ;
1515
1616export default function html ( statics ) {
17- const str = statics . join ( '\0 ') ;
18- const tpl = CACHE [ str ] || ( CACHE [ str ] = build ( str ) ) ;
17+ const key = statics . reduce ( ( key , s ) => key + s . length + '$' + s , ' ') ;
18+ const tpl = CACHE [ key ] || ( CACHE [ key ] = build ( statics ) ) ;
1919 // eslint-disable-next-line prefer-rest-params
2020 return tpl ( this , arguments ) ;
2121}
@@ -38,15 +38,13 @@ const MODE_ATTRIBUTE = 13;
3838const MODE_SKIP = 47 ;
3939
4040/** Create a template function given strings from a tagged template. */
41- function build ( input ) {
41+ function build ( statics ) {
4242 let out = 'return ' ;
4343 let buffer = '' ;
4444 let mode = MODE_WHITESPACE ;
45- let fieldIndex = 1 ;
4645 let field = '' ;
4746 let hasChildren = 0 ;
48- let propCount = 0 ;
49- let spreads = 0 ;
47+ let props = '' ;
5048 let quote = 0 ;
5149 let spread , slash , charCode , inTag , propName , propHasValue ;
5250
@@ -64,22 +62,19 @@ function build(input) {
6462 }
6563 else if ( mode === MODE_ATTRIBUTE || ( mode === MODE_WHITESPACE && buffer === '...' ) ) {
6664 if ( mode === MODE_WHITESPACE ) {
67- spread = true ;
68- if ( ! spreads ++ ) {
69- if ( propCount === 0 ) out + = ', Object.assign({},' ;
70- else out = out . replace ( / , \( \{ ( . * ? ) $ / , ', Object.assign({},{$1' ) + '},' ;
65+ if ( ! spread ) {
66+ spread = true ;
67+ if ( ! props ) props = 'Object.assign({},' ;
68+ else props = ' Object.assign({},' + props + '},' ;
7169 }
72- out += field + ',{' ;
73- propCount ++ ;
70+ props += field + ',{' ;
7471 }
7572 else if ( propName ) {
76- if ( ! spread ) out += ', ' ;
77- if ( propCount === 0 ) out += '({ ' ;
78- out += propName + ':' ;
79- out += field || ( ( propHasValue || buffer ) && JSON . stringify ( buffer ) ) || 'true' ;
73+ if ( ! props ) props += '{ ' ;
74+ else if ( ! props . endsWith ( '{' ) ) props += ', ' ;
75+ props += JSON . stringify ( propName ) + ':' ;
76+ props += field || ( ( propHasValue || buffer ) && JSON . stringify ( buffer ) ) || 'true' ;
8077 propName = '' ;
81- spread = false ;
82- propCount ++ ;
8378 }
8479 propHasValue = false ;
8580 }
@@ -94,96 +89,98 @@ function build(input) {
9489 buffer = field = '' ;
9590 }
9691
97- for ( let i = 0 ; i < input . length ; i ++ ) {
98- charCode = input . charCodeAt ( i ) ;
99- field = '' ;
100-
101- if ( charCode === QUOTE_SINGLE || charCode === QUOTE_DOUBLE ) {
102- if ( quote === charCode ) {
103- quote = 0 ;
104- continue ;
105- }
106- if ( quote === 0 ) {
107- quote = charCode ;
108- continue ;
109- }
110- }
111-
112- if ( charCode === 0 ) {
92+ for ( let i = 0 ; i < statics . length ; i ++ ) {
93+ if ( i > 0 ) {
11394 if ( ! inTag ) commit ( ) ;
114- field = `$_h[${ fieldIndex ++ } ]` ;
95+ field = `$_h[${ i } ]` ;
11596 commit ( ) ;
116- continue ;
11797 }
98+
99+ const input = statics [ i ] ;
100+ for ( let j = 0 ; j < input . length ; j ++ ) {
101+ charCode = input . charCodeAt ( j ) ;
102+ field = '' ;
118103
119- if ( quote === 0 ) {
120- switch ( charCode ) {
121- case TAG_START :
122- if ( ! inTag ) {
123- // commit buffer
124- commit ( ) ;
125- inTag = true ;
126- propCount = 0 ;
127- slash = spread = propHasValue = false ;
128- mode = MODE_TAGNAME ;
129- continue ;
130- }
131-
132- case TAG_END :
133- if ( inTag ) {
134- commit ( ) ;
135- if ( mode !== MODE_SKIP ) {
136- if ( propCount === 0 ) {
137- out += ',null' ;
104+ if ( charCode === QUOTE_SINGLE || charCode === QUOTE_DOUBLE ) {
105+ if ( quote === charCode ) {
106+ quote = 0 ;
107+ continue ;
108+ }
109+ if ( quote === 0 ) {
110+ quote = charCode ;
111+ continue ;
112+ }
113+ }
114+
115+ if ( quote === 0 ) {
116+ switch ( charCode ) {
117+ case TAG_START :
118+ if ( ! inTag ) {
119+ // commit buffer
120+ commit ( ) ;
121+ inTag = true ;
122+ props = '' ;
123+ slash = spread = propHasValue = false ;
124+ mode = MODE_TAGNAME ;
125+ continue ;
126+ }
127+
128+ case TAG_END :
129+ if ( inTag ) {
130+ commit ( ) ;
131+ if ( mode !== MODE_SKIP ) {
132+ if ( ! props ) {
133+ out += ',null' ;
134+ }
135+ else {
136+ out += ',' + props + '}' + ( spread ? ')' : '' ) ;
137+ }
138138 }
139- else {
140- out += '} )' ;
139+ if ( slash ) {
140+ out += ')' ;
141141 }
142+ spread = inTag = false ;
143+ props = '' ;
144+ mode = MODE_TEXT ;
145+ continue ;
142146 }
143- if ( slash ) {
144- out += ')' ;
147+
148+ case EQUALS :
149+ if ( inTag ) {
150+ mode = MODE_ATTRIBUTE ;
151+ propHasValue = true ;
152+ propName = buffer ;
153+ buffer = '' ;
154+ continue ;
145155 }
146- inTag = false ;
147- propCount = 0 ;
148- mode = MODE_TEXT ;
149- continue ;
150- }
151-
152- case EQUALS :
153- if ( inTag ) {
154- mode = MODE_ATTRIBUTE ;
155- propHasValue = true ;
156- propName = buffer ;
157- buffer = '' ;
158- continue ;
159- }
160156
161- case SLASH :
162- if ( inTag ) {
163- if ( ! slash ) {
164- slash = true ;
165- // </foo>
166- if ( mode === MODE_TAGNAME && ! field && ! buffer . trim ( ) . length ) {
167- buffer = field = '' ;
168- mode = MODE_SKIP ;
157+ case SLASH :
158+ if ( inTag ) {
159+ if ( ! slash ) {
160+ slash = true ;
161+ // </foo>
162+ if ( mode === MODE_TAGNAME && ! field && ! buffer . trim ( ) . length ) {
163+ buffer = field = '' ;
164+ mode = MODE_SKIP ;
165+ }
169166 }
167+ continue ;
168+ }
169+ case TAB :
170+ case NEWLINE :
171+ case RETURN :
172+ case SPACE :
173+ // <a disabled>
174+ if ( inTag ) {
175+ commit ( ) ;
176+ mode = MODE_WHITESPACE ;
177+ continue ;
170178 }
171- continue ;
172- }
173- case TAB :
174- case NEWLINE :
175- case RETURN :
176- case SPACE :
177- // <a disabled>
178- if ( inTag ) {
179- commit ( ) ;
180- continue ;
181- }
179+ }
182180 }
183- }
184-
185- buffer += input . charAt ( i ) ;
186181
182+ buffer += input . charAt ( j ) ;
183+ }
187184 }
188185 commit ( ) ;
189186 return Function ( 'h' , '$_h' , out ) ;
0 commit comments