Hello again! To answer my own question
I've made something and will post here in case this triggers feedback.
tl;dr
- It works, but it was complicated and will not scale well for large documentations. I might open an issue to suggest introducing a new event, but I would really need some guidance to provide the patch myself
- This whole need comes from a package for generating Sphinx Domain easily that I'll soon publish, stay tuned ;)
The domain index will generate also index entries for resolved cross-references (stored in the domain data). The issue is that the resolution happens
after the generation of indices. The following transformer
regenerate the index entries
after the resolution of cross-references
class BackrefsIndexer(SphinxPostTransform):
default_priority = ReferencesResolver.default_priority + 1
index_class: Type
domain_name: str
def is_supported(self) -> bool:
return super().is_supported() and hasattr(self.app.builder, "domain_indices")
def run(self, **kwargs: Any) -> None:
domain_indices = getattr(self.app.builder, "domain_indices", [])
# Find the domain index we are rebuilding
index_number = 0
for index_name, index_class, original_entries_for_char, collapse in domain_indices:
if index_class == self.index_class:
break
index_number += 1
else:
return
index = index_class(self.env.domains[self.domain_name])
# Generate again the index
regenerated, _ = index.generate()
# Use a dict instead of list of tuples expected
new_entries_for_char = defaultdict(list, regenerated)
# Merge with entries not in this docname
for character, entries in original_entries_for_char:
new_entries = []
for entry in entries:
if self.env.docname != entry.docname:
new_entries.append(entry)
new_entries_for_char[character].extend(new_entries)
def key(character_entries):
# sub index items have their own display name
# ignore it in the sorting
character, entries = character_entries
return (character, [entry for entry in entries if entry.subtype in (0,1)])
# Change the dict into the sorted list of tuples expected
resorted = sorted(new_entries_for_char.items(), key=key)
# Replace the regenerated index
domain_indices[index_number] = (
index_name,
index_class,
resorted,
collapse
)
Sadly, it generates the
whole index for
each document. This would not be required if I could know that we are post-transforming the
last document, or if there was an event that happens just before writing or something.
Here is the result
In this case
- location objects can have multiple names (directives arguments),
- whereas the first one is a "primary name". Imagine having "New York City" which is also called "The Big Apple".
- The entry `A nice city` is a cross-reference with an explicit title, say :world:location:`A nice city <Foobartown>`.