Skip to content

Parse SubRip line by line so empty lines are not dropped - #293

Merged
niksedk merged 1 commit into
mainfrom
claude/srt-parser-empty-lines
Sep 15, 2026
Merged

niksedk merged 1 commit into
mainfrom
claude/srt-parser-empty-lines

Conversation

@niksedk

@niksedk niksedk commented Sep 15, 2026

Copy link
Copy Markdown
Member

Problem

Subtitle Edit 5 writes a paragraph with no text as N / time / blank / blank (SubRip.ToText). SubRipParser.Parse split the SRT on blank lines and skipped blocks with fewer than 3 lines, so:

  • the empty paragraph became a 2-line block and was dropped, and
  • the next block started with an empty line, so its time line was at lines[2] instead of lines[1], and it was dropped too.

Plugins that parse and serialize the whole subtitle (RemoveUnicodeCharacters, WordCensor, AmericanToBritish, BritishToAmerican, TypewriterEffect) therefore deleted lines from the user's subtitle, and every SelectedIndices entry below the empty line was shifted. Example: ["Hello.", "", "- Andro!\n- Ben, I've been oozed.", "Last."] parsed to 2 blocks.

Fix

  • se5/Plugin-Shared/SubRipParser.cs: Parse is now line based. A block starts at a number line followed by a time code line (at the start or after a blank line); text lines accumulate until the next block start; trailing blank lines are trimmed. The time code pattern also accepts hours past 99 and a leading - for negative times, both of which SE writes and the old pattern dropped. Public API (SrtBlock, Parse, Serialize) is unchanged.
  • se5/TypewriterEffect/SubRipParser.cs: same fix in TypewriterEffect's own copy.
  • se5/Haxor/Program.cs: Haxor had its own blank-line split. Empty lines lined up by accident, but a line whose text contains a blank line split in two: selecting the line after it changed nothing, and selecting the line itself translated only its first half. It now walks the lines the same way; output is otherwise unchanged.

Verification

A scratch test project referencing SE's libse (SubRip.ToText / LoadSubtitle), run with CRLF and LF:

  • The example above: old parser 2 of 4 blocks, new parser 4 of 4. Serialize(Parse(srt)) is byte identical to SE's output, and editing index 2 changes only the dialog.
  • Empty first/last lines, consecutive empty lines, a blank line inside a paragraph, number-only text, whitespace-only text, times past 99 hours: both parsers match libse at every index, and libse reads the serialized result back identical. The old parser dropped blocks in 4 of these 6 cases.
  • A negative start time stays its own block (the old parser dropped it). Serialize still writes negative times as 0, as before.
  • Haxor: the built plugin run for every single-line selection and for all lines; libse reads back exactly the selected lines translated.
  • All six plugins build with no warnings.

After merge

Each affected plugin needs a release (workflow dispatch with release), then se5-plugins.json pointed at the new releases:

  • american-to-british.yml, british-to-american.yml, remove-unicode-characters.yml, word-censor.yml (Plugin-Shared)
  • typewriter.yml, haxor.yml (own changes)

SrtCueDocument on claude/split-dialogs could then use SubRipParser.Parse instead of its own reader.

🤖 Generated with Claude Code

Subtitle Edit writes a paragraph with no text as "N / time / blank / blank".
SubRipParser.Parse split on blank lines and skipped blocks under 3 lines, so
the empty paragraph was dropped along with the paragraph after it (its time
line landed at lines[2]). Plugins that parse and serialize the whole subtitle
deleted those lines, and every SelectedIndices entry below them was shifted.

Parse is now a line-based reader: a block starts at a number followed by a
time code line (at the start or after a blank line), text accumulates until
the next block start, and trailing blank lines are trimmed. The time code
pattern also accepts hours past 99 and negative times, both of which SE
writes and the old pattern dropped. The public API is unchanged.

TypewriterEffect's copy of the parser gets the same fix. Haxor had its own
blank-line split: a line whose text contained a blank line split in two and
shifted the selection, so it now walks lines the same way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@niksedk
niksedk merged commit c67ef87 into main Sep 15, 2026
57 checks passed
@niksedk
niksedk deleted the claude/srt-parser-empty-lines branch September 15, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant