summary refs log tree commit diff stats
path: root/lib/packages
diff options
context:
space:
mode:
authorAndrey Makarov <ph.makarov@gmail.com>2023-06-28 14:38:54 -0600
committerGitHub <noreply@github.com>2023-06-28 22:38:54 +0200
commit57de460437924a951d393ced8b7c88418fe2541a (patch)
treec46cd5150aaab8962c117de00faae2486b389bd8 /lib/packages
parentb35942ef8386d082b8564b2aa62843a4949cdb60 (diff)
downloadNim-57de460437924a951d393ced8b7c88418fe2541a.tar.gz
Don't throw errors on RST tables in Markdown and RstMarkdown modes (#22165)
* Don't throw errors on RST tables in Markdown and RstMarkdown modes

Additions to RST simple tables (#19859) made their parsing more
restrictive, which can introduce problems with of some old
nimforum posts, which have tables with sloppily aligned columns
(like this one:
https://github.com/nim-lang/nimforum/issues/330#issuecomment-1376039966).
Also this strictness contradicts to Markdown style of not getting
in the way (ignoring errors).

So this PR proposes a new strategy of dealing with errors:
* In Markdown and legacy (old default) RstMarkdown we try to
  continue parsing, emitting only warnings
* And only in pure RST mode we throw a error

I expect that this strategy will be applied to more parts of markup code
in the future.

* Don't return anything in `checkColumns`
Diffstat (limited to 'lib/packages')
-rw-r--r--lib/packages/docutils/rst.nim44
1 files changed, 34 insertions, 10 deletions
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index ae564b643..2894010ef 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -585,6 +585,29 @@ proc rstMessage(p: RstParser, msgKind: MsgKind) =
                              p.col + currentTok(p).col, msgKind,
                              currentTok(p).symbol)
 
+# Functions `isPureRst` & `stopOrWarn` address differences between
+# Markdown and RST:
+# * Markdown always tries to continue working. If it is really impossible
+#   to parse a markup element, its proc just returns `nil` and parsing
+#   continues for it as for normal text paragraph.
+#   The downside is that real mistakes/typos are often silently ignored.
+#   The same applies to legacy `RstMarkdown` mode for nimforum.
+# * RST really signals errors. The downside is that it's more intrusive -
+#   the user must escape special syntax with \ explicitly.
+#
+# TODO: we need to apply this strategy to all markup elements eventually.
+
+func isPureRst(p: RstParser): bool =
+  roSupportMarkdown notin p.s.options
+
+proc stopOrWarn(p: RstParser, errorType: MsgKind, arg: string) =
+  let realMsgKind = if isPureRst(p): errorType else: mwRstStyle
+  rstMessage(p, realMsgKind, arg)
+
+proc stopOrWarn(p: RstParser, errorType: MsgKind, arg: string, line, col: int) =
+  let realMsgKind = if isPureRst(p): errorType else: mwRstStyle
+  rstMessage(p, realMsgKind, arg, line, col)
+
 proc currInd(p: RstParser): int =
   result = p.indentStack[high(p.indentStack)]
 
@@ -2596,11 +2619,11 @@ proc getColumns(p: RstParser, cols: var RstCols, startIdx: int): int =
 proc checkColumns(p: RstParser, cols: RstCols) =
   var i = p.idx
   if p.tok[i].symbol[0] != '=':
-    rstMessage(p, mwRstStyle,
+    stopOrWarn(p, meIllformedTable,
                "only tables with `=` columns specification are allowed")
   for col in 0 ..< cols.len:
     if tokEnd(p, i) != cols[col].stop:
-      rstMessage(p, meIllformedTable,
+      stopOrWarn(p, meIllformedTable,
                  "end of table column #$1 should end at position $2" % [
                    $(col+1), $(cols[col].stop+ColRstOffset)],
                  p.tok[i].line, tokEnd(p, i))
@@ -2609,12 +2632,12 @@ proc checkColumns(p: RstParser, cols: RstCols) =
       if p.tok[i].kind == tkWhite:
         inc i
       if p.tok[i].kind notin {tkIndent, tkEof}:
-        rstMessage(p, meIllformedTable, "extraneous column specification")
+        stopOrWarn(p, meIllformedTable, "extraneous column specification")
     elif p.tok[i].kind == tkWhite:
       inc i
     else:
-      rstMessage(p, meIllformedTable, "no enough table columns",
-                 p.tok[i].line, p.tok[i].col)
+      stopOrWarn(p, meIllformedTable,
+                 "no enough table columns", p.tok[i].line, p.tok[i].col)
 
 proc getSpans(p: RstParser, nextLine: int,
               cols: RstCols, unitedCols: RstCols): seq[int] =
@@ -2669,17 +2692,18 @@ proc parseSimpleTableRow(p: var RstParser, cols: RstCols, colChar: char): PRstNo
       if tokEnd(p) <= colEnd(nCell):
         if tokStart(p) < colStart(nCell):
           if currentTok(p).kind != tkWhite:
-            rstMessage(p, meIllformedTable,
+            stopOrWarn(p, meIllformedTable,
                        "this word crosses table column from the left")
-          else:
-            inc p.idx
+            row[nCell].add(currentTok(p).symbol)
         else:
           row[nCell].add(currentTok(p).symbol)
-          inc p.idx
+        inc p.idx
       else:
         if tokStart(p) < colEnd(nCell) and currentTok(p).kind != tkWhite:
-          rstMessage(p, meIllformedTable,
+          stopOrWarn(p, meIllformedTable,
                      "this word crosses table column from the right")
+          row[nCell].add(currentTok(p).symbol)
+          inc p.idx
         inc nCell
     if currentTok(p).kind == tkIndent: inc p.idx
     if tokEnd(p) <= colEnd(0): break