jsxrs 0.1.3

A Rust library for rendering JSX/TSX to complete HTML documents at build-time or server-side.
Documentation

jsxrs

A Rust library for rendering JSX/TSX to complete HTML documents at build-time or server-side.

Overview

jsxrs parses JSX/TSX files and renders them to full HTML documents. It leverages SWC for high-performance parsing and supports modern JSX features including components, props, fragments, and TypeScript.

Features

  • JSX & TSX Support - Parse and render both JavaScript and TypeScript JSX files
  • Props & Expressions - Pass runtime values to components via props
  • Component Imports - Import and render other JSX/TSX components
  • Special <Head> Component - Add elements to the document <head> (title, meta, link, style, script)
  • Tailwind CSS Integration - Automatically generate CSS from Tailwind class names
  • TypeScript Codegen - Generate Rust structs from TypeScript interfaces
  • XSS Protection - Automatic HTML escaping for user content

Installation

Add jsxrs to your Cargo.toml:

[dependencies]
jsxrs = "0.1"

Usage

Basic Rendering

use jsxrs::{render_string, RenderConfig};
use serde_json::json;

let source = r#"
export default function Greeting(props) {
  return <div>Hello, {props.name}!</div>;
}
"#;

let config = RenderConfig::default();
let props = json!({"name": "World"});
let html = render_string(source, "page.jsx", &props, &config).unwrap();

println!("{}", html);

Rendering from File

use jsxrs::{render_file, RenderConfig};
use serde_json::json;
use std::path::PathBuf;

let path = PathBuf::from("src/page.tsx");
let config = RenderConfig {
    pretty: true,
    base_dir: Some(PathBuf::from("src")),
    head_elements: vec![],
    tailwind: false,
};
let html = render_file(&path, &json!({}), &config).unwrap();

Configuration

use jsxrs::{HeadElement, RenderConfig};

let config = RenderConfig {
    pretty: true,                          // Format output with indentation
    base_dir: Some(PathBuf::from(".")),    // Base directory for component resolution
    head_elements: vec![
        HeadElement::Title("My Page".to_string()),
        HeadElement::Meta { 
            name: "description".to_string(), 
            content: "A wonderful page".to_string() 
        },
    ],
    tailwind: false,                       // Enable Tailwind CSS generation
};

Tailwind CSS

Enable Tailwind CSS generation to automatically collect and generate CSS from class names:

let config = RenderConfig {
    tailwind: true,
    ..Default::default()
};

The library will extract all class attributes and generate the corresponding Tailwind CSS.

Using the <Head> Component

Add elements to the document head using the special <Head> component:

export default function Page() {
  return (
    <>
      <Head>
        <title>My Page</title>
        <meta name="description" content="Welcome" />
        <link rel="stylesheet" href="/styles.css" />
      </Head>
      <div>Page content here</div>
    </>
  );
}

Component Imports

Import and render other components:

import Button from './components/button';

export default function Page() {
  return (
    <div>
      <Button label="Click me" />
    </div>
  );
}

Ensure base_dir is configured in RenderConfig for import resolution.

TypeScript Codegen

Generate Rust structs from TypeScript interfaces:

use jsxrs::codegen;

codegen::generate_types(
    &["src/types.tsx"],
    "src/generated/types.rs",
).unwrap();

Given a TypeScript interface:

interface User {
  id: number;
  name: string;
  email?: string;
}

This generates:

use serde::{Serialize, Deserialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
    pub id: f64,
    pub name: String,
    pub email: Option<String>,
}

API Reference

render_string

Renders a JSX/TSX source string to a complete HTML document.

pub fn render_string(
    source: &str,
    file_name: &str,
    props: &Value,
    config: &RenderConfig,
) -> Result<String, JsxrsError>

render_file

Renders a JSX/TSX file to a complete HTML document.

pub fn render_file(
    path: &Path,
    props: &Value,
    config: &RenderConfig,
) -> Result<String, JsxrsError>

generate_types

Generates Rust struct definitions from TypeScript interface declarations.

pub fn generate_types(
    tsx_paths: &[impl AsRef<Path>],
    output_path: &Path,
) -> Result<(), JsxrsError>

RenderConfig

Configuration for the rendering pipeline:

Field Type Description
pretty bool Format output with indentation
base_dir Option<PathBuf> Base directory for component resolution
head_elements Vec<HeadElement> Static head elements to include
tailwind bool Enable Tailwind CSS generation

HeadElement

Elements that can be added to the document head:

  • Title(String) - Page title
  • Meta { name, content } - Meta tags
  • Link { rel, href } - Link tags
  • Style(String) - Inline styles
  • Script(String) - Inline scripts

Supported JSX Features

  • HTML elements (div, span, p, etc.)
  • Self-closing tags (img, br, hr, input, etc.)
  • JSX Fragments (<>...</>)
  • Props and expressions ({props.value}, {1 + 1})
  • Type annotations in TSX files
  • Arrow function and function declarations
  • Component composition

Security

jsxrs automatically escapes HTML content to prevent XSS attacks. User-supplied content in text nodes and attributes is properly escaped.