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 expand_document(&mut self, doc: Document) -> Vec<Document> {
296 vec![self.transform_document(doc)]
297 }
298
299 fn expand_block(&mut self, block: Block) -> Vec<Block> {
308 vec![self.transform_block(block)]
309 }
310
311 fn expand_inline(&mut self, inline: Inline) -> Vec<Inline> {
320 vec![self.transform_inline(inline)]
321 }
322
323 fn expand_table_cell(&mut self, cell: TableCell) -> Vec<TableCell> {
325 vec![self.transform_table_cell(cell)]
326 }
327
328 fn expand_list_item(&mut self, item: ListItem) -> Vec<ListItem> {
330 vec![self.transform_list_item(item)]
331 }
332
333 fn expand_table_row(&mut self, row: TableRow) -> Vec<TableRow> {
335 vec![self.transform_table_row(row)]
336 }
337
338 fn expand_heading(&mut self, heading: Heading) -> Vec<Heading> {
340 vec![self.transform_heading(heading)]
341 }
342
343 fn expand_link(&mut self, link: Link) -> Vec<Link> {
345 vec![self.transform_link(link)]
346 }
347
348 fn expand_image(&mut self, image: Image) -> Vec<Image> {
350 vec![self.transform_image(image)]
351 }
352
353 fn expand_code_block(&mut self, code_block: CodeBlock) -> Vec<CodeBlock> {
355 vec![self.transform_code_block(code_block)]
356 }
357
358 fn expand_text(&mut self, text: String) -> Vec<String> {
360 vec![self.transform_text(text)]
361 }
362
363 fn expand_footnote_definition(
365 &mut self,
366 footnote: FootnoteDefinition,
367 ) -> Vec<FootnoteDefinition> {
368 vec![self.transform_footnote_definition(footnote)]
369 }
370
371 fn expand_github_alert(&mut self, alert: GitHubAlert) -> Vec<GitHubAlert> {
373 vec![self.transform_github_alert(alert)]
374 }
375
376 fn walk_expand_document(&mut self, mut doc: Document) -> Vec<Document> {
385 doc.blocks = doc
386 .blocks
387 .into_iter()
388 .flat_map(|block| self.walk_expand_block(block))
389 .collect();
390 vec![doc]
391 }
392
393 fn walk_expand_block(&mut self, block: Block) -> Vec<Block> {
399 match block {
400 Block::Paragraph(inlines) => {
401 let expanded_inlines: Vec<Inline> = inlines
402 .into_iter()
403 .flat_map(|inline| self.walk_expand_inline(inline))
404 .collect();
405 vec![Block::Paragraph(expanded_inlines)]
406 }
407 Block::Heading(mut heading) => {
408 heading.content = heading
409 .content
410 .into_iter()
411 .flat_map(|inline| self.walk_expand_inline(inline))
412 .collect();
413 vec![Block::Heading(heading)]
414 }
415 Block::BlockQuote(blocks) => {
416 let expanded_blocks: Vec<Block> = blocks
417 .into_iter()
418 .flat_map(|block| self.walk_expand_block(block))
419 .collect();
420 vec![Block::BlockQuote(expanded_blocks)]
421 }
422 Block::List(mut list) => {
423 list.items = list
424 .items
425 .into_iter()
426 .flat_map(|item| self.walk_expand_list_item(item))
427 .collect();
428 vec![Block::List(list)]
429 }
430 Block::Table(mut table) => {
431 table.rows = table
432 .rows
433 .into_iter()
434 .flat_map(|row| self.walk_expand_table_row(row))
435 .collect();
436 vec![Block::Table(table)]
437 }
438 Block::FootnoteDefinition(mut footnote) => {
439 footnote.blocks = footnote
440 .blocks
441 .into_iter()
442 .flat_map(|block| self.walk_expand_block(block))
443 .collect();
444 vec![Block::FootnoteDefinition(footnote)]
445 }
446 Block::GitHubAlert(mut alert) => {
447 alert.blocks = alert
448 .blocks
449 .into_iter()
450 .flat_map(|block| self.walk_expand_block(block))
451 .collect();
452 vec![Block::GitHubAlert(alert)]
453 }
454 Block::Definition(mut def) => {
455 def.label = def
456 .label
457 .into_iter()
458 .flat_map(|inline| self.walk_expand_inline(inline))
459 .collect();
460 vec![Block::Definition(def)]
461 }
462 other => vec![self.transform_block(other)],
464 }
465 }
466
467 fn walk_expand_inline(&mut self, inline: Inline) -> Vec<Inline> {
472 vec![self.transform_inline(inline)]
473 }
474
475 fn walk_expand_table_cell(&mut self, cell: TableCell) -> Vec<TableCell> {
477 let expanded_cell = cell
478 .into_iter()
479 .flat_map(|inline| self.expand_inline(inline))
480 .collect();
481 vec![expanded_cell]
482 }
483
484 fn walk_expand_list_item(&mut self, mut item: ListItem) -> Vec<ListItem> {
486 item.blocks = item
487 .blocks
488 .into_iter()
489 .flat_map(|block| self.expand_block(block))
490 .collect();
491 vec![item]
492 }
493
494 fn walk_expand_table_row(&mut self, row: TableRow) -> Vec<TableRow> {
496 let expanded_row = row
497 .into_iter()
498 .flat_map(|cell| self.expand_table_cell(cell))
499 .collect();
500 vec![expanded_row]
501 }
502
503 fn walk_expand_heading(&mut self, mut heading: Heading) -> Vec<Heading> {
505 heading.content = heading
506 .content
507 .into_iter()
508 .flat_map(|inline| self.expand_inline(inline))
509 .collect();
510 vec![heading]
511 }
512
513 fn walk_expand_link(&mut self, mut link: Link) -> Vec<Link> {
515 link.children = link
516 .children
517 .into_iter()
518 .flat_map(|inline| self.expand_inline(inline))
519 .collect();
520 vec![link]
521 }
522
523 fn walk_expand_image(&mut self, image: Image) -> Vec<Image> {
525 vec![image]
527 }
528
529 fn walk_expand_code_block(&mut self, code_block: CodeBlock) -> Vec<CodeBlock> {
531 vec![code_block]
533 }
534
535 fn walk_expand_text(&mut self, text: String) -> Vec<String> {
537 vec![text]
539 }
540
541 fn walk_expand_footnote_definition(
543 &mut self,
544 mut footnote: FootnoteDefinition,
545 ) -> Vec<FootnoteDefinition> {
546 footnote.blocks = footnote
547 .blocks
548 .into_iter()
549 .flat_map(|block| self.expand_block(block))
550 .collect();
551 vec![footnote]
552 }
553
554 fn walk_expand_github_alert(&mut self, mut alert: GitHubAlert) -> Vec<GitHubAlert> {
556 alert.blocks = alert
557 .blocks
558 .into_iter()
559 .flat_map(|block| self.expand_block(block))
560 .collect();
561 vec![alert]
562 }
563
564 fn walk_transform_footnote_definition(
566 &mut self,
567 mut footnote: FootnoteDefinition,
568 ) -> FootnoteDefinition {
569 footnote.blocks = footnote
570 .blocks
571 .into_iter()
572 .map(|block| self.transform_block(block))
573 .collect();
574 footnote
575 }
576
577 fn walk_transform_github_alert(&mut self, mut alert: GitHubAlert) -> GitHubAlert {
579 alert.blocks = alert
580 .blocks
581 .into_iter()
582 .map(|block| self.transform_block(block))
583 .collect();
584 alert
585 }
586}
587
588pub trait TransformWith {
590 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self;
592}
593
594impl TransformWith for Document {
595 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
596 transformer.transform_document(self)
597 }
598}
599
600impl TransformWith for Block {
601 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
602 transformer.transform_block(self)
603 }
604}
605
606impl TransformWith for Inline {
607 fn transform_with<T: Transformer>(self, transformer: &mut T) -> Self {
608 transformer.transform_inline(self)
609 }
610}
611
612pub trait ExpandWith {
614 fn expand_with<T: Transformer>(self, transformer: &mut T) -> Vec<Self>
616 where
617 Self: Sized;
618}
619
620impl ExpandWith for Document {
621 fn expand_with<T: Transformer>(self, transformer: &mut T) -> Vec<Self> {
622 transformer.walk_expand_document(self)
623 }
624}
625
626impl ExpandWith for Block {
627 fn expand_with<T: Transformer>(self, transformer: &mut T) -> Vec<Self> {
628 transformer.walk_expand_block(self)
629 }
630}
631
632impl ExpandWith for Inline {
633 fn expand_with<T: Transformer>(self, transformer: &mut T) -> Vec<Self> {
634 transformer.walk_expand_inline(self)
635 }
636}
637
638pub struct CompositeTransformer {
640 transformers: Vec<Box<dyn Transformer>>,
641}
642
643impl CompositeTransformer {
644 pub fn new() -> Self {
646 Self {
647 transformers: Vec::new(),
648 }
649 }
650
651 pub fn add_transformer<T: Transformer + 'static>(mut self, transformer: T) -> Self {
653 self.transformers.push(Box::new(transformer));
654 self
655 }
656}
657
658impl Default for CompositeTransformer {
659 fn default() -> Self {
660 Self::new()
661 }
662}
663
664impl Transformer for CompositeTransformer {
665 fn transform_document(&mut self, mut doc: Document) -> Document {
666 for transformer in &mut self.transformers {
667 doc = transformer.transform_document(doc);
668 }
669 doc
670 }
671
672 fn transform_block(&mut self, mut block: Block) -> Block {
673 for transformer in &mut self.transformers {
674 block = transformer.transform_block(block);
675 }
676 block
677 }
678
679 fn transform_inline(&mut self, mut inline: Inline) -> Inline {
680 for transformer in &mut self.transformers {
681 inline = transformer.transform_inline(inline);
682 }
683 inline
684 }
685}