5.2 KiB
WRN Language Specification 1.0
This document is the canonical public contract for .wrn files in WRNexusJS 0.3.x.
The executable source of truth is @wrnexus/syntax; the compiler re-exports its
parser and AST for compatibility.
Compatibility promise
WRNexusJS 0.3 keeps all previously supported declarations, including:
page,component, andlayoutrootslayout = "...",types,props,state,view,seo, andstylefunctions,lifecycle, andwatchapi,ssr,client, andrealtimedata-for,{#each}, conditions, interpolations, events, andclass:*
New syntax is additive. Existing projects do not need to adopt it immediately. Since WRNexusJS 0.5.1, dynamic component props may use JSX-style unquoted expressions. Quoted expression attributes remain supported for compatibility:
state items = [{"label":"Accessibility","href":"/accessibility"}]
<FeatureList items={items} />
<FeatureList items={[{"label":"Accessibility","href":"/accessibility"}]} />
<FeatureList primaryAction={{"label":"Open","href":"/open"}} />
<FeatureList items="{items}" />
Expression-valued component props serialize arrays and objects as JSON while preserving booleans, numbers, and strings. Literal HTML attributes continue to require quotes.
File structure
A file may begin with TypeScript imports and must contain one root declaration:
import { appUrl } from "@wrnexus/helpers";
page Home {
view {
<main>Home</main>
}
}
Root names are JavaScript identifiers. The valid root kinds are page, component,
and layout.
Execution declarations
runtime = "universal"
hydrate = "visible"
Runtime targets:
server: never emits an interactive browser scopeclient: intended for browser executionuniversal: server-rendered and optionally hydrated
Hydration strategies:
loadidlevisibleinteractionnonemedia:<media-query>
client = "..." remains an alias for a hydration declaration. The existing
client { ... } mode block remains valid.
Props and state
props {
title: string
count: number = 0
enabled: boolean = false
}
state open: boolean = false
state links = [{"label":"Home","href":"/"}]
state options = {"dense":true}
A prop without an initializer is required. State always requires an initializer. State initializers are JavaScript expressions, including native arrays and objects. Typed initializers are validated when their literal type can be determined.
Computed values and effects
computed {
total = price * quantity
label = `${quantity} items`
}
effect {
document.title = label
}
Computed values are dependency-tracked and cached. Effects rerun after a batched reactive update when a referenced state or computed value changes.
Data loading and actions
load server {
return await repository.list(ctx.tenant?.id)
}
load client {
return await fetch("/api/live").then((response) => response.json())
}
action save(input) {
return await repository.save(input)
}
Server and client loaders are exported separately by the compiler. Named actions
are exported individually and through __wrnexusActions for framework adapters.
Security metadata
security {
auth = "required"
csrf = "true"
roles = "admin,editor"
rateLimit = "strict"
}
The compiler exports this metadata as __wrnexusSecurity. Runtime middleware or
plugins can enforce organization-specific policy. Metadata does not replace global
security headers or API validation.
View syntax
view {
<button
type="button"
class:opacity-50='loading'
@click='save()'
>
{loading ? "Saving..." : title}
</button>
}
Supported view features include:
- HTML and component tags
- escaped
{expression}interpolation - event attributes such as
@click,@window:scroll, and@document:click - conditional
class:*attributes data-showdata-for="item, index in items", optionally keyed withkey item.idordata-key="item.id"{#if},{:else if},{:else}, and{/if}{#each items as item, index key item.id}, optional keys, and optional{:empty}branches- comments and scoped styles
{#if} and {#each} are rendered on the server for the initial response and
remain reactive after hydration. Browser state changes switch conditional
branches and rerender loop rows, including the {:empty} branch.
Output is escaped by default. Explicit raw HTML APIs must be treated as security boundaries.
Stable diagnostics
Canonical diagnostics use stable identifiers such as:
WRN-PARSE-001WRN-PARSE-MEMBERWRN-PROP-INITIALIZERWRN-SYMBOL-DUPLICATEWRN-HYDRATE-STRATEGYWRN-RUNTIME-TARGETWRN-RUNTIME-SERVER-INTERACTIVEWRN-A11Y-001
Compiler, doctor, build, and future language-server integrations should consume
@wrnexus/syntax diagnostics rather than implementing independent parsers.
AST ownership
The canonical packages are:
@wrnexus/syntax lexer, parser, AST, specification, diagnostics
@wrnexus/compiler code generation and compatibility re-exports
Direct imports from compiler internals are deprecated. Public imports from
@wrnexus/compiler continue to work in 0.3.x.