Rst parser respect :start-after: and :end-before: in include directive (#12972)

* [FEATURE] rst parser respect :start-after: in include

Rst parser now respects `:start-after:` and `:end-before:` attributes
for `include` directive.

* [DOC] include directive parsing proc update

* [TEST] Added unit tests for include rst directive in `rst` module
This commit is contained in:
Kamanji
2020-01-05 12:01:21 +03:00
committed by Andreas Rumpf
parent ae68ff959b
commit 9a5aaadda8
2 changed files with 118 additions and 10 deletions

View File

@@ -1558,15 +1558,20 @@ proc parseDirBody(p: var RstParser, contentParser: SectionParser): PRstNode =
popInd(p)
proc dirInclude(p: var RstParser): PRstNode =
#
#The following options are recognized:
#
#start-after : text to find in the external data file
# Only the content after the first occurrence of the specified text will
# be included.
#end-before : text to find in the external data file
# Only the content before the first occurrence of the specified text
# (but after any after text) will be included.
##
## The following options are recognized:
##
## :start-after: text to find in the external data file
##
## Only the content after the first occurrence of the specified
## text will be included. If text is not found inclusion will
## start from beginning of the file
##
## :end-before: text to find in the external data file
##
## Only the content before the first occurrence of the specified
## text (but after any after text) will be included. If text is
## not found inclusion will happen until the end of the file.
#literal : flag (empty)
# The entire included text is inserted into the document as a single
# literal block (useful for program listings).
@@ -1586,10 +1591,34 @@ proc dirInclude(p: var RstParser): PRstNode =
result = newRstNode(rnLiteralBlock)
add(result, newRstNode(rnLeaf, readFile(path)))
else:
let inputString = readFile(path).string()
let startPosition =
block:
let searchFor = n.getFieldValue("start-after").strip()
if searchFor != "":
let pos = inputString.find(searchFor)
if pos != -1: pos + searchFor.len()
else: 0
else:
0
let endPosition =
block:
let searchFor = n.getFieldValue("end-before").strip()
if searchFor != "":
let pos = inputString.find(searchFor, start = startPosition)
if pos != -1: pos - 1
else: 0
else:
inputString.len - 1
var q: RstParser
initParser(q, p.s)
q.filename = path
q.col += getTokens(readFile(path), false, q.tok)
q.col += getTokens(
inputString[startPosition..endPosition].strip(),
false,
q.tok)
# workaround a GCC bug; more like the interior pointer bug?
#if find(q.tok[high(q.tok)].symbol, "\0\x01\x02") > 0:
# InternalError("Too many binary zeros in include file")

79
tests/stdlib/trst.nim Normal file
View File

@@ -0,0 +1,79 @@
# tests for rst module
import ../../lib/packages/docutils/rstgen
import ../../lib/packages/docutils/rst
import unittest
import os
suite "RST include directive":
test "Include whole":
"other.rst".writeFile("**test1**")
let input = ".. include:: other.rst"
assert "<strong>test1</strong>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")
test "Include starting from":
"other.rst".writeFile("""
And this should **NOT** be visible in `docs.html`
OtherStart
*Visible*
""")
let input = """
.. include:: other.rst
:start-after: OtherStart
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")
test "Include everything before":
"other.rst".writeFile("""
*Visible*
OtherEnd
And this should **NOT** be visible in `docs.html`
""")
let input = """
.. include:: other.rst
:end-before: OtherEnd
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")
test "Include everything between":
"other.rst".writeFile("""
And this should **NOT** be visible in `docs.html`
OtherStart
*Visible*
OtherEnd
And this should **NOT** be visible in `docs.html`
""")
let input = """
.. include:: other.rst
:start-after: OtherStart
:end-before: OtherEnd
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")
test "Ignore premature ending string":
"other.rst".writeFile("""
OtherEnd
And this should **NOT** be visible in `docs.html`
OtherStart
*Visible*
OtherEnd
And this should **NOT** be visible in `docs.html`
""")
let input = """
.. include:: other.rst
:start-after: OtherStart
:end-before: OtherEnd
"""
assert "<em>Visible</em>" == rstTohtml(input, {}, defaultConfig())
removeFile("other.rst")