Skip to content

Commit 20f6130

Browse files
committed
Use RST roles for formatting.
1 parent c635c09 commit 20f6130

File tree

4 files changed

+104
-18
lines changed

4 files changed

+104
-18
lines changed

src/antsibull/jinja2/filters.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232

3333

3434
def _option_name_html(matcher):
35-
parts = matcher.group(1).split('=', 1)
36-
if len(parts) == 1:
37-
return f'<em>{parts[0]}</em>'
38-
return f"<em>{parts[0]}</em>=<code class='docutils literal notranslate'>{parts[1]}</code>"
35+
text = matcher.group(1)
36+
if '=' not in text and ':' not in text:
37+
return f'<code class="ansible-option literal notranslate"><strong>{text}</strong></code>'
38+
return f'<code class="ansible-option-value literal notranslate">{text}</code>'
3939

4040

4141
def html_ify(text):
@@ -59,9 +59,9 @@ def html_ify(text):
5959
r"<code class='docutils literal notranslate'>\1</code>", text)
6060
text, _counts['option-name'] = _SEM_OPTION_NAME.subn(_option_name_html, text)
6161
text, _counts['option-value'] = _SEM_OPTION_VALUE.subn(
62-
r"<code class='docutils literal notranslate'>\1</code>", text)
62+
r"<code class='ansible-value literal notranslate'>\1</code>", text)
6363
text, _counts['environment-var'] = _SEM_ENV_VARIABLE.subn(
64-
r"<code class='docutils literal notranslate'>\1</code>", text)
64+
r"<code class='xref std std-envvar literal notranslate'>\1</code>", text)
6565
text, _counts['ruler'] = _RULER.subn(r"<hr/>", text)
6666

6767
text = text.strip()
@@ -96,15 +96,6 @@ def do_max(seq):
9696
# https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#character-level-inline-markup-1
9797
# for further information.
9898

99-
def _option_name_rst(matcher):
100-
parts = matcher.group(1).split('=', 1)
101-
start = f"\\ :strong:`{rst_escape(parts[0], escape_ending_whitespace=True)}`\\ "
102-
if len(parts) == 1:
103-
return start
104-
end = f"\\ :literal:`{rst_escape(parts[1], escape_ending_whitespace=True)}`\\ "
105-
return f'{start}={end}'
106-
107-
10899
def _rst_ify_italic(m):
109100
return f"\\ :emphasis:`{rst_escape(m.group(1), escape_ending_whitespace=True)}`\\ "
110101

@@ -141,6 +132,18 @@ def _rst_ify_const(m):
141132
return f"\\ :literal:`{rst_escape(m.group(1), escape_ending_whitespace=True)}`\\ "
142133

143134

135+
def _rst_ify_option_name(m):
136+
return f"\\ :ansopt:`{rst_escape(m.group(1), escape_ending_whitespace=True)}`\\ "
137+
138+
139+
def _rst_ify_value(m):
140+
return f"\\ :ansval:`{rst_escape(m.group(1), escape_ending_whitespace=True)}`\\ "
141+
142+
143+
def _rst_ify_envvar(m):
144+
return f"\\ :envvar:`{rst_escape(m.group(1), escape_ending_whitespace=True)}`\\ "
145+
146+
144147
def rst_ify(text):
145148
''' convert symbols like I(this is in italics) to valid restructured text '''
146149

@@ -155,9 +158,9 @@ def rst_ify(text):
155158
text, _counts['url'] = _URL.subn(_rst_ify_url, text)
156159
text, _counts['ref'] = _REF.subn(_rst_ify_ref, text)
157160
text, _counts['const'] = _CONST.subn(_rst_ify_const, text)
158-
text, _counts['option-name'] = _SEM_OPTION_NAME.subn(_option_name_rst, text)
159-
text, _counts['option-value'] = _SEM_OPTION_VALUE.subn(_rst_ify_const, text)
160-
text, _counts['environment-var'] = _SEM_ENV_VARIABLE.subn(_rst_ify_const, text)
161+
text, _counts['option-name'] = _SEM_OPTION_NAME.subn(_rst_ify_option_name, text)
162+
text, _counts['option-value'] = _SEM_OPTION_VALUE.subn(_rst_ify_value, text)
163+
text, _counts['environment-var'] = _SEM_ENV_VARIABLE.subn(_rst_ify_envvar, text)
161164
text, _counts['ruler'] = _RULER.subn('\n\n.. raw:: html\n\n <hr>\n\n', text)
162165

163166
flog.fields(counts=_counts).info('Number of macros converted to rst equivalents')

src/antsibull/lint_extra_docs.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
import docutils.utils
1212
import rstcheck
1313

14+
from docutils.parsers.rst import roles as docutils_roles
15+
16+
from sphinx_antsibull_ext import roles as antsibull_roles
17+
1418
from .extra_docs import (
1519
find_extra_docs,
1620
lint_required_conditions,
@@ -46,6 +50,12 @@ def lint_optional_conditions(content: str, path: str, collection_name: str
4650
return [(result[0], 0, result[1]) for result in results]
4751

4852

53+
def _setup_rstcheck():
54+
'''Make sure that rstcheck knows about our roles.'''
55+
for name, role in antsibull_roles.ROLES.items():
56+
docutils_roles.register_local_role(name, role)
57+
58+
4959
def lint_collection_extra_docs_files(path_to_collection: str
5060
) -> t.List[t.Tuple[str, int, int, str]]:
5161
try:
@@ -56,6 +66,7 @@ def lint_collection_extra_docs_files(path_to_collection: str
5666
result = []
5767
all_labels = set()
5868
docs = find_extra_docs(path_to_collection)
69+
_setup_rstcheck()
5970
for doc in docs:
6071
try:
6172
# Load content

src/sphinx_antsibull_ext/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414

1515
from .assets import setup_assets
16+
from .roles import setup_roles
1617

1718

1819
def setup(app):
@@ -24,6 +25,9 @@ def setup(app):
2425
# Add assets
2526
setup_assets(app)
2627

28+
# Add roles
29+
setup_roles(app)
30+
2731
return dict(
2832
parallel_read_safe=True,
2933
parallel_write_safe=True,

src/sphinx_antsibull_ext/roles.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# coding: utf-8
2+
# Author: Felix Fontein <[email protected]>
3+
# License: GPLv3+
4+
# Copyright: Ansible Project, 2021
5+
'''
6+
Add roles for semantic markup.
7+
'''
8+
9+
from docutils import nodes
10+
11+
12+
def option_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
13+
"""Format Ansible option key, or option key-value.
14+
15+
Returns 2 part tuple containing list of nodes to insert into the
16+
document and a list of system messages. Both are allowed to be
17+
empty.
18+
19+
:param name: The role name used in the document.
20+
:param rawtext: The entire markup snippet, with role.
21+
:param text: The text marked with the role.
22+
:param lineno: The line number where rawtext appears in the input.
23+
:param inliner: The inliner instance that called us.
24+
:param options: Directive options for customization.
25+
:param content: The directive content for customization.
26+
"""
27+
children = []
28+
classes = []
29+
if '=' not in text and ':' not in text:
30+
children.append(nodes.strong(rawtext, text))
31+
rawtext = ''
32+
text = ''
33+
classes.append('ansible-option')
34+
else:
35+
classes.append('ansible-option-value')
36+
return [nodes.literal(rawtext, text, *children, classes=classes)], []
37+
38+
39+
def value_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
40+
"""Format Ansible option value.
41+
42+
Returns 2 part tuple containing list of nodes to insert into the
43+
document and a list of system messages. Both are allowed to be
44+
empty.
45+
46+
:param name: The role name used in the document.
47+
:param rawtext: The entire markup snippet, with role.
48+
:param text: The text marked with the role.
49+
:param lineno: The line number where rawtext appears in the input.
50+
:param inliner: The inliner instance that called us.
51+
:param options: Directive options for customization.
52+
:param content: The directive content for customization.
53+
"""
54+
return [nodes.literal(rawtext, text, classes=['ansible-value'])], []
55+
56+
57+
ROLES = {
58+
'ansopt': option_role,
59+
'ansval': value_role,
60+
}
61+
62+
63+
def setup_roles(app):
64+
'''
65+
Setup roles for a Sphinx app object.
66+
'''
67+
for name, role in ROLES.items():
68+
app.add_role(name, role)

0 commit comments

Comments
 (0)