Strict CSP

Expression-in-attribute frameworks normally compile :onclick="count++" with new Function — which a strict Content-Security-Policy (no 'unsafe-eval') blocks, and Chrome MV3 extensions forbid outright. Banking, government, healthcare, extensions — same wall.

Sprae’s evaluator is pluggable. The CSP build swaps new Function for jessie — a JS interpreter, no eval anywhere — and keeps standard JS expressions:

<!-- all of these run under script-src 'self' -->
<button :onclick="user.name = 'John'">Set name</button>
<li :each="item in items.filter(i => i.active)" :text="item.name"></li>
<input :onkeydown.enter="todos.push({ text: draft, done: false })" />

Setup

<!-- CDN (self-host the file for script-src 'self') -->
<script src="/js/sprae-csp.umd.js" data-start></script>
// or ESM
import sprae from 'sprae'
import jessie from 'subscript/jessie'

sprae.use({ compile: jessie })

Get the bundle: sprae-csp.umd.js · sprae-csp.js (ESM)

vs Alpine’s CSP build

Alpine offers a CSP build that restricts expressions to a small subset. Per its own docs:

expression sprae CSP Alpine CSP
user.name = 'John' (property assignment)
items.filter(i => i.active) (arrow functions)
Math.max(a, b), JSON.stringify(x) (globals)
:html / x-html
size, min+gzip 18.1kb 20.3kb

Alpine’s recommended workaround is moving logic into Alpine.data() components — sprae just runs your expression.

Known limits

The full sprae test suite runs against the CSP build on every commit (CI). Differences from the eval build:

Chrome extension (MV3)

MV3 disallows remotely-hosted code and string evaluation — so: bundle sprae-csp with the extension, no CDN.

// manifest.json
{
  "manifest_version": 3,
  "action": { "default_popup": "popup.html" }
}
<!-- popup.html -->
<script src="sprae-csp.umd.js" data-start></script>
<div :scope="{ on: false }">
  <button :onclick="on = !on" :text="on ? 'Disable' : 'Enable'"></button>
</div>

Header example

Content-Security-Policy: default-src 'self'; script-src 'self'

No 'unsafe-eval', no 'unsafe-inline' needed — directives are attributes, not inline scripts.