markdown_ppp/ast_transform/
transformer.rs1use crate::ast::*;
32
33pub trait Transformer {
56 fn transform_document(&mut self, doc: Document) -> Document {
58 self.walk_transform_document(doc)
59 }
60
61 fn transform_block(&mut self, block: Block) -> Block {
63 self.walk_transform_block(block)
64 }
65
66 fn transform_inline(&mut self, inline: Inline) -> Inline {
68 self.walk_transform_inline(inline)
69 }
70
71 fn walk_transform_document(&mut self, mut doc: Document) -> Document {
73 doc.blocks = doc
74 .blocks
75 .into_iter()
76 .map(|block| self.transform_block(block))
77 .collect();
78 doc
79 }
80
81 fn walk_transform_block(&mut self, block: Block) -> Block {
83 match block {
84 Block::Paragraph(inlines) => Block::Paragraph(
85 inlines
86 .into_iter()
87 .map(|inline| self.transform_inline(inline))
88 .collect(),
89 ),
90 Block::Heading(mut heading) => {
91 heading.content = heading
92 .content
93 .into_iter()
94 .map(|inline| self.transform_inline(inline))
95 .collect();
96 Block::Heading(heading)
97 }
98 Block::BlockQuote(blocks) => Block::BlockQuote(
99 blocks
100 .into_iter()
101 .map(|block| self.transform_block(block))
102 .collect(),
103 ),
104 Block::List(mut list) => {
105 list.items = list
106 .items
107 .into_iter()
108 .map(|mut item| {
109 item.blocks = item
110 .blocks
111 .into_iter()
112 .map(|block| self.transform_block(block))
113 .collect();
114 item
115 })
116 .collect();
117 Block::List(list)
118 }
119 Block::Table(mut table) => {
120 table.rows = table
121 .rows
122 .into_iter()
123 .map(|row| {
124 row.into_iter()
125 .map(|cell| {
126 cell.into_iter()
127 .map(|inline| self.transform_inline(inline))
128 .collect()
129 })
130 .collect()
131 })
132 .collect();
133 Block::Table(table)
134 }
135 Block::FootnoteDefinition(mut footnote) => {
136 footnote.blocks = footnote
137 .blocks
138 .into_iter()
139 .map(|block| self.transform_block(block))
140 .collect();
141 Block::FootnoteDefinition(footnote)
142 }
143 Block::GitHubAlert(mut alert) => {
144 alert.blocks = alert
145 .blocks
146 .into_iter()
147 .map(|block| self.transform_block(block))
148 .collect();
149 Block::GitHubAlert(alert)
150 }
151 Block::Definition(mut def) => {
152 def.label = def
153 .label
154 .into_iter()
155 .map(|inline| self.transform_inline(inline))
156 .collect();
157 Block::Definition(def)
158 }
159 other => other,
161 }
162 }
163
164 fn walk_transform_inline(&mut self, inline: Inline) -> Inline {
166 match inline {
167 Inline::Emphasis(inlines) => Inline::Emphasis(
168 inlines
169 .into_iter()
170 .map(|inline| self.transform_inline(inline))
171 .collect(),
172 ),
173 Inline::Strong(inlines) => Inline::Strong(
174 inlines
175 .into_iter()
176 .map(|inline| self.transform_inline(inline))
177 .collect(),
178 ),
179 Inline::Strikethrough(inlines) => Inline::Strikethrough(
180 inlines
181 .into_iter()
182 .map(|inline| self.transform_inline(inline))
183 .collect(),
184 ),
185 Inline::Link(mut link) => {
186 link.children = link
187 .children
188 .into_iter()
189 .map(|inline| self.transform_inline(inline))
190 .collect();
191 Inline::Link(link)
192 }
193 Inline::LinkReference(mut link_ref) => {
194 link_ref.label = link_ref
195 .label
196 .into_iter()
197 .map(|inline| self.transform_inline(inline))
198 .collect();
199 link_ref.text = link_ref
200 .text
201 .into_iter()
202 .map(|inline| self.transform_inline(inline))
203 .collect();
204 Inline::LinkReference(link_ref)
205 }
206 other => other,
208 }
209 }
210}
211
212pub trait TransformWith {
214 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self;
216}
217
218impl TransformWith for Document {
219 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
220 transformer.transform_document(self)
221 }
222}
223
224impl TransformWith for Block {
225 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
226 transformer.transform_block(self)
227 }
228}
229
230impl TransformWith for Inline {
231 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
232 transformer.transform_inline(self)
233 }
234}
235
236pub struct CompositeTransformer {
238 transformers: Vec<Box<dyn Transformer>>,
239}
240
241impl CompositeTransformer {
242 pub fn new() -> Self {
244 Self {
245 transformers: Vec::new(),
246 }
247 }
248
249 pub fn add_transformer<T: Transformer + 'static>(mut self, transformer: T) -> Self {
251 self.transformers.push(Box::new(transformer));
252 self
253 }
254}
255
256impl Default for CompositeTransformer {
257 fn default() -> Self {
258 Self::new()
259 }
260}
261
262impl Transformer for CompositeTransformer {
263 fn transform_document(&mut self, mut doc: Document) -> Document {
264 for transformer in &mut self.transformers {
265 doc = transformer.transform_document(doc);
266 }
267 doc
268 }
269
270 fn transform_block(&mut self, mut block: Block) -> Block {
271 for transformer in &mut self.transformers {
272 block = transformer.transform_block(block);
273 }
274 block
275 }
276
277 fn transform_inline(&mut self, mut inline: Inline) -> Inline {
278 for transformer in &mut self.transformers {
279 inline = transformer.transform_inline(inline);
280 }
281 inline
282 }
283}