Skip to content

Repository files navigation

Sarala

A seamless WYSIWYG Markdown editor — no preview pane, no split view.

The editing surface is the preview. Every paragraph, heading, list, quote, table, and code fence is a live block: click into one and it opens to raw Markdown, click away and it renders in place. One parser, one theme, one window — what you see while writing is exactly what exports.


Latest release Build Snap Store License: GPL-3.0-or-later Platforms Built with Tauri SolidJS


Sarala — Markdown that reads like a finished document

See it

Sarala editing a Markdown document in the light theme — file tree and outline sidebar, a live-rendered table, and syntax-highlighted C

Light theme — rendered tables and Shiki-highlighted code, with the file tree and outline in the sidebar.



Sarala in the Night theme showing a welcome document with clickable task-list checkboxes and the theme palette

Night theme — clickable task lists, live-styled inline formatting, and the quick theme palette.


Install

🍎 macOS — Homebrew

The easiest way to get Sarala on a Mac:

brew tap solancer/sarala https://github.com/solancer/sarala
brew install --cask sarala

Sarala's universal build is ad-hoc signed (so it runs natively on both Apple Silicon and Intel) but isn't Apple-notarized. The cask clears the quarantine attribute on install so Gatekeeper won't block the first launch — no extra flags needed. Upgrade later with brew upgrade --cask sarala.

🐧 Linux — Snap Store

Get it from the Snap Store

sudo snap install sarala

📦 Every platform — direct download

Grab an installer from the latest release:

Platform Files
macOS .dmg (universal)
Windows .exe · .msi
Linux .AppImage · .deb · .rpm · snap

Features

  • Live block editing — type Markdown and the active block styles itself as you type: syntax markers stay visible but dimmed (the gray ## next to a heading, gray [ ]( ) around a blue link), and the block fully renders when you press Enter or move the caret away
  • Smart Enter — continues lists (with auto-numbering and unchecked task carry-over), continues blockquotes, ends a list on an empty item, auto-closes a just-opened code fence, and inserts plain newlines inside fences; Shift+Enter for a soft break
  • Click-to-edit anywhere — click into rendered text and the caret lands at that exact spot in the source (rendered→source position mapping); merge on backspace at block start, arrow-key navigation across blocks, IME-safe (composition events respected)
  • GFM — tables, task lists (clickable checkboxes), strikethrough, and fenced code highlighted by Shiki (TextMate grammars + VS Code themes; light/dark via CSS variables, self-contained inline styles in export)
  • Math (KaTeX) — inline $…$ and block $$…$$, rendered in inactive blocks and shown as raw source while editing; optional \(…\) / \[…\] delimiters and a ```math block (preference-gated, off by default); a broken formula keeps its last good render with an error rather than blanking
  • Diagrams (Mermaid) — ```mermaid blocks render every diagram type (flowchart, sequence, gantt, class, state, pie, ER, gitGraph, mindmap, timeline, quadrant, sankey, XY, block, kanban, architecture); invalid syntax shows an inline error and keeps the last good diagram; the diagram theme follows the app's light/dark theme
  • Find & replace (Cmd/Ctrl+F, replace one or all) and an Open Quickly fuzzy finder (Shift+Cmd/Ctrl+P)
  • Sidebar — file tree (open a folder, browse .md files) and a live outline (click a heading to jump)
  • Distraction-free modesSource mode (Cmd/Ctrl+/) as an escape hatch to the full raw document, plus Focus (F8) and Typewriter (F9)
  • Native menu bar (File, Edit, Paragraph, Format, View, Themes, Window, Help) — every item dispatches through one frontend command bus shared with the keyboard shortcuts
  • Paragraph tools — heading levels, pipe-table editing (insert/rows/columns/alignment), lists and task toggles, quotes, math/code blocks, [TOC], footnotes, GFM alerts
  • Themes — Paper, Graphite, GitHub, Night, Newsprint, Whitey — pure CSS variables; add your own in src/styles/app.css
  • Export — HTML (with an outline sidebar), real PDF (headless Chromium with configurable page size, margins, and header/footer using ${pageNo}/${totalPages}/${title}/${date}; falls back to the print dialog), and docx/odt/rtf/epub/LaTeX/MediaWiki/rst/Textile/OPML via Pandoc. Named presets store a format, output path, after-export action (reveal/open/run a command), and pandoc flags; Export with Previous re-runs the last. Per-document YAML keys (export_filename, export_pdf_margin, …) override settings. Import via Pandoc too
  • Local images — relative src paths resolve against the document's folder (via Tauri's asset protocol) and render inline; inserting an image can copy it into a configurable folder (with a ${filename} variable), and per-document copy-images-to / image-root-url YAML keys override the copy folder and image root
  • Built for daily writing — recent files, settings persisted to disk, smart punctuation, LF/CRLF line endings, word/character count, a dirty indicator (window title shows — Edited), confirm-on-close, and atomic saves (temp file + rename)
  • Auto-update (opt-in) — Help ▸ Check for Updates… checks a manifest, then downloads, verifies (minisign), installs, and relaunches — signed artifacts from GitHub Releases, see Releasing

Shortcuts

Most items live in the native menus with their accelerators shown inline; the core set:

Keys Action
Cmd/Ctrl+S / Shift+Cmd/Ctrl+S Save / Save As
Cmd/Ctrl+O / Shift+Cmd/Ctrl+O Open file / Open folder
Shift+Cmd/Ctrl+P Open Quickly
Cmd/Ctrl+F / Cmd/Ctrl+G / Alt+Cmd/Ctrl+F Find / Find next / Replace
Cmd/Ctrl+/ Toggle source mode
Shift+Cmd/Ctrl+L Toggle sidebar
F8 / F9 Focus mode / Typewriter mode
Cmd/Ctrl+B / I / U / K Bold / italic / underline / link
Cmd/Ctrl+E / Shift+Cmd/Ctrl+X Inline code / strike
Cmd/Ctrl+1…6, 0 Heading level / paragraph
Cmd/Ctrl+= / Cmd/Ctrl+- Increase / decrease heading level
Alt+Cmd/Ctrl+T / C / Q / O / U / X Table / fences / quote / ordered / bullet / task list
Alt+Up / Alt+Down Move block up / down
Shift+Cmd/Ctrl+0 / = / - Actual size / zoom in / zoom out
Cmd/Ctrl+P Print (also: Export ▸ PDF)
Esc Render the current block

Run it

Prereqs: Node 18+, Rust stable, and Tauri's platform dependencies (https://tauri.app/start/prerequisites/ — on Linux that's webkit2gtk-4.1, etc.).

pnpm install
pnpm tauri dev      # desktop app
pnpm tauri build    # installers in src-tauri/target/release/bundle

The frontend also runs standalone in a browser (pnpm dev) with an in-memory demo document — file dialogs are desktop-only, and Save downloads the file instead.

Architecture

src/
  markdown.ts        parser config, block splitter (fence/front-matter aware),
                     outline extraction, word count, task toggling
  store.ts           reactive document model: blocks, split/merge, dirty state
  commands.ts        command bus: every menu id / shortcut maps to one action
  settings.ts        persisted settings (recent files, theme, zoom, toggles)
  tabletools.ts      pipe-table parse/serialize + caret-positioned edits
  platform.ts        Tauri invoke bridge with graceful browser fallback
  livesource.ts      the live styler: dims markers, styles content in real
                     time; caret offset get/set; click-position mapping
  components/
    Editor.tsx       block list + click-to-append behavior
    Block.tsx        the hybrid cell: rendered HTML ⇄ live-styled
                     contenteditable source (Enter semantics, caret logic)
    Sidebar.tsx      file tree + outline tabs
    SourceView.tsx   whole-document raw mode
    StatusBar.tsx    counts, theme + mode toggles
    FindBar.tsx      find / replace across blocks
    QuickOpen.tsx    fuzzy file finder overlay
src-tauri/
  src/main.rs        list_dir (md-aware recursive walk), read_file,
                     save_file (atomic write), settings, pandoc bridge,
                     dialog / opener / clipboard plugins
  src/menu.rs        native menu tree; forwards item ids as one "menu"
                     event — no editing logic in Rust

Design notes

  • Block model over character model. The document is an array of Markdown blocks (code fences and YAML front matter are kept whole). The active block is a contenteditable whose innerHTML is re-styled by styleSource() on every input — the key invariant is that the styled HTML's textContent is byte-identical to the source, which is what makes caret save/restore by text offset exact (verified by roundtrip tests).
  • One pipeline. The same renderMarkdown() renders editor blocks and the HTML export, so editing view and output can never diverge.
  • Normalization on save falls out of the model: blocks re-join with exactly one blank line between them.

Releasing

Releases are automated — bump the version, push a tag, and CI does the rest:

pnpm release 0.2.0          # bump manifests + commit + tag v0.2.0
pnpm release 0.2.0 --push   # ...and push main + the tag in one go

Pushing the vX.Y.Z tag triggers release.yml: it builds and signs on macOS (universal), Windows, and Linux; publishes the GitHub Release with installers and updater artifacts (each with a .sig); and writes latest.json to the updater gist — the moment existing installs start seeing the update. The full signing-key setup, CI secrets, latest.json shape, and the macOS notarization caveat live in RELEASING.md.

Roadmap

Custom CSS theme folder.

License

GPL-3.0-or-later © Srinivas Gowda

About

Sarala is a fast, distraction-free WYSIWYG Markdown editor. It styles Markdown live as you type while keeping the underlying source intact, and renders code, math (KaTeX), Mermaid, and D2 diagrams.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages