Skip to content

gwigz/jsx-inline

Repository files navigation

@gwigz/jsx-inline

Compile JSX templates into optimized inline string literals at build time. No runtime, no virtual DOM, just concatenated strings.

Write your markup with JSX for type safety and composability, then run compile() as a build step. It evaluates each .tsx file, minifies the HTML, shortens CSS class names, and outputs a plain .ts file with string concatenation in place of every JSX expression.

When is this useful?

When your target environment doesn't have a DOM or JSX runtime, but you still want to author HTML with JSX. This is especially handy for TypeScriptToLua projects that need to embed markup in Lua strings, you get the ergonomics of JSX during development and compact string output in the compiled result.

Install

bun add -D @gwigz/jsx-inline
# or
npm install -D @gwigz/jsx-inline

Setup

Configure JSX in your tsconfig.json:

{
  "compilerOptions": {
+   "jsx": "react",
+   "jsxFactory": "h",
+   "jsxFragmentFactory": "Fragment"
  }
}

Usage

Call compile() in your build script before transpilation:

import { compile } from "@gwigz/jsx-inline";

await compile(["src/template.tsx", "src/ui.tsx"]);

This reads each .tsx file, evaluates the JSX, and writes a corresponding .ts file with all markup replaced by string literals. Run your normal build step after.

Options

Option Type Default Description
minifyOptions object Override html-minifier-terser options

Example

Given a template:

// @jsx h
export function pageShell(title: string) {
  return (
    <html>
      <head>
        <title>{title}</title>
      </head>
      <body>
        <h1>{title}</h1>
      </body>
    </html>
  );
}

After compile(), the generated .ts file contains:

export function pageShell(title: string) {
  return "<html><head><title>" + title + "</title></head><body><h1>" + title + "</h1></body></html>";
}

CSS classes and IDs are shortened across all files (toolbara, statusb, etc.) to minimize output size. Boolean attributes like checked are automatically detected from parameter types and compiled into conditional expressions (e.g. checked={enabled} becomes (enabled ? ' checked=""' : "")).

How it works

  1. Evaluate parses each .tsx with ts-morph, detects template functions and inline JSX, evaluates them with an embedded minimal JSX runtime, and minifies the resulting HTML
  2. Shorten builds a shortening map from all combined HTML, replacing CSS class names and IDs with single-letter equivalents
  3. Generate replaces each JSX node in the AST with a string concatenation expression, splicing dynamic values back in at their original positions

About

Compiles JSX templates into optimized inline string literals

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors