discard """ outputsub: "" """ # tests for rstgen module. import ../../lib/packages/docutils/rstgen import ../../lib/packages/docutils/rst import unittest, strutils, strtabs import std/private/miscdollars proc toHtml(input: string, rstOptions: RstParseOptions = {roSupportMarkdown, roNimFile}, error: ref string = nil, warnings: ref seq[string] = nil): string = ## If `error` is nil then no errors should be generated. ## The same goes for `warnings`. proc testMsgHandler(filename: string, line, col: int, msgkind: MsgKind, arg: string) = let mc = msgkind.whichMsgClass let a = $msgkind % arg var message: string toLocation(message, filename, line, col + ColRstOffset) message.add " $1: $2" % [$mc, a] if mc == mcError: doAssert error != nil, "unexpected RST error '" & message & "'" error[] = message # we check only first error because subsequent ones may be meaningless raise newException(EParseError, message) else: doAssert warnings != nil, "unexpected RST warning '" & message & "'" warnings[].add message try: result = rstToHtml(input, rstOptions, defaultConfig(), msgHandler=testMsgHandler) except EParseError: discard # inline code tags (for parsing originated from highlite.nim) proc id(str: string): string = """""" & str & "" proc op(str: string): string = """""" & str & "" proc pu(str: string): string = """""" & str & "" suite "YAML syntax highlighting": test "Basics": let input = """.. code-block:: yaml %YAML 1.2 --- a string: string a list: - item 1 - item 2 a map: ? key : value ...""" let output = input.toHtml({}) doAssert output == """
%YAML 1.2
---
a string: string
a list:
  - item 1
  - item 2
a map:
? key
: value
...
""" test "Block scalars": let input = """.. code-block:: yaml a literal block scalar: | some text # not a comment # a comment, since less indented # another comment a folded block scalar: >2 some text # not a comment since indented as specified # a comment another literal block scalar: |+ # comment after header allowed, since more indented than parent""" let output = input.toHtml({}) doAssert output == """
a literal block scalar: |
  some text
  # not a comment
 # a comment, since less indented
  # another comment
a folded block scalar: >2
   some text
  # not a comment since indented as specified
 # a comment
another literal block scalar:
  |+ # comment after header
 allowed, since more indented than parent
""" test "Directives": let input = """.. code-block:: yaml %YAML 1.2 --- %not a directive ... %a directive ... a string % not a directive ... %TAG ! !foo:""" let output = input.toHtml({}) doAssert output == """
%YAML 1.2
---
%not a directive
...
%a directive
...
a string
% not a directive
...
%TAG ! !foo:
""" test "Flow Style and Numbers": let input = """.. code-block:: yaml { "quoted string": 42, 'single quoted string': false, [ list, "with", 'entries' ]: 73.32e-73, more numbers: [-783, 11e78], not numbers: [ 42e, 0023, +32.37, 8 ball] }""" let output = input.toHtml({}) doAssert output == """
{
  "quoted string": 42,
  'single quoted string': false,
  [ list, "with", 'entries' ]: 73.32e-73,
  more numbers: [-783, 11e78],
  not numbers: [ 42e, 0023, +32.37, 8 ball]
}
""" test "Directives: warnings": let input = dedent""" .. non-existant-warning: Paragraph. .. another.wrong:warning::: Paragraph. """ var warnings = new seq[string] let output = input.toHtml(warnings=warnings) check output == "" doAssert warnings[].len == 2 check "(1, 24) Warning: RST style:" in warnings[0] check "double colon :: may be missing at end of 'non-existant-warning'" in warnings[0] check "(3, 25) Warning: RST style:" in warnings[1] check "RST style: too many colons for a directive (should be ::)" in warnings[1] test "not a directive": let input = "..warning:: I am not a warning." check input.toHtml == input test "Anchors, Aliases, Tags": let input = """.. code-block:: yaml --- !!map !!str string: ! 42 ? &anchor !!seq []: : !localtag foo alias: *anchor """ let output = input.toHtml({}) doAssert output == """
--- !!map
!!str string: !<tag:yaml.org,2002:int> 42
? &anchor !!seq []:
: !localtag foo
alias: *anchor
""" test "Edge cases": let input = """.. code-block:: yaml ... %a string: a:string:not:a:map ... not a list: -2 -3 -4 example.com/not/a#comment: ?not a map key """ let output = input.toHtml({}) doAssert output == """
...
 %a string:
  a:string:not:a:map
...
not a list:
  -2
  -3
  -4
example.com/not/a#comment:
  ?not a map key
""" suite "RST/Markdown general": test "RST emphasis": doAssert rstToHtml("*Hello* **world**!", {}, newStringTable(modeStyleInsensitive)) == "Hello world!" test "Markdown links": check("(( [Nim](https://nim-lang.org/) ))".toHtml == """(( Nim ))""") check("(([Nim](https://nim-lang.org/)))".toHtml == """((Nim))""") check("[[Nim](https://nim-lang.org/)]".toHtml == """[Nim]""") test "Markdown tables": let input1 = """ | A1 header | A2 \| not fooled | :--- | ----: | | C1 | C2 **bold** | ignored | | D1 `code \|` | D2 | also ignored | E1 \| text | | | F2 without pipe not in table""" let output1 = input1.toHtml #[ TODO: `\|` inside a table cell should render as `|` `|` outside a table cell should render as `\|` consistently with markdown, see https://stackoverflow.com/a/66557930/1426932 ]# check(output1 == """
A1 headerA2 | not fooled
C1C2 bold
D1 """ & id"code" & " " & op"\|" & """D2
E1 | text
F2 without pipe

not in table

""") let input2 = """ | A1 header | A2 | | --- | --- |""" let output2 = input2.toHtml doAssert output2 == """
A1 headerA2
""" test "RST tables": let input1 = """ Test 2 column/4 rows table: ==== === H0 H1 ==== === A0 A1 ==== === A2 A3 ==== === A4 A5 ==== === """ let output1 = rstToLatex(input1, {}) doAssert "{|X|X|}" in output1 # 2 columns doAssert count(output1, "\\\\") == 4 # 4 rows for cell in ["H0", "H1", "A0", "A1", "A2", "A3", "A4", "A5"]: doAssert cell in output1 let input2 = """ Now test 3 columns / 2 rows, and also borders containing 4 =, 3 =, 1 = signs: ==== === = H0 H1 H ==== === = A0 A1 X Ax Y ==== === = """ let output2 = rstToLatex(input2, {}) doAssert "{|X|X|X|}" in output2 # 3 columns doAssert count(output2, "\\\\") == 2 # 2 rows for cell in ["H0", "H1", "H", "A0", "A1", "X", "Ax", "Y"]: doAssert cell in output2 test "RST adornments": let input1 = """ Check that a few punctuation symbols are not parsed as adornments: :word1: word2 .... word3 """ let output1 = input1.toHtml discard output1 test "RST sections": let input1 = """ Long chapter name ''''''''''''''''''' """ let output1 = input1.toHtml doAssert "Long chapter name" in output1 and "Some chapter" in output6 # check that overline and underline match let input7 = dedent """ ------------ Some chapter ----------- """ var error7 = new string let output7 = input7.toHtml(error=error7) check(error7[] == "input(1, 1) Error: new section expected (underline " & "\'-----------\' does not match overline \'------------\')") let input8 = dedent """ ----------- Overflow ----------- """ var error8 = new string let output8 = input8.toHtml(error=error8) check(error8[] == "input(1, 1) Error: new section expected (overline " & "\'-----------\' is too short)") # check that hierarchy of title styles works let input9good = dedent """ Level1 ====== Level2 ------ Level3 ~~~~~~ L1 == Another2 -------- More3 ~~~~~ """ let output9good = input9good.toHtml doAssert "

Level1

" in output9good doAssert "

Level2

" in output9good doAssert "

Level3

" in output9good doAssert "

L1

" in output9good doAssert "

Another2

" in output9good doAssert "

More3

" in output9good # check that swap causes an exception let input9Bad = dedent """ Level1 ====== Level2 ------ Level3 ~~~~~~ L1 == More ~~~~ Another ------- """ var error9Bad = new string let output9Bad = input9bad.toHtml(error=error9Bad) check(error9Bad[] == "input(15, 1) Error: new section expected (section " & "level inconsistent: underline ~~~~~ unexpectedly found, while " & "the following intermediate section level(s) are missing on " & "lines 12..15: underline -----)") # the same as input9good but with overline headings # first overline heading has a special meaning: document title let input10 = dedent """ ====== Title0 ====== +++++++++ SubTitle0 +++++++++ ------ Level1 ------ Level2 ------ ~~~~~~ Level3 ~~~~~~ -- L1 -- Another2 -------- ~~~~~ More3 ~~~~~ """ var option: bool var rstGenera: RstGenerator var output10: string rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", {}) rstGenera.renderRstToOut(rstParse(input10, "", 1, 1, option, {}), output10) doAssert rstGenera.meta[metaTitle] == "Title0" doAssert rstGenera.meta[metaSubTitle] == "SubTitle0" doAssert "

Level1

" in output10 doAssert "

Level2

" in output10 doAssert "

Level3

" in output10 doAssert "

L1

" in output10 doAssert "

Another2

" in output10 doAssert "

More3

" in output10 # check that a paragraph prevents interpreting overlines as document titles let input11 = dedent """ Paragraph ====== Title0 ====== +++++++++ SubTitle0 +++++++++ """ var option11: bool var rstGenera11: RstGenerator var output11: string rstGenera11.initRstGenerator(outHtml, defaultConfig(), "input", {}) rstGenera11.renderRstToOut(rstParse(input11, "", 1, 1, option11, {}), output11) doAssert rstGenera11.meta[metaTitle] == "" doAssert rstGenera11.meta[metaSubTitle] == "" doAssert "

Title0

" in output11 doAssert "

SubTitle0

" in output11 # check that RST and Markdown headings don't interfere let input12 = dedent """ ====== Title0 ====== MySection1a +++++++++++ # MySection1b MySection1c +++++++++++ ##### MySection5a MySection2a ----------- """ var option12: bool var rstGenera12: RstGenerator var output12: string rstGenera12.initRstGenerator(outHtml, defaultConfig(), "input", {}) rstGenera12.renderRstToOut(rstParse(input12, "", 1, 1, option12, {roSupportMarkdown}), output12) doAssert rstGenera12.meta[metaTitle] == "Title0" doAssert rstGenera12.meta[metaSubTitle] == "" doAssert output12 == "\n

MySection1a

" & # RST "\n

MySection1b

" & # Markdown "\n

MySection1c

" & # RST "\n
MySection5a
" & # Markdown "\n

MySection2a

" # RST test "RST inline text": let input1 = "GC_step" let output1 = input1.toHtml doAssert output1 == "GC_step" test "RST links": let input1 = """ Want to learn about `my favorite programming language`_? .. _my favorite programming language: https://nim-lang.org""" let output1 = input1.toHtml doAssert "" in output1 test "Markdown code block": let input1 = """ ``` let x = 1 ``` """ let output1 = input1.toHtml doAssert """" & id"foo" & op"." & id"bar" & "") check("""`foo\`\`bar`""".toHtml == """""" & id"foo" & pu"`" & pu"`" & id"bar" & "") check("""`foo\`bar`""".toHtml == """""" & id"foo" & pu"`" & id"bar" & "") check("""`\`bar`""".toHtml == """""" & pu"`" & id"bar" & "") check("""`a\b\x\\ar`""".toHtml == """""" & id"a" & op"""\""" & id"b" & op"""\""" & id"x" & op"""\\""" & id"ar" & "") test "inline literal": check """``foo.bar``""".toHtml == """foo.bar""" check """``foo\bar``""".toHtml == """foo\bar""" check """``f\`o\\o\b`ar``""".toHtml == """f\`o\\o\b`ar""" test "default-role": # nim(default) -> literal -> nim -> code(=literal) let input = dedent""" Par1 `value1`. .. default-role:: literal Par2 `value2`. .. default-role:: nim Par3 `value3`. .. default-role:: code Par4 `value4`.""" let p1 = """Par1 """ & id"value1" & "." let p2 = """

Par2 value2.

""" let p3 = """

Par3 """ & id"value3" & ".

" let p4 = """

Par4 value4.

""" let expected = p1 & p2 & "\n" & p3 & "\n" & p4 & "\n" check(input.toHtml == expected) test "role directive": let input = dedent""" .. role:: y(code) :language: yaml .. role:: brainhelp(code) :language: brainhelp """ var warnings = new seq[string] let output = input.toHtml(warnings=warnings) check(warnings[].len == 1 and "language 'brainhelp' not supported" in warnings[0]) test "RST comments": let input1 = """ Check that comment disappears: .. some comment """ let output1 = input1.toHtml doAssert output1 == "Check that comment disappears:" test "RST line blocks": let input1 = """ ===== Test1 ===== | | | line block | other line """ var option: bool var rstGenera: RstGenerator var output1: string rstGenera.initRstGenerator(outHtml, defaultConfig(), "input", {}) rstGenera.renderRstToOut(rstParse(input1, "", 1, 1, option, {}), output1) doAssert rstGenera.meta[metaTitle] == "Test1" # check that title was not overwritten to '|' doAssert output1 == "



line block
other line

" let output1l = rstToLatex(input1, {}) doAssert "line block\n\n" in output1l doAssert "other line\n\n" in output1l doAssert output1l.count("\\vspace") == 2 + 2 # +2 surrounding paddings let input2 = dedent""" Paragraph1 | Paragraph2""" let output2 = input2.toHtml doAssert "Paragraph1


Paragraph2

\n" == output2 let input3 = dedent""" | xxx | yyy | zzz""" let output3 = input3.toHtml doAssert "xxx
" in output3 doAssert "yyy
" in output3 doAssert "zzz
" in output3 # check that '| ' with a few spaces is still parsed as new line let input4 = dedent""" | xxx | | zzz""" let output4 = input4.toHtml doAssert "xxx

" in output4 doAssert "zzz
" in output4 test "RST enumerated lists": let input1 = dedent """ 1. line1 1 2. line2 2 3. line3 3 4. line4 4 5. line5 5 """ let output1 = input1.toHtml for i in 1..5: doAssert ($i & ". line" & $i) notin output1 doAssert ("
  • line" & $i & " " & $i & "
  • ") in output1 let input2 = dedent """ 3. line3 4. line4 5. line5 7. line7 8. line8 """ let output2 = input2.toHtml for i in [3, 4, 5, 7, 8]: doAssert ($i & ". line" & $i) notin output2 doAssert ("
  • line" & $i & "
  • ") in output2 # check that nested enumerated lists work let input3 = dedent """ 1. a) string1 2. string2 """ let output3 = input3.toHtml doAssert count(output3, "
      ") == 2 doAssert "
    1. string1
    2. " in output3 and "
    3. string2
    4. " in output3 let input4 = dedent """ Check that enumeration specifiers are respected 9. string1 10. string2 12. string3 b) string4 c) string5 e) string6 """ let output4 = input4.toHtml doAssert count(output4, "
        ") == 4 for enumerator in [9, 12]: doAssert "start=\"$1\"" % [$enumerator] in output4 for enumerator in [2, 5]: # 2=b, 5=e doAssert "start=\"$1\"" % [$enumerator] in output4 let input5 = dedent """ Check that auto-numbered enumeration lists work. #. string1 #. string2 #. string3 #) string5 #) string6 """ let output5 = input5.toHtml doAssert count(output5, "
          ") == 2 doAssert count(output5, "
        1. ") == 5 let input5a = dedent """ Auto-numbered RST list can start with 1 even when Markdown support is on. 1. string1 #. string2 #. string3 """ let output5a = input5a.toHtml doAssert count(output5a, "
            ") == 1 doAssert count(output5a, "
          1. ") == 3 let input6 = dedent """ ... And for alphabetic enumerators too! b. string1 #. string2 #. string3 """ let output6 = input6.toHtml doAssert count(output6, "
              ") == 1 doAssert count(output6, "
            1. ") == 3 doAssert "start=\"2\"" in output6 and "class=\"loweralpha simple\"" in output6 let input7 = dedent """ ... And for uppercase alphabetic enumerators. C. string1 #. string2 #. string3 """ let output7 = input7.toHtml doAssert count(output7, "
                ") == 1 doAssert count(output7, "
              1. ") == 3 doAssert "start=\"3\"" in output7 and "class=\"upperalpha simple\"" in output7 # check that it's not recognized as enum.list without indentation on 2nd line let input8 = dedent """ Paragraph. A. stringA B. stringB C. string1 string2 """ var warnings8 = new seq[string] let output8 = input8.toHtml(warnings = warnings8) check(warnings8[].len == 1) check("input(6, 1) Warning: RST style: \n" & " not enough indentation on line 6" in warnings8[0]) doAssert output8 == "Paragraph.
                  " & "
                1. stringA
                2. \n
                3. stringB
                4. \n
                \n

                C. string1 string2

                \n" test "Markdown enumerated lists": let input1 = dedent """ Below are 2 enumerated lists: Markdown-style (5 items) and RST (1 item) 1. line1 1. line2 1. line3 1. line4 1. line5 #. lineA """ let output1 = input1.toHtml for i in 1..5: doAssert ($i & ". line" & $i) notin output1 doAssert ("
              2. line" & $i & "
              3. ") in output1 doAssert count(output1, "
                  ") == 2 test "RST bullet lists": let input1 = dedent """ * line1 1 * line2 2 * line3 3 * line4 4 * line5 5 """ let output1 = input1.toHtml for i in 1..5: doAssert ("
                1. line" & $i & " " & $i & "
                2. ") in output1 doAssert count(output1, "
                    ") == 1 test "Nim RST footnotes and citations": # check that auto-label footnote enumerated properly after a manual one let input1 = dedent """ .. [1] Body1. .. [#note] Body2 Ref. [#note]_ """ let output1 = input1.toHtml doAssert output1.count(">[1]") == 1 doAssert output1.count(">[2]") == 2 doAssert "href=\"#footnote-note\"" in output1 doAssert ">[-1]" notin output1 doAssert "Body1." in output1 doAssert "Body2" in output1 # check that there are NO footnotes/citations, only comments: let input2 = dedent """ .. [1 #] Body1. .. [# note] Body2. .. [wrong citation] That gives you a comment. .. [not&allowed] That gives you a comment. Not references[#note]_[1 #]_ [wrong citation]_ and [not&allowed]_. """ let output2 = input2.toHtml doAssert output2 == "Not references[#note]_[1 #]_ [wrong citation]_ and [not&allowed]_. " # check that auto-symbol footnotes work: let input3 = dedent """ Ref. [*]_ and [*]_ and [*]_. .. [*] Body1 .. [*] Body2. .. [*] Body3. .. [*] Body4 And [*]_. """ let output3 = input3.toHtml # both references and footnotes. Footnotes have link to themselves. doAssert output3.count("href=\"#footnotesym-1\">[*]") == 2 doAssert output3.count("href=\"#footnotesym-2\">[**]") == 2 doAssert output3.count("href=\"#footnotesym-3\">[***]") == 2 doAssert output3.count("href=\"#footnotesym-4\">[^]") == 2 # footnote group doAssert output3.count("
                    " & "
                    ") == 1 # footnotes doAssert output3.count("
                    " & "[*]
                    ") == 1 doAssert output3.count("
                    " & "[**]
                    ") == 1 doAssert output3.count("
                    " & "[***]
                    ") == 1 doAssert output3.count("
                    " & "[^]
                    ") == 1 for i in 1 .. 4: doAssert ("Body" & $i) in output3 # check manual, auto-number and auto-label footnote enumeration let input4 = dedent """ .. [3] Manual1. .. [#] Auto-number1. .. [#mylabel] Auto-label1. .. [#note] Auto-label2. .. [#] Auto-number2. Ref. [#note]_ and [#]_ and [#]_. """ let output4 = input4.toHtml doAssert ">[-1]" notin output1 let order = @[ "footnote-3", "[3]", "Manual1.", "footnoteauto-1", "[1]", "Auto-number1", "footnote-mylabel", "[2]", "Auto-label1", "footnote-note", "[4]", "Auto-label2", "footnoteauto-2", "[5]", "Auto-number2", ] for i in 0 .. order.len-2: let pos1 = output4.find(order[i]) let pos2 = output4.find(order[i+1]) doAssert pos1 >= 0 doAssert pos2 >= 0 doAssert pos1 < pos2 # forgot [#]_ let input5 = dedent """ .. [3] Manual1. .. [#] Auto-number1. .. [#note] Auto-label2. Ref. [#note]_ """ var error5 = new string let output5 = input5.toHtml(error=error5) check(error5[] == "input(6, 1) Error: mismatch in number of footnotes " & "and their refs: 1 (lines 2) != 0 (lines ) for auto-numbered " & "footnotes") # extra [*]_ let input6 = dedent """ Ref. [*]_ .. [*] Auto-Symbol. Ref. [*]_ """ var error6 = new string let output6 = input6.toHtml(error=error6) check(error6[] == "input(6, 1) Error: mismatch in number of footnotes " & "and their refs: 1 (lines 3) != 2 (lines 2, 6) for auto-symbol " & "footnotes") let input7 = dedent """ .. [Some:CITATION-2020] Citation. Ref. [some:citation-2020]_. """ let output7 = input7.toHtml doAssert output7.count("href=\"#citation-somecoloncitationminus2020\"") == 2 doAssert output7.count("[Some:CITATION-2020]") == 1 doAssert output7.count("[some:citation-2020]") == 1 doAssert output3.count("
                    " & "
                    ") == 1 let input8 = dedent """ .. [Some] Citation. Ref. [som]_. """ var warnings8 = new seq[string] let output8 = input8.toHtml(warnings=warnings8) check(warnings8[] == @["input(4, 1) Warning: unknown substitution " & "\'citation-som\'"]) # check that footnote group does not break parsing of other directives: let input9 = dedent """ .. [Some] Citation. .. _`internal anchor`: .. [Another] Citation. .. just comment. .. [Third] Citation. Paragraph1. Paragraph2 ref `internal anchor`_. """ let output9 = input9.toHtml #doAssert "id=\"internal-anchor\"" in output9 #doAssert "internal anchor" notin output9 doAssert output9.count("
                    " & "
                    ") == 1 doAssert output9.count("
                    ") == 3 doAssert "just comment" notin output9 # check that nested citations/footnotes work let input10 = dedent """ Paragraph1 [#]_. .. [First] Citation. .. [#] Footnote. .. [Third] Citation. """ let output10 = input10.toHtml doAssert output10.count("
                    " & "
                    ") == 3 doAssert output10.count("
                    ") == 3 doAssert "[First]" in output10 doAssert "[1]" in output10 doAssert "[Third]" in output10 let input11 = ".. [note]\n" # should not crash let output11 = input11.toHtml doAssert "[note]" in output11 # check that references to auto-numbered footnotes work let input12 = dedent """ Ref. [#]_ and [#]_ STOP. .. [#] Body1. .. [#] Body3 .. [2] Body2. """ let output12 = input12.toHtml let orderAuto = @[ "#footnoteauto-1", "[1]", "#footnoteauto-2", "[3]", "STOP.", "Body1.", "Body3", "Body2." ] for i in 0 .. orderAuto.len-2: let pos1 = output12.find(orderAuto[i]) let pos2 = output12.find(orderAuto[i+1]) doAssert pos1 >= 0 doAssert pos2 >= 0 doAssert pos1 < pos2 test "Nim (RST extension) code-block": # check that presence of fields doesn't consume the following text as # its code (which is a literal block) let input0 = dedent """ .. code-block:: nim :number-lines: 0 Paragraph1""" let output0 = input0.toHtml doAssert "

                    Paragraph1

                    " in output0 test "Nim code-block :number-lines:": let input = dedent """ .. code-block:: nim :number-lines: 55 x y """ check "
                    55\n56\n
                    " in input.toHtml test "RST admonitions": # check that all admonitions are implemented let input0 = dedent """ .. admonition:: endOf admonition .. attention:: endOf attention .. caution:: endOf caution .. danger:: endOf danger .. error:: endOf error .. hint:: endOf hint .. important:: endOf important .. note:: endOf note .. tip:: endOf tip .. warning:: endOf warning """ let output0 = input0.toHtml for a in ["admonition", "attention", "caution", "danger", "error", "hint", "important", "note", "tip", "warning" ]: doAssert "endOf " & a & "
                    " in output0 # Test that admonition does not swallow up the next paragraph. let input1 = dedent """ .. error:: endOfError Test paragraph. """ let output1 = input1.toHtml doAssert "endOfError
                    " in output1 doAssert "

                    Test paragraph.

                    " in output1 doAssert "class=\"admonition admonition-error\"" in output1 # Test that second line is parsed as continuation of the first line. let input2 = dedent """ .. error:: endOfError Test2p. Test paragraph. """ let output2 = input2.toHtml doAssert "endOfError Test2p.
                    " in output2 doAssert "

                    Test paragraph.

                    " in output2 doAssert "class=\"admonition admonition-error\"" in output2 let input3 = dedent """ .. note:: endOfNote """ let output3 = input3.toHtml doAssert "endOfNote
                    " in output3 doAssert "class=\"admonition admonition-info\"" in output3 test "RST internal links": let input1 = dedent """ Start. .. _target000: Paragraph. .. _target001: * bullet list * Y .. _target002: 1. enumeration list 2. Y .. _target003: term 1 Definition list 1. .. _target004: | line block .. _target005: :a: field list value .. _target006: -a option description .. _target007: :: Literal block .. _target008: Doctest blocks are not implemented. .. _target009: block quote .. _target010: ===== ===== ======= A B A and B ===== ===== ======= False False False ===== ===== ======= .. _target100: .. CAUTION:: admonition .. _target101: .. code:: nim const pi = 3.14 .. _target102: .. code-block:: const pi = 3.14 Paragraph2. .. _target202: ---- That was a transition. """ let output1 = input1.toHtml doAssert "

                    target300" in output2 doAssert "href=\"#subsectiona\">target301" in output2 doAssert "href=\"#citation-cit2020\">target103" in output2 let output2l = rstToLatex(input2, {}) doAssert "\\label{section-xyz}\\hypertarget{section-xyz}{}" in output2l doAssert "\\hyperlink{section-xyz}{target300}" in output2l doAssert "\\hyperlink{subsectiona}{target301}" in output2l test "RST internal links (inline)": let input1 = dedent """ Paragraph with _`some definition`. Ref. `some definition`_. """ let output1 = input1.toHtml doAssert "some definition" in output1 doAssert "Ref. some definition" in output1 test "RST references (additional symbols)": # check that ., _, -, +, : are allowed symbols in references without ` ` let input1 = dedent """ sec.1 ----- 2-other:sec+c_2 ^^^^^^^^^^^^^^^ .. _link.1_2021: Paragraph Ref. sec.1_! and 2-other:sec+c_2_;and link.1_2021_. """ let output1 = input1.toHtml doAssert "id=\"secdot1\"" in output1 doAssert "id=\"Z2minusothercolonsecplusc-2\"" in output1 doAssert "id=\"linkdot1-2021\"" in output1 let ref1 = "sec.1" let ref2 = "2-other:sec+c_2" let ref3 = "link.1_2021" let refline = "Ref. " & ref1 & "! and " & ref2 & ";and " & ref3 & "." doAssert refline in output1 test "Option lists 1": # check that "* b" is not consumed by previous bullet item because of # incorrect indentation handling in option lists let input = dedent """ * a -m desc -n very long desc * b""" let output = input.toHtml check(output.count("") == 2) check(output.count("

                    -m
                    """ & """
                    desc
                    """ in output) check("""
                    -n
                    """ & """
                    very long desc
                    """ in output) test "Option lists 2": # check that 2nd option list is not united with the 1st let input = dedent """ * a -m desc -n very long desc -d option""" let output = input.toHtml check(output.count("-m""" & """
                    desc
                    """ in output) check("""
                    -n
                    """ & """
                    very long desc
                    """ in output) check("""
                    -d
                    """ & """
                    option
                    """ in output) check "

                    option

                    " notin output test "Option list 3 (double /)": let input = dedent """ * a //compile compile1 //doc doc1 cont -d option""" let output = input.toHtml check(output.count("compile""" & """
                    compile1
                    """ in output) check("""
                    doc
                    """ & """
                    doc1 cont
                    """ in output) check("""
                    -d
                    """ & """
                    option
                    """ in output) check "

                    option

                    " notin output test "Roles: subscript prefix/postfix": let expected = "See some text." check "See :subscript:`some text`.".toHtml == expected check "See `some text`:subscript:.".toHtml == expected test "Roles: correct parsing from beginning of line": let expected = "3He is an isotope of helium." check """:superscript:`3`\ He is an isotope of helium.""".toHtml == expected check """:sup:`3`\ He is an isotope of helium.""".toHtml == expected check """`3`:sup:\ He is an isotope of helium.""".toHtml == expected check """`3`:superscript:\ He is an isotope of helium.""".toHtml == expected test "Roles: warnings": let input = dedent""" See function :py:func:`spam`. See also `egg`:py:class:. """ var warnings = new seq[string] let output = input.toHtml(warnings=warnings) doAssert warnings[].len == 2 check "(1, 14) Warning: " in warnings[0] check "language 'py:func' not supported" in warnings[0] check "(3, 15) Warning: " in warnings[1] check "language 'py:class' not supported" in warnings[1] check("""

                    See function spam.

                    """ & "\n" & """

                    See also egg.

                    """ & "\n" == output) test "(not) Roles: check escaping 1": let expected = """See :subscript:""" & """""" & id"some" & " " & id"text" & "." check """See \:subscript:`some text`.""".toHtml == expected check """See :subscript\:`some text`.""".toHtml == expected test "(not) Roles: check escaping 2": check("""See :subscript:\`some text\`.""".toHtml == "See :subscript:`some text`.") test "Field list": check(":field: text".toHtml == """""" & """""" & """""" & """""" & "\n
                    field: text
                    ") test "Field list: body after newline": let output = dedent """ :field: text1""".toHtml check "field:" in output check "" in output test "Field list (incorrect)": check ":field:text".toHtml == ":field:text" suite "RST/Code highlight": test "Basic Python code highlight": let pythonCode = """ .. code-block:: python def f_name(arg=42): print(f"{arg}") """ let expected = """

                    def f_name(arg=42): print(f"{arg}")

                    """ check strip(rstToHtml(pythonCode, {}, newStringTable(modeCaseSensitive))) == strip(expected)
                    text1