diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 9bdcf80fc585dd..db36a0248bcf17 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -1,4 +1,4 @@ -name: mkdocs +name: mdbook on: release: @@ -6,7 +6,7 @@ on: workflow_dispatch: jobs: - mkdocs: + mdbook: runs-on: ubuntu-latest env: CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }} @@ -18,16 +18,16 @@ jobs: - uses: Swatinem/rust-cache@v1 - name: "Install dependencies" run: | - pip install -r docs/requirements.txt - - name: "Copy README File" + cargo install mdbook + - name: "Generate the website" run: | python scripts/transform_readme.py --target mkdocs - python scripts/generate_mkdocs.py - mkdocs build --strict + python scripts/generate_book.py + cd docs && mdbook build - name: "Deploy to Cloudflare Pages" if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }} uses: cloudflare/wrangler-action@2.0.0 with: apiToken: ${{ secrets.CF_API_TOKEN }} accountId: ${{ secrets.CF_ACCOUNT_ID }} - command: pages publish site --project-name=ruff-docs --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA} + command: pages publish docs/book/ --project-name=ruff-docs --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA} diff --git a/.gitignore b/.gitignore index e13e01999aa0c2..2a0d0255d12459 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ # Local cache .ruff_cache crates/ruff/resources/test/cpython -mkdocs.yml .overrides ### @@ -160,9 +159,6 @@ venv.bak/ # Rope project settings .ropeproject -# mkdocs documentation -/site - # mypy .mypy_cache/ .dmypy.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 812f12b610e119..445681e340d13e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ Welcome! We're happy to have you here. Thank you in advance for your contributio - [Example: Adding a new lint rule](#example-adding-a-new-lint-rule) - [Rule naming convention](#rule-naming-convention) - [Example: Adding a new configuration option](#example-adding-a-new-configuration-option) -- [MkDocs](#mkdocs) +- [mdBook](#mdbook) - [Release Process](#release-process) - [Benchmarks](#benchmarks) @@ -181,21 +181,21 @@ lives in `crates/ruff/src/flake8_to_ruff/converter.rs`. Finally, regenerate the documentation and generated code with `cargo dev generate-all`. -## MkDocs +## mdBook To preview any changes to the documentation locally: -1. Install MkDocs and Material for MkDocs with: +1. Install mdBook with: ```shell - pip install -r docs/requirements.txt + cargo install mdbook ``` -2. Generate the MkDocs site with: +2. Generate the markdown files with: ```shell - python scripts/generate_mkdocs.py + python scripts/generate_book.py ``` 3. Run the development server with: ```shell - mkdocs serve + cd docs && mdbook serve ``` The documentation should then be available locally at diff --git a/crates/ruff_dev/src/generate_docs.rs b/crates/ruff_dev/src/generate_docs.rs index e95c74aa7ba69c..a6ca7e1f90c110 100644 --- a/crates/ruff_dev/src/generate_docs.rs +++ b/crates/ruff_dev/src/generate_docs.rs @@ -19,7 +19,7 @@ pub struct Args { } pub fn main(args: &Args) -> Result<()> { - let out_dir = Path::new("docs/rules"); + let out_dir = Path::new("docs/src/rules"); if !args.dry_run { fs::create_dir_all(out_dir)?; } @@ -74,7 +74,7 @@ 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}")); + after.push_str(&format!("[`{option}`]: ../settings.html#{anchor}")); continue; } diff --git a/docs/.gitignore b/docs/.gitignore index 8efd6c8dd091cd..5145b03f7acd93 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,3 +1,2 @@ -* -!assets -!requirements.txt +book +src diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md new file mode 100644 index 00000000000000..b4a5475efac411 --- /dev/null +++ b/docs/SUMMARY.md @@ -0,0 +1,10 @@ +# Summary + +- [Overview](./index.md) +- [Installation And Usage](./installation-and-usage.md) +- [Configuration](./configuration.md) +- [Rules](./rules.md) +- [Settings](./settings.md) +- [Editor Integrations](./editor-integrations.md) +- [FAQ](./faq.md) +- [Contributing](./contributing.md) diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 00000000000000..e25a008e6e0df1 --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,13 @@ +[book] +authors = ["The Ruff Developers"] +language = "en" +multilingual = false +src = "src" +title = "Ruff Documentation" + +[output.html] +git-repository-url = "https://github.com/charliermarsh/ruff" + +[output.html.fold] +enable = true +level = 0 diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index b5b1417243b463..00000000000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -mkdocs~=1.4.2 -mkdocs-material~=9.0.6 -PyYAML~=6.0 diff --git a/docs/assets/ruff-favicon.png b/docs/theme/favicon.png similarity index 100% rename from docs/assets/ruff-favicon.png rename to docs/theme/favicon.png diff --git a/docs/theme/head.hbs b/docs/theme/head.hbs new file mode 100644 index 00000000000000..340d60d8162c10 --- /dev/null +++ b/docs/theme/head.hbs @@ -0,0 +1 @@ + diff --git a/mkdocs.template.yml b/mkdocs.template.yml deleted file mode 100644 index 4ce6d30a39cefc..00000000000000 --- a/mkdocs.template.yml +++ /dev/null @@ -1,53 +0,0 @@ -site_name: Ruff -theme: - name: material - logo: assets/ruff.svg - favicon: assets/ruff-favicon.png - features: - - navigation.instant - - navigation.tracking - - content.code.annotate - - toc.integrate - - toc.follow - - navigation.path - - navigation.top - - navigation.footer - - content.code.copy - palette: - - media: "(prefers-color-scheme: light)" - scheme: default - primary: red - toggle: - icon: material/weather-sunny - name: Switch to dark mode - - media: "(prefers-color-scheme: dark)" - scheme: slate - primary: red - toggle: - icon: material/weather-night - name: Switch to light mode - custom_dir: .overrides -repo_url: https://github.com/charliermarsh/ruff -repo_name: ruff -site_author: charliermarsh -site_url: https://beta.ruff.rs/docs/ -site_dir: site/docs -markdown_extensions: - - toc: - permalink: "#" - - pymdownx.snippets: - - pymdownx.magiclink: - - attr_list: - - md_in_html: - - pymdownx.highlight: - anchor_linenums: true - - pymdownx.inlinehilite: - - pymdownx.superfences: - - markdown.extensions.attr_list: - - pymdownx.keys: - - pymdownx.tasklist: - custom_checkbox: true - - pymdownx.highlight: - anchor_linenums: true -plugins: - - search diff --git a/scripts/generate_mkdocs.py b/scripts/generate_book.py similarity index 59% rename from scripts/generate_mkdocs.py rename to scripts/generate_book.py index 71f6ddc136c278..502baf41b34544 100644 --- a/scripts/generate_mkdocs.py +++ b/scripts/generate_book.py @@ -1,11 +1,9 @@ -"""Generate an MkDocs-compatible `docs` and `mkdocs.yml` from the README.md.""" +"""Generate the Markdown files for mdbook in `docs/src`.""" import argparse import shutil import subprocess from pathlib import Path -import yaml - SECTIONS: list[tuple[str, str]] = [ ("Overview", "index.md"), ("Installation and Usage", "installation-and-usage.md"), @@ -20,14 +18,9 @@ "This README is also available as [documentation](https://beta.ruff.rs/docs/)." ) -FATHOM_SCRIPT: str = ( - '" -) - def main() -> None: - """Generate an MkDocs-compatible `docs` and `mkdocs.yml`.""" + """Generate the Markdown files for mdbook in `docs/src`.""" subprocess.run(["cargo", "dev", "generate-docs"], check=True) @@ -46,12 +39,24 @@ def main() -> None: "rules/", ) - docs_path = Path("docs") + docs_path = Path("docs/src") docs_path.mkdir(parents=True, exist_ok=True) + with (docs_path.parent / "SUMMARY.md").open("r") as f: + text = f.read() + + rules_item = "- [Rules](./rules.md)\n" + assert rules_item in text + rule_items = (f" - [{f.stem}](rules/{f.name})\n" for f in sorted(docs_path.joinpath("rules").iterdir())) + text = text.replace(rules_item, rules_item + "".join(rule_items)) + + with (docs_path / "SUMMARY.md").open("w") as f: + f.write(text) + # Split the README.md into sections. for title, filename in SECTIONS: with docs_path.joinpath(filename).open("w+") as f: + f.write(f"# {title}\n") block = content.split(f"") if len(block) != 2: msg = f"Section {title} not found in README.md" @@ -67,37 +72,10 @@ def main() -> None: # Copy the CONTRIBUTING.md. shutil.copy("CONTRIBUTING.md", docs_path / "contributing.md") - # Add the nav section to mkdocs.yml. - with Path("mkdocs.template.yml").open(encoding="utf8") as fp: - config = yaml.safe_load(fp) - config["nav"] = [ - {"Overview": "index.md"}, - {"Installation and Usage": "installation-and-usage.md"}, - {"Configuration": "configuration.md"}, - {"Rules": "rules.md"}, - {"Settings": "settings.md"}, - {"Editor Integrations": "editor-integrations.md"}, - {"FAQ": "faq.md"}, - {"Contributing": "contributing.md"}, - ] - config["extra"] = {"analytics": {"provider": "fathom"}} - - Path(".overrides/partials/integrations/analytics").mkdir( - parents=True, - exist_ok=True, - ) - with Path(".overrides/partials/integrations/analytics/fathom.html").open( - "w+", - ) as fp: - fp.write(FATHOM_SCRIPT) - - with Path("mkdocs.yml").open("w+") as fp: - yaml.safe_dump(config, fp) - if __name__ == "__main__": parser = argparse.ArgumentParser( - description="Generate an MkDocs-compatible `docs` and `mkdocs.yml`.", + description=__doc__, ) args = parser.parse_args() main()