RTF Export Feature
Relevant source files
The following files were used as context for generating this wiki page:
The RTF Export feature in the Writer application provides users with the ability to convert Markdown documents into Rich Text Format (RTF) files. This feature bridges the gap between distraction-free Markdown editing and traditional word processing environments by leveraging a multi-stage conversion pipeline that transforms Markdown to HTML, then to NSAttributedString, and finally to RTF data.
The feature is integrated directly into the macOS menu bar and is designed to preserve the visual styling defined by the user's selected PreviewTheme.
Sources: Writer/RTFExporter.swift:7-11, CLAUDE.md:46
Architectural Overview
The export process follows a specific data transformation pipeline. Unlike direct Markdown-to-RTF conversion, the system utilizes the existing MarkdownRenderer to generate an intermediate HTML representation. This ensures that the exported document maintains consistency with the live preview seen within the application.
Data Flow Transformation
- Markdown Input: The raw string from the
EditorStore. - HTML Generation:
MarkdownRendererconverts Markdown to HTML body content and wraps it in a full document with theme-specific CSS. - Attributed String Conversion: The HTML is parsed into an
NSAttributedStringusing AppKit's document reading options. - RTF Encoding: The attributed string is encoded into RTF data using the standard
rtf(from:documentAttributes:)method.
The following diagram illustrates the sequence of operations when a user triggers an RTF export:
Core Components
RTFExporter Utility
The RTFExporter is a @MainActor constrained struct responsible for managing the export lifecycle. It handles the UI interaction for file naming and location selection via NSSavePanel, as well as the technical conversion from strings to file data.
| Component | Description | Source |
|---|---|---|
markdown | The source Markdown text to be converted. | RTFExporter.swift:11 |
theme | The PreviewTheme providing CSS styles for the intermediate HTML. | RTFExporter.swift:12 |
save(suggestedName:) | Primary entry point that displays the save panel and executes the pipeline. | RTFExporter.swift:16 |
htmlToAttributedString(_:) | Private helper that uses NSAttributedString.DocumentType.html for parsing. | RTFExporter.swift:53 |
Integration with MarkdownRenderer
The export feature heavily relies on the MarkdownRenderer and its HTMLVisitor to parse the Markdown Abstract Syntax Tree (AST). This visitor converts various Markdown elements (headings, strong text, emphasis, code blocks, etc.) into their corresponding HTML tags.
Implementation Details
Intermediate HTML Generation
The RTF export utilizes the same rendering logic as the live preview and HTML export. It calls MarkdownRenderer.renderBodyContent(_:) to generate the core content and MarkdownRenderer.wrapInHTMLDocument(_:theme:) to inject CSS styles derived from the PreviewTheme.
// From Writer/RTFExporter.swift:17-18
let bodyContent = MarkdownRenderer.renderBodyContent(markdown)
let html = MarkdownRenderer.wrapInHTMLDocument(bodyContent, theme: theme)
Sources: Writer/RTFExporter.swift:17-18, Writer/MarkdownRenderer.swift:169-181
Conversion and Error Handling
The conversion to NSAttributedString is critical for RTF generation. The system uses a documentType of .html to ensure that the CSS styles provided by the theme are interpreted correctly before being serialized into RTF format.
The system defines specific errors via the ExportError enum (shared with the HTML exporter) to handle user cancellations or filesystem write failures.
| Error Case | Meaning |
|---|---|
.cancelled | User closed the NSSavePanel without selecting a location. |
.writeFailed(Error) | The system could not convert the HTML or write the data to the target URL. |
Sources: Writer/RTFExporter.swift:29-45, Writer/HTMLExporter.swift:37-48
User Access and Interaction
The RTF Export feature is exposed to the user through the File menu and a global keyboard shortcut.
- Menu Item: File > Export to RTF
- Shortcut:
Command + Shift + R(⌘⇧R) - State Dependency: The menu item is disabled if no file is selected or if the current document text is empty.
Sources: Writer/WriterApp.swift:54-68, Writer/WriterApp.swift:123-126, CLAUDE.md:46
Conclusion
The RTF Export Feature is a specialized implementation of the project's broader rendering architecture. By piping Markdown through an HTML stage, it ensures that exported Rich Text documents accurately reflect the stylistic choices defined in the application's themes while maintaining compatibility with standard word processors.