Markdown Standard Formatter
unlistedby jjm.one
Format Markdown with Prettier, markdownlint, EditorConfig, and Obsidian-safe preservation rules.
Markdown Standard Formatter
An Obsidian Markdown formatter shipped as both a desktop plugin and a standalone CI/local CLI. Both run the same pipeline — Prettier, markdownlint, .editorconfig, a shared project policy, and Obsidian-safe syntax preservation — so a note formats identically in Obsidian and in CI.
Repository: https://github.com/jjm-one/Markdown-Standard-Formatter-for-Obsidian
Alpha. Not in Obsidian's Community Plugins browser yet — install with BRAT or manually. Anything may change before
1.0.0; keep backups.
Documentation
Start here:
- Obsidian plugin guide — install, first format, every setting and command, troubleshooting. Written for people who have never used a formatter.
- Command-line tool guide — format a whole folder from a terminal, plus git-hook and CI setup.
Reference:
- Configuration — the
.markdown-standard-formatter.jsonpolicy model, every key, and precedence. - Obsidian compatibility — protected syntax and the markdownlint rules disabled by default.
- Standalone CLI — every argument, exit code, and CI recipe.
- Architecture · Testing — internals.
What it does
- Formats the active note on demand (command, hotkey, ribbon) or automatically on modify, open, or close — every automatic trigger is off by default.
- Resolves
.editorconfigand trusted Prettier configuration per note, and applies configurable markdownlint fixes. - Reads a committed vault-level
.markdown-standard-formatter.jsonpolicy and a gitignore-style.markdown-standard-formatter-ignore, both shared by the plugin and the CLI. - Preserves Obsidian syntax by default: Properties/frontmatter, wikilinks, embeds, callouts, block IDs, comments, MathJax, tags, inline footnotes, highlights, and fenced code blocks.
- Every configuration source reloads automatically — no Obsidian restart needed.
Install the plugin
BRAT (recommended). Install BRAT from Community Plugins, run BRAT: Add a beta plugin for testing, and paste https://github.com/jjm-one/Markdown-Standard-Formatter-for-Obsidian. BRAT keeps it updated.
Manual. Download main.js, manifest.json, and styles.css from the latest release into <Vault>/.obsidian/plugins/markdown-standard-formatter/, reload Obsidian, and enable it.
Full walkthrough and the rolling main-latest development channel: Obsidian plugin guide → Installing.
Use the CLI
Every release attaches markdown-standard-formatter-cli.cjs, a bundled Node.js 24 CLI that runs the same formatter core:
node markdown-standard-formatter-cli.cjs check . # exit 1 if formatting is needed; never writes
node markdown-standard-formatter-cli.cjs format . # rewrite changed files in place
Exit codes: 0 clean · 1 changes required (check only) · 2 error. Ready-made Docker, GitHub Actions, and GitLab CI setups are in examples/.
All options, --show-errors, verbosity levels, exclusions, and CI recipes: Standalone CLI.
Configure
Drop .markdown-standard-formatter.json at the vault root to share one policy across a vault. Every key is optional and overrides the corresponding default:
{
"proseWrap": "always",
"markdownStructures": { "tables": "preserve" },
"markdownlint": { "MD013": true }
}
Precedence: built-in defaults → Obsidian settings UI → vault project file. A complete, commented starter is .markdown-standard-formatter.example.json; the full model, every key, and the default markdownlint rule set are in Configuration.
Excluding notes
List gitignore-style patterns in .markdown-standard-formatter-ignore at the vault root — * matches within a path segment, ** crosses directories, ! re-includes. The same file is honored by the plugin and the CLI. Details and the project-config ignore block: Configuration.
Triggers
| Trigger | Setting | Default |
|---|---|---|
| Manual command / hotkey / ribbon | — | always available |
| Continuous after a vault write (debounced) | formatOnModify | off |
| On file open | formatOnOpen | off |
| On last Markdown view close | formatOnClose | off |
Desktop only
The plugin uses Node.js-backed Prettier/markdownlint and filesystem configuration discovery, so it declares isDesktopOnly: true and does not run on Obsidian mobile — see Architecture.
Develop
npm install
npm run dev # watch build
npm run ci # full gate: lint, types, tests + coverage, build, package
Run the suite with npm test. See Testing, Architecture, and Contributing.
Releases & automation
Releases are GitHub Releases from SemVer tags (no v prefix; pre-1.0 tags are pre-releases), built and attested by an automated workflow that attaches main.js, manifest.json, styles.css, and the standalone CLI. A rolling main-latest prerelease tracks the newest successful main build.
Security and supply chain: CI runs npm audit; CodeQL, Semgrep, and OpenSSF Scorecard run on pushes and a schedule; the formatter core is fuzzed with jazzer.js on every relevant PR and weekly; releases carry SLSA build provenance; every GitHub Action is SHA-pinned and every workflow keeps least-privilege token permissions (both enforced by npm run check:repository); Dependabot updates npm packages, Actions, and the example Docker image weekly with grouped low-risk auto-merge.
License
Copyright © 2026 jjm.one. Licensed under the GNU Lesser General Public License v3.0 only (LGPL-3.0-only) — see LICENSE and the texts under LICENSES/. The production bundle includes MIT-licensed third-party components; see THIRD_PARTY_NOTICES.md.
Disclaimer
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. To the maximum extent permitted by applicable law, the authors and contributors accept no liability for any claim, damages, data loss, or other consequences arising from the use of, or inability to use, this software. Formatting rewrites file contents — keep backups or version control. These terms follow sections 15–17 of the GNU GPL v3, as incorporated by the LGPL v3.0; see LICENSE.
For plugin developers
Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.