From 861c42c258ee81ff20630fdaa49813de5311881d Mon Sep 17 00:00:00 2001 From: Andrey Makarov Date: Mon, 29 Mar 2021 19:32:49 +0300 Subject: [PATCH] RST: enable parsing of prefix roles (ref #17340) (#17514) --- doc/contributing.rst | 9 ++++++++ lib/packages/docutils/rst.nim | 38 +++++++++++++++++--------------- tests/stdlib/trstgen.nim | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/doc/contributing.rst b/doc/contributing.rst index b7188a436a34..279a4ee941e5 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -285,6 +285,15 @@ or the first is preferred. +When you specify an *RST role* (highlighting/interpretation marker) do it +in the postfix form for uniformity, that is after \`text in backticks\`. +For example an ``:idx:`` role for referencing a topic ("SQLite" in the +example below) from `Nim Index`_ can be used in doc comment this way: + +.. code-block:: nim + ## A higher level `SQLite`:idx: database wrapper. + +.. _`Nim Index`: https://nim-lang.org/docs/theindex.html Best practices ============== diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index 6845f61b93ff..d331c2c12d36 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -68,7 +68,7 @@ ## substitution references, standalone hyperlinks, ## internal links (inline and outline) ## + \`interpreted text\` with roles ``:literal:``, ``:strong:``, -## ``emphasis``, ``:sub:``/``:subscript:``, ``:sup:``/``:supscript:`` +## ``emphasis``, ``:sub:``/``:subscript:``, ``:sup:``/``:superscript:`` ## (see `RST roles list`_ for description). ## + inline internal targets ## @@ -1018,6 +1018,16 @@ proc fixupEmbeddedRef(n, a, b: PRstNode) = for i in countup(0, sep - incr): a.add(n.sons[i]) for i in countup(sep + 1, n.len - 2): b.add(n.sons[i]) +proc whichRole(sym: string): RstNodeKind = + case sym + of "idx": result = rnIdx + of "literal": result = rnInlineLiteral + of "strong": result = rnStrongEmphasis + of "emphasis": result = rnEmphasis + of "sub", "subscript": result = rnSub + of "sup", "superscript": result = rnSup + else: result = rnGeneralRole + proc parsePostfix(p: var RstParser, n: PRstNode): PRstNode = var newKind = n.kind var newSons = n.sons @@ -1042,22 +1052,8 @@ proc parsePostfix(p: var RstParser, n: PRstNode): PRstNode = result = newRstNode(newKind, newSons) elif match(p, p.idx, ":w:"): # a role: - if nextTok(p).symbol == "idx": - newKind = rnIdx - elif nextTok(p).symbol == "literal": - newKind = rnInlineLiteral - elif nextTok(p).symbol == "strong": - newKind = rnStrongEmphasis - elif nextTok(p).symbol == "emphasis": - newKind = rnEmphasis - elif nextTok(p).symbol == "sub" or - nextTok(p).symbol == "subscript": - newKind = rnSub - elif nextTok(p).symbol == "sup" or - nextTok(p).symbol == "supscript": - newKind = rnSup - else: - newKind = rnGeneralRole + newKind = whichRole(nextTok(p).symbol) + if newKind == rnGeneralRole: let newN = newRstNode(rnInner, n.sons) newSons = @[newN, newLeaf(nextTok(p).symbol)] inc p.idx, 3 @@ -1318,6 +1314,12 @@ proc parseInline(p: var RstParser, father: PRstNode) = var n = newRstNode(rnInlineLiteral) parseUntil(p, n, "``", false) father.add(n) + elif match(p, p.idx, ":w:") and p.tok[p.idx+3].symbol == "`": + let k = whichRole(nextTok(p).symbol) + let n = newRstNode(k) + inc p.idx, 3 + parseUntil(p, n, "`", false) # bug #17260 + father.add(n) elif isInlineMarkupStart(p, "`"): var n = newRstNode(rnInterpretedText) parseUntil(p, n, "`", false) # bug #17260 @@ -1677,7 +1679,7 @@ proc whichSection(p: RstParser): RstNodeKind = elif predNL(p) and currentTok(p).symbol in ["+", "*", "-"] and nextTok(p).kind == tkWhite: result = rnBulletList - elif match(p, p.idx, ":w:") and predNL(p): + elif match(p, p.idx, ":w:E") and predNL(p): # (currentTok(p).symbol == ":") result = rnFieldList elif match(p, p.idx, "(e) ") or match(p, p.idx, "e) ") or diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim index 0f3890faa7a4..da01c30d2192 100644 --- a/tests/stdlib/trstgen.nim +++ b/tests/stdlib/trstgen.nim @@ -1326,6 +1326,47 @@ Test1 output) check("""-doption""" in 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 "(not) Roles: check escaping 1": + let expected = """See :subscript:""" & + """some 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 = """
text1