You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Import .fdx (Final Draft XML) files into Scriptty as a Film, into a Series as a new Episode, or via the standard Open dialog (auto-detected by extension). Mirrors the Fountain import flow (#184) — same dirty-state guards, same import-summary toast, same per-episode entry points.
Why
Final Draft is the dominant pro screenwriting tool. Co-writing handoffs frequently arrive as .fdx. Scriptty already imports Fountain (#184) but not FDX, so writers coming from Final Draft hit a wall on day one.
Spec research findings (lock the design)
Done a thorough pass on the FDX format — full report in the implementation comment below. Key facts that shape v1:
Format: XML 1.0, UTF-8, no public DTD. Only <Content> is required at the root; everything else is optional and varies wildly across Final Draft versions and other apps that round-trip the format.
Element types are explicit (Type="Scene Heading", "Action", "Character", "Parenthetical", "Dialogue", "Transition", "Shot", "General", "Lyrics", "Outline N"). No Fountain-style forced-prefix heuristics needed — just dispatch on the attribute.
Inline formatting uses sibling <Text> children with Style="Bold+Italic+Underline" (+-separated). Maps directly to ProseMirror's bold/italic/underline marks (Scriptty already supports all three).
Title page is free-form <Paragraph> blocks — no <Title>/<Author> semantic markers. Real Final Draft pads with blank lines and centres credits. v1: dump full title-page text into meta.extra["fdx_title_page"] and try a Beat-style heuristic for meta.title / meta.author / meta.draft_date / meta.contact.
Dual dialogue: <Paragraph><DualDialogue><Paragraph Type="Character">…</Paragraph><Paragraph Type="Dialogue">…</Paragraph>…</DualDialogue></Paragraph>. Collapse to sequential pairs (matches Fountain handling per Fountain import (round-trip-safe) #184 scope).
Locked scene numbers (<Paragraph Type="Scene Heading" Number="1A">) — meaningful for production. v1: drop with summary count, revisit when scene_cards gains a free-form metadata field.
Scope decisions (locked)
FDX feature
Scriptty mapping
Type="Scene Heading" / "Shot"
scene_heading node (Shot folded — Scriptty has no separate Shot type)
What
Import
.fdx(Final Draft XML) files into Scriptty as a Film, into a Series as a new Episode, or via the standard Open dialog (auto-detected by extension). Mirrors the Fountain import flow (#184) — same dirty-state guards, same import-summary toast, same per-episode entry points.Why
Final Draft is the dominant pro screenwriting tool. Co-writing handoffs frequently arrive as
.fdx. Scriptty already imports Fountain (#184) but not FDX, so writers coming from Final Draft hit a wall on day one.Spec research findings (lock the design)
Done a thorough pass on the FDX format — full report in the implementation comment below. Key facts that shape v1:
<Content>is required at the root; everything else is optional and varies wildly across Final Draft versions and other apps that round-trip the format.Type="Scene Heading","Action","Character","Parenthetical","Dialogue","Transition","Shot","General","Lyrics","Outline N"). No Fountain-style forced-prefix heuristics needed — just dispatch on the attribute.<Text>children withStyle="Bold+Italic+Underline"(+-separated). Maps directly to ProseMirror's bold/italic/underline marks (Scriptty already supports all three).<Paragraph>blocks — no<Title>/<Author>semantic markers. Real Final Draft pads with blank lines and centres credits. v1: dump full title-page text intometa.extra["fdx_title_page"]and try a Beat-style heuristic formeta.title/meta.author/meta.draft_date/meta.contact.<Paragraph><DualDialogue><Paragraph Type="Character">…</Paragraph><Paragraph Type="Dialogue">…</Paragraph>…</DualDialogue></Paragraph>. Collapse to sequential pairs (matches Fountain handling per Fountain import (round-trip-safe) #184 scope).<Paragraph Type="Scene Heading" Number="1A">) — meaningful for production. v1: drop with summary count, revisit when scene_cards gains a free-form metadata field.Scope decisions (locked)
Type="Scene Heading"/"Shot"scene_headingnode (Shot folded — Scriptty has no separate Shot type)Type="Action"/"General"/"Lyrics"/"Outline N"actionnodeType="Character"(incl. extensions like(V.O.))characternode — extensions kept inlineType="Parenthetical"parentheticalnode — parens kept in content (project convention)Type="Dialogue"dialoguenodeType="Transition"transitionnode<Text Style="Bold">/"Italic"/"Underline"(or+-combined)<Text Style="Strikeout"/"AllCaps"/"Highlight"><DualDialogue><TitlePage>meta.title/meta.author/meta.draft_date/meta.contact+ full text →meta.extra["fdx_title_page"]Versionattributemeta.extra["fdx_source_version"](cheap debug aid)<Revisions>+<Text RevisionID><ScriptNotes>/ inline<ScriptNote>Range="loc,end"is unreliable once the editor touches the doc)<LockedPages>/<Paragraph Number="1A"><TagData>(production tagging)<SceneProperties>(colour, length, arc beats)<HeaderAndFooter>,<PageLayout>,<SmartType>,<Watermarking>,<Macros>,<Actors>,<CastList>, etc..fdr(legacy binary).fdxonlyNo new ProseMirror node types, no editor schema changes. Reuses
meta.extrafrom #185.Sub-issues
quick-xmldep) — TBDOut of scope (this feature)
Range="loc,end"anchors break the moment the editor touches the doc — better to drop loudly than preserve wrong)