JavaScript Hypertext Preprocessor β a lightweight toolkit for mixing HTML and JavaScript with PHP-style template syntax, supporting streaming and progressive rendering.
src/
parser.ts # Tokenizer: template string β Token[] (text | code | expr)
compiler.ts # Token[] β async function body string β AsyncFunction
_runtime.ts # Inlined JS runtime for echo/stream/text concatenation
render.ts # Request/response layer: cookies, headers, redirects, HTML escaping
cli.ts # CLI entry: serves static files with srvx, renders .html as templates
index.ts # Public API re-exports
Data flow: Template string β parseTemplate() β tokens β compileTemplateToString() β JS code string β new AsyncFunction() β render function
Converts template syntax to normalized <?...?> tags, then tokenizes:
<script server>...</script>β<?js...?>{{{ expr }}}β<?=expr?>(raw) /{{ expr }}β<?=htmlspecialchars(expr)?>(escaped)- Regex-based tokenizer extracts
text,code, andexprtokens
- Generates
echo()calls for text/expr tokens, raw code for code tokens - Two modes:
stream: true(returnsReadableStream) /stream: false(returnsstring) contextKeysoption uses destructuring instead ofwith()for strict mode compatibility
Inlined JS code (not imported at runtime). Two variants:
runtimeStream: Collects chunks, returnsReadableStreamwithconcatStreams()runtimeText: Collects chunks, awaits promises, concatenates to string
Handles: strings, functions, Promises, Response objects, ReadableStreams, Uint8Arrays
createRenderContext(): Builds context with$REQUEST,$URL,$COOKIES(lazy-parsed via Proxy),setCookie,redirect,htmlspecialcharsrenderToResponse(): Executes compiled template with context, returnsFastResponse
Starts srvx dev server with serveStatic middleware that intercepts .html files, compiles them as templates, and renders with request context + $GLOBALS.
pnpm install # Install deps
pnpm dev # Interactive test runner (vitest dev)
pnpm vitest run <path> # Run specific test file
pnpm test # Full: lint + type-check + tests with coverage
pnpm build # Build with obuild (outputs to dist/)
pnpm play # Start playground server
pnpm fmt # automd + oxlint --fix + oxfmtsrvxβ HTTP server (FastResponse, serve, serveStatic, log)cookie-esβ Cookie parsing/serializationobuildβ Build toolvitestβ Test runneroxlint/oxfmtβ Linter and formattertsgo(@typescript/native-preview) β Type checking
Tests are in test/ using vitest:
test/parser.test.tsβ Tokenizer tests for all syntax variantstest/compiler.test.tsβ End-to-end compile + render tests with snapshot comparisons (formatted viaoxfmt)
Snapshots live in test/snapshots/.
| Syntax | Purpose |
|---|---|
<? code ?> / <?js code ?> |
JavaScript control flow |
<?= expr ?> |
Raw output expression |
{{ expr }} |
HTML-escaped output |
{{{ expr }}} |
Raw (unescaped) output |
<script server>...</script> |
Server-side script block |
$REQUEST, $METHOD, $URL, $HEADERS, $COOKIES, $RESPONSE, htmlspecialchars(), setCookie(), redirect(), echo()