diff --git a/.claude/rules/xtask.md b/.claude/rules/xtask.md index 140e32c83..fb0803c3f 100644 --- a/.claude/rules/xtask.md +++ b/.claude/rules/xtask.md @@ -25,9 +25,10 @@ paths: ## Dev tool version pinning -Dev tools whose versions must match Cargo.lock (e.g., `wasm-bindgen-cli`) are installed -via `cargo xtask dev-setup`, which reads the locked version automatically. Never hardcode -these versions in CI workflows or documentation — always use `cargo xtask dev-setup`. +Dev tools whose versions must match Cargo.lock (e.g., `wasm-bindgen-cli`) are pinned in +`crates/xtask/src/dev_setup.rs`. When updating `wasm-bindgen` in Cargo.lock, also update +the pinned version in `dev_setup.rs` to match. CI workflows extract the version directly +from `crates/wasm-quarto-hub-client/Cargo.lock` to avoid duplication. ## Adding a new subcommand diff --git a/.github/workflows/build-wasm.yml b/.github/workflows/build-wasm.yml deleted file mode 100644 index 95f1af7b7..000000000 --- a/.github/workflows/build-wasm.yml +++ /dev/null @@ -1,58 +0,0 @@ -# Tests a broad set of Quarto functionality that users are likely to encounter. -# A failure indicates some signficant portion of functionality is likely to be broken. -name: Build WASM Artifacts -on: workflow_dispatch -jobs: - build-wasm: - runs-on: ubuntu-latest - - name: Build WASM Artifacts - - steps: - - uses: actions/checkout@v6 - - name: Set up Rust nightly - uses: dtolnay/rust-toolchain@nightly - - - name: Set up build tools - if: runner.os == 'linux' - shell: bash - run: | - sudo apt-get update - sudo apt-get install -y build-essential curl file git - - - name: Set up Clang - uses: egor-tensin/setup-clang@v2 - with: - version: latest - platform: x64 - - - name: Setup wasm-pack - shell: bash - run: | - cargo install wasm-pack - - # tree-sitter setup - - name: Set up tree-sitter CLI (Linux) - if: runner.os == 'Linux' - run: | - sudo apt-get install libc6-dev - sudo apt-get install gcc-multilib - curl -LO https://github.com/tree-sitter/tree-sitter/releases/download/v0.25.8/tree-sitter-linux-x86.gz - gunzip tree-sitter-linux-x86.gz - chmod +x tree-sitter-linux-x86 - sudo mv tree-sitter-linux-x86 /usr/local/bin/tree-sitter - - # build and run tests - - name: Build - run: | - cd crates/wasm-qmd-parser - export CFLAGS_wasm32_unknown_unknown="-I$(pwd)/wasm-sysroot -Wbad-function-cast -Wcast-function-type -fno-builtin -DHAVE_ENDIAN_H" - wasm-pack build --target web --dev - shell: bash - - # upload artifacts - - name: Upload WASM Artifacts - uses: actions/upload-artifact@v7 - with: - name: wasm-qmd-parser - path: crates/wasm-qmd-parser/pkg \ No newline at end of file diff --git a/.github/workflows/hub-client-e2e.yml b/.github/workflows/hub-client-e2e.yml index d8ef6103b..b793c3544 100644 --- a/.github/workflows/hub-client-e2e.yml +++ b/.github/workflows/hub-client-e2e.yml @@ -32,11 +32,9 @@ jobs: [ "$time" != "@0" ] && touch -d "$time" "$file" 2>/dev/null || true done - # Rust toolchain for WASM build - - name: Set up Rust nightly - uses: dtolnay/rust-toolchain@nightly - with: - targets: wasm32-unknown-unknown + # Install toolchain from rust-toolchain.toml (nightly + components + targets) + - name: Set up Rust + run: rustup show active-toolchain - name: Set up Clang uses: egor-tensin/setup-clang@v2 @@ -48,9 +46,6 @@ jobs: with: cache-on-failure: true - - name: Install wasm-pack - run: cargo install wasm-pack - # tree-sitter for grammar builds - name: Set up tree-sitter CLI run: | @@ -72,6 +67,19 @@ jobs: - name: Build TypeScript packages run: npm run build + # wasm-bindgen-cli must match the wasm-bindgen version in Cargo.lock + # Use pre-built binary via taiki-e/install-action (faster, avoids transitive dep issues) + - name: Detect wasm-bindgen version + id: wb-version + run: | + VERSION=$(grep -A1 'name = "wasm-bindgen"' crates/wasm-quarto-hub-client/Cargo.lock | grep version | head -1 | sed 's/.*"\(.*\)"/\1/') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Install wasm-bindgen-cli + uses: taiki-e/install-action@v2 + with: + tool: wasm-bindgen-cli@${{ steps.wb-version.outputs.version }} + # Build WASM module - name: Build WASM run: | diff --git a/.github/workflows/test-suite.yml b/.github/workflows/test-suite.yml index 4184d6506..5d04f3001 100644 --- a/.github/workflows/test-suite.yml +++ b/.github/workflows/test-suite.yml @@ -46,13 +46,9 @@ jobs: id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@main - # Consistent Rust setup for both platforms - - name: Set up Rust nightly - uses: dtolnay/rust-toolchain@nightly - - - name: Output rust version - shell: bash - run: rustup --version + # Install toolchain from rust-toolchain.toml (nightly + components + targets) + - name: Set up Rust + run: rustup show active-toolchain # Cache Rust AFTER toolchain is set up - name: Cache Rust dependencies diff --git a/.github/workflows/ts-test-suite.yml b/.github/workflows/ts-test-suite.yml index 0acb179ab..2df5437a9 100644 --- a/.github/workflows/ts-test-suite.yml +++ b/.github/workflows/ts-test-suite.yml @@ -46,13 +46,9 @@ jobs: id: set-up-homebrew uses: Homebrew/actions/setup-homebrew@main - # Consistent Rust setup for both platforms - - name: Set up Rust nightly - uses: dtolnay/rust-toolchain@nightly - - - name: Output rust version - shell: bash - run: rustup --version + # Install toolchain from rust-toolchain.toml (nightly + components + targets) + - name: Set up Rust + run: rustup show active-toolchain # # Cache Rust AFTER toolchain is set up # - name: Cache Rust dependencies @@ -123,9 +119,19 @@ jobs: run: brew install llvm shell: bash - - name: Install wasm-bindgen-cli + # wasm-bindgen-cli must match the wasm-bindgen version in Cargo.lock + # Use pre-built binary via taiki-e/install-action (faster, avoids transitive dep issues) + - name: Detect wasm-bindgen version + id: wb-version shell: bash - run: cargo install wasm-bindgen-cli --version 0.2.108 + run: | + VERSION=$(grep -A1 'name = "wasm-bindgen"' crates/wasm-quarto-hub-client/Cargo.lock | grep version | head -1 | sed 's/.*"\(.*\)"/\1/') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Install wasm-bindgen-cli + uses: taiki-e/install-action@v2 + with: + tool: wasm-bindgen-cli@${{ steps.wb-version.outputs.version }} - name: Build WASM module shell: bash diff --git a/CLAUDE.md b/CLAUDE.md index 751a2d2ce..39e8571d9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -271,11 +271,12 @@ When fixing ANY bug: - `quarto-treesitter-ast`: generic tree-sitter AST traversal utilities **WASM:** -- `wasm-qmd-parser`: WASM module with entry points from `pampa` (see [crates/wasm-qmd-parser/CLAUDE.md](crates/wasm-qmd-parser/CLAUDE.md) for build instructions) +- `wasm-quarto-hub-client`: WASM client for hub-client (see [crates/wasm-quarto-hub-client/README.md](crates/wasm-quarto-hub-client/README.md) for build instructions) +- `wasm-qmd-parser`: lightweight parsing-only WASM wrapper around `pampa` (dormant — kept for future use) ### `hub-client/` - Quarto Hub web client -A React/TypeScript web application for collaborative editing of Quarto projects. Uses Automerge for real-time sync and the WASM build of `wasm-qmd-parser` for live preview rendering. +A React/TypeScript web application for collaborative editing of Quarto projects. Uses Automerge for real-time sync and the WASM build of `wasm-quarto-hub-client` for live preview rendering. **Key directories:** - `src/components/` - React components (Editor, FileSidebar, tabs, etc.) @@ -309,7 +310,8 @@ All VFS file paths use the `/project/` prefix. When resolving file paths in WASM - `pampa` is the core Quarto engine crate - `quarto-core` handles higher-level orchestration -- `wasm-quarto-hub-client` is the WASM client (NOT wasm-qmd-parser) +- `wasm-quarto-hub-client` is the active WASM client for hub-client +- `wasm-qmd-parser` is dormant — a lightweight parsing-only WASM wrapper kept for future use - Always check `git diff` for uncommitted changes before starting work on a continuation session ## hub-client Commit Instructions diff --git a/Cargo.toml b/Cargo.toml index f7e223eed..7ad82a3bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = [ ] default-members = ["crates/*", "crates/experiments/reconcile-viewer"] # Excluded crates require special build toolchains or targets: -# - WASM crates: build with wasm-pack or --target wasm32-unknown-unknown +# - WASM crates: require --target wasm32-unknown-unknown and -Zbuild-std (see dev-docs/wasm.md) # - pampa/fuzz: requires nightly Rust + libfuzzer-sys (Linux/macOS only), run via `cargo fuzz` # crates/experiments is a container directory, not a crate, so we exclude it from crates/* matching. exclude = [ @@ -97,9 +97,6 @@ path = "./crates/tree-sitter-qmd" [workspace.dependencies.tree-sitter-sexpr] path = "./crates/tree-sitter-sexpr" -[workspace.dependencies.wasm-qmd-parser] -path = "./crates/wasm-qmd-parser" - [workspace.dependencies.pampa] path = "./crates/pampa" default-features = false @@ -273,7 +270,7 @@ lua-src = { path = "crates/lua-src-wasm" } # Profiles must be set at the workspace level [profile.dev] # Tell `rustc` to optimize for small code size to -# work around "too many locals" error from wasm-pack +# work around "too many locals" error in WASM builds # https://github.com/wasm-bindgen/wasm-bindgen/issues/3451#issuecomment-1562982835 opt-level = "s" diff --git a/crates/wasm-qmd-parser/.appveyor.yml b/crates/wasm-qmd-parser/.appveyor.yml deleted file mode 100644 index 50910bd6f..000000000 --- a/crates/wasm-qmd-parser/.appveyor.yml +++ /dev/null @@ -1,11 +0,0 @@ -install: - - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - - if not defined RUSTFLAGS rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain nightly - - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - - rustc -V - - cargo -V - -build: false - -test_script: - - cargo test --locked diff --git a/crates/wasm-qmd-parser/.cargo/config.toml b/crates/wasm-qmd-parser/.cargo/config.toml deleted file mode 100644 index 1deefb166..000000000 --- a/crates/wasm-qmd-parser/.cargo/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[target.wasm32-unknown-unknown] -rustflags = ["-C", "target-feature=+bulk-memory", "-Zwasm-c-abi=spec"] \ No newline at end of file diff --git a/crates/wasm-qmd-parser/.github/dependabot.yml b/crates/wasm-qmd-parser/.github/dependabot.yml deleted file mode 100644 index 7377d3759..000000000 --- a/crates/wasm-qmd-parser/.github/dependabot.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: 2 -updates: -- package-ecosystem: cargo - directory: "/" - schedule: - interval: daily - time: "08:00" - open-pull-requests-limit: 10 diff --git a/crates/wasm-qmd-parser/.travis.yml b/crates/wasm-qmd-parser/.travis.yml deleted file mode 100644 index 7a913256e..000000000 --- a/crates/wasm-qmd-parser/.travis.yml +++ /dev/null @@ -1,69 +0,0 @@ -language: rust -sudo: false - -cache: cargo - -matrix: - include: - - # Builds with wasm-pack. - - rust: beta - env: RUST_BACKTRACE=1 - addons: - firefox: latest - chrome: stable - before_script: - - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) - - cargo install-update -a - - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f - script: - - cargo generate --git . --name testing - # Having a broken Cargo.toml (in that it has curlies in fields) anywhere - # in any of our parent dirs is problematic. - - mv Cargo.toml Cargo.toml.tmpl - - cd testing - - wasm-pack build - - wasm-pack test --chrome --firefox --headless - - # Builds on nightly. - - rust: nightly - env: RUST_BACKTRACE=1 - before_script: - - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) - - cargo install-update -a - - rustup target add wasm32-unknown-unknown - script: - - cargo generate --git . --name testing - - mv Cargo.toml Cargo.toml.tmpl - - cd testing - - cargo check - - cargo check --target wasm32-unknown-unknown - - cargo check --no-default-features - - cargo check --target wasm32-unknown-unknown --no-default-features - - cargo check --no-default-features --features console_error_panic_hook - - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook - - cargo check --no-default-features --features "console_error_panic_hook wee_alloc" - - cargo check --target wasm32-unknown-unknown --no-default-features --features "console_error_panic_hook wee_alloc" - - # Builds on beta. - - rust: beta - env: RUST_BACKTRACE=1 - before_script: - - (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update) - - (test -x $HOME/.cargo/bin/cargo-generate || cargo install --vers "^0.2" cargo-generate) - - cargo install-update -a - - rustup target add wasm32-unknown-unknown - script: - - cargo generate --git . --name testing - - mv Cargo.toml Cargo.toml.tmpl - - cd testing - - cargo check - - cargo check --target wasm32-unknown-unknown - - cargo check --no-default-features - - cargo check --target wasm32-unknown-unknown --no-default-features - - cargo check --no-default-features --features console_error_panic_hook - - cargo check --target wasm32-unknown-unknown --no-default-features --features console_error_panic_hook - # Note: no enabling the `wee_alloc` feature here because it requires - # nightly for now. diff --git a/crates/wasm-qmd-parser/CLAUDE.md b/crates/wasm-qmd-parser/CLAUDE.md deleted file mode 100644 index 34fbc2211..000000000 --- a/crates/wasm-qmd-parser/CLAUDE.md +++ /dev/null @@ -1,32 +0,0 @@ -# wasm-qmd-parser - -WASM build of the `pampa` qmd parser for use in browser environments. - -## Important: Excluded from Workspace - -This crate is **excluded from the default workspace build** because it cannot be compiled as a native shared library. The dependency chain pulls in V8 (via deno_core) which uses thread-local storage incompatible with native cdylib builds. - -Build this crate explicitly using wasm-pack as described below. - -## Build Instructions - -```bash -cd crates/wasm-qmd-parser - -# macOS only: Use Homebrew LLVM (Apple Clang doesn't support wasm32-unknown-unknown) -# Requires: brew install llvm -export PATH="/opt/homebrew/opt/llvm/bin:$PATH" - -# Set C flags for tree-sitter WASM compilation -# - Include our C shims from wasm-sysroot -# - Define HAVE_ENDIAN_H for tree-sitter's endian detection -export CFLAGS_wasm32_unknown_unknown="-I$(pwd)/wasm-sysroot -Wbad-function-cast -Wcast-function-type -fno-builtin -DHAVE_ENDIAN_H" - -# Build with wasm-pack -# Note: Requires opt-level = "s" in workspace profile.dev to avoid "too many locals" error -wasm-pack build --target web --dev -``` - -## Output - -The built package is output to `pkg/` and can be used directly in web applications or published to npm. diff --git a/crates/wasm-qmd-parser/README.md b/crates/wasm-qmd-parser/README.md index 6b6840850..f6a1f785e 100644 --- a/crates/wasm-qmd-parser/README.md +++ b/crates/wasm-qmd-parser/README.md @@ -1,84 +1,26 @@ -
wasm-pack-template