diff options
-rw-r--r-- | compiler/docgen.nim | 4 | ||||
-rw-r--r-- | lib/packages/docutils/rst.nim | 162 | ||||
-rw-r--r-- | lib/packages/docutils/rstast.nim | 70 | ||||
-rw-r--r-- | lib/packages/docutils/rstgen.nim | 50 | ||||
-rw-r--r-- | tests/stdlib/trstgen.nim | 5 |
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`_? |