Skip to content

Commit

Permalink
Add doctype: RST|Markdown|RstMarkdown pragma
Browse files Browse the repository at this point in the history
Implements nim-lang/RFCs#68 ,
see also discussion in nim-lang#17987

The permitted values:
* `markdown`, which is default. It still contains nearly all of
  the RST supported but it is assumed that in time we will give up
  most or all RST features in this mode
* `rst`, without any extensions
* `RstMarkdown` — compatibility with Nim 1.x. It's basically RST
  with those Markdown features enabled that don't conflict with RST.
  • Loading branch information
a-mr committed Aug 20, 2022
1 parent 1c31de3 commit 24946da
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 4 deletions.
37 changes: 37 additions & 0 deletions compiler/docgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
if preferMarkdown:
options.incl roPreferMarkdown
if not standaloneDoc: options.incl roNimFile
# (options can be changed dynamically in `setDoctype` by `{.doctype.}`)
result.sharedState = newRstSharedState(
options, filename.string,
docgenFindFile, compilerMsgHandler)
Expand Down Expand Up @@ -1121,6 +1122,37 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonItem =
param["types"].add %($kind)
result.json["signature"]["genericParams"].add param

proc setDoctype(d: PDoc, n: PNode) =
## Processes `{.doctype.}` pragma changing Markdown/RST parsing options.
if n != nil:
if n.len == 2:
var dt = ""
if n[1].kind == nkStrLit:
dt = n[1].strVal.toLowerAscii
elif n[1].kind == nkIdent:
dt = n[1].ident.s.toLowerAscii
else:
localError(d.conf, n.info, errUser,
"unknown argument type $1 provided to doctype" % [
$n[1].kind])
return
case dt
of "markdown":
d.sharedState.options.incl roSupportMarkdown
d.sharedState.options.incl roPreferMarkdown
of "rstmarkdown":
d.sharedState.options.incl roSupportMarkdown
d.sharedState.options.excl roPreferMarkdown
of "rst":
d.sharedState.options.excl roSupportMarkdown
d.sharedState.options.excl roPreferMarkdown
else: localError(d.conf, n.info, errUser,
("unknown doctype value \"$1\", should be from " &
"\"RST\", \"Markdown\", \"RstMarkdown\"") % [dt])
else:
localError(d.conf, n.info, errUser,
"doctype pragma takes exactly 1 argument")

proc checkForFalse(n: PNode): bool =
result = n.kind == nkIdent and cmpIgnoreStyle(n.ident.s, "false") == 0

Expand Down Expand Up @@ -1238,6 +1270,8 @@ proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
of nkPragma:
let pragmaNode = findPragma(n, wDeprecated)
d.modDeprecationMsg.add(genDeprecationMsg(d, pragmaNode))
let doctypeNode = findPragma(n, wDoctype)
setDoctype(d, doctypeNode)
of nkCommentStmt: d.modDescPre.add(genComment(d, n))
of nkProcDef, nkFuncDef:
when useEffectSystem: documentRaises(d.cache, n)
Expand Down Expand Up @@ -1373,6 +1407,9 @@ proc add(d: PDoc; j: JsonItem) =

proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
case n.kind
of nkPragma:
let doctypeNode = findPragma(n, wDoctype)
setDoctype(d, doctypeNode)
of nkCommentStmt:
if includeComments:
d.add JsonItem(rst: genComment(d, n), rstField: "comment",
Expand Down
5 changes: 4 additions & 1 deletion compiler/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const
wDeprecated,
wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
wExperimental, wThis, wUsed, wInvariant, wAssume, wAssert}
wExperimental, wDoctype, wThis, wUsed, wInvariant, wAssume, wAssert}
stmtPragmasTopLevel* = {wChecks, wObjChecks, wFieldChecks, wRangeChecks,
wBoundChecks, wOverflowChecks, wNilChecks, wStaticBoundchecks,
wStyleChecks, wAssertions,
Expand Down Expand Up @@ -1216,6 +1216,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if not isTopLevel(c):
localError(c.config, n.info, "'experimental' pragma only valid as toplevel statement or in a 'push' environment")
processExperimental(c, it)
of wDoctype:
if not isTopLevel(c):
localError(c.config, n.info, "'doctype' pragma only valid as toplevel statement")
of wThis:
if it.kind in nkPragmaCallKinds and it.len == 2:
c.selfName = considerQuotedIdent(c, it[1])
Expand Down
2 changes: 1 addition & 1 deletion compiler/wordrecg.nim
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ type
wLocalPassc = "localPassC", wBorrow = "borrow", wDiscardable = "discardable",
wFieldChecks = "fieldChecks", wSubsChar = "subschar", wAcyclic = "acyclic",
wShallow = "shallow", wUnroll = "unroll", wLinearScanEnd = "linearScanEnd",
wComputedGoto = "computedGoto", wExperimental = "experimental",
wComputedGoto = "computedGoto", wExperimental = "experimental", wDoctype = "doctype",
wWrite = "write", wGensym = "gensym", wInject = "inject", wDirty = "dirty",
wInheritable = "inheritable", wThreadVar = "threadvar", wEmit = "emit",
wAsmNoStackFrame = "asmNoStackFrame", wImplicitStatic = "implicitStatic",
Expand Down
2 changes: 1 addition & 1 deletion lib/packages/docutils/rst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ type
filenameToIdx*: Table[string, FileIndex]
idxToFilename*: seq[string]
RstSharedState = object
options: RstParseOptions # parsing options
options*: RstParseOptions # parsing options
hLevels: LevelMap # hierarchy of heading styles
hTitleCnt: int # =0 if no title, =1 if only main title,
# =2 if both title and subtitle are present
Expand Down
82 changes: 82 additions & 0 deletions nimdoc/test_doctype/expected/test_doctype.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- This file is generated by Nim. -->
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nimdoc/test_doctype/test_doctype</title>

<!-- Favicon -->
<link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
<link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">

<!-- Google fonts -->
<link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
<link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>

<!-- CSS -->
<link rel="stylesheet" type="text/css" href="nimdoc.out.css">

<!-- JS -->
<script type="text/javascript" src="dochack.js"></script>
</head>
<body>
<div class="document" id="documentId">
<div class="container">
<h1 class="title">nimdoc/test_doctype/test_doctype</h1>
<div class="row">
<div class="three columns">
<div class="theme-switch-wrapper">
<label class="theme-switch" for="checkbox">
<input type="checkbox" id="checkbox" />
<div class="slider round"></div>
</label>
&nbsp;&nbsp;&nbsp; <em>Dark Mode</em>
</div>
<div id="global-links">
<ul class="simple">
<li><a href="theindex.html">Index</a></li>
</ul>
</div>
<div id="searchInputDiv">
Search: <input type="search" id="searchInput" onkeyup="search()"/>
</div>
<div>
Group by:
<select onchange="groupBy(this.value)">
<option value="section">Section</option>
<option value="type">Type</option>
</select>
</div>
<ul class="simple simple-toc" id="toc-list">
<li><a class="reference" id="check_toc" href="#check">Check</a></li>
<li><a class="reference" id="text_toc" href="#text">text</a></li>

</ul>

</div>
<div class="nine columns" id="content">

<div id="tocRoot"></div>

<p class="module-desc"><p>Check</p>
<p><pre class="listing">
<span class="Identifier">text</span></pre></p>

<h1><a class="toc-backref" id="check" href="#check">Check</a></h1>
<h1><a class="toc-backref" id="text" href="#text">text</a></h1></p>

</div>
</div>

<div class="twelve-columns footer">
<span class="nim-sprite"></span>
<br>
<small style="color: var(--hint);">Made with Nim. Generated: 1970-01-02 03:46:40 UTC</small>
</div>
</div>
</div>

</body>
</html>
15 changes: 15 additions & 0 deletions nimdoc/test_doctype/test_doctype.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Markdown (default) interpretes this as text + a Markdown code block:

## Check
## ~~~~~
## text
## ~~~~~

{.doctype: RST.}

# Now RST interpretes this as 2 headings:

## Check
## ~~~~~
## text
## ~~~~~
11 changes: 10 additions & 1 deletion nimdoc/tester.nim
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ proc testNimDoc(prjDir, docsDir: string; switches: NimSwitches; fixup = false) =
if nimBuildIndexSwitches != "":
exec("$1 buildIndex $2" % [nimExe, nimBuildIndexSwitches])

for expected in walkDirRec(prjDir / "expected/"):
for expected in walkDirRec(prjDir / "expected/", checkDir=true):
let produced = expected.replace('\\', '/').replace("/expected/", "/$1/" % [docsDir])
if not fileExists(produced):
echo "FAILURE: files not found: ", produced
Expand Down Expand Up @@ -79,5 +79,14 @@ let
"$1/$2" % [test2Dir, test2DocsDir]])
testNimDoc(test2Dir, test2DocsDir, test2Switches, fixup)

# Test `nim doc` on file with `{.doctype.}` pragma
let
test3PrjDir = "test_doctype"
test3PrjName = "test_doctype"
test3Dir = baseDir / test3PrjDir
test3DocsDir = "htmldocs"
test3Switches = NimSwitches(doc: @["$1/$2.nim" % [test3Dir, test3PrjName]])
testNimDoc(test3Dir, test3DocsDir, test3Switches, fixup)

if failures > 0:
quit "$# failures occurred; see note in nimdoc/tester.nim regarding -d:nimTestsNimdocFixup" % $failures

0 comments on commit 24946da

Please sign in to comment.