Is there a way to compose standard text roles in reStructuredText? For instance, to format a string as both literal and strong?
The following do not do what I had hoped:
**``text``**
``**text**``
:strong:`:literal:`text``
:literal:`:strong:`text``
No, this is not directly possible. Content passed into the function which implements the role (argument text) is not further parsed.
See Creating reStructuredText Interpreted Text Roles.
That said, you could implement your own rst role which would parse the text further via nested_parse() if you like - but that's not what are you asking about here.
Comment from docutils/docutils/parsers/rst/roles.py suggests that the nested
parse feature you are asking about was/is planned/suggested, but hasn't been
implemented so far.
# Once nested inline markup is implemented, this and other methods should
# recursively call inliner.nested_parse().
(The following is hereby released under CC0.)
If you have the ability to extend the parser (e.g. if you are using Sphinx), you can add a custom role that parses its contents. (Note that this will work for simple things like bold/italic and substitutions, but will most likely fall on its face if you try to nest roles or such craziness.
I use this:
from docutils import nodes
from docutils.parsers.rst.states import Struct
def make_parsed_text_role(class_names=[], node_class=nodes.inline):
def parsed_text_role(name, rawtext, text, lineno, inliner,
options={}, content=[]):
# Prepare context for nested parsing
memo = Struct(document=inliner.document,
reporter=inliner.reporter,
language=inliner.language)
# Create parent node
options['classes'] = class_names
parent = node_class(rawtext, '', **options)
# Parse role text for markup and add to parent
processed, messages = inliner.parse(text, lineno, memo, parent)
parent += processed
# Return parent node, and any messages from nested parsing
return [parent], messages
return parsed_text_role
You can use this via a Sphinx conf.py like so:
# Configuration file for the Sphinx documentation builder (conf.py).
project = 'My Documentation'
# ...
# ...paste the above code here...
def setup(app):
app.add_role('foo', make_parsed_text_role(class_names=['foo']))
In your documentation, this will let you write:
This is :foo:`some **bold** text`!
In HTML, this will produce a <span class="foo">, at least for the default nodes.inline node class. Use of the generator pattern is optional, but it's super-convenient if you want to make a whole bunch of these custom roles.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With