posit-dev / posit-dev/great-docs

Citation anchors collide and references resolve to the wrong target

Open
#334 0 comments 0 reactions 1 assignee View on GitHub

@has2k1 is already working on this.

Since Sep 1, 2026.

Difficulty: [3] Advanced Priority: [2] Medium Type: ☹︎ Bug
Dominant language
Python
Stars
262
Forks
18
Avg merge
1d 4h
Merged PRs (30d)
14

Description

Numbered citation conversion rewrites raw docstrings before Great Docs generates their pages. At that stage, the converter cannot determine which regions contain code or which page and object own each citation.

Two independent cases therefore produce the same failures: duplicate id="cite-…" attributes and [N]_ references that resolve to the wrong citation.

1. Literal blocks in numpy and google docstrings

The converter treats citation syntax inside :: literal blocks and .. code-block:: bodies as real citations.

def mean(x):
    """
    Compute a mean

    Write a References section like this::

        .. [1] Hoare, C.A.R. (1961). Algorithm 64: Quicksort.

    References
    ----------
    .. [1] Knuth, D. (1984). Literate Programming.
    """

Conversion destroys the example and gives its citation the same anchor as the real citation. The [1]_ reference then resolves to the example instead of the Knuth citation.

Fenced code blocks already work correctly. The Sphinx parser is also unaffected because it converts :: literal blocks to fences before citation conversion runs.

Treating every indented line as code would also suppress legitimate citations nested under parameter descriptions. Checking only for a trailing :: would misclassify directives such as .. note::, whose bodies contain prose and may contain citations that require conversion.

2. Shared namespaces for aliases and multi-object pages

If an object an its alias are documented on the same page and they documentation has a citation, the back links to the from the citation text will point to the the first documented object.

A Griffe alias exposes its target’s docstring, so each alias operates on the same value. The first resolved path converts the citation markers with its own anchor stem. Later paths then reuse that converted markup.

The links remain internally consistent, but their anchor stem identifies the first resolved path rather than the path being documented. Documenting the same target through multiple paths on one page also produces duplicate anchors.

On the whole, citation anchors are not scoped to individual objects either. On a page that documents several objects, a [1]_ reference in one docstring can resolve to a citation definition in another.

Possible Solution

Move citation processing to a Lua filter or a pass over the generated .qmd files. Both stages have the page and object context required to namespace anchors correctly, and both distinguish code from prose.

Case 1 should be rare. Case 2 should be rare as well but more likely than case 1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.