1pub use rdx_ast::*;
2pub use rdx_parser::parse;
3
4mod transforms;
5pub use transforms::abbreviation::AbbreviationExpand;
6pub use transforms::auto_number::{AutoNumber, NumberEntry, NumberRegistry};
7pub use transforms::citation_resolve::{BibEntry, CitationResolve, CitationStyle};
8pub use transforms::cross_ref_resolve::CrossRefResolve;
9pub use transforms::print_fallback::PrintFallback;
10pub use transforms::slug::AutoSlug;
11pub use transforms::strip_target::StripTarget;
12pub use transforms::toc::TableOfContents;
13
14pub trait Transform {
34 fn name(&self) -> &str;
36
37 fn transform(&self, root: &mut Root, source: &str);
40}
41
42pub struct Pipeline {
55 transforms: Vec<Box<dyn Transform>>,
56}
57
58impl Pipeline {
59 pub fn new() -> Self {
60 Pipeline {
61 transforms: Vec::new(),
62 }
63 }
64
65 #[allow(clippy::should_implement_trait)]
67 pub fn add(mut self, transform: impl Transform + 'static) -> Self {
68 self.transforms.push(Box::new(transform));
69 self
70 }
71
72 pub fn run(&self, input: &str) -> Root {
74 let mut root = parse(input);
75 for t in &self.transforms {
76 t.transform(&mut root, input);
77 }
78 root
79 }
80
81 pub fn apply(&self, root: &mut Root, source: &str) {
83 for t in &self.transforms {
84 t.transform(root, source);
85 }
86 }
87}
88
89impl Default for Pipeline {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95pub fn parse_with_defaults(input: &str) -> Root {
97 Pipeline::new()
98 .add(AutoSlug::new())
99 .add(TableOfContents::default())
100 .run(input)
101}
102
103#[allow(clippy::ptr_arg)]
106pub fn walk_mut(nodes: &mut Vec<Node>, f: &mut dyn FnMut(&mut Node)) {
107 for node in nodes.iter_mut() {
108 f(node);
109 if let Some(children) = node.children_mut() {
110 walk_mut(children, f);
111 }
112 }
113}
114
115pub fn walk<'a>(nodes: &'a [Node], f: &mut dyn FnMut(&'a Node)) {
117 for node in nodes {
118 f(node);
119 if let Some(children) = node.children() {
120 walk(children, f);
121 }
122 }
123}
124
125pub fn synthetic_pos() -> Position {
131 let pt = Point {
132 line: 0,
133 column: 0,
134 offset: 0,
135 };
136 Position {
137 start: pt.clone(),
138 end: pt,
139 }
140}
141
142pub fn collect_text(nodes: &[Node]) -> String {
144 let mut out = String::new();
145 walk(nodes, &mut |node| {
146 if let Node::Text(t) = node {
147 out.push_str(&t.value);
148 }
149 });
150 out
151}