Feature: Rest: .. include::: Support :start-after: and :end-before: in :literal: mode (#26130)

With this addition, we can include code samples in the docs using
comments as achors. This is analogous to mdBook's
[shiftinclude](https://github.com/daviddrysdale/mdbook-shiftinclude)
preprocessor, which is used extensively in the Status projects docs,
e.g.:
https://github.com/status-im/nim-chronos/blob/master/docs/src/tutorials/http_client/chapter1.md?plain=1#L16

P.S. One missing piece would be the ability to de-dent the included code
automatically but that's a feature for another PR. This isn't as
critical as the ability to include parts of the code.
This commit is contained in:
Constantine Molchanov
2026-08-23 14:36:25 +04:00
committed by GitHub
parent 6f1e6fdd06
commit 37223d2ea9
2 changed files with 54 additions and 22 deletions

View File

@@ -3319,31 +3319,31 @@ proc dirInclude(p: var RstParser): PRstNode =
rstMessage(p, meCannotOpenFile, filename)
else:
# XXX: error handling; recursive file inclusion!
let inputString = readFile(path)
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
if getFieldValue(n, "literal") != "":
result = newRstNode(rnLiteralBlock)
result.add newLeaf(readFile(path))
result.add newLeaf(inputString[startPosition..endPosition])
else:
let inputString = readFile(path)
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)
let saveFileIdx = p.s.currFileIdx

View File

@@ -1630,6 +1630,38 @@ And this should **NOT** be visible in `docs.html`
doAssert "<em>Visible</em>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
removeFile("other.rst")
test "`:literal:` flag":
"code.nim".writeFile("""
discard
""")
let input = """
.. include:: code.nim
:literal:
"""
check "<pre>discard\n</pre>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
removeFile("code.nim")
test "Include everything between in `:literal:` mode":
"code.nim".writeFile("""
proc notIncluded = discard
#CodeStart
proc included = discard
#CodeEnd
proc notIncluded = discard
""")
let input = """
.. include:: code.nim
:literal:
:start-after: #CodeStart
:end-before: #CodeEnd
"""
check "<pre>\nproc included = discard\n</pre>" == rstToHtml(input, {roSandboxDisabled}, defaultConfig())
removeFile("code.nim")
suite "RST escaping":
test "backspaces":
check("""\ this""".toAst == dedent"""