1import nixos_render_docs as nrd
2import pytest
3import textwrap
4
5from sample_md import sample1
6
7class Renderer(nrd.html.HTMLRenderer):
8 def _pull_image(self, src: str) -> str:
9 return src
10
11class Converter(nrd.md.Converter[nrd.html.HTMLRenderer]):
12 def __init__(self, manpage_urls: dict[str, str], xrefs: dict[str, nrd.manual_structure.XrefTarget]):
13 super().__init__()
14 self._renderer = Renderer(manpage_urls, xrefs)
15
16def unpretty(s: str) -> str:
17 return "".join(map(str.strip, s.splitlines())).replace('␣', ' ').replace('↵', '\n')
18
19def test_lists_styles() -> None:
20 # nested lists rotate through a number of list style
21 c = Converter({}, {})
22 assert c._render("- - - - foo") == unpretty("""
23 <div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;">
24 <li class="listitem">
25 <div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: circle;">
26 <li class="listitem">
27 <div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: square;">
28 <li class="listitem">
29 <div class="itemizedlist"><ul class="itemizedlist compact" style="list-style-type: disc;">
30 <li class="listitem"><p>foo</p></li>
31 </ul></div>
32 </li>
33 </ul></div>
34 </li>
35 </ul></div>
36 </li>
37 </ul></div>
38 """)
39 assert c._render("1. 1. 1. 1. 1. 1. foo") == unpretty("""
40 <div class="orderedlist"><ol class="orderedlist compact" type="1">
41 <li class="listitem">
42 <div class="orderedlist"><ol class="orderedlist compact" type="a">
43 <li class="listitem">
44 <div class="orderedlist"><ol class="orderedlist compact" type="i">
45 <li class="listitem">
46 <div class="orderedlist"><ol class="orderedlist compact" type="A">
47 <li class="listitem">
48 <div class="orderedlist"><ol class="orderedlist compact" type="I">
49 <li class="listitem">
50 <div class="orderedlist"><ol class="orderedlist compact" type="1">
51 <li class="listitem"><p>foo</p></li>
52 </ol></div>
53 </li>
54 </ol></div>
55 </li>
56 </ol></div>
57 </li>
58 </ol></div>
59 </li>
60 </ol></div>
61 </li>
62 </ol></div>
63 """)
64
65def test_xrefs() -> None:
66 # nested lists rotate through a number of list style
67 c = Converter({}, {
68 'foo': nrd.manual_structure.XrefTarget('foo', '<hr/>', 'toc1', 'title1', 'index.html'),
69 'bar': nrd.manual_structure.XrefTarget('bar', '<br/>', 'toc2', 'title2', 'index.html', True),
70 })
71 assert c._render("[](#foo)") == '<p><a class="xref" href="index.html#foo" title="title1" ><hr/></a></p>'
72 assert c._render("[](#bar)") == '<p><a class="xref" href="index.html" title="title2" ><br/></a></p>'
73 with pytest.raises(nrd.html.UnresolvedXrefError) as exc:
74 c._render("[](#baz)")
75 assert exc.value.args[0] == 'bad local reference, id #baz not known'
76
77def test_images() -> None:
78 c = Converter({}, {})
79 assert c._render("") == unpretty("""
80 <p>
81 <div class="mediaobject">
82 <img src="foo" alt="*alt text*" title="title text" />
83 </div>
84 </p>
85 """)
86
87def test_tables() -> None:
88 c = Converter({}, {})
89 assert c._render(textwrap.dedent("""
90 | d | l | m | r |
91 |---|:--|:-:|--:|
92 | a | b | c | d |
93 """)) == unpretty("""
94 <div class="informaltable">
95 <table class="informaltable" border="1">
96 <colgroup>
97 <col align="left" />
98 <col align="left" />
99 <col align="center" />
100 <col align="right" />
101 </colgroup>
102 <thead>
103 <tr>
104 <th align="left">d</th>
105 <th align="left">l</th>
106 <th align="center">m</th>
107 <th align="right">r</th>
108 </tr>
109 </thead>
110 <tbody>
111 <tr>
112 <td align="left">a</td>
113 <td align="left">b</td>
114 <td align="center">c</td>
115 <td align="right">d</td>
116 </tr>
117 </tbody>
118 </table>
119 </div>
120 """)
121
122def test_footnotes() -> None:
123 c = Converter({}, {
124 "bar": nrd.manual_structure.XrefTarget("bar", "", None, None, ""),
125 "bar.__back.0": nrd.manual_structure.XrefTarget("bar.__back.0", "", None, None, ""),
126 "bar.__back.1": nrd.manual_structure.XrefTarget("bar.__back.1", "", None, None, ""),
127 })
128 assert c._render(textwrap.dedent("""
129 foo [^bar] baz [^bar]
130
131 [^bar]: note
132 """)) == unpretty("""
133 <p>
134 foo <a href="#bar" class="footnote" id="bar.__back.0"><sup class="footnote">[1]</sup></a>␣
135 baz <a href="#bar" class="footnote" id="bar.__back.1"><sup class="footnote">[1]</sup></a>
136 </p>
137 <div class="footnotes">
138 <br />
139 <hr style="width:100; text-align:left;margin-left: 0" />
140 <div id="bar" class="footnote">
141 <p>
142 note<a href="#bar.__back.0" class="para"><sup class="para">[1]</sup></a>
143 <a href="#bar.__back.1" class="para"><sup class="para">[1]</sup></a>
144 </p>
145 </div>
146 </div>
147 """)
148
149def test_full() -> None:
150 c = Converter({ 'man(1)': 'http://example.org' }, {})
151 assert c._render(sample1) == unpretty("""
152 <div class="warning">
153 <h3 class="title">Warning</h3>
154 <p>foo</p>
155 <div class="note">
156 <h3 class="title">Note</h3>
157 <p>nested</p>
158 </div>
159 </div>
160 <p>
161 <a class="link" href="link" target="_top">↵
162 multiline↵
163 </a>
164 </p>
165 <p>
166 <a class="link" href="http://example.org" target="_top">
167 <span class="citerefentry"><span class="refentrytitle">man</span>(1)</span>
168 </a> reference
169 </p>
170 <p><a id="b" />some <a id="a" />nested anchors</p>
171 <p>
172 <span class="emphasis"><em>emph</em></span>␣
173 <span class="strong"><strong>strong</strong></span>␣
174 <span class="emphasis"><em>nesting emph <span class="strong"><strong>and strong</strong></span>␣
175 and <code class="literal">code</code></em></span>
176 </p>
177 <div class="itemizedlist">
178 <ul class="itemizedlist " style="list-style-type: disc;">
179 <li class="listitem"><p>wide bullet</p></li>
180 <li class="listitem"><p>list</p></li>
181 </ul>
182 </div>
183 <div class="orderedlist">
184 <ol class="orderedlist " type="1">
185 <li class="listitem"><p>wide ordered</p></li>
186 <li class="listitem"><p>list</p></li>
187 </ol>
188 </div>
189 <div class="itemizedlist">
190 <ul class="itemizedlist compact" style="list-style-type: disc;">
191 <li class="listitem"><p>narrow bullet</p></li>
192 <li class="listitem"><p>list</p></li>
193 </ul>
194 </div>
195 <div class="orderedlist">
196 <ol class="orderedlist compact" type="1">
197 <li class="listitem"><p>narrow ordered</p></li>
198 <li class="listitem"><p>list</p></li>
199 </ol>
200 </div>
201 <div class="blockquote">
202 <blockquote class="blockquote">
203 <p>quotes</p>
204 <div class="blockquote">
205 <blockquote class="blockquote">
206 <p>with <span class="emphasis"><em>nesting</em></span></p>
207 <pre class="programlisting">↵
208 nested code block↵
209 </pre>
210 </blockquote>
211 </div>
212 <div class="itemizedlist">
213 <ul class="itemizedlist compact" style="list-style-type: disc;">
214 <li class="listitem"><p>and lists</p></li>
215 <li class="listitem">
216 <pre class="programlisting">↵
217 containing code↵
218 </pre>
219 </li>
220 </ul>
221 </div>
222 <p>and more quote</p>
223 </blockquote>
224 </div>
225 <div class="orderedlist">
226 <ol class="orderedlist compact" start="100" type="1">
227 <li class="listitem"><p>list starting at 100</p></li>
228 <li class="listitem"><p>goes on</p></li>
229 </ol>
230 </div>
231 <div class="variablelist">
232 <dl class="variablelist">
233 <dt><span class="term">deflist</span></dt>
234 <dd>
235 <div class="blockquote">
236 <blockquote class="blockquote">
237 <p>
238 with a quote↵
239 and stuff
240 </p>
241 </blockquote>
242 </div>
243 <pre class="programlisting">↵
244 code block↵
245 </pre>
246 <pre class="programlisting">↵
247 fenced block↵
248 </pre>
249 <p>text</p>
250 </dd>
251 <dt><span class="term">more stuff in same deflist</span></dt>
252 <dd>
253 <p>foo</p>
254 </dd>
255 </dl>
256 </div>""")