HTML Export Feature
Relevant source files
The following files were used as context for generating this wiki page:
The HTML Export Feature in the Writer application allows users to transform Markdown documents into standalone, styled HTML files. This system leverages a custom rendering pipeline that converts Markdown Abstract Syntax Tree (AST) nodes into HTML elements, applying inline CSS based on the user's selected preview theme.
The feature is integrated directly into the macOS menu bar and keyboard shortcuts, providing a seamless transition from editing to distribution. It shares the same underlying rendering logic as the live preview pane, ensuring consistency between what the user sees in the editor and the final exported file.
Sources: CLAUDE.md:15-28, WriterApp.swift:108-112, HTMLExporter.swift:8-12
Core Architecture and Rendering Pipeline
The export process follows a structured pipeline: parsing the raw Markdown, visiting the resulting nodes to generate HTML strings, and wrapping that content in a full HTML document template containing CSS styles.
The Rendering Pipeline Flow
This diagram illustrates the data flow from raw Markdown text to a saved HTML file.
The pipeline utilizes Apple's Markdown framework for initial parsing and a custom HTMLVisitor for string generation.
Sources: MarkdownRenderer.swift:144-160, HTMLExporter.swift:14-17
Components and Responsibilities
| Component | Responsibility |
|---|---|
HTMLExporter | Orchestrates the export process, manages the NSSavePanel, and writes the file to disk. |
MarkdownRenderer | High-level static utility that coordinates body rendering and HTML document wrapping. |
HTMLVisitor | A MarkupVisitor implementation that traverses the Markdown AST to generate HTML tags. |
PreviewTheme | Provides the CSS styles injected into the <style> block of the exported document. |
Sources: HTMLExporter.swift:8-18, MarkdownRenderer.swift:7-142, PreviewTheme.swift:63-145
Implementation Details
HTML Generation Logic
The conversion of Markdown to HTML is handled by the HTMLVisitor. It maps specific Markdown elements to their corresponding HTML tags.
- Standard Elements: Paragraphs (
<p>), Headings (<h1>-<h6>), Emphasis (<em>), and Strong (<strong>). - Lists and Tables: Supports both ordered/unordered lists and complex table structures (
<table>,<thead>,<tbody>). - Code: Inline code is wrapped in
<code>while block code uses<pre><code class="language-...">. - Custom Syntax: The renderer includes a post-processing step to support
==highlight==syntax, converting it to<mark class="highlight">using a regular expression.
Sources: MarkdownRenderer.swift:18-120, MarkdownRenderer.swift:174-185
Theme Integration
The exported HTML is "standalone," meaning it does not rely on external stylesheets. The PreviewTheme struct contains a cssStyles computed property that generates a comprehensive CSS string. This string includes styling for:
- Typography (font families, sizes, line heights)
- Colors (background, text, links, borders)
- Element-specific spacing (margins for paragraphs, padding for code blocks)
Sources: PreviewTheme.swift:64-145, MarkdownRenderer.swift:163-172
Export Execution
The export is triggered from the WriterApp via the exportToHTML() function. This function initializes the HTMLExporter with the current document text and active theme.
// From Writer/WriterApp.swift:19-35
private func exportToHTML() {
let exporter = HTMLExporter(
markdown: editorStore.documentText, theme: themeStore.previewTheme)
let suggestedName = (editorStore.selectedFileURL?.deletingPathExtension().lastPathComponent ?? "document") + ".html"
Task {
do {
let url = try await exporter.save(suggestedName: suggestedName)
exportSuccess = url.path
} catch let error as any Error where (error as NSError).code != NSUserCancelledError {
exportError = error.localizedDescription
}
}
}
Sources: WriterApp.swift:19-35, HTMLExporter.swift:21-41
Interaction Sequence
The following sequence diagram shows the interaction between the App, the Exporter, and the User during an export operation.
Conclusion
The HTML Export Feature serves as a bridge between the internal Markdown state and standard web formats. By sharing the MarkdownRenderer and PreviewTheme with the WebView used for live previews, the system ensures high fidelity between the editing experience and the final output. The use of Apple's Markdown framework and a visitor pattern provides a robust and extensible foundation for future document transformations.