mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-03 11:42:33 +00:00
make rst.nim use object variant (#17138)
* make rst.nim use object variant * add workaround * fix mistake
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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\">" &
|
||||
|
||||
@@ -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`_?
|
||||
|
||||
Reference in New Issue
Block a user