summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/docgen.nim4
-rw-r--r--lib/packages/docutils/rst.nim162
-rw-r--r--lib/packages/docutils/rstast.nim70
-rw-r--r--lib/packages/docutils/rstgen.nim50
-rw-r--r--tests/stdlib/trstgen.nim5
5 files changed, 159 insertions, 132 deletions
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index 5df203a04..09a3983d4 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -677,8 +677,8 @@ proc getRstName(n: PNode): PRstNode =
   case n.kind
   of nkPostfix: result = getRstName(n[1])
   of nkPragmaExpr: result = getRstName(n[0])
-  of nkSym: result = newRstNode(rnLeaf, n.sym.renderDefinitionName)
-  of nkIdent: result = newRstNode(rnLeaf, n.ident.s)
+  of nkSym: result = newRstLeaf(n.sym.renderDefinitionName)
+  of nkIdent: result = newRstLeaf(n.ident.s)
   of nkAccQuoted:
     result = getRstName(n[0])
     for i in 1..<n.len: result.text.add(getRstName(n[i]).text)
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index 914494987..f764b65b0 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -786,8 +786,10 @@ proc newRstNodeA(p: var RstParser, kind: RstNodeKind): PRstNode =
     result.anchor = p.curAnchor
     p.curAnchor = ""
 
+template newLeaf(s: string): PRstNode = newRstLeaf(s)
+
 proc newLeaf(p: var RstParser): PRstNode =
-  result = newRstNode(rnLeaf, currentTok(p).symbol)
+  result = newLeaf(currentTok(p).symbol)
 
 proc getReferenceName(p: var RstParser, endStr: string): PRstNode =
   var res = newRstNode(rnInner)
@@ -930,7 +932,8 @@ proc fixupEmbeddedRef(n, a, b: PRstNode) =
   for i in countup(sep + 1, n.len - 2): b.add(n.sons[i])
 
 proc parsePostfix(p: var RstParser, n: PRstNode): PRstNode =
-  result = n
+  var newKind = n.kind
+  var newSons = n.sons
   if isInlineMarkupEnd(p, "_") or isInlineMarkupEnd(p, "__"):
     inc p.idx
     if p.tok[p.idx-2].symbol == "`" and p.tok[p.idx-3].symbol == ">":
@@ -938,40 +941,42 @@ proc parsePostfix(p: var RstParser, n: PRstNode): PRstNode =
       var b = newRstNode(rnInner)
       fixupEmbeddedRef(n, a, b)
       if a.len == 0:
-        result = newRstNode(rnStandaloneHyperlink)
-        result.add(b)
+        newKind = rnStandaloneHyperlink
+        newSons = @[b]
       else:
-        result = newRstNode(rnHyperlink)
-        result.add(a)
-        result.add(b)
+        newKind = rnHyperlink
+        newSons = @[a, b]
         setRef(p, rstnodeToRefname(a), b)
     elif n.kind == rnInterpretedText:
-      n.kind = rnRef
+      newKind = rnRef
     else:
-      result = newRstNode(rnRef)
-      result.add(n)
+      newKind = rnRef
+      newSons = @[n]
+    result = newRstNode(newKind, newSons)
   elif match(p, p.idx, ":w:"):
     # a role:
     if nextTok(p).symbol == "idx":
-      n.kind = rnIdx
+      newKind = rnIdx
     elif nextTok(p).symbol == "literal":
-      n.kind = rnInlineLiteral
+      newKind = rnInlineLiteral
     elif nextTok(p).symbol == "strong":
-      n.kind = rnStrongEmphasis
+      newKind = rnStrongEmphasis
     elif nextTok(p).symbol == "emphasis":
-      n.kind = rnEmphasis
+      newKind = rnEmphasis
     elif nextTok(p).symbol == "sub" or
         nextTok(p).symbol == "subscript":
-      n.kind = rnSub
+      newKind = rnSub
     elif nextTok(p).symbol == "sup" or
         nextTok(p).symbol == "supscript":
-      n.kind = rnSup
+      newKind = rnSup
     else:
-      result = newRstNode(rnGeneralRole)
-      n.kind = rnInner
-      result.add(n)
-      result.add(newRstNode(rnLeaf, nextTok(p).symbol))
+      newKind = rnGeneralRole
+      let newN = newRstNode(rnInner, n.sons)
+      newSons = @[newN, newLeaf(nextTok(p).symbol)]
     inc p.idx, 3
+    result = newRstNode(newKind, newSons)
+  else:  # no change
+    result = n
 
 proc matchVerbatim(p: RstParser, start: int, expr: string): int =
   result = start
@@ -997,7 +1002,7 @@ proc isUrl(p: RstParser, i: int): bool =
     p.tok[i+3].kind == tkWord and
     p.tok[i].symbol in ["http", "https", "ftp", "telnet", "file"]
 
-proc parseUrl(p: var RstParser, father: PRstNode) =
+proc parseWordOrUrl(p: var RstParser, father: PRstNode) =
   #if currentTok(p).symbol[strStart] == '<':
   if isUrl(p, p.idx):
     var n = newRstNode(rnStandaloneHyperlink)
@@ -1020,7 +1025,7 @@ proc parseUrl(p: var RstParser, father: PRstNode) =
 proc parseBackslash(p: var RstParser, father: PRstNode) =
   assert(currentTok(p).kind == tkPunct)
   if currentTok(p).symbol == "\\\\":
-    father.add(newRstNode(rnLeaf, "\\"))
+    father.add newLeaf("\\")
     inc p.idx
   elif currentTok(p).symbol == "\\":
     # XXX: Unicode?
@@ -1052,13 +1057,13 @@ proc parseUntil(p: var RstParser, father: PRstNode, postfix: string,
       father.add(newLeaf(p))
       inc p.idx
     of tkIndent:
-      father.add(newRstNode(rnLeaf, " "))
+      father.add newLeaf(" ")
       inc p.idx
       if currentTok(p).kind == tkIndent:
         rstMessage(p, meExpected, postfix, line, col)
         break
     of tkWhite:
-      father.add(newRstNode(rnLeaf, " "))
+      father.add newLeaf(" ")
       inc p.idx
     else: rstMessage(p, meExpected, postfix, line, col)
 
@@ -1069,7 +1074,7 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode =
     inc p.idx
   else:
     args = nil
-  var n = newRstNode(rnLeaf, "")
+  var n = newLeaf("")
   while true:
     case currentTok(p).kind
     of tkEof:
@@ -1165,7 +1170,7 @@ proc parseFootnoteName(p: var RstParser, reference: bool): PRstNode =
       else:
         if not validRefnamePunct(p.tok[i].symbol):
           return nil
-    result.add newRstNode(rnLeaf, p.tok[i].symbol)
+    result.add newLeaf(p.tok[i].symbol)
     inc i
   p.idx = i
 
@@ -1239,7 +1244,7 @@ proc parseInline(p: var RstParser, father: PRstNode) =
       if n != nil:
         father.add(n)
         return
-    parseUrl(p, father)
+    parseWordOrUrl(p, father)
   of tkAdornment, tkOther, tkWhite:
     if roSupportMarkdown in p.s.options and currentTok(p).symbol == "```":
       inc p.idx
@@ -1379,7 +1384,7 @@ proc getArgument(n: PRstNode): string =
 proc parseDotDot(p: var RstParser): PRstNode {.gcsafe.}
 proc parseLiteralBlock(p: var RstParser): PRstNode =
   result = newRstNodeA(p, rnLiteralBlock)
-  var n = newRstNode(rnLeaf, "")
+  var n = newLeaf("")
   if currentTok(p).kind == tkIndent:
     var indent = currentTok(p).ival
     inc p.idx
@@ -1559,6 +1564,7 @@ proc whichSection(p: RstParser): RstNodeKind =
   else: result = rnLeaf
 
 proc parseLineBlock(p: var RstParser): PRstNode =
+  ## Returns rnLineBlock with all sons of type rnLineBlockItem
   result = nil
   if nextTok(p).kind in {tkWhite, tkIndent}:
     var col = currentTok(p).col
@@ -1567,13 +1573,13 @@ proc parseLineBlock(p: var RstParser): PRstNode =
       var item = newRstNode(rnLineBlockItem)
       if nextTok(p).kind == tkWhite:
         if nextTok(p).symbol.len > 1:  # pass additional indentation after '| '
-          item.text = nextTok(p).symbol
+          item.lineIndent = nextTok(p).symbol
         inc p.idx, 2
         pushInd(p, p.tok[p.idx].col)
         parseSection(p, item)
         popInd(p)
       else:  # tkIndent => add an empty line
-        item.text = "\n"
+        item.lineIndent = "\n"
         inc p.idx, 1
       result.add(item)
       if currentTok(p).kind == tkIndent and currentTok(p).ival == col and
@@ -1594,7 +1600,7 @@ proc parseParagraph(p: var RstParser, result: PRstNode) =
         inc p.idx
         case whichSection(p)
         of rnParagraph, rnLeaf, rnHeadline, rnOverline, rnDirective:
-          result.add(newRstNode(rnLeaf, " "))
+          result.add newLeaf(" ")
         of rnLineBlock:
           result.addIfNotNil(parseLineBlock(p))
         else: break
@@ -1604,7 +1610,7 @@ proc parseParagraph(p: var RstParser, result: PRstNode) =
       if currentTok(p).symbol == "::" and
           nextTok(p).kind == tkIndent and
           currInd(p) < nextTok(p).ival:
-        result.add(newRstNode(rnLeaf, ":"))
+        result.add newLeaf(":")
         inc p.idx            # skip '::'
         result.add(parseLiteralBlock(p))
         break
@@ -1679,7 +1685,8 @@ proc parseSimpleTable(p: var RstParser): PRstNode =
       getColumns(p, cols)
       setLen(row, cols.len)
       if a != nil:
-        for j in 0 ..< a.len: a.sons[j].kind = rnTableHeaderCell
+        for j in 0 ..< a.len:  # fix rnTableDataCell -> rnTableHeaderCell
+          a.sons[j] = newRstNode(rnTableHeaderCell, a.sons[j].sons)
     if currentTok(p).kind == tkEof: break
     for j in countup(0, high(row)): row[j] = ""
     # the following while loop iterates over the lines a single cell may span:
@@ -1781,7 +1788,7 @@ proc parseOverline(p: var RstParser): PRstNode =
     if currentTok(p).kind == tkIndent:
       inc p.idx
       if prevTok(p).ival > currInd(p):
-        result.add(newRstNode(rnLeaf, " "))
+        result.add newLeaf(" ")
       else:
         break
     else:
@@ -1897,9 +1904,9 @@ proc parseEnumList(p: var RstParser): PRstNode =
   for i in 0 ..< wildToken[w]-1:  # add first enumerator with (, ), and .
     if p.tok[p.idx + i].symbol == "#":
       prevAE = "#"
-      result.text.add "1"
+      result.labelFmt.add "1"
     else:
-      result.text.add p.tok[p.idx + i].symbol
+      result.labelFmt.add p.tok[p.idx + i].symbol
   var prevEnum = p.tok[p.idx + wildIndex[w]].symbol
   inc p.idx, wildToken[w]
   while true:
@@ -1988,7 +1995,8 @@ proc parseSection(p: var RstParser, result: PRstNode) =
       parseParagraph(p, a)
     result.addIfNotNil(a)
   if sonKind(result, 0) == rnParagraph and sonKind(result, 1) != rnParagraph:
-    result.sons[0].kind = rnInner
+    result.sons[0] = newRstNode(rnInner, result.sons[0].sons,
+                                anchor=result.sons[0].anchor)
 
 proc parseSectionWrapper(p: var RstParser): PRstNode =
   result = newRstNode(rnInner)
@@ -2010,7 +2018,7 @@ type
   DirFlags = set[DirFlag]
   SectionParser = proc (p: var RstParser): PRstNode {.nimcall.}
 
-proc parseDirective(p: var RstParser, flags: DirFlags): PRstNode =
+proc parseDirective(p: var RstParser, k: RstNodeKind, flags: DirFlags): PRstNode =
   ## Parses arguments and options for a directive block.
   ##
   ## A directive block will always have three sons: the arguments for the
@@ -2020,7 +2028,7 @@ proc parseDirective(p: var RstParser, flags: DirFlags): PRstNode =
   ##
   ## Both rnDirArg and rnFieldList children nodes might be nil, so you need to
   ## check them before accessing.
-  result = newRstNodeA(p, rnDirective)
+  result = newRstNodeA(p, k)
   var args: PRstNode = nil
   var options: PRstNode = nil
   if hasArg in flags:
@@ -2065,7 +2073,7 @@ proc parseBlockContent(p: var RstParser, father: var PRstNode,
     father.add content
     result = true
 
-proc parseDirective(p: var RstParser, flags: DirFlags,
+proc parseDirective(p: var RstParser, k: RstNodeKind, flags: DirFlags,
                     contentParser: SectionParser): PRstNode =
   ## A helper proc that does main work for specific directive procs.
   ## Always returns a generic rnDirective tree with these 3 children:
@@ -2075,7 +2083,7 @@ proc parseDirective(p: var RstParser, flags: DirFlags,
   ## 3) a node returned by `contentParser`.
   ##
   ## .. warning:: Any of the 3 children may be nil.
-  result = parseDirective(p, flags)
+  result = parseDirective(p, k, flags)
   if not isNil(contentParser) and
       parseBlockContent(p, result, contentParser):
     discard "result is updated by parseBlockContent"
@@ -2111,7 +2119,7 @@ proc dirInclude(p: var RstParser): PRstNode =
   #    encoding (if specified).
   #
   result = nil
-  var n = parseDirective(p, {hasArg, argIsFile, hasOptions}, nil)
+  var n = parseDirective(p, rnDirective, {hasArg, argIsFile, hasOptions}, nil)
   var filename = strip(addNodes(n.sons[0]))
   var path = p.findRelativeFile(filename)
   if path == "":
@@ -2120,7 +2128,7 @@ proc dirInclude(p: var RstParser): PRstNode =
     # XXX: error handling; recursive file inclusion!
     if getFieldValue(n, "literal") != "":
       result = newRstNode(rnLiteralBlock)
-      result.add(newRstNode(rnLeaf, readFile(path)))
+      result.add newLeaf(readFile(path))
     else:
       let inputString = readFile(path)
       let startPosition =
@@ -2172,13 +2180,13 @@ proc dirCodeBlock(p: var RstParser, nimExtension = false): PRstNode =
   ## As an extension this proc will process the ``file`` extension field and if
   ## present will replace the code block with the contents of the referenced
   ## file.
-  result = parseDirective(p, {hasArg, hasOptions}, parseLiteralBlock)
+  result = parseDirective(p, rnCodeBlock, {hasArg, hasOptions}, parseLiteralBlock)
   var filename = strip(getFieldValue(result, "file"))
   if filename != "":
     var path = p.findRelativeFile(filename)
     if path == "": rstMessage(p, meCannotOpenFile, filename)
     var n = newRstNode(rnLiteralBlock)
-    n.add(newRstNode(rnLeaf, readFile(path)))
+    n.add newLeaf(readFile(path))
     result.sons[2] = n
 
   # Extend the field block if we are using our custom Nim extension.
@@ -2190,47 +2198,36 @@ proc dirCodeBlock(p: var RstParser, nimExtension = false): PRstNode =
     var extraNode = newRstNode(rnField)
     extraNode.add(newRstNode(rnFieldName))
     extraNode.add(newRstNode(rnFieldBody))
-    extraNode.sons[0].add(newRstNode(rnLeaf, "default-language"))
-    extraNode.sons[1].add(newRstNode(rnLeaf, "Nim"))
+    extraNode.sons[0].add newLeaf("default-language")
+    extraNode.sons[1].add newLeaf("Nim")
     result.sons[1].add(extraNode)
 
-  result.kind = rnCodeBlock
-
 proc dirContainer(p: var RstParser): PRstNode =
-  result = parseDirective(p, {hasArg}, parseSectionWrapper)
-  assert(result.kind == rnDirective)
+  result = parseDirective(p, rnContainer, {hasArg}, parseSectionWrapper)
   assert(result.len == 3)
-  result.kind = rnContainer
 
 proc dirImage(p: var RstParser): PRstNode =
-  result = parseDirective(p, {hasOptions, hasArg, argIsFile}, nil)
-  result.kind = rnImage
+  result = parseDirective(p, rnImage, {hasOptions, hasArg, argIsFile}, nil)
 
 proc dirFigure(p: var RstParser): PRstNode =
-  result = parseDirective(p, {hasOptions, hasArg, argIsFile},
+  result = parseDirective(p, rnFigure, {hasOptions, hasArg, argIsFile},
                           parseSectionWrapper)
-  result.kind = rnFigure
 
 proc dirTitle(p: var RstParser): PRstNode =
-  result = parseDirective(p, {hasArg}, nil)
-  result.kind = rnTitle
+  result = parseDirective(p, rnTitle, {hasArg}, nil)
 
 proc dirContents(p: var RstParser): PRstNode =
-  result = parseDirective(p, {hasArg}, nil)
-  result.kind = rnContents
+  result = parseDirective(p, rnContents, {hasArg}, nil)
 
 proc dirIndex(p: var RstParser): PRstNode =
-  result = parseDirective(p, {}, parseSectionWrapper)
-  result.kind = rnIndex
+  result = parseDirective(p, rnIndex, {}, parseSectionWrapper)
 
 proc dirAdmonition(p: var RstParser, d: string): PRstNode =
-  result = parseDirective(p, {}, parseSectionWrapper)
-  result.kind = rnAdmonition
-  result.text = d
+  result = parseDirective(p, rnAdmonition, {}, parseSectionWrapper)
+  result.adType = d
 
 proc dirDefaultRole(p: var RstParser): PRstNode =
-  result = parseDirective(p, {hasArg}, nil)
-  result.kind = rnDefaultRole
+  result = parseDirective(p, rnDefaultRole, {hasArg}, nil)
 
 proc dirRawAux(p: var RstParser, result: var PRstNode, kind: RstNodeKind,
                contentParser: SectionParser) =
@@ -2242,9 +2239,9 @@ proc dirRawAux(p: var RstParser, result: var PRstNode, kind: RstNodeKind,
     else:
       var f = readFile(path)
       result = newRstNode(kind)
-      result.add(newRstNode(rnLeaf, f))
+      result.add newLeaf(f)
   else:
-    result.kind = kind
+    result = newRstNode(kind, result.sons)
     result.add(parseDirBody(p, contentParser))
 
 proc dirRaw(p: var RstParser): PRstNode =
@@ -2256,7 +2253,7 @@ proc dirRaw(p: var RstParser): PRstNode =
   #
   # html
   # latex
-  result = parseDirective(p, {hasOptions, hasArg, argIsWord})
+  result = parseDirective(p, rnDirective, {hasOptions, hasArg, argIsWord})
   if result.sons[0] != nil:
     if cmpIgnoreCase(result.sons[0].sons[0].text, "html") == 0:
       dirRawAux(p, result, rnRawHtml, parseLiteralBlock)
@@ -2360,7 +2357,7 @@ proc parseDotDot(p: var RstParser): PRstNode =
     var a = getReferenceName(p, ":")
     if currentTok(p).kind == tkWhite: inc p.idx
     var b = untilEol(p)
-    if len(b) == 0 and b.text == "":  # set internal anchor
+    if len(b) == 0:  # set internal anchor
       addAnchor(p, rstnodeToRefname(a), reset=false)
     else:  # external hyperlink
       setRef(p, rstnodeToRefname(a), b)
@@ -2389,7 +2386,7 @@ proc parseDotDot(p: var RstParser): PRstNode =
 proc resolveSubs(p: var RstParser, n: PRstNode): PRstNode =
   ## Resolves substitutions and anchor aliases, groups footnotes.
   ## Takes input node `n` and returns the same node with recursive
-  ## substitutions to `result`.
+  ## substitutions in `n.sons` to `result`.
   result = n
   if n == nil: return
   case n.kind
@@ -2400,23 +2397,22 @@ proc resolveSubs(p: var RstParser, n: PRstNode): PRstNode =
     else:
       var key = addNodes(n)
       var e = getEnv(key)
-      if e != "": result = newRstNode(rnLeaf, e)
+      if e != "": result = newLeaf(e)
       else: rstMessage(p, mwUnknownSubstitution, key)
   of rnRef:
     let refn = rstnodeToRefname(n)
     var y = findRef(p, refn)
     if y != nil:
       result = newRstNode(rnHyperlink)
-      n.kind = rnInner
-      result.add(n)
-      result.add(y)
+      let text = newRstNode(rnInner, n.sons)
+      result.sons = @[text, y]
     else:
       let s = findMainAnchor(p, refn)
       if s != "":
         result = newRstNode(rnInternalRef)
-        n.kind = rnInner
-        result.add(n)  # visible text of reference
-        result.add(newRstNode(rnLeaf, s))  # link itself
+        let text = newRstNode(rnInner, n.sons)
+        result.sons = @[text,        # visible text of reference
+                        newLeaf(s)]  # link itself
   of rnFootnote:
     var (fnType, num) = getFootnoteType(n.sons[0])
     case fnType
@@ -2429,7 +2425,7 @@ proc resolveSubs(p: var RstParser, n: PRstNode): PRstNode =
       else:
         num = getFootnoteNum(p, n.order)
       var nn = newRstNode(rnInner)
-      nn.add newRstNode(rnLeaf, $num)
+      nn.add newLeaf($num)
       result.sons[0] = nn
     of fnAutoSymbol:
       let sym = getAutoSymbol(p, n.order)
@@ -2439,7 +2435,7 @@ proc resolveSubs(p: var RstParser, n: PRstNode): PRstNode =
     var (fnType, num) = getFootnoteType(n.sons[0])
     template addLabel(number: int | string) =
       var nn = newRstNode(rnInner)
-      nn.add newRstNode(rnLeaf, $number)
+      nn.add newLeaf($number)
       result.add(nn)
     var refn = fnType.prefix
     # create new rnFootnoteRef, add final label, and finalize target refn:
@@ -2462,10 +2458,10 @@ proc resolveSubs(p: var RstParser, n: PRstNode): PRstNode =
       refn.add rstnodeToRefname(n)
     let s = findMainAnchor(p, refn)
     if s != "":
-      result.add(newRstNode(rnLeaf, s))     # add link
+      result.add newLeaf(s)     # add link
     else:
       rstMessage(p, mwUnknownSubstitution, refn)
-      result.add(newRstNode(rnLeaf, refn))  # add link
+      result.add newLeaf(refn)  # add link
   of rnLeaf:
     discard
   of rnContents:
diff --git a/lib/packages/docutils/rstast.nim b/lib/packages/docutils/rstast.nim
index 41dadd035..6902b4a8b 100644
--- a/lib/packages/docutils/rstast.nim
+++ b/lib/packages/docutils/rstast.nim
@@ -36,10 +36,9 @@ type
     rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock,
     rnLineBlock,              # the | thingie
     rnLineBlockItem,          # a son of rnLineBlock - one line inside it.
-                              # When `RstNode` text="\n" the line's empty
+                              # When `RstNode` lineIndent="\n" the line's empty
     rnBlockQuote,             # text just indented
     rnTable, rnGridTable, rnMarkdownTable, rnTableRow, rnTableHeaderCell, rnTableDataCell,
-    rnLabel,                  # used for footnotes and other things
     rnFootnote,               # a footnote
     rnCitation,               # similar to footnote, so use rnFootnote instead
     rnFootnoteGroup,          # footnote group - exists for a purely stylistic
@@ -74,14 +73,25 @@ type
 
   PRstNode* = ref RstNode    ## an RST node
   RstNodeSeq* = seq[PRstNode]
-  RstNode* {.acyclic, final.} = object ## an RST node's description
-    kind*: RstNodeKind       ## the node's kind
-    text*: string             ## valid for leafs in the AST; and the title of
-                              ## the document or the section; and rnEnumList
-                              ## and rnAdmonition; and rnLineBlockItem
-    level*: int               ## valid for headlines/overlines only
-    order*: int               ## footnote order (for auto-symbol footnotes and
+  RstNode* {.acyclic, final.} = object ## AST node (result of RST parsing)
+    case kind*: RstNodeKind ## the node's kind
+    of rnLeaf, rnSmiley:
+      text*: string           ## string that is expected to be displayed
+    of rnEnumList:
+      labelFmt*: string       ## label format like "(1)"
+    of rnLineBlockItem:
+      lineIndent*: string     ## a few spaces or newline at the line beginning
+    of rnAdmonition:
+      adType*: string         ## admonition type: "note", "caution", etc. This
+                              ## text will set the style and also be displayed
+    of rnOverline, rnHeadline:
+      level*: int             ## level of headings starting from 1 (document
+                              ## title) to larger ones (minor sub-sections)
+    of rnFootnote, rnCitation, rnFootnoteRef:
+      order*: int             ## footnote order (for auto-symbol footnotes and
                               ## auto-numbered ones without a label)
+    else:
+      discard
     anchor*: string           ## anchor, internal link target
                               ## (aka HTML id tag, aka Latex label/hypertarget)
     sons*: RstNodeSeq        ## the node's sons
@@ -89,15 +99,19 @@ type
 proc len*(n: PRstNode): int =
   result = len(n.sons)
 
-proc newRstNode*(kind: RstNodeKind): PRstNode =
-  new(result)
-  result.sons = @[]
-  result.kind = kind
+proc newRstNode*(kind: RstNodeKind, sons: seq[PRstNode] = @[],
+                 anchor = ""): PRstNode =
+  result = PRstNode(kind: kind, sons: sons)
 
-proc newRstNode*(kind: RstNodeKind, s: string): PRstNode =
+proc newRstNode*(kind: RstNodeKind, s: string): PRstNode {.deprecated.} =
+  assert kind in {rnLeaf, rnSmiley}
   result = newRstNode(kind)
   result.text = s
 
+proc newRstLeaf*(s: string): PRstNode =
+  result = newRstNode(rnLeaf)
+  result.text = s
+
 proc lastSon*(n: PRstNode): PRstNode =
   result = n.sons[len(n.sons)-1]
 
@@ -105,7 +119,7 @@ proc add*(father, son: PRstNode) =
   add(father.sons, son)
 
 proc add*(father: PRstNode; s: string) =
-  add(father.sons, newRstNode(rnLeaf, s))
+  add(father.sons, newRstLeaf(s))
 
 proc addIfNotNil*(father, son: PRstNode) =
   if son != nil: add(father, son)
@@ -311,7 +325,7 @@ proc renderRstToJsonNode(node: PRstNode): JsonNode =
       (key: "kind", val: %($node.kind)),
       (key: "level", val: %BiggestInt(node.level))
      ]
-  if node.text.len > 0:
+  if node.kind in {rnLeaf, rnSmiley} and node.text.len > 0:
     result.add("text", %node.text)
   if len(node.sons) > 0:
     var accm = newSeq[JsonNode](len(node.sons))
@@ -338,10 +352,24 @@ proc renderRstToStr*(node: PRstNode, indent=0): string =
   if node == nil:
     result.add " ".repeat(indent) & "[nil]\n"
     return
-  result.add " ".repeat(indent) & $node.kind &
-      (if node.text == "":   "" else: "\t'" & node.text & "'") &
-      (if node.level == 0:   "" else: "\tlevel=" & $node.level) &
-      (if node.order == 0:   "" else: "\torder=" & $node.order) &
-      (if node.anchor == "": "" else: "\tanchor='" & node.anchor & "'") & "\n"
+  result.add " ".repeat(indent) & $node.kind
+  case node.kind
+  of rnLeaf, rnSmiley:
+    result.add (if node.text == "": "" else: "\t'" & node.text & "'")
+  of rnEnumList:
+    result.add "\tlabelFmt=" & node.labelFmt
+  of rnLineBlockItem:
+    var txt: string
+    if node.lineIndent == "\n": txt = "\t(blank line)"
+    else: txt = "\tlineIndent=" & $node.lineIndent.len
+    result.add txt
+  of rnHeadline, rnOverline:
+    result.add (if node.level == 0: "" else: "\tlevel=" & $node.level)
+  of rnFootnote, rnCitation, rnFootnoteRef:
+    result.add (if node.order == 0:   "" else: "\torder=" & $node.order)
+  else:
+    discard
+  result.add (if node.anchor == "": "" else: "\tanchor='" & node.anchor & "'")
+  result.add "\n"
   for son in node.sons:
     result.add renderRstToStr(son, indent=indent+2)
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index e2dd60ca1..93c8d29b1 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -1066,45 +1066,45 @@ proc renderEnumList(d: PDoc, n: PRstNode, result: var string) =
     specStart = ""
     i1 = 0
     pre = ""
-    i2 = n.text.len-1
+    i2 = n.labelFmt.len - 1
     post = ""
-  if n.text[0] == '(':
+  if n.labelFmt[0] == '(':
     i1 = 1
     pre = "("
-  if n.text[^1] == ')' or n.text[^1] == '.':
-    i2 = n.text.len-2
-    post = $n.text[^1]
+  if n.labelFmt[^1] == ')' or n.labelFmt[^1] == '.':
+    i2 = n.labelFmt.len - 2
+    post = $n.labelFmt[^1]
   let enumR = i1 .. i2  # enumerator range without surrounding (, ), .
   if d.target == outLatex:
-    result.add ("\n%"&n.text&"\n")
+    result.add ("\n%" & n.labelFmt & "\n")
     # use enumerate parameters from package enumitem
-    if n.text[i1].isDigit:
+    if n.labelFmt[i1].isDigit:
       var labelDef = ""
       if pre != "" or post != "":
         labelDef = "label=" & pre & "\\arabic*" & post & ","
-      if n.text[enumR] != "1":
-        specStart = "start=$1" % [n.text[enumR]]
+      if n.labelFmt[enumR] != "1":
+        specStart = "start=$1" % [n.labelFmt[enumR]]
       if labelDef != "" or specStart != "":
         specifier = "[$1$2]" % [labelDef, specStart]
     else:
       let (first, labelDef) =
-        if n.text[i1].isUpperAscii: ('A', "label=" & pre & "\\Alph*" & post)
+        if n.labelFmt[i1].isUpperAscii: ('A', "label=" & pre & "\\Alph*" & post)
         else: ('a', "label=" & pre & "\\alph*" & post)
-      if n.text[i1] != first:
-        specStart = ",start=" & $(ord(n.text[i1]) - ord(first) + 1)
+      if n.labelFmt[i1] != first:
+        specStart = ",start=" & $(ord(n.labelFmt[i1]) - ord(first) + 1)
       specifier = "[$1$2]" % [labelDef, specStart]
   else:  # HTML
     # TODO: implement enumerator formatting using pre and post ( and ) for HTML
-    if n.text[i1].isDigit:
-      if n.text[enumR] != "1":
-        specStart = " start=\"$1\"" % [n.text[enumR]]
+    if n.labelFmt[i1].isDigit:
+      if n.labelFmt[enumR] != "1":
+        specStart = " start=\"$1\"" % [n.labelFmt[enumR]]
       specifier = "class=\"simple\"" & specStart
     else:
       let (first, labelDef) =
-        if n.text[i1].isUpperAscii: ('A', "class=\"upperalpha simple\"")
+        if n.labelFmt[i1].isUpperAscii: ('A', "class=\"upperalpha simple\"")
         else: ('a', "class=\"loweralpha simple\"")
-      if n.text[i1] != first:
-        specStart = " start=\"$1\"" % [ $(ord(n.text[i1]) - ord(first) + 1) ]
+      if n.labelFmt[i1] != first:
+        specStart = " start=\"$1\"" % [ $(ord(n.labelFmt[i1]) - ord(first) + 1) ]
       specifier = labelDef & specStart
   renderAux(d, n, "<ol$2 " & specifier & ">$1</ol>\n",
             "\\begin{enumerate}" & specifier & "$2$1\\end{enumerate}\n",
@@ -1115,7 +1115,7 @@ proc renderAdmonition(d: PDoc, n: PRstNode, result: var string) =
     htmlCls = "admonition_warning"
     texSz = "\\large"
     texColor = "orange"
-  case n.text
+  case n.adType
   of "hint", "note", "tip":
     htmlCls = "admonition-info"; texSz = "\\normalsize"; texColor = "green"
   of "attention", "admonition", "important", "warning":
@@ -1123,7 +1123,7 @@ proc renderAdmonition(d: PDoc, n: PRstNode, result: var string) =
   of "danger", "error":
     htmlCls = "admonition-error"; texSz = "\\Large"; texColor = "red"
   else: discard
-  let txt = n.text.capitalizeAscii()
+  let txt = n.adType.capitalizeAscii()
   let htmlHead = "<div class=\"admonition " & htmlCls & "\">"
   renderAux(d, n,
       htmlHead & "<span$2 class=\"" & htmlCls & "-text\"><b>" & txt &
@@ -1191,19 +1191,19 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   of rnQuotedLiteralBlock:
     doAssert false, "renderRstToOut"
   of rnLineBlock:
-    if n.sons.len == 1 and n.sons[0].text == "\n":
+    if n.sons.len == 1 and n.sons[0].lineIndent == "\n":
       # whole line block is one empty line, no need to add extra spacing
       renderAux(d, n, "<p$2>$1</p> ", "\n\n$2\n$1", result)
     else:  # add extra spacing around the line block for Latex
       renderAux(d, n, "<p$2>$1</p>",
         "\n\\vspace{0.5em}$2\n$1\\vspace{0.5em}\n", result)
   of rnLineBlockItem:
-    if n.text.len == 0:  # normal case - no additional indentation
+    if n.lineIndent.len == 0:  # normal case - no additional indentation
       renderAux(d, n, "$1<br/>", "\\noindent $1\n\n", result)
-    elif n.text == "\n":  # add one empty line
+    elif n.lineIndent == "\n":  # add one empty line
       renderAux(d, n, "<br/>", "\\vspace{1em}\n", result)
     else:  # additional indentation w.r.t. '| '
-      let indent = $(0.5 * (n.text.len - 1).toFloat) & "em"
+      let indent = $(0.5 * (n.lineIndent.len - 1).toFloat) & "em"
       renderAux(d, n,
         "<span style=\"margin-left: " & indent & "\">$1</span><br/>",
         "\\noindent\\hspace{" & indent & "}$1\n\n", result)
@@ -1233,8 +1233,6 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
     renderAux(d, n, "<td>$1</td>", "$1", result)
   of rnTableHeaderCell:
     renderAux(d, n, "<th>$1</th>", "\\textbf{$1}", result)
-  of rnLabel:
-    doAssert false, "renderRstToOut" # used for footnotes and other
   of rnFootnoteGroup:
     renderAux(d, n,
       "<hr class=\"footnote\">" &
diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim
index 0a4df1023..ba3ee9378 100644
--- a/tests/stdlib/trstgen.nim
+++ b/tests/stdlib/trstgen.nim
@@ -298,6 +298,11 @@ Some chapter
     expect(EParseError):
       let output8 = rstToHtml(input8, {roSupportMarkdown}, defaultConfig())
 
+  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`_?