Skip to content

Commit f276d62

Browse files
feat: add webui-wasm crate for WebAssembly playground
Introduce a new webui-wasm crate that compiles the full WebUI parse → protocol → render pipeline to WebAssembly, enabling an interactive browser-based playground with zero server dependencies. WebAssembly crate (crates/webui-wasm): - Exposes build_and_render(), build_protocol(), and render() via wasm-bindgen for JavaScript consumption - Uses the real webui-parser with CssStrategy::Inline so component styles work in-memory without external CSS files - Feature-gates walkdir/filesystem behind 'fs' feature so webui-parser compiles cleanly for wasm32-unknown-unknown - Removes 6 unused deps from webui-parser (tokio, anyhow, tree-sitter-typescript, lazy_static, nom, streaming-iterator) - Bumps tree-sitter-language to 0.1.7 for bundled WASM C headers Build tooling: - Cross-platform cargo xtask build-wasm command with auto-detection of LLVM clang, wasi-libc, and WASM headers per OS - Friendly colored error messages with platform-specific install hints using the console crate (matches webui-cli style) - JS glue patching to replace tree-sitter env imports with inline C stdlib stubs for browser compatibility - Reusable GitHub Actions composite action (.github/actions/setup-wasm) shared by PR checks and docs deployment workflows - Refactored xtask into modules: main.rs, build_wasm.rs, build_apps.rs, util.rs
1 parent 8474ad7 commit f276d62

16 files changed

Lines changed: 1128 additions & 572 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: 'Setup and Build WASM'
2+
description: 'Install WASM toolchain, build webui-wasm, and verify output'
3+
4+
runs:
5+
using: 'composite'
6+
steps:
7+
- name: Setup Rust
8+
uses: dtolnay/rust-toolchain@stable
9+
with:
10+
toolchain: 1.93
11+
targets: wasm32-unknown-unknown
12+
13+
- name: Rust Cache
14+
uses: Swatinem/rust-cache@v2
15+
16+
- name: Install wasm-pack
17+
shell: bash
18+
run: cargo install wasm-pack
19+
20+
- name: Install LLVM
21+
shell: bash
22+
run: sudo apt-get update && sudo apt-get install -y clang llvm lld
23+
24+
- name: Setup WASM headers
25+
shell: bash
26+
run: |
27+
cargo fetch
28+
WASM_HEADERS=$(find $HOME/.cargo/registry/src -path "*/tree-sitter-language-*/wasm/include" -type d | head -1)
29+
if [ -n "$WASM_HEADERS" ]; then
30+
echo "WASI_INCLUDE=$WASM_HEADERS" >> $GITHUB_ENV
31+
else
32+
echo "::error::Could not find tree-sitter-language WASM headers"
33+
exit 1
34+
fi
35+
36+
- name: Build WASM
37+
shell: bash
38+
run: cargo xtask build-wasm
39+
40+
- name: Verify WASM output
41+
shell: bash
42+
run: |
43+
test -f docs/public/wasm/webui_wasm_bg.wasm
44+
test -f docs/public/wasm/webui_wasm.js
45+
! grep -q "from 'env'" docs/public/wasm/webui_wasm.js

.github/workflows/docs.yml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,40 @@ on:
88
branches: [ "main" ]
99
paths:
1010
- 'docs/**'
11+
- 'crates/webui-wasm/**'
12+
- 'crates/webui-parser/**'
13+
- 'crates/webui-handler/**'
14+
- 'crates/webui-protocol/**'
1115
workflow_dispatch:
1216

1317
jobs:
1418
build-and-deploy:
1519
runs-on: ubuntu-latest
1620

1721
steps:
18-
# Step 1: Checkout the repository
1922
- name: Checkout Repository
2023
uses: actions/checkout@v4
2124

22-
# Step 2: Setup Node.js environment
25+
- name: Build WASM playground
26+
uses: ./.github/actions/setup-wasm
27+
2328
- name: Setup Node.js
2429
uses: actions/setup-node@v3
2530
with:
2631
node-version: '22'
27-
28-
# Step 3: Setup pnpm
32+
2933
- name: Setup pnpm
3034
uses: pnpm/action-setup@v2
3135
with:
3236
version: latest
3337
run_install: false
3438

35-
# Step 4: Install dependencies
3639
- name: Install Dependencies
3740
run: cd docs && pnpm install
3841

39-
# Step 5: Build the Vitepress site
4042
- name: Build Site
4143
run: cd docs && pnpm build
4244

43-
# Step 6: Deploy to GitHub Pages
4445
- name: Deploy to GitHub Pages
4546
uses: peaceiris/actions-gh-pages@v3
4647
with:

.github/workflows/pr.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,14 @@ jobs:
5454

5555
- name: Build docs
5656
run: pnpm --filter @webui/docs build
57+
58+
wasm:
59+
name: WASM Build
60+
runs-on: ubuntu-latest
61+
# Only run when WASM-relevant files change
62+
if: |
63+
contains(github.event.pull_request.labels.*.name, 'wasm') ||
64+
github.event_name == 'workflow_dispatch'
65+
steps:
66+
- uses: actions/checkout@v3
67+
- uses: ./.github/actions/setup-wasm

Cargo.lock

Lines changed: 31 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ members = [
77
"crates/webui-parser",
88
"crates/webui-protocol",
99
"crates/webui-state",
10+
"crates/webui-wasm",
1011
"xtask",
1112
]
1213
resolver = "2"
@@ -30,6 +31,8 @@ tokio = { version = "1.49.0", features = ["full"] }
3031
clap = { version = "4", features = ["derive"] }
3132
console = "0.15"
3233
prost = "0.13"
34+
wasm-bindgen = "0.2"
35+
serde-wasm-bindgen = "0.6"
3336

3437
# Test dependencies
3538
criterion = "0.8.2"

crates/webui-parser/Cargo.toml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,21 @@ repository.workspace = true
99

1010
[features]
1111
default = ["fs"]
12-
fs = []
12+
fs = ["walkdir"]
1313

1414
[dependencies]
1515
webui-expressions = { path = "../webui-expressions" }
1616
webui-protocol = { path = "../webui-protocol" }
1717
serde = { workspace = true }
1818
serde_json = { workspace = true }
1919
thiserror = { workspace = true }
20-
anyhow = { workspace = true }
21-
tokio = { workspace = true }
2220
tree-sitter = "0.26.5"
21+
tree-sitter-language = "0.1.7"
2322
tree-sitter-html = "0.23.2"
2423
tree-sitter-css = "0.25.0"
25-
tree-sitter-typescript = "0.23.2"
26-
walkdir = "2.5.0"
27-
lazy_static = "1.5.0"
28-
nom = "8.0.0"
29-
streaming-iterator = "0.1.9"
24+
walkdir = { version = "2.5.0", optional = true }
3025

3126
[dev-dependencies]
3227
mockall = { workspace = true }
33-
tokio-test = { workspace = true }
3428
tempfile = { workspace = true }
3529
webui-test-utils = { path = "../webui-test-utils" }

crates/webui-wasm/Cargo.toml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "webui-wasm"
3+
description = "WebAssembly bindings for WebUI framework — powers the online playground"
4+
version.workspace = true
5+
edition.workspace = true
6+
authors.workspace = true
7+
license.workspace = true
8+
repository.workspace = true
9+
10+
[package.metadata.wasm-pack.profile.release]
11+
wasm-opt = false
12+
13+
[lib]
14+
crate-type = ["cdylib", "rlib"]
15+
16+
[dependencies]
17+
webui-parser = { path = "../webui-parser", default-features = false }
18+
webui-handler = { path = "../webui-handler" }
19+
webui-protocol = { path = "../webui-protocol" }
20+
serde = { workspace = true }
21+
serde_json = { workspace = true }
22+
wasm-bindgen = { workspace = true }
23+
serde-wasm-bindgen = { workspace = true }
24+
25+
[dev-dependencies]
26+
webui-test-utils = { path = "../webui-test-utils" }

0 commit comments

Comments
 (0)