Live Preview System
Relevant source files
The following files were used as context for generating this wiki page:
The Live Preview System in Writer is a real-time rendering engine that transforms Markdown text into a formatted visual representation. It allows users to see their changes instantaneously as they type in the editor, providing a distraction-free and professional editing experience.
The system relies on a combination of Apple's Markdown framework for Abstract Syntax Tree (AST) parsing and WebKit for displaying the rendered HTML output. It manages state via the Observation framework, ensuring that updates in the EditorStore are immediately reflected in the preview pane.
Sources: CLAUDE.md:19-21, Writer/WebView.swift:1-10
Architecture and Components
The architecture follows a modular approach where text processing, styling, and rendering are decoupled into specialized components.
Component Overview
| Component | Responsibility |
|---|---|
| EditorStore | Manages the raw markdown document text and triggers updates. |
| MarkdownRenderer | Converts markdown strings into HTML using a custom HTMLVisitor. |
| PreviewTheme | Provides CSS styles based on selected typography and color palettes. |
| WebView | A SwiftUI wrapper for WKWebView that displays the final document. |
| HTMLVisitor | A custom implementation of MarkupVisitor that traverses the Markdown AST. |
Sources: CLAUDE.md:23-42, Writer/MarkdownRenderer.swift:6-120, Writer/EditorStore.swift:23-40
System Data Flow
The flow of data starts with user input in the editor, which is synchronized to the EditorStore, processed into HTML, and finally displayed in the WebView.
The diagram shows how raw text and theme data converge in the renderer before being loaded into the web view.
Sources: Writer/WebView.swift:48-52, Writer/MarkdownRenderer.swift:145-160
Markdown Rendering Pipeline
The rendering pipeline is centered around the MarkdownRenderer and the HTMLVisitor. The system uses the Apple Markdown framework to parse the text into a Document structure.
HTML Generation Logic
The HTMLVisitor struct implements the MarkupVisitor protocol. It maps various markdown elements (headings, paragraphs, lists, tables, etc.) to their corresponding HTML tags.
- Standard Tags: Converts standard elements like
visitHeadingto<h>tags andvisitStrongto<strong>. - Custom Syntax: The
MarkdownRendererincludes a post-processing step to handle a custom==highlight==syntax, converting it into<mark class="highlight">tags using a cached regular expression. - Safety: The system escapes HTML entities in the raw markdown before parsing to prevent injection or rendering issues.
Sources: Writer/MarkdownRenderer.swift:17-104, Writer/MarkdownRenderer.swift:135-143, Writer/MarkdownRenderer.swift:163-174
Sequence of Rendering
The following sequence diagram illustrates the lifecycle of a preview update when the document text changes.
Styling and Themes
The visual appearance of the live preview is controlled by PreviewTheme. This structure defines the typography (fonts for body, headings, and code) and the color palette (background, text, links, and borders).
CSS Generation
The PreviewTheme generates a complete CSS stylesheet as a string via the cssStyles property. This stylesheet is injected into the <head> of the HTML document during the wrapping phase.
| Theme Property | Default (Sans Serif) |
|---|---|
bodyFontFamily | -apple-system, BlinkMacSystemFont, ... |
baseFontSize | 16px |
lineHeight | 1.6 |
backgroundColor | #ffffff |
textColor | #24292e |
Sources: Writer/PreviewTheme.swift:23-36, Writer/PreviewTheme.swift:60-149
Theme Selection UI
The WebView provides a floating menu (overlay) that allows users to switch between available themes, such as "Sans Serif" and "Serif". When a theme is selected, the ThemeStore is updated, which triggers a re-render of the WebView.
Sources: Writer/WebView.swift:12-32
Layout and Visibility
The live preview is integrated into the ContentView using an HSplitView. This allows the user to adjust the width of the preview pane relative to the editor.
- Visibility Toggle: Users can show or hide the preview using the "Show/Hide Preview" button or the
⌘Pshortcut. - State Management: The visibility is managed by
LayoutStore.showPreview. When hidden, thepreviewContainerframe is set to zero width and opacity. - Responsive Width: The editor pane is constrained to a maximum width (e.g., 800px) within its container to maintain readability, while the preview pane expands to fill the remaining split view space.
Sources: Writer/ContentView.swift:85-93, Writer/ContentView.swift:101-114, Writer/ContentView.swift:137-142
Summary
The Live Preview System provides a robust bridge between raw Markdown editing and high-fidelity HTML rendering. By combining a custom AST visitor with a CSS-driven theme engine, it ensures that the preview is both technically accurate and aesthetically consistent. The use of WKWebView further enables the same rendering pipeline to be reused for various export formats, such as PDF and HTML.
Sources: CLAUDE.md:29-37, Writer/WebView.swift:48-52