xtask/codegen/
js_pkgs.rs

1use std::fs;
2
3use anyhow::Result;
4use heck::ToPascalCase as _;
5use toml::Table;
6
7pub fn write() -> Result<()> {
8    let langs_dir = crate::WORKSPACE_DIR.join("syntastica-js/langs");
9    let _ = fs::remove_dir_all(&langs_dir);
10    fs::create_dir_all(&langs_dir)?;
11    fs::write(
12        langs_dir.join("README.md"),
13        include_str!("./js_langs_readme.md"),
14    )?;
15
16    for lang in &crate::LANGUAGE_CONFIG.languages {
17        if !lang.wasm {
18            continue;
19        }
20        let lang_dir = langs_dir.join(&lang.name);
21        let src_dir = lang_dir.join("src");
22        fs::create_dir_all(&src_dir)?;
23        fs::write(lang_dir.join("LICENSE"), include_str!("../../../LICENSE"))?;
24
25        let lang_name = &lang.name;
26        let lang_name_pascal = &lang.name.to_pascal_case();
27
28        fs::write(
29            lang_dir.join("README.md"),
30            format!(
31                r###"# `syntastica-js-{lang_name}`
32
33{lang_name_pascal} language support for
34[`syntastica-js`](https://www.npmjs.com/package/@syntastica/core).
35"###
36            ),
37        )?;
38
39        fs::write(
40            lang_dir.join("Cargo.toml"),
41            format!(
42                r###"[package]
43name = "syntastica-js-{lang_name}"
44version.workspace = true
45authors.workspace = true
46documentation = "https://rubixdev.github.io/syntastica/syntastica_js/"
47edition.workspace = true
48license.workspace = true
49repository.workspace = true
50description = "{lang_name_pascal} language support for syntastica-js"
51
52[lib]
53crate-type = ["cdylib"]
54
55[dependencies]
56syntastica-macros = {{ workspace = true, features = ["js"] }}
57syntastica-queries.workspace = true
58
59tree-sitter.workspace = true
60
61[build-dependencies]
62syntastica-macros = {{ workspace = true, features = ["js"] }}
63
64cc.workspace = true
65tree-sitter-generate.workspace = true
66"###
67            ),
68        )?;
69
70        fs::write(
71            lang_dir.join("build.rs"),
72            format!(
73                r###"const EMSCRIPTEN_FLAGS: &[&str] = &[
74    "-sTOTAL_MEMORY=33554432",
75    "-sSIDE_MODULE=2",
76    "-sWASM=1",
77    "-sNODEJS_CATCH_EXIT=0",
78];
79
80fn main() -> Result<(), Box<dyn std::error::Error>> {{
81    if std::env::var("TARGET").is_ok_and(|s| s == "wasm32-unknown-emscripten") {{
82        for flag in EMSCRIPTEN_FLAGS {{
83            println!("cargo::rustc-link-arg={{flag}}");
84        }}
85
86        syntastica_macros::js_lang_build!("{lang_name}");
87    }}
88    Ok(())
89}}
90
91include!("../../../syntastica-parsers-git/build_helper.rs");
92"###
93            ),
94        )?;
95
96        let syntastica_version = toml::from_str::<Table>(
97            &fs::read_to_string(crate::WORKSPACE_DIR.join("Cargo.toml")).unwrap(),
98        )
99        .unwrap()["workspace"]["package"]["version"]
100            .as_str()
101            .unwrap()
102            .to_string();
103        fs::write(
104            lang_dir.join("package.json"),
105            format!(
106                r###"{{
107  "$schema": "https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/package.json",
108  "name": "@syntastica/lang-{lang_name}",
109  "version": "{syntastica_version}",
110  "description": "{lang_name_pascal} language support for syntastica-js",
111  "keywords": ["tree-sitter", "highlight", "parsing", "syntax"],
112  "homepage": "https://github.com/RubixDev/syntastica/tree/main/syntastica-js#readme",
113  "bugs": "https://github.com/RubixDev/syntastica/issues",
114  "license": "MPL-2.0",
115  "author": "RubixDev",
116  "funding": {{
117    "url": "https://ko-fi.com/rubixdev",
118    "type": "ko-fi"
119  }},
120  "files": ["{lang_name}.wasm"],
121  "repository": {{
122    "type": "git",
123    "url": "git+https://github.com/RubixDev/syntastica.git",
124    "directory": "syntastica-js/langs/{lang_name}"
125  }},
126  "publishConfig": {{
127    "access": "public"
128  }},
129  "scripts": {{
130    "build": "env CFLAGS=-fPIC cargo build --profile release-wasm --target wasm32-unknown-emscripten",
131    "postbuild": "cp \"${{CARGO_TARGET_DIR:-../../../target}}/wasm32-unknown-emscripten/release-wasm/syntastica_js_{lang_name}.wasm\" {lang_name}.wasm"
132  }}
133}}
134"###
135            ),
136        )?;
137
138        fs::write(
139            src_dir.join("lib.rs"),
140            format!(
141                r###"#![no_std]
142#![warn(rust_2018_idioms)]
143
144use tree_sitter::Language;
145
146syntastica_macros::js_lang_info!();
147syntastica_macros::js_lang_lib!("{lang_name}");
148"###
149            ),
150        )?;
151    }
152
153    Ok(())
154}