viewpoint-js 0.2.3

Compile-time validated JavaScript macro for Viewpoint
Documentation

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

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\")"

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 (handles NaN, Infinity, -Infinity)
  • Boolean: bool
  • Strings: String, &str (properly escaped)
  • Option: Option<T> where T: ToJsValue (produces value or null)
  • JSON: serde_json::Value (with json feature)

Features

  • json - Enable serde_json::Value support for interpolation

License

MIT