README file from
GithubHard Line Wrap for Obsidian
Transparently hard-wrap markdown files on disk while displaying them as soft-wrapped paragraphs in the editor.
Files are always stored with hard line breaks at a configurable column width (default 80), making them pleasant to read in a terminal, emacs, git diffs, etc. Obsidian's editor sees the unwrapped form — one long line per paragraph — and handles visual wrapping natively.
Configuration
Global settings
In Settings > Hard Wrap:
| Setting | Default | Description |
|---|---|---|
| Enable hard-wrapping | on | Master toggle |
| Column width | 80 | Wrap target (40–200) |
Per-file override
Add a hard-wrap key to a file's frontmatter:
---
hard-wrap: 60 # wrap at 60 columns
---
---
hard-wrap: false # disable for this file
---
---
hard-wrap: true # enable with global default columns
---
Omitting the key uses the global default.
Commands
- Reformat current file with hard wraps — normalizes the editor content by running unwrap → wrap → unwrap. This cleans up hard breaks that the plugin didn't insert — e.g. text pasted from an external source, or soft wraps added manually — without requiring a save/reload cycle. Also useful after changing the column width or after external edits.
How it works
The plugin monkey-patches three methods on MarkdownView.prototype
using monkey-around:
- On load (
setViewData): hard-wrapped paragraphs are joined into single lines before the content reaches the editor. - On save (
getViewData): the editor's single-line paragraphs are re-wrapped at the configured column width before being written to disk. - On mode switch (
setMode): when switching back to source mode,this.datais re-unwrapped. Obsidian'ssetModebypassessetViewDataand feedsthis.datadirectly to the editor, so without this patch the editor would show hard-wrapped lines after toggling between source and reading mode.
Both auto-save (the debounced requestSave) and manual save (Ctrl+S, close) go
through getViewData, so all save paths produce hard-wrapped output. Patching
getViewData rather than save is important because Obsidian also calls
getViewData outside the save path. When a file is modified externally while
the editor has unsaved changes, Obsidian performs a 3-way merge between
lastSavedData, the current getViewData() return value, and the new disk
content. Since lastSavedData and the disk content are both in hard-wrapped
form, getViewData() must return wrapped text too — otherwise the merge would
treat every re-wrapped line break as a conflicting change. Obsidian also uses
getViewData() for change detection (comparing against lastSavedData to
decide whether a save is needed), which likewise requires consistent
representations.
On plugin unload, all open markdown files are force-saved so they remain hard-wrapped on disk.
What gets wrapped
The transform follows CommonMark soft-line-break semantics. Anything a markdown renderer would join into a single paragraph gets wrapped/unwrapped:
- Plain paragraphs
- Blockquote content (including nested blockquotes)
- List item content (unordered, ordered, nested)
- Footnote definitions
- Callout body text
Everything else passes through verbatim:
- Frontmatter (YAML between
---fences) - Fenced code blocks (backtick and tilde)
- Indented code blocks
- ATX and setext headings
- Tables
- Thematic breaks
- HTML blocks
- Callout headers (
[!type]lines)
Within wrappable text, inline elements are never broken across lines:
- Links:
[text](url)and[text][ref] - Images:
 - Inline code:
`code`
Hard line breaks (trailing \ or two trailing spaces) are preserved.
Build
Requires Node.js >= 18.
npm install
npm run build # production build → main.js
npm run dev # watch mode (rebuilds on change)
npm test # run unit tests
The build uses esbuild. Output is a single main.js (CommonJS). The
obsidian package and @codemirror/* are externals (provided by
Obsidian at runtime). monkey-around is bundled.
Known limitations
- Search: Obsidian indexes on-disk (hard-wrapped) content. A search for a phrase that spans a wrap boundary won't match.
Note on code authorship
This plugin and its documentation were substantially created using AI. They have been tested and reviewed by the human author.