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