Skip to content

Commit

Permalink
Fix option links in mkdocs rule pages
Browse files Browse the repository at this point in the history
In 28c9263 I introduced automatic
linkification of option references in rule documentation,
which automatically converted the following:

    ## Options

    * `namespace-packages`

to:

    ## Options

    * [`namespace-packages`]

    [`namespace-packages`]: ../../settings#namespace-packages

While the above is a correct CommonMark[1] link definition,
what I was missing was that we used mkdocs for our documentation
generation, which as it turns out uses a non-CommonMark-compliant
Markdown parser, namely Python-Markdown, which contrary to CommonMark
doesn't support link definitions containing code tags.

This commit fixes the broken links via a regex hack.

[1]: https://commonmark.org/
  • Loading branch information
not-my-profile authored and charliermarsh committed Feb 14, 2023
1 parent 8609931 commit a77b456
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/ruff_dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ clap = { workspace = true }
itertools = { workspace = true }
libcst = { workspace = true }
once_cell = { workspace = true }
regex.workspace = true
ruff = { path = "../ruff" }
ruff_cli = { path = "../ruff_cli" }
rustpython-common = { workspace = true }
Expand Down
56 changes: 54 additions & 2 deletions crates/ruff_dev/src/generate_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use std::fs;

use anyhow::Result;
use regex::{Captures, Regex};
use ruff::registry::{Linter, Rule, RuleNamespace};
use ruff::settings::options::Options;
use ruff::settings::options_base::ConfigurationOptions;
Expand Down Expand Up @@ -56,6 +57,21 @@ fn process_documentation(documentation: &str, out: &mut String) {
let mut in_options = false;
let mut after = String::new();

// HACK: This is an ugly regex hack that's necessary because mkdocs uses
// a non-CommonMark-compliant Markdown parser, which doesn't support code
// tags in link definitions
// (see https://github.com/Python-Markdown/markdown/issues/280).
let documentation = Regex::new(r"\[`(.*?)`\]($|[^\[])").unwrap().replace_all(
documentation,
|caps: &Captures| {
format!(
"[`{option}`][{option}]{sep}",
option = &caps[1],
sep = &caps[2]
)
},
);

for line in documentation.split_inclusive('\n') {
if line.starts_with("## ") {
in_options = line == "## Options\n";
Expand All @@ -69,8 +85,8 @@ fn process_documentation(documentation: &str, out: &mut String) {
);

let anchor = option.rsplit('.').next().unwrap();
out.push_str(&format!("* [`{option}`]\n"));
after.push_str(&format!("[`{option}`]: ../../settings#{anchor}"));
out.push_str(&format!("* [`{option}`][{option}]\n"));
after.push_str(&format!("[{option}]: ../../settings#{anchor}"));

continue;
}
Expand All @@ -83,3 +99,39 @@ fn process_documentation(documentation: &str, out: &mut String) {
out.push_str(&after);
}
}

#[cfg(test)]
mod tests {
use super::process_documentation;

#[test]
fn test_process_documentation() {
let mut out = String::new();
process_documentation(
"
See also [`mccabe.max-complexity`].
Something [`else`][other].
## Options
* `mccabe.max-complexity`
[other]: http://example.com.",
&mut out,
);
assert_eq!(
out,
"
See also [`mccabe.max-complexity`][mccabe.max-complexity].
Something [`else`][other].
## Options
* [`mccabe.max-complexity`][mccabe.max-complexity]
[other]: http://example.com.
[mccabe.max-complexity]: ../../settings#max-complexity"
);
}
}

0 comments on commit a77b456

Please sign in to comment.