1import nixos_render_docs as nrd
2import pytest
3
4from markdown_it.token import Token
5
6class Converter(nrd.md.Converter[nrd.docbook.DocBookRenderer]):
7 # actual renderer doesn't matter, we're just parsing.
8 def __init__(self, manpage_urls: dict[str, str]) -> None:
9 super().__init__()
10 self._renderer = nrd.docbook.DocBookRenderer(manpage_urls)
11
12def test_attr_span_parsing() -> None:
13 c = Converter({})
14 assert c._parse("[]{#test}") == [
15 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
16 content='', markup='', info='', meta={}, block=True, hidden=False),
17 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1, content='[]{#test}',
18 markup='', info='', meta={}, block=True, hidden=False,
19 children=[
20 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'id': 'test'}, map=None, level=0,
21 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
22 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
23 children=None, content='', markup='', info='', meta={}, block=False, hidden=False)
24 ]),
25 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0,
26 children=None, content='', markup='', info='', meta={}, block=True, hidden=False)
27 ]
28 assert c._parse("[]{.test}") == [
29 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
30 content='', markup='', info='', meta={}, block=True, hidden=False),
31 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1, content='[]{.test}',
32 markup='', info='', meta={}, block=True, hidden=False,
33 children=[
34 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'class': 'test'}, map=None,
35 level=0, children=None, content='', markup='', info='', meta={}, block=False,
36 hidden=False),
37 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
38 children=None, content='', markup='', info='', meta={}, block=False, hidden=False)
39 ]),
40 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0,
41 children=None, content='', markup='', info='', meta={}, block=True, hidden=False)
42 ]
43 assert c._parse("[]{.test1 .test2 #foo .test3 .test4}") == [
44 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
45 content='', markup='', info='', meta={}, block=True, hidden=False),
46 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
47 content='[]{.test1 .test2 #foo .test3 .test4}',
48 markup='', info='', meta={}, block=True, hidden=False,
49 children=[
50 Token(type='attr_span_begin', tag='span', nesting=1,
51 attrs={'class': 'test1 test2 test3 test4', 'id': 'foo'}, map=None, level=0,
52 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
53 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
54 children=None, content='', markup='', info='', meta={}, block=False, hidden=False)
55 ]),
56 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0,
57 children=None, content='', markup='', info='', meta={}, block=True, hidden=False)
58 ]
59 assert c._parse("[]{#a #a}") == [
60 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
61 content='', markup='', info='', meta={}, block=True, hidden=False),
62 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
63 content='[]{#a #a}', markup='', info='', meta={}, block=True, hidden=False,
64 children=[
65 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
66 content='[]{#a #a}', markup='', info='', meta={}, block=False, hidden=False)
67 ]),
68 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
69 content='', markup='', info='', meta={}, block=True, hidden=False)
70 ]
71 assert c._parse("[]{foo}") == [
72 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
73 content='', markup='', info='', meta={}, block=True, hidden=False),
74 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
75 content='[]{foo}', markup='', info='', meta={}, block=True, hidden=False,
76 children=[
77 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
78 content='[]{foo}', markup='', info='', meta={}, block=False, hidden=False)
79 ]),
80 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
81 content='', markup='', info='', meta={}, block=True, hidden=False)
82 ]
83
84def test_attr_span_formatted() -> None:
85 c = Converter({})
86 assert c._parse("a[b c `d` ***e***]{#test}f") == [
87 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0,
88 children=None, content='', markup='', info='', meta={}, block=True, hidden=False),
89 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
90 content='a[b c `d` ***e***]{#test}f', markup='', info='', meta={}, block=True, hidden=False,
91 children=[
92 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0,
93 children=None, content='a', markup='', info='', meta={}, block=False, hidden=False),
94 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'id': 'test'}, map=None, level=0,
95 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
96 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
97 content='b c ', markup='', info='', meta={}, block=False, hidden=False),
98 Token(type='code_inline', tag='code', nesting=0, attrs={}, map=None, level=1,
99 children=None, content='d', markup='`', info='', meta={}, block=False, hidden=False),
100 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
101 content=' ', markup='', info='', meta={}, block=False, hidden=False),
102 Token(type='em_open', tag='em', nesting=1, attrs={}, map=None, level=1, children=None,
103 content='', markup='*', info='', meta={}, block=False, hidden=False),
104 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=2, children=None,
105 content='', markup='', info='', meta={}, block=False, hidden=False),
106 Token(type='strong_open', tag='strong', nesting=1, attrs={}, map=None, level=2,
107 children=None, content='', markup='**', info='', meta={}, block=False, hidden=False),
108 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=3, children=None,
109 content='e', markup='', info='', meta={}, block=False, hidden=False),
110 Token(type='strong_close', tag='strong', nesting=-1, attrs={}, map=None, level=2,
111 children=None, content='', markup='**', info='', meta={}, block=False, hidden=False),
112 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=2, children=None,
113 content='', markup='', info='', meta={}, block=False, hidden=False),
114 Token(type='em_close', tag='em', nesting=-1, attrs={}, map=None, level=1, children=None,
115 content='', markup='*', info='', meta={}, block=False, hidden=False),
116 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
117 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
118 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
119 content='f', markup='', info='', meta={}, block=False, hidden=False)
120 ]),
121 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
122 content='', markup='', info='', meta={}, block=True, hidden=False)
123 ]
124
125def test_attr_span_in_heading() -> None:
126 c = Converter({})
127 # inline anchors in headers are allowed, but header attributes should be preferred
128 assert c._parse("# foo []{#bar} baz") == [
129 Token(type='heading_open', tag='h1', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
130 content='', markup='#', info='', meta={}, block=True, hidden=False),
131 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
132 content='foo []{#bar} baz', markup='', info='', meta={}, block=True, hidden=False,
133 children=[
134 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
135 content='foo ', markup='', info='', meta={}, block=False, hidden=False),
136 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'id': 'bar'}, map=None, level=0,
137 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
138 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
139 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
140 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
141 content=' baz', markup='', info='', meta={}, block=False, hidden=False)
142 ]),
143 Token(type='heading_close', tag='h1', nesting=-1, attrs={}, map=None, level=0, children=None,
144 content='', markup='#', info='', meta={}, block=True, hidden=False)
145 ]
146
147def test_attr_span_on_links() -> None:
148 c = Converter({})
149 assert c._parse("[ [a](#bar) ]{#foo}") == [
150 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
151 content='', markup='', info='', meta={}, block=True, hidden=False),
152 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1, content='[ [a](#bar) ]{#foo}',
153 markup='', info='', meta={}, block=True, hidden=False,
154 children=[
155 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'id': 'foo'}, map=None, level=0,
156 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
157 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
158 content=' ', markup='', info='', meta={}, block=False, hidden=False),
159 Token(type='link_open', tag='a', nesting=1, attrs={'href': '#bar'}, map=None, level=1,
160 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
161 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=2, children=None,
162 content='a', markup='', info='', meta={}, block=False, hidden=False),
163 Token(type='link_close', tag='a', nesting=-1, attrs={}, map=None, level=1, children=None,
164 content='', markup='', info='', meta={}, block=False, hidden=False),
165 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
166 content=' ', markup='', info='', meta={}, block=False, hidden=False),
167 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
168 children=None, content='', markup='', info='', meta={}, block=False, hidden=False)
169 ]),
170 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
171 content='', markup='', info='', meta={}, block=True, hidden=False)
172 ]
173
174def test_attr_span_nested() -> None:
175 # inline anchors may contain more anchors (even though this is a bit pointless)
176 c = Converter({})
177 assert c._parse("[ [a]{#bar} ]{#foo}") == [
178 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
179 content='', markup='', info='', meta={}, block=True, hidden=False),
180 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
181 content='[ [a]{#bar} ]{#foo}', markup='', info='', meta={}, block=True, hidden=False,
182 children=[
183 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'id': 'foo'}, map=None, level=0,
184 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
185 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
186 content=' ', markup='', info='', meta={}, block=False, hidden=False),
187 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'id': 'bar'}, map=None, level=1,
188 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
189 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=2, children=None,
190 content='a', markup='', info='', meta={}, block=False, hidden=False),
191 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=1,
192 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
193 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
194 content=' ', markup='', info='', meta={}, block=False, hidden=False),
195 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
196 children=None, content='', markup='', info='', meta={}, block=False, hidden=False)
197 ]),
198 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
199 content='', markup='', info='', meta={}, block=True, hidden=False)
200 ]
201
202def test_attr_span_escaping() -> None:
203 c = Converter({})
204 assert c._parse("\\[a]{#bar}") == [
205 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
206 content='', markup='', info='', meta={}, block=True, hidden=False),
207 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
208 content='\\[a]{#bar}', markup='', info='', meta={}, block=True, hidden=False,
209 children=[
210 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
211 content='[a]{#bar}', markup='\\[', info='escape', meta={}, block=False, hidden=False)
212 ]),
213 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
214 content='', markup='', info='', meta={}, block=True, hidden=False)
215 ]
216 assert c._parse("\\\\[a]{#bar}") == [
217 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
218 content='', markup='', info='', meta={}, block=True, hidden=False),
219 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
220 content='\\\\[a]{#bar}', markup='', info='', meta={}, block=True, hidden=False,
221 children=[
222 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
223 content='\\', markup='\\\\', info='escape', meta={}, block=False, hidden=False),
224 Token(type='attr_span_begin', tag='span', nesting=1, attrs={'id': 'bar'}, map=None, level=0,
225 children=None, content='', markup='', info='', meta={}, block=False, hidden=False),
226 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
227 content='a', markup='', info='', meta={}, block=False, hidden=False),
228 Token(type='attr_span_end', tag='span', nesting=-1, attrs={}, map=None, level=0,
229 children=None, content='', markup='', info='', meta={}, block=False, hidden=False)
230 ]),
231 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
232 content='', markup='', info='', meta={}, block=True, hidden=False)
233 ]
234 assert c._parse("\\\\\\[a]{#bar}") == [
235 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
236 content='', markup='', info='', meta={}, block=True, hidden=False),
237 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
238 children=[
239 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
240 content='\\[a]{#bar}', markup='\\\\', info='escape', meta={}, block=False, hidden=False)
241 ],
242 content='\\\\\\[a]{#bar}', markup='', info='', meta={}, block=True, hidden=False),
243 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
244 content='', markup='', info='', meta={}, block=True, hidden=False)
245 ]
246
247def test_inline_comment_basic() -> None:
248 c = Converter({})
249 assert c._parse("a <!-- foo --><!----> b") == [
250 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
251 content='', markup='', info='', meta={}, block=True, hidden=False),
252 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
253 content='a <!-- foo --><!----> b', markup='', info='', meta={}, block=True, hidden=False,
254 children=[
255 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
256 content='a b', markup='', info='', meta={}, block=False, hidden=False)
257 ]),
258 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
259 content='', markup='', info='', meta={}, block=True, hidden=False)
260 ]
261 assert c._parse("a<!-- b -->") == [
262 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
263 content='', markup='', info='', meta={}, block=True, hidden=False),
264 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
265 content='a<!-- b -->', markup='', info='', meta={}, block=True, hidden=False,
266 children=[
267 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
268 content='a', markup='', info='', meta={}, block=False, hidden=False)
269 ]),
270 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
271 content='', markup='', info='', meta={}, block=True, hidden=False)
272 ]
273
274def test_inline_comment_does_not_nest_in_code() -> None:
275 c = Converter({})
276 assert c._parse("`a<!-- b -->c`") == [
277 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
278 content='', markup='', info='', meta={}, block=True, hidden=False),
279 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
280 content='`a<!-- b -->c`', markup='', info='', meta={}, block=True, hidden=False,
281 children=[
282 Token(type='code_inline', tag='code', nesting=0, attrs={}, map=None, level=0, children=None,
283 content='a<!-- b -->c', markup='`', info='', meta={}, block=False, hidden=False)
284 ]),
285 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
286 content='', markup='', info='', meta={}, block=True, hidden=False)
287 ]
288
289def test_inline_comment_does_not_nest_elsewhere() -> None:
290 c = Converter({})
291 assert c._parse("*a<!-- b -->c*") == [
292 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
293 content='', markup='', info='', meta={}, block=True, hidden=False),
294 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
295 content='*a<!-- b -->c*', markup='', info='', meta={}, block=True, hidden=False,
296 children=[
297 Token(type='em_open', tag='em', nesting=1, attrs={}, map=None, level=0, children=None,
298 content='', markup='*', info='', meta={}, block=False, hidden=False),
299 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
300 content='ac', markup='', info='', meta={}, block=False, hidden=False),
301 Token(type='em_close', tag='em', nesting=-1, attrs={}, map=None, level=0, children=None,
302 content='', markup='*', info='', meta={}, block=False, hidden=False)
303 ]),
304 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
305 content='', markup='', info='', meta={}, block=True, hidden=False)
306 ]
307
308def test_inline_comment_can_be_escaped() -> None:
309 c = Converter({})
310 assert c._parse("a\\<!-- b -->c") == [
311 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
312 content='', markup='', info='', meta={}, block=True, hidden=False),
313 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
314 content='a\\<!-- b -->c', markup='', info='', meta={}, block=True, hidden=False,
315 children=[
316 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
317 content='a<!-- b -->c', markup='', info='', meta={}, block=False, hidden=False)
318 ]),
319 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
320 content='', markup='', info='', meta={}, block=True, hidden=False)
321 ]
322 assert c._parse("a\\\\<!-- b -->c") == [
323 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
324 content='', markup='', info='', meta={}, block=True, hidden=False),
325 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
326 children=[
327 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
328 content='a\\c', markup='', info='', meta={}, block=False, hidden=False)
329 ],
330 content='a\\\\<!-- b -->c', markup='', info='', meta={}, block=True, hidden=False),
331 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
332 content='', markup='', info='', meta={}, block=True, hidden=False)
333 ]
334 assert c._parse("a\\\\\\<!-- b -->c") == [
335 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
336 content='', markup='', info='', meta={}, block=True, hidden=False),
337 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
338 children=[
339 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
340 content='a\\<!-- b -->c', markup='', info='', meta={}, block=False, hidden=False)
341 ],
342 content='a\\\\\\<!-- b -->c', markup='', info='', meta={}, block=True, hidden=False),
343 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
344 content='', markup='', info='', meta={}, block=True, hidden=False)
345 ]
346
347def test_block_comment() -> None:
348 c = Converter({})
349 assert c._parse("<!-- a -->") == []
350 assert c._parse("<!-- a\n-->") == []
351 assert c._parse("<!--\na\n-->") == []
352 assert c._parse("<!--\n\na\n\n-->") == []
353 assert c._parse("<!--\n\n```\n\n\n```\n\n-->") == []
354
355def test_heading_attributes() -> None:
356 c = Converter({})
357 assert c._parse("# foo *bar* {#hid}") == [
358 Token(type='heading_open', tag='h1', nesting=1, attrs={'id': 'hid'}, map=[0, 1], level=0,
359 children=None, content='', markup='#', info='', meta={}, block=True, hidden=False),
360 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
361 content='foo *bar* {#hid}', markup='', info='', meta={}, block=True, hidden=False,
362 children=[
363 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
364 content='foo ', markup='', info='', meta={}, block=False, hidden=False),
365 Token(type='em_open', tag='em', nesting=1, attrs={}, map=None, level=0, children=None,
366 content='', markup='*', info='', meta={}, block=False, hidden=False),
367 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=1, children=None,
368 content='bar', markup='', info='', meta={}, block=False, hidden=False),
369 Token(type='em_close', tag='em', nesting=-1, attrs={}, map=None, level=0, children=None,
370 content='', markup='*', info='', meta={}, block=False, hidden=False),
371 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
372 content='', markup='', info='', meta={}, block=False, hidden=False)
373 ]),
374 Token(type='heading_close', tag='h1', nesting=-1, attrs={}, map=None, level=0, children=None,
375 content='', markup='#', info='', meta={}, block=True, hidden=False)
376 ]
377 assert c._parse("# foo--bar {#id-with--double-dashes}") == [
378 Token(type='heading_open', tag='h1', nesting=1, attrs={'id': 'id-with--double-dashes'}, map=[0, 1],
379 level=0, children=None, content='', markup='#', info='', meta={}, block=True, hidden=False),
380 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
381 content='foo--bar {#id-with--double-dashes}', markup='', info='', meta={}, block=True,
382 hidden=False,
383 children=[
384 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
385 content='foo–bar', markup='', info='', meta={}, block=False, hidden=False)
386 ]),
387 Token(type='heading_close', tag='h1', nesting=-1, attrs={}, map=None, level=0, children=None,
388 content='', markup='#', info='', meta={}, block=True, hidden=False)
389 ]
390
391def test_admonitions() -> None:
392 c = Converter({})
393 assert c._parse("::: {.note}") == [
394 Token(type='admonition_open', tag='div', nesting=1, attrs={}, map=[0, 1], level=0,
395 children=None, content='', markup=':::', info=' {.note}', meta={'kind': 'note'}, block=True,
396 hidden=False),
397 Token(type='admonition_close', tag='div', nesting=-1, attrs={}, map=None, level=0,
398 children=None, content='', markup=':::', info='', meta={}, block=True, hidden=False)
399 ]
400 assert c._parse("::: {.caution}") == [
401 Token(type='admonition_open', tag='div', nesting=1, attrs={}, map=[0, 1], level=0,
402 children=None, content='', markup=':::', info=' {.caution}', meta={'kind': 'caution'},
403 block=True, hidden=False),
404 Token(type='admonition_close', tag='div', nesting=-1, attrs={}, map=None, level=0,
405 children=None, content='', markup=':::', info='', meta={}, block=True, hidden=False)
406 ]
407 assert c._parse("::: {.tip}") == [
408 Token(type='admonition_open', tag='div', nesting=1, attrs={}, map=[0, 1], level=0,
409 children=None, content='', markup=':::', info=' {.tip}', meta={'kind': 'tip'}, block=True,
410 hidden=False),
411 Token(type='admonition_close', tag='div', nesting=-1, attrs={}, map=None, level=0,
412 children=None, content='', markup=':::', info='', meta={}, block=True, hidden=False)
413 ]
414 assert c._parse("::: {.important}") == [
415 Token(type='admonition_open', tag='div', nesting=1, attrs={}, map=[0, 1], level=0,
416 children=None, content='', markup=':::', info=' {.important}', meta={'kind': 'important'},
417 block=True, hidden=False),
418 Token(type='admonition_close', tag='div', nesting=-1, attrs={}, map=None, level=0,
419 children=None, content='', markup=':::', info='', meta={}, block=True, hidden=False)
420 ]
421 assert c._parse("::: {.warning}") == [
422 Token(type='admonition_open', tag='div', nesting=1, attrs={}, map=[0, 1], level=0,
423 children=None, content='', markup=':::', info=' {.warning}', meta={'kind': 'warning'},
424 block=True, hidden=False),
425 Token(type='admonition_close', tag='div', nesting=-1, attrs={}, map=None, level=0,
426 children=None, content='', markup=':::', info='', meta={}, block=True, hidden=False)
427 ]
428
429def test_example() -> None:
430 c = Converter({})
431 assert c._parse("::: {.example}\n# foo") == [
432 Token(type='example_open', tag='div', nesting=1, attrs={}, map=[0, 2], level=0, children=None,
433 content='', markup=':::', info=' {.example}', meta={}, block=True, hidden=False),
434 Token(type='example_title_open', tag='h1', nesting=1, attrs={}, map=[1, 2], level=1, children=None,
435 content='', markup='#', info='', meta={}, block=True, hidden=False),
436 Token(type='inline', tag='', nesting=0, attrs={}, map=[1, 2], level=2,
437 content='foo', markup='', info='', meta={}, block=True, hidden=False,
438 children=[
439 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
440 content='foo', markup='', info='', meta={}, block=False, hidden=False)
441 ]),
442 Token(type='example_title_close', tag='h1', nesting=-1, attrs={}, map=None, level=1, children=None,
443 content='', markup='#', info='', meta={}, block=True, hidden=False),
444 Token(type='example_close', tag='div', nesting=-1, attrs={}, map=None, level=0, children=None,
445 content='', markup='', info='', meta={}, block=True, hidden=False)
446 ]
447 assert c._parse("::: {#eid .example}\n# foo") == [
448 Token(type='example_open', tag='div', nesting=1, attrs={'id': 'eid'}, map=[0, 2], level=0,
449 children=None, content='', markup=':::', info=' {#eid .example}', meta={}, block=True,
450 hidden=False),
451 Token(type='example_title_open', tag='h1', nesting=1, attrs={}, map=[1, 2], level=1, children=None,
452 content='', markup='#', info='', meta={}, block=True, hidden=False),
453 Token(type='inline', tag='', nesting=0, attrs={}, map=[1, 2], level=2,
454 content='foo', markup='', info='', meta={}, block=True, hidden=False,
455 children=[
456 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
457 content='foo', markup='', info='', meta={}, block=False, hidden=False)
458 ]),
459 Token(type='example_title_close', tag='h1', nesting=-1, attrs={}, map=None, level=1, children=None,
460 content='', markup='#', info='', meta={}, block=True, hidden=False),
461 Token(type='example_close', tag='div', nesting=-1, attrs={}, map=None, level=0, children=None,
462 content='', markup='', info='', meta={}, block=True, hidden=False)
463 ]
464 assert c._parse("::: {.example .note}") == [
465 Token(type='paragraph_open', tag='p', nesting=1, attrs={}, map=[0, 1], level=0, children=None,
466 content='', markup='', info='', meta={}, block=True, hidden=False),
467 Token(type='inline', tag='', nesting=0, attrs={}, map=[0, 1], level=1,
468 content='::: {.example .note}', markup='', info='', meta={}, block=True, hidden=False,
469 children=[
470 Token(type='text', tag='', nesting=0, attrs={}, map=None, level=0, children=None,
471 content='::: {.example .note}', markup='', info='', meta={}, block=False, hidden=False)
472 ]),
473 Token(type='paragraph_close', tag='p', nesting=-1, attrs={}, map=None, level=0, children=None,
474 content='', markup='', info='', meta={}, block=True, hidden=False)
475 ]
476 assert c._parse("::: {.example}\n### foo: `code`\nbar\n:::\nbaz") == [
477 Token(type='example_open', tag='div', nesting=1, map=[0, 3], markup=':::', info=' {.example}',
478 block=True),
479 Token(type='example_title_open', tag='h3', nesting=1, map=[1, 2], level=1, markup='###', block=True),
480 Token(type='inline', tag='', nesting=0, map=[1, 2], level=2, content='foo: `code`', block=True,
481 children=[
482 Token(type='text', tag='', nesting=0, content='foo: '),
483 Token(type='code_inline', tag='code', nesting=0, content='code', markup='`')
484 ]),
485 Token(type='example_title_close', tag='h3', nesting=-1, level=1, markup='###', block=True),
486 Token(type='paragraph_open', tag='p', nesting=1, map=[2, 3], level=1, block=True),
487 Token(type='inline', tag='', nesting=0, map=[2, 3], level=2, content='bar', block=True,
488 children=[
489 Token(type='text', tag='', nesting=0, content='bar')
490 ]),
491 Token(type='paragraph_close', tag='p', nesting=-1, level=1, block=True),
492 Token(type='example_close', tag='div', nesting=-1, markup=':::', block=True),
493 Token(type='paragraph_open', tag='p', nesting=1, map=[4, 5], block=True),
494 Token(type='inline', tag='', nesting=0, map=[4, 5], level=1, content='baz', block=True,
495 children=[
496 Token(type='text', tag='', nesting=0, content='baz')
497 ]),
498 Token(type='paragraph_close', tag='p', nesting=-1, block=True)
499 ]
500
501 with pytest.raises(RuntimeError) as exc:
502 c._parse("::: {.example}\n### foo\n### bar\n:::")
503 assert exc.value.args[0] == 'unexpected non-title heading in example in line 3'
504
505def test_footnotes() -> None:
506 c = Converter({})
507 assert c._parse("text [^foo]\n\n[^foo]: bar") == [
508 Token(type='paragraph_open', tag='p', nesting=1, map=[0, 1], block=True),
509 Token(type='inline', tag='', nesting=0, map=[0, 1], level=1, content='text [^foo]', block=True,
510 children=[
511 Token(type='text', tag='', nesting=0, content='text '),
512 Token(type='footnote_ref', tag='', nesting=0, attrs={'id': 'foo.__back.0'},
513 meta={'id': 0, 'subId': 0, 'label': 'foo', 'target': 'foo'})
514 ]),
515 Token(type='paragraph_close', tag='p', nesting=-1, block=True),
516 Token(type='footnote_block_open', tag='', nesting=1),
517 Token(type='footnote_open', tag='', nesting=1, attrs={'id': 'foo'}, meta={'id': 0, 'label': 'foo'}),
518 Token(type='paragraph_open', tag='p', nesting=1, map=[2, 3], level=1, block=True, hidden=False),
519 Token(type='inline', tag='', nesting=0, map=[2, 3], level=2, content='bar', block=True,
520 children=[
521 Token(type='text', tag='', nesting=0, content='bar')
522 ]),
523 Token(type='footnote_anchor', tag='', nesting=0,
524 meta={'id': 0, 'label': 'foo', 'subId': 0, 'target': 'foo.__back.0'}),
525 Token(type='paragraph_close', tag='p', nesting=-1, level=1, block=True),
526 Token(type='footnote_close', tag='', nesting=-1),
527 Token(type='footnote_block_close', tag='', nesting=-1),
528 ]