JSX runtime escape
PRISM is safe by default: both text children and attribute values are HTML-escaped automatically — on the compile-fold path (renderChild / __bextEsc) and the runtime alike. The first column shows the auto-escaped default; the second uses <Raw> to opt OUT (only for HTML you trust).
Tip
Never call escapeHtml() manually on values you pass as JSX children — they'll be double-encoded. Reserve <Raw> for HTML produced by a trusted renderer (marked, sanitize-html, etc.) and never for raw user input.
Output
| Payload | {value} (auto-escaped) | <Raw html={value} /> (opt-out) | attribute |
|---|---|---|---|
| plain text | hello world | hello world | |
| HTML chars | <b>strong</b> | strong | |
| image tag | <img src=x> | ||
| ampersand & quotes | Tom & Jerry's "best" episode | Tom & Jerry's "best" episode | |
| attr injection | " onmouseover="x | " onmouseover="x |
// PRISM's escape policy (safe by default):
// <p>{x}</p> — children are HTML-ESCAPED automatically.
// <input value={x}> — attributes are escaped automatically too.
// <p><Raw html={x}/> — opt OUT of escaping (you vouch x is safe HTML).
//
// You no longer call escapeHtml() by hand for plain values — the runtime
// (and the compile fold's renderChild) escape any child that isn't marked
// safe. Reach for <Raw> / dangerouslySetInnerHTML only for trusted markup.
import { Raw } from "@bext-stack/framework/jsx-runtime";
export default function Page({ user, renderedMarkdown }) {
return (
<div>
<p>{user.bio}</p> {/* auto-escaped — safe */}
<input value={user.bio} /> {/* attributes auto-escaped */}
<div><Raw html={renderedMarkdown} /></div> {/* opt-out: trusted HTML */}
</div>
);
}