Format presets
A format preset is a reusable format. There is no separate file type for it:
a preset is simply a ScriptPub document that is all header — a
config with empty (or absent) content. Any syntax that can carry
a config can carry a preset (a json file with no content key, an html file
with no <main> content — both parse to content: []).
isPresetDoc(doc) === (doc.content.length === 0)
Identity — PresetRef
A preset’s identity lives in the config’s top-level preset field:
| Field | Type | Description |
|---|---|---|
name |
string |
The preset’s display name, e.g. "Screenplay". Distinct from meta.title, which titles the sample body. |
uri |
string |
Stable identifier (below). |
The uri scheme records where a preset comes from:
| Form | Meaning |
|---|---|
scriptpub:preset/<id> |
A built-in preset. |
scriptpub:curated/<slug> |
A curated preset — part of a shipped set. |
scriptpub:local/<id> |
A user-made preset — device-scoped, not globally resolvable. |
| any URL | A published preset resolvable at that address. |
Provenance for free
Creating a script from a preset clones the preset’s config — and the preset
field rides along. So every script records which preset (name + uri) it was seeded
from. Editing the script’s format never rewrites the field: it is history, not a
live link. Deleting a preset never touches scripts already seeded from it.
Sample body
A preset file may carry content. When it does, that body is the preset’s sample — a short demonstration script that should exercise every block kind, mark, and section the format defines. The sample is preview material for format editors and preset pickers; a script created from the preset starts empty unless the tool explicitly offers the sample as seed content. A header-only file is just a preset without a sample.
Built-in presets
Four presets ship as default instances of the format shape — each is a normal,
fully editable FormatConfig:
- Screenplay (
scriptpub:preset/screenplay) — scene headings (numbered, continuous), action, character cues (with a Characters index and(CONT'D)), parentheticals, dialogue, transitions, dual dialogue, and title-page kinds. - Play (
scriptpub:preset/play) — acts and scenes (scenes reset per act), dialogue-first, stage directions. - Story (
scriptpub:preset/story) — chapters, justified indented paragraphs, headings, scene breaks. - Catalog (
scriptpub:preset/catalog) — the default format for collections and library indexes: group/subgroup headings, linked list entries, annotation notes.
Anatomy of a preset file
The curated Poetry preset (scriptpub:curated/poetry) is a complete,
minimal .spub.html preset — the concrete reference for the whole file
shape. Abridged:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Untitled Poem</title>
<script type="application/json" id="scriptpub">
{
"scriptpub": 2,
"meta": { "title": "Untitled Poem", "language": "en" },
"preset": { "name": "Poetry", "uri": "scriptpub:curated/poetry" },
"blocks": [
{ "id": "heading", "label": "Title",
"behavior": { "outline": true, "rank": 1 },
"editor": { "shortcut": "Mod-1", "enter": "line" },
"syntax": { "html": { "match": [{ "construct": "h1" }], "write": { "tag": "h1" } },
"md": { "match": [{ "construct": "heading", "level": 1 }], "write": { "construct": "heading", "level": 1 } } } },
{ "id": "line", "label": "Line", "default": true,
"editor": { "shortcut": "Mod-2", "enter": "line" },
"syntax": { "html": { "write": { "tag": "p" } } } },
{ "id": "stanza_break", "label": "Stanza break", "shape": "void",
"syntax": { "html": { "match": [{ "construct": "hr" }], "write": { "tag": "hr" } } } }
],
"marks": [
{ "id": "em", "label": "Italic", "editor": { "shortcut": "Mod-i" },
"syntax": { "html": { "write": { "tag": "em" } }, "md": { "write": { "delim": "*" } } } },
{ "id": "strong", "label": "Bold", "editor": { "shortcut": "Mod-b" },
"syntax": { "html": { "write": { "tag": "strong" } }, "md": { "write": { "delim": "**" } } } }
],
"syntax": { "html": { "newline": "br" } }
}
</script>
<style id="scriptpub-style">
h1.heading { font-size: 1.4rem; font-weight: bold; margin-top: 2.4rem; }
p.line { margin-left: 4ch; }
hr.stanza_break { border: none; margin-top: 1.2rem; }
</style>
</head>
<body>
<main>
<h1>Harbor Light</h1>
<p>The tide keeps what the pier lets go,</p>
<hr />
<p>And every light that says <em>come home</em> says <strong>stay away</strong> the same.</p>
</main>
</body>
</html>
Everything above <main> is the format; <main> is the sample body. Strip that
body and you have a header-only preset.