@@ -130,27 +130,69 @@ impl SourceBuilder {
130130 Ok ( ( ) )
131131 }
132132
133- fn write_buffered_code (
134- & mut self ,
135- token : & Token < ' _ > ,
136- escape : bool ,
137- ) -> Result < ( ) , Error > {
138- self . write_buffered_code_with_suffix ( token, escape, "" )
139- }
140-
141- fn write_buffered_code_with_suffix (
133+ fn parse_filter (
142134 & mut self ,
143135 token : & Token < ' _ > ,
144- escape : bool ,
145- suffix : & str ,
146- ) -> Result < ( ) , Error > {
136+ ) -> Result < Option < ( Filter , TokenStream ) > , Error > {
147137 // parse and split off filter
148138 let code_block = syn:: parse_str :: < CodeBlock > ( token. as_str ( ) ) . map_err ( |e| {
149139 let span = e. span ( ) ;
150140 let mut err = make_error ! ( ErrorKind :: RustSyntaxError ( e) ) ;
151141 err. offset = into_offset ( token. as_str ( ) , span) . map ( |p| token. offset ( ) + p) ;
152142 err
153143 } ) ?;
144+
145+ Ok ( code_block
146+ . filter
147+ . map ( |filter| ( filter, code_block. expr . into_token_stream ( ) ) ) )
148+ }
149+
150+ fn write_with_filter (
151+ & mut self ,
152+ token : & Token < ' _ > ,
153+ filter : Filter ,
154+ expr_str : & str ,
155+ ) -> Result < ( ) , Error > {
156+ let ( name, extra_args) = match filter {
157+ Filter :: Ident ( i) => ( i. to_string ( ) , None ) ,
158+ Filter :: Call ( c) => (
159+ c. func . into_token_stream ( ) . to_string ( ) ,
160+ Some ( c. args . into_token_stream ( ) . to_string ( ) ) ,
161+ ) ,
162+ } ;
163+
164+ self . source . push_str ( "sailfish::runtime::filter::" ) ;
165+ self . source . push_str ( & name) ;
166+ self . source . push ( '(' ) ;
167+
168+ // arguments to filter function
169+ {
170+ self . source . push_str ( "&(" ) ;
171+ let entry = SourceMapEntry {
172+ original : token. offset ( ) ,
173+ new : self . source . len ( ) ,
174+ length : expr_str. len ( ) ,
175+ } ;
176+ self . source_map . entries . push ( entry) ;
177+ self . source . push_str ( expr_str) ;
178+ self . source . push ( ')' ) ;
179+
180+ if let Some ( extra_args) = extra_args {
181+ self . source . push_str ( ", " ) ;
182+ self . source . push_str ( & extra_args) ;
183+ }
184+ }
185+
186+ self . source . push ( ')' ) ;
187+
188+ Ok ( ( ) )
189+ }
190+
191+ fn write_buffered_code (
192+ & mut self ,
193+ token : & Token < ' _ > ,
194+ escape : bool ,
195+ ) -> Result < ( ) , Error > {
154196 let method = if self . escape && escape {
155197 "render_escaped"
156198 } else {
@@ -161,46 +203,30 @@ impl SourceBuilder {
161203 self . source . push_str ( method) ;
162204 self . source . push_str ( "!(__sf_buf, " ) ;
163205
164- if let Some ( filter) = code_block. filter {
165- let expr_str = format ! ( "{}{}" , code_block. expr. into_token_stream( ) , suffix) ;
166- let ( name, extra_args) = match filter {
167- Filter :: Ident ( i) => ( i. to_string ( ) , None ) ,
168- Filter :: Call ( c) => (
169- c. func . into_token_stream ( ) . to_string ( ) ,
170- Some ( c. args . into_token_stream ( ) . to_string ( ) ) ,
171- ) ,
172- } ;
206+ if let Some ( ( filter, code_token_stream) ) = self . parse_filter ( token) ? {
207+ let expr_str = format ! ( "{}" , code_token_stream) ;
208+ self . write_with_filter ( token, filter, & expr_str) ?;
209+ } else {
210+ self . write_token ( token) ;
211+ }
173212
174- self . source . push_str ( "sailfish::runtime::filter::" ) ;
175- self . source . push_str ( & name) ;
176- self . source . push ( '(' ) ;
213+ self . source . push_str ( ");\n " ) ;
177214
178- // arguments to filter function
179- {
180- self . source . push_str ( "&(" ) ;
181- let entry = SourceMapEntry {
182- original : token. offset ( ) ,
183- new : self . source . len ( ) ,
184- length : expr_str. len ( ) ,
185- } ;
186- self . source_map . entries . push ( entry) ;
187- self . source . push_str ( & expr_str) ;
188- self . source . push ( ')' ) ;
189-
190- if let Some ( extra_args) = extra_args {
191- self . source . push_str ( ", " ) ;
192- self . source . push_str ( & extra_args) ;
193- }
194- }
215+ Ok ( ( ) )
216+ }
195217
196- self . source . push ( ')' ) ;
218+ fn write_nested_template_once ( & mut self , token : & Token < ' _ > ) -> Result < ( ) , Error > {
219+ if let Some ( ( filter, code_token_stream) ) = self . parse_filter ( token) ? {
220+ self . source . push_str ( "__sf_rt::render!(__sf_buf, " ) ;
221+ let expr_str = format ! ( "{}{}" , code_token_stream, ".render_once()?" ) ;
222+ self . write_with_filter ( token, filter, & expr_str) ?;
223+ self . source . push_str ( ");\n " ) ;
197224 } else {
225+ self . source . push ( '(' ) ;
198226 self . write_token ( token) ;
199- self . source . push_str ( suffix ) ;
227+ self . source . push_str ( ").render_once_to(__sf_buf)?; \n " ) ;
200228 }
201229
202- self . source . push_str ( ");\n " ) ;
203-
204230 Ok ( ( ) )
205231 }
206232
@@ -214,11 +240,9 @@ impl SourceBuilder {
214240 TokenKind :: BufferedCode { escape } => {
215241 self . write_buffered_code ( & token, escape) ?
216242 }
217- TokenKind :: NestedTemplateOnce => self . write_buffered_code_with_suffix (
218- & token,
219- false ,
220- ".render_once()?" ,
221- ) ?,
243+ TokenKind :: NestedTemplateOnce => {
244+ self . write_nested_template_once ( & token) ?
245+ }
222246 TokenKind :: Text => {
223247 // concatenate repeated text token
224248 let offset = token. offset ( ) ;
@@ -399,7 +423,7 @@ mod tests {
399423 . ast
400424 . into_token_stream( )
401425 . to_string( ) ,
402- r#"{ __sf_rt :: render_text ! (__sf_buf , "outer ") ; __sf_rt :: render ! (__sf_buf , inner . render_once ( ) ?) ; __sf_rt :: render_text ! (__sf_buf , " outer") ; }"#
426+ r#"{ __sf_rt :: render_text ! (__sf_buf , "outer ") ; ( inner) . render_once_to (__sf_buf ) ? ; __sf_rt :: render_text ! (__sf_buf , " outer") ; }"#
403427 ) ;
404428 }
405429
0 commit comments