Skip to content

feat(editor): add live markdown preview while typing - #1757

Open
Th-Underscore wants to merge 16 commits into
SableClient:feat/prosemirror-composerfrom
Th-Underscore:feat/markdown-preview-prosemirror
Open

feat(editor): add live markdown preview while typing#1757
Th-Underscore wants to merge 16 commits into
SableClient:feat/prosemirror-composerfrom
Th-Underscore:feat/markdown-preview-prosemirror

Conversation

@Th-Underscore

Copy link
Copy Markdown

Based on ProseMirror refactor #1724. See Th-Underscore/Sable@e89b1b8...2e8f26f for the proper changes list.

Description

Adds a live markdown preview to the ProseMirror composer. Formatting renders inline while you type (bold/italic/underline/strikethrough/spoiler/code/link, multi-line code blocks, and per-level headings) in a Discord-style way. The markdown syntax characters stay visible but dimmed, and the styled content keeps its formatting. Fenced code blocks are highlighted with Sable's own syntax highlighter, so the preview colours match sent messages. Bare URLs are styled as links and open on Ctrl/Cmd+click; a plain click never navigates. Backslash escapes are honoured (e.g. test\*beep\* stays literal).

An opt-in "Show Markdown Preview" setting (default off, in General > Editor) additionally renders a preview box above the composer through the normal timeline renderer. Purely cosmetic. Preview links respect the existing "Underline Links" setting.

Two extras:

  • markEventConsumedByHost: a workaround for a bug in feat(editor): replace Slate with ProseMirror in the composer #1724's own composer (Enter can't insert a newline)
  • RoomTimeline: viewport-repin fix - the timeline rubber-bands to the bottom while the user scrolls up and the composer grows (the markdown decorations make this much more noticeable)

Tested on the desktop app, Ubuntu 24.04.

image

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation - .changeset
  • My changes generate no new warnings

AI disclosure:

  • Partially AI assisted (clarify which code was AI assisted and briefly explain what it does).
  • Fully AI generated (explain what all the generated code does in moderate detail).

I designed and directed the feature, chose the Discord-style behaviors, and tested it in the GUI, while the code itself was largely AI-generated.

Not WYSIWYG - explicitly preserves markdown format markers. The composer preview is a ProseMirror decoration plugin over a markdown tokenizer; it styles content at render time without touching the document, so serialized output is unchanged. Code blocks reuse Sable's existing arborium highlighting, matching sent messages. Nested format markers are recursed for stacked fonts/format types.

@Th-Underscore

Th-Underscore commented Aug 13, 2026

Copy link
Copy Markdown
Author

There is some slight inconsistency when newlines are introduced within inline marker types, but generally a nonissue (even Discord has such problems):

image The preview box above is how it is actually sent.

@eleboucher
eleboucher changed the base branch from dev to feat/prosemirror-composer August 13, 2026 08:16
@eleboucher
eleboucher force-pushed the feat/prosemirror-composer branch 7 times, most recently from a754be6 to 9a54e8c Compare August 13, 2026 16:06
@eleboucher
eleboucher force-pushed the feat/prosemirror-composer branch from 9a54e8c to 7b107f2 Compare August 13, 2026 18:01
Stack overlapping inline formatting so inner spans keep the outer marks,
render spoilers as a translucent highlight, show atoms in the preview text,
and cap the preview box height with its own scrollbar.
…r growth

The atBottom flag lags real scroll position by up to 100px, so a user who
has started scrolling up is still flagged while a growing composer shrinks
the timeline viewport. Gate the viewport ResizeObserver repin on the actual
distance to the pre-resize bottom instead of the lagging flag.
Style fenced code with arborium's real token elements, keep backslash
escaped delimiters literal, scale heading levels (# to ###### onto folds'
H2 to H6) at weight 600 with real bold inside, and underline preview links
only when the underline-links setting is on.
@Th-Underscore
Th-Underscore force-pushed the feat/markdown-preview-prosemirror branch from 64fa3d0 to 82f12c1 Compare August 14, 2026 12:17
@eleboucher
eleboucher force-pushed the feat/prosemirror-composer branch from 7b107f2 to 03ad55f Compare August 16, 2026 10:20
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