Skip to content

fix: prevent non-markdown files from rendering in md viewer#2791

Merged
abose merged 13 commits intomainfrom
ai
Apr 5, 2026
Merged

fix: prevent non-markdown files from rendering in md viewer#2791
abose merged 13 commits intomainfrom
ai

Conversation

@abose
Copy link
Copy Markdown
Member

@abose abose commented Apr 5, 2026

Guard _loadMdviewrPreview to check that the current document is actually a markdown file before activating MarkdownSync. Fixes race where async getPreviewDetails returns stale markdown details but the editor has already switched to a binary/json file, causing its content to be rendered as markdown.

Add tests verifying: binary/json files don't render in md viewer, last md preview stays visible for non-previewable files, and md preview resumes correctly when switching back to md.

abose added 7 commits April 5, 2026 08:20
Guard _loadMdviewrPreview to check that the current document is
actually a markdown file before activating MarkdownSync. Fixes race
where async getPreviewDetails returns stale markdown details but
the editor has already switched to a binary/json file, causing
its content to be rendered as markdown.

Add tests verifying: binary/json files don't render in md viewer,
last md preview stays visible for non-previewable files, and md
preview resumes correctly when switching back to md.
Set spellcheck=false, autocorrect=off, autocapitalize=off on
viewer-content when entering edit mode to prevent browser squiggly
underlines on contenteditable text.
Add CSP meta tag to md viewer iframe HTML:
- script-src 'self': blocks inline scripts and external script URLs
  from markdown content, only allows the bundled mdviewer JS
- connect-src 'self': blocks fetch/XHR to external URLs, preventing
  data exfiltration even if a script somehow executes
- img-src allows external URLs (needed for markdown images)
- style-src allows self + unsafe-inline (needed for element positioning)

Combined with the existing iframe sandbox (no allow-same-origin),
this provides defense-in-depth against malicious markdown content.
Add allow-clipboard-read/write sandbox flags and permissions policy
on the md viewer iframe for Chromium context menu paste support.
Hide paste menu items on browsers where Clipboard API is blocked
(Safari/Firefox sandboxed iframes). Add cut/copy/paste items to
the table right-click context menu.
- Fix code block editing: normalize <br> → \n before Prism re-highlights
  to prevent newline collapse in contenteditable code blocks
- Re-enable _annotateCodeBlockLines for per-line cursor sync in code blocks
- Add _updateSourceLineAttrs to recompute data-source-line after edits
  using CM's actual text (via MDVIEWR_SOURCE_LINES message) for accuracy
- Fix stale annotation detection: re-annotate when line numbers drift
- Fix <br> paragraph cursor sync: count <br> before cursor in
  _getSourceLineFromElement for exact CM line within soft-break paragraphs
- Move \n to end of line spans (not start) so blank lines are clickable
- Fix scroll jump when clicking in code blocks: remove data-source-line
  from <pre> in early-return path of _annotateCodeBlockLines
- Fix scroll-to-top on click in edit mode: block fromScroll sync from CM
  to prevent feedback loop (click → CM scroll → scroll sync back → jump)
- Add per-line highlight for <br> paragraphs: wrap specific line content
  in cursor-sync-highlight span instead of highlighting whole <p>
- Track _lastHighlightTargetLine for accurate re-apply after re-renders
- Fix _getSourceLineFromElement to count <br> before cursor for exact line
- Lang-picker: reposition upward when dropdown clipped at bottom
- Lang-picker: fix blur with transform:none when visible
- Fix cursor jumping to previous line after applying heading format on
  empty lines: place cursor inside the newly created block element
- Block CM scroll-to-line when viewer has focus in edit mode to prevent
  highlight span creation from displacing the cursor
// causing line number drift if used directly.
const iframeWindow = _getIframeWindow();
if (iframeWindow && _doc) {
iframeWindow.postMessage({
abose added 6 commits April 5, 2026 14:51
Remove _annotateCodeBlockLines entirely — per-line cursor sync in code
blocks now uses \n counting at click time (same approach as <br> in
paragraphs). This eliminates DOM mutation of code block content, avoids
Prism re-highlight conflicts, and simplifies the codebase.

- bridge.js: count \n before cursor in _getSourceLineFromElement for PRE
- bridge.js: add positioned overlay div for per-line code block highlight
- bridge.js: simplify _reapplyCursorSyncHighlight to reuse handleScrollToLine
- bridge.js: temporary marker span for scroll-to-line in code blocks
- editor.js: remove _annotateCodeBlockLines import and calls
- viewer.js: delete _annotateCodeBlockLines function (~110 lines removed)
- Use >= instead of > in data-source-line search so child elements (li)
  override their parent containers (ul/ol) with the same line number
- Force light theme in md viewer for paper-like appearance regardless of
  editor theme (infrastructure preserved for future dark mode support)
…croll

- Fix CM→viewer scroll sync in edit mode: use _scrollFromViewer flag to
  block only feedback loops, not all scroll-based sync
- Skip highlight (not scroll) when viewer has focus to prevent cursor
  displacement while still allowing scroll restoration
- Prevent theme reflow on reload by skipping if already applied
- Hide lang-picker on scroll
- Fix scroll position not restored after reload: send MDVIEWR_SOURCE_LINES
  only after edit-mode content changes, not during initial load/reload
  where it would cause reflows that reset scroll position
- Force light theme via no-op handleSetTheme (HTML default is light)
- Hide format bar when selection is inside code blocks
- Add beforeEach cleanup in Document Cache test suite to prevent state
  leakage between scroll position tests
- Fix task list checkbox styling: use li:has(> input[checkbox]) instead
  of missing task-list-item class (marked v17 doesn't add it)
- Hide bullet points on task list items, add min-height for empty items
- Hide format bar when selection is inside code blocks
- Prevent cursor from being placed before checkbox in task list items
- Backspace after checkbox removes it, converting to regular bullet
Suppress handleScrollToLine for 500ms after file switch to prevent CM
cursor activity from overriding the doc cache's restored scroll position.
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 5, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
D Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@abose abose merged commit 51c7be4 into main Apr 5, 2026
13 of 21 checks passed
@abose abose deleted the ai branch April 5, 2026 16:36
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