libhanzzok/codegen/walker/
decorator_chain.rs1use v_htmlescape::escape;
2
3use crate::{
4 codegen::{Context, HtmlNode},
5 core::ast::{DecoratorChainNode, InlineObjectNode, Raw, TextNode},
6 syntax::{Token, TokenKind},
7};
8
9use super::Walker;
10
11impl Walker<DecoratorChainNode> for Context<'_> {
12 fn walk(&mut self, node: DecoratorChainNode) -> Vec<crate::codegen::HtmlNode> {
13 let should_be_raw_until = node
14 .decorators
15 .iter()
16 .enumerate()
17 .find(|(_, node)| {
18 self.compiler
19 .decorator_rules
20 .get(&node.name)
21 .map(|rule| rule.accept_raw_text())
22 .unwrap_or(false)
23 })
24 .map(|(index, _)| index + 1)
25 .unwrap_or(0);
26 let should_be_raw = should_be_raw_until > 0;
27 let should_be_raw_until = if should_be_raw {
28 should_be_raw_until - 1
29 } else {
30 should_be_raw_until
31 };
32 let mut nodes = if should_be_raw {
33 vec![HtmlNode::create_text(
34 escape(
35 &node
36 .main_text
37 .raw()
38 .into_iter()
39 .chain(
40 node.decorators
41 .iter()
42 .take(should_be_raw_until)
43 .flat_map(|node| node.raw()),
44 )
45 .map(|t| t.text.clone())
46 .collect::<String>()
47 .trim_end(),
48 )
49 .to_string(),
50 )]
51 } else {
52 let node = match *node.main_text {
53 InlineObjectNode::Text(text) => {
54 let mut tokens = text.tokens;
55 while let Some((
56 (
57 Token {
58 kind: TokenKind::HorizontalSpace,
59 ..
60 },
61 _,
62 ),
63 elements,
64 )) = tokens.split_last_mut()
65 {
66 if let Some((
67 Token {
68 kind: TokenKind::PunctuationReverseSolidus,
69 ..
70 },
71 _,
72 )) = elements.last()
73 {
74 break;
75 }
76
77 tokens = elements.to_vec();
78 }
79 InlineObjectNode::Text(TextNode { tokens })
80 }
81 a @ _ => a,
82 };
83
84 self.walk(node)
85 };
86 let mut is_first = true;
87 for decorator in node.decorators.into_iter().skip(should_be_raw_until) {
88 let rule = match self.compiler.decorator_rules.get(&decorator.name) {
89 Some(rule) => rule,
90 None => continue,
91 };
92 if !is_first && rule.accept_raw_text() {
93 continue;
94 }
95 is_first = false;
96 nodes = rule.apply(
97 self,
98 nodes,
99 decorator
100 .params
101 .and_then(|s| serde_hzdata::from_str(&s).ok()),
102 );
103 }
104 nodes
105 }
106}