Feat/markdown anchor sync plan#216
Merged
saeedvaziry merged 81 commits intomuxy-app:mainfrom Apr 25, 2026
Merged
Conversation
- Add MarkdownTabState and MarkdownTabView for markdown file handling - Add Mermaid diagram rendering with native and JS fallback support - Add EditorMarkdownViewMode for code/preview/split views - Add markdown file detection and auto-preview mode - Add comprehensive Mermaid normalizer tests
… into feat/markdown-renderer-pr
… into feat/markdown-renderer-pr
Contributor
Author
|
Closes #196 |
…/muxy into feat/markdown-anchor-sync-plan
…sync-plan # Conflicts: # Muxy/Views/Editor/EditorPane.swift
There was a problem hiding this comment.
Pull request overview
Adds a Markdown viewing experience to Muxy tabs (preview/code/split), including Mermaid diagram rendering and anchor-based scroll syncing between the editor and preview.
Changes:
- Introduces a Markdown renderer (Marked + Highlight.js) with Mermaid.js diagram support and DOM sanitization.
- Implements anchor parsing + editor/preview coordination to sync scroll positions in split view.
- Updates the editor UI/state to support Markdown view modes and scroll-sync controls, with accompanying unit tests.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/MuxyTests/Models/ViewportStateTests.swift | Updates expectations for document height now that padding is included. |
| Tests/MuxyTests/Models/MermaidCodeBlockNormalizerTests.swift | Adds tests for Mermaid code block normalization and HTML template contracts. |
| Tests/MuxyTests/Models/MarkdownSyncCoordinatorTests.swift | Adds tests for editor↔preview sync and relayout behavior. |
| Tests/MuxyTests/Models/MarkdownEditorAnchorMapperTests.swift | Adds tests for mapping editor scroll position to an active anchor/progress snapshot. |
| Tests/MuxyTests/Models/MarkdownAnchorParserTests.swift | Adds tests for parsing Markdown into stable, inclusive anchor ranges. |
| Tests/MuxyTests/Models/EditorTabStateTests.swift | Ensures Markdown tabs default to preview mode with scroll sync enabled. |
| Muxy/Views/Markdown/MarkdownTabView.swift | Adds WKWebView-based Markdown preview plumbing, scroll observation, and sync-point reporting. |
| Muxy/Views/Markdown/MarkdownPreviewAnchorGeometryBridge.swift | Adds JS bridge to measure DOM anchor geometry and report it to Swift for more accurate sync. |
| Muxy/Views/Editor/EditorPane.swift | Adds Markdown view mode switching (code/preview/split) and integrates preview into the editor pane. |
| Muxy/Views/Editor/CodeEditorRepresentable.swift | Adds editor-side anchor snapshotting + scroll metric publishing and drives preview refresh/sync. |
| Muxy/Models/ViewportState.swift | Adjusts line height calculation and includes document vertical padding in total height. |
| Muxy/Models/MermaidCodeBlockNormalizer.swift | Normalizes Mermaid labels by converting in-label newlines to <br/>. |
| Muxy/Models/MarkdownSyncCoordinator.swift | Coordinates which side is the scroll driver and suppresses echo updates. |
| Muxy/Models/MarkdownSyncAnchor.swift | Defines anchor kinds and the anchor model used for syncing. |
| Muxy/Models/MarkdownRenderer.swift | Provides the HTML/JS/CSS template for Markdown rendering, sanitization, and Mermaid rendering. |
| Muxy/Models/MarkdownPreviewAnchorGeometry.swift | Adds a model for preview DOM anchor geometry snapshots. |
| Muxy/Models/MarkdownEditorAnchorSyncSnapshot.swift | Adds a model representing the editor’s active anchor + local progress. |
| Muxy/Models/MarkdownEditorAnchorMapper.swift | Implements logic to choose an active anchor and compute progress for a focused editor line. |
| Muxy/Models/MarkdownAnchorParser.swift | Implements a Swift-side Markdown block parser for building sync anchors. |
| Muxy/Models/EditorTabState.swift | Adds Markdown state (view mode, scroll sync, driver tracking, caches) to editor tabs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <title>\(title)</title> | ||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" integrity="sha512-..." crossorigin="anonymous"></script> |
Comment on lines
+559
to
+563
| guard message.name == MarkdownWebBridge.scrollHandlerName, | ||
| scrollSyncEnabled, | ||
| !isNavigationInFlight, | ||
| let payload = message.body as? [String: Any], | ||
| let scrollTopNumber = payload["scrollTop"] as? NSNumber |
Comment on lines
+302
to
+306
| const root = document.documentElement; | ||
| if (!root) return; | ||
| root.classList.toggle('muxy-hide-content-scrollbar', \( | ||
| hideScrollbar | ||
| )); |
Comment on lines
+293
to
+294
| textView.setSelectedRange(NSRange(location: 0, length: 0)) | ||
| textView.scrollRangeToVisible(NSRange(location: 0, length: 0)) |
| } | ||
|
|
||
| func previewDidRelayout() -> Output { | ||
| Output() |
|
|
||
| guard abs(targetY - currentY) > 0.1 else { return } | ||
|
|
||
| markdownScrollDriver = .editor |
Comment on lines
+68
to
+72
| if bracketDepth > 0, | ||
| ch.isNewline | ||
| { | ||
| output.append("<br/>") | ||
| cursor = next |
Comment on lines
+71
to
+77
| let markdown = """ | ||
| ```mermaid | ||
| graph TD | ||
| A[Hello\\nWorld] --> B | ||
| ``` | ||
| """ | ||
|
|
Comment on lines
+97
to
+101
| let markdown = """ | ||
| # Title | ||
|
|
||
| Paragraph | ||
|
|
Comment on lines
+12
to
+17
| let line = lines[index] | ||
| let trimmed = line.trimmingCharacters(in: .whitespaces) | ||
|
|
||
| if trimmed.isEmpty { | ||
| index += 1 | ||
| continue |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Changes
Added markdown (full, split, code view).
Added initial mermaid.js support for diagram rendering.
Anchor scroll sync for more accurate scrolling
How to use:
cmd + P => open a .md file and 🪄
Testing
scripts/checks.shpassesScreenshots