I've written a custom domain in Sphinx. It has directives that register items (which all end up in the data
member) then parallel builds get merged together with merge_domaindata
.
I want to create an index-like page that lists every item registered in the domain. I want more control than I could get with a regular Index
-- in particular, I'd like to generate some custom nodes for each item in my domain's data
.
Is there any way to do that? Looking at the core events sequence, it looks like I'd have to delay until after all the env-merge-info
event finishes (because before then, we haven't merged the multiple domain objects together). But I want to be able to use cross-references in my generated nodes, so it should be before the reference resolver post-transform.
Could I maybe register a post-transform to do it? How could I go about that, and what would be the recommended transform priority?
I'm still looking for better answers, but here's at least one way to achieve this.
The key idea is:
For me, this ended up looking something like this.
First, a directive that just inserts a pending node:
class CustomIndexDirective(SphinxDirective):
def run(self) -> list[nodes.Node]:
return [nodes.pending(None, transform_target="custom_index_transform")]
Then, a post-transform transformer that finds the pending node and replaces it with whatever we want to generate:
class CustomIndexTransform(SphinxPostTransform):
default_priority = 0 # still not sure if this is a best practice, but 0 seems to work
for pending_node in self.document.findall(
lambda node: isinstance(node, nodes.pending)
and node.attributes.get("transform_target") == "custom_index_transform"
):
my_domain = self.env.get_domain("my_domain")
new_node = ... # implement as necessary based on my_domain.data
pending_node.replace_self(new_node)
In the extension root, register both the directive and the transform:
def setup(app: Sphinx) -> ExtensionMetadata:
app.add_directive("custom-index", CustomIndexDirective)
app.add_post_transform(CustomIndexTransform)
Finally, in one of the .rst files in the source tree, invoke the custom directive:
.. custom-index::