use super::transformer::Transformer;
use crate::ast::*;
pub struct TransformPipeline {
steps: Vec<Box<dyn FnOnce(Document) -> Document>>,
}
impl TransformPipeline {
pub fn new() -> Self {
Self { steps: Vec::new() }
}
pub fn transform_text<F>(mut self, f: F) -> Self
where
F: Fn(String) -> String + 'static,
{
use crate::ast_transform::Transform;
self.steps.push(Box::new(move |doc| doc.transform_text(f)));
self
}
pub fn transform_image_urls<F>(mut self, f: F) -> Self
where
F: Fn(String) -> String + 'static,
{
use crate::ast_transform::Transform;
self.steps
.push(Box::new(move |doc| doc.transform_image_urls(f)));
self
}
pub fn transform_link_urls<F>(mut self, f: F) -> Self
where
F: Fn(String) -> String + 'static,
{
use crate::ast_transform::Transform;
self.steps
.push(Box::new(move |doc| doc.transform_link_urls(f)));
self
}
pub fn transform_autolink_urls<F>(mut self, f: F) -> Self
where
F: Fn(String) -> String + 'static,
{
use crate::ast_transform::Transform;
self.steps
.push(Box::new(move |doc| doc.transform_autolink_urls(f)));
self
}
pub fn transform_code<F>(mut self, f: F) -> Self
where
F: Fn(String) -> String + 'static,
{
use crate::ast_transform::Transform;
self.steps.push(Box::new(move |doc| doc.transform_code(f)));
self
}
pub fn transform_html<F>(mut self, f: F) -> Self
where
F: Fn(String) -> String + 'static,
{
use crate::ast_transform::Transform;
self.steps.push(Box::new(move |doc| doc.transform_html(f)));
self
}
pub fn transform_with<T: Transformer + 'static>(mut self, transformer: T) -> Self {
use crate::ast_transform::Transform;
self.steps
.push(Box::new(move |doc| doc.transform_with(transformer)));
self
}
pub fn custom<F>(mut self, f: F) -> Self
where
F: FnOnce(Document) -> Document + 'static,
{
self.steps.push(Box::new(f));
self
}
pub fn when<F>(mut self, condition: bool, builder: F) -> Self
where
F: FnOnce(TransformPipeline) -> TransformPipeline,
{
if condition {
let sub_pipeline = builder(TransformPipeline::new());
self.steps
.push(Box::new(move |doc| sub_pipeline.apply(doc)));
}
self
}
pub fn when_doc<P, F>(mut self, predicate: P, builder: F) -> Self
where
P: Fn(&Document) -> bool + 'static,
F: FnOnce(TransformPipeline) -> TransformPipeline + 'static,
{
self.steps.push(Box::new(move |doc| {
if predicate(&doc) {
let sub_pipeline = builder(TransformPipeline::new());
sub_pipeline.apply(doc)
} else {
doc
}
}));
self
}
pub fn remove_empty_paragraphs(mut self) -> Self {
use crate::ast_transform::FilterTransform;
self.steps
.push(Box::new(|doc| doc.remove_empty_paragraphs()));
self
}
pub fn remove_empty_text(mut self) -> Self {
use crate::ast_transform::FilterTransform;
self.steps.push(Box::new(|doc| doc.remove_empty_text()));
self
}
pub fn normalize_whitespace(mut self) -> Self {
use crate::ast_transform::FilterTransform;
self.steps.push(Box::new(|doc| doc.normalize_whitespace()));
self
}
pub fn filter_blocks<F>(mut self, predicate: F) -> Self
where
F: Fn(&Block) -> bool + 'static,
{
use crate::ast_transform::FilterTransform;
self.steps
.push(Box::new(move |doc| doc.filter_blocks(predicate)));
self
}
pub fn apply(self, mut doc: Document) -> Document {
for step in self.steps {
doc = step(doc);
}
doc
}
}
impl Default for TransformPipeline {
fn default() -> Self {
Self::new()
}
}
pub trait PipeExt {
fn pipe<F, R>(self, f: F) -> R
where
F: FnOnce(Self) -> R,
Self: Sized,
{
f(self)
}
}
impl PipeExt for Document {}