diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index eaefc7265d..50b8556629 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -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")
diff --git a/tests/stdlib/trst.nim b/tests/stdlib/trst.nim
new file mode 100644
index 0000000000..6b1bd6897c
--- /dev/null
+++ b/tests/stdlib/trst.nim
@@ -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 "test1" == 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 "Visible" == 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 "Visible" == 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 "Visible" == 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 "Visible" == rstTohtml(input, {}, defaultConfig())
+ removeFile("other.rst")