summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/packages/docutils/rst.nim49
-rw-r--r--tests/stdlib/trst.nim79
2 files changed, 118 insertions, 10 deletions
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index eaefc7265..50b855662 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 000000000..6b1bd6897
--- /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 "<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")