diff options
author | Andrey Makarov <ph.makarov@gmail.com> | 2020-12-31 13:20:04 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-31 11:20:04 +0100 |
commit | 5984f7a7dda5e6fb3119cd5705d5758e1b8f3fc7 (patch) | |
tree | 1a6b36185ba46ee8f846eb5e985245fcd91b7b36 | |
parent | 17992fca1dc0b3674dce123296b277551bbca1db (diff) | |
download | Nim-5984f7a7dda5e6fb3119cd5705d5758e1b8f3fc7.tar.gz |
RST: improve line blocks (#16518)
-rw-r--r-- | lib/packages/docutils/rst.nim | 24 | ||||
-rw-r--r-- | lib/packages/docutils/rstast.nim | 5 | ||||
-rw-r--r-- | lib/packages/docutils/rstgen.nim | 16 | ||||
-rw-r--r-- | nimdoc/rst2html/expected/rst_examples.html | 2 | ||||
-rw-r--r-- | tests/stdlib/trstgen.nim | 38 |
5 files changed, 68 insertions, 17 deletions
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index 698d76da1..8d16edc61 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 f01bcada1..e4e192fa3 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 5aa2b03d4..52125b52c 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, "<p>$1</p>", "$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, "<p>$1</p> ", "\n\n$1", result) + else: # add extra spacing around the line block for Latex + renderAux(d, n, "<p>$1</p>", "\n\\vspace{0.5em}\n$1\\vspace{0.5em}\n", result) of rnLineBlockItem: - renderAux(d, n, "$1<br />", "$1\\\\\n", result) + if n.text.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 + renderAux(d, n, "<br/>", "\\vspace{1em}\n", result) + else: # additional indentation w.r.t. '| ' + let indent = $(0.5 * (n.text.len - 1).toFloat) & "em" + renderAux(d, n, + "<span style=\"margin-left: " & indent & "\">$1</span><br/>", + "\\noindent\\hspace{" & indent & "}$1\n\n", result) of rnBlockQuote: renderAux(d, n, "<blockquote><p>$1</p></blockquote>\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 a95fac0bd..23d192009 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 <p>Apart from built-in operations like array indexing, memory allocation, etc. the <tt class="docutils literal"><span class="pre">raise</span></tt> statement is the only way to raise an exception.</p> <p><tt class="docutils literal"><span class="pre">typedesc</span></tt> used as a parameter type also introduces an implicit generic. <tt class="docutils literal"><span class="pre">typedesc</span></tt> has its own set of rules:</p> <p>The <tt class="docutils literal"><span class="pre">!=</span></tt>, <tt class="docutils literal"><span class="pre">></span></tt>, <tt class="docutils literal"><span class="pre">>=</span></tt>, <tt class="docutils literal"><span class="pre">in</span></tt>, <tt class="docutils literal"><span class="pre">notin</span></tt>, <tt class="docutils literal"><span class="pre">isnot</span></tt> operators are in fact templates:</p> -<p><tt class="docutils literal"><span class="pre">a > b</span></tt> is transformed into <tt class="docutils literal"><span class="pre">b < a</span></tt>.<br /><tt class="docutils literal"><span class="pre">a in b</span></tt> is transformed into <tt class="docutils literal"><span class="pre">contains(b, a)</span></tt>.<br /><tt class="docutils literal"><span class="pre">notin</span></tt> and <tt class="docutils literal"><span class="pre">isnot</span></tt> have the obvious meanings.<br /></p><p>A template where every parameter is <tt class="docutils literal"><span class="pre">untyped</span></tt> is called an <span id="immediate_1">immediate</span> template. For historical reasons templates can be explicitly annotated with an <tt class="docutils literal"><span class="pre">immediate</span></tt> pragma and then these templates do not take part in overloading resolution and the parameters' types are <em>ignored</em> by the compiler. Explicit immediate templates are now deprecated.</p> +<p><tt class="docutils literal"><span class="pre">a > b</span></tt> is transformed into <tt class="docutils literal"><span class="pre">b < a</span></tt>.<br/><tt class="docutils literal"><span class="pre">a in b</span></tt> is transformed into <tt class="docutils literal"><span class="pre">contains(b, a)</span></tt>.<br/><tt class="docutils literal"><span class="pre">notin</span></tt> and <tt class="docutils literal"><span class="pre">isnot</span></tt> have the obvious meanings.<br/></p><p>A template where every parameter is <tt class="docutils literal"><span class="pre">untyped</span></tt> is called an <span id="immediate_1">immediate</span> template. For historical reasons templates can be explicitly annotated with an <tt class="docutils literal"><span class="pre">immediate</span></tt> pragma and then these templates do not take part in overloading resolution and the parameters' types are <em>ignored</em> by the compiler. Explicit immediate templates are now deprecated.</p> <h2><a class="toc-backref" id="constants-and-constant-expressions-symbol-lookup-in-generics" href="#constants-and-constant-expressions-symbol-lookup-in-generics">Symbol lookup in generics</a></h2> <h3><a class="toc-backref" id="symbol-lookup-in-generics-open-and-closed-symbols" href="#symbol-lookup-in-generics-open-and-closed-symbols">Open and Closed symbols</a></h3><p>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.</p> diff --git a/tests/stdlib/trstgen.nim b/tests/stdlib/trstgen.nim index 54a3db202..7acb23c5b 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<br />" in output1 - doAssert "other line<br />" in output1 + doAssert output1 == "<p><br/><br/>line block<br/>other line<br/></p>" 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<p><br/></p> <p>Paragraph2</p>\n" == output2 + + let input3 = dedent""" + | xxx + | yyy + | zzz""" + + let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig()) + doAssert "xxx<br/>" in output3 + doAssert "<span style=\"margin-left: 1.0em\">yyy</span><br/>" in output3 + doAssert "<span style=\"margin-left: 2.0em\">zzz</span><br/>" 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<br/><br/>" in output4 + doAssert "<span style=\"margin-left: 2.0em\">zzz</span><br/>" in output4 test "RST enumerated lists": let input1 = dedent """ |