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 transform_table_cell(&mut self, cell: TableCell) -> TableCell {
73 self.walk_transform_table_cell(cell)
74 }
75
76 fn transform_list_item(&mut self, item: ListItem) -> ListItem {
78 self.walk_transform_list_item(item)
79 }
80
81 fn transform_table_row(&mut self, row: TableRow) -> TableRow {
83 self.walk_transform_table_row(row)
84 }
85
86 fn transform_heading(&mut self, heading: Heading) -> Heading {
88 self.walk_transform_heading(heading)
89 }
90
91 fn transform_link(&mut self, link: Link) -> Link {
93 self.walk_transform_link(link)
94 }
95
96 fn transform_image(&mut self, image: Image) -> Image {
98 self.walk_transform_image(image)
99 }
100
101 fn transform_code_block(&mut self, code_block: CodeBlock) -> CodeBlock {
103 self.walk_transform_code_block(code_block)
104 }
105
106 fn transform_text(&mut self, text: String) -> String {
108 self.walk_transform_text(text)
109 }
110
111 fn transform_footnote_definition(
113 &mut self,
114 footnote: FootnoteDefinition,
115 ) -> FootnoteDefinition {
116 self.walk_transform_footnote_definition(footnote)
117 }
118
119 fn transform_github_alert(&mut self, alert: GitHubAlert) -> GitHubAlert {
121 self.walk_transform_github_alert(alert)
122 }
123
124 fn walk_transform_document(&mut self, mut doc: Document) -> Document {
126 doc.blocks = doc
127 .blocks
128 .into_iter()
129 .map(|block| self.transform_block(block))
130 .collect();
131 doc
132 }
133
134 fn walk_transform_block(&mut self, block: Block) -> Block {
136 match block {
137 Block::Paragraph(inlines) => Block::Paragraph(
138 inlines
139 .into_iter()
140 .map(|inline| self.transform_inline(inline))
141 .collect(),
142 ),
143 Block::Heading(heading) => Block::Heading(self.transform_heading(heading)),
144 Block::BlockQuote(blocks) => Block::BlockQuote(
145 blocks
146 .into_iter()
147 .map(|block| self.transform_block(block))
148 .collect(),
149 ),
150 Block::List(mut list) => {
151 list.items = list
152 .items
153 .into_iter()
154 .map(|item| self.transform_list_item(item))
155 .collect();
156 Block::List(list)
157 }
158 Block::Table(mut table) => {
159 table.rows = table
160 .rows
161 .into_iter()
162 .map(|row| self.transform_table_row(row))
163 .collect();
164 Block::Table(table)
165 }
166 Block::FootnoteDefinition(footnote) => {
167 Block::FootnoteDefinition(self.transform_footnote_definition(footnote))
168 }
169 Block::GitHubAlert(alert) => Block::GitHubAlert(self.transform_github_alert(alert)),
170 Block::Definition(mut def) => {
171 def.label = def
172 .label
173 .into_iter()
174 .map(|inline| self.transform_inline(inline))
175 .collect();
176 Block::Definition(def)
177 }
178 Block::CodeBlock(code_block) => Block::CodeBlock(self.transform_code_block(code_block)),
179 other => other,
181 }
182 }
183
184 fn walk_transform_inline(&mut self, inline: Inline) -> Inline {
186 match inline {
187 Inline::Emphasis(inlines) => Inline::Emphasis(
188 inlines
189 .into_iter()
190 .map(|inline| self.transform_inline(inline))
191 .collect(),
192 ),
193 Inline::Strong(inlines) => Inline::Strong(
194 inlines
195 .into_iter()
196 .map(|inline| self.transform_inline(inline))
197 .collect(),
198 ),
199 Inline::Strikethrough(inlines) => Inline::Strikethrough(
200 inlines
201 .into_iter()
202 .map(|inline| self.transform_inline(inline))
203 .collect(),
204 ),
205 Inline::Link(link) => Inline::Link(self.transform_link(link)),
206 Inline::LinkReference(mut link_ref) => {
207 link_ref.label = link_ref
208 .label
209 .into_iter()
210 .map(|inline| self.transform_inline(inline))
211 .collect();
212 link_ref.text = link_ref
213 .text
214 .into_iter()
215 .map(|inline| self.transform_inline(inline))
216 .collect();
217 Inline::LinkReference(link_ref)
218 }
219 Inline::Image(image) => Inline::Image(self.transform_image(image)),
220 Inline::Text(text) => Inline::Text(self.transform_text(text)),
221 other => other,
223 }
224 }
225
226 fn walk_transform_table_cell(&mut self, cell: TableCell) -> TableCell {
228 cell.into_iter()
229 .map(|inline| self.transform_inline(inline))
230 .collect()
231 }
232
233 fn walk_transform_list_item(&mut self, mut item: ListItem) -> ListItem {
235 item.blocks = item
236 .blocks
237 .into_iter()
238 .map(|block| self.transform_block(block))
239 .collect();
240 item
241 }
242
243 fn walk_transform_table_row(&mut self, row: TableRow) -> TableRow {
245 row.into_iter()
246 .map(|cell| self.transform_table_cell(cell))
247 .collect()
248 }
249
250 fn walk_transform_heading(&mut self, mut heading: Heading) -> Heading {
252 heading.content = heading
253 .content
254 .into_iter()
255 .map(|inline| self.transform_inline(inline))
256 .collect();
257 heading
258 }
259
260 fn walk_transform_link(&mut self, mut link: Link) -> Link {
262 link.children = link
263 .children
264 .into_iter()
265 .map(|inline| self.transform_inline(inline))
266 .collect();
267 link
268 }
269
270 fn walk_transform_image(&mut self, image: Image) -> Image {
272 image
274 }
275
276 fn walk_transform_code_block(&mut self, code_block: CodeBlock) -> CodeBlock {
278 code_block
280 }
281
282 fn walk_transform_text(&mut self, text: String) -> String {
284 text
286 }
287
288 fn walk_transform_footnote_definition(
290 &mut self,
291 mut footnote: FootnoteDefinition,
292 ) -> FootnoteDefinition {
293 footnote.blocks = footnote
294 .blocks
295 .into_iter()
296 .map(|block| self.transform_block(block))
297 .collect();
298 footnote
299 }
300
301 fn walk_transform_github_alert(&mut self, mut alert: GitHubAlert) -> GitHubAlert {
303 alert.blocks = alert
304 .blocks
305 .into_iter()
306 .map(|block| self.transform_block(block))
307 .collect();
308 alert
309 }
310}
311
312pub trait TransformWith {
314 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self;
316}
317
318impl TransformWith for Document {
319 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
320 transformer.transform_document(self)
321 }
322}
323
324impl TransformWith for Block {
325 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
326 transformer.transform_block(self)
327 }
328}
329
330impl TransformWith for Inline {
331 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
332 transformer.transform_inline(self)
333 }
334}
335
336pub struct CompositeTransformer {
338 transformers: Vec<Box<dyn Transformer>>,
339}
340
341impl CompositeTransformer {
342 pub fn new() -> Self {
344 Self {
345 transformers: Vec::new(),
346 }
347 }
348
349 pub fn add_transformer<T: Transformer + 'static>(mut self, transformer: T) -> Self {
351 self.transformers.push(Box::new(transformer));
352 self
353 }
354}
355
356impl Default for CompositeTransformer {
357 fn default() -> Self {
358 Self::new()
359 }
360}
361
362impl Transformer for CompositeTransformer {
363 fn transform_document(&mut self, mut doc: Document) -> Document {
364 for transformer in &mut self.transformers {
365 doc = transformer.transform_document(doc);
366 }
367 doc
368 }
369
370 fn transform_block(&mut self, mut block: Block) -> Block {
371 for transformer in &mut self.transformers {
372 block = transformer.transform_block(block);
373 }
374 block
375 }
376
377 fn transform_inline(&mut self, mut inline: Inline) -> Inline {
378 for transformer in &mut self.transformers {
379 inline = transformer.transform_inline(inline);
380 }
381 inline
382 }
383}