ZX
A Zig library for building web applications with JSX-like syntax. Write declarative UI components using familiar JSX patterns, transpiled to efficient Zig code.
📚 Full Documentation of ZX →
Contributing
Project Overview
This is a VS Code extension that provides syntax highlighting, language support, and formatting for ZX files (.zx). ZX allows you to write HTML within Zig code using JSX-like syntax.
Project Structure
zx-vscode/
├── src/ # TypeScript source code
│ ├── extension.ts # Main extension entry point - handles activation, LSP setup, formatting middleware
│ ├── util.ts # Utility functions (ZLS path detection)
│ └── fmt/ # Formatting logic
│ ├── fmt.ts # Main formatting orchestrator (formatZx, formatZig, formatHtml)
│ └── util.ts # Formatting utilities (HTML extraction, expression parsing)
├── syntaxes/ # TextMate grammar files for syntax highlighting
│ ├── zx.tmLanguage.json # Main ZX syntax definition
│ └── zx-injection.tmLanguage.json # Injection grammar for embedded content
├── test/ # Test suite
│ ├── fmt/ # Formatting tests
│ └── data.test.ts # Data structure tests
├── images/ # Extension icons
└── language-configuration.json # VS Code language configuration (brackets, comments, etc.)
Why This Structure?
src/extension.ts: Centralizes VS Code API integration and extension lifecycle management
src/fmt/: Separates formatting concerns into a dedicated module with clear responsibilities
syntaxes/: Uses TextMate grammars (standard for VS Code) to define language syntax
- Virtual document providers: Enable formatting of embedded HTML/Zig by creating temporary documents that VS Code's formatters can process
How Things Work
The formatting system follows a sophisticated pipeline to handle the mixed Zig/HTML nature of ZX files:
1. User triggers format (Cmd+Shift+P → Format Document)
│
└─→ extension.ts: provideFormattingEdits()
│
└─→ fmt.ts: formatZx()
│
├─→ Step 1: Extract HTML blocks
│ └─→ util.ts: extractHtmls()
│ • Scans document for HTML tags inside parentheses
│ • Replaces HTML with placeholders (<html:N />)
│ • Returns prepared Zig code + HTML map
│
├─→ Step 2: Format Zig code
│ └─→ fmt.ts: formatZig()
│ └─→ runZigFmt() (uses zig fmt CLI or ZLS)
│
├─→ Step 3: Format HTML blocks
│ └─→ fmt.ts: formatHtml()
│ ├─→ Extract Zig expressions from HTML
│ ├─→ Recursively format nested HTML (if any)
│ ├─→ Format Zig expressions (if enabled)
│ └─→ Use vscode-html-languageservice to format HTML
│
└─→ Step 4: Merge everything back
└─→ patchInFormattedHtml()
• Replaces placeholders with formatted HTML
• Returns complete formatted document
Key Components
Language Server Integration
- Uses ZLS (Zig Language Server) from the official Zig extension
- Provides diagnostics, hover, and other LSP features
- Filters out false positives (e.g., "expected expression, found '<'" for ZX syntax)
Virtual Document Providers
- Creates temporary virtual documents for embedded HTML/Zig content
- Allows VS Code's HTML formatter to process HTML blocks in isolation
- Uses URI schemes:
embedded-content-fmt-html:// and embedded-content-fmt-zig://
HTML Extraction Logic
- Tracks string boundaries to avoid false matches
- Only extracts HTML inside parentheses (ZX syntax requirement)
- Uses
vscode-html-languageservice scanner to identify HTML tags
Recursive Formatting
- Handles nested HTML inside Zig expressions
- Formats inner HTML blocks before formatting the containing Zig expression
- Maintains proper indentation across nested levels
How to Contribute
Setup
Prerequisites
- Bun.js - We use it for testing
- Zig - We use it for formatting
- VS Code - We use it for development
Clone and install dependencies:
git clone https://github.com/nurulhudaapon/zx-vscode.git
cd zx-vscode
npm install
Compile TypeScript:
npm run compile
# Or watch mode for development:
npm run watch
Open in VS Code:
- Open the project folder in VS Code
- Press
F5 to launch a new Extension Development Host window
- In the new window, open a
.zx file to test the extension
Making Changes
Adding Syntax Highlighting:
Modifying Formatting:
- Main logic:
src/fmt/fmt.ts
- Utilities:
src/fmt/util.ts
- Test your changes with the test suite (see below)
Changing Extension Behavior:
- Entry point:
src/extension.ts
- Add commands in
package.json under contributes.commands
- Register handlers in
activate() function
Testing
Have 'bun.js' installed as we use it for testing.
Run the test suite:
npm test
Test files are located in test/:
test/fmt/fmt.test.ts - Formatting function tests
test/fmt/util.test.ts - Utility function tests
test/data.test.ts - Data structure and edge case tests
Manual Testing:
- Launch extension in development mode (
F5)
- Create test
.zx files with various patterns
- Test formatting, syntax highlighting, and LSP features
- Check the Output panel → "ZX Language Server" for logs
Submitting Contributions
- Create a branch and make your changes
- Format code:
npm run fmt
- Run tests:
npm test
- Open a Pull Request with a clear description
Areas That Need Help
- Syntax highlighting improvements: Better recognition of edge cases
- Formatting edge cases: Handling complex nested structures
- Performance optimization: Faster formatting for large files
- LSP features: See detailed checklist below
LSP Features Checklist
The following LSP features need implementation to provide a better development experience:
HTML Block Support:
- [ ] Diagnostics for HTML syntax errors within ZX files
- [ ] Autocomplete for HTML tags and attributes inside HTML blocks
- [ ] Hover information for HTML elements (showing tag documentation, attribute descriptions)
- [ ] Go to definition for HTML components/imports
- [ ] Semantic highlighting for HTML content
ZX File Analysis via ZLS:
- [ ] Transform
.zx files to .zig format for ZLS processing
- [ ] Create virtual document provider that converts ZX → Zig on-the-fly
- [ ] Map ZLS diagnostics back to original ZX file positions
- [ ] Handle ZX-specific syntax in Zig transformation (preserve HTML blocks as comments or special markers)
- [ ] Support for
.zx file imports in Zig code analysis
- [ ] Type checking and diagnostics for Zig expressions within HTML blocks
Virtual Document Provider for ZLS:
- [ ] Implement
TextDocumentContentProvider for zx:// URI scheme
- [ ] Convert ZX syntax to valid Zig code that ZLS can understand
- [ ] Preserve source mapping between virtual Zig and original ZX positions
- [ ] Handle nested HTML blocks in Zig expressions
- [ ] Support incremental document updates
- [ ] Cache transformed documents for performance
Integration Points:
- [ ] Register virtual document provider in
extension.ts
- [ ] Configure ZLS to accept virtual Zig documents
- [ ] Map LSP responses (diagnostics, hover, completion) back to ZX positions
- [ ] Handle edge cases (empty files, syntax errors, malformed HTML)
Testing Requirements:
- [ ] Test virtual document transformation accuracy
- [ ] Test position mapping (Zig → ZX)
- [ ] Test diagnostics propagation
- [ ] Test autocomplete in various contexts (HTML, Zig expressions, mixed)
- [ ] Test hover information accuracy