diff --git a/.gitattributes b/.gitattributes index 2f41707..8425c58 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -*.ipynb filter=strip-notebook-output +*.ipynb filter=strip-notebook-output diff --git a/.github/actions/build-docs/action.yml b/.github/actions/build-docs/action.yml new file mode 100644 index 0000000..d1f3ec6 --- /dev/null +++ b/.github/actions/build-docs/action.yml @@ -0,0 +1,42 @@ +name: "Build Documentation" +description: "Build Sphinx documentation" +inputs: + python-version: + description: "Python version to use" + required: false + default: "3.10" + treat-warnings-as-errors: + description: "Treat warnings as errors (-W flag)" + required: false + default: "false" +runs: + using: "composite" + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + + - name: Install pandoc + shell: bash + run: | + apt-get update + apt-get install -y pandoc + + - name: Check if pdflatex is available + shell: bash + run: | + which pdflatex + pdflatex --version + + - name: Install Python dependencies + shell: bash + run: | + python -m pip install --upgrade pip + pip install ".[docs]" + + - name: Build Sphinx docs + shell: bash + run: | + cd docs + make html diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index bdb095b..0000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: Deploy docs to GitHub Pages - -on: - push: - branches: ["devel"] # TODO: Set to main only after release - workflow_dispatch: - -defaults: - run: - shell: bash - -permissions: - contents: read - pages: write - id-token: write - -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - build-and-deploy: - runs-on: ubuntu-latest - container: - image: texlive/texlive:latest - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - - name: Cache pip - uses: actions/cache@v3 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Install pandoc - run: | - apt-get update - apt-get install -y pandoc - - # - name: Install TeX Live with pdflatex - # run: | - # sudo apt-get update - # sudo apt-get install -y texlive-full - # sudo apt-get install -y texlive texlive-latex-base texlive-latex-extra texlive-fonts-recommended texlive-science - - - name: Check if pdflatex is available - run: | - which pdflatex - pdflatex --version - - - name: Set up virtual environment and install project - run: | - python -m venv env - source env/bin/activate - pip install --upgrade pip - pip install ".[test, dev, docs]" - - - name: Build Sphinx docs - run: | - source env/bin/activate - cd docs - make html - - - name: Setup Pages - uses: actions/configure-pages@v5 - - - name: Upload built docs - uses: actions/upload-pages-artifact@v3 - with: - path: docs/build/html/ - - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index eaff1cd..2e65b3f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -31,4 +31,3 @@ jobs: TWINE_USERNAME: __token__ # Use API token TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} run: twine upload dist/* - diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml new file mode 100644 index 0000000..31aefb8 --- /dev/null +++ b/.github/workflows/publish_docs.yml @@ -0,0 +1,46 @@ +name: Deploy docs to GitHub Pages + +on: + push: + branches: ["devel"] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + container: + image: texlive/texlive:latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build documentation + uses: ./.github/actions/build-docs + with: + python-version: "3.10" + treat-warnings-as-errors: "false" + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload built docs + uses: actions/upload-pages-artifact@v3 + with: + path: docs/build/html/ + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml new file mode 100644 index 0000000..a376459 --- /dev/null +++ b/.github/workflows/publish_pypi.yml @@ -0,0 +1,36 @@ +name: Publish Python Package + +on: + push: + branches: + - main + +jobs: + build-and-publish: + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/project/tikzpics/ + permissions: + id-token: write + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install build tools + run: | + python -m pip install --upgrade pip + pip install build + + - name: Build the package + run: python -m build + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 61b3cb6..fce5a85 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -15,42 +15,32 @@ defaults: shell: bash jobs: - cloc: + pre-commit: runs-on: ubuntu-latest steps: - name: Checkout the code uses: actions/checkout@v4 - - name: Download and run cloc - run: | - curl -s https://raw.githubusercontent.com/AlDanial/cloc/master/cloc > cloc - chmod +x cloc - ./cloc --version - ./cloc $(git ls-files) - - black: - runs-on: ubuntu-latest - steps: - - name: Checkout the code - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" - - name: Code formatting with black - run: | - pip install black "black[jupyter]" - black --check src/ - black --check tutorials/ + - name: Run pre-commit + uses: pre-commit/action@v3.0.1 - isort: + cloc: runs-on: ubuntu-latest steps: - name: Checkout the code uses: actions/checkout@v4 - - name: Code formatting with isort + - name: Download and run cloc run: | - pip install isort - isort --check src/ - isort --check tutorials/ + curl -s https://raw.githubusercontent.com/AlDanial/cloc/master/cloc > cloc + chmod +x cloc + ./cloc --version + ./cloc $(git ls-files) mypy: runs-on: ubuntu-latest @@ -59,43 +49,12 @@ jobs: - name: Checkout the code uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + - name: Type checking with mypy run: | pip install mypy mypy src/ || true - - prospector: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - name: Checkout the code - uses: actions/checkout@v4 - - - name: Code analysis with prospector - run: | - pip install prospector - prospector src/ || true - - ruff: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - name: Checkout the code - uses: actions/checkout@v4 - - - name: Linting with ruff - run: | - pip install ruff - ruff check src/ || true - - pylint: - runs-on: ubuntu-latest - continue-on-error: true - steps: - - name: Checkout the code - uses: actions/checkout@v4 - - - name: Linting with pylint - run: | - pip install pylint - pylint src/ || true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3025731..f8d1285 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,7 @@ jobs: key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} restore-keys: | ${{ runner.os }}-pip- - + - name: Install pandoc run: | apt-get update @@ -106,4 +106,3 @@ jobs: - name: Build the package run: python -m build - diff --git a/.github/workflows/test_docs.yml b/.github/workflows/test_docs.yml new file mode 100644 index 0000000..413bd1a --- /dev/null +++ b/.github/workflows/test_docs.yml @@ -0,0 +1,39 @@ +name: Test Documentation Build + +on: + push: + branches: + - main + - devel + pull_request: + branches: + - main + - devel + +defaults: + run: + shell: bash + +jobs: + test-docs: + runs-on: ubuntu-latest + container: + image: texlive/texlive:latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build documentation + uses: ./.github/actions/build-docs + with: + python-version: "3.10" + treat-warnings-as-errors: "true" + + - name: Upload docs artifact + uses: actions/upload-artifact@v4 + if: always() + with: + name: documentation + path: docs/build/html/ + retention-days: 7 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7de373c..d0b7c87 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,4 +54,3 @@ deploy: stage: deploy script: echo "Define your deployment script!" environment: production - diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af67085..61316d0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,15 +1,21 @@ +--- repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 # Use the latest stable version + rev: v6.0.0 hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace - id: check-added-large-files # Prevent giant files from being committed. - args: ["--maxkb=1000"] - - id: check-merge-conflict # Check for files that contain merge conflict strings. - - id: check-toml # Attempts to load all TOML files to verify syntax. - - id: check-yaml # Attempts to load all yaml files to verify syntax. - args: ["--unsafe"] - + args: [--maxkb=500] + - id: check-merge-conflict # Check for files that contain merge conflict strings. - repo: https://github.com/kynan/nbstripout - rev: 0.8.1 + rev: 0.9.0 hooks: - - id: nbstripout # remove jupyter notebook cell output + - id: nbstripout # strip jupyter noteook output + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.9.1 + hooks: + - id: ruff + args: [--fix, --select, I] + - id: ruff-format diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css new file mode 100644 index 0000000..fb0ac08 --- /dev/null +++ b/docs/source/_static/custom.css @@ -0,0 +1,93 @@ +/* Improved toctree styling */ + +/* Main page toctree container */ +.toctree-wrapper { + margin: 2rem 0; +} + +/* Toctree list styling */ +.toctree-wrapper ul { + padding-left: 0; + list-style: none; +} + +/* Toctree list items */ +.toctree-wrapper li { + margin: 0.4rem 0; + padding: 0.6rem 1rem; + border-bottom: 1.5px solid #c5d1e0; + border-left: 3px solid transparent; + transition: all 0.2s ease; +} + +.toctree-wrapper li:hover { + border-left-color: #4f46e5; + background: rgba(79, 70, 229, 0.03); +} + +.toctree-wrapper li:last-child { + border-bottom: 1.5px solid #c5d1e0; +} + +/* Toctree links */ +.toctree-wrapper a.reference { + font-size: 1.1rem; + font-weight: 500; + color: #1a365d; + text-decoration: none; + display: inline-block; + transition: all 0.2s ease; + padding: 0.25rem 0; +} + +.toctree-wrapper a.reference:hover { + color: #2563eb; + transform: translateX(5px); +} + +/* Nested toctree items */ +.toctree-wrapper ul ul { + padding-left: 1.5rem; + margin-top: 0.3rem; +} + +.toctree-wrapper ul ul li { + margin: 0.25rem 0; + padding: 0.4rem 0.8rem; + border-bottom: 1px solid #dce4f0; + border-left: 2px solid transparent; +} + +.toctree-wrapper ul ul li:hover { + border-left-color: #6366f1; + background: rgba(99, 102, 241, 0.03); +} + +.toctree-wrapper ul ul a.reference { + font-size: 1rem; + font-weight: 400; + color: #4a5568; +} + +.toctree-wrapper ul ul a.reference:hover { + color: #4f46e5; +} + +/* Toctree caption */ +.toctree-wrapper p.caption { + font-size: 1.3rem; + font-weight: 600; + color: #1e3a5f; + margin-bottom: 1rem; + padding-bottom: 0.5rem; + border-bottom: 3px solid #4f46e5; +} + +/* Improve spacing on main page */ +div.section > .toctree-wrapper { + background: linear-gradient(135deg, #f0f4f8 0%, #e8eef5 100%); + padding: 1.5rem; + border-radius: 12px; + box-shadow: 0 4px 6px rgba(79, 70, 229, 0.08); + border: 1px solid #dce4f0; +} diff --git a/docs/source/api.md b/docs/source/api.md deleted file mode 100644 index a1c08b6..0000000 --- a/docs/source/api.md +++ /dev/null @@ -1,6 +0,0 @@ -# API - -Description of the API - -```{toctree} -:maxdepth: 1 \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 5f47608..c8db3c9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -2,136 +2,100 @@ # # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html - import os import shutil +import sys +from pathlib import Path -# At the top. -import sphinx_bootstrap_theme - - -def copy_tutorials(app): - src = os.path.abspath("../tutorials") - dst = os.path.abspath("source/tutorials") - - # Remove existing target directory if it exists - if os.path.exists(dst): - shutil.rmtree(dst) +sys.path.insert(0, os.path.abspath("../src")) - shutil.copytree(src, dst) +# Copy tutorial notebooks from project root to docs/source/tutorials/ +tutorials_source = Path(__file__).parent.parent.parent / "tutorials" +tutorials_dest = Path(__file__).parent / "tutorials" - -def setup(app): - app.connect("builder-inited", copy_tutorials) - # app.add_stylesheet("my-styles.css") - app.add_css_file("custom.css") +if tutorials_source.exists(): + tutorials_dest.mkdir(exist_ok=True) + for notebook in tutorials_source.glob("*.ipynb"): + shutil.copy2(notebook, tutorials_dest / notebook.name) # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = "tikzpics" -copyright = "2025, Max Lindqvist" -author = "Max Lindqvist" +copyright = "2025, Max" +author = "Max" # -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. extensions = [ - "nbsphinx", - "sphinx.ext.mathjax", "sphinx.ext.autodoc", - "myst_parser", # enable Markdown support + "sphinx.ext.autosummary", + "sphinx.ext.viewcode", + "sphinx.ext.napoleon", + "sphinxcontrib.mermaid", + "sphinx_design", + "nbsphinx", ] -exclude_patterns = [] +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] -# Recognize both .rst and .md -source_suffix = { - ".rst": "restructuredtext", - ".md": "markdown", -} +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**/.ipynb_checkpoints"] -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +# nbsphinx configuration +nbsphinx_execute = "always" # Execute notebooks during build -# html_theme = "furo" -# conf.py -# ... -# Activate the theme. -html_theme = "bootstrap" -html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() +# -- Options for HTML output ------------------------------------------------- -# (Optional) Logo. Should be small enough to fit the navbar (ideally 24x24). -# Path should be relative to the ``_static`` files directory. -# html_logo = "my_logo.png" +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_book_theme" -# Theme options are theme-specific and customize the look and feel of a -# theme further. html_theme_options = { - # Navigation bar title. (Default: ``project`` value) - "navbar_title": "python-template", - # Tab name for entire site. (Default: "Site") - "navbar_site_name": "Site", - # A list of tuples containing pages or urls to link to. - # Valid tuples should be in the following forms: - # (name, page) # a link to a page - # (name, "/aa/bb", 1) # a link to an arbitrary relative url - # (name, "http://example.com", True) # arbitrary absolute url - # Note the "1" or "True" value above as the third argument to indicate - # an arbitrary url. - "navbar_links": [ - ("Quickstart", "quickstart"), - ("Tutorials", "tutorials"), - ("API", "api"), - # ("Link", "http://example.com", True), + "repository_branch": "devel", + "show_toc_level": 2, + "secondary_sidebar_items": ["page-toc"], + "use_sidenotes": True, + "home_page_in_toc": True, + "collapse_navigation": False, + "navigation_depth": 2, + "icon_links": [ + { + "name": "GitHub", + "url": "https://github.com/max-models/tikzpics/", + "icon": "fab fa-github", + "type": "fontawesome", + }, + { + "name": "⭐ Star us!", + "url": "https://github.com/max-models/tikzpics/", + "icon": "fas fa-star", + "type": "fontawesome", + }, ], - # Render the next and previous page links in navbar. (Default: true) - "navbar_sidebarrel": False, - # Render the current pages TOC in the navbar. (Default: true) - "navbar_pagenav": False, - # Tab name for the current pages TOC. (Default: "Page") - "navbar_pagenav_name": "Page", - # Global TOC depth for "site" navbar tab. (Default: 1) - # Switching to -1 shows all levels. - "globaltoc_depth": 2, - # Include hidden TOCs in Site navbar? - # - # Note: If this is "false", you cannot have mixed ``:hidden:`` and - # non-hidden ``toctree`` directives in the same page, or else the build - # will break. - # - # Values: "true" (default) or "false" - "globaltoc_includehidden": "true", - # HTML navbar class (Default: "navbar") to attach to