├── .editorconfig ├── .github ├── FUNDING.yml └── workflows │ ├── build.yml │ └── docs.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── README.md ├── docs ├── assets │ ├── example.pdf │ └── example.png ├── example │ └── index.md └── index.md ├── mkdocs.yml ├── mkdocs_site_urls └── __init__.py ├── pyproject.toml ├── requirements-docs.txt ├── setup.cfg └── setup.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | indent_size = 4 8 | end_of_line = lf 9 | charset = utf-8 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | indent_style = space 13 | max_line_length = 90 14 | 15 | [*.{yaml,yml}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [foosel] 4 | patreon: foosel 5 | custom: https://octoprint.org/support-octoprint/ 6 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | pull_request: 5 | release: 6 | types: [published] 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build: 11 | name: 🔨 Build distribution 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: 🏗 Set up Python 3.11 16 | uses: actions/setup-python@v4 17 | with: 18 | python-version: "3.11" 19 | - name: 🏗 Install build dependencies 20 | run: | 21 | python -m pip install wheel --user 22 | - name: 🔨 Build a binary wheel and a source tarball 23 | run: | 24 | python setup.py sdist bdist_wheel 25 | - name: ⬆ Upload build result 26 | uses: actions/upload-artifact@v4 27 | with: 28 | name: dist 29 | path: dist 30 | 31 | pre-commit: 32 | name: 🧹 Pre-commit 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v3 36 | - name: 🏗 Set up Python 3.11 37 | uses: actions/setup-python@v4 38 | with: 39 | python-version: "3.11" 40 | - name: 🏗 Set up dev dependencies 41 | run: | 42 | pip install pre-commit 43 | - name: 🚀 Run pre-commit 44 | run: | 45 | pre-commit run --all-files --show-diff-on-failure 46 | 47 | publish-on-pypi: 48 | name: 📦 Publish tagged releases to PyPI 49 | if: github.event_name == 'release' && github.repository == 'OctoPrint/mkdocs-site-urls' 50 | needs: 51 | - build 52 | - pre-commit 53 | runs-on: ubuntu-latest 54 | environment: release 55 | permissions: 56 | id-token: write 57 | steps: 58 | - name: ⬇ Download build result 59 | uses: actions/download-artifact@v4 60 | with: 61 | name: dist 62 | path: dist 63 | - name: 📦 Publish to index 64 | uses: pypa/gh-action-pypi-publish@release/v1 65 | with: 66 | password: ${{ secrets.pypi_token }} 67 | -------------------------------------------------------------------------------- /.github/workflows/docs.yaml: -------------------------------------------------------------------------------- 1 | name: Build & publish docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 10 | permissions: 11 | contents: read 12 | pages: write 13 | id-token: write 14 | 15 | jobs: 16 | build: 17 | name: Build 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: ⬇ Checkout 21 | uses: actions/checkout@v3 22 | 23 | - name: 🐍 Set up Python 3.11 24 | uses: actions/setup-python@v4 25 | with: 26 | python-version: "3.11" 27 | 28 | - name: 🐍 Preinstall some build dependencies 29 | run: | 30 | pip install --upgrade pip 31 | pip install -r requirements-docs.txt 32 | 33 | - name: 🏗 Build docs 34 | run: | 35 | mkdocs build 36 | env: 37 | SITE_URL: https://octoprint.github.io/mkdocs-site-urls/ 38 | 39 | - name: ⬆ Upload pages artifact 40 | uses: actions/upload-pages-artifact@v1 41 | with: 42 | path: ./site 43 | 44 | deploy: 45 | name: Deploy 46 | runs-on: ubuntu-latest 47 | needs: build 48 | 49 | environment: 50 | name: github-pages 51 | url: ${{ steps.deployment.outputs.page_url }} 52 | 53 | steps: 54 | - name: 🚀 Deploy to GitHub Pages 55 | id: deployment 56 | uses: actions/deploy-pages@v1 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | dist 3 | *.egg-info 4 | *.egg 5 | __pycache__ 6 | *.pyc 7 | *.pyo 8 | *.pyd 9 | venv 10 | site 11 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | default_language_version: 2 | python: python3.11 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v4.4.0 6 | hooks: 7 | - id: end-of-file-fixer 8 | - id: trailing-whitespace 9 | - id: check-case-conflict 10 | - id: check-merge-conflict 11 | - id: fix-encoding-pragma 12 | args: ["--remove"] 13 | - repo: https://github.com/asottile/pyupgrade 14 | rev: v3.9.0 15 | hooks: 16 | - id: pyupgrade 17 | args: ["--py37-plus"] 18 | - repo: https://github.com/pre-commit/mirrors-isort 19 | rev: v5.10.1 20 | hooks: 21 | - id: isort 22 | - repo: https://github.com/psf/black 23 | rev: 23.7.0 24 | hooks: 25 | - id: black 26 | - repo: https://github.com/pycqa/flake8 27 | rev: 6.0.0 28 | hooks: 29 | - id: flake8 30 | args: [--config=setup.cfg] 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Gina Häußge 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MkDocs Site URLs Plugin 2 | 3 | ![GitHub release](https://img.shields.io/github/v/release/OctoPrint/mkdocs-site-urls?logo=github&logoColor=white) 4 | ![PyPI](https://img.shields.io/pypi/v/mkdocs-site-urls?logo=python&logoColor=white) 5 | ![Build status](https://img.shields.io/github/actions/workflow/status/OctoPrint/mkdocs-site-urls/build.yml?branch=main) 6 | [![Code of Conduct](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](https://octoprint.org/conduct/) 7 | [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) 8 | [![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1)](https://pycqa.github.io/isort/) 9 | [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) 10 | 11 | A MkDocs plugin that adds support for site-relative `site:` URLs. 12 | 13 | Example: 14 | 15 | | URL | site_url | resulting URL | 16 | | --- | -------- | ------------- | 17 | | `site:images/foo.png` | `https://example.com/` | `/images/foo.png` | 18 | | `site:images/foo.png` | `https://example.com/bar/` | `/bar/images/foo.png` | 19 | 20 | **Please note**: This plugin requires MkDocs 1.5 or higher. 21 | 22 | ## Getting Started 23 | 24 | 1. Install the plugin from PyPI 25 | ```bash 26 | pip install mkdocs-site-urls 27 | ``` 28 | 2. Add the `site-urls` plugin to your `mkdocs.yml` plugins section: 29 | ```yaml 30 | plugins: 31 | - site-urls 32 | ``` 33 | 3. Start using site-relative URLs in your Markdown files by prefixing them with `site:`: 34 | ```markdown 35 | [Link to another page](site:another-page/relative/to/the/site/root) 36 | 37 | ![Image](site:images/foo.png) 38 | ``` 39 | 40 | ## Configuration 41 | 42 | By default the plugin will replace URLs in `href`, `src` and `data` attributes. You can configure the attributes to replace 43 | by setting the `attributes` option in your `mkdocs.yml`, e.g.: 44 | 45 | ```yaml 46 | plugins: 47 | - site-urls: 48 | attributes: 49 | - href 50 | - src 51 | - data 52 | - data-url 53 | ``` 54 | 55 | Be advised that in case of any customization on your part you need to include the default attributes as well if you want 56 | to keep them, as the default list will not be included automatically anymore. 57 | 58 | ## How it works 59 | 60 | The plugin hooks into the [`on_page_content` event](https://www.mkdocs.org/dev-guide/plugins/#on_page_content) 61 | and replaces all URLs in the configured attributes (by default `href`, `src` or `data`) in the rendered HTML with the corresponding site-relative URLs. 62 | 63 | ## License 64 | 65 | This project is licensed under the MIT license, see the [LICENSE](https://github.com/OctoPrint/mkdocs-site-urls/blob/main/LICENSE) file for details. 66 | -------------------------------------------------------------------------------- /docs/assets/example.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OctoPrint/mkdocs-site-urls/4caef2b8ec66e04a40dfc07b8b7644d1eb582734/docs/assets/example.pdf -------------------------------------------------------------------------------- /docs/assets/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OctoPrint/mkdocs-site-urls/4caef2b8ec66e04a40dfc07b8b7644d1eb582734/docs/assets/example.png -------------------------------------------------------------------------------- /docs/example/index.md: -------------------------------------------------------------------------------- 1 | # Example 2 | 3 | !!! example 4 | 5 | === "Markdown" 6 | 7 | ``` 8 | [link to README](site:.) 9 | 10 | ![example image](site:assets/example.png) 11 | 12 | 13 | ``` 14 | 15 | === "Output" 16 | 17 | [link to README](site:.) 18 | 19 | ![example image](site:assets/example.png) 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | {% 2 | include-markdown "../README.md" 3 | %} 4 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: MkDocs Site URLs Plugin 2 | site_url: !ENV [SITE_URL, "http://127.0.0.1:8000"] 3 | dev_addr: 127.0.0.1:8000 4 | repo_name: OctoPrint/mkdocs-site-urls 5 | repo_url: https://github.com/OctoPrint/mkdocs-site-urls 6 | 7 | nav: 8 | - README: index.md 9 | - Examples: example/index.md 10 | 11 | theme: 12 | name: material 13 | palette: 14 | # Palette toggle for light mode 15 | - scheme: default 16 | toggle: 17 | icon: material/brightness-7 18 | name: Switch to dark mode 19 | 20 | # Palette toggle for dark mode 21 | - scheme: slate 22 | toggle: 23 | icon: material/brightness-4 24 | name: Switch to light mode 25 | 26 | plugins: 27 | - include-markdown 28 | - search 29 | - site-urls: 30 | attributes: 31 | - src 32 | - href 33 | - data 34 | - data-src 35 | 36 | markdown_extensions: 37 | - admonition 38 | - pymdownx.details 39 | - pymdownx.superfences 40 | - pymdownx.tabbed: 41 | alternate_style: true 42 | 43 | watch: 44 | - docs 45 | - mkdocs.yml 46 | - README.md 47 | -------------------------------------------------------------------------------- /mkdocs_site_urls/__init__.py: -------------------------------------------------------------------------------- 1 | import re 2 | import urllib.parse 3 | 4 | import mkdocs.plugins 5 | from mkdocs.config import config_options as c 6 | from mkdocs.config.defaults import MkDocsConfig 7 | 8 | logger = mkdocs.plugins.get_plugin_logger(__name__) 9 | 10 | 11 | class SiteUrlsConfig(mkdocs.config.base.Config): 12 | attributes = c.Type(list, default=["href", "src", "data"]) 13 | 14 | 15 | class SiteUrlsPlugin(mkdocs.plugins.BasePlugin[SiteUrlsConfig]): 16 | def on_pre_build(self, *, config: MkDocsConfig) -> None: 17 | self._regex = re.compile( 18 | r"(" + "|".join(self.config["attributes"]) + r')="site:([^"]+)"', 19 | re.IGNORECASE, 20 | ) 21 | 22 | @mkdocs.plugins.event_priority(50) 23 | def on_page_content(self, html, page, config, files): 24 | site_url = config["site_url"] 25 | path = urllib.parse.urlparse(site_url).path 26 | 27 | if not path: 28 | path = "/" 29 | if not path.endswith("/"): 30 | path += "/" 31 | 32 | def _replace(match): 33 | param = match.group(1) 34 | url = match.group(2) 35 | if url.startswith("/"): 36 | url = url[1:] 37 | 38 | logger.info(f"Replacing site:{match.group(2)} with {path}{url}") 39 | return f'{param}="{path}{url}"' 40 | 41 | return self._regex.sub(_replace, html) 42 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=40.8.0", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.black] 6 | line-length = 90 7 | -------------------------------------------------------------------------------- /requirements-docs.txt: -------------------------------------------------------------------------------- 1 | mkdocs>=1.5.0 2 | mkdocs-material 3 | mkdocs-include-markdown-plugin 4 | -e . 5 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | license_file = LICENSE 3 | 4 | [bdist_wheel] 5 | universal = 1 6 | 7 | [flake8] 8 | max-line-length = 90 9 | extend-ignore = E203, E231, E265, E266, E402, E501, E731, B023, B903, B904, B907, B950, W503 10 | select = B,C,E,F,W,T4,B9 11 | 12 | [isort] 13 | multi_line_output = 3 14 | include_trailing_comma = True 15 | force_grid_wrap = 0 16 | use_parentheses = True 17 | ensure_newline_before_comments = True 18 | line_length = 90 19 | known_first_party = 20 | mkdocs_site_urls 21 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | with open("README.md", encoding="utf-8") as f: 4 | long_description = f.read() 5 | 6 | setup( 7 | name="mkdocs-site-urls", 8 | version="0.2.0", 9 | author="Gina Häußge", 10 | author_email="gina@octoprint.org", 11 | url="https://github.com/OctoPrint/mkdocs-site-urls", 12 | project_urls={"Source": "https://github.com/OctoPrint/mkdocs-site-urls"}, 13 | keywords=["mkdocs", "plugin"], 14 | packages=find_packages(), 15 | license="MIT", 16 | description="A MkDocs plugin that adds support for site-relative URLs", 17 | long_description=long_description, 18 | long_description_content_type="text/markdown", 19 | include_package_data=True, 20 | python_requires=">=3.7", 21 | entry_points={"mkdocs.plugins": ["site-urls = mkdocs_site_urls:SiteUrlsPlugin"]}, 22 | ) 23 | --------------------------------------------------------------------------------