discard """
outputsub: ""
"""
# tests for rstgen module.
import ../../lib/packages/docutils/rstgen
import ../../lib/packages/docutils/rst
import unittest, strutils, strtabs
proc toHtml(input: string): string =
rstToHtml(input, {roSupportMarkdown}, defaultConfig())
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 = rstTohtml(input, {}, defaultConfig())
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 = rstToHtml(input, {}, defaultConfig())
doAssert output == """a literal block scalar: |
some text
# not a comment
a folded block scalar: >2
some text
# not a comment since indented as specified
another literal block scalar:
|+
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 = rstToHtml(input, {}, defaultConfig())
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 = rstToHtml(input, {}, defaultConfig())
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 "Anchors, Aliases, Tags":
let input = """.. code-block:: yaml
--- !!map
!!str string: ! 42
? &anchor !!seq []:
: !localtag foo
alias: *anchor
"""
let output = rstToHtml(input, {}, defaultConfig())
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 = rstToHtml(input, {}, defaultConfig())
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":
let
a = rstToHtml("(( [Nim](https://nim-lang.org/) ))", {roSupportMarkdown}, defaultConfig())
b = rstToHtml("(([Nim](https://nim-lang.org/)))", {roSupportMarkdown}, defaultConfig())
c = rstToHtml("[[Nim](https://nim-lang.org/)]", {roSupportMarkdown}, defaultConfig())
doAssert a == """(( Nim ))"""
doAssert b == """((Nim))"""
doAssert c == """[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 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
doAssert output1 == """A1 header | A2 | not fooled |
C1 | C2 bold |
D1 code | | D2 |
E1 | text | |
| F2 without pipe |
not in table
"""
let input2 = """
| A1 header | A2 |
| --- | --- |"""
let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
doAssert output2 == """"""
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 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
discard output1
test "RST sections":
let input1 = """
Long chapter name
'''''''''''''''''''
"""
let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
doAssert "Long chapter name" in output1 and "Some chapter
" in output6
# check that overline and underline match
let input7 = dedent """
------------
Some chapter
-----------
"""
expect(EParseError):
let output7 = rstToHtml(input7, {roSupportMarkdown}, defaultConfig())
let input8 = dedent """
-----------
Overflow
-----------
"""
expect(EParseError):
let output8 = rstToHtml(input8, {roSupportMarkdown}, defaultConfig())
# check that hierarchy of title styles works
let input9good = dedent """
Level1
======
Level2
------
Level3
~~~~~~
L1
==
Another2
--------
More3
~~~~~
"""
let output9good = rstToHtml(input9good, {roSupportMarkdown}, defaultConfig())
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
-------
"""
expect(EParseError):
let output9Bad = rstToHtml(input9Bad, {roSupportMarkdown}, defaultConfig())
# 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 ==
"\nMySection1a
" & # RST
"\nMySection1b
" & # Markdown
"\nMySection1c
" & # RST
"\nMySection5a
" & # Markdown
"\nMySection2a
" # 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 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
doAssert "" in output1
test "Markdown code block":
let input1 = """
```
let x = 1
``` """
let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
doAssert "
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 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
doAssert "Paragraph1
Paragraph2
\n" == output2
let input3 = dedent"""
| xxx
| yyy
| zzz"""
let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig())
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 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig())
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 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
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 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
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 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig())
doAssert count(output3, "") == 2
doAssert "- string1
" in output3 and "- string2
" 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 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig())
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 = rstToHtml(input5, {roSupportMarkdown}, defaultConfig())
doAssert count(output5, "") == 2
doAssert count(output5, "- ") == 5
let input5a = dedent """
Auto-numbered RST list can start with 1 even when Markdown support is on.
1. string1
#. string2
#. string3
"""
let output5a = rstToHtml(input5a, {roSupportMarkdown}, defaultConfig())
doAssert count(output5a, "
") == 1
doAssert count(output5a, "- ") == 3
let input6 = dedent """
... And for alphabetic enumerators too!
b. string1
#. string2
#. string3
"""
let output6 = rstToHtml(input6, {roSupportMarkdown}, defaultConfig())
doAssert count(output6, "
") == 1
doAssert count(output6, "- ") == 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 = rstToHtml(input7, {roSupportMarkdown}, defaultConfig())
doAssert count(output7, "
") == 1
doAssert count(output7, "- ") == 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 """
A. string1
string2
"""
# TODO: find out hot to catch warning here instead of throwing a defect
expect(AssertionDefect):
let output8 = input8.toHtml
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 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
for i in 1..5:
doAssert ($i & ". line" & $i) notin output1
doAssert ("
- line" & $i & "
") 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 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
for i in 1..5:
doAssert ("- line" & $i & " " & $i & "
") 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("" &
"