# Markdown Viewer Features: Live Markdown Preview, Diagrams, Export, and Sharing This page is the source-of-truth feature reference for Markdown Viewer. It describes what the app does, how each feature behaves for users, the implementation limits that matter in practice, and what happens to document data. ## Product Summary Markdown Viewer is a browser-based Markdown editor and viewer for opening `.md` and `.markdown` files, writing plain Markdown, and reading a live GitHub-style Preview. It runs as a static web application, a Progressive Web App, a Docker-hosted static site, and a Neutralino desktop application. The Editor is built around a plain textarea, a rendered Preview pane in Split view with sync scrolling, Document tabs, import/export tools, sharing tools, rich Markdown renderers, and optional Cloudflare endpoints for Share Snapshot and Live Share. Most work happens in the browser or desktop webview. Markdown parsing, syntax highlighting, math rendering, diagram post-processing, PDF/PNG capture, tab storage, undo/redo, search, and formatting tools are client-side. The exceptions are explicit network features: GitHub import, emoji lookup, CDN library loading in the web build, remote diagram fallback services, large Share Snapshot storage, and Live Share relay rooms. ## Main Workspace The app opens with a header, Files sidebar, document tab bar, formatting toolbar, editor pane, resize divider, preview pane, and bottom status bar. - The left **Files** sidebar organizes Markdown files into fixed **Workspace** and **Secret Workspace** roots with nested folders, All files, Recent, Favorites, and search views. - The sidebar is resizable and collapsible on desktop, narrower on tablet, and becomes a full-height drawer on mobile. - Editor mode shows only the textarea. - Split view shows the Editor and Preview side by side. - Preview mode shows only the rendered document. - A file menu can open a second document beside the active document. A shared control switches both sides between Edit and Preview, and synchronized scrolling is optional. - On small screens, the mobile menu exposes the same core actions and the layout avoids a cramped split view. - A draggable divider resizes the Editor and Preview in Split view and keeps both panes above 20% width. - The divider also supports keyboard adjustment with left and right arrow keys while split view is active. - The GitHub link in the header opens the source repository. - The bottom status bar centers reading time, word count, and character count, while its right edge reports Saving or All changes saved. The editor includes line numbers, wrapped-line height handling, a highlight layer for find results, live cursor overlays during Live Share, and skeleton placeholders during initial or heavy rendering. Line-number calculations are cached so large documents do not force a full layout measurement on every keystroke. ## Files Sidebar, Tabs, and Local Workspace Storage Users can work with multiple documents at once. - Every existing saved document is migrated into **Workspace**. The two workspace roots are fixed, but users can create nested folders inside either root. - Secret Workspace encrypts its files and folder names locally with a password-derived AES-GCM key. It remains locked after reload, the key stays in memory only while unlocked, and a forgotten password cannot be recovered. Resetting Secret Workspace permanently deletes its encrypted payload. - The sidebar has explicit **New file** and **New folder** actions for the selected location. Files can be dragged onto another folder or workspace; the Move dialog remains available for keyboard and touch workflows. - Deleting a folder tree moves every file inside it to the workspace root before removing the folders, so document content is not lost. - New files can be created from the sidebar, tab bar, mobile menu, imports, shared snapshots, and Live Share joins. Multi-file imports show a compact bottom progress indicator. - The sidebar supports file open, rename, duplicate, favorite, move, Markdown download, and delete actions. Recent and Favorites are filtered references to the original files, not copies. - Multi-selected files can be opened or moved together. Any mixed selection of files and folders can be deleted together after a confirmation that explains which files will be deleted and which files inside removed folders will return to the workspace root. - Tabs can be reordered by drag and drop. Their menus support rename, duplicate, favorite, two-document split, Markdown download, and close; the tab context menu also provides Close others, Close to the right, Close to the left, and Close all. - Right-clicking the no-document workspace opens the same five Quick Start commands shown in the empty state. Right-clicking an editor or preview surface opens New file, selection-aware clipboard commands, and the current document's management actions; unavailable editing commands remain visible but disabled in preview and read-only contexts. - Hovering a tab shows its containing folder path and filename. Files stored directly at the Workspace root show only their filename. - The app does not impose a document-count limit. Available browser quota or filesystem capacity is the practical limit. - Each normal tab stores a title, content, workspace/folder location, favorite state, recent activity metadata, scroll position, view mode, local review threads, and creation time. - The active tab id and untitled-document counter are stored separately. - Temporary Share Snapshot and Live Share tabs are deliberately excluded from persistent tab storage. - **Reset workspace** permanently deletes normal files, review data, folders, settings, Secret Workspace ciphertext, history, and trash after confirmation. Storage used by the current implementation includes: | Key | What It Stores | | :--- | :--- | | IndexedDB `documents` | Lightweight metadata for each normal Workspace document. | | IndexedDB `contents` | One content record per normal document, loaded only when opened. | | IndexedDB `secretRecords` | One encrypted object per Secret Workspace document plus an encrypted folder record. | | IndexedDB `trash` | Local records retained when normal documents are deleted. | | `markdownViewerDocumentOrganization` | Fixed workspace state, non-secret folders, active sidebar filter, sidebar width/collapse state, and the last non-secret creation location. | | IndexedDB `metadata` | Vault id, encrypted Secret Workspace manifest, and migration markers. | | `markdownViewerActiveTab` | The active tab id. | | `markdownViewerUntitledCounter` | Counter used for new Untitled tab names. | | `markdownViewerGlobalState` | Theme, direction, view preferences, scroll sync, and similar global UI state. | | `app-lang` | Selected interface language. | | `find-replace-docked` | Whether the Find and Replace panel is docked. | On the web, document data lives in IndexedDB while small preferences remain in `localStorage`. Existing monolithic `markdownViewerTabs` data is migrated once. On desktop, normal content is stored as individual Markdown files in `Documents/Markdown Viewer Vault/Workspace` by default; metadata, history, trash, journals, settings, and encrypted Secret Workspace objects live under the same durable vault. Workspace settings includes **Private mode**, which pauses document-state writes for the current private session without clearing existing documents or Secret Workspace. The private-mode preference remains so the behavior survives a reload. **Storage and Backup** reports usage, separate normal and secret document counts, a logical browser storage location or fixed desktop vault path, exports/imports ZIP backups, and can include unchanged encrypted Secret Workspace records. Import permanently replaces the current workspace after confirmation. Backups exclude trash, desktop history, and recovery journals. Browser storage is best-effort by default and is shown as read-only status. **Reset workspace** permanently clears all local workspace data after confirmation; **Reset Secret Workspace** remains available for deleting only the encrypted area. ## Comments and Suggestion Mode Review mode adds structured feedback to the rendered document without inserting or changing Markdown. User flow: - Open **Review** from the desktop document toolbar or mobile menu. - Select the plus beside a rendered YAML table, heading, paragraph, code block, or diagram. - Add a comment or suggestion. Reviewed blocks show one control for reading existing feedback and a separate plus for adding another item. - Edit, resolve, reopen, or delete individual threads. The panel can also copy a Markdown summary, resolve all open items, or delete all feedback after confirmation. - Close Review to restore the previous Editor, Split, or Preview layout. Opening a new tab closes Review automatically. Storage and sharing: - Review threads stay with normal local tabs and survive reloads. Private mode pauses new persistence; workspace backups retain review data, while Reset workspace deletes it. - Feedback is excluded from Markdown, HTML, PDF, PNG, print, duplicated tabs, and Share Snapshot links. - If the related source block changes, the thread remains visible as unanchored feedback instead of moving to the wrong block. - Live Share synchronizes Review threads through a separate Yjs document. View-only participants can review without receiving Markdown edit permission. - The panel is a side panel on desktop, a drawer on tablet, and a touch-friendly bottom sheet on mobile, using the app's existing colors, controls, themes, and accessibility patterns. ## Editing and Formatting Tools The formatting toolbar inserts or transforms Markdown at the current selection. It provides WYSIWYG-style helpers for plain Markdown with live preview, not full in-place rich-text editing. - Undo and redo use the app's custom per-tab history. - Clear document opens a confirmation modal. - Bold, italic, strikethrough, quote, inline code, code block, terminal block, horizontal rule, and headings H1-H6 insert standard Markdown. - Bulleted and numbered lists work on selected lines or the current line. - Pressing Enter inside a list continues the list; pressing Enter on an empty list item exits the list. - Tab inserts two spaces; Shift+Tab outdents selected lines. - Title case, uppercase, and lowercase transform selected text or the current line. - Alignment buttons insert left, center, or right aligned HTML blocks. - The direction toggle switches between left-to-right and right-to-left content direction. - Link, image, reference, table, emoji, symbol, alert, and diagram buttons open focused modals. - Date/time inserts a local timestamp. - Fullscreen uses the browser Fullscreen API when available. - Find and Replace and Fullscreen are direct formatting-toolbar actions. About Markdown Viewer opens from the header or mobile menu. View-only Share Snapshot tabs and view-only Live Share participant tabs block mutating tools and announce that the editor is read-only. Non-mutating actions such as fullscreen, find, help, and info remain available. ## Custom Undo and Redo The app keeps its own edit history for each tab so toolbar actions, typed edits, and programmatic changes can be undone consistently. - `Ctrl+Z` or `Cmd+Z` undoes the previous edit in the active editor. - `Ctrl+Shift+Z`, `Cmd+Shift+Z`, `Ctrl+Y`, or `Cmd+Y` redoes. - Undo and redo buttons are disabled when the current tab cannot be edited. - Cursor position is tracked so undo and redo feel close to native textarea behavior. ## Find and Replace Find and Replace is a floating or docked panel with editor and preview highlighting. - Open it with the toolbar, `Ctrl+F`, or `Cmd+F`. - `Ctrl+H` or `Cmd+H` opens the panel focused on replacement. - It supports case-sensitive matching, whole-word matching, regular expressions, selection-only search, and replace-all. - Regex replacements can use numbered capture groups like `$1` and named groups like `$`. - Preserve-case replacement adjusts replacement casing to match the matched text. - Search scope can be limited using a Marked lexer map, including headings, code blocks, Mermaid blocks, LaTeX blocks, or the entire document. - Diff preview shows the effect before bulk replacement. - The panel can be dragged, docked, undocked, and reset to a visible position. Its floating position is constrained to the viewport. - Find history and replace history are kept in memory for the current session, up to 10 entries each. Limitations: - AST scoping depends on Marked token boundaries. Very unusual Markdown can be classified as plain text. - Scope validation protects LaTeX delimiters and Mermaid block starts, but it cannot prove every replacement is semantically correct. - Preview highlighting works on visible text nodes and may skip text produced inside complex third-party SVG renderers. ## Live Markdown Preview and GitHub-Flavored Markdown Markdown is parsed with Marked and highlighted with Highlight.js. Rendered HTML is sanitized with DOMPurify before it is inserted into the preview. Supported Markdown behavior includes: - CommonMark-style headings, paragraphs, line breaks, emphasis, blockquotes, lists, code blocks, horizontal rules, links, images, and inline HTML. - GitHub-Flavored Markdown (GFM) features such as tables, task lists, strikethrough, and autolinks. - Heading ids generated from heading text for in-document anchor navigation. - Reference definitions and reference links. - Multi-paragraph footnotes with back references. - Definition lists using a term followed by `: definition`. - Superscript with `^text^`. - Subscript with `~text~`. - Highlight with `==text==`. - GitHub-style alert blocks for NOTE, TIP, IMPORTANT, WARNING, and CAUTION. - Emoji shortcodes processed through JoyPixels when the emoji library is available. - Raw HTML is allowed only after sanitization. Scripts and unsafe event handlers are removed. The worker and main renderer both preserve block math, custom diagram shells, footnote state, definition lists, superscript, subscript, and highlight syntax so advanced blocks do not collapse during live updates. The two-document split uses the same post-processing pipeline for math, Mermaid, remote diagrams, maps, STL, and ABC notation. ## Web Worker and Preview Performance Rendering is designed to keep typing responsive. - Small documents render on the main thread after a short debounce. - Very large documents can render in `preview-worker.js`. - The current worker threshold is 50,000 characters. - Render debounce is size-aware: 100 ms for typical documents, 160 ms for large documents, and 240 ms for huge documents. - Worker rendering has a 12 second timeout and falls back if worker rendering fails repeatedly. - When safe, the worker splits Markdown into blocks, hashes each block, and returns segmented HTML. - The main thread caches sanitized segments and patches only changed preview sections. - Segmented rendering is avoided when document constructs need global context, such as footnotes or reference-style definitions. - Preview sections use `content-visibility: auto` so off-screen content costs less to lay out. Limitations: - Huge documents still depend on browser memory and DOM limits. - Advanced renderers such as Mermaid, MathJax, maps, STL, ABC, and remote diagrams run after the base Markdown pass, so they can appear slightly later than text. - The app retries advanced post-processing when shared or live content loads before renderer libraries are ready. ## Math Rendering MathJax renders LaTeX-style math. - Inline math uses `$...$`. - Display math uses `$$...$$`, `\(...\)`, or `\[...\]`. - Fenced `math` code blocks are converted into display math. - Additional MathJax packages are configured for richer notation. - MathJax loads only when math-like text is detected. - After typesetting, the app removes or hides MathJax assistive markup from export captures so duplicate text does not appear in PDFs or PNGs. Limitations: - The first math render in the web build may require downloading MathJax unless it is already cached. - Invalid LaTeX is shown according to MathJax behavior and may produce warnings or unrendered source. - A literal dollar sign should be escaped as `\$` when it is not intended to start math. ## Insert Diagrams, Charts, Maps, Models, and Music Markdown Viewer supports many fenced-code renderers for diagrams, charts, mind maps, digital timing diagrams, music notation, geographic maps, and 3D STL models. | Fence Language | Renderer | User Behavior | Network Notes | | :--- | :--- | :--- | :--- | | `mermaid` | Mermaid.js | Renders diagrams as SVG with zoom, copy, PNG, and SVG actions. | Client-side library. Diagram insertion previews may use mermaid.ink. | | `plantuml` | PlantUML/Kroki | Renders SVG and provides zoom, copy, PNG, and SVG actions. | Uses PlantUML server first, then Kroki fallback. | | `d2` | Kroki | Renders D2 SVG and provides zoom, copy, PNG, and SVG actions. | Uses Kroki. Some source is normalized for common SQL-table cases. | | `graphviz` / `dot` | Kroki | Renders Graphviz SVG and provides zoom, copy, PNG, and SVG actions. | Uses Kroki. | | `vega-lite` / `vegalite` | Kroki | Renders Vega-Lite charts. | Uses Kroki. | | `wavedrom` | Kroki | Renders WaveDrom timing diagrams. | Uses Kroki. | | `markmap` | Markmap, D3 | Renders a mind-map style SVG. | Client-side libraries. | | `geojson` | Leaflet | Renders an interactive map. | Client-side library; map tiles may require network depending on tile source. | | `topojson` | Leaflet and TopoJSON | Converts TopoJSON to GeoJSON and renders an interactive map. | Client-side library; map tiles may require network. | | `stl` | Three.js | Renders a 3D STL model with orbit controls, solid/surface-angle/wireframe modes, zoom modal, copy, and PNG export. | Client-side libraries. | | `abc` | ABCJS | Renders sheet music, supports playback, cursor sync, note highlighting, copy, PNG, and SVG export. | Client-side library; browser audio support required for playback. | Every diagram shell keeps the original source in a data attribute so the app can rerender after theme changes, shared document loading, and export preparation. Diagram PNG exports add a solid background when needed so transparent SVGs stay visible. Limitations: - Remote diagram engines send diagram source to third-party rendering endpoints. Do not use those fences for private diagram text unless you trust the endpoint or provide your own deployment. - Remote render requests have a 15 second timeout and retry twice. - Clipboard image writing requires a secure context and browser support for `ClipboardItem`. - WebGL STL rendering depends on GPU/browser support. The app disposes old STL views to reduce memory leaks. - ABC audio playback depends on browser audio APIs and may be unavailable in some environments. ## Insert Diagram & More Modal The **Insert Diagram & More** modal offers searchable templates grouped by engine. It shows source code and a live preview before insertion. - Categories include Mermaid, PlantUML, D2, Graphviz, Vega-Lite, ABC notation, WaveDrom, and Markmap. - Template code is cleaned before insertion. - Previews are cached in the browser Cache API under `diagram-previews` when possible. - Remote preview generation can use Kroki or mermaid.ink depending on the template. ## Imports Markdown Viewer can open `.md` and `.markdown` documents from local files, drag and drop, GitHub URLs, and desktop file arguments. Local file import: - Accepts `.md`, `.markdown`, and `text/markdown`. - Extension checks are case-insensitive. - Rejects an individual Markdown file larger than 10 MB. - Dragging files over the app shows a compact drop notice. Explorer document drags use a Markdown file preview, folders expand on hover, and the Explorer scrolls near its top and bottom edges. - The first 8 KB of a file are scanned for null bytes to avoid loading binary files as text. - Imported local files open in the active tab or a new tab depending on the action. Media insertion: - Uploading from the media dialog, pasting from the clipboard, and dropping an image, animated GIF, or supported video all use the same insertion pipeline and a visible progress toast. - Small raster files retain their safe raster format; larger still images are resized and converted to WebP with a bounded upload size. GIF bytes are retained so animation is not lost. - Supported managed video formats are MP4, WebM, and Ogg. Videos are inserted as sanitized HTML5 `