8
8
9
9
import json
10
10
import re
11
- from html import escape as html_escape
12
- from urllib .parse import quote
13
11
14
12
import typing as t
15
13
20
18
21
19
mlog = log .fields (mod = __name__ )
22
20
23
- # Warning: If you add to this, then you also have to change ansible-doc
24
- # (ansible/cli/__init__.py) in the ansible/ansible repository
25
- _ITALIC = re .compile (r"\bI\(([^)]+)\)" )
26
- _BOLD = re .compile (r"\bB\(([^)]+)\)" )
27
- _MODULE = re .compile (r"\bM\(([^).]+)\.([^).]+)\.([^)]+)\)" )
28
- _URL = re .compile (r"\bU\(([^)]+)\)" )
29
- _LINK = re .compile (r"\bL\(([^)]+), *([^)]+)\)" )
30
- _REF = re .compile (r"\bR\(([^)]+), *([^)]+)\)" )
31
- _CONST = re .compile (r"\bC\(([^)]+)\)" )
32
- _RULER = re .compile (r"\bHORIZONTALLINE\b" )
33
-
34
21
_EMAIL_ADDRESS = re .compile (r"(?:<{mail}>|\({mail}\)|{mail})" .format (mail = r"[\w.+-]+@[\w.-]+\.\w+" ))
35
22
36
23
37
- def html_ify (text ):
38
- ''' convert symbols like I(this is in italics) to valid HTML '''
39
-
40
- flog = mlog .fields (func = 'html_ify' )
41
- flog .fields (text = text ).debug ('Enter' )
42
- _counts = {}
43
-
44
- text = html_escape (text )
45
- text , _counts ['italic' ] = _ITALIC .subn (r"<em>\1</em>" , text )
46
- text , _counts ['bold' ] = _BOLD .subn (r"<b>\1</b>" , text )
47
- text , _counts ['module' ] = _MODULE .subn (
48
- r"<a href='../../\1/\2/\3_module.html' class='module'>\1.\2.\3</a>" , text )
49
- text , _counts ['url' ] = _URL .subn (r"<a href='\1'>\1</a>" , text )
50
- text , _counts ['ref' ] = _REF .subn (r"<span class='module'>\1</span>" , text )
51
- text , _counts ['link' ] = _LINK .subn (r"<a href='\2'>\1</a>" , text )
52
- text , _counts ['const' ] = _CONST .subn (
53
- r"<code class='docutils literal notranslate'>\1</code>" , text )
54
- text , _counts ['ruler' ] = _RULER .subn (r"<hr/>" , text )
55
-
56
- text = text .strip ()
57
- flog .fields (counts = _counts ).info ('Number of macros converted to html equivalents' )
58
- flog .debug ('Leave' )
59
- return text
60
-
61
-
62
24
def documented_type (text ) -> str :
63
25
''' Convert any python type to a type for documentation '''
64
26
@@ -80,89 +42,6 @@ def do_max(seq):
80
42
return max (seq )
81
43
82
44
83
- # In the following, we make heavy use of escaped whitespace ("\ ") being removed from the output.
84
- # See
85
- # https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#character-level-inline-markup-1
86
- # for further information.
87
-
88
- def _rst_ify_italic (m : 're.Match' ) -> str :
89
- return f"\\ :emphasis:`{ rst_escape (m .group (1 ), escape_ending_whitespace = True )} `\\ "
90
-
91
-
92
- def _rst_ify_bold (m : 're.Match' ) -> str :
93
- return f"\\ :strong:`{ rst_escape (m .group (1 ), escape_ending_whitespace = True )} `\\ "
94
-
95
-
96
- def _rst_ify_module (m : 're.Match' ) -> str :
97
- fqcn = f'{ m .group (1 )} .{ m .group (2 )} .{ m .group (3 )} '
98
- return f"\\ :ref:`{ rst_escape (fqcn )} <ansible_collections.{ fqcn } _module>`\\ "
99
-
100
-
101
- def _escape_url (url : str ) -> str :
102
- # We include '<>[]{}' in safe to allow urls such as 'https://<HOST>:[PORT]/v{version}/' to
103
- # remain unmangled by percent encoding
104
- return quote (url , safe = ':/#?%<>[]{}' )
105
-
106
-
107
- def _rst_ify_link (m : 're.Match' ) -> str :
108
- return f"\\ `{ rst_escape (m .group (1 ))} <{ _escape_url (m .group (2 ))} >`__\\ "
109
-
110
-
111
- def _rst_ify_url (m : 're.Match' ) -> str :
112
- return f"\\ { _escape_url (m .group (1 ))} \\ "
113
-
114
-
115
- def _rst_ify_ref (m : 're.Match' ) -> str :
116
- return f"\\ :ref:`{ rst_escape (m .group (1 ))} <{ m .group (2 )} >`\\ "
117
-
118
-
119
- def _rst_ify_const (m : 're.Match' ) -> str :
120
- # Escaping does not work in double backticks, so we use the :literal: role instead
121
- return f"\\ :literal:`{ rst_escape (m .group (1 ), escape_ending_whitespace = True )} `\\ "
122
-
123
-
124
- def rst_ify (text ):
125
- ''' convert symbols like I(this is in italics) to valid restructured text '''
126
-
127
- flog = mlog .fields (func = 'rst_ify' )
128
- flog .fields (text = text ).debug ('Enter' )
129
- _counts = {}
130
-
131
- text , _counts ['italic' ] = _ITALIC .subn (_rst_ify_italic , text )
132
- text , _counts ['bold' ] = _BOLD .subn (_rst_ify_bold , text )
133
- text , _counts ['module' ] = _MODULE .subn (_rst_ify_module , text )
134
- text , _counts ['link' ] = _LINK .subn (_rst_ify_link , text )
135
- text , _counts ['url' ] = _URL .subn (_rst_ify_url , text )
136
- text , _counts ['ref' ] = _REF .subn (_rst_ify_ref , text )
137
- text , _counts ['const' ] = _CONST .subn (_rst_ify_const , text )
138
- text , _counts ['ruler' ] = _RULER .subn ('\n \n .. raw:: html\n \n <hr>\n \n ' , text )
139
-
140
- flog .fields (counts = _counts ).info ('Number of macros converted to rst equivalents' )
141
- flog .debug ('Leave' )
142
- return text
143
-
144
-
145
- def rst_escape (value : t .Any , escape_ending_whitespace = False ) -> str :
146
- ''' make sure value is converted to a string, and RST special characters are escaped '''
147
-
148
- if not isinstance (value , str ):
149
- value = str (value )
150
-
151
- value = value .replace ('\\ ' , '\\ \\ ' )
152
- value = value .replace ('<' , '\\ <' )
153
- value = value .replace ('>' , '\\ >' )
154
- value = value .replace ('_' , '\\ _' )
155
- value = value .replace ('*' , '\\ *' )
156
- value = value .replace ('`' , '\\ `' )
157
-
158
- if escape_ending_whitespace and value .endswith (' ' ):
159
- value = value + '\\ '
160
- if escape_ending_whitespace and value .startswith (' ' ):
161
- value = '\\ ' + value
162
-
163
- return value
164
-
165
-
166
45
def rst_fmt (text , fmt ):
167
46
''' helper for Jinja2 to do format strings '''
168
47
0 commit comments