28 releases
Uses new Rust 2024
| 0.4.3 | Jan 17, 2026 |
|---|---|
| 0.4.2 | Jan 4, 2026 |
| 0.3.6 | Jan 4, 2026 |
| 0.2.16 | Jan 2, 2026 |
| 0.2.11 | Dec 31, 2025 |
#24 in #playwright
Used in 2 crates
100KB
2K
SLoC
viewpoint-js
Compile-time validated JavaScript macro for Viewpoint.
This crate provides a js! macro that validates JavaScript syntax at compile time,
similar to how serde_json::json! validates JSON. This catches JavaScript syntax
errors early, before they reach the browser.
Features
- Compile-time validation: JavaScript syntax errors are caught during compilation
- Value interpolation: Embed Rust expressions using
#{expr}syntax (quoted/escaped) - Raw interpolation: Inject pre-built JavaScript using
@{expr}syntax (unquoted) - Zero runtime overhead: Static strings when no interpolation is used
- Clear error messages: Points to the exact location of syntax errors
- Full JavaScript syntax support: Single-quoted strings, template literals, regex literals, and more
Usage
Add to your Cargo.toml:
[dependencies]
viewpoint-js = "0.2"
viewpoint-js-core = "0.2" # Required for interpolation
Simple Expressions
use viewpoint_js::js;
// Returns &'static str
let code = js!{ 1 + 2 };
let code = js!{ () => window.innerWidth };
let code = js!{
(() => {
const items = document.querySelectorAll('li');
return items.length;
})()
};
Value Interpolation
Use #{expr} to embed Rust values into JavaScript (properly quoted and escaped):
use viewpoint_js::js;
use viewpoint_js_core::ToJsValue;
let selector = ".my-class";
let code = js!{ document.querySelector(#{selector}) };
// Produces: "document.querySelector(\".my-class\")"
let count = 42;
let code = js!{ Array(#{count}).fill(0) };
// Produces: "Array(42).fill(0)"
Raw Interpolation
Use @{expr} to inject pre-built JavaScript expressions directly (without quoting):
use viewpoint_js::js;
// Inject a JavaScript expression as-is
let selector_expr = "document.querySelectorAll('.item')";
let code = js!{ Array.from(@{selector_expr}) };
// Produces: "Array.from(document.querySelectorAll('.item'))"
// Useful for building complex JS with dynamic parts
let frame_access = get_frame_access_code();
let code = js!{
(function() {
const doc = @{frame_access};
return doc.title;
})()
};
Mixing Both Interpolation Types
You can use both #{} and @{} in the same macro call:
use viewpoint_js::js;
let selector_expr = "document.body";
let attr_name = "data-id";
let code = js!{ @{selector_expr}.setAttribute(#{attr_name}, "value") };
// Produces: "document.body.setAttribute(\"data-id\", \"value\")"
JavaScript Syntax Support
The js! macro supports all JavaScript string and literal syntax:
use viewpoint_js::js;
// Single-quoted strings
let code = js!{ console.log('hello') };
// Template literals with JavaScript interpolation
let code = js!{ `Hello, ${userName}!` };
// Template literals with Rust interpolation
let name = "world";
let code = js!{ `Hello, #{name}!` };
// Regex literals
let code = js!{ /^test/.test(str) };
// XPath with mixed quotes
let code = js!{ document.evaluate("//div[@class='item']", doc) };
// CSS attribute selectors
let code = js!{ document.querySelector('[data-id="test"]') };
Compile-Time Errors
Invalid JavaScript produces compile-time errors:
use viewpoint_js::js;
// This won't compile!
let code = js!{ function( };
Supported Types for Interpolation
The following types implement ToJsValue:
- Integers:
i8,i16,i32,i64,i128,isize,u8,u16,u32,u64,u128,usize - Floats:
f32,f64(handlesNaN,Infinity,-Infinity) - Boolean:
bool - Strings:
String,&str(properly escaped) - Option:
Option<T>whereT: ToJsValue(produces value ornull) - JSON:
serde_json::Value(withjsonfeature)
Features
json- Enableserde_json::Valuesupport for interpolation
License
MIT
Dependencies
~16–30MB
~331K SLoC