Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions docs/formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,84 @@ def f(x):
[literal blocks]: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#literal-blocks
[`code-block` and `sourcecode` directives]: https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#directive-code-block

## Markdown code formatting

*This feature is currently only available in [preview mode](preview.md#preview).*

The Ruff formatter can also format Python code blocks in Markdown files.
In these files, Ruff will format any CommonMark [fenced code blocks][]
with the following info strings: `python`, `py`, `python3`, `py3`, or `pyi`.
Fenced code blocks without an info string are assumed to be Python code examples
and will also be formatted.

If a code example is recognized and treated as Python, the Ruff formatter will
automatically skip it if the code does not parse as valid Python or if the
reformatted code would produce an invalid Python program.

Code blocks marked as `python`, `py`, `python3`, or `py3` will be formatted with
the normal Python code formatting style, while any code blocks marked with
`pyi` will be formatted like Python type stub files.

While [formatting suppression](#format-suppression) comments will be handled as
usual within code blocks, the formatter will also skip formatting any code block
surrounded by appropriate HTML comments, such as:

````markdown
<!-- fmt:off -->
```py
print( 'hello' )
```
<!-- fmt:on -->
````

Any number of code blocks may be contained within a matching pair of `off` and
`on` HTML comments, and any `off` comment *without* a matching `on` comment
will implicitly cover the remaining portion of the document.

The Ruff formatter will also recognize HTML comments from [blacken-docs][],
`<!-- blacken-docs:off -->` and `<!-- blacken-docs:on -->`, which are equivalent
to `<!-- fmt:off -->` and `<!-- fmt:on -->` respectively.

[blacken-docs]: https://github.com/adamchainz/blacken-docs/

Ruff will not automatically discover or format Markdown files in your project,
but will format any Markdown files explicitly passed with a `.md` extension:

```shell-session
$ ruff format --preview --check docs/
warning: No Python files found under the given path(s)

$ ruff format --preview --check docs/*.md
13 files already formatted
```

This is likely to change in a future release when the feature is stabilized.
Including Markdown files without also enabling [preview mode](preview.md#preview)
will result in an error message and non-zero [exit code](#exit-codes).

To include Markdown files by default when running Ruff on your project, add them
with [`extend-include`](settings.md#extend-include) in your project settings:

=== "pyproject.toml"

```toml
[tool.ruff]
# Find and format code blocks in Markdown files
extend-include = ["*.md"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify, something like extend-include = ["docs/*.md"] also works as expected, but extend-include = ["docs/*"] does nothing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine for this glob not to end with *.md, but I did have to check:

~/astral/worktrees/ruff1/target/debug/ruff format --check --no-cache --config 'extend-include=["*"]' --preview
unformatted: File would be reformatted
 --> try.md:1:1
1 | ```py
  - import  math
2 + import math
3 | ```

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extension needs to be included, otherwise ruff will also discover other files that aren't python/markdown/toml, and will end up trying to format them as python:

$ ruff format --check --preview --config 'extend-include=["docs/*"]' docs/ | grep -C1 extra.js
invalid-syntax: Simple statements must be separated by newlines or semicolons
--> docs/js/extra.js:1:1

# OR
extend-include = ["docs/*.md"]
```

=== "ruff.toml"

```toml
# Find and format code blocks in Markdown files
extend-include = ["*.md"]
# OR
extend-include = ["docs/*.md"]
```


## Format suppression

Like Black, Ruff supports `# fmt: on`, `# fmt: off`, and `# fmt: skip` pragma comments, which can
Expand Down