rs_web/markdown/
pipeline.rs1use std::path::Path;
2
3use super::parser::{events_to_html, parse_markdown};
4use super::transforms::AstTransform;
5use crate::config::Config;
6
7#[allow(dead_code)]
9pub struct TransformContext<'a> {
10 pub config: &'a Config,
11 pub current_path: &'a Path,
12 pub base_url: &'a str,
13}
14
15pub struct Pipeline {
17 transforms: Vec<Box<dyn AstTransform>>,
18}
19
20impl Pipeline {
21 pub fn new() -> Self {
22 Self {
23 transforms: Vec::new(),
24 }
25 }
26
27 pub fn with<T: AstTransform + 'static>(mut self, transform: T) -> Self {
29 self.transforms.push(Box::new(transform));
30 self
31 }
32
33 pub fn build(mut self) -> Self {
35 self.transforms.sort_by_key(|t| t.priority());
36 self
37 }
38
39 pub fn process(&self, content: &str, ctx: &TransformContext<'_>) -> String {
41 let content = if let Some(stripped) = content.strip_prefix("---") {
43 if let Some(end) = stripped.find("---") {
44 &stripped[end + 3..]
45 } else {
46 content
47 }
48 } else {
49 content
50 };
51
52 let mut events = parse_markdown(content);
53
54 for transform in &self.transforms {
56 events = transform.transform(events, ctx);
57 }
58
59 events_to_html(events.into_iter())
61 }
62}
63
64impl Pipeline {
65 pub fn from_config(_config: &Config) -> Self {
67 use super::transforms::*;
68
69 Self::new()
70 .with(LazyImagesTransform)
71 .with(HeadingAnchorsTransform::new())
72 .with(ExternalLinksTransform)
73 .build()
74 }
75}
76
77impl Default for Pipeline {
78 fn default() -> Self {
79 use super::transforms::*;
80
81 Self::new()
82 .with(LazyImagesTransform)
83 .with(HeadingAnchorsTransform::new())
84 .with(ExternalLinksTransform)
85 .build()
86 }
87}