Markdown parser fork with extended syntax for personal use.
at main 270 lines 8.5 kB view raw
1mod test_utils; 2use markdown::{ 3 mdast::{MdxjsEsm, Node, Root}, 4 message, to_html_with_options, to_mdast, 5 unist::Position, 6 Constructs, Options, ParseOptions, 7}; 8use pretty_assertions::assert_eq; 9use test_utils::swc::{parse_esm, parse_expression}; 10 11#[test] 12fn mdx_esm() -> Result<(), message::Message> { 13 let swc = Options { 14 parse: ParseOptions { 15 constructs: Constructs::mdx(), 16 mdx_esm_parse: Some(Box::new(parse_esm)), 17 mdx_expression_parse: Some(Box::new(parse_expression)), 18 ..Default::default() 19 }, 20 ..Default::default() 21 }; 22 23 assert_eq!( 24 to_html_with_options("import a from 'b'\n\nc", &swc)?, 25 "<p>c</p>", 26 "should support an import" 27 ); 28 29 assert_eq!( 30 to_html_with_options("export default a\n\nb", &swc)?, 31 "<p>b</p>", 32 "should support an export" 33 ); 34 35 assert_eq!( 36 to_html_with_options("impossible", &swc)?, 37 "<p>impossible</p>", 38 "should not support other keywords (`impossible`)" 39 ); 40 41 assert_eq!( 42 to_html_with_options("exporting", &swc)?, 43 "<p>exporting</p>", 44 "should not support other keywords (`exporting`)" 45 ); 46 47 assert_eq!( 48 to_html_with_options("import.", &swc)?, 49 "<p>import.</p>", 50 "should not support a non-whitespace after the keyword" 51 ); 52 53 assert_eq!( 54 to_html_with_options("import('a')", &swc)?, 55 "<p>import('a')</p>", 56 "should not support a non-whitespace after the keyword (import-as-a-function)" 57 ); 58 59 assert_eq!( 60 to_html_with_options(" import a from 'b'\n export default c", &swc)?, 61 "<p>import a from 'b'\nexport default c</p>", 62 "should not support an indent" 63 ); 64 65 assert_eq!( 66 to_html_with_options("- import a from 'b'\n> export default c", &swc)?, 67 "<ul>\n<li>import a from 'b'</li>\n</ul>\n<blockquote>\n<p>export default c</p>\n</blockquote>", 68 "should not support keywords in containers" 69 ); 70 71 assert_eq!( 72 to_html_with_options("import a from 'b'\nexport default c", &swc)?, 73 "", 74 "should support imports and exports in the same “block”" 75 ); 76 77 assert_eq!( 78 to_html_with_options("import a from 'b'\n\nexport default c", &swc)?, 79 "", 80 "should support imports and exports in separate “blocks”" 81 ); 82 83 assert_eq!( 84 to_html_with_options("a\n\nimport a from 'b'\n\nb\n\nexport default c", &swc)?, 85 "<p>a</p>\n<p>b</p>\n", 86 "should support imports and exports in between other constructs" 87 ); 88 89 assert_eq!( 90 to_html_with_options("a\nimport a from 'b'\n\nb\nexport default c", &swc)?, 91 "<p>a\nimport a from 'b'</p>\n<p>b\nexport default c</p>", 92 "should not support import/exports when interrupting paragraphs" 93 ); 94 95 assert_eq!( 96 to_html_with_options("import a", &swc) 97 .err() 98 .unwrap() 99 .to_string(), 100 "1:9: Could not parse esm with swc: Expected ',', got '<eof>' (mdx:swc)", 101 "should crash on invalid import/exports (1)" 102 ); 103 104 assert_eq!( 105 to_html_with_options("import 1/1", &swc) 106 .err() 107 .unwrap() 108 .to_string(), 109 "1:8: Could not parse esm with swc: Expected 'from', got 'numeric literal (1, 1)' (mdx:swc)", 110 "should crash on invalid import/exports (2)" 111 ); 112 113 assert_eq!( 114 to_html_with_options("export {\n a\n} from 'b'\n\nc", &swc)?, 115 "<p>c</p>", 116 "should support line endings in import/exports" 117 ); 118 119 assert_eq!( 120 to_html_with_options("export {\n\n a\n\n} from 'b'\n\nc", &swc)?, 121 "<p>c</p>", 122 "should support blank lines in import/exports" 123 ); 124 125 assert_eq!( 126 to_html_with_options("import a from 'b'\n*md*?", &swc) 127 .err() 128 .unwrap() 129 .to_string(), 130 "2:6: Could not parse esm with swc: Expression expected (mdx:swc)", 131 "should crash on markdown after import/export w/o blank line" 132 ); 133 134 assert_eq!( 135 to_html_with_options("export var a = 1\n// b\n/* c */\n\nd", &swc)?, 136 "<p>d</p>", 137 "should support comments in “blocks”" 138 ); 139 140 assert_eq!( 141 to_html_with_options("export var a = 1\nvar b\n\nc", &swc) 142 .err() 143 .unwrap() 144 .to_string(), 145 "2:1: Unexpected statement in code: only import/exports are supported (mdx:swc)", 146 "should crash on other statements in “blocks”" 147 ); 148 149 assert_eq!( 150 to_html_with_options("import ('a')\n\nb", &swc) 151 .err() 152 .unwrap() 153 .to_string(), 154 "1:1: Unexpected statement in code: only import/exports are supported (mdx:swc)", 155 "should crash on import-as-a-function with a space `import (x)`" 156 ); 157 158 assert_eq!( 159 to_html_with_options("import a from 'b'\nexport {a}\n\nc", &swc)?, 160 "<p>c</p>", 161 "should support a reexport from another import" 162 ); 163 164 assert_eq!( 165 to_html_with_options("import a from 'b';\nexport {a};\n\nc", &swc)?, 166 "<p>c</p>", 167 "should support a reexport from another import w/ semicolons" 168 ); 169 170 assert_eq!( 171 to_html_with_options("import a from 'b'\nexport {a as default}\n\nc", &swc)?, 172 "<p>c</p>", 173 "should support a reexport default from another import" 174 ); 175 176 assert_eq!( 177 to_html_with_options("export var a = () => <b />", &swc)?, 178 "", 179 "should support JSX by default" 180 ); 181 182 assert_eq!( 183 to_html_with_options("export {a}\n", &swc)?, 184 "", 185 "should support EOF after EOL" 186 ); 187 188 assert_eq!( 189 to_html_with_options("import a from 'b'\n\nexport {a}\n\nc", &swc)?, 190 "<p>c</p>", 191 "should support a reexport from another esm block (1)" 192 ); 193 194 assert_eq!( 195 to_html_with_options("import a from 'b'\n\nexport {a}\n\n# c", &swc)?, 196 "<h1>c</h1>", 197 "should support a reexport from another esm block (2)" 198 ); 199 200 let cases = vec![ 201 ("default", "import a from \"b\""), 202 ("whole", "import * as a from \"b\""), 203 ("destructuring", "import {a} from \"b\""), 204 ("destructuring and rename", "import {a as b} from \"c\""), 205 ("default and destructuring", "import a, {b as c} from \"d\""), 206 ("default and whole", "import a, * as b from \"c\""), 207 ("side-effects", "import \"a\""), 208 ]; 209 210 for case in cases { 211 assert_eq!( 212 to_html_with_options(case.1, &swc)?, 213 "", 214 "should support imports: {}", 215 case.0 216 ); 217 } 218 219 let cases = vec![ 220 ("var", "export var a = \"\""), 221 ("const", "export const a = \"\""), 222 ("let", "export let a = \"\""), 223 ("multiple", "export var a, b"), 224 ("multiple w/ assignment", "export var a = \"a\", b = \"b\""), 225 ("function", "export function a() {}"), 226 ("class", "export class a {}"), 227 ("destructuring", "export var {a} = {}"), 228 ("rename destructuring", "export var {a: b} = {}"), 229 ("array destructuring", "export var [a] = []"), 230 ("default", "export default a = 1"), 231 ("default function", "export default function a() {}"), 232 ("default class", "export default class a {}"), 233 ("aggregate", "export * from \"a\""), 234 ("whole reexport", "export * as a from \"b\""), 235 ("reexport destructuring", "export {a} from \"b\""), 236 ( 237 "reexport destructuring w rename", 238 "export {a as b} from \"c\"", 239 ), 240 ("reexport as a default whole", "export {default} from \"b\""), 241 ( 242 "reexport default and non-default", 243 "export {default as a, b} from \"c\"", 244 ), 245 ]; 246 247 for case in cases { 248 assert_eq!( 249 to_html_with_options(case.1, &swc)?, 250 "", 251 "should support exports: {}", 252 case.0 253 ); 254 } 255 256 assert_eq!( 257 to_mdast("import a from 'b'\nexport {a}", &swc.parse)?, 258 Node::Root(Root { 259 children: vec![Node::MdxjsEsm(MdxjsEsm { 260 value: "import a from 'b'\nexport {a}".into(), 261 position: Some(Position::new(1, 1, 0, 2, 11, 28)), 262 stops: vec![(0, 0), (17, 17), (18, 18)] 263 })], 264 position: Some(Position::new(1, 1, 0, 2, 11, 28)) 265 }), 266 "should support mdx esm as `MdxjsEsm`s in mdast" 267 ); 268 269 Ok(()) 270}