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
Part of #184 (Fountain import). Spec findings posted in the umbrella's research comment — read that first.
What
Update src-tauri/src/screenplay/fountain.rs so that data preserved during import (synopses, sections, inline notes, meta.extra) is re-emitted on export, AND apply the forcing rules required to keep round-trip lossless against Fountain's parsing precedence.
Forcing rules (critical — without these, round-trip silently corrupts)
Fountain's auto-detection misreads stored elements unless we preemptively force them:
Character — must @-prefix when the name:
contains any Malayalam, Tamil, Devanagari, or other caseless-script character (caseless scripts can't satisfy the all-caps rule)
contains any lowercase Latin letter (e.g. iPhone Voice, Mary)
is otherwise not all-uppercase Latin (digits + parens + spaces are fine, but bare digits aren't valid)
Action — must !-prefix when the line:
is entirely uppercase Latin and would auto-detect as a Character (caps + alpha + non-empty next line)
is entirely uppercase Latin and ends in TO: (would auto-detect as a Transition)
begins with INT, EXT, EST, INT./EXT, INT/EXT, or I/E (would auto-detect as a Scene Heading)
Scene Heading — must .-prefix when the heading text doesn't begin with a recognised slug prefix (INT, EXT, EST, INT./EXT, INT/EXT, I/E). Common case: Malayalam scene slugs.
Transition — must >-prefix when the transition text isn't all-caps Latin ending in TO:. Includes any Malayalam transition.
Implement once as a force_prefix_for(node, text) helper used by every emitter.
Element emission
Source
Emitted as
meta.extra map
Title-page keys at top of file, sorted (BTreeMap key order). Original key spelling preserved.
scene_cards[i].description
= description synopsis line(s) directly after scene i's heading. Multi-line descriptions → multiple = lines.
# ... / ## ... / etc. emitted before scene i's heading, stripping the marker.
scene_cards[i].notes lines without a section marker
[[ ... ]] inline note inserted at the end of scene i's last action block (positional approximation — original anchor was lost on import)
Boneyard is never emitted (dropped on import).
Dual dialogue is never emitted (collapsed on import).
Custom scene numbers are not emitted (Scriptty auto-numbers).
Emphasis markers are not emitted (stripped on import — v1 data loss).
Whitespace gotchas
Two-space-trailing convention in dialogue: when emitting a multi-paragraph dialogue block, separate paragraphs with a (two-space) line, not a fully blank line. Otherwise the next reader will end the dialogue block.
Use \n line endings (LF), not CRLF.
Don't trim trailing whitespace blindly — let the emitter own which lines need the two-space convention.
Considerations / heads-up for the PR
The section-depth marker syntax ([[#section depth=N]] ...) is internal — choose something unlikely to collide with real user notes. Document the convention in SCREENPLAY_FORMAT.md.
Synopses currently exist as a scene_cards.description field that users also edit by hand — this issue means user-authored descriptions also get emitted as Fountain synopses. That's the right behavior (Fountain readers will show them in outline mode), but worth calling out: scene card descriptions become semi-public on Fountain export. Mention prominently in the Export modal copy.
If a user adds a scene_cards[i].notes entry by hand it'll be emitted as an inline note at scene end. Existing export behavior changes for non-imported files too — call this out in the PR description.
Part of #184 (Fountain import). Spec findings posted in the umbrella's research comment — read that first.
What
Update
src-tauri/src/screenplay/fountain.rsso that data preserved during import (synopses, sections, inline notes,meta.extra) is re-emitted on export, AND apply the forcing rules required to keep round-trip lossless against Fountain's parsing precedence.Forcing rules (critical — without these, round-trip silently corrupts)
Fountain's auto-detection misreads stored elements unless we preemptively force them:
@-prefix when the name:iPhone Voice,Mary)!-prefix when the line:TO:(would auto-detect as a Transition)INT,EXT,EST,INT./EXT,INT/EXT, orI/E(would auto-detect as a Scene Heading).-prefix when the heading text doesn't begin with a recognised slug prefix (INT,EXT,EST,INT./EXT,INT/EXT,I/E). Common case: Malayalam scene slugs.>-prefix when the transition text isn't all-caps Latin ending inTO:. Includes any Malayalam transition.Implement once as a
force_prefix_for(node, text)helper used by every emitter.Element emission
meta.extramapscene_cards[i].description= descriptionsynopsis line(s) directly after scenei's heading. Multi-line descriptions → multiple=lines.scene_cards[i].noteslines prefixed[[#section depth=N]] ...# .../## .../ etc. emitted before scenei's heading, stripping the marker.scene_cards[i].noteslines without a section marker[[ ... ]]inline note inserted at the end of scenei's last action block (positional approximation — original anchor was lost on import)Boneyard is never emitted (dropped on import).
Dual dialogue is never emitted (collapsed on import).
Custom scene numbers are not emitted (Scriptty auto-numbers).
Emphasis markers are not emitted (stripped on import — v1 data loss).
Whitespace gotchas
(two-space) line, not a fully blank line. Otherwise the next reader will end the dialogue block.\nline endings (LF), not CRLF.Considerations / heads-up for the PR
[[#section depth=N]] ...) is internal — choose something unlikely to collide with real user notes. Document the convention inSCREENPLAY_FORMAT.md.scene_cards.descriptionfield that users also edit by hand — this issue means user-authored descriptions also get emitted as Fountain synopses. That's the right behavior (Fountain readers will show them in outline mode), but worth calling out: scene card descriptions become semi-public on Fountain export. Mention prominently in the Export modal copy.scene_cards[i].notesentry by hand it'll be emitted as an inline note at scene end. Existing export behavior changes for non-imported files too — call this out in the PR description.Test plan
import → export → import → exportmust reach a fixed point after one full round.രമേശ്) →@രമേശ്on exportiPhone Voice) →@iPhone VoiceBANG!→!BANG!HE WALKS UP TO:→!HE WALKS UP TO:INT.MISLEADING→!INT.MISLEADINGഅകത്ത്. വീട് - രാത്രി→.അകത്ത്. വീട് - രാത്രി>prefix