Skip to main content

oxc_markdown_parser/
options.rs

1//! Parser configuration.
2//!
3//! MD and MDX are "the same syntax with different meanings":
4//! the syntactic difference reduces to which constructs are enabled,
5//! so both dialects share one parser, one AST, and one API.
6//! Downstream code never branches on a dialect enum, only on which nodes actually appear.
7
8/// Which syntax constructs the parser recognizes.
9///
10/// CommonMark's core (paragraphs, headings, thematic breaks, blockquotes,
11/// lists, fenced code, emphasis, links, hard breaks) is always on.
12/// Everything listed here is a construct that some dialect turns off or bolts on.
13///
14/// The default set mirrors Prettier's parser composition:
15/// GFM + math + wiki-link + liquid,
16/// plus container directives (`:::`), which Prettier lacks and consequently corrupts.
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub struct Constructs {
19    /// `<https://example.com>` / `<user@example.com>`. Syntax error in MDX.
20    pub autolink: bool,
21    /// 4-space indented code blocks.
22    /// In MDX the indent is an ordinary paragraph (continuation) instead.
23    pub code_indented: bool,
24    /// HTML blocks (CommonMark types 1–7).
25    /// In MDX `<` at flow start is JSX.
26    pub html_flow: bool,
27    /// Inline HTML tags/comments.
28    /// In MDX `<` in text is JSX.
29    pub html_text: bool,
30
31    /// GFM bare-URL links (`www.example.com`).
32    /// Printed verbatim.
33    pub gfm_autolink_literal: bool,
34    /// GFM footnotes (`[^label]`).
35    pub gfm_footnote: bool,
36    /// GFM strikethrough (`~~x~~`).
37    pub gfm_strikethrough: bool,
38    /// Whether a single `~` also opens strikethrough.
39    /// GitHub and Prettier (`singleTilde: false`) require `~~`;
40    /// keep this off to leave subscript conventions like `H~2~O` alone.
41    pub gfm_strikethrough_single_tilde: bool,
42    /// GFM tables.
43    pub gfm_table: bool,
44    /// GFM task list items (`- [x]`).
45    pub gfm_task_list_item: bool,
46
47    /// `$$ … $$` display math.
48    pub math_flow: bool,
49    /// `$ … $` inline math, printed verbatim.
50    pub math_text: bool,
51    /// `{% … %}` / `{{ … }}` template tags, multi-line capable.
52    /// Never interpreted, kept lossless.
53    pub liquid: bool,
54    /// `[[target]]` wiki links, alias-less minimal form, printed verbatim.
55    pub wiki_link: bool,
56
57    /// `::: … :::` container directives.
58    /// Fence lines are kept verbatim (dialects disagree on their grammar);
59    /// only children are markdown.
60    pub container_directive: bool,
61
62    /// MDX `import` / `export` statements at flow start.
63    pub mdx_esm: bool,
64    /// MDX `{expr}` as its own flow block.
65    pub mdx_expression_flow: bool,
66    /// MDX `{expr}` in text.
67    pub mdx_expression_text: bool,
68    /// MDX JSX elements at flow start.
69    pub mdx_jsx_flow: bool,
70    /// MDX JSX elements in text.
71    pub mdx_jsx_text: bool,
72}
73
74impl Constructs {
75    /// Markdown mode: CommonMark + GFM + Prettier's extensions + directives.
76    pub fn markdown() -> Self {
77        Self {
78            autolink: true,
79            code_indented: true,
80            html_flow: true,
81            html_text: true,
82            gfm_autolink_literal: true,
83            gfm_footnote: true,
84            gfm_strikethrough: true,
85            gfm_strikethrough_single_tilde: false,
86            gfm_table: true,
87            gfm_task_list_item: true,
88            math_flow: true,
89            math_text: true,
90            liquid: true,
91            wiki_link: true,
92            container_directive: true,
93            mdx_esm: false,
94            mdx_expression_flow: false,
95            mdx_expression_text: false,
96            mdx_jsx_flow: false,
97            mdx_jsx_text: false,
98        }
99    }
100
101    /// MDX mode: `autolink` / `code_indented` / `html_flow` / `html_text` off, the `mdx_*` family on.
102    /// Unlike markdown mode, parsing can emit diagnostics (MDX has syntax errors; CommonMark does not).
103    ///
104    /// TODO: Not usable yet: the `mdx_*` constructs are unimplemented,
105    /// and disabling `code_indented` must also lift micromark's 4-space/3-column indent limits engine-wide (currently hardcoded),
106    /// so this preset misparses e.g. `    # hi`.
107    pub fn mdx() -> Self {
108        Self {
109            autolink: false,
110            code_indented: false,
111            html_flow: false,
112            html_text: false,
113            mdx_esm: true,
114            mdx_expression_flow: true,
115            mdx_expression_text: true,
116            mdx_jsx_flow: true,
117            mdx_jsx_text: true,
118            ..Self::markdown()
119        }
120    }
121}
122
123impl Default for Constructs {
124    fn default() -> Self {
125        Self::markdown()
126    }
127}
128
129/// Options for [`Parser`](crate::Parser).
130#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
131pub struct ParserOptions {
132    pub constructs: Constructs,
133}
134
135impl ParserOptions {
136    /// Markdown mode (the default): [`Constructs::markdown`].
137    pub fn markdown() -> Self {
138        Self { constructs: Constructs::markdown() }
139    }
140
141    /// MDX mode: [`Constructs::mdx`].
142    pub fn mdx() -> Self {
143        Self { constructs: Constructs::mdx() }
144    }
145}