use crate::ast::generic::*;
pub trait GenericTransformer<T> {
fn transform_document(&mut self, doc: Document<T>) -> Document<T> {
self.walk_transform_document(doc)
}
fn transform_block(&mut self, block: Block<T>) -> Block<T> {
self.walk_transform_block(block)
}
fn transform_inline(&mut self, inline: Inline<T>) -> Inline<T> {
self.walk_transform_inline(inline)
}
fn transform_table_cell(&mut self, cell: TableCell<T>) -> TableCell<T> {
self.walk_transform_table_cell(cell)
}
fn transform_list_item(&mut self, item: ListItem<T>) -> ListItem<T> {
self.walk_transform_list_item(item)
}
fn transform_table_row(&mut self, row: TableRow<T>) -> TableRow<T> {
self.walk_transform_table_row(row)
}
fn transform_heading(&mut self, heading: Heading<T>) -> Heading<T> {
self.walk_transform_heading(heading)
}
fn transform_link(&mut self, link: Link<T>) -> Link<T> {
self.walk_transform_link(link)
}
fn transform_image(&mut self, image: Image<T>) -> Image<T> {
self.walk_transform_image(image)
}
fn transform_code_block(&mut self, code_block: CodeBlock<T>) -> CodeBlock<T> {
self.walk_transform_code_block(code_block)
}
fn transform_footnote_definition(
&mut self,
footnote: FootnoteDefinition<T>,
) -> FootnoteDefinition<T> {
self.walk_transform_footnote_definition(footnote)
}
fn transform_github_alert(&mut self, alert: GitHubAlertNode<T>) -> GitHubAlertNode<T> {
self.walk_transform_github_alert(alert)
}
fn expand_document(&mut self, doc: Document<T>) -> Vec<Document<T>> {
vec![self.transform_document(doc)]
}
fn expand_block(&mut self, block: Block<T>) -> Vec<Block<T>> {
vec![self.transform_block(block)]
}
fn expand_inline(&mut self, inline: Inline<T>) -> Vec<Inline<T>> {
vec![self.transform_inline(inline)]
}
fn expand_table_cell(&mut self, cell: TableCell<T>) -> Vec<TableCell<T>> {
vec![self.transform_table_cell(cell)]
}
fn expand_list_item(&mut self, item: ListItem<T>) -> Vec<ListItem<T>> {
vec![self.transform_list_item(item)]
}
fn expand_table_row(&mut self, row: TableRow<T>) -> Vec<TableRow<T>> {
vec![self.transform_table_row(row)]
}
fn expand_heading(&mut self, heading: Heading<T>) -> Vec<Heading<T>> {
vec![self.transform_heading(heading)]
}
fn expand_link(&mut self, link: Link<T>) -> Vec<Link<T>> {
vec![self.transform_link(link)]
}
fn expand_image(&mut self, image: Image<T>) -> Vec<Image<T>> {
vec![self.transform_image(image)]
}
fn expand_code_block(&mut self, code_block: CodeBlock<T>) -> Vec<CodeBlock<T>> {
vec![self.transform_code_block(code_block)]
}
fn expand_footnote_definition(
&mut self,
footnote: FootnoteDefinition<T>,
) -> Vec<FootnoteDefinition<T>> {
vec![self.transform_footnote_definition(footnote)]
}
fn expand_github_alert(&mut self, alert: GitHubAlertNode<T>) -> Vec<GitHubAlertNode<T>> {
vec![self.transform_github_alert(alert)]
}
fn walk_transform_document(&mut self, mut doc: Document<T>) -> Document<T> {
doc.blocks = doc
.blocks
.into_iter()
.map(|block| self.transform_block(block))
.collect();
doc
}
fn walk_transform_block(&mut self, block: Block<T>) -> Block<T> {
match block {
Block::Paragraph { content, user_data } => Block::Paragraph {
content: content
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect(),
user_data,
},
Block::Heading(heading) => Block::Heading(self.transform_heading(heading)),
Block::BlockQuote { blocks, user_data } => Block::BlockQuote {
blocks: blocks
.into_iter()
.map(|block| self.transform_block(block))
.collect(),
user_data,
},
Block::List(list) => Block::List(self.transform_list_item_container(list)),
Block::Table(table) => Block::Table(self.transform_table(table)),
Block::FootnoteDefinition(footnote) => {
Block::FootnoteDefinition(self.transform_footnote_definition(footnote))
}
Block::GitHubAlert(alert) => Block::GitHubAlert(self.transform_github_alert(alert)),
Block::Definition(mut def) => {
def.label = def
.label
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect();
Block::Definition(def)
}
Block::CodeBlock(code_block) => Block::CodeBlock(self.transform_code_block(code_block)),
other => other,
}
}
fn walk_transform_inline(&mut self, inline: Inline<T>) -> Inline<T> {
match inline {
Inline::Emphasis { content, user_data } => Inline::Emphasis {
content: content
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect(),
user_data,
},
Inline::Strong { content, user_data } => Inline::Strong {
content: content
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect(),
user_data,
},
Inline::Strikethrough { content, user_data } => Inline::Strikethrough {
content: content
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect(),
user_data,
},
Inline::Link(link) => Inline::Link(self.transform_link(link)),
Inline::LinkReference(mut link_ref) => {
link_ref.label = link_ref
.label
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect();
link_ref.text = link_ref
.text
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect();
Inline::LinkReference(link_ref)
}
Inline::Image(image) => Inline::Image(self.transform_image(image)),
other => other,
}
}
fn walk_transform_table_cell(&mut self, cell: TableCell<T>) -> TableCell<T> {
cell.into_iter()
.map(|inline| self.transform_inline(inline))
.collect()
}
fn walk_transform_list_item(&mut self, mut item: ListItem<T>) -> ListItem<T> {
item.blocks = item
.blocks
.into_iter()
.map(|block| self.transform_block(block))
.collect();
item
}
fn walk_transform_table_row(&mut self, row: TableRow<T>) -> TableRow<T> {
row.into_iter()
.map(|cell| self.transform_table_cell(cell))
.collect()
}
fn walk_transform_heading(&mut self, mut heading: Heading<T>) -> Heading<T> {
heading.content = heading
.content
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect();
heading
}
fn walk_transform_link(&mut self, mut link: Link<T>) -> Link<T> {
link.children = link
.children
.into_iter()
.map(|inline| self.transform_inline(inline))
.collect();
link
}
fn walk_transform_image(&mut self, image: Image<T>) -> Image<T> {
image
}
fn walk_transform_code_block(&mut self, code_block: CodeBlock<T>) -> CodeBlock<T> {
code_block
}
fn walk_transform_footnote_definition(
&mut self,
mut footnote: FootnoteDefinition<T>,
) -> FootnoteDefinition<T> {
footnote.blocks = footnote
.blocks
.into_iter()
.map(|block| self.transform_block(block))
.collect();
footnote
}
fn walk_transform_github_alert(&mut self, mut alert: GitHubAlertNode<T>) -> GitHubAlertNode<T> {
alert.blocks = alert
.blocks
.into_iter()
.map(|block| self.transform_block(block))
.collect();
alert
}
fn transform_list_item_container(&mut self, mut list: List<T>) -> List<T> {
list.items = list
.items
.into_iter()
.map(|item| self.transform_list_item(item))
.collect();
list
}
fn transform_table(&mut self, mut table: Table<T>) -> Table<T> {
table.rows = table
.rows
.into_iter()
.map(|row| self.transform_table_row(row))
.collect();
table
}
fn walk_expand_document(&mut self, mut doc: Document<T>) -> Vec<Document<T>> {
doc.blocks = doc
.blocks
.into_iter()
.flat_map(|block| self.walk_expand_block(block))
.collect();
vec![doc]
}
fn walk_expand_block(&mut self, block: Block<T>) -> Vec<Block<T>> {
let transformed_block = match block {
Block::Paragraph { content, user_data } => Block::Paragraph {
content: content
.into_iter()
.flat_map(|inline| self.walk_expand_inline(inline))
.collect(),
user_data,
},
Block::Heading(heading) => {
let expanded_headings = self.expand_heading(heading);
return expanded_headings.into_iter().map(Block::Heading).collect();
}
Block::BlockQuote { blocks, user_data } => Block::BlockQuote {
blocks: blocks
.into_iter()
.flat_map(|block| self.walk_expand_block(block))
.collect(),
user_data,
},
Block::List(list) => {
let expanded_list = self.expand_list_container(list);
return expanded_list.into_iter().map(Block::List).collect();
}
Block::Table(table) => {
let expanded_table = self.expand_table_container(table);
return expanded_table.into_iter().map(Block::Table).collect();
}
Block::FootnoteDefinition(footnote) => {
let expanded_footnotes = self.expand_footnote_definition(footnote);
return expanded_footnotes
.into_iter()
.map(Block::FootnoteDefinition)
.collect();
}
Block::GitHubAlert(alert) => {
let expanded_alerts = self.expand_github_alert(alert);
return expanded_alerts
.into_iter()
.map(Block::GitHubAlert)
.collect();
}
Block::Definition(mut def) => {
def.label = def
.label
.into_iter()
.flat_map(|inline| self.walk_expand_inline(inline))
.collect();
Block::Definition(def)
}
Block::CodeBlock(code_block) => {
let expanded_code_blocks = self.expand_code_block(code_block);
return expanded_code_blocks
.into_iter()
.map(Block::CodeBlock)
.collect();
}
other => other,
};
vec![transformed_block]
}
fn walk_expand_inline(&mut self, inline: Inline<T>) -> Vec<Inline<T>> {
let transformed_inline = match inline {
Inline::Emphasis { content, user_data } => Inline::Emphasis {
content: content
.into_iter()
.flat_map(|inline| self.walk_expand_inline(inline))
.collect(),
user_data,
},
Inline::Strong { content, user_data } => Inline::Strong {
content: content
.into_iter()
.flat_map(|inline| self.walk_expand_inline(inline))
.collect(),
user_data,
},
Inline::Strikethrough { content, user_data } => Inline::Strikethrough {
content: content
.into_iter()
.flat_map(|inline| self.walk_expand_inline(inline))
.collect(),
user_data,
},
Inline::Link(link) => {
let expanded_links = self.expand_link(link);
return expanded_links.into_iter().map(Inline::Link).collect();
}
Inline::LinkReference(mut link_ref) => {
link_ref.label = link_ref
.label
.into_iter()
.flat_map(|inline| self.walk_expand_inline(inline))
.collect();
link_ref.text = link_ref
.text
.into_iter()
.flat_map(|inline| self.walk_expand_inline(inline))
.collect();
Inline::LinkReference(link_ref)
}
Inline::Image(image) => {
let expanded_images = self.expand_image(image);
return expanded_images.into_iter().map(Inline::Image).collect();
}
other => other,
};
vec![transformed_inline]
}
fn expand_list_container(&mut self, mut list: List<T>) -> Vec<List<T>> {
list.items = list
.items
.into_iter()
.flat_map(|item| self.expand_list_item(item))
.collect();
vec![list]
}
fn expand_table_container(&mut self, mut table: Table<T>) -> Vec<Table<T>> {
table.rows = table
.rows
.into_iter()
.flat_map(|row| self.expand_table_row(row))
.collect();
vec![table]
}
}
pub trait GenericTransformWith<T> {
fn transform_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Self;
}
impl<T> GenericTransformWith<T> for Document<T> {
fn transform_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Self {
transformer.transform_document(self)
}
}
impl<T> GenericTransformWith<T> for Block<T> {
fn transform_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Self {
transformer.transform_block(self)
}
}
impl<T> GenericTransformWith<T> for Inline<T> {
fn transform_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Self {
transformer.transform_inline(self)
}
}
pub trait GenericExpandWith<T> {
fn expand_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Vec<Self>
where
Self: Sized;
}
impl<T> GenericExpandWith<T> for Document<T> {
fn expand_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Vec<Self> {
transformer.walk_expand_document(self)
}
}
impl<T> GenericExpandWith<T> for Block<T> {
fn expand_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Vec<Self> {
transformer.walk_expand_block(self)
}
}
impl<T> GenericExpandWith<T> for Inline<T> {
fn expand_with<Tr: GenericTransformer<T>>(self, transformer: &mut Tr) -> Vec<Self> {
transformer.walk_expand_inline(self)
}
}