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