Skip to content

Commit fb4b491

Browse files
authored
Add exports of functions for each phase
Closes GH-60.
1 parent c860d49 commit fb4b491

File tree

4 files changed

+121
-41
lines changed

4 files changed

+121
-41
lines changed

src/hast_util_to_swc.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
//! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2828
2929
use crate::hast;
30-
use crate::swc::{parse_esm_to_tree, parse_expression_to_tree};
30+
use crate::swc::{parse_esm_to_tree, parse_expression_to_tree, serialize};
3131
use crate::swc_utils::{
3232
create_jsx_attr_name_from_str, create_jsx_name_from_str, inter_element_whitespace,
3333
position_to_span,
@@ -53,6 +53,13 @@ pub struct Program {
5353
pub comments: Vec<swc_core::common::comments::Comment>,
5454
}
5555

56+
impl Program {
57+
/// Serialize to JS.
58+
pub fn serialize(&mut self) -> String {
59+
serialize(&mut self.module, Some(&self.comments))
60+
}
61+
}
62+
5663
/// Whether we’re in HTML or SVG.
5764
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5865
enum Space {

src/lib.rs

Lines changed: 102 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
extern crate markdown;
1515
mod configuration;
16-
mod hast;
16+
pub mod hast;
1717
mod hast_util_to_swc;
1818
mod mdast_util_to_hast;
1919
mod mdx_plugin_recma_document;
@@ -23,17 +23,25 @@ mod swc_util_build_jsx;
2323
mod swc_utils;
2424

2525
use crate::{
26-
hast_util_to_swc::hast_util_to_swc,
27-
mdast_util_to_hast::mdast_util_to_hast,
28-
mdx_plugin_recma_document::{mdx_plugin_recma_document, Options as DocumentOptions},
29-
mdx_plugin_recma_jsx_rewrite::{mdx_plugin_recma_jsx_rewrite, Options as RewriteOptions},
26+
hast_util_to_swc::hast_util_to_swc as to_swc,
27+
mdx_plugin_recma_document::{
28+
mdx_plugin_recma_document as wrap_document, Options as DocumentOptions,
29+
},
30+
mdx_plugin_recma_jsx_rewrite::{
31+
mdx_plugin_recma_jsx_rewrite as jsx_rewrite, Options as RewriteOptions,
32+
},
3033
swc::{parse_esm, parse_expression, serialize},
3134
swc_util_build_jsx::{swc_util_build_jsx, Options as BuildOptions},
3235
};
33-
use markdown::{message, to_mdast, Constructs, Location, ParseOptions};
34-
use swc_core::alloc::collections::FxHashSet;
36+
use hast_util_to_swc::Program;
37+
use markdown::{
38+
message::{self, Message},
39+
to_mdast, Constructs, Location, ParseOptions,
40+
};
41+
use swc_core::{alloc::collections::FxHashSet, common::Span};
3542

3643
pub use crate::configuration::{MdxConstructs, MdxParseOptions, Options};
44+
pub use crate::mdast_util_to_hast::mdast_util_to_hast;
3745
pub use crate::mdx_plugin_recma_document::JsxRuntime;
3846

3947
/// Turn MDX into JavaScript.
@@ -54,6 +62,40 @@ pub use crate::mdx_plugin_recma_document::JsxRuntime;
5462
/// This project errors for many different reasons, such as syntax errors in
5563
/// the MDX format or misconfiguration.
5664
pub fn compile(value: &str, options: &Options) -> Result<String, message::Message> {
65+
let mdast = mdast_util_from_mdx(value, options)?;
66+
let hast = mdast_util_to_hast(&mdast);
67+
let location = Location::new(value.as_bytes());
68+
let mut explicit_jsxs = FxHashSet::default();
69+
let mut program = hast_util_to_swc(&hast, options, Some(&location), &mut explicit_jsxs)?;
70+
mdx_plugin_recma_document(&mut program, options, Some(&location))?;
71+
mdx_plugin_recma_jsx_rewrite(&mut program, options, Some(&location), &explicit_jsxs)?;
72+
Ok(serialize(&mut program.module, Some(&program.comments)))
73+
}
74+
75+
/// Turn markdown into a syntax tree.
76+
///
77+
/// ## Errors
78+
///
79+
/// There are several errors that can occur with how
80+
/// JSX, expressions, or ESM are written.
81+
///
82+
/// ## Examples
83+
///
84+
/// ```
85+
/// use mdxjs::{mdast_util_from_mdx, Options};
86+
/// # fn main() -> Result<(), markdown::message::Message> {
87+
///
88+
/// let tree = mdast_util_from_mdx("# Hey, *you*!", &Options::default())?;
89+
///
90+
/// println!("{:?}", tree);
91+
/// // => Root { children: [Heading { children: [Text { value: "Hey, ", position: Some(1:3-1:8 (2-7)) }, Emphasis { children: [Text { value: "you", position: Some(1:9-1:12 (8-11)) }], position: Some(1:8-1:13 (7-12)) }, Text { value: "!", position: Some(1:13-1:14 (12-13)) }], position: Some(1:1-1:14 (0-13)), depth: 1 }], position: Some(1:1-1:14 (0-13)) }
92+
/// # Ok(())
93+
/// # }
94+
/// ```
95+
pub fn mdast_util_from_mdx(
96+
value: &str,
97+
options: &Options,
98+
) -> Result<markdown::mdast::Node, Message> {
5799
let parse_options = ParseOptions {
58100
constructs: Constructs {
59101
attention: options.parse.constructs.attention,
@@ -96,43 +138,73 @@ pub fn compile(value: &str, options: &Options) -> Result<String, message::Messag
96138
mdx_esm_parse: Some(Box::new(parse_esm)),
97139
mdx_expression_parse: Some(Box::new(parse_expression)),
98140
};
141+
142+
to_mdast(value, &parse_options)
143+
}
144+
145+
/// Compile hast into SWC’s ES AST.
146+
///
147+
/// ## Errors
148+
///
149+
/// This project errors for many different reasons, such as syntax errors in
150+
/// the MDX format or misconfiguration.
151+
pub fn hast_util_to_swc(
152+
hast: &hast::Node,
153+
options: &Options,
154+
location: Option<&Location>,
155+
explicit_jsxs: &mut FxHashSet<Span>,
156+
) -> Result<Program, markdown::message::Message> {
157+
to_swc(hast, options.filepath.clone(), location, explicit_jsxs)
158+
}
159+
160+
/// Wrap the SWC ES AST nodes coming from hast into a whole document.
161+
///
162+
/// ## Errors
163+
///
164+
/// This project errors for many different reasons, such as syntax errors in
165+
/// the MDX format or misconfiguration.
166+
pub fn mdx_plugin_recma_document(
167+
program: &mut Program,
168+
options: &Options,
169+
location: Option<&Location>,
170+
) -> Result<(), markdown::message::Message> {
99171
let document_options = DocumentOptions {
100172
pragma: options.pragma.clone(),
101173
pragma_frag: options.pragma_frag.clone(),
102174
pragma_import_source: options.pragma_import_source.clone(),
103175
jsx_import_source: options.jsx_import_source.clone(),
104176
jsx_runtime: options.jsx_runtime,
105177
};
178+
wrap_document(program, &document_options, location)
179+
}
180+
181+
/// Rewrite JSX in an MDX file so that components can be passed in and provided.
182+
/// Also compiles JSX to function calls unless `options.jsx` is true.
183+
///
184+
/// ## Errors
185+
///
186+
/// This project errors for many different reasons, such as syntax errors in
187+
/// the MDX format or misconfiguration.
188+
pub fn mdx_plugin_recma_jsx_rewrite(
189+
program: &mut Program,
190+
options: &Options,
191+
location: Option<&Location>,
192+
explicit_jsxs: &FxHashSet<Span>,
193+
) -> Result<(), markdown::message::Message> {
106194
let rewrite_options = RewriteOptions {
107195
development: options.development,
108196
provider_import_source: options.provider_import_source.clone(),
109197
};
110-
let build_options = BuildOptions {
111-
development: options.development,
112-
};
113198

114-
let mut explicit_jsxs = FxHashSet::default();
115-
116-
let location = Location::new(value.as_bytes());
117-
let mdast = to_mdast(value, &parse_options)?;
118-
let hast = mdast_util_to_hast(&mdast);
119-
let mut program = hast_util_to_swc(
120-
&hast,
121-
options.filepath.clone(),
122-
Some(&location),
123-
&mut explicit_jsxs,
124-
)?;
125-
mdx_plugin_recma_document(&mut program, &document_options, Some(&location))?;
126-
mdx_plugin_recma_jsx_rewrite(
127-
&mut program,
128-
&rewrite_options,
129-
Some(&location),
130-
explicit_jsxs,
131-
);
199+
jsx_rewrite(program, &rewrite_options, location, explicit_jsxs);
132200

133201
if !options.jsx {
134-
swc_util_build_jsx(&mut program, &build_options, Some(&location))?;
202+
let build_options = BuildOptions {
203+
development: options.development,
204+
};
205+
206+
swc_util_build_jsx(program, &build_options, location)?;
135207
}
136208

137-
Ok(serialize(&mut program.module, Some(&program.comments)))
209+
Ok(())
138210
}

src/mdast_util_to_hast.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,10 @@ pub fn mdast_util_to_hast(mdast: &mdast::Node) -> hast::Node {
231231
}));
232232
}
233233

234-
tail_element
235-
.children
236-
.append(&mut backreference_opt.take().unwrap());
234+
if let Some(mut backreference) = backreference_opt {
235+
backreference_opt = None;
236+
tail_element.children.append(&mut backreference);
237+
}
237238
}
238239
}
239240

src/mdx_plugin_recma_jsx_rewrite.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub fn mdx_plugin_recma_jsx_rewrite(
4343
program: &mut Program,
4444
options: &Options,
4545
location: Option<&Location>,
46-
explicit_jsxs: FxHashSet<Span>,
46+
explicit_jsxs: &FxHashSet<Span>,
4747
) {
4848
let mut state = State {
4949
scopes: vec![],
@@ -137,7 +137,7 @@ struct Scope {
137137
}
138138

139139
/// Context.
140-
#[derive(Debug, Default, Clone)]
140+
#[derive(Debug, Clone)]
141141
struct State<'a> {
142142
/// Location info.
143143
location: Option<&'a Location>,
@@ -157,7 +157,7 @@ struct State<'a> {
157157
/// helper function to throw when they are missing.
158158
create_error_helper: bool,
159159

160-
explicit_jsxs: FxHashSet<Span>,
160+
explicit_jsxs: &'a FxHashSet<Span>,
161161
}
162162

163163
impl State<'_> {
@@ -1044,7 +1044,7 @@ mod tests {
10441044

10451045
let mut program = hast_util_to_swc(&hast, filepath, Some(&location), &mut explicit_jsxs)?;
10461046
mdx_plugin_recma_document(&mut program, &DocumentOptions::default(), Some(&location))?;
1047-
mdx_plugin_recma_jsx_rewrite(&mut program, options, Some(&location), explicit_jsxs);
1047+
mdx_plugin_recma_jsx_rewrite(&mut program, options, Some(&location), &explicit_jsxs);
10481048
Ok(serialize(&mut program.module, Some(&program.comments)))
10491049
}
10501050

@@ -1867,7 +1867,7 @@ function _missingMdxReference(id, component, place) {
18671867
}))))],
18681868
},
18691869
};
1870-
mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, explicit_jsxs);
1870+
mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, &explicit_jsxs);
18711871
assert_eq!(
18721872
serialize(&mut program.module, None),
18731873
"let a = <b/>;\n",
@@ -1899,7 +1899,7 @@ function _missingMdxReference(id, component, place) {
18991899
}))))],
19001900
},
19011901
};
1902-
mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, explicit_jsxs);
1902+
mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, &explicit_jsxs);
19031903
assert_eq!(
19041904
serialize(&mut program.module, None),
19051905
"let <invalid>;\n",
@@ -1931,7 +1931,7 @@ function _missingMdxReference(id, component, place) {
19311931
}))))],
19321932
},
19331933
};
1934-
mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, explicit_jsxs);
1934+
mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, &explicit_jsxs);
19351935
assert_eq!(
19361936
serialize(&mut program.module, None),
19371937
"let a;\n",

0 commit comments

Comments
 (0)