Skip to content

API reference

Auto-generated from the package's docstrings.

Plugin

mkdocs_source_links.plugin

MkDocs plugin entry point.

SourceLinksPlugin

Bases: BasePlugin

MkDocs plugin that rewrites parent-directory markdown links to forge URLs.

During mkdocs build, ](../path) links in each page's markdown are replaced with GitHub blob/tree view URLs. Source files on disk are not modified.

Attributes:

Name Type Description
config_scheme PlainConfigSchema

Plugin configuration schema. Supports enabled (turn rewriting on or off), branch (override the git branch used in forge URLs), forge (override forge autodetection: one of github, gitlab, bitbucket, gitea, azure), pin (branch or commit — embed the current commit SHA instead of a branch name), and warn_on_missing (warn when a ../ link target does not exist).

Notes

Requires repo_url in mkdocs.yml. Pages without a backing file (virtual pages) are left unchanged. The git view ref is resolved once per build in on_config.

Source code in src/mkdocs_source_links/plugin.py
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
class SourceLinksPlugin(BasePlugin):
    """MkDocs plugin that rewrites parent-directory markdown links to forge URLs.

    During ``mkdocs build``, ``](../path)`` links in each page's markdown are replaced with GitHub
    blob/tree view URLs. Source files on disk are not modified.

    Attributes
    ----------
    config_scheme : PlainConfigSchema
        Plugin configuration schema. Supports ``enabled`` (turn rewriting on or off),
        ``branch`` (override the git branch used in forge URLs), ``forge`` (override forge
        autodetection: one of ``github``, ``gitlab``, ``bitbucket``, ``gitea``, ``azure``),
        ``pin`` (``branch`` or ``commit`` — embed the current commit SHA instead of a branch
        name), and ``warn_on_missing`` (warn when a ``../`` link target does not exist).

    Notes
    -----
    Requires ``repo_url`` in ``mkdocs.yml``. Pages without a backing file (virtual pages) are left
    unchanged. The git view ref is resolved once per build in ``on_config``.
    """

    config_scheme: PlainConfigSchema = (
        ("enabled", config_options.Type(bool, default=True)),
        ("pin", config_options.Choice(("branch", "commit"), default="branch")),
        ("branch", config_options.Optional(config_options.Type(str))),
        ("forge", config_options.Optional(config_options.Choice(SUPPORTED_FORGES))),
        ("warn_on_missing", config_options.Type(bool, default=True)),
    )

    _view_ref: ViewRef

    def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
        """Resolve the git view ref once per build and cache it.

        Resolving here (rather than per page) avoids running ``git`` for every page when
        ``pin: commit`` is set.

        Parameters
        ----------
        config : MkDocsConfig
            MkDocs site configuration.

        Returns
        -------
        MkDocsConfig
            The unmodified configuration.
        """
        branch = resolve_branch(
            plugin_branch=self.config.get("branch"),
            extra=config.extra or {},
            edit_uri=config.edit_uri,
        )
        if not self.config.get("enabled", True):
            self._view_ref = ViewRef(branch, "branch")
            return config
        self._view_ref = resolve_view_ref(
            pin=self.config.get("pin", "branch"),
            repo_root=Path(config.config_file_path).parent,
            branch=branch,
        )
        return config

    def on_page_markdown(
        self,
        markdown: str,
        /,
        *,
        page: Page,
        config: MkDocsConfig,
        files: Files,  # noqa: ARG002 (unused-method-argument) (required by MkDocs hook signature)
    ) -> str:
        """Rewrite ``](../…)`` links in page markdown to forge view URLs.

        Parameters
        ----------
        markdown : str
            Markdown source for the page after metadata has been stripped.
        page : Page
            MkDocs page whose ``file.abs_src_path`` locates the doc in the repo.
        config : MkDocsConfig
            MkDocs site configuration; ``repo_url`` must be set for any
            rewriting to occur.
        files : Files
            MkDocs file collection (required by the hook signature; unused).

        Returns
        -------
        str
            Markdown with parent-directory links rewritten, or the original ``markdown`` when the
            plugin is disabled, ``repo_url`` is missing, or the page has no backing file.
        """
        if not self.config.get("enabled", True):
            return markdown
        if not config.repo_url:
            return markdown
        if page.file.abs_src_path is None:
            return markdown

        report_missing: Callable[[str], None] | None = None
        if self.config.get("warn_on_missing", True):
            src_path = page.file.src_path

            def _warn(target: str) -> None:
                log.warning("Link target does not exist: %s (in %s)", target, src_path)

            report_missing = _warn

        return rewrite_repo_parent_links(
            markdown,
            page_abs_path=Path(page.file.abs_src_path),
            repo_root=Path(config.config_file_path).parent,
            repo_url=config.repo_url,
            view_ref=self._view_ref,
            forge=self.config.get("forge"),
            report_missing=report_missing,
        )

on_config

on_config(config)

Resolve the git view ref once per build and cache it.

Resolving here (rather than per page) avoids running git for every page when pin: commit is set.

Parameters:

Name Type Description Default
config MkDocsConfig

MkDocs site configuration.

required

Returns:

Type Description
MkDocsConfig

The unmodified configuration.

Source code in src/mkdocs_source_links/plugin.py
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
    """Resolve the git view ref once per build and cache it.

    Resolving here (rather than per page) avoids running ``git`` for every page when
    ``pin: commit`` is set.

    Parameters
    ----------
    config : MkDocsConfig
        MkDocs site configuration.

    Returns
    -------
    MkDocsConfig
        The unmodified configuration.
    """
    branch = resolve_branch(
        plugin_branch=self.config.get("branch"),
        extra=config.extra or {},
        edit_uri=config.edit_uri,
    )
    if not self.config.get("enabled", True):
        self._view_ref = ViewRef(branch, "branch")
        return config
    self._view_ref = resolve_view_ref(
        pin=self.config.get("pin", "branch"),
        repo_root=Path(config.config_file_path).parent,
        branch=branch,
    )
    return config

on_page_markdown

on_page_markdown(markdown, /, *, page, config, files)

Rewrite ](../…) links in page markdown to forge view URLs.

Parameters:

Name Type Description Default
markdown str

Markdown source for the page after metadata has been stripped.

required
page Page

MkDocs page whose file.abs_src_path locates the doc in the repo.

required
config MkDocsConfig

MkDocs site configuration; repo_url must be set for any rewriting to occur.

required
files Files

MkDocs file collection (required by the hook signature; unused).

required

Returns:

Type Description
str

Markdown with parent-directory links rewritten, or the original markdown when the plugin is disabled, repo_url is missing, or the page has no backing file.

Source code in src/mkdocs_source_links/plugin.py
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
def on_page_markdown(
    self,
    markdown: str,
    /,
    *,
    page: Page,
    config: MkDocsConfig,
    files: Files,  # noqa: ARG002 (unused-method-argument) (required by MkDocs hook signature)
) -> str:
    """Rewrite ``](../…)`` links in page markdown to forge view URLs.

    Parameters
    ----------
    markdown : str
        Markdown source for the page after metadata has been stripped.
    page : Page
        MkDocs page whose ``file.abs_src_path`` locates the doc in the repo.
    config : MkDocsConfig
        MkDocs site configuration; ``repo_url`` must be set for any
        rewriting to occur.
    files : Files
        MkDocs file collection (required by the hook signature; unused).

    Returns
    -------
    str
        Markdown with parent-directory links rewritten, or the original ``markdown`` when the
        plugin is disabled, ``repo_url`` is missing, or the page has no backing file.
    """
    if not self.config.get("enabled", True):
        return markdown
    if not config.repo_url:
        return markdown
    if page.file.abs_src_path is None:
        return markdown

    report_missing: Callable[[str], None] | None = None
    if self.config.get("warn_on_missing", True):
        src_path = page.file.src_path

        def _warn(target: str) -> None:
            log.warning("Link target does not exist: %s (in %s)", target, src_path)

        report_missing = _warn

    return rewrite_repo_parent_links(
        markdown,
        page_abs_path=Path(page.file.abs_src_path),
        repo_root=Path(config.config_file_path).parent,
        repo_url=config.repo_url,
        view_ref=self._view_ref,
        forge=self.config.get("forge"),
        report_missing=report_missing,
    )

mkdocs_source_links.rewrite

Rewrite ../ markdown links to forge view URLs.

repo_relative_path

repo_relative_path(*, page_abs_path, href, repo_root)

Resolve a ../ link from a doc page to a repo-root-relative POSIX path.

Parameters:

Name Type Description Default
page_abs_path Path

Absolute path to the page's markdown file on disk.

required
href str

Link target as written in the markdown; only ../ targets are resolved.

required
repo_root Path

Repository root used to resolve the target and build the relative path.

required

Returns:

Type Description
str | None

Repo-root-relative POSIX path, or None if href is not a ../ link or resolves outside repo_root.

Source code in src/mkdocs_source_links/rewrite.py
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
def repo_relative_path(*, page_abs_path: Path, href: str, repo_root: Path) -> str | None:
    """Resolve a ``../`` link from a doc page to a repo-root-relative POSIX path.

    Parameters
    ----------
    page_abs_path : Path
        Absolute path to the page's markdown file on disk.
    href : str
        Link target as written in the markdown; only ``../`` targets are resolved.
    repo_root : Path
        Repository root used to resolve the target and build the relative path.

    Returns
    -------
    str | None
        Repo-root-relative POSIX path, or ``None`` if ``href`` is not a ``../`` link or resolves
        outside ``repo_root``.
    """
    if not href.startswith("../"):
        return None
    target = (page_abs_path.parent / href).resolve()
    return _repo_relative(target=target, repo_root=repo_root)
rewrite_repo_parent_links(
    markdown,
    *,
    page_abs_path,
    repo_root,
    repo_url,
    view_ref,
    forge=None,
    report_missing=None,
)

Replace ](../…) markdown links with git-forge view URLs.

Only links whose target resolves to an existing file or directory inside repo_root are rewritten. Unsupported hosts, paths outside the repo, and missing targets are left unchanged.

Parameters:

Name Type Description Default
markdown str

Markdown source text for a single documentation page.

required
page_abs_path Path

Absolute path to the page's markdown file on disk.

required
repo_root Path

Repository root used to resolve ../ targets and to build repo-relative paths for the forge URL.

required
repo_url str

Forge repository URL from mkdocs.yml (for example a GitHub URL).

required
view_ref ViewRef

Git branch name or commit SHA and its kind for blob/tree URLs.

required
forge str | None

Explicit forge name; when None the forge is autodetected from repo_url.

None
report_missing Callable[[str], None] | None

Optional callback invoked with the link target (as written in the markdown) for each ../ link that resolves inside repo_root but points at a path that does not exist on disk. Links outside the repo are not reported.

None

Returns:

Type Description
str

Markdown with matching parent-directory links rewritten to forge URLs.

Notes

Directory targets use tree URLs; file targets use blob URLs (on forges that distinguish them). URL fragments (#anchor) and link titles are preserved, and angle-bracket destinations (](<../x>)) are supported. Links inside fenced code blocks and inline code spans are left unchanged.

Source code in src/mkdocs_source_links/rewrite.py
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def rewrite_repo_parent_links(
    markdown: str,
    *,
    page_abs_path: Path,
    repo_root: Path,
    repo_url: str,
    view_ref: ViewRef,
    forge: str | None = None,
    report_missing: Callable[[str], None] | None = None,
) -> str:
    """Replace ``](../…)`` markdown links with git-forge view URLs.

    Only links whose target resolves to an existing file or directory inside ``repo_root`` are
    rewritten. Unsupported hosts, paths outside the repo, and missing targets are left unchanged.

    Parameters
    ----------
    markdown : str
        Markdown source text for a single documentation page.
    page_abs_path : Path
        Absolute path to the page's markdown file on disk.
    repo_root : Path
        Repository root used to resolve ``../`` targets and to build
        repo-relative paths for the forge URL.
    repo_url : str
        Forge repository URL from ``mkdocs.yml`` (for example a GitHub URL).
    view_ref : ViewRef
        Git branch name or commit SHA and its kind for blob/tree URLs.
    forge : str | None
        Explicit forge name; when ``None`` the forge is autodetected from ``repo_url``.
    report_missing : Callable[[str], None] | None
        Optional callback invoked with the link target (as written in the markdown) for each
        ``../`` link that resolves inside ``repo_root`` but points at a path that does not exist
        on disk. Links outside the repo are not reported.

    Returns
    -------
    str
        Markdown with matching parent-directory links rewritten to forge URLs.

    Notes
    -----
    Directory targets use ``tree`` URLs; file targets use ``blob`` URLs (on forges that
    distinguish them). URL fragments (``#anchor``) and link titles are preserved, and
    angle-bracket destinations (``](<../x>)``) are supported. Links inside fenced code blocks
    and inline code spans are left unchanged.
    """

    def repl(match: re.Match[str]) -> str:
        path_part = match.group("path") or match.group("path_a")
        if path_part is None:
            # Matched a fenced code block or inline code span: leave it untouched.
            return match.group(0)
        fragment = match.group("frag") or match.group("frag_a") or ""
        title = match.group("title")
        # path_part always starts with "../" (guaranteed by the link branch of _SCAN).
        target = (page_abs_path.parent / path_part).resolve()
        repo_path = _repo_relative(target=target, repo_root=repo_root)
        if repo_path is None:
            return match.group(0)

        if target.is_dir():
            is_dir = True
        elif target.is_file():
            is_dir = False
        else:
            if report_missing is not None:
                report_missing(path_part)
            return match.group(0)

        forge_name = forge or detect_forge(repo_url)
        url = repo_view_url(
            repo_url=repo_url,
            ref=view_ref.ref,
            ref_kind=view_ref.kind,
            repo_path=repo_path,
            is_dir=is_dir,
            forge=forge_name,
        )
        if url is None:
            return match.group(0)
        out_fragment = (
            translate_line_fragment(fragment, forge=forge_name) if forge_name else fragment
        )
        title_suffix = f" {title}" if title else ""
        return f"]({url}{out_fragment}{title_suffix})"

    return _SCAN.sub(repl, markdown)

Forge URLs

mkdocs_source_links.urls

Forge view URL builders with host autodetection.

Supports GitHub, GitLab, Bitbucket Cloud, Gitea/Forgejo (incl. Codeberg), and Azure DevOps. Public forge hosts are detected automatically; self-hosted instances on non-obvious domains can be selected with an explicit forge name.

detect_forge

detect_forge(repo_url)

Identify the git forge that hosts a repository URL.

Detection first matches well-known public hosts exactly, then falls back to hostname-label hints so self-hosted instances (for example GitHub Enterprise at github.example.com) are recognized. Ambiguous custom domains return None and should be configured explicitly.

Parameters:

Name Type Description Default
repo_url str

Repository URL from mkdocs.yml (repo_url).

required

Returns:

Type Description
str | None

A forge name from :data:SUPPORTED_FORGES, or None if the host is unknown.

Source code in src/mkdocs_source_links/urls.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def detect_forge(repo_url: str) -> str | None:
    """Identify the git forge that hosts a repository URL.

    Detection first matches well-known public hosts exactly, then falls back to hostname-label
    hints so self-hosted instances (for example GitHub Enterprise at ``github.example.com``) are
    recognized. Ambiguous custom domains return ``None`` and should be configured explicitly.

    Parameters
    ----------
    repo_url : str
        Repository URL from ``mkdocs.yml`` (``repo_url``).

    Returns
    -------
    str | None
        A forge name from :data:`SUPPORTED_FORGES`, or ``None`` if the host is unknown.
    """
    host = (urlsplit(repo_url).hostname or "").lower()
    if not host:
        return None
    if host in _KNOWN_HOSTS:
        return _KNOWN_HOSTS[host]
    if host.endswith(".visualstudio.com"):
        return "azure"
    for needle, forge in _HOST_HINTS:
        if _host_matches_hint(host, needle):
            return forge
    return None

repo_view_url

repo_view_url(
    *,
    repo_url,
    ref,
    ref_kind,
    repo_path,
    is_dir,
    forge=None,
)

Build a git-forge view URL for a path inside the repository.

Parameters:

Name Type Description Default
repo_url str

Forge repository URL from mkdocs.yml.

required
ref str

Git branch name or commit SHA to embed in the URL.

required
ref_kind RefKind

Whether ref is a branch name or a commit SHA. Azure DevOps uses different version prefixes (GB vs GC) depending on this value.

required
repo_path str

Repo-root-relative POSIX path to the target file or directory.

required
is_dir bool

Whether repo_path is a directory or a file. Forges that distinguish the two (GitHub, GitLab) use tree vs blob accordingly.

required
forge str | None

Explicit forge name from :data:SUPPORTED_FORGES. When None, the forge is autodetected from repo_url.

None

Returns:

Type Description
str | None

Forge view URL, or None if the forge could not be determined.

Source code in src/mkdocs_source_links/urls.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def repo_view_url(
    *,
    repo_url: str,
    ref: str,
    ref_kind: RefKind,
    repo_path: str,
    is_dir: bool,
    forge: str | None = None,
) -> str | None:
    """Build a git-forge view URL for a path inside the repository.

    Parameters
    ----------
    repo_url : str
        Forge repository URL from ``mkdocs.yml``.
    ref : str
        Git branch name or commit SHA to embed in the URL.
    ref_kind : RefKind
        Whether ``ref`` is a branch name or a commit SHA. Azure DevOps uses different
        version prefixes (``GB`` vs ``GC``) depending on this value.
    repo_path : str
        Repo-root-relative POSIX path to the target file or directory.
    is_dir : bool
        Whether ``repo_path`` is a directory or a file. Forges that distinguish the two
        (GitHub, GitLab) use ``tree`` vs ``blob`` accordingly.
    forge : str | None
        Explicit forge name from :data:`SUPPORTED_FORGES`. When ``None``, the forge is
        autodetected from ``repo_url``.

    Returns
    -------
    str | None
        Forge view URL, or ``None`` if the forge could not be determined.
    """
    forge_name = forge or detect_forge(repo_url)
    if forge_name is None:
        return None
    request = _ForgeRequest(
        base=_normalize_repo_base(repo_url),
        ref=ref,
        ref_kind=ref_kind,
        repo_path=quote(repo_path, safe="/"),
        is_dir=is_dir,
    )
    return _BUILDERS[forge_name](request)

Branch resolution

mkdocs_source_links.branch

Resolve git branch for forge URLs from MkDocs config.

resolve_branch

resolve_branch(*, plugin_branch, extra, edit_uri)

Resolve the git branch name used in forge view URLs.

Branch resolution follows MkDocs and plugin configuration in priority order: explicit plugin branch, then extra.git_branch, then the branch parsed from edit_uri, then main.

Parameters:

Name Type Description Default
plugin_branch str | None

Value of the plugin's branch config option, if set.

required
extra Mapping[str, Any]

MkDocs extra mapping; git_branch is consulted when present.

required
edit_uri str | None

MkDocs edit_uri; the segment after edit/ or blob/ is used as the branch name when present. GitLab-style -/edit/<branch>/… paths are supported.

required

Returns:

Type Description
str

Branch name for forge URLs.

Source code in src/mkdocs_source_links/branch.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def resolve_branch(
    *,
    plugin_branch: str | None,
    extra: Mapping[str, Any],
    edit_uri: str | None,
) -> str:
    """Resolve the git branch name used in forge view URLs.

    Branch resolution follows MkDocs and plugin configuration in priority order: explicit plugin
    ``branch``, then ``extra.git_branch``, then the branch parsed from ``edit_uri``, then ``main``.

    Parameters
    ----------
    plugin_branch : str | None
        Value of the plugin's ``branch`` config option, if set.
    extra : Mapping[str, Any]
        MkDocs ``extra`` mapping; ``git_branch`` is consulted when present.
    edit_uri : str | None
        MkDocs ``edit_uri``; the segment after ``edit/`` or ``blob/`` is used as the branch name
        when present. GitLab-style ``-/edit/<branch>/…`` paths are supported.

    Returns
    -------
    str
        Branch name for forge URLs.
    """
    if plugin_branch:
        return plugin_branch
    if branch := extra.get("git_branch"):
        return str(branch)
    if edit_uri:
        parts = edit_uri.strip("/").split("/")
        if len(parts) >= 3 and parts[0] == "-" and parts[1] in ("edit", "blob"):
            return parts[2]
        if len(parts) >= 2 and parts[0] in ("edit", "blob"):
            return parts[1]
    return "main"

Git ref resolution

mkdocs_source_links.ref

Resolve git ref and ref kind for forge view URLs.

ViewRef

Bases: NamedTuple

Git ref and kind for forge view URLs.

Source code in src/mkdocs_source_links/ref.py
15
16
17
18
19
class ViewRef(NamedTuple):
    """Git ref and kind for forge view URLs."""

    ref: str
    kind: RefKind

resolve_view_ref

resolve_view_ref(*, pin, repo_root, branch)

Resolve the git ref and kind used in forge view URLs.

When pin is commit, the current HEAD SHA is resolved via git rev-parse. If git is unavailable, times out, or repo_root is not a repository, the resolved branch is used instead.

Parameters:

Name Type Description Default
pin str

Pin mode: branch or commit.

required
repo_root Path

Repository root passed to git -C.

required
branch str

Resolved branch name used when pin is branch or as a fallback for commit.

required

Returns:

Type Description
ViewRef

Ref string and kind (branch or commit) for URL building.

Source code in src/mkdocs_source_links/ref.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def resolve_view_ref(*, pin: str, repo_root: Path, branch: str) -> ViewRef:
    """Resolve the git ref and kind used in forge view URLs.

    When ``pin`` is ``commit``, the current HEAD SHA is resolved via ``git rev-parse``. If git is
    unavailable, times out, or ``repo_root`` is not a repository, the resolved branch is used
    instead.

    Parameters
    ----------
    pin : str
        Pin mode: ``branch`` or ``commit``.
    repo_root : Path
        Repository root passed to ``git -C``.
    branch : str
        Resolved branch name used when ``pin`` is ``branch`` or as a fallback for ``commit``.

    Returns
    -------
    ViewRef
        Ref string and kind (``branch`` or ``commit``) for URL building.
    """
    if pin != "commit" or _GIT is None:
        return ViewRef(branch, "branch")
    try:
        result = subprocess.run(  # noqa: S603 (subprocess-without-shell-equals-true)
            [_GIT, "-C", str(repo_root), "rev-parse", "HEAD"],
            capture_output=True,
            text=True,
            check=True,
            timeout=10,
        )
    except (OSError, subprocess.SubprocessError):
        return ViewRef(branch, "branch")
    sha = result.stdout.strip()
    if not sha:
        return ViewRef(branch, "branch")
    return ViewRef(sha, "commit")

Line anchors

mkdocs_source_links.anchors

Translate canonical line-number URL fragments to forge-specific syntax.

translate_line_fragment

translate_line_fragment(fragment, *, forge)

Translate a canonical #L line fragment to forge-specific syntax.

Canonical input uses #L10 for a single line and #L10-L20 for a range. Non-line fragments (for example #section) are returned unchanged. Azure DevOps does not support hash-based line anchors in view URLs, so line fragments are dropped for that forge.

Parameters:

Name Type Description Default
fragment str

URL fragment from the markdown link, including the leading #, or an empty string.

required
forge str

Forge name from :data:~mkdocs_source_links.urls.SUPPORTED_FORGES.

required

Returns:

Type Description
str

Forge-specific fragment, the original fragment when it is not a line anchor, or an empty string for Azure line anchors.

Source code in src/mkdocs_source_links/anchors.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
def translate_line_fragment(fragment: str, *, forge: str) -> str:
    """Translate a canonical ``#L`` line fragment to forge-specific syntax.

    Canonical input uses ``#L10`` for a single line and ``#L10-L20`` for a range. Non-line
    fragments (for example ``#section``) are returned unchanged. Azure DevOps does not support
    hash-based line anchors in view URLs, so line fragments are dropped for that forge.

    Parameters
    ----------
    fragment : str
        URL fragment from the markdown link, including the leading ``#``, or an empty string.
    forge : str
        Forge name from :data:`~mkdocs_source_links.urls.SUPPORTED_FORGES`.

    Returns
    -------
    str
        Forge-specific fragment, the original fragment when it is not a line anchor, or an empty
        string for Azure line anchors.
    """
    if not fragment:
        return fragment
    match = _LINE_FRAGMENT.match(fragment)
    if match is None:
        return fragment
    start = match.group(1)
    end = match.group(2)
    if forge == "azure":
        return ""
    if forge == "gitlab":
        return f"#L{start}-{end}" if end else f"#L{start}"
    if forge == "bitbucket":
        return f"#lines-{start}:{end}" if end else f"#lines-{start}"
    return f"#L{start}-L{end}" if end else f"#L{start}"