1use std::cell::RefCell;
3use std::collections::HashMap;
4use std::fmt;
5use std::rc::Rc;
6
7use serde::Serialize;
8use serde_json::{Map, Value};
9
10use crate::{
11 error::{HelperError, RenderError},
12 helper::{Helper, HelperResult, LocalHelper},
13 json,
14 output::{Output, StringOutput},
15 parser::{
16 ast::{
17 Block, Call, CallTarget, Lines, Link, Node, ParameterValue, Path,
18 Slice,
19 },
20 path,
21 },
22 template::Template,
23 trim::{TrimHint, TrimState},
24 Registry, RenderResult,
25};
26
27const PARTIAL_BLOCK: &str = "@partial-block";
28const HELPER_MISSING: &str = "helperMissing";
29const BLOCK_HELPER_MISSING: &str = "blockHelperMissing";
30const HELPER_LINK: &str = "link";
31
32type HelperValue = Option<Value>;
33
34pub mod assert;
35pub mod context;
36pub mod scope;
37
38pub use assert::{assert, Type};
39pub use context::{Context, MissingValue, Property};
40pub use scope::Scope;
41
42const STACK_MAX: usize = 32;
44
45enum HelperTarget<'a> {
46 Name(&'a str),
47 Helper(&'a Box<dyn Helper + 'a>),
48}
49
50#[derive(Eq, PartialEq, Hash, Debug, Clone)]
60pub enum CallSite {
61 Partial(String),
63 Helper(String),
65 BlockHelper(String),
67}
68
69impl fmt::Display for CallSite {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(f, "{}", {
72 match *self {
73 CallSite::Partial(ref name) => format!("partial#{}", name),
74 CallSite::Helper(ref name) => format!("helper#{}", name),
75 CallSite::BlockHelper(ref name) => format!("block#{}", name),
76 }
77 })
78 }
79}
80
81impl Into<String> for CallSite {
82 fn into(self) -> String {
83 match self {
84 CallSite::Partial(name)
85 | CallSite::Helper(name)
86 | CallSite::BlockHelper(name) => name,
87 }
88 }
89}
90
91pub struct Render<'render> {
93 registry: &'render Registry<'render>,
94 local_helpers: Rc<RefCell<HashMap<String, Box<dyn LocalHelper + 'render>>>>,
95 partials: HashMap<String, &'render Node<'render>>,
96 name: &'render str,
97 root: Value,
98 writer: Box<&'render mut dyn Output>,
99 scopes: Vec<Scope>,
100 trim: TrimState,
101 hint: Option<TrimHint>,
102 end_tag_hint: Option<TrimHint>,
103 stack: Vec<CallSite>,
104 current_partial_name: Vec<Option<&'render str>>,
105}
106
107impl<'render> Render<'render> {
108 pub fn new<T>(
113 registry: &'render Registry<'render>,
114 name: &'render str,
115 data: &T,
116 writer: Box<&'render mut dyn Output>,
117 stack: Vec<CallSite>,
118 ) -> RenderResult<Self>
119 where
120 T: Serialize,
121 {
122 let root = serde_json::to_value(data).map_err(RenderError::from)?;
123 let scopes: Vec<Scope> = Vec::new();
124
125 Ok(Self {
126 registry,
127 local_helpers: Rc::new(RefCell::new(HashMap::new())),
128 partials: HashMap::new(),
129 name,
130 root,
131 writer,
132 scopes,
133 trim: Default::default(),
134 hint: None,
135 end_tag_hint: None,
136 stack,
137 current_partial_name: Vec::new(),
138 })
139 }
140
141 pub fn template_name(&self) -> &str {
147 self.name
148 }
149
150 pub fn current_name(&self) -> &str {
163 if !self.current_partial_name.is_empty() {
164 self.current_partial_name.last().unwrap().unwrap_or(self.name)
165 } else { self.name }
166 }
167
168 pub fn once<T>(
177 &self,
178 file_name: &str,
179 content: &str,
180 data: &T,
181 ) -> HelperResult<String>
182 where
183 T: Serialize,
184 {
185 let result = self
186 .registry()
187 .once_stack(file_name, &content, data, self.stack.clone())
188 .map_err(|e| HelperError::new(e.to_string()))?;
189 Ok(result)
190 }
191
192 pub fn registry(&self) -> &Registry<'_> {
194 self.registry
195 }
196
197 pub fn render(&mut self, node: &'render Node<'render>) -> RenderResult<()> {
201 for event in node.into_iter().event(Default::default()) {
202 self.render_node(event.node, event.trim)?;
203 }
204 Ok(())
205 }
206
207 pub fn get_template(&self, name: &str) -> Option<&'render Template> {
209 self.registry.get(name)
210 }
211
212 pub fn out(&mut self) -> &mut Box<&'render mut dyn Output> {
218 &mut self.writer
219 }
220
221 pub fn escape(&self, val: &str) -> String {
223 (self.registry.escape())(val)
224 }
225
226 pub fn write(&mut self, s: &str) -> HelperResult<usize> {
228 self.write_str(s, false)
229 .map_err(Box::new)
230 .map_err(HelperError::from)
231 }
232
233 pub fn write_escaped(&mut self, s: &str) -> HelperResult<usize> {
236 self.write_str(s, true)
237 .map_err(Box::new)
238 .map_err(HelperError::from)
239 }
240
241 pub fn push_scope(&mut self, scope: Scope) {
243 self.scopes.push(scope);
244 }
245
246 pub fn pop_scope(&mut self) -> Option<Scope> {
248 self.scopes.pop()
249 }
250
251 pub fn scope_mut(&mut self) -> Option<&mut Scope> {
253 self.scopes.last_mut()
254 }
255
256 pub fn data(&self) -> &Value {
258 &self.root
259 }
260
261 pub fn inverse<'a>(
264 &mut self,
265 template: &'a Node<'a>,
266 ) -> Result<Option<&'a Node<'a>>, HelperError> {
267 let mut alt: Option<&'a Node<'_>> = None;
268 let mut branch: Option<&'a Node<'_>> = None;
269
270 match template {
271 Node::Block(ref block) => {
272 if !block.conditions().is_empty() {
273 for node in block.conditions().iter() {
274 match node {
275 Node::Block(clause) => {
276 if clause.call().is_empty() {
278 alt = Some(node);
279 } else {
280 if let Some(value) = self
281 .call(clause.call())
282 .map_err(Box::new)?
283 {
284 if json::is_truthy(&value) {
285 branch = Some(node);
286 break;
287 }
288 }
289 }
290 }
291 _ => {}
292 }
293 }
294 }
295 }
296 _ => {}
297 }
298
299 Ok(branch.or(alt))
300 }
301
302 pub fn template(
306 &mut self,
307 node: &'render Node<'render>,
308 ) -> Result<(), HelperError> {
309 let mut hint: Option<TrimHint> = None;
310 for event in node.into_iter().event(self.hint) {
311 let mut trim = event.trim;
312
313 if event.first {
314 let hint = node.trim();
315 if hint.after {
316 trim.start = true;
317 }
318 }
319
320 if event.last {
321 match node {
322 Node::Block(ref block) => {
323 let last_hint = block.trim_close();
324 if last_hint.before {
325 trim.end = true;
326 }
327 hint = Some(last_hint);
328 }
329 _ => {}
330 }
331 }
332
333 self.render_node(event.node, trim)
334 .map_err(|e| HelperError::Render(Box::new(e)))?;
335 }
336
337 self.end_tag_hint = hint;
340
341 Ok(())
342 }
343
344 pub fn buffer(
350 &self,
351 node: &'render Node<'render>,
352 ) -> Result<String, HelperError> {
353 let mut writer = StringOutput::new();
354 let mut rc = Render::new(
355 self.registry,
356 self.name,
357 &self.root,
358 Box::new(&mut writer),
359 self.stack.clone(),
360 )
361 .map_err(Box::new)?;
362
363 rc.stack = self.stack.clone();
365 rc.scopes = self.scopes.clone();
366
367 rc.template(node)?;
370
371 drop(rc);
373
374 Ok(writer.into())
375 }
376
377 pub fn evaluate<'a>(
390 &'a self,
391 value: &str,
392 ) -> HelperResult<Option<&'a Value>> {
393 if let Some(path) = path::from_str(value)? {
394 return Ok(self.lookup(&path));
395 }
396 Ok(None)
397 }
398
399 pub fn try_evaluate<'a>(
405 &'a self,
406 value: &str,
407 kinds: &[Type],
408 ) -> HelperResult<&'a Value> {
409 let val = self.evaluate(value)?.or(Some(&Value::Null)).unwrap();
410 let (result, kind) = assert(val, kinds);
411 if !result {
412 return Err(HelperError::TypeAssert(
413 value.to_string(),
414 kind.unwrap(),
415 Type::from(val).to_string(),
416 ));
417 }
418 Ok(val)
419 }
420
421 fn lookup<'a>(&'a self, path: &Path<'_>) -> Option<&'a Value> {
423 if path.absolute() {
431 return None;
432 }
433
434 if path.is_root() {
436 json::find_parts(
437 path.components().iter().skip(1).map(|c| c.as_value()),
438 &self.root,
439 )
440 } else if path.is_explicit() {
442 let value = if let Some(scope) = self.scopes.last() {
443 if let Some(base) = scope.base_value() {
444 base
445 } else {
446 &self.root
447 }
448 } else {
449 &self.root
450 };
451
452 if path.components().len() == 1 {
454 Some(value)
455 } else {
457 json::find_parts(
458 path.components().iter().skip(1).map(|c| c.as_value()),
459 value,
460 )
461 }
462 } else if path.is_local() {
465 if let Some(scope) = self.scopes.last() {
466 json::find_parts(
467 path.components().iter().map(|c| c.as_value()),
468 scope.locals(),
469 )
470 } else {
471 None
472 }
473 } else if path.parents() > 0 {
474 let mut all: Vec<(&Value, Option<&Value>)> = self
475 .scopes
476 .iter()
477 .map(|s| (s.locals(), s.base_value().as_ref()))
478 .collect();
479
480 all.insert(0, (&self.root, None));
483
484 if all.len() > path.parents() as usize {
485 let index: usize = all.len() - (path.parents() as usize + 1);
486 if let Some((locals, value)) = all.get(index) {
487 if let Some(res) = json::find_parts(
488 path.components().iter().map(|c| c.as_value()),
489 locals,
490 ) {
491 return Some(res);
492 } else if let Some(value) = value {
493 if let Some(res) = json::find_parts(
494 path.components().iter().map(|c| c.as_value()),
495 value,
496 ) {
497 return Some(res);
498 }
499 }
500 None
501 } else {
502 None
503 }
504 } else {
505 None
506 }
507 } else {
508 let mut values: Vec<(&Value, Option<&Value>)> = self
509 .scopes
510 .iter()
511 .map(|v| (v.locals(), v.base_value().as_ref()))
512 .rev()
513 .collect();
514 values.push((&self.root, None));
515
516 for (locals, value) in values {
517 if let Some(res) = json::find_parts(
518 path.components().iter().map(|c| c.as_value()),
519 locals,
520 ) {
521 return Some(res);
522 } else if let Some(value) = value {
523 if let Some(res) = json::find_parts(
524 path.components().iter().map(|c| c.as_value()),
525 value,
526 ) {
527 return Some(res);
528 }
529 }
530 }
531 None
532 }
533 }
534
535 fn arguments(
537 &mut self,
538 call: &Call<'_>,
539 missing: &mut Vec<MissingValue>,
540 ) -> RenderResult<Vec<Value>> {
541 let mut out: Vec<Value> = Vec::new();
542 for (i, p) in call.arguments().iter().enumerate() {
543 let arg = match p {
544 ParameterValue::Json { ref value, .. } => value.clone(),
545 ParameterValue::Path(ref path) => {
546 self.lookup(path).cloned().unwrap_or_else(|| {
547 missing.push(MissingValue::Argument(
548 i,
549 Value::String(path.as_str().to_string()),
550 ));
551 Value::Null
552 })
553 }
554 ParameterValue::SubExpr(ref call) => {
555 self.statement(call)?.unwrap_or_else(|| {
556 missing.push(MissingValue::Argument(
557 i,
558 Value::String(call.as_str().to_string()),
559 ));
560 Value::Null
561 })
562 }
563 };
564 out.push(arg);
565 }
566 Ok(out)
567 }
568
569 fn hash(
571 &mut self,
572 call: &Call<'_>,
573 missing: &mut Vec<MissingValue>,
574 ) -> RenderResult<Map<String, Value>> {
575 let mut out = Map::new();
576 for (k, p) in call.parameters() {
577 let (key, value) = match p {
578 ParameterValue::Json { ref value, .. } => {
579 (k.to_string(), value.clone())
580 }
581 ParameterValue::Path(ref path) => {
582 let val = self.lookup(path).cloned().unwrap_or_else(|| {
583 missing.push(MissingValue::Parameter(
584 k.to_string(),
585 Value::String(path.as_str().to_string()),
586 ));
587 Value::Null
588 });
589 (k.to_string(), val)
590 }
591 ParameterValue::SubExpr(ref call) => (
592 k.to_string(),
593 self.statement(call)?.unwrap_or_else(|| {
594 missing.push(MissingValue::Parameter(
595 k.to_string(),
596 Value::String(call.as_str().to_string()),
597 ));
598 Value::Null
599 }),
600 ),
601 };
602 out.insert(key, value);
603 }
604
605 Ok(out)
606 }
607
608 pub fn register_local_helper(
612 &mut self,
613 name: &'render str,
614 helper: Box<dyn LocalHelper + 'render>,
615 ) {
616 let registry = Rc::make_mut(&mut self.local_helpers);
617 registry.borrow_mut().insert(name.to_string(), helper);
618 }
619
620 pub fn unregister_local_helper(&mut self, name: &'render str) {
625 let registry = Rc::make_mut(&mut self.local_helpers);
626 registry.borrow_mut().remove(name);
627 }
628
629 fn invoke<'a>(
630 &mut self,
631 name: &str,
632 target: HelperTarget<'a>,
633 call: &Call<'_>,
634 content: Option<&'render Node<'render>>,
635 text: Option<&'render str>,
636 property: Option<Property>,
637 ) -> RenderResult<HelperValue> {
638 let site = if content.is_some() {
639 CallSite::BlockHelper(name.to_string())
640 } else {
641 CallSite::Helper(name.to_string())
642 };
643
644 let amount = self.stack.iter().filter(|&n| *n == site).count();
645 if amount >= STACK_MAX {
646 return Err(RenderError::HelperCycle(site.into()));
647 }
648 self.stack.push(site);
649
650 let mut missing: Vec<MissingValue> = Vec::new();
651 let args = self.arguments(call, &mut missing)?;
652 let hash = self.hash(call, &mut missing)?;
653 let mut context = Context::new(
654 call,
655 name.to_owned(),
656 args,
657 hash,
658 text,
659 property,
660 missing,
661 );
662
663 let local_helpers = Rc::clone(&self.local_helpers);
664
665 let value: Option<Value> = match target {
666 HelperTarget::Name(name) => {
667 if let Some(helper) = local_helpers.borrow().get(name) {
668 helper.call(self, &mut context, content)?
669 } else if let Some(helper) = self.registry.helpers().get(name) {
670 helper.call(self, &mut context, content)?
671 } else {
672 None
673 }
674 }
675 HelperTarget::Helper(helper) => {
677 helper.call(self, &mut context, content)?
678 }
679 };
680
681 drop(local_helpers);
682
683 self.stack.pop();
684
685 Ok(value)
686 }
687
688 fn has_helper(&mut self, name: &str) -> bool {
689 self.local_helpers.borrow().get(name).is_some()
690 || self.registry.helpers().get(name).is_some()
691 }
692
693 fn resolve(&mut self, path: &Path<'_>) -> RenderResult<HelperValue> {
695 if let Some(value) = self.lookup(path).cloned().take() {
696 Ok(Some(value))
697 } else {
698 if self.registry.strict() {
699 Err(RenderError::VariableNotFound(
700 path.as_str().to_string(),
701 self.name.to_string(),
702 ))
703 } else {
704 Ok(None)
706 }
707 }
708 }
709
710 pub(crate) fn call(
712 &mut self,
713 call: &Call<'_>,
714 ) -> RenderResult<HelperValue> {
715 match call.target() {
716 CallTarget::Path(ref path) => {
717 if path.is_explicit() {
719 Ok(self.lookup(path).cloned())
720 } else if path.is_simple() {
722 if self.has_helper(path.as_str()) {
723 self.invoke(
724 path.as_str(),
725 HelperTarget::Name(path.as_str()),
726 call,
727 None,
728 None,
729 None,
730 )
731 } else {
732 let value = self.lookup(path).cloned();
733 if let None = value {
734 if let Some(ref helper) =
735 self.registry.handlers().helper_missing
736 {
737 return self.invoke(
738 HELPER_MISSING,
739 HelperTarget::Helper(helper),
740 call,
741 None,
742 None,
743 None,
744 );
745 } else {
746 if self.registry.strict() {
748 return Err(RenderError::VariableNotFound(
749 path.as_str().to_string(),
750 self.name.to_string(),
751 ));
752 }
753 }
754 }
755 Ok(value)
756 }
757 } else {
758 self.resolve(path)
759 }
760 }
761 CallTarget::SubExpr(ref sub) => self.call(sub),
762 }
763 }
764
765 fn statement(&mut self, call: &Call<'_>) -> RenderResult<HelperValue> {
766 if call.is_partial() {
767 self.render_partial(call, None)?;
768 Ok(None)
769 } else {
770 Ok(self.call(call)?)
771 }
772 }
773
774 fn get_partial_name<'a>(
775 &mut self,
776 call: &Call<'_>,
777 ) -> RenderResult<String> {
778 match call.target() {
779 CallTarget::Path(ref path) => {
780 if path.as_str() == PARTIAL_BLOCK {
781 return Ok(PARTIAL_BLOCK.to_string());
782 } else if path.is_simple() {
783 return Ok(path.as_str().to_string());
784 } else {
785 return Err(RenderError::PartialIdentifier(
786 path.as_str().to_string(),
787 ));
788 }
789 }
790 CallTarget::SubExpr(ref call) => {
791 let result = self.statement(call)?.unwrap_or(Value::Null);
792 return Ok(json::stringify(&result));
793 }
794 }
795 }
796
797 fn render_partial(
798 &mut self,
799 call: &Call<'_>,
800 partial_block: Option<&'render Node<'render>>,
801 ) -> RenderResult<()> {
802 let name = self.get_partial_name(call)?;
803
804 let site = CallSite::Partial(name.to_string());
805 if self.stack.contains(&site) {
806 return Err(RenderError::PartialCycle(site.into()));
807 }
808 self.stack.push(site);
809
810 if let Some(node) = partial_block {
811 self.partials.insert(PARTIAL_BLOCK.to_string(), node);
812 }
813
814 let node = if let Some(local_partial) = self.partials.get(&name) {
815 local_partial
816 } else {
817 let template = self
818 .get_template(&name)
819 .ok_or_else(|| RenderError::PartialNotFound(name))?;
820
821 self.current_partial_name.push(template.file_name());
822
823 template.node()
824 };
825
826 let mut missing: Vec<MissingValue> = Vec::new();
827 let hash = self.hash(call, &mut missing)?;
828 let scope = if !call.arguments().is_empty() {
829 let arguments = self.arguments(call, &mut missing)?;
830 if let Some(context) = arguments.get(0) {
831 Scope::from((context.clone(), hash))
832 } else {
833 Scope::from(hash)
834 }
835 } else {
836 Scope::from(hash)
837 };
838
839 self.scopes.push(scope);
840 for event in node.into_iter().event(self.hint) {
844 self.render_node(event.node, event.trim)?;
845 }
846 self.scopes.pop();
847
848 self.current_partial_name.pop();
849 self.stack.pop();
850
851 Ok(())
852 }
853
854 fn block_helper_missing(
855 &mut self,
856 node: &'render Node<'render>,
857 _block: &'render Block<'render>,
858 call: &'render Call<'render>,
859 text: Option<&str>,
860 raw: bool,
861 ) -> RenderResult<()> {
862 if raw {
865 if let Some(text) = text {
866 self.write_str(text, false)?;
867 }
868 } else {
869 match call.target() {
870 CallTarget::Path(ref path) => {
871 if let Some(value) = self.lookup(path).cloned() {
872 if let Some(ref helper) =
873 self.registry.handlers().block_helper_missing
874 {
875 let prop = Property {
876 name: path.as_str().to_string(),
877 value,
878 };
879 self.invoke(
880 BLOCK_HELPER_MISSING,
881 HelperTarget::Helper(helper),
882 call,
883 Some(node),
884 None,
885 Some(prop),
886 )?;
887 } else {
888 self.template(node)?;
890 }
891 } else if let Some(ref helper) =
892 self.registry.handlers().helper_missing
893 {
894 self.invoke(
895 HELPER_MISSING,
896 HelperTarget::Helper(helper),
897 call,
898 None,
899 None,
900 None,
901 )?;
902 } else {
903 if self.registry.strict() {
904 return Err(RenderError::HelperNotFound(
905 path.as_str().to_string(),
906 ));
907 }
908 }
909 }
910 _ => {}
911 }
912 }
913
914 Ok(())
915 }
916
917 fn block(
918 &mut self,
919 node: &'render Node<'render>,
920 block: &'render Block<'render>,
921 ) -> RenderResult<()> {
922 let call = block.call();
923 let raw = block.is_raw();
924
925 if call.is_partial() {
926 self.render_partial(call, Some(node))?;
927 } else {
928 match call.target() {
929 CallTarget::Path(ref path) => {
930 if path.is_simple() {
931 let mut text: Option<&str> = None;
932
933 if raw {
934 text = if !block.nodes().is_empty() {
936 Some(block.nodes().get(0).unwrap().as_str())
937 } else {
939 Some("")
940 };
941
942 match node {
945 Node::Block(ref block) => {
946 let hint = block.trim_close();
947
948 if node.trim().after {
950 if let Some(ref content) = text {
951 text = Some(content.trim_start());
952 }
953 }
954
955 if hint.before {
957 if let Some(ref content) = text {
958 text = Some(content.trim_end());
959 }
960 }
961
962 self.end_tag_hint = Some(hint);
964 }
965 _ => {}
966 }
967 }
968
969 if self.has_helper(path.as_str()) {
970 self.invoke(
971 path.as_str(),
972 HelperTarget::Name(path.as_str()),
973 call,
974 Some(node),
975 text,
976 None,
977 )?;
978 } else {
979 return self.block_helper_missing(
980 node, block, call, text, raw,
981 );
982 }
983 } else {
984 return Err(RenderError::BlockIdentifier(
985 path.as_str().to_string(),
986 ));
987 }
988 }
989 CallTarget::SubExpr(ref _call) => {
990 return Err(RenderError::BlockTargetSubExpr)
991 }
992 }
993 }
994 Ok(())
995 }
996
997 fn link(
999 &mut self,
1000 helper: &Box<dyn Helper + 'render>,
1001 link: &'render Link<'render>,
1002 ) -> RenderResult<()> {
1003 let lines = link.lines();
1004 let href = Value::String(link.href().to_string());
1005 let label = Value::String(link.label().to_string());
1006 let title = Value::String(link.title().to_string());
1007
1008 let mut call = Call::new(link.source(), 0..0, 0..0);
1011 call.add_argument(ParameterValue::from((
1012 link.source(),
1013 href,
1014 link.href_span().clone(),
1015 lines.clone(),
1016 )));
1017 call.add_argument(ParameterValue::from((
1018 link.source(),
1019 label,
1020 link.label_span().clone(),
1021 lines.clone(),
1022 )));
1023 call.add_argument(ParameterValue::from((
1024 link.source(),
1025 title,
1026 link.title_span().clone(),
1027 lines.clone(),
1028 )));
1029
1030 self.invoke(
1031 HELPER_LINK,
1032 HelperTarget::Helper(helper),
1033 &call,
1034 None,
1035 None,
1036 None,
1037 )?;
1038
1039 Ok(())
1040 }
1041
1042 pub(crate) fn render_node(
1043 &mut self,
1044 node: &'render Node<'render>,
1045 trim: TrimState,
1046 ) -> RenderResult<()> {
1047 self.trim = trim;
1048 self.hint = Some(node.trim());
1049
1050 if let Some(hint) = self.end_tag_hint.take() {
1051 if hint.after {
1052 self.trim.start = true;
1053 }
1054 }
1055
1056 match node {
1057 Node::Text(ref n) => {
1058 self.write_str(n.as_str(), false)?;
1059 }
1060 Node::RawStatement(ref n) => {
1061 let raw = &n.as_str()[1..];
1062 self.write_str(raw, false)?;
1063 }
1064 Node::Link(ref n) => {
1065 if n.is_escaped() {
1066 self.write_str(n.after_escape(), false)?;
1067 } else {
1068 if cfg!(feature = "links") {
1069 if let Some(helper) = &self.registry.handlers().link {
1070 self.link(helper, n)?;
1071 } else {
1072 self.write_str(n.as_str(), false)?;
1073 }
1074 } else {
1075 self.write_str(n.as_str(), false)?;
1076 }
1077 }
1078 }
1079 Node::RawComment(_) => {}
1080 Node::Comment(_) => {}
1081 Node::Document(_) => {}
1082 Node::Statement(ref call) => {
1083 if let Some(ref value) = self.statement(call)? {
1084 let val = json::stringify(value);
1085 self.write_str(&val, call.is_escaped())?;
1086 }
1087 }
1088 Node::Block(ref block) => {
1089 self.block(node, block)?;
1090 }
1091 }
1092
1093 Ok(())
1094 }
1095
1096 fn write_str(&mut self, s: &str, escape: bool) -> RenderResult<usize> {
1097 let val = if self.trim.start { s.trim_start() } else { s };
1098 let val = if self.trim.end { val.trim_end() } else { val };
1099 if val.is_empty() {
1100 return Ok(0);
1101 }
1102
1103 if escape {
1104 let escaped = (self.registry.escape())(val);
1105 Ok(self.writer.write_str(&escaped).map_err(RenderError::from)?)
1106 } else {
1107 Ok(self.writer.write_str(val).map_err(RenderError::from)?)
1108 }
1109 }
1110}