{html_escape(parameters[0])}
"
+class _OptionName(Command):
+ command = 'O'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['option-name'] += 1
+ if context.plugin_fqcn is None or context.plugin_type is None:
+ raise Exception('The markup O(...) cannot be used outside a plugin or role')
+ text = parameters[0]
+ try:
+ plugin_fqcn, plugin_type, option_link, option, value = parse_option(
+ text, context.plugin_fqcn, context.plugin_type, require_plugin=False)
+ except ValueError as exc:
+ return _create_error(f'O({text})', str(exc))
+ if value is None:
+ cls = 'ansible-option'
+ text = f'{option}'
+ strong_start = ''
+ strong_end = ''
+ else:
+ cls = 'ansible-option-value'
+ text = f'{option}={value}'
+ strong_start = ''
+ strong_end = ''
+ if plugin_fqcn and plugin_type and plugin_fqcn.count('.') >= 2:
+ # TODO: handle role arguments (entrypoint!)
+ namespace, name, plugin = plugin_fqcn.split('.', 2)
+ url = f'../../{namespace}/{name}/{plugin}_{plugin_type}.html'
+ fragment = f'parameter-{quote(option_link.replace(".", "/"))}'
+ link_start = (
+ f''
+ ''
+ )
+ link_end = ''
+ else:
+ link_start = ''
+ link_end = ''
+ return (
+ f''
+ f'{strong_start}{link_start}{text}{link_end}{strong_end}
'
+ )
+
+
+class _OptionValue(Command):
+ command = 'V'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['option-value'] += 1
+ text = parameters[0]
+ return f'{html_escape(text)}
'
+
+
+class _EnvVariable(Command):
+ command = 'E'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['environment-var'] += 1
+ text = parameters[0]
+ return f'{html_escape(text)}
'
+
+
+class _RetValue(Command):
+ command = 'RV'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['return-value'] += 1
+ if context.plugin_fqcn is None or context.plugin_type is None:
+ raise Exception('The markup RV(...) cannot be used outside a plugin or role')
+ text = parameters[0]
+ try:
+ plugin_fqcn, plugin_type, rv_link, rv, value = parse_return_value(
+ text, context.plugin_fqcn, context.plugin_type, require_plugin=False)
+ except ValueError as exc:
+ return _create_error(f'RV({text})', str(exc))
+ cls = 'ansible-return-value'
+ if value is None:
+ text = f'{rv}'
+ else:
+ text = f'{rv}={value}'
+ if plugin_fqcn and plugin_type and plugin_fqcn.count('.') >= 2:
+ namespace, name, plugin = plugin_fqcn.split('.', 2)
+ url = f'../../{namespace}/{name}/{plugin}_{plugin_type}.html'
+ fragment = f'return-{quote(rv_link.replace(".", "/"))}'
+ link_start = (
+ f''
+ ''
+ )
+ link_end = ''
+ else:
+ link_start = ''
+ link_end = ''
+ return f'{link_start}{text}{link_end}
'
+
+
class _HorizontalLine(Command):
command = 'HORIZONTALLINE'
parameter_count = 0
@@ -178,16 +290,21 @@ def handle(self, parameters: t.List[str], context: t.Any) -> str:
_Link(),
_Ref(),
_Const(),
+ _OptionName(),
+ _OptionValue(),
+ _EnvVariable(),
+ _RetValue(),
_HorizontalLine(),
])
-def html_ify(text: str) -> str:
+@pass_context
+def html_ify(context: Context, text: str) -> str:
''' convert symbols like I(this is in italics) to valid HTML '''
flog = mlog.fields(func='html_ify')
flog.fields(text=text).debug('Enter')
- our_context = _Context()
+ our_context = _Context(context)
try:
text = convert_text(text, _COMMAND_SET, html_escape, our_context)
diff --git a/src/antsibull_docs/jinja2/rstify.py b/src/antsibull_docs/jinja2/rstify.py
index 6aa72a6f..203f4f37 100644
--- a/src/antsibull_docs/jinja2/rstify.py
+++ b/src/antsibull_docs/jinja2/rstify.py
@@ -11,8 +11,14 @@
import typing as t
+from jinja2.runtime import Context
+from jinja2.utils import pass_context
+
from antsibull_core.logging import log
+from ..semantic_helper import augment_plugin_name_type
+
+from .filters import extract_plugin_data
from .parser import Command, CommandSet, convert_text
@@ -63,9 +69,13 @@ def _create_error(text: str, error: str) -> str:
class _Context:
+ j2_context: Context
counts: t.Dict[str, int]
+ plugin_fqcn: t.Optional[str]
+ plugin_type: t.Optional[str]
- def __init__(self):
+ def __init__(self, j2_context: Context):
+ self.j2_context = j2_context
self.counts = {
'italic': 0,
'bold': 0,
@@ -81,6 +91,7 @@ def __init__(self):
'return-value': 0,
'ruler': 0,
}
+ self.plugin_fqcn, self.plugin_type = extract_plugin_data(j2_context)
# In the following, we make heavy use of escaped whitespace ("\ ") being removed from the output.
@@ -182,6 +193,52 @@ def handle(self, parameters: t.List[str], context: t.Any) -> str:
return f"\\ :literal:`{rst_escape(parameters[0], escape_ending_whitespace=True)}`\\ "
+class _OptionName(Command):
+ command = 'O'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['option-name'] += 1
+ if context.plugin_fqcn is None or context.plugin_type is None:
+ raise Exception('The markup O(...) cannot be used outside a plugin or role')
+ text = augment_plugin_name_type(parameters[0], context.plugin_fqcn, context.plugin_type)
+ return f"\\ :ansopt:`{rst_escape(text, escape_ending_whitespace=True)}`\\ "
+
+
+class _OptionValue(Command):
+ command = 'V'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['option-value'] += 1
+ return f"\\ :ansval:`{rst_escape(parameters[0], escape_ending_whitespace=True)}`\\ "
+
+
+class _EnvVariable(Command):
+ command = 'E'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['environment-var'] += 1
+ return f"\\ :envvar:`{rst_escape(parameters[0], escape_ending_whitespace=True)}`\\ "
+
+
+class _RetValue(Command):
+ command = 'RV'
+ parameter_count = 1
+ escaped_content = True
+
+ def handle(self, parameters: t.List[str], context: t.Any) -> str:
+ context.counts['return-value'] += 1
+ if context.plugin_fqcn is None or context.plugin_type is None:
+ raise Exception('The markup RV(...) cannot be used outside a plugin or role')
+ text = augment_plugin_name_type(parameters[0], context.plugin_fqcn, context.plugin_type)
+ return f"\\ :ansretval:`{rst_escape(text, escape_ending_whitespace=True)}`\\ "
+
+
class _HorizontalLine(Command):
command = 'HORIZONTALLINE'
parameter_count = 0
@@ -201,16 +258,21 @@ def handle(self, parameters: t.List[str], context: t.Any) -> str:
_Link(),
_Ref(),
_Const(),
+ _OptionName(),
+ _OptionValue(),
+ _EnvVariable(),
+ _RetValue(),
_HorizontalLine(),
])
-def rst_ify(text: str) -> str:
+@pass_context
+def rst_ify(context: Context, text: str) -> str:
''' convert symbols like I(this is in italics) to valid restructured text '''
flog = mlog.fields(func='rst_ify')
flog.fields(text=text).debug('Enter')
- our_context = _Context()
+ our_context = _Context(context)
try:
text = convert_text(text, _COMMAND_SET, rst_escape, our_context)
diff --git a/src/antsibull_docs/semantic_helper.py b/src/antsibull_docs/semantic_helper.py
new file mode 100644
index 00000000..e1dbe399
--- /dev/null
+++ b/src/antsibull_docs/semantic_helper.py
@@ -0,0 +1,87 @@
+# Author: Felix Fontein Bar. BAR!
-Totally unrelated to become_user. Even with become_user=foo.
-Might not be compatible when become_user is bar
, though.
Totally unrelated to become_user
. Even with become_user=foo
.
Might not be compatible when become_user
is bar
, though.