{"id":13472437,"url":"https://github.com/mkdocstrings/autorefs","last_synced_at":"2025-05-16T09:04:34.509Z","repository":{"id":39595643,"uuid":"337651663","full_name":"mkdocstrings/autorefs","owner":"mkdocstrings","description":"Automatically link across pages in MkDocs.","archived":false,"fork":false,"pushed_at":"2025-03-08T13:34:46.000Z","size":1719,"stargazers_count":65,"open_issues_count":2,"forks_count":11,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-12T13:53:35.650Z","etag":null,"topics":["anchor","cross-linking","cross-references","mkdocs","mkdocs-plugin","mkdocstrings"],"latest_commit_sha":null,"homepage":"https://mkdocstrings.github.io/autorefs/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkdocstrings.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"pawamoy","polar":"pawamoy"}},"created_at":"2021-02-10T07:44:02.000Z","updated_at":"2025-04-04T17:48:01.000Z","dependencies_parsed_at":"2024-02-27T13:30:23.290Z","dependency_job_id":"e7c6adef-e15b-405e-997c-84b8ef1ea639","html_url":"https://github.com/mkdocstrings/autorefs","commit_stats":{"total_commits":71,"total_committers":9,"mean_commits":7.888888888888889,"dds":0.5915492957746479,"last_synced_commit":"40940c591e9cc557573ccd35351ca2b535ec371b"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkdocstrings%2Fautorefs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkdocstrings%2Fautorefs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkdocstrings%2Fautorefs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkdocstrings%2Fautorefs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkdocstrings","download_url":"https://codeload.github.com/mkdocstrings/autorefs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254501557,"owners_count":22081528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anchor","cross-linking","cross-references","mkdocs","mkdocs-plugin","mkdocstrings"],"created_at":"2024-07-31T16:00:54.622Z","updated_at":"2025-05-16T09:04:29.494Z","avatar_url":"https://github.com/mkdocstrings.png","language":"Python","funding_links":["https://github.com/sponsors/pawamoy","https://polar.sh/pawamoy"],"categories":["Python"],"sub_categories":[],"readme":"# mkdocs-autorefs\n\n[![ci](https://github.com/mkdocstrings/autorefs/workflows/ci/badge.svg)](https://github.com/mkdocstrings/autorefs/actions?query=workflow%3Aci)\n[![documentation](https://img.shields.io/badge/docs-mkdocs-708FCC.svg?style=flat)](https://mkdocstrings.github.io/autorefs/)\n[![pypi version](https://img.shields.io/pypi/v/mkdocs-autorefs.svg)](https://pypi.org/project/mkdocs-autorefs/)\n[![conda version](https://img.shields.io/conda/vn/conda-forge/mkdocs-autorefs.svg)](https://anaconda.org/conda-forge/mkdocs-autorefs)\n[![gitpod](https://img.shields.io/badge/gitpod-workspace-708FCC.svg?style=flat)](https://gitpod.io/#https://github.com/mkdocstrings/autorefs)\n[![gitter](https://badges.gitter.im/join%20chat.svg)](https://app.gitter.im/#/room/#autorefs:gitter.im)\n\nAutomatically link across pages in MkDocs.\n\n## Installation\n\n```bash\npip install mkdocs-autorefs\n```\n\n## Usage\n\n```yaml\n# mkdocs.yml\nplugins:\n- search\n- autorefs\n```\n\nIn one of your Markdown files (e.g. `doc1.md`) create some headings:\n\n```markdown\n## Hello, world!\n\n## Another heading\n\nLink to [Hello, World!](#hello-world) on the same page.\n```\n\nThis is a [*normal* link to an anchor](https://www.mkdocs.org/user-guide/writing-your-docs/#linking-to-pages). MkDocs generates anchors for each heading, and they can always be used to link to something, either within the same page (as shown here) or by specifying the path of the other page.\n\nBut with this plugin, you can **link to a heading from any other page** on the site *without* needing to know the path of either of the pages, just the heading title itself.\n\nLet's create another Markdown page to try this, `subdir/doc2.md`:\n\n```markdown\nWe can [link to that heading][hello-world] from another page too.\n\nThis works the same as [a normal link to that heading](../doc1.md#hello-world).\n```\n\nLinking to a heading without needing to know the destination page can be useful if specifying that path is cumbersome, e.g. when the pages have deeply nested paths, are far apart, or are moved around frequently.\n\n### Non-unique headings\n\nWhen linking to a heading that appears several times throughout the site, this plugin will log a warning message stating that multiple URLs were found and that headings should be made unique, and will resolve the link using the first found URL.\n\nTo prevent getting warnings, use [Markdown anchors](#markdown-anchors) to add unique aliases to your headings, and use these aliases when referencing the headings.\n\nIf you cannot use Markdown anchors, for example because you inject the same generated contents in multiple locations (for example mkdocstrings' API documentation), then you can try to alleviate the warnings by enabling the `resolve_closest` option:\n\n```yaml\nplugins:\n- autorefs:\n    resolve_closest: true\n```\n\nWhen `resolve_closest` is enabled, and multiple URLs are found for the same identifier, the plugin will try to resolve to the one that is \"closest\" to the current page (the page containing the link). By closest, we mean:\n\n- URLs that are relative to the current page's URL, climbing up parents\n- if multiple URLs are relative to it, use the one at the shortest distance if possible.\n\nIf multiple relative URLs are at the same distance, the first of these URLs will be used. If no URL is relative to the current page's URL, the first URL of all found URLs will be used.\n\nExamples:\n\nCurrent page | Candidate URLs | Relative URLs | Winner\n------------ | -------------- | ------------- | ------\n` ` | `x/#b`, `#b` | `#b` | `#b` (only one relative)\n`a/` | `b/c/#d`, `c/#d` | none | `b/c/#d` (no relative, use first one, even if longer distance)\n`a/b/` | `x/#e`, `a/c/#e`, `a/d/#e` | `a/c/#e`, `a/d/#e` (relative to parent `a/`) | `a/c/#e` (same distance, use first one)\n`a/b/` | `x/#e`, `a/c/d/#e`, `a/c/#e` | `a/c/d/#e`, `a/c/#e` (relative to parent `a/`) | `a/c/#e` (shortest distance)\n`a/b/c/` | `x/#e`, `a/#e`, `a/b/#e`, `a/b/c/d/#e`, `a/b/c/#e` | `a/b/c/d/#e`, `a/b/c/#e` | `a/b/c/#e` (shortest distance)\n\n### Markdown anchors\n\nThe autorefs plugin offers a feature called \"Markdown anchors\". Such anchors can be added anywhere in a document, and linked to from any other place.\n\nThe syntax is:\n\n```md\n[](){ #id-of-the-anchor }\n```\n\nIf you look closely, it starts with the usual syntax for a link, `[]()`, except both the text value and URL of the link are empty. Then we see `{ #id-of-the-anchor }`, which is the syntax supported by the [`attr_list`](https://python-markdown.github.io/extensions/attr_list/) extension. It sets an HTML id to the anchor element. The autorefs plugin simply gives a meaning to such anchors with ids. Note that raw HTML anchors like `\u003ca id=\"foo\"\u003e\u003c/a\u003e` are not supported.\n\nThe `attr_list` extension must be enabled for the Markdown anchors feature to work:\n\n```yaml\n# mkdocs.yml\nplugins:\n- search\n- autorefs\n\nmarkdown_extensions:\n- attr_list\n```\n\nNow, you can add anchors to documents:\n\n```md\nSomewhere in a document.\n\n[](){ #foobar-paragraph }\n\nParagraph about foobar.\n```\n\n...making it possible to link to this anchor with our automatic links:\n\n```md\nIn any document.\n\nCheck out the [paragraph about foobar][foobar-paragraph].\n```\n\nIf you add a Markdown anchor right above a heading, this anchor will redirect to the heading itself:\n\n```md\n[](){ #foobar }\n## A verbose title about foobar\n```\n\nLinking to the `foobar` anchor will bring you directly to the heading, not the anchor itself, so the URL will show `#a-verbose-title-about-foobar` instead of `#foobar`. These anchors therefore act as \"aliases\" for headings. It is possible to define multiple aliases per heading:\n\n```md\n[](){ #contributing }\n[](){ #development-setup }\n## How to contribute to the project?\n```\n\nSuch aliases are especially useful when the same headings appear in several different pages. Without aliases, linking to the heading is undefined behavior (it could lead to any one of the headings). With unique aliases above headings, you can make sure to link to the right heading.\n\nFor example, consider the following setup. You have one document per operating system describing how to install a project with the OS package manager or from sources:\n\n```tree\ndocs/\n  install/\n    arch.md\n    debian.md\n    gentoo.md\n```\n\nEach page has:\n\n```md\n## Install with package manager\n...\n\n## Install from sources\n...\n```\n\nYou don't want to change headings and make them redundant, like `## Arch: Install with package manager` and `## Debian: Install with package manager` just to be able to reference the right one with autorefs. Instead you can do this:\n\n```md\n[](){ #arch-install-pkg }\n## Install with package manager\n...\n\n[](){ #arch-install-src }\n## Install from sources\n...\n```\n\n...changing `arch` by `debian`, `gentoo`, etc. in the other pages.\n\n---\n\nYou can also change the actual identifier of a heading, thanks again to the `attr_list` Markdown extension:\n\n```md\n## Install from sources { #arch-install-src }\n...\n```\n\n...though note that this will impact the URL anchor too (and therefore the permalink to the heading).\n\n### Link titles\n\nWhen rendering cross-references, the autorefs plugin sets `title` HTML attributes on links. These titles are displayed as tooltips when hovering on links. For mandatory cross-references (user-written ones), the original title of the target section is used as tooltip, for example: `Original title`. For optional cross-references (typically rendered by mkdocstrings handlers), the identifier is appended to the original title, for example: `Original title (package.module.function)`. This is useful to indicate the fully qualified name of API objects.\n\nSince the presence of titles prevents [the instant preview feature of Material for MkDocs][instant-preview] from working, the autorefs plugin will detect when this theme and feature are used, and only set titles on *external* links (for which instant previews cannot work).\n\nIf you want to force autorefs to always set titles, never set titles, or only set titles on external links, you can use the `link_titles` option:\n\n```yaml\nplugins:\n- autorefs:\n    link_titles: external\n    # link_titles: true\n    # link_titles: false\n    # link_titles: auto  # default\n```\n\n[instant-preview]: https://squidfunk.github.io/mkdocs-material/setup/setting-up-navigation/#instant-previews\n\nBy default, HTML tags are only preserved in titles if the current theme in use is Material for MkDocs and its `content.tooltips` feature is enabled. If your chosen theme does support HTML tags in titles, you can prevent tags stripping with the `strip_title_tags` option:\n\n```yaml\nplugins:\n- autorefs:\n    strip_title_tags: false\n    # strip_title_tags: true\n    # strip_title_tags: auto  # default\n```\n\n### Backlinks\n\nThe autorefs plugin supports recording backlinks, that other plugins or systems can then use to render backlinks into pages.\n\nFor example, when linking from page `foo/`, section `Section` to a heading with identifier `heading` thanks to a cross-reference `[Some heading][heading]`, the plugin will record that `foo/#section` references `heading`.\n\n```md\n# Page foo\n\nThis is page foo.\n\n## Section\n\nThis section references [some heading][heading].\n```\n\nThe `record_backlinks` attribute of the autorefs plugin must be set to true before Markdown is rendered to HTML to enable backlinks recording. This is typically done in an `on_config` MkDocs hook:\n\n```python\nfrom mkdocs.config.defaults import MkDocsConfig\n\n\ndef on_config(config: MkDocsConfig) -\u003e MkDocsConfig | None:\n    config.plugins[\"autorefs\"].record_backlinks = True\n    return config\n```\n\nNote that for backlinks to be recorded with accurate URLs, headings must have HTML IDs, meaning either the `toc` extension must be enabled, or the `attr_list` extension must be enabled *and* authors must add IDs to the relevant headings, with the `## Heading { #heading-id }` syntax.\n\nOther plugins or systems integrating with the autorefs plugin can then retrieve backlinks for a specific identifier:\n\n```python\nbacklinks = autorefs_plugin.get_backlinks(\"heading\")\n```\n\nThe `get_backlinks` method returns a map of backlink types to sets of backlinks. A backlink is a tuple of navigation breadcrumbs, each breadcrumb having a title and URL.\n\n```python\nprint(backlinks)\n# {\n#  \"referenced-by\": {\n#      Backlink(\n#          crumbs=(\n#              BacklinkCrumb(title=\"Foo\", url=\"foo/\"),\n#              BacklinkCrumb(title=\"Section\", url=\"foo/#section\"),\n#          ),\n#      ),\n#  }\n```\n\nThe default backlink type is `referenced-by`, but can be customized by other plugins or systems thanks to the `backlink-type` HTML data attribute on `autoref` elements. Such plugins and systems can also specify the anchor on the current page to use for the backlink with the `backlink-anchor` HTML data attribute on `autoref` elements.\n\n```html\n\u003cautoref identifier=\"heading\" backlink-type=\"mentionned-by\" backlink-anchor=\"section-paragraph\"\u003e\n```\n\nThis feature is typically designed for use in [mkdocstrings](https://mkdocstrings.github.io/) handlers, though is not exclusive to mkdocstrings: it can be used by any other plugin or even author hooks. Such a hook is provided as an example here:\n\n```python\ndef on_env(env, /, *, config, files):\n    regex = r\"\u003cbacklinks\\s+identifier=\\\"([^\\\"]+)\\\"\\s*/?\u003e\"\n\n    def repl(match: Match) -\u003e str:\n        identifier = match.group(1)\n        backlinks = config.plugin[\"autorefs\"].get_backlinks(identifier, from_url=file.page.url)\n        if not backlinks:\n            return \"\"\n        return \"\".join(_render_backlinks(backlinks))\n\n    for file in files:\n        if file.page and file.page.content:\n            file.page.content = re.sub(regex, repl, file.page.content)\n\n    return env\n\n\n\ndef _render_backlinks(backlinks):\n    yield \"\u003cdiv\u003e\"\n    for backlink_type, backlink_list in backlinks:\n        yield f\"\u003cb\u003e{verbose_type[backlink_type]}:\u003c/b\u003e\"\n        yield \"\u003cul\u003e\"\n        for backlink in sorted(backlink_list, key: lambda b: b.crumbs):\n            yield \"\u003cli\u003e\"\n            for crumb in backlink.crumbs:\n                if crumb.url and crumb.title:\n                    yield f'\u003ca href=\"{crumb.url}\"\u003e{crumb.title}\u003c/a\u003e'\n                elif crumb.title:\n                    yield f\"\u003cspan\u003e{crumb.title}\u003c/span\u003e\"\n            yield \"\u003c/li\u003e\"\n        yield \"\u003c/ul\u003e\"\n    yield \"\u003c/div\u003e\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkdocstrings%2Fautorefs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkdocstrings%2Fautorefs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkdocstrings%2Fautorefs/lists"}