Hi,
For my project I'm using Sphinx with a custom domain and I've managed to
create custom ObjectDescription objects, e.g.:
.. mydomain:someobjtype:: MyInstance
:myoption: My option text
Some body text, with standard- or other domain references, such as :ref:
`mysection`.
Also, I've managed to create a custom XRefRole subclass, so that I can
control how references are created. Very cool so far.
Now, what I'd like to do, is to "re-render" some of those objects on other
pages. Use case examples:
- I have a reference documentation section where I have the extensive
list of all objects documented, but also some "Getting Started" documents
where I not only want to reference a few of them, but also literally
re-include / repeat / re-render them for convenience of the reader. With
regular cross-references the reader having to navigate away from the page
for very small object definitions hurts the experience a lot, imo.
- Repeatedly small object references, which should be inlined for
readability. E.g.:
.. mydomain:enum:: Color
:value red: Red is the color for...
:value green: Green is used for ...
.. mydomain:class:: Light
:param: color
:type: :mydomain:enum:`Color`
Then this should render the parameter description with a reference to
the Enum object, but also render: "valid options are: red, green".
If I understand the internals of Sphinx correctly, the logic boils down to
this (please tell me if I am misunderstanding something):
- ObjectDescriptions objects will create the content nodes.
- The XRefRole allows to create cross-references to the content nodes
via the Domain.
- A Transformer traverses the document node tree twice (?) to be able to
resolve a <-> b references, assuming that none of them will be of type
pending_xref after the second run.
- The Transformer (ReferencesResolver) provides a deepcopy of the branch
of nodes to resolve_xref(), for each domain.
(This is blocking me from hacking further by going "out of scope" and
simply connect to the nodes in the document where it was rendered and where
the Transformer will call resolve_xref() on again later.)
- A Writer doesn't deal with stuff like references, but simply renders
the nodes.
Here's what I've tried so far:
1. Exploit the cross-reference logic; In the domain's resolve_xref()
function, where you would normally call return
sphinx.util.nodes.make_refnode([...]), I am returning a full tree of nodes
again. Together with some other hacks, I am able to access those nodes
which then re-renders the same object on reference. (E.g. inline ref like
:mydomain:someobjtype:`MyInstance`.)
However, the problem I'm facing is that this fails in case other
references are part of this tree of nodes, such as the reference to
'mysection' in the example above. This is because they are of the type
pending_xref in my tree, they are not resolved anymore later, and the
writer can't render them, raising an exception. I can solve the problem
only for references within my own domain with a recursive resolve_xref().
It seems the caller of resolve_xref(), ReferencesResolver, is simply not
prepared for new references being returned, but really assumes a simple
link.
2. Document all objects in separate files, then using the RST include
directive to render them on all places that I need. Apart from this being
cumbersome, this is not working well enough for me.
- it will generate identical object descriptions, all being indexed,
emitting a warning that I should put :noindex: on all-but-one. True, but
since this is an RST-level literal include I can't adjust where noindex
flags are added.
- the path to the file to include is relative to the current
document, making it hard to move content around. The cross-reference hack
above does this much better.
3. Looking at the Writer level to render output another time. It seems
that I would break stuff as it's not page-aware any longer, such as
breaking relative links.
I'm currently looking into proceeding with the first option, and adding a
custom Transformer as well, but wanted to ask around here for
ideas/suggestions on a broader level, because this all feels like a huge
hack to something that seems so simple. Yet, I don't see any projects
online who are trying to tackle this on a Sphinx-level (I only see 'smart'
RST generators for custom purposes).
Any suggestions are pretty much welcome. Thanks!
Gert
--
You received this message because you are subscribed to the Google Groups
"sphinx-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sphinx-users.
For more options, visit https://groups.google.com/d/optout.