Skip to content

Latest commit

Β 

History

History
93 lines (64 loc) Β· 3.74 KB

File metadata and controls

93 lines (64 loc) Β· 3.74 KB

Rendu - Agent Guide

JavaScript Hypertext Preprocessor β€” a lightweight toolkit for mixing HTML and JavaScript with PHP-style template syntax, supporting streaming and progressive rendering.

Architecture

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

Parser (parser.ts)

Converts template syntax to normalized <?...?> tags, then tokenizes:

  1. <script server>...</script> β†’ <?js...?>
  2. {{{ expr }}} β†’ <?=expr?> (raw) / {{ expr }} β†’ <?=htmlspecialchars(expr)?> (escaped)
  3. Regex-based tokenizer extracts text, code, and expr tokens

Compiler (compiler.ts)

  • Generates echo() calls for text/expr tokens, raw code for code tokens
  • Two modes: stream: true (returns ReadableStream) / stream: false (returns string)
  • contextKeys option uses destructuring instead of with() for strict mode compatibility

Runtime (_runtime.ts)

Inlined JS code (not imported at runtime). Two variants:

  • runtimeStream: Collects chunks, returns ReadableStream with concatStreams()
  • runtimeText: Collects chunks, awaits promises, concatenates to string

Handles: strings, functions, Promises, Response objects, ReadableStreams, Uint8Arrays

Render (render.ts)

  • createRenderContext(): Builds context with $REQUEST, $URL, $COOKIES (lazy-parsed via Proxy), setCookie, redirect, htmlspecialchars
  • renderToResponse(): Executes compiled template with context, returns FastResponse

CLI (cli.ts)

Starts srvx dev server with serveStatic middleware that intercepts .html files, compiles them as templates, and renders with request context + $GLOBALS.

Commands

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 + oxfmt

Key Dependencies

  • srvx β€” HTTP server (FastResponse, serve, serveStatic, log)
  • cookie-es β€” Cookie parsing/serialization
  • obuild β€” Build tool
  • vitest β€” Test runner
  • oxlint / oxfmt β€” Linter and formatter
  • tsgo (@typescript/native-preview) β€” Type checking

Testing

Tests are in test/ using vitest:

  • test/parser.test.ts β€” Tokenizer tests for all syntax variants
  • test/compiler.test.ts β€” End-to-end compile + render tests with snapshot comparisons (formatted via oxfmt)

Snapshots live in test/snapshots/.

Template Syntax Reference

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

Context Variables

$REQUEST, $METHOD, $URL, $HEADERS, $COOKIES, $RESPONSE, htmlspecialchars(), setCookie(), redirect(), echo()