DprintMarkdownFormatter
View SourceA fast, configurable markdown formatter for Elixir that combines the power of
Rust's dprint-plugin-markdown with native Elixir integration.
Features
- 🚀 High Performance: Uses Rust's
dprint-plugin-markdownvia Rustler NIFs - 🔧 Highly Configurable: Extensive formatting options for line width, text wrapping, emphasis styles, and more
- 📝 Module Attribute Formatting: Automatically formats markdown in
@moduledoc,@doc, etc. - 🎯 Mix Integration: Works seamlessly with
mix format - 🔤 Sigil Support: Provides
~Msigil for embedding markdown - 📦 Precompiled Binaries: Fast installation without requiring Rust toolchain
Installation
Add to your mix.exs:
def deps do
[
{:dprint_markdown_formatter, "~> 0.5.1"}
]
endQuick Start
Sigil Usage
Use the ~M sigil for embedding markdown content that gets automatically
formatted by mix format:
import DprintMarkdownFormatter.Sigil
# This markdown will be automatically formatted when you run `mix format`
markdown = ~M"""
# API Documentation
This is **bold** text with extra spaces.
* Poorly formatted list
"""
# After `mix format`, the sigil content becomes properly formattedIntegration with mix format
Add to your .formatter.exs:
[
plugins: [DprintMarkdownFormatter],
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}", "*.{md,markdown}"]
]This enables automatic formatting of .md and .markdown files. To also format
module attributes, configure format_module_attributes in your project.
Configuration
Global Configuration
Configure in your mix.exs:
def project do
[
# ... other config
dprint_markdown_formatter: [
line_width: 100,
text_wrap: :never,
emphasis_kind: :underscores,
format_module_attributes: true # Enable module attribute formatting
]
]
endAvailable Options
| Option | Default | Description |
|---|---|---|
:line_width | 80 | Maximum line width |
:text_wrap | :always | Text wrapping: :always, :never, :maintain |
:emphasis_kind | :asterisks | Emphasis style: :asterisks, :underscores |
:strong_kind | :asterisks | Strong text style: :asterisks, :underscores |
:unordered_list_kind | :dashes | List style: :dashes, :asterisks |
:format_module_attributes | nil | Module attribute formatting (see below) |
Note: Configuration values can be provided as atoms (:never) or strings
("never"). Atoms are preferred for consistency with Elixir conventions.
Module Attribute Configuration
# Skip all formatting (default)
format_module_attributes: nil
# Format common doc attributes
format_module_attributes: true # [:moduledoc, :doc, :typedoc, :shortdoc, :deprecated]
# Format specific attributes only
format_module_attributes: [:moduledoc, :doc, :custom_doc]Module Attribute Formatting Example
Before mix format:
defmodule MyModule do
@moduledoc """
This is messy markdown content.
* Poorly formatted list
* Another item
"""
@doc """
Function documentation with extra spaces.
"""
def my_function, do: :ok
endAfter mix format:
defmodule MyModule do
@moduledoc """
This is messy markdown content.
- Properly formatted list
- Another item
"""
@doc """
Function documentation with extra spaces.
"""
def my_function, do: :ok
endTroubleshooting
Module attributes not being formatted
Make sure you have:
- Added
plugins: [DprintMarkdownFormatter]to.formatter.exs - Configured
format_module_attributes: truein yourmix.exs - Run
mix formaton your.exfiles
Compilation issues
If you see Rust compilation errors, you can force using precompiled binaries:
export RUSTLER_PRECOMPILED_FORCE_BUILD=false
mix deps.get
Development
Prerequisites
- Elixir 1.16+
- Rust toolchain (optional, precompiled binaries available)
Commands
# Setup
mix deps.get
mix compile
# Development
mix test # Run tests
mix check # Run all quality checks (format, credo, dialyzer, cargo fmt, cargo clippy)
mix format # Format Elixir code
mix credo # Static analysis
mix dialyzer # Type checking
# Rust development (in native/dprint_markdown_formatter/)
cargo build # Build the NIF
cargo test # Run Rust tests
Architecture
- Elixir Layer: Public API, configuration management, Mix integration
- Rust NIF: Core formatting engine using
dprint-plugin-markdown - Rustler: Type-safe bridge between Elixir and Rust
Key Components
DprintMarkdownFormatter: Main public APIDprintMarkdownFormatter.Native: Rustler NIF wrapperDprintMarkdownFormatter.Sigil:~Msigil implementation
License
MIT License - see the LICENSE file for details.
Code Generation
This project was generated and developed with assistance from Claude Code, Anthropic's AI coding assistant. All commits in this repository include co-author attribution to Claude.
Acknowledgments
- Built on dprint-plugin-markdown
- Uses Rustler for Elixir/Rust integration