Skip to content

Source links

Griffe records the file path and the first and last line of every object it finds. Each object can then link straight to the code that defines it. Set sourceLink on a package and every heading gets a View source link:

astro.config.mjs
import starlight from '@astrojs/starlight';
import { defineConfig } from 'astro/config';
import starlightPydocs from 'starlight-pydocs';
export default defineConfig({
integrations: [
starlight({
title: 'My docs',
plugins: [
starlightPydocs({
packages: [
{
name: 'mypkg',
search: ['../src'],
// Paths are relative to the repository root.
sourceLink: {
host: 'github',
repo: 'you/mypkg',
ref: 'main',
root: '..',
},
},
],
}),
],
}),
],
});

host picks a forge’s URL layout. repo is the owner/name slug. ref is the branch or tag to link at. root is the directory the URL paths are computed against, and most configurations get this wrong; see below.

Three hosts have presets. host must be one of them. Any other value is a configuration error. For any other forge, use a template.

host URL shape
github https://github.com/{repo}/blob/{ref}/{path}#L{start}-L{end}
gitlab https://gitlab.com/{repo}/-/blob/{ref}/{path}#L{start}-{end}
bitbucket https://bitbucket.org/{repo}/src/{ref}/{path}#lines-{start}:{end}

ref defaults to main. Point it at a tag to pin the links to a release, or at a branch to keep them current.

Griffe reports file paths relative to the directory it ran in, which is the Astro project root. These paths are repository-relative only when the project root and the repository root are the same directory. A documentation site in docs/, with its Python sources one level up, gets paths that are not repository-relative. When the sources are outside the project entirely, the paths are absolute.

This is the common layout:

  • Directorysrc/
    • Directorymypkg/
      • report.py a link should point here
  • Directorydocs/ the Astro project, where griffe runs
    • astro.config.mjs
    • Directorysrc/
  • pyproject.toml

root names the directory that {path} is computed against. This directory is itself relative to the Astro project root. For this layout, the repository root is one level up:

astro.config.mjs
6 collapsed lines
import starlight from '@astrojs/starlight';
import { defineConfig } from 'astro/config';
import starlightPydocs, { pydocsSidebarGroup } from 'starlight-pydocs';
export default defineConfig({
integrations: [
starlight({
title: 'My project',
plugins: [
starlightPydocs({
packages: [
{
name: 'mypkg',
search: ['../src'],
sourceLink: {
host: 'github',
repo: 'you/mypkg',
ref: 'main',
root: '..',
},
},
7 collapsed lines
],
}),
],
sidebar: [{ label: 'API reference', items: [pydocsSidebarGroup] }],
}),
],
});

With root: '..', {path} becomes src/mypkg/report.py. This is what the forge expects. Without root, the link would point at mypkg/report.py, or it would carry the absolute path of the machine that ran the build.

Set root to your repository root whenever the Astro project is a subdirectory. This documentation site does exactly that.

For a self-hosted forge, Gitea, Sourcehut, or an internal code browser, give a template instead of a host.

astro.config.mjs
6 collapsed lines
import starlight from '@astrojs/starlight';
import { defineConfig } from 'astro/config';
import starlightPydocs, { pydocsSidebarGroup } from 'starlight-pydocs';
export default defineConfig({
integrations: [
starlight({
title: 'My project',
plugins: [
starlightPydocs({
packages: [
{
name: 'mypkg',
search: ['../src'],
sourceLink: {
template: 'https://git.internal.example/mypkg/-/blob/{ref}/{path}#L{start}-L{end}',
ref: 'v2.1.0',
root: '..',
},
8 collapsed lines
},
],
}),
],
sidebar: [{ label: 'API reference', items: [pydocsSidebarGroup] }],
}),
],
});
Placeholder Value
{path} Path of the file the object is defined in
{start} First line of the object
{end} Last line of the object, or the first when griffe knows only one
{ref} The ref option

{path} is required. A template without it is a configuration error, because a link to a whole repository is not a source link. The other placeholders are optional. Drop the line fragment if your browser does not support line anchors. Paths always use forward slashes, regardless of the operating system the build ran on.

Each documented object gets a link next to its heading. The link’s title shows the file and line range:

<a class="pyd-source-link" href="https://github.com/you/mypkg/blob/main/src/mypkg/report.py#L57-L160"
title="src/mypkg/report.py:57-160">View source</a>

The label comes from the viewSource string. It follows the site’s locale, and you can replace it per component with labels={{ viewSource: 'Source' }}.

Griffe 2 records a source_link per object: a blob URL at the commit it extracted from, derived from the repository’s own git remote. When you don’t configure sourceLink, starlight-pydocs uses that link as-is. It needs no configuration from you, but it has two limits. First, it is pinned to the commit that was checked out when the dump was made. Second, it only exists when griffe ran inside a git checkout with a recognisable remote, so a pre-generated dump from someone else’s CI may or may not carry one.

That second limit is why an explicit sourceLink with an explicit ref is the safer choice. Griffe detects the ref for itself in a git checkout. A build from a git archive, such as a source tarball with no .git directory, has nothing to detect, so the links disappear. Configuring sourceLink also gives you links that follow a branch or a tag, and it lets you point links at a remote other than the one griffe happened to see.