12
12
from urllib .parse import quote
13
13
14
14
from antsibull_core .logging import log
15
+ from jinja2 .runtime import Context
16
+ from jinja2 .utils import pass_context
15
17
18
+ from ..semantic_helper import parse_option , parse_return_value
19
+ from .filters import extract_plugin_data
16
20
from .parser import Command , CommandSet , convert_text
17
21
18
22
mlog = log .fields (mod = __name__ )
@@ -33,9 +37,13 @@ def _create_error(text: str, error: str) -> str:
33
37
34
38
35
39
class _Context :
40
+ j2_context : Context
36
41
counts : t .Dict [str , int ]
42
+ plugin_fqcn : t .Optional [str ]
43
+ plugin_type : t .Optional [str ]
37
44
38
- def __init__ (self ):
45
+ def __init__ (self , j2_context : Context ):
46
+ self .j2_context = j2_context
39
47
self .counts = {
40
48
'italic' : 0 ,
41
49
'bold' : 0 ,
@@ -51,6 +59,7 @@ def __init__(self):
51
59
'return-value' : 0 ,
52
60
'ruler' : 0 ,
53
61
}
62
+ self .plugin_fqcn , self .plugin_type = extract_plugin_data (j2_context )
54
63
55
64
56
65
# In the following, we make heavy use of escaped whitespace ("\ ") being removed from the output.
@@ -157,6 +166,107 @@ def handle(self, parameters: t.List[str], context: t.Any) -> str:
157
166
return f"<code class='docutils literal notranslate'>{ html_escape (parameters [0 ])} </code>"
158
167
159
168
169
+ class _OptionName (Command ):
170
+ command = 'O'
171
+ parameter_count = 1
172
+ escaped_content = True
173
+
174
+ def handle (self , parameters : t .List [str ], context : t .Any ) -> str :
175
+ context .counts ['option-name' ] += 1
176
+ if context .plugin_fqcn is None or context .plugin_type is None :
177
+ raise Exception ('The markup O(...) cannot be used outside a plugin or role' )
178
+ text = parameters [0 ]
179
+ try :
180
+ plugin_fqcn , plugin_type , option_link , option , value = parse_option (
181
+ text , context .plugin_fqcn , context .plugin_type , require_plugin = False )
182
+ except ValueError as exc :
183
+ return _create_error (f'O({ text } )' , str (exc ))
184
+ if value is None :
185
+ cls = 'ansible-option'
186
+ text = f'{ option } '
187
+ strong_start = '<strong>'
188
+ strong_end = '</strong>'
189
+ else :
190
+ cls = 'ansible-option-value'
191
+ text = f'{ option } ={ value } '
192
+ strong_start = ''
193
+ strong_end = ''
194
+ if plugin_fqcn and plugin_type and plugin_fqcn .count ('.' ) >= 2 :
195
+ # TODO: handle role arguments (entrypoint!)
196
+ namespace , name , plugin = plugin_fqcn .split ('.' , 2 )
197
+ url = f'../../{ namespace } /{ name } /{ plugin } _{ plugin_type } .html'
198
+ fragment = f'parameter-{ quote (option_link .replace ("." , "/" ))} '
199
+ link_start = (
200
+ f'<a class="reference internal" href="{ url } #{ fragment } ">'
201
+ '<span class="std std-ref"><span class="pre">'
202
+ )
203
+ link_end = '</span></span></a>'
204
+ else :
205
+ link_start = ''
206
+ link_end = ''
207
+ return (
208
+ f'<code class="{ cls } literal notranslate">'
209
+ f'{ strong_start } { link_start } { text } { link_end } { strong_end } </code>'
210
+ )
211
+
212
+
213
+ class _OptionValue (Command ):
214
+ command = 'V'
215
+ parameter_count = 1
216
+ escaped_content = True
217
+
218
+ def handle (self , parameters : t .List [str ], context : t .Any ) -> str :
219
+ context .counts ['option-value' ] += 1
220
+ text = parameters [0 ]
221
+ return f'<code class="ansible-value literal notranslate">{ html_escape (text )} </code>'
222
+
223
+
224
+ class _EnvVariable (Command ):
225
+ command = 'E'
226
+ parameter_count = 1
227
+ escaped_content = True
228
+
229
+ def handle (self , parameters : t .List [str ], context : t .Any ) -> str :
230
+ context .counts ['environment-var' ] += 1
231
+ text = parameters [0 ]
232
+ return f'<code class="xref std std-envvar literal notranslate">{ html_escape (text )} </code>'
233
+
234
+
235
+ class _RetValue (Command ):
236
+ command = 'RV'
237
+ parameter_count = 1
238
+ escaped_content = True
239
+
240
+ def handle (self , parameters : t .List [str ], context : t .Any ) -> str :
241
+ context .counts ['return-value' ] += 1
242
+ if context .plugin_fqcn is None or context .plugin_type is None :
243
+ raise Exception ('The markup RV(...) cannot be used outside a plugin or role' )
244
+ text = parameters [0 ]
245
+ try :
246
+ plugin_fqcn , plugin_type , rv_link , rv , value = parse_return_value (
247
+ text , context .plugin_fqcn , context .plugin_type , require_plugin = False )
248
+ except ValueError as exc :
249
+ return _create_error (f'RV({ text } )' , str (exc ))
250
+ cls = 'ansible-return-value'
251
+ if value is None :
252
+ text = f'{ rv } '
253
+ else :
254
+ text = f'{ rv } ={ value } '
255
+ if plugin_fqcn and plugin_type and plugin_fqcn .count ('.' ) >= 2 :
256
+ namespace , name , plugin = plugin_fqcn .split ('.' , 2 )
257
+ url = f'../../{ namespace } /{ name } /{ plugin } _{ plugin_type } .html'
258
+ fragment = f'return-{ quote (rv_link .replace ("." , "/" ))} '
259
+ link_start = (
260
+ f'<a class="reference internal" href="{ url } #{ fragment } ">'
261
+ '<span class="std std-ref"><span class="pre">'
262
+ )
263
+ link_end = '</span></span></a>'
264
+ else :
265
+ link_start = ''
266
+ link_end = ''
267
+ return f'<code class="{ cls } literal notranslate">{ link_start } { text } { link_end } </code>'
268
+
269
+
160
270
class _HorizontalLine (Command ):
161
271
command = 'HORIZONTALLINE'
162
272
parameter_count = 0
@@ -176,16 +286,21 @@ def handle(self, parameters: t.List[str], context: t.Any) -> str:
176
286
_Link (),
177
287
_Ref (),
178
288
_Const (),
289
+ _OptionName (),
290
+ _OptionValue (),
291
+ _EnvVariable (),
292
+ _RetValue (),
179
293
_HorizontalLine (),
180
294
])
181
295
182
296
183
- def html_ify (text : str ) -> str :
297
+ @pass_context
298
+ def html_ify (context : Context , text : str ) -> str :
184
299
''' convert symbols like I(this is in italics) to valid HTML '''
185
300
flog = mlog .fields (func = 'html_ify' )
186
301
flog .fields (text = text ).debug ('Enter' )
187
302
188
- our_context = _Context ()
303
+ our_context = _Context (context )
189
304
190
305
try :
191
306
text = convert_text (text , _COMMAND_SET , html_escape , our_context )
0 commit comments