diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index 698d76da10..8d16edc617 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -1147,7 +1147,8 @@ proc isAdornmentHeadline(p: RstParser, adornmentIdx: int): bool = proc isLineBlock(p: RstParser): bool = var j = tokenAfterNewline(p) result = currentTok(p).col == p.tok[j].col and p.tok[j].symbol == "|" or - p.tok[j].col > currentTok(p).col + p.tok[j].col > currentTok(p).col or + p.tok[j].symbol == "\n" proc predNL(p: RstParser): bool = result = true @@ -1245,21 +1246,28 @@ proc whichSection(p: RstParser): RstNodeKind = proc parseLineBlock(p: var RstParser): PRstNode = result = nil - if nextTok(p).kind == tkWhite: + if nextTok(p).kind in {tkWhite, tkIndent}: var col = currentTok(p).col result = newRstNode(rnLineBlock) - pushInd(p, p.tok[p.idx + 2].col) - inc p.idx, 2 while true: var item = newRstNode(rnLineBlockItem) - parseSection(p, item) + if nextTok(p).kind == tkWhite: + if nextTok(p).symbol.len > 1: # pass additional indentation after '| ' + item.text = 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" + inc p.idx, 1 result.add(item) if currentTok(p).kind == tkIndent and currentTok(p).ival == col and - nextTok(p).symbol == "|" and p.tok[p.idx + 2].kind == tkWhite: - inc p.idx, 3 + nextTok(p).symbol == "|" and + p.tok[p.idx + 2].kind in {tkWhite, tkIndent}: + inc p.idx, 1 else: break - popInd(p) proc parseParagraph(p: var RstParser, result: PRstNode) = while true: diff --git a/lib/packages/docutils/rstast.nim b/lib/packages/docutils/rstast.nim index f01bcada12..e4e192fa38 100644 --- a/lib/packages/docutils/rstast.nim +++ b/lib/packages/docutils/rstast.nim @@ -35,7 +35,8 @@ type rnOptionList, rnOptionListItem, rnOptionGroup, rnOption, rnOptionString, rnOptionArgument, rnDescription, rnLiteralBlock, rnQuotedLiteralBlock, rnLineBlock, # the | thingie - rnLineBlockItem, # sons of the | thing + rnLineBlockItem, # a son of rnLineBlock - one line inside it. + # When `RstNode` text="\n" the line's empty rnBlockQuote, # text just indented rnTable, rnGridTable, rnMarkdownTable, rnTableRow, rnTableHeaderCell, rnTableDataCell, rnLabel, # used for footnotes and other things @@ -73,7 +74,7 @@ type 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 rnAdmonition; and rnLineBlockItem level*: int ## valid for some node kinds sons*: RstNodeSeq ## the node's sons diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index 5aa2b03d4c..52125b52ca 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -1160,9 +1160,21 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) = of rnQuotedLiteralBlock: doAssert false, "renderRstToOut" of rnLineBlock: - renderAux(d, n, "

$1

", "$1\n\n", result) + if n.sons.len == 1 and n.sons[0].text == "\n": + # whole line block is one empty line, no need to add extra spacing + renderAux(d, n, "

$1

", "\n\n$1", result) + else: # add extra spacing around the line block for Latex + renderAux(d, n, "

$1

", "\n\\vspace{0.5em}\n$1\\vspace{0.5em}\n", result) of rnLineBlockItem: - renderAux(d, n, "$1
", "$1\\\\\n", result) + if n.text.len == 0: # normal case - no additional indentation + renderAux(d, n, "$1
", "\\noindent $1\n\n", result) + elif n.text == "\n": # add one empty line + renderAux(d, n, "
", "\\vspace{1em}\n", result) + else: # additional indentation w.r.t. '| ' + let indent = $(0.5 * (n.text.len - 1).toFloat) & "em" + renderAux(d, n, + "$1
", + "\\noindent\\hspace{" & indent & "}$1\n\n", result) of rnBlockQuote: renderAux(d, n, "

$1

\n", "\\begin{quote}$1\\end{quote}\n", result) diff --git a/nimdoc/rst2html/expected/rst_examples.html b/nimdoc/rst2html/expected/rst_examples.html index a95fac0bd9..23d1920097 100644 --- a/nimdoc/rst2html/expected/rst_examples.html +++ b/nimdoc/rst2html/expected/rst_examples.html @@ -215,7 +215,7 @@ stmt = IND{>} stmt ^+ IND{=} DED # list of statements

Apart from built-in operations like array indexing, memory allocation, etc. the raise statement is the only way to raise an exception.

typedesc used as a parameter type also introduces an implicit generic. typedesc has its own set of rules:

The !=, >, >=, in, notin, isnot operators are in fact templates:

-

a > b is transformed into b < a.
a in b is transformed into contains(b, a).
notin and isnot have the obvious meanings.

A template where every parameter is untyped is called an immediate template. For historical reasons templates can be explicitly annotated with an immediate pragma and then these templates do not take part in overloading resolution and the parameters' types are ignored by the compiler. Explicit immediate templates are now deprecated.

+

a > b is transformed into b < a.
a in b is transformed into contains(b, a).
notin and isnot have the obvious meanings.

A template where every parameter is untyped is called an immediate template. For historical reasons templates can be explicitly annotated with an immediate pragma and then these templates do not take part in overloading resolution and the parameters' types are ignored by the compiler. Explicit immediate templates are now deprecated.

Symbol lookup in generics

Open and Closed symbols

The symbol binding rules in generics are slightly subtle: There are "open" and "closed" symbols. A "closed" symbol cannot be re-bound in the instantiation context, an "open" symbol can. Per default overloaded symbols are open and every other symbol is closed.

diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim index 54a3db202d..7acb23c5bf 100644 --- a/tests/stdlib/trstgen.nim +++ b/tests/stdlib/trstgen.nim @@ -355,11 +355,41 @@ Test1 rstGenera.renderRstToOut(rstParse(input1, "", 1, 1, option, {}), output1) doAssert rstGenera.meta[metaTitle] == "Test1" # check that title was not overwritten to '|' - doAssert "line block
" in output1 - doAssert "other line
" in output1 + doAssert output1 == "



line block
other line

" let output1l = rstToLatex(input1, {}) - doAssert "line block\\\\" in output1l - doAssert "other line\\\\" in output1l + doAssert "line block\n\n" in output1l + doAssert "other line\n\n" in output1l + doAssert output1l.count("\\vspace") == 2 + 2 # +2 surrounding paddings + + let input2 = dedent""" + Paragraph1 + + | + + Paragraph2""" + + let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig()) + doAssert "Paragraph1


Paragraph2

\n" == output2 + + let input3 = dedent""" + | xxx + | yyy + | zzz""" + + let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig()) + doAssert "xxx
" in output3 + doAssert "yyy
" in output3 + doAssert "zzz
" in output3 + + # check that '| ' with a few spaces is still parsed as new line + let input4 = dedent""" + | xxx + | + | zzz""" + + let output4 = rstToHtml(input4, {roSupportMarkdown}, defaultConfig()) + doAssert "xxx

" in output4 + doAssert "zzz
" in output4 test "RST enumerated lists": let input1 = dedent """