From 0ca8fe8c12dde40008305e7925cac410952f0752 Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Fri, 19 Sep 2025 05:18:24 -0400 Subject: [PATCH] feat(playground): add export flag --- crates/cli/src/main.rs | 13 +++++-- crates/cli/src/playground.rs | 66 ++++++++++++++++++++++++++++++++++++ docs/src/cli/playground.md | 4 +++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 76ba57ff..11545ff8 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -545,6 +545,9 @@ struct Playground { /// Path to the directory containing the grammar and Wasm files #[arg(long)] pub grammar_path: Option, + /// Export playground files to specified directory instead of serving them + #[arg(long, short)] + pub export: Option, } #[derive(Args)] @@ -1786,9 +1789,15 @@ impl Tags { impl Playground { fn run(self, current_dir: &Path) -> Result<()> { - let open_in_browser = !self.quiet; let grammar_path = self.grammar_path.as_deref().map_or(current_dir, Path::new); - playground::serve(grammar_path, open_in_browser)?; + + if let Some(export_path) = self.export { + playground::export(grammar_path, &export_path)?; + } else { + let open_in_browser = !self.quiet; + playground::serve(grammar_path, open_in_browser)?; + } + Ok(()) } } diff --git a/crates/cli/src/playground.rs b/crates/cli/src/playground.rs index 2344a805..a966d5c0 100644 --- a/crates/cli/src/playground.rs +++ b/crates/cli/src/playground.rs @@ -46,6 +46,72 @@ fn get_main_html(tree_sitter_dir: Option<&Path>) -> Cow<'static, [u8]> { ) } +pub fn export(grammar_path: &Path, export_path: &Path) -> Result<()> { + let (grammar_name, language_wasm) = wasm::load_language_wasm_file(grammar_path)?; + + fs::create_dir_all(export_path).with_context(|| { + format!( + "Failed to create export directory: {}", + export_path.display() + ) + })?; + + let tree_sitter_dir = env::var("TREE_SITTER_BASE_DIR").map(PathBuf::from).ok(); + + let playground_js = get_playground_js(tree_sitter_dir.as_deref()); + let lib_js = get_lib_js(tree_sitter_dir.as_deref()); + let lib_wasm = get_lib_wasm(tree_sitter_dir.as_deref()); + + let has_local_playground_js = !playground_js.is_empty(); + let has_local_lib_js = !lib_js.is_empty(); + let has_local_lib_wasm = !lib_wasm.is_empty(); + + let mut main_html = str::from_utf8(&get_main_html(tree_sitter_dir.as_deref())) + .unwrap() + .replace("THE_LANGUAGE_NAME", &grammar_name); + + if !has_local_playground_js { + main_html = main_html.replace( + r#""#, + r#""# + ); + } + if !has_local_lib_js { + main_html = main_html.replace( + "import * as TreeSitter from './web-tree-sitter.js';", + "import * as TreeSitter from 'https://tree-sitter.github.io/web-tree-sitter.js';", + ); + } + + fs::write(export_path.join("index.html"), main_html.as_bytes()) + .with_context(|| "Failed to write index.html")?; + + fs::write(export_path.join("tree-sitter-parser.wasm"), language_wasm) + .with_context(|| "Failed to write parser wasm file")?; + + if has_local_playground_js { + fs::write(export_path.join("playground.js"), playground_js) + .with_context(|| "Failed to write playground.js")?; + } + + if has_local_lib_js { + fs::write(export_path.join("web-tree-sitter.js"), lib_js) + .with_context(|| "Failed to write web-tree-sitter.js")?; + } + + if has_local_lib_wasm { + fs::write(export_path.join("web-tree-sitter.wasm"), lib_wasm) + .with_context(|| "Failed to write web-tree-sitter.wasm")?; + } + + println!( + "Exported playground to {}", + export_path.canonicalize()?.display() + ); + + Ok(()) +} + pub fn serve(grammar_path: &Path, open_in_browser: bool) -> Result<()> { let server = get_server()?; let (grammar_name, language_wasm) = wasm::load_language_wasm_file(grammar_path)?; diff --git a/docs/src/cli/playground.md b/docs/src/cli/playground.md index 4f194b9c..0dbff469 100644 --- a/docs/src/cli/playground.md +++ b/docs/src/cli/playground.md @@ -13,6 +13,10 @@ For this to work, you must have already built the parser as a Wasm module. This ## Options +### `-e/--export ` + +Export static playground files to the specified directory instead of serving them. + ### `-q/--quiet` Don't automatically open the playground in the default browser.