Current section
Files
Jump to
Current section
Files
dprint_markdown_formatter
README.md
README.md
# DprintMarkdownFormatter[](https://hex.pm/packages/dprint_markdown_formatter)[](https://hexdocs.pm/dprint_markdown_formatter/)A fast, configurable markdown formatter for Elixir that combines the power ofRust's `dprint-plugin-markdown` with native Elixir integration.## Features- **🚀 High Performance**: Uses Rust's `dprint-plugin-markdown` via 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 `~M` sigil for embedding markdown- **📦 Precompiled Binaries**: Fast installation without requiring Rust toolchain## InstallationAdd to your `mix.exs`:```elixirdef deps do [ {:dprint_markdown_formatter, "~> 0.1.0"} ]end```## Quick Start### Basic Usage```elixir# Format a single stringmarkdown = """# Poorly Formatted TitleThis is a paragraph with extra spaces.* Inconsistent list* Another item"""formatted = DprintMarkdownFormatter.format(markdown, [])# Output:# # Poorly Formatted Title# # This is a paragraph with extra spaces.# # - Inconsistent list# - Another item```### Sigil UsageUse the `~M` sigil for embedding markdown content that gets automaticallyformatted by `mix format`:```elixirimport 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 formatted```## Integration with mix formatAdd to your `.formatter.exs`:```elixir[ plugins: [DprintMarkdownFormatter]]```This enables automatic formatting of `.md` and `.markdown` files. To also formatmodule attributes, configure `format_module_attributes` in your project.## Configuration### Global ConfigurationConfigure in your `mix.exs`:```elixirdef project do [ # ... other config dprint_markdown_formatter: [ line_width: 100, text_wrap: :never, emphasis_kind: :underscores, format_module_attributes: true # Enable module attribute formatting ] ]end```### Per-call Configuration```elixiropts = [ line_width: 120, text_wrap: :never, emphasis_kind: :underscores, unordered_list_kind: :asterisks]DprintMarkdownFormatter.format(markdown, opts)```### Available 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```elixir# Skip all formatting (default)format_module_attributes: nil# Format common doc attributesformat_module_attributes: true # [:moduledoc, :doc, :typedoc, :shortdoc, :deprecated]# Format specific attributes onlyformat_module_attributes: [:moduledoc, :doc, :custom_doc]```## Module Attribute Formatting ExampleBefore `mix format`:```elixirdefmodule MyModule do @moduledoc """ This is messy markdown content. * Poorly formatted list * Another item """ @doc """ Function documentation with extra spaces. """ def my_function, do: :okend```After `mix format`:```elixirdefmodule MyModule do @moduledoc """ This is messy markdown content. - Properly formatted list - Another item """ @doc """ Function documentation with extra spaces. """ def my_function, do: :okend```## Troubleshooting### Module attributes not being formattedMake sure you have:1. Added `plugins: [DprintMarkdownFormatter]` to `.formatter.exs`2. Configured `format_module_attributes: true` in your `mix.exs`3. Run `mix format` on your `.ex` files### Compilation issuesIf you see Rust compilation errors, you can force using precompiled binaries:```bashexport RUSTLER_PRECOMPILED_FORCE_BUILD=falsemix deps.get```## Development### Prerequisites- Elixir 1.16+- Rust toolchain (optional, precompiled binaries available)### Commands```bash# Setupmix deps.getmix compile# Developmentmix test # Run testsmix check # Run all quality checks (format, credo, dialyzer, cargo fmt, cargo clippy)mix format # Format Elixir codemix credo # Static analysismix dialyzer # Type checking# Rust development (in native/dprint_markdown_formatter/)cargo build # Build the NIFcargo 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 API- `DprintMarkdownFormatter.Native`: Rustler NIF wrapper- `DprintMarkdownFormatter.Sigil`: `~M` sigil implementation## LicenseMIT License - see the LICENSE file for details.## Code GenerationThis project was generated and developed with assistance from[Claude Code](https://claude.ai/code), Anthropic's AI coding assistant. Allcommits in this repository include co-author attribution to Claude.## Acknowledgments- Built on [dprint-plugin-markdown](https://github.com/dprint/dprint-plugin-markdown)- Uses [Rustler](https://github.com/rusterlium/rustler) for Elixir/Rust integration