summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/docgen.nim9
-rw-r--r--lib/packages/docutils/rst.nim29
-rw-r--r--lib/packages/docutils/rstgen.nim8
-rw-r--r--tests/stdlib/trstgen.nim200
4 files changed, 156 insertions, 90 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index fd5c8b47a..37831c72c 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -25,6 +25,7 @@ from std/private/globs import nativeToUnixPath
 const
   exportSection = skField
   docCmdSkip = "skip"
+  DocColOffset = "## ".len  # assuming that a space was added after ##
 
 type
   TSections = array[TSymKind, Rope]
@@ -322,8 +323,12 @@ proc genComment(d: PDoc, n: PNode): string =
     when false:
       # RFC: to preseve newlines in comments, this would work:
       comment = comment.replace("\n", "\n\n")
-    renderRstToOut(d[], parseRst(comment, toFullPath(d.conf, n.info), toLinenumber(n.info),
-                   toColumn(n.info), (var dummy: bool; dummy), d.options, d.conf), result)
+    renderRstToOut(d[],
+                   parseRst(comment, toFullPath(d.conf, n.info),
+                            toLinenumber(n.info),
+                            toColumn(n.info) + DocColOffset,
+                            (var dummy: bool; dummy), d.options, d.conf),
+                   result)
 
 proc genRecCommentAux(d: PDoc, n: PNode): Rope =
   if n == nil: return nil
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index d54d7fa27..b5eef7610 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -146,7 +146,8 @@
 ## .. _Sphinx directives: https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html
 
 import
-  os, strutils, rstast, algorithm, lists, sequtils
+  os, strutils, rstast, std/enumutils, algorithm, lists, sequtils,
+  std/private/miscdollars
 
 type
   RstParseOption* = enum     ## options for the RST parser
@@ -477,9 +478,10 @@ type
   EParseError* = object of ValueError
 
 const
-  LineRstInit* = 1 ## Initial line number for standalone RST text
-  ColRstInit* = 0 ## Initial column number for standalone RST text
-                  ## (Nim global reporting adds ColOffset=1)
+  LineRstInit* = 1  ## Initial line number for standalone RST text
+  ColRstInit* = 0   ## Initial column number for standalone RST text
+                    ## (Nim global reporting adds ColOffset=1)
+  ColRstOffset* = 1 ## 1: a replica of ColOffset for internal use
 
 template currentTok(p: RstParser): Token = p.tok[p.idx]
 template prevTok(p: RstParser): Token = p.tok[p.idx - 1]
@@ -487,7 +489,7 @@ template nextTok(p: RstParser): Token = p.tok[p.idx + 1]
 
 proc whichMsgClass*(k: MsgKind): MsgClass =
   ## returns which message class `k` belongs to.
-  case ($k)[1]
+  case k.symbolName[1]
   of 'e', 'E': result = mcError
   of 'w', 'W': result = mcWarning
   of 'h', 'H': result = mcHint
@@ -497,7 +499,9 @@ proc defaultMsgHandler*(filename: string, line, col: int, msgkind: MsgKind,
                         arg: string) =
   let mc = msgkind.whichMsgClass
   let a = $msgkind % arg
-  let message = "$1($2, $3) $4: $5" % [filename, $line, $col, $mc, a]
+  var message: string
+  toLocation(message, filename, line, col + ColRstOffset)
+  message.add " $1: $2" % [$mc, a]
   if mc == mcError: raise newException(EParseError, message)
   else: writeLine(stdout, message)
 
@@ -1973,25 +1977,32 @@ proc parseEnumList(p: var RstParser): PRstNode =
     if match(p, p.idx, wildcards[w]): break
     inc w
   assert w < wildcards.len
+
   proc checkAfterNewline(p: RstParser, report: bool): bool =
+    ## If no indentation on the next line then parse as a normal paragraph
+    ## according to the RST spec. And report a warning with suggestions
     let j = tokenAfterNewline(p, start=p.idx+1)
+    let requiredIndent = p.tok[p.idx+wildToken[w]].col
     if p.tok[j].kind notin {tkIndent, tkEof} and
-        p.tok[j].col < p.tok[p.idx+wildToken[w]].col and
+        p.tok[j].col < requiredIndent and
         (p.tok[j].col > col or
           (p.tok[j].col == col and not match(p, j, wildcards[w]))):
       if report:
         let n = p.line + p.tok[j].line
         let msg = "\n" & """
           not enough indentation on line $2
-              (if it's continuation of enumeration list),
+              (should be at column $3 if it's a continuation of enum. list),
           or no blank line after line $1 (if it should be the next paragraph),
           or no escaping \ at the beginning of line $1
               (if lines $1..$2 are a normal paragraph, not enum. list)""".
           unindent(8)
-        rstMessage(p, mwRstStyle, msg % [$(n-1), $n])
+        let c = p.col + requiredIndent + ColRstOffset
+        rstMessage(p, mwRstStyle, msg % [$(n-1), $n, $c],
+                   p.tok[j].line, p.tok[j].col)
       result = false
     else:
       result = true
+
   if not checkAfterNewline(p, report = true):
     return nil
   result = newRstNodeA(p, rnEnumList)
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index f72ff9e8f..c52a0fdcc 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -1476,7 +1476,8 @@ $content
 # ---------- forum ---------------------------------------------------------
 
 proc rstToHtml*(s: string, options: RstParseOptions,
-                config: StringTableRef): string =
+                config: StringTableRef,
+                msgHandler: MsgHandler = rst.defaultMsgHandler): string =
   ## Converts an input rst string into embeddable HTML.
   ##
   ## This convenience proc parses any input string using rst markup (it doesn't
@@ -1503,11 +1504,10 @@ proc rstToHtml*(s: string, options: RstParseOptions,
 
   const filen = "input"
   var d: RstGenerator
-  initRstGenerator(d, outHtml, config, filen, options, myFindFile,
-                   rst.defaultMsgHandler)
+  initRstGenerator(d, outHtml, config, filen, options, myFindFile, msgHandler)
   var dummyHasToc = false
   var rst = rstParse(s, filen, line=LineRstInit, column=ColRstInit,
-                     dummyHasToc, options)
+                     dummyHasToc, options, myFindFile, msgHandler)
   result = ""
   renderRstToOut(d, rst, result)
 
diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim
index 61e4d44e7..cf82cdf91 100644
--- a/tests/stdlib/trstgen.nim
+++ b/tests/stdlib/trstgen.nim
@@ -7,9 +7,34 @@ outputsub: ""
 import ../../lib/packages/docutils/rstgen
 import ../../lib/packages/docutils/rst
 import unittest, strutils, strtabs
-
-proc toHtml(input: string): string =
-  rstToHtml(input, {roSupportMarkdown}, defaultConfig())
+import std/private/miscdollars
+
+proc toHtml(input: string,
+            rstOptions: RstParseOptions = {roSupportMarkdown},
+            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
 
 suite "YAML syntax highlighting":
   test "Basics":
@@ -24,7 +49,7 @@ suite "YAML syntax highlighting":
     ? key
     : value
     ..."""
-    let output = rstTohtml(input, {}, defaultConfig())
+    let output = input.toHtml({})
     doAssert output == """<pre class = "listing"><span class="Directive">%YAML 1.2</span>
 <span class="Keyword">---</span>
 <span class="StringLit">a string</span><span class="Punctuation">:</span> <span class="StringLit">string</span>
@@ -50,7 +75,7 @@ suite "YAML syntax highlighting":
     another literal block scalar:
       |+ # comment after header
      allowed, since more indented than parent"""
-    let output = rstToHtml(input, {}, defaultConfig())
+    let output = input.toHtml({})
     doAssert output == """<pre class = "listing"><span class="StringLit">a literal block scalar</span><span class="Punctuation">:</span> <span class="Command">|</span><span class="Command"></span><span class="LongStringLit">
   some text
   # not a comment
@@ -76,7 +101,7 @@ suite "YAML syntax highlighting":
     % not a directive
     ...
     %TAG ! !foo:"""
-    let output = rstToHtml(input, {}, defaultConfig())
+    let output = input.toHtml({})
     doAssert output == """<pre class = "listing"><span class="Directive">%YAML 1.2</span>
 <span class="Keyword">---</span>
 <span class="StringLit">%not a directive</span>
@@ -97,7 +122,7 @@ suite "YAML syntax highlighting":
       more numbers: [-783, 11e78],
       not numbers: [ 42e, 0023, +32.37, 8 ball]
     }"""
-    let output = rstToHtml(input, {}, defaultConfig())
+    let output = input.toHtml({})
     doAssert output == """<pre class = "listing"><span class="Punctuation">{</span>
   <span class="StringLit">&quot;</span><span class="StringLit">quoted string&quot;</span><span class="Punctuation">:</span> <span class="DecNumber">42</span><span class="Punctuation">,</span>
   <span class="StringLit">'single quoted string'</span><span class="Punctuation">:</span> <span class="StringLit">false</span><span class="Punctuation">,</span>
@@ -114,7 +139,7 @@ suite "YAML syntax highlighting":
     : !localtag foo
     alias: *anchor
     """
-    let output = rstToHtml(input, {}, defaultConfig())
+    let output = input.toHtml({})
     doAssert output == """<pre class = "listing"><span class="Keyword">---</span> <span class="TagStart">!!map</span>
 <span class="TagStart">!!str</span> <span class="StringLit">string</span><span class="Punctuation">:</span> <span class="TagStart">!&lt;tag:yaml.org,2002:int&gt;</span> <span class="DecNumber">42</span>
 <span class="Punctuation">?</span> <span class="Label">&amp;anchor</span> <span class="TagStart">!!seq</span> <span class="Punctuation">[</span><span class="Punctuation">]</span><span class="Punctuation">:</span>
@@ -134,7 +159,7 @@ suite "YAML syntax highlighting":
     example.com/not/a#comment:
       ?not a map key
     """
-    let output = rstToHtml(input, {}, defaultConfig())
+    let output = input.toHtml({})
     doAssert output == """<pre class = "listing"><span class="Keyword">...</span>
  <span class="StringLit">%a string</span><span class="Punctuation">:</span>
   <span class="StringLit">a:string:not:a:map</span>
@@ -154,14 +179,12 @@ suite "RST/Markdown general":
       "<em>Hello</em> <strong>world</strong>!"
 
   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 == """(( <a class="reference external" href="https://nim-lang.org/">Nim</a> ))"""
-    doAssert b == """((<a class="reference external" href="https://nim-lang.org/">Nim</a>))"""
-    doAssert c == """[<a class="reference external" href="https://nim-lang.org/">Nim</a>]"""
+    check("(( [Nim](https://nim-lang.org/) ))".toHtml ==
+        """(( <a class="reference external" href="https://nim-lang.org/">Nim</a> ))""")
+    check("(([Nim](https://nim-lang.org/)))".toHtml ==
+        """((<a class="reference external" href="https://nim-lang.org/">Nim</a>))""")
+    check("[[Nim](https://nim-lang.org/)]".toHtml ==
+        """[<a class="reference external" href="https://nim-lang.org/">Nim</a>]""")
 
   test "Markdown tables":
     let input1 = """
@@ -172,7 +195,7 @@ suite "RST/Markdown general":
 | E1 \| text   |
 |              | F2 without pipe
 not in table"""
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert output1 == """<table border="1" class="docutils"><tr><th>A1 header</th><th>A2 | not fooled</th></tr>
 <tr><td>C1</td><td>C2 <strong>bold</strong></td></tr>
 <tr><td>D1 <tt class="docutils literal"><span class="pre">code |</span></tt></td><td>D2</td></tr>
@@ -183,7 +206,7 @@ not in table"""
     let input2 = """
 | A1 header | A2 |
 | --- | --- |"""
-    let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    let output2 = input2.toHtml
     doAssert output2 == """<table border="1" class="docutils"><tr><th>A1 header</th><th>A2</th></tr>
 </table>"""
 
@@ -225,7 +248,7 @@ A0     A1   X
     let input1 = """
 Check that a few punctuation symbols are not parsed as adornments:
 :word1: word2 .... word3 """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     discard output1
 
   test "RST sections":
@@ -233,7 +256,7 @@ Check that a few punctuation symbols are not parsed as adornments:
 Long chapter name
 '''''''''''''''''''
 """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "Long chapter name" in output1 and "<h1" in output1
 
     let input2 = """
@@ -242,7 +265,7 @@ Short chapter name:
 ChA
 ===
 """
-    let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    let output2 = input2.toHtml
     doAssert "ChA" in output2 and "<h1" in output2
 
     let input3 = """
@@ -251,7 +274,7 @@ Very short chapter name:
 X
 ~
 """
-    let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig())
+    let output3 = input3.toHtml
     doAssert "X" in output3 and "<h1" in output3
 
     let input4 = """
@@ -261,8 +284,10 @@ Wrong chapter
 ------------
 
 """
-    expect(EParseError):
-      let output4 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig())
+    var error4 = new string
+    let output4 = input4.toHtml(error = error4)
+    check(error4[] == "input(3, 1) Error: new section expected (underline " &
+            "\'------------\' is too short)")
 
     let input5 = """
 Check that punctuation after adornment and indent are not detected as adornment.
@@ -271,14 +296,14 @@ Some chapter
 --------------
 
   "punctuation symbols" """
-    let output5 = rstToHtml(input5, {roSupportMarkdown}, defaultConfig())
+    let output5 = input5.toHtml
     doAssert "&quot;punctuation symbols&quot;" in output5 and "<h1" in output5
 
     # check that EOF after adornment does not prevent it parsing as heading
     let input6 = dedent """
       Some chapter
       ------------"""
-    let output6 = rstToHtml(input6, {roSupportMarkdown}, defaultConfig())
+    let output6 = input6.toHtml
     doAssert "<h1 id=\"some-chapter\">Some chapter</h1>" in output6
 
     # check that overline and underline match
@@ -287,16 +312,20 @@ Some chapter
       Some chapter
       -----------
       """
-    expect(EParseError):
-      let output7 = rstToHtml(input7, {roSupportMarkdown}, defaultConfig())
+    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
       -----------
       """
-    expect(EParseError):
-      let output8 = rstToHtml(input8, {roSupportMarkdown}, defaultConfig())
+    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 """
@@ -319,7 +348,7 @@ Some chapter
       ~~~~~
 
       """
-    let output9good = rstToHtml(input9good, {roSupportMarkdown}, defaultConfig())
+    let output9good = input9good.toHtml
     doAssert "<h1 id=\"level1\">Level1</h1>" in output9good
     doAssert "<h2 id=\"level2\">Level2</h2>" in output9good
     doAssert "<h3 id=\"level3\">Level3</h3>" in output9good
@@ -348,8 +377,12 @@ Some chapter
       -------
 
       """
-    expect(EParseError):
-      let output9Bad = rstToHtml(input9Bad, {roSupportMarkdown}, defaultConfig())
+    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
@@ -464,7 +497,7 @@ Some chapter
 Want to learn about `my favorite programming language`_?
 
 .. _my favorite programming language: https://nim-lang.org"""
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "<a" in output1 and "href=\"https://nim-lang.org\"" in output1
 
   test "RST transitions":
@@ -475,7 +508,7 @@ context1
 
 context2
 """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "<hr" in output1
 
     let input2 = """
@@ -485,8 +518,10 @@ This is too short to be a transition:
 
 context2
 """
-    expect(EParseError):
-      let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    var error2 = new string
+    let output2 = input2.toHtml(error=error2)
+    check(error2[] == "input(3, 1) Error: new section expected (overline " &
+            "\'---\' is too short)")
 
   test "RST literal block":
     let input1 = """
@@ -495,7 +530,7 @@ Test literal block
 ::
 
   check """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "<pre>" in output1
 
   test "Markdown code block":
@@ -503,7 +538,7 @@ Test literal block
 ```
 let x = 1
 ``` """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "<pre" in output1 and "class=\"Keyword\"" notin output1
 
     let input2 = """
@@ -511,7 +546,7 @@ Parse the block with language specifier:
 ```Nim
 let x = 1
 ``` """
-    let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    let output2 = input2.toHtml
     doAssert "<pre" in output2 and "class=\"Keyword\"" in output2
 
   test "RST comments":
@@ -520,7 +555,7 @@ Check that comment disappears:
 
 ..
   some comment """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert output1 == "Check that comment disappears:"
 
   test "RST line blocks":
@@ -555,7 +590,7 @@ Test1
 
       Paragraph2"""
 
-    let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    let output2 = input2.toHtml
     doAssert "Paragraph1<p><br/></p> <p>Paragraph2</p>\n" == output2
 
     let input3 = dedent"""
@@ -563,7 +598,7 @@ Test1
       |   yyy
       |     zzz"""
 
-    let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig())
+    let output3 = input3.toHtml
     doAssert "xxx<br/>" in output3
     doAssert "<span style=\"margin-left: 1.0em\">yyy</span><br/>" in output3
     doAssert "<span style=\"margin-left: 2.0em\">zzz</span><br/>" in output3
@@ -574,7 +609,7 @@ Test1
       |      
       |     zzz"""
 
-    let output4 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig())
+    let output4 = input4.toHtml
     doAssert "xxx<br/><br/>" in output4
     doAssert "<span style=\"margin-left: 2.0em\">zzz</span><br/>" in output4
 
@@ -597,7 +632,7 @@ Test1
       5. line5
          5
       """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     for i in 1..5:
       doAssert ($i & ". line" & $i) notin output1
       doAssert ("<li>line" & $i & " " & $i & "</li>") in output1
@@ -619,7 +654,7 @@ Test1
 
       8. line8
       """
-    let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    let output2 = input2.toHtml
     for i in [3, 4, 5, 7, 8]:
       doAssert ($i & ". line" & $i) notin output2
       doAssert ("<li>line" & $i & "</li>") in output2
@@ -629,7 +664,7 @@ Test1
       1.  a) string1
       2. string2
       """
-    let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig())
+    let output3 = input3.toHtml
     doAssert count(output3, "<ol ") == 2
     doAssert count(output3, "</ol>") == 2
     doAssert "<li>string1</li>" in output3 and "<li>string2</li>" in output3
@@ -645,7 +680,7 @@ Test1
       c) string5
       e) string6
       """
-    let output4 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig())
+    let output4 = input4.toHtml
     doAssert count(output4, "<ol ") == 4
     doAssert count(output4, "</ol>") == 4
     for enumerator in [9, 12]:
@@ -665,7 +700,7 @@ Test1
       #) string5
       #) string6
       """
-    let output5 = rstToHtml(input5, {roSupportMarkdown}, defaultConfig())
+    let output5 = input5.toHtml
     doAssert count(output5, "<ol ") == 2
     doAssert count(output5, "</ol>") == 2
     doAssert count(output5, "<li>") == 5
@@ -677,7 +712,7 @@ Test1
       #. string2
       #. string3
       """
-    let output5a = rstToHtml(input5a, {roSupportMarkdown}, defaultConfig())
+    let output5a = input5a.toHtml
     doAssert count(output5a, "<ol ") == 1
     doAssert count(output5a, "</ol>") == 1
     doAssert count(output5a, "<li>") == 3
@@ -689,7 +724,7 @@ Test1
       #. string2
       #. string3
       """
-    let output6 = rstToHtml(input6, {roSupportMarkdown}, defaultConfig())
+    let output6 = input6.toHtml
     doAssert count(output6, "<ol ") == 1
     doAssert count(output6, "</ol>") == 1
     doAssert count(output6, "<li>") == 3
@@ -702,7 +737,7 @@ Test1
       #. string2
       #. string3
       """
-    let output7 = rstToHtml(input7, {roSupportMarkdown}, defaultConfig())
+    let output7 = input7.toHtml
     doAssert count(output7, "<ol ") == 1
     doAssert count(output7, "</ol>") == 1
     doAssert count(output7, "<li>") == 3
@@ -710,12 +745,20 @@ Test1
 
     # check that it's not recognized as enum.list without indentation on 2nd line
     let input8 = dedent """
-      A. string1
+      Paragraph.
+
+      A. stringA
+      B. stringB
+      C. string1
       string2
       """
-    # TODO: find out hot to catch warning here instead of throwing a defect
-    expect(AssertionDefect):
-      let output8 = input8.toHtml
+    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.<ol class=\"upperalpha simple\">" &
+        "<li>stringA</li>\n<li>stringB</li>\n</ol>\n<p>C. string1 string2 </p>\n"
 
   test "Markdown enumerated lists":
     let input1 = dedent """
@@ -729,7 +772,7 @@ Test1
 
       #. lineA
       """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     for i in 1..5:
       doAssert ($i & ". line" & $i) notin output1
       doAssert ("<li>line" & $i & "</li>") in output1
@@ -755,7 +798,7 @@ Test1
       * line5
         5
       """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     for i in 1..5:
       doAssert ("<li>line" & $i & " " & $i & "</li>") in output1
     doAssert count(output1, "<ul ") == 1
@@ -857,9 +900,11 @@ Test1
 
       Ref. [#note]_
       """
-    # TODO: find out hot to configure proper exception instead of defect
-    expect(AssertionDefect):
-      let output5 = input5.toHtml
+    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 """
@@ -869,8 +914,11 @@ Test1
 
       Ref. [*]_
       """
-    expect(AssertionDefect):
-      let output6 = input6.toHtml
+    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.
@@ -889,8 +937,10 @@ Test1
 
       Ref. [som]_.
       """
-    expect(AssertionDefect):
-      let output8 = input8.toHtml
+    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 """
@@ -966,7 +1016,7 @@ Test1
          :number-lines: 0
 
       Paragraph1"""
-    let output0 = rstToHtml(input0, {roSupportMarkdown}, defaultConfig())
+    let output0 = input0.toHtml
     doAssert "<p>Paragraph1</p>" in output0
 
   test "RST admonitions":
@@ -983,7 +1033,7 @@ Test1
       .. tip:: endOf tip
       .. warning:: endOf warning
     """
-    let output0 = rstToHtml(input0, {roSupportMarkdown}, defaultConfig())
+    let output0 = input0.toHtml
     for a in ["admonition", "attention", "caution", "danger", "error", "hint",
         "important", "note", "tip", "warning" ]:
       doAssert "endOf " & a & "</div>" in output0
@@ -994,7 +1044,7 @@ Test1
 
       Test paragraph.
     """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "endOfError</div>" in output1
     doAssert "<p>Test paragraph. </p>" in output1
     doAssert "class=\"admonition admonition-error\"" in output1
@@ -1006,7 +1056,7 @@ Test1
 
       Test paragraph.
     """
-    let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    let output2 = input2.toHtml
     doAssert "endOfError Test2p.</div>" in output2
     doAssert "<p>Test paragraph. </p>" in output2
     doAssert "class=\"admonition admonition-error\"" in output2
@@ -1014,7 +1064,7 @@ Test1
     let input3 = dedent """
       .. note:: endOfNote
     """
-    let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig())
+    let output3 = input3.toHtml
     doAssert "endOfNote</div>" in output3
     doAssert "class=\"admonition admonition-info\"" in output3
 
@@ -1099,7 +1149,7 @@ Test1
 
       That was a transition.
     """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "<p id=\"target000\""     in output1
     doAssert "<ul id=\"target001\""    in output1
     doAssert "<ol id=\"target002\""    in output1
@@ -1125,7 +1175,7 @@ Test1
 
       Ref. target101_
     """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     # "target101" should be erased and changed to "section-xyz":
     doAssert "href=\"#target101\"" notin output1
     doAssert "id=\"target101\""    notin output1
@@ -1154,7 +1204,7 @@ Test1
       Ref. target103_.
 
     """
-    let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
+    let output2 = input2.toHtml
     # "target101" should be erased and changed to "section-xyz":
     doAssert "href=\"#target300\"" notin output2
     doAssert "id=\"target300\""    notin output2
@@ -1178,7 +1228,7 @@ Test1
 
       Ref. `some definition`_.
     """
-    let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
+    let output1 = input1.toHtml
     doAssert "<span class=\"target\" " &
         "id=\"some-definition\">some definition</span>" in output1
     doAssert "Ref. <a class=\"reference internal\" " &