diff --git a/cookiecutter.json b/cookiecutter.json index 3fdda2c9..26a671c4 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -7,9 +7,13 @@ "package_name": "{{cookiecutter.project_slug.replace('-', '_')}}", "project_short_description": "A cookiecutter template with ARC recommendations.", "initialise_git_repository": true, + "deploy_docs_to_github_pages": false, "github_username": "{{cookiecutter.author_given_names.lower().replace(' ', '-')}}-{{cookiecutter.author_family_names.lower().replace(' ', '-')}}", "min_python_version": ["3.9", "3.10", "3.11", "3.12"], "max_python_version": ["3.12", "3.11", "3.10", "3.9"], "license": ["MIT", "BSD-3", "GPL-3.0"], - "funder": "JBFC: The Joe Bloggs Funding Council" + "funder": "JBFC: The Joe Bloggs Funding Council", + "__prompts__": { + "deploy_docs_to_github_pages": "Enable automatically deploying HTML documentation to GitHub Pages website on pushes to main" + } } diff --git a/tests/test_package_gen.py b/tests/test_package_gen.py index f0862345..7d4d8516 100644 --- a/tests/test_package_gen.py +++ b/tests/test_package_gen.py @@ -56,6 +56,9 @@ def test_package_generation( "tests", pathlib.Path(".github"), pathlib.Path(".github") / "workflows", + "mkdocs.yml", + pathlib.Path("docs") / "index.md", + pathlib.Path("docs") / "api.md", ] for f in expected_files: full_path = test_project_dir / f diff --git a/{{cookiecutter.project_slug}}/.github/workflows/docs.yml b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml new file mode 100644 index 00000000..12235db0 --- /dev/null +++ b/{{cookiecutter.project_slug}}/.github/workflows/docs.yml @@ -0,0 +1,48 @@ +name: Documentation + +on: + push: + branches: + - main + pull_request: + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - name: Checkout source + uses: actions/checkout@v4 + + - name: Cache tox + uses: actions/cache@v4 + with: + path: .tox + key: tox-${{ '{{' }} hashFiles('pyproject.toml') {{ '}}' }} + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.x" + cache: "pip" + cache-dependency-path: "pyproject.toml" + + - name: Install tox + run: python -m pip install tox + - name: Build HTML documentation with tox + run: tox -e docs +{%- if cookiecutter.deploy_docs_to_github_pages %} + + # Automatically deploy documentation to a GitHub Pages website on pushing to main. + # Requires configuring the repository to deploy GitHub pages from a branch + # gh-pages (https://tinyurl.com/gh-pages-from-branch), which will be created the + # first time this workflow step is run. + - name: Publish documentation on GitHub pages + if: success() && github.event_name != 'pull_request' + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ '{{' }} secrets.GITHUB_TOKEN {{ '}}' }} + publish_dir: site + publish_branch: gh-pages + user_name: "github-actions[bot]" + user_email: "github-actions[bot]@users.noreply.github.com" +{%- endif %} diff --git a/{{cookiecutter.project_slug}}/README.md b/{{cookiecutter.project_slug}}/README.md index 847480f7..12262a0f 100644 --- a/{{cookiecutter.project_slug}}/README.md +++ b/{{cookiecutter.project_slug}}/README.md @@ -3,6 +3,7 @@ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) [![Tests status][tests-badge]][tests-link] [![Linting status][linting-badge]][linting-link] +[![Documentation status][documentation-badge]][documentation-link] [![License][license-badge]](./LICENSE.md) -[Framework 1](https://something.com) -[Framework 2](https://something.com) -[Framework 3](https://something.com) +- [Framework 1](https://something.com) +- [Framework 2](https://something.com) +- [Framework 3](https://something.com) ## Getting Started @@ -108,6 +111,24 @@ pytest tests again from the root of the repository. +### Building Documentation + +The MkDocs HTML documentation can be built locally by running + +```sh +tox -e docs +``` + +from the root of the repository. +The built documentation will be written to `site`. + +Alternatively to build and preview the documentation locally, in a Python environment +with the optional `docs` dependencies installed, run + +```sh +mkdocs serve +``` + ## Roadmap - [x] Initial Research diff --git a/{{cookiecutter.project_slug}}/docs/LICENSE.md b/{{cookiecutter.project_slug}}/docs/LICENSE.md new file mode 100644 index 00000000..606f09a3 --- /dev/null +++ b/{{cookiecutter.project_slug}}/docs/LICENSE.md @@ -0,0 +1,3 @@ +{! +include-markdown "../LICENSE.md" +!} diff --git a/{{cookiecutter.project_slug}}/docs/api.md b/{{cookiecutter.project_slug}}/docs/api.md new file mode 100644 index 00000000..eb5f8c56 --- /dev/null +++ b/{{cookiecutter.project_slug}}/docs/api.md @@ -0,0 +1,3 @@ +# API reference + +::: {{cookiecutter.package_name}} diff --git a/{{cookiecutter.project_slug}}/docs/index.md b/{{cookiecutter.project_slug}}/docs/index.md new file mode 100644 index 00000000..61196b9f --- /dev/null +++ b/{{cookiecutter.project_slug}}/docs/index.md @@ -0,0 +1,4 @@ +{! +include-markdown "../README.md" +rewrite-relative-urls=false +!} diff --git a/{{cookiecutter.project_slug}}/mkdocs.yml b/{{cookiecutter.project_slug}}/mkdocs.yml new file mode 100644 index 00000000..36b2bb3f --- /dev/null +++ b/{{cookiecutter.project_slug}}/mkdocs.yml @@ -0,0 +1,61 @@ +site_name: "{{cookiecutter.project_name}}" +site_description: "Documentation website for {{cookiecutter.project_name}}" +site_author: "{{cookiecutter.author_given_names}} {{cookiecutter.author_family_names}}" +copyright: "Copyright © {% now 'utc', '%Y' %} {{cookiecutter.author_given_names}} {{cookiecutter.author_family_names}}" +repo_url: "https://github.com/{{cookiecutter.github_username}}/{{cookiecutter.project_slug}}/" +repo_name: "{{cookiecutter.github_username}}/{{cookiecutter.project_slug}}" +edit_uri: edit/main/docs/ + +validation: + omitted_files: warn + absolute_links: warn + unrecognized_links: warn + +theme: + name: "material" + features: + - content.action.edit + palette: + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to system preference + icon: + repo: fontawesome/brands/github + +nav: + - Overview: index.md + - API reference: api.md + - License: LICENSE.md + +markdown_extensions: + - pymdownx.tasklist + +plugins: + - search + - mkdocstrings: + default_handler: python + handlers: + python: + docstring_style: google + import: + - "https://docs.python.org/3/objects.inv" + paths: [src] + - include-markdown: + opening_tag: "{!" + closing_tag: "!}" + +extra: + social: + - icon: fontawesome/brands/github + link: "https://github.com/{{cookiecutter.github_username}}" diff --git a/{{cookiecutter.project_slug}}/pyproject.toml b/{{cookiecutter.project_slug}}/pyproject.toml index ce13c8ff..8f3f2d10 100644 --- a/{{cookiecutter.project_slug}}/pyproject.toml +++ b/{{cookiecutter.project_slug}}/pyproject.toml @@ -37,6 +37,12 @@ optional-dependencies = {dev = [ "ruff", "tox", "twine", +], docs = [ + "mkdocs", + "mkdocs-include-markdown-plugin", + "mkdocs-material", + "mkdocstrings", + "mkdocstrings-python", ], test = [ "pytest", "pytest-cov", @@ -123,6 +129,12 @@ legacy_tox_ini = """ extras = test + [testenv:docs] + commands = + mkdocs build --strict + extras = + docs + [tox] env_list = {%- for python_version in range( diff --git a/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py b/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py index e6dfdbd4..7b895c37 100644 --- a/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py +++ b/{{cookiecutter.project_slug}}/src/{{cookiecutter.package_name}}/__init__.py @@ -1,2 +1,17 @@ """{{cookiecutter.package_name}} package.""" from ._version import __version__ # noqa: F401 + + +def example_function(argument: str, keyword_argument: str = "default") -> str: + """ + Concatenate string arguments - an example function docstring. + + Args: + argument: An argument. + keyword_argument: A keyword argument with a default value. + + Returns: + The concatenation of `argument` and `keyword_argument`. + + """ + return argument + keyword_argument