Skip to content

Feature/highlight words - #164

Closed
erklu wants to merge 14 commits into
mainfrom
feature/highlight-words
Closed

erklu wants to merge 14 commits into
mainfrom
feature/highlight-words

Conversation

@erklu

@erklu erklu commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator

Highlights in the transcript editor

Refs #131 (the highlight half, for transcriptions; comments and subtitles come later)

Select text and press Ctrl + Shift + H, or use the Highlight button in the toolbar, to highlight it. Do it again to take the highlight off. A highlight is a note to self made while reviewing against the recording: it never changes the text.

Transcriptions only, for now. A set of subtitles is saved as plain SRT, which has nowhere to keep a highlight. In the subtitle editor the key is not bound, the shortcuts dialog does not list it and the export options are not offered. Extending it there needs a place to keep marks beside an SRT result (a backend question) and is left for later.

Behaviour

  • Whole words. A selection that takes any part of a word takes all of it, so a highlight never cuts a word in two and can follow the words through every edit. With nothing selected the word the caret is in (or against) is used; in the space between words there is nothing to highlight and a notice says so.
  • One key does both. When everything the selection takes is already highlighted the highlight comes off; otherwise everything gets one (a mixed selection becomes fully highlighted, a second press clears it). The selection is put back after the redraw, so the same key undoes what it just did.
  • Across paragraphs. A selection reaching over several paragraphs is one gesture and one undo step.
  • They follow the words. Through typing, split, merge, deleting across paragraphs, the one-word moves (Ctrl/⌘ + ↑/↓) and Find & Replace. Words that stay keep their highlight; a word corrected inside a highlighted stretch stays highlighted; a word typed between two highlighted words joins the highlight; any other new word does not earn one (typing a word is not highlighting it, unlike with My edits); removed words take theirs with them.
  • Saved with the transcription. Written as "highlighted" next to the existing "edited" in the segments, only when there are any, and read back on open (junk in the field is ignored). Files saved before this open exactly as before.
  • RTF export (two new checkboxes under RTF Options, unchecked by default and hidden when there is no mark of that kind in what is exported, bulk exports included): Include highlights writes them as \highlight1 (pure yellow, Word's own marker colour); Include my edits (underlined) writes the words the reader changed teal and underlined (underlined as well because a printout may have no colour). Both can be on, and a word can carry both. A clean export is byte-for-byte what it was (the colour table is only written when used); compared against main on 32 combinations of the existing options, with an emoji, odd whitespace, a trailing line break and an empty caption in the text. No other export format carries either.

Appearance

This does change how things look, so for review:

  • A highlighted word is drawn yellow with a 2 px line above and below. The lines are there on purpose: yellow on white is only 1.14:1, so colour cannot carry the marking alone (1.4.1, 1.4.11). The lines measure 4.9:1 against the page, the text on the yellow 13.6:1. Dark mode uses a dark gold: text 8.0:1, lines 12.6:1 against the surface.
  • No horizontal padding, unlike the other two markings, so highlighting does not move the text. The space between two highlighted words is highlighted too, so a passage reads as one stretch (not across a line break).
  • On a flagged or changed word the highlight takes the wash and the word keeps its own bar underneath, so both are visible. The word being played keeps its tint and the lines stay.
  • Exposed as role="mark"; no text is added to the paragraph.
  • A new "Highlight" button in the toolbar (a marker pen icon from Material Symbols Outlined, which ships with NiceGUI), quiet like the others, in the place where Validate sits in the subtitle editor (so transcriptions only). It does what the key does. It has a tooltip naming the key and aria-keyshortcuts. A mouse press on it does not take focus, so the selection it acts on is not lost (the same reason the caption row's music-note icon prevents the default on mousedown). One new tab stop in the toolbar; the tab order inside the text is unchanged.
  • A new "Highlighting" group in the transcription's shortcuts dialog; two new checkboxes in the RTF options when there is something to carry.

Implementation

  • utils/caption.py: SRTCaption.highlighted_words (copied, saved).
  • utils/srt_review.py: carry_highlights, words_in_selection, carry_marks, marked_spans, token_is_highlight; review_runs gives runs hl.
  • utils/srt.py: toggle_highlight (refuses for subtitles), restore in parse_txt, and every place that carries marks (split, merge, delete range, word moves, typing) now carries this set too. utils/srt_search.py: Replace uses carry_marks.
  • utils/srt_export.py: export_rtf(..., highlights, edits), the two checkboxes and rtf_marks_available().
  • utils/transcript_editor.js: runClass, highlightSpans, selectRange/pointAt, the key (Ctrl only, by event.code: Cmd+Shift+H is Home in the browser on a Mac; no Alt; not in subtitleMode). It sits ahead of the block-scoped lists because a selection can reach across paragraphs and those only see the caret's block.
  • utils/transcript_editor.py: toggle_highlight, highlight_selection (the button's half); highlightSelection() in the component; the button itself in pages/srt.py. utils/styles.py: the marking, in both themes. utils/srt_render.py: dialog group. AGENTS.md updated.

Notes

  • Typing at the very edge of a highlighted stretch can show the new word highlighted in the browser until the next redraw, while the server (correctly) has not given it one. The same kind of stand-in as the My edits marking while typing.
  • Existing tests that assumed one 'edit-word' literal in the template were updated for runClass, and the transcription's shortcut list for the new group.
  • Not in this PR: comments (the other half of Feature Request: Highlights and Comments in Transcript Editor #131), and highlights or My edits kept for subtitles.

Not yet verified

Logic, saving, RTF text and the component source are covered by tests. Tried by hand (by the author of the issue, in the dev environment): highlighting with the key and with the toolbar button, and exporting to RTF and opening it in Word, where the highlights come out yellow and the changed words teal and underlined. The RTF also opens and shows as intended in LibreOffice. Dark mode looked at in a screenshot from the dev environment: the dark-gold wash with the yellow lines reads clearly and apart from the teal changed words. The word being played over a highlight looked at too (dark mode, screenshot): the playing word has its blue tint and the highlight's lines run on above and below it. Not yet checked: any screen reader.

Tests

tests/test_highlights.py (word selection, carrying through every kind of edit, toggling, saving and reopening, drawing, RTF and when it is offered, the handler, the component source, the styles, subtitles refused). Full suite: 1125 passed, 3 failed: the 3 pre-existing failures on main (TestAddingACaptionForSpeech).

erklu and others added 14 commits October 18, 2026 07:44
#131)

Select text and press Ctrl+Shift+H, or use the Highlight button in the
toolbar, to highlight it; do it again to take the highlight off. A note
to self made while reviewing against the recording -- it never changes
the text.

- Anchored to whole words (SRTCaption.highlighted_words), kept apart from
  the "my edits" marks. carry_highlights() moves them with the words
  through typing, split, merge, delete across captions, word moves and
  Find & Replace; a word typed between two highlighted words joins the
  highlight, any other new word does not earn one.
- Saved with the transcription ("highlighted" next to "edited").
  Transcriptions only for now: a set of subtitles is plain SRT and has
  nowhere to keep them.
- Drawn yellow with a line above and below so colour is not the only cue
  (1.4.1, 1.4.11), role="mark", distinguishable from flagged words, my
  edits and the word being played, in both themes.
- RTF export can carry highlights and changed words; the options are
  unchecked by default and only shown when there is something to carry
  (a clean export is unchanged).
- Shortcuts dialog gets a "Highlighting" group for transcriptions.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
The plain Material Icons "highlight" is a torch. The marker pen is in
Material Symbols Outlined, which ships with NiceGUI (checked: the
ligature is in the bundled font).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
…s bar outside it

A highlighted word that was also flagged (or changed) had its frame's lower
line replaced by the word's own bar, so it read as a flagged word on a yellow
wash and was hard to tell from a plain highlight. The frame (a line above and
below) is now the same on every highlighted word, and the word's own bar is
drawn outside it, 3px below, as a box-shadow with no inset so it takes no room.
Rendered with the editor's line height (1.6) the bar clears the next line.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
carry_highlights marks it on the server, but set_text does not re-render the
block being typed into, so the word stood there plain in the middle of a
highlighted passage until the page was reloaded. highlightNewWord() applies
the server's rule in the DOM, for a new word only and only when the nearest
word on each side is highlighted, with an attribute (Vue owns the class) that
the next render drops. Reproduced and checked in jsdom against the real
component, and the computed styles checked in Chromium.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
…t-words

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
…hat is hidden

A per-user preference beside My edits (transcriptions only, default on).
Hidden highlights are not drawn and not read out, but stay in the data and
follow the text through every edit. The highlight command, while they are
hidden, turns the display on and adds to words lacking a highlight, never
removes, and says why in a toast.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
Hiding highlights is a way of looking at the text for a while, not a
preference, and a hidden highlight forgotten for days is worse than switching
them off again. Every editor now opens with them shown.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCjpD3ehigLiUGH1oVQQAW
@erklu

erklu commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator Author

Closing this PR: all of its commits are already in develop, so it will reach main with the develop → main release PR. No changes are lost, and the branch is kept.

@erklu erklu closed this Oct 21, 2026
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.

2 participants