DprintMarkdownFormatter (dprint_markdown_formatter v0.3.0)

View Source

A fast markdown formatter using dprint-plugin-markdown via Rustler NIF.

This module provides an interface to format markdown text using the dprint-plugin-markdown formatter implemented in Rust for performance.

Configuration

Options for dprint can be configured in mix.exs:

def project do
  [
    # ... other config
    dprint_markdown_formatter: [
      line_width: 100,
      text_wrap: :never,
      emphasis_kind: :underscores,

      # Enable formatting for default attributes (moduledoc, doc, typedoc, shortdoc, deprecated)
      format_module_attributes: true,

      # Or disable all formatting (default behavior)
      # format_module_attributes: nil,

      # Or specify custom attributes
      # format_module_attributes: [:moduledoc, :doc, :custom_doc, :note]
    ]
  ]
end

Available Options

  • :line_width - Maximum line width (default: 80)
  • :text_wrap - Text wrapping behavior: :always, :never, :maintain (default: :always)
  • :emphasis_kind - Emphasis style: :asterisks, :underscores (default: :asterisks)
  • :strong_kind - Strong text style: :asterisks, :underscores (default: :asterisks)
  • :new_line_kind - Line ending type: :auto, :lf, :crlf (default: :auto)
  • :unordered_list_kind - Unordered list style: :dashes, :asterisks (default: :dashes)

Note: Configuration values can be provided as atoms (:never) or strings ("never"). Atoms are preferred for consistency with Elixir conventions.

  • :format_module_attributes - Configure which module attributes to format. Supports four input types for maximum flexibility:

    nil (default): Skip formatting all module attributes.

    Boolean true: Format common documentation attributes: :moduledoc, :doc, :typedoc, :shortdoc, :deprecated

    Boolean false: Skip formatting all module attributes.

    List of atoms: Format only the specified attributes. Any module attribute containing string content can be specified. Examples:

    # Format only module docs
    format_module_attributes: [:moduledoc]
    
    # Format standard docs plus custom attributes  
    format_module_attributes: [:moduledoc, :doc, :custom_doc, :note, :example]
    
    # Format testing attributes
    format_module_attributes: [:moduletag, :tag, :describetag]

    Only string values are processed (boolean false values are preserved unchanged). Use default_doc_attributes/0 to get the standard list.

Sigil Support

For convenient markdown handling, you can use the ~M sigil:

import DprintMarkdownFormatter.Sigil

# Raw markdown
markdown = ~M"""
# Hello World

Some content here.
"""

Summary

Functions

Returns the default list of module attributes that are formatted when format_module_attributes: true.

Returns the features supported by this formatter plugin.

Mix.Tasks.Format implementation for backward compatibility.

Formats markdown text with error details.

Functions

default_doc_attributes()

@spec default_doc_attributes() :: [atom()]

Returns the default list of module attributes that are formatted when format_module_attributes: true.

This list includes the most commonly used documentation attributes in Elixir projects.

Examples

iex> DprintMarkdownFormatter.default_doc_attributes()
[:moduledoc, :doc, :typedoc, :shortdoc, :deprecated]

# Extend with custom attributes
custom_attrs = DprintMarkdownFormatter.default_doc_attributes() ++ [:custom_doc, :note]

features(opts)

@spec features(keyword()) :: [sigils: [atom()], extensions: [binary()]]

Returns the features supported by this formatter plugin.

This plugin supports:

  • The ~M sigil for markdown content
  • Files with .md and .markdown extensions (pure markdown)
  • Files with .ex and .exs extensions (module attributes only)

format(contents, opts)

@spec format(
  String.t(),
  keyword()
) :: String.t()

Mix.Tasks.Format implementation for backward compatibility.

This is the actual function used by Mix formatter. It calls format_with_errors/2 internally and returns the original content if formatting fails.

Examples

iex> DprintMarkdownFormatter.format("# Hello    World", [])
"# Hello World\n"

iex> DprintMarkdownFormatter.format("# Hello    World", extension: ".md")
"# Hello World\n"

iex> DprintMarkdownFormatter.format("# Hello    World", sigil: :M)
"# Hello World"

iex> DprintMarkdownFormatter.format("# Hello    World", line_width: 60)
"# Hello World\n"

iex> DprintMarkdownFormatter.format("* Item 1\n* Item 2", unordered_list_kind: :asterisks)
"* Item 1\n* Item 2\n"

format_with_errors(contents, opts)

@spec format_with_errors(
  String.t(),
  keyword()
) :: {:ok, String.t()} | {:error, DprintMarkdownFormatter.Error.t()}

Formats markdown text with error details.

Returns {:ok, formatted_content} on success, or {:error, error} on failure. This provides more detailed error information than the Mix.Tasks.Format version.

Examples

iex> DprintMarkdownFormatter.format_with_errors("# Hello    World", [])
{:ok, "# Hello World\n"}

iex> DprintMarkdownFormatter.format_with_errors("# Hello", line_width: 100)
{:ok, "# Hello\n"}

# Error cases return detailed error information (e.g., invalid content types)
# {:error, %DprintMarkdownFormatter.Error.ValidationError{}} would be returned for invalid inputs