Improve Markdown code blocks & start moving docs to Markdown style (#19954)
- add additional parameters parsing (other implementations will just
ignore them). E.g. if in RST we have:
.. code:: nim
:test: "nim c $1"
...
then in Markdown that will be:
```nim test="nim c $1"
...
```
- implement Markdown interpretation of additional indentation which is
less than 4 spaces (>=4 spaces is a code block but it's not
implemented yet). RST interpretes it as quoted block, for Markdown it's
just normal paragraphs.
- add separate `md2html` and `md2tex` commands. This is to separate
Markdown behavior in cases when it diverges w.r.t. RST significantly —
most conspicously like in the case of additional indentation above, and
also currently the contradicting inline rule of Markdown is also turned
on only in `md2html` and `md2tex`. **Rationale:** mixing Markdown and
RST arbitrarily is a way to nowhere, we need to provide a way to fix the
particular behavior. Note that still all commands have **both** Markdown
and RST features **enabled**. In this PR `*.nim` files can be processed
only in Markdown mode, while `md2html` is for `*.md` files and
`rst2html` for `*.rst` files.
- rename `*.rst` files to `.*md` as our current default behavior is
already Markdown-ish
- convert code blocks in `docgen.rst` to Markdown style as an example.
Other code blocks will be converted in the follow-up PRs
- fix indentation inside Markdown code blocks — additional indentation
is preserved there
- allow more than 3 backticks open/close blocks (tildas \~ are still not
allowed to avoid conflict with RST adornment headings) see also
https://github.com/nim-lang/RFCs/issues/355
- better error messages
- (other) fix a bug that admonitions cannot be used in sandbox mode; fix
annoying warning on line 2711
This commit is contained in:
parent
f35c9cf73d
commit
417b90a7e5
47 changed files with 341 additions and 126 deletions
|
|
@ -449,6 +449,8 @@ proc parseCommand*(command: string): Command =
|
||||||
of "doc2", "doc": cmdDoc
|
of "doc2", "doc": cmdDoc
|
||||||
of "doc2tex": cmdDoc2tex
|
of "doc2tex": cmdDoc2tex
|
||||||
of "rst2html": cmdRst2html
|
of "rst2html": cmdRst2html
|
||||||
|
of "md2tex": cmdMd2tex
|
||||||
|
of "md2html": cmdMd2html
|
||||||
of "rst2tex": cmdRst2tex
|
of "rst2tex": cmdRst2tex
|
||||||
of "jsondoc0": cmdJsondoc0
|
of "jsondoc0": cmdJsondoc0
|
||||||
of "jsondoc2", "jsondoc": cmdJsondoc
|
of "jsondoc2", "jsondoc": cmdJsondoc
|
||||||
|
|
@ -480,7 +482,8 @@ proc setCommandEarly*(conf: ConfigRef, command: string) =
|
||||||
# command early customizations
|
# command early customizations
|
||||||
# must be handled here to honor subsequent `--hint:x:on|off`
|
# must be handled here to honor subsequent `--hint:x:on|off`
|
||||||
case conf.cmd
|
case conf.cmd
|
||||||
of cmdRst2html, cmdRst2tex: # xxx see whether to add others: cmdGendepend, etc.
|
of cmdRst2html, cmdRst2tex, cmdMd2html, cmdMd2tex:
|
||||||
|
# xxx see whether to add others: cmdGendepend, etc.
|
||||||
conf.foreignPackageNotes = {hintSuccessX}
|
conf.foreignPackageNotes = {hintSuccessX}
|
||||||
else:
|
else:
|
||||||
conf.foreignPackageNotes = foreignPackageNotesDefault
|
conf.foreignPackageNotes = foreignPackageNotesDefault
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ type
|
||||||
jEntriesFinal: JsonNode # final JSON after RST pass 2 and rendering
|
jEntriesFinal: JsonNode # final JSON after RST pass 2 and rendering
|
||||||
types: TStrTable
|
types: TStrTable
|
||||||
sharedState: PRstSharedState
|
sharedState: PRstSharedState
|
||||||
isPureRst: bool
|
standaloneDoc: bool
|
||||||
conf*: ConfigRef
|
conf*: ConfigRef
|
||||||
cache*: IdentCache
|
cache*: IdentCache
|
||||||
exampleCounter: int
|
exampleCounter: int
|
||||||
|
|
@ -230,6 +230,7 @@ template declareClosures =
|
||||||
case msgKind
|
case msgKind
|
||||||
of meCannotOpenFile: k = errCannotOpenFile
|
of meCannotOpenFile: k = errCannotOpenFile
|
||||||
of meExpected: k = errXExpected
|
of meExpected: k = errXExpected
|
||||||
|
of meMissingClosing: k = errRstMissingClosing
|
||||||
of meGridTableNotImplemented: k = errRstGridTableNotImplemented
|
of meGridTableNotImplemented: k = errRstGridTableNotImplemented
|
||||||
of meMarkdownIllformedTable: k = errRstMarkdownIllformedTable
|
of meMarkdownIllformedTable: k = errRstMarkdownIllformedTable
|
||||||
of meIllformedTable: k = errRstIllformedTable
|
of meIllformedTable: k = errRstIllformedTable
|
||||||
|
|
@ -276,16 +277,18 @@ proc isLatexCmd(conf: ConfigRef): bool = conf.cmd in {cmdRst2tex, cmdDoc2tex}
|
||||||
|
|
||||||
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||||
outExt: string = HtmlExt, module: PSym = nil,
|
outExt: string = HtmlExt, module: PSym = nil,
|
||||||
isPureRst = false): PDoc =
|
standaloneDoc = false, preferMarkdown = true): PDoc =
|
||||||
declareClosures()
|
declareClosures()
|
||||||
new(result)
|
new(result)
|
||||||
result.module = module
|
result.module = module
|
||||||
result.conf = conf
|
result.conf = conf
|
||||||
result.cache = cache
|
result.cache = cache
|
||||||
result.outDir = conf.outDir.string
|
result.outDir = conf.outDir.string
|
||||||
result.isPureRst = isPureRst
|
result.standaloneDoc = standaloneDoc
|
||||||
var options= {roSupportRawDirective, roSupportMarkdown, roPreferMarkdown, roSandboxDisabled}
|
var options= {roSupportRawDirective, roSupportMarkdown, roSandboxDisabled}
|
||||||
if not isPureRst: options.incl roNimFile
|
if preferMarkdown:
|
||||||
|
options.incl roPreferMarkdown
|
||||||
|
if not standaloneDoc: options.incl roNimFile
|
||||||
result.sharedState = newRstSharedState(
|
result.sharedState = newRstSharedState(
|
||||||
options, filename.string,
|
options, filename.string,
|
||||||
docgenFindFile, compilerMsgHandler)
|
docgenFindFile, compilerMsgHandler)
|
||||||
|
|
@ -333,7 +336,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
|
||||||
# Make sure the destination directory exists
|
# Make sure the destination directory exists
|
||||||
createDir(outp.splitFile.dir)
|
createDir(outp.splitFile.dir)
|
||||||
# Include the current file if we're parsing a nim file
|
# Include the current file if we're parsing a nim file
|
||||||
let importStmt = if d.isPureRst: "" else: "import \"$1\"\n" % [d.filename.replace("\\", "/")]
|
let importStmt = if d.standaloneDoc: "" else: "import \"$1\"\n" % [d.filename.replace("\\", "/")]
|
||||||
writeFile(outp, importStmt & content)
|
writeFile(outp, importStmt & content)
|
||||||
|
|
||||||
proc interpSnippetCmd(cmd: string): string =
|
proc interpSnippetCmd(cmd: string): string =
|
||||||
|
|
@ -1512,7 +1515,7 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
|
||||||
"\\\\\\vspace{0.5em}\\large $1", [esc(d.target, d.meta[metaSubtitle])])
|
"\\\\\\vspace{0.5em}\\large $1", [esc(d.target, d.meta[metaSubtitle])])
|
||||||
|
|
||||||
var groupsection = getConfigVar(d.conf, "doc.body_toc_groupsection")
|
var groupsection = getConfigVar(d.conf, "doc.body_toc_groupsection")
|
||||||
let bodyname = if d.hasToc and not d.isPureRst and not d.conf.isLatexCmd:
|
let bodyname = if d.hasToc and not d.standaloneDoc and not d.conf.isLatexCmd:
|
||||||
groupsection.setLen 0
|
groupsection.setLen 0
|
||||||
"doc.body_toc_group"
|
"doc.body_toc_group"
|
||||||
elif d.hasToc: "doc.body_toc"
|
elif d.hasToc: "doc.body_toc"
|
||||||
|
|
@ -1626,9 +1629,11 @@ proc commandDoc*(cache: IdentCache, conf: ConfigRef) =
|
||||||
generateIndex(d)
|
generateIndex(d)
|
||||||
|
|
||||||
proc commandRstAux(cache: IdentCache, conf: ConfigRef;
|
proc commandRstAux(cache: IdentCache, conf: ConfigRef;
|
||||||
filename: AbsoluteFile, outExt: string) =
|
filename: AbsoluteFile, outExt: string,
|
||||||
|
preferMarkdown: bool) =
|
||||||
var filen = addFileExt(filename, "txt")
|
var filen = addFileExt(filename, "txt")
|
||||||
var d = newDocumentor(filen, cache, conf, outExt, isPureRst = true)
|
var d = newDocumentor(filen, cache, conf, outExt, standaloneDoc = true,
|
||||||
|
preferMarkdown = preferMarkdown)
|
||||||
let rst = parseRst(readFile(filen.string),
|
let rst = parseRst(readFile(filen.string),
|
||||||
line=LineRstInit, column=ColRstInit,
|
line=LineRstInit, column=ColRstInit,
|
||||||
conf, d.sharedState)
|
conf, d.sharedState)
|
||||||
|
|
@ -1637,11 +1642,13 @@ proc commandRstAux(cache: IdentCache, conf: ConfigRef;
|
||||||
writeOutput(d)
|
writeOutput(d)
|
||||||
generateIndex(d)
|
generateIndex(d)
|
||||||
|
|
||||||
proc commandRst2Html*(cache: IdentCache, conf: ConfigRef) =
|
proc commandRst2Html*(cache: IdentCache, conf: ConfigRef,
|
||||||
commandRstAux(cache, conf, conf.projectFull, HtmlExt)
|
preferMarkdown=false) =
|
||||||
|
commandRstAux(cache, conf, conf.projectFull, HtmlExt, preferMarkdown)
|
||||||
|
|
||||||
proc commandRst2TeX*(cache: IdentCache, conf: ConfigRef) =
|
proc commandRst2TeX*(cache: IdentCache, conf: ConfigRef,
|
||||||
commandRstAux(cache, conf, conf.projectFull, TexExt)
|
preferMarkdown=false) =
|
||||||
|
commandRstAux(cache, conf, conf.projectFull, TexExt, preferMarkdown)
|
||||||
|
|
||||||
proc commandJson*(cache: IdentCache, conf: ConfigRef) =
|
proc commandJson*(cache: IdentCache, conf: ConfigRef) =
|
||||||
## implementation of a deprecated jsondoc0 command
|
## implementation of a deprecated jsondoc0 command
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ type
|
||||||
# non-fatal errors
|
# non-fatal errors
|
||||||
errIllFormedAstX, errCannotOpenFile,
|
errIllFormedAstX, errCannotOpenFile,
|
||||||
errXExpected,
|
errXExpected,
|
||||||
|
errRstMissingClosing,
|
||||||
errRstGridTableNotImplemented,
|
errRstGridTableNotImplemented,
|
||||||
errRstMarkdownIllformedTable,
|
errRstMarkdownIllformedTable,
|
||||||
errRstIllformedTable,
|
errRstIllformedTable,
|
||||||
|
|
@ -105,6 +106,7 @@ const
|
||||||
errIllFormedAstX: "illformed AST: $1",
|
errIllFormedAstX: "illformed AST: $1",
|
||||||
errCannotOpenFile: "cannot open '$1'",
|
errCannotOpenFile: "cannot open '$1'",
|
||||||
errXExpected: "'$1' expected",
|
errXExpected: "'$1' expected",
|
||||||
|
errRstMissingClosing: "$1",
|
||||||
errRstGridTableNotImplemented: "grid table is not implemented",
|
errRstGridTableNotImplemented: "grid table is not implemented",
|
||||||
errRstMarkdownIllformedTable: "illformed delimiter row of a markdown table",
|
errRstMarkdownIllformedTable: "illformed delimiter row of a markdown table",
|
||||||
errRstIllformedTable: "Illformed table: $1",
|
errRstIllformedTable: "Illformed table: $1",
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,8 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||||
var ret = if optUseNimcache in conf.globalOptions: getNimcacheDir(conf)
|
var ret = if optUseNimcache in conf.globalOptions: getNimcacheDir(conf)
|
||||||
else: conf.projectPath
|
else: conf.projectPath
|
||||||
doAssert ret.string.isAbsolute # `AbsoluteDir` is not a real guarantee
|
doAssert ret.string.isAbsolute # `AbsoluteDir` is not a real guarantee
|
||||||
if conf.cmd in cmdDocLike + {cmdRst2html, cmdRst2tex}: ret = ret / htmldocsDir
|
if conf.cmd in cmdDocLike + {cmdRst2html, cmdRst2tex, cmdMd2html, cmdMd2tex}:
|
||||||
|
ret = ret / htmldocsDir
|
||||||
conf.outDir = ret
|
conf.outDir = ret
|
||||||
|
|
||||||
## process all commands
|
## process all commands
|
||||||
|
|
@ -302,7 +303,7 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||||
commandDoc2(graph, HtmlExt)
|
commandDoc2(graph, HtmlExt)
|
||||||
if optGenIndex in conf.globalOptions and optWholeProject in conf.globalOptions:
|
if optGenIndex in conf.globalOptions and optWholeProject in conf.globalOptions:
|
||||||
commandBuildIndex(conf, $conf.outDir)
|
commandBuildIndex(conf, $conf.outDir)
|
||||||
of cmdRst2html:
|
of cmdRst2html, cmdMd2html:
|
||||||
# XXX: why are warnings disabled by default for rst2html and rst2tex?
|
# XXX: why are warnings disabled by default for rst2html and rst2tex?
|
||||||
for warn in rstWarnings:
|
for warn in rstWarnings:
|
||||||
conf.setNoteDefaults(warn, true)
|
conf.setNoteDefaults(warn, true)
|
||||||
|
|
@ -311,16 +312,16 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||||
conf.quitOrRaise "compiler wasn't built with documentation generator"
|
conf.quitOrRaise "compiler wasn't built with documentation generator"
|
||||||
else:
|
else:
|
||||||
loadConfigs(DocConfig, cache, conf, graph.idgen)
|
loadConfigs(DocConfig, cache, conf, graph.idgen)
|
||||||
commandRst2Html(cache, conf)
|
commandRst2Html(cache, conf, preferMarkdown = (conf.cmd == cmdMd2html))
|
||||||
of cmdRst2tex, cmdDoc2tex:
|
of cmdRst2tex, cmdMd2tex, cmdDoc2tex:
|
||||||
for warn in rstWarnings:
|
for warn in rstWarnings:
|
||||||
conf.setNoteDefaults(warn, true)
|
conf.setNoteDefaults(warn, true)
|
||||||
when defined(leanCompiler):
|
when defined(leanCompiler):
|
||||||
conf.quitOrRaise "compiler wasn't built with documentation generator"
|
conf.quitOrRaise "compiler wasn't built with documentation generator"
|
||||||
else:
|
else:
|
||||||
if conf.cmd == cmdRst2tex:
|
if conf.cmd in {cmdRst2tex, cmdMd2tex}:
|
||||||
loadConfigs(DocTexConfig, cache, conf, graph.idgen)
|
loadConfigs(DocTexConfig, cache, conf, graph.idgen)
|
||||||
commandRst2TeX(cache, conf)
|
commandRst2TeX(cache, conf, preferMarkdown = (conf.cmd == cmdMd2tex))
|
||||||
else:
|
else:
|
||||||
docLikeCmd commandDoc2(graph, TexExt)
|
docLikeCmd commandDoc2(graph, TexExt)
|
||||||
of cmdJsondoc0: docLikeCmd commandJson(cache, conf)
|
of cmdJsondoc0: docLikeCmd commandJson(cache, conf)
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
|
||||||
# `The parameter is incorrect`
|
# `The parameter is incorrect`
|
||||||
let cmd = cmdPrefix & output.quoteShell & ' ' & conf.arguments
|
let cmd = cmdPrefix & output.quoteShell & ' ' & conf.arguments
|
||||||
execExternalProgram(conf, cmd.strip(leading=false,trailing=true))
|
execExternalProgram(conf, cmd.strip(leading=false,trailing=true))
|
||||||
of cmdDocLike, cmdRst2html, cmdRst2tex: # bugfix(cmdRst2tex was missing)
|
of cmdDocLike, cmdRst2html, cmdRst2tex, cmdMd2html, cmdMd2tex: # bugfix(cmdRst2tex was missing)
|
||||||
if conf.arguments.len > 0:
|
if conf.arguments.len > 0:
|
||||||
# reserved for future use
|
# reserved for future use
|
||||||
rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd])
|
rawMessage(conf, errGenerated, "'$1 cannot handle arguments" % [$conf.cmd])
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,8 @@ type
|
||||||
cmdDoc2tex # convert .nim doc comments to LaTeX
|
cmdDoc2tex # convert .nim doc comments to LaTeX
|
||||||
cmdRst2html # convert a reStructuredText file to HTML
|
cmdRst2html # convert a reStructuredText file to HTML
|
||||||
cmdRst2tex # convert a reStructuredText file to TeX
|
cmdRst2tex # convert a reStructuredText file to TeX
|
||||||
|
cmdMd2html # convert a Markdown file to HTML
|
||||||
|
cmdMd2tex # convert a Markdown file to TeX
|
||||||
cmdJsondoc0
|
cmdJsondoc0
|
||||||
cmdJsondoc
|
cmdJsondoc
|
||||||
cmdCtags
|
cmdCtags
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@
|
||||||
.. no syntax highlighting here by default:
|
.. no syntax highlighting here by default:
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
"Heresy grows from idleness." -- Unknown.
|
|
||||||
|
> "Heresy grows from idleness." -- Unknown.
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
|
@ -581,7 +581,7 @@ Code reviews
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. include:: docstyle.rst
|
.. include:: docstyle.md
|
||||||
|
|
||||||
|
|
||||||
Evolving the stdlib
|
Evolving the stdlib
|
||||||
|
|
@ -35,14 +35,13 @@ Quick start
|
||||||
|
|
||||||
Generate HTML documentation for a file:
|
Generate HTML documentation for a file:
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim doc <filename>.nim
|
nim doc <filename>.nim
|
||||||
|
```
|
||||||
|
|
||||||
Generate HTML documentation for a whole project:
|
Generate HTML documentation for a whole project:
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
# delete any htmldocs/*.idx file before starting
|
# delete any htmldocs/*.idx file before starting
|
||||||
nim doc --project --index:on --git.url:<url> --git.commit:<tag> --outdir:htmldocs <main_filename>.nim
|
nim doc --project --index:on --git.url:<url> --git.commit:<tag> --outdir:htmldocs <main_filename>.nim
|
||||||
# this will generate html files, a theindex.html index, css and js under `htmldocs`
|
# this will generate html files, a theindex.html index, css and js under `htmldocs`
|
||||||
|
|
@ -54,7 +53,7 @@ Generate HTML documentation for a whole project:
|
||||||
# or `$nimcache/htmldocs` with `--usenimcache` which avoids clobbering your sources;
|
# or `$nimcache/htmldocs` with `--usenimcache` which avoids clobbering your sources;
|
||||||
# and likewise without `--project`.
|
# and likewise without `--project`.
|
||||||
# Adding `-r` will open in a browser directly.
|
# Adding `-r` will open in a browser directly.
|
||||||
|
```
|
||||||
|
|
||||||
Documentation Comments
|
Documentation Comments
|
||||||
----------------------
|
----------------------
|
||||||
|
|
@ -120,8 +119,8 @@ Example of Nim file input
|
||||||
The following examples will generate documentation for this sample
|
The following examples will generate documentation for this sample
|
||||||
*Nim* module, aptly named ``doc/docgen_sample.nim``:
|
*Nim* module, aptly named ``doc/docgen_sample.nim``:
|
||||||
|
|
||||||
.. code:: nim
|
```nim file=docgen_sample.nim
|
||||||
:file: docgen_sample.nim
|
```
|
||||||
|
|
||||||
All the below commands save their output to ``htmldocs`` directory relative to
|
All the below commands save their output to ``htmldocs`` directory relative to
|
||||||
the directory of file;
|
the directory of file;
|
||||||
|
|
@ -137,9 +136,9 @@ optionally, an index file.
|
||||||
|
|
||||||
The `doc`:option: command:
|
The `doc`:option: command:
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim doc docgen_sample.nim
|
nim doc docgen_sample.nim
|
||||||
|
```
|
||||||
|
|
||||||
Partial Output::
|
Partial Output::
|
||||||
...
|
...
|
||||||
|
|
@ -159,8 +158,7 @@ HTML -> PDF conversion).
|
||||||
|
|
||||||
The `doc2tex`:option: command:
|
The `doc2tex`:option: command:
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim doc2tex docgen_sample.nim
|
nim doc2tex docgen_sample.nim
|
||||||
cd htmldocs
|
cd htmldocs
|
||||||
xelatex docgen_sample.tex
|
xelatex docgen_sample.tex
|
||||||
|
|
@ -169,6 +167,7 @@ The `doc2tex`:option: command:
|
||||||
# large documents) to get all labels generated.
|
# large documents) to get all labels generated.
|
||||||
# That depends on this warning in the end of `xelatex` output:
|
# That depends on this warning in the end of `xelatex` output:
|
||||||
# LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
|
# LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.
|
||||||
|
```
|
||||||
|
|
||||||
The output is ``docgen_sample.pdf``.
|
The output is ``docgen_sample.pdf``.
|
||||||
|
|
||||||
|
|
@ -183,9 +182,9 @@ Note that this tool is built off of the `doc`:option: command
|
||||||
|
|
||||||
The `jsondoc`:option: command:
|
The `jsondoc`:option: command:
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim jsondoc docgen_sample.nim
|
nim jsondoc docgen_sample.nim
|
||||||
|
```
|
||||||
|
|
||||||
Output::
|
Output::
|
||||||
{
|
{
|
||||||
|
|
@ -209,9 +208,9 @@ renamed to `jsondoc0`:option:.
|
||||||
|
|
||||||
The `jsondoc0`:option: command:
|
The `jsondoc0`:option: command:
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim jsondoc0 docgen_sample.nim
|
nim jsondoc0 docgen_sample.nim
|
||||||
|
```
|
||||||
|
|
||||||
Output::
|
Output::
|
||||||
[
|
[
|
||||||
|
|
@ -249,9 +248,9 @@ the anchor [*]_ of Nim symbol that corresponds to link text.
|
||||||
|
|
||||||
If you have a constant:
|
If you have a constant:
|
||||||
|
|
||||||
.. code:: Nim
|
```Nim
|
||||||
|
|
||||||
const pi* = 3.14
|
const pi* = 3.14
|
||||||
|
```
|
||||||
|
|
||||||
then it should be referenced in one of the 2 forms:
|
then it should be referenced in one of the 2 forms:
|
||||||
|
|
||||||
|
|
@ -262,9 +261,9 @@ B. qualified (with symbol kind specification)::
|
||||||
|
|
||||||
For routine kinds there are more options. Consider this definition:
|
For routine kinds there are more options. Consider this definition:
|
||||||
|
|
||||||
.. code:: Nim
|
```Nim
|
||||||
|
|
||||||
proc foo*(a: int, b: float): string
|
proc foo*(a: int, b: float): string
|
||||||
|
```
|
||||||
|
|
||||||
Generally following syntax is allowed for referencing `foo`:
|
Generally following syntax is allowed for referencing `foo`:
|
||||||
|
|
||||||
|
|
@ -352,11 +351,11 @@ recognized fine::
|
||||||
(without parameter names, see form A.2 above).
|
(without parameter names, see form A.2 above).
|
||||||
E.g. for this signature:
|
E.g. for this signature:
|
||||||
|
|
||||||
.. code:: Nim
|
```Nim
|
||||||
|
|
||||||
proc binarySearch*[T, K](a: openArray[T]; key: K;
|
proc binarySearch*[T, K](a: openArray[T]; key: K;
|
||||||
cmp: proc (x: T; y: K): int {.closure.}): int
|
cmp: proc (x: T; y: K): int {.closure.}): int
|
||||||
~~ ~~ ~~~~~
|
~~ ~~ ~~~~~
|
||||||
|
```
|
||||||
|
|
||||||
you cannot use names underlined by `~~` so it must be referenced with
|
you cannot use names underlined by `~~` so it must be referenced with
|
||||||
``cmp: proc(T, K)``. Hence these forms are valid::
|
``cmp: proc(T, K)``. Hence these forms are valid::
|
||||||
|
|
@ -379,10 +378,10 @@ recognized fine::
|
||||||
.. Note:: A bit special case is operators
|
.. Note:: A bit special case is operators
|
||||||
(as their signature is also defined with `\``):
|
(as their signature is also defined with `\``):
|
||||||
|
|
||||||
.. code:: Nim
|
```Nim
|
||||||
|
|
||||||
func `$`(x: MyType): string
|
func `$`(x: MyType): string
|
||||||
func `[]`*[T](x: openArray[T]): T
|
func `[]`*[T](x: openArray[T]): T
|
||||||
|
```
|
||||||
|
|
||||||
A short form works without additional backticks::
|
A short form works without additional backticks::
|
||||||
|
|
||||||
|
|
@ -412,9 +411,9 @@ Related Options
|
||||||
Project switch
|
Project switch
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim doc --project filename.nim
|
nim doc --project filename.nim
|
||||||
|
```
|
||||||
|
|
||||||
This will recursively generate documentation of all Nim modules imported
|
This will recursively generate documentation of all Nim modules imported
|
||||||
into the input module that belong to the Nimble package that ``filename.nim``
|
into the input module that belong to the Nimble package that ``filename.nim``
|
||||||
|
|
@ -425,9 +424,9 @@ also be generated.
|
||||||
Index switch
|
Index switch
|
||||||
------------
|
------------
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim doc --index:on filename.nim
|
nim doc --index:on filename.nim
|
||||||
|
```
|
||||||
|
|
||||||
This will generate an index of all the exported symbols in the input Nim
|
This will generate an index of all the exported symbols in the input Nim
|
||||||
module, and put it into a neighboring file with the extension of ``.idx``. The
|
module, and put it into a neighboring file with the extension of ``.idx``. The
|
||||||
|
|
@ -443,9 +442,9 @@ file.
|
||||||
See source switch
|
See source switch
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim doc --git.url:<url> filename.nim
|
nim doc --git.url:<url> filename.nim
|
||||||
|
```
|
||||||
|
|
||||||
With the `git.url`:option: switch the *See source* hyperlink will appear below each
|
With the `git.url`:option: switch the *See source* hyperlink will appear below each
|
||||||
documented item in your source code pointing to the implementation of that
|
documented item in your source code pointing to the implementation of that
|
||||||
|
|
@ -490,9 +489,9 @@ supports highlighting of a few other languages supported by the
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
.. code:: cmd
|
```cmd
|
||||||
|
|
||||||
nim rst2html docgen.rst
|
nim rst2html docgen.rst
|
||||||
|
```
|
||||||
|
|
||||||
Output::
|
Output::
|
||||||
You're reading it!
|
You're reading it!
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
.. include:: rstcommon.rst
|
.. include:: rstcommon.rst
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
"Abstraction is layering ignorance on top of reality." -- Richard Gabriel
|
> "Abstraction is layering ignorance on top of reality." -- Richard Gabriel
|
||||||
|
|
||||||
|
|
||||||
Directory structure
|
Directory structure
|
||||||
|
|
@ -10,9 +10,9 @@ Nim Manual
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
|
|
||||||
"Complexity" seems to be a lot like "energy": you can transfer it from the
|
> "Complexity" seems to be a lot like "energy": you can transfer it from the
|
||||||
end-user to one/some of the other players, but the total amount seems to remain
|
> end-user to one/some of the other players, but the total amount seems to remain
|
||||||
pretty much constant for a given task. -- Ran
|
> pretty much constant for a given task. -- Ran
|
||||||
|
|
||||||
|
|
||||||
About this document
|
About this document
|
||||||
|
|
@ -4025,7 +4025,7 @@ In the standard library every name of a routine that returns a `var` type
|
||||||
starts with the prefix `m` per convention.
|
starts with the prefix `m` per convention.
|
||||||
|
|
||||||
|
|
||||||
.. include:: manual/var_t_return.rst
|
.. include:: manual/var_t_return.md
|
||||||
|
|
||||||
Future directions
|
Future directions
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -505,7 +505,7 @@ The compiler ensures that every code path initializes variables which contain
|
||||||
non-nilable pointers. The details of this analysis are still to be specified
|
non-nilable pointers. The details of this analysis are still to be specified
|
||||||
here.
|
here.
|
||||||
|
|
||||||
.. include:: manual_experimental_strictnotnil.rst
|
.. include:: manual_experimental_strictnotnil.md
|
||||||
|
|
||||||
|
|
||||||
Aliasing restrictions in parameter passing
|
Aliasing restrictions in parameter passing
|
||||||
|
|
@ -11,7 +11,7 @@ Nim's Memory Management
|
||||||
..
|
..
|
||||||
|
|
||||||
|
|
||||||
"The road to hell is paved with good intentions."
|
> "The road to hell is paved with good intentions."
|
||||||
|
|
||||||
|
|
||||||
Multi-paradigm Memory Management Strategies
|
Multi-paradigm Memory Management Strategies
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
||||||
"Look at you, hacker. A pathetic creature of meat and bone, panting and
|
> "Look at you, hacker. A pathetic creature of meat and bone, panting and
|
||||||
sweating as you run through my corridors. How can you challenge a perfect,
|
> sweating as you run through my corridors. How can you challenge a perfect,
|
||||||
immortal machine?"
|
> immortal machine?"
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
|
@ -54,7 +54,7 @@ All examples below use default PCRE Regex patterns:
|
||||||
nimgrep --excludeDir:'^\.git$' --excludeDir:'^\.hg$' --excludeDir:'^\.svn$'
|
nimgrep --excludeDir:'^\.git$' --excludeDir:'^\.hg$' --excludeDir:'^\.svn$'
|
||||||
# short: --ed:'^\.git$' --ed:'^\.hg$' --ed:'^\.svn$'
|
# short: --ed:'^\.git$' --ed:'^\.hg$' --ed:'^\.svn$'
|
||||||
|
|
||||||
+ To search only in paths containing the `tests` sub-directory recursively::
|
+ To search only in paths containing the `tests` sub-directory recursively:
|
||||||
|
|
||||||
.. code:: cmd
|
.. code:: cmd
|
||||||
nimgrep --recursive --includeDir:'(^|/)tests($|/)'
|
nimgrep --recursive --includeDir:'(^|/)tests($|/)'
|
||||||
|
|
@ -5,5 +5,5 @@ Nim Documentation Overview
|
||||||
:Author: Andreas Rumpf
|
:Author: Andreas Rumpf
|
||||||
:Version: |nimversion|
|
:Version: |nimversion|
|
||||||
|
|
||||||
.. include:: docs.rst
|
.. include:: docs.md
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ Nim Tutorial (Part II)
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
"Repetition renders the ridiculous reasonable." -- Norman Wildberger
|
> "Repetition renders the ridiculous reasonable." -- Norman Wildberger
|
||||||
|
|
||||||
This document is a tutorial for the advanced constructs of the *Nim*
|
This document is a tutorial for the advanced constructs of the *Nim*
|
||||||
programming language. **Note that this document is somewhat obsolete as the**
|
programming language. **Note that this document is somewhat obsolete as the**
|
||||||
|
|
@ -13,7 +13,7 @@ Nim Tutorial (Part III)
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
"With Great Power Comes Great Responsibility." -- Spider Man's Uncle
|
> "With Great Power Comes Great Responsibility." -- Spider Man's Uncle
|
||||||
|
|
||||||
This document is a tutorial about Nim's macro system.
|
This document is a tutorial about Nim's macro system.
|
||||||
A macro is a function that is executed at compile-time and transforms
|
A macro is a function that is executed at compile-time and transforms
|
||||||
|
|
@ -125,9 +125,7 @@ proc initGeneralTokenizer*(g: var GeneralTokenizer, buf: cstring) =
|
||||||
g.length = 0
|
g.length = 0
|
||||||
g.state = low(TokenClass)
|
g.state = low(TokenClass)
|
||||||
g.lang = low(SourceLanguage)
|
g.lang = low(SourceLanguage)
|
||||||
var pos = 0 # skip initial whitespace:
|
g.pos = 0
|
||||||
while g.buf[pos] in {' ', '\t'..'\r'}: inc(pos)
|
|
||||||
g.pos = pos
|
|
||||||
|
|
||||||
proc initGeneralTokenizer*(g: var GeneralTokenizer, buf: string) =
|
proc initGeneralTokenizer*(g: var GeneralTokenizer, buf: string) =
|
||||||
initGeneralTokenizer(g, cstring(buf))
|
initGeneralTokenizer(g, cstring(buf))
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,23 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
## ==================================
|
## ==================================
|
||||||
## rst
|
## packages/docutils/rst
|
||||||
## ==================================
|
## ==================================
|
||||||
##
|
##
|
||||||
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
## Nim-flavored reStructuredText and Markdown
|
## Nim-flavored reStructuredText and Markdown
|
||||||
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
##
|
##
|
||||||
## This module implements a `reStructuredText`:idx: (RST) parser.
|
## This module implements a `reStructuredText`:idx: (RST) and
|
||||||
|
## `Markdown`:idx: parser.
|
||||||
## A large subset is implemented with some limitations_ and
|
## A large subset is implemented with some limitations_ and
|
||||||
## `Nim-specific features`_.
|
## `Nim-specific features`_.
|
||||||
## A few `extra features`_ of the `Markdown`:idx: syntax are
|
## Both Markdown and RST are mark-up languages whose goal is to
|
||||||
## also supported.
|
## typeset texts with complex structure, formatting and references
|
||||||
|
## using simple plaintext representation.
|
||||||
##
|
##
|
||||||
## Nim can output the result to HTML [#html]_ or Latex [#latex]_.
|
## This module is also embedded into Nim compiler; the compiler can output
|
||||||
|
## the result to HTML [#html]_ or Latex [#latex]_.
|
||||||
##
|
##
|
||||||
## .. [#html] commands `nim doc`:cmd: for ``*.nim`` files and
|
## .. [#html] commands `nim doc`:cmd: for ``*.nim`` files and
|
||||||
## `nim rst2html`:cmd: for ``*.rst`` files
|
## `nim rst2html`:cmd: for ``*.rst`` files
|
||||||
|
|
@ -29,11 +32,13 @@
|
||||||
## .. [#latex] commands `nim doc2tex`:cmd: for ``*.nim`` and
|
## .. [#latex] commands `nim doc2tex`:cmd: for ``*.nim`` and
|
||||||
## `nim rst2tex`:cmd: for ``*.rst``.
|
## `nim rst2tex`:cmd: for ``*.rst``.
|
||||||
##
|
##
|
||||||
## If you are new to RST please consider reading the following:
|
## If you are new to Markdown/RST please consider reading the following:
|
||||||
##
|
##
|
||||||
## 1) a short `quick introduction`_
|
## 1) `Markdown Basic Syntax`_
|
||||||
## 2) an `RST reference`_: a comprehensive cheatsheet for RST
|
## 2) a long specification of Markdown: `CommonMark Spec`_
|
||||||
## 3) a more formal 50-page `RST specification`_.
|
## 3) a short `quick introduction`_ to RST
|
||||||
|
## 4) an `RST reference`_: a comprehensive cheatsheet for RST
|
||||||
|
## 5) a more formal 50-page `RST specification`_.
|
||||||
##
|
##
|
||||||
## Features
|
## Features
|
||||||
## --------
|
## --------
|
||||||
|
|
@ -120,7 +125,13 @@
|
||||||
##
|
##
|
||||||
## * emoji / smiley symbols
|
## * emoji / smiley symbols
|
||||||
## * Markdown tables
|
## * Markdown tables
|
||||||
## * Markdown code blocks
|
## * Markdown code blocks. For them the same additional arguments as for RST
|
||||||
|
## code blocks can be provided (e.g. `test` or `number-lines`) but with
|
||||||
|
## a one-line syntax like this::
|
||||||
|
##
|
||||||
|
## ```nim test number-lines=10
|
||||||
|
## echo "ok"
|
||||||
|
## ```
|
||||||
## * Markdown links
|
## * Markdown links
|
||||||
## * Markdown headlines
|
## * Markdown headlines
|
||||||
## * Markdown block quotes
|
## * Markdown block quotes
|
||||||
|
|
@ -211,6 +222,8 @@
|
||||||
## See `packages/docutils/rstgen module <rstgen.html>`_ to know how to
|
## See `packages/docutils/rstgen module <rstgen.html>`_ to know how to
|
||||||
## generate HTML or Latex strings to embed them into your documents.
|
## generate HTML or Latex strings to embed them into your documents.
|
||||||
##
|
##
|
||||||
|
## .. _Markdown Basic Syntax: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax
|
||||||
|
## .. _CommonMark Spec: https://spec.commonmark.org/0.30
|
||||||
## .. _quick introduction: https://docutils.sourceforge.io/docs/user/rst/quickstart.html
|
## .. _quick introduction: https://docutils.sourceforge.io/docs/user/rst/quickstart.html
|
||||||
## .. _RST reference: https://docutils.sourceforge.io/docs/user/rst/quickref.html
|
## .. _RST reference: https://docutils.sourceforge.io/docs/user/rst/quickref.html
|
||||||
## .. _RST specification: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html
|
## .. _RST specification: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html
|
||||||
|
|
@ -253,6 +266,7 @@ type
|
||||||
MsgKind* = enum ## the possible messages
|
MsgKind* = enum ## the possible messages
|
||||||
meCannotOpenFile = "cannot open '$1'",
|
meCannotOpenFile = "cannot open '$1'",
|
||||||
meExpected = "'$1' expected",
|
meExpected = "'$1' expected",
|
||||||
|
meMissingClosing = "$1",
|
||||||
meGridTableNotImplemented = "grid table is not implemented",
|
meGridTableNotImplemented = "grid table is not implemented",
|
||||||
meMarkdownIllformedTable = "illformed delimiter row of a Markdown table",
|
meMarkdownIllformedTable = "illformed delimiter row of a Markdown table",
|
||||||
meIllformedTable = "Illformed table: $1",
|
meIllformedTable = "Illformed table: $1",
|
||||||
|
|
@ -323,7 +337,10 @@ const
|
||||||
":geek:": "icon_e_geek",
|
":geek:": "icon_e_geek",
|
||||||
":ugeek:": "icon_e_ugeek"
|
":ugeek:": "icon_e_ugeek"
|
||||||
}
|
}
|
||||||
SandboxDirAllowlist = ["image", "code", "code-block"]
|
SandboxDirAllowlist = [
|
||||||
|
"image", "code", "code-block", "admonition", "attention", "caution",
|
||||||
|
"container", "contents", "danger", "default-role", "error", "figure",
|
||||||
|
"hint", "important", "index", "note", "role", "tip", "title", "warning"]
|
||||||
|
|
||||||
type
|
type
|
||||||
TokType = enum
|
TokType = enum
|
||||||
|
|
@ -1616,27 +1633,81 @@ proc parseUntil(p: var RstParser, father: PRstNode, postfix: string,
|
||||||
inc p.idx
|
inc p.idx
|
||||||
else: rstMessage(p, meExpected, postfix, line, col)
|
else: rstMessage(p, meExpected, postfix, line, col)
|
||||||
|
|
||||||
|
proc parseMarkdownCodeblockFields(p: var RstParser): PRstNode =
|
||||||
|
## Parses additional (after language string) code block parameters
|
||||||
|
## in a format *suggested* in the `CommonMark Spec`_ with handling of `"`.
|
||||||
|
if currentTok(p).kind == tkIndent:
|
||||||
|
result = nil
|
||||||
|
else:
|
||||||
|
result = newRstNode(rnFieldList)
|
||||||
|
while currentTok(p).kind != tkIndent:
|
||||||
|
if currentTok(p).kind == tkWhite:
|
||||||
|
inc p.idx
|
||||||
|
else:
|
||||||
|
let field = newRstNode(rnField)
|
||||||
|
var fieldName = ""
|
||||||
|
while currentTok(p).kind notin {tkWhite, tkIndent, tkEof} and
|
||||||
|
currentTok(p).symbol != "=":
|
||||||
|
fieldName.add currentTok(p).symbol
|
||||||
|
inc p.idx
|
||||||
|
field.add(newRstNode(rnFieldName, @[newLeaf(fieldName)]))
|
||||||
|
if currentTok(p).kind == tkWhite: inc p.idx
|
||||||
|
let fieldBody = newRstNode(rnFieldBody)
|
||||||
|
if currentTok(p).symbol == "=":
|
||||||
|
inc p.idx
|
||||||
|
if currentTok(p).kind == tkWhite: inc p.idx
|
||||||
|
var fieldValue = ""
|
||||||
|
if currentTok(p).symbol == "\"":
|
||||||
|
while true:
|
||||||
|
fieldValue.add currentTok(p).symbol
|
||||||
|
inc p.idx
|
||||||
|
if currentTok(p).kind == tkEof:
|
||||||
|
rstMessage(p, meExpected, "\"")
|
||||||
|
elif currentTok(p).symbol == "\"":
|
||||||
|
fieldValue.add "\""
|
||||||
|
inc p.idx
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
while currentTok(p).kind notin {tkWhite, tkIndent, tkEof}:
|
||||||
|
fieldValue.add currentTok(p).symbol
|
||||||
|
inc p.idx
|
||||||
|
fieldBody.add newLeaf(fieldValue)
|
||||||
|
field.add(fieldBody)
|
||||||
|
result.add(field)
|
||||||
|
|
||||||
proc parseMarkdownCodeblock(p: var RstParser): PRstNode =
|
proc parseMarkdownCodeblock(p: var RstParser): PRstNode =
|
||||||
result = newRstNodeA(p, rnCodeBlock)
|
result = newRstNodeA(p, rnCodeBlock)
|
||||||
|
let line = curLine(p)
|
||||||
|
let baseCol = currentTok(p).col
|
||||||
|
let baseSym = currentTok(p).symbol # usually just ```
|
||||||
|
inc p.idx
|
||||||
result.info = lineInfo(p)
|
result.info = lineInfo(p)
|
||||||
var args = newRstNode(rnDirArg)
|
var args = newRstNode(rnDirArg)
|
||||||
|
var fields: PRstNode = nil
|
||||||
if currentTok(p).kind == tkWord:
|
if currentTok(p).kind == tkWord:
|
||||||
args.add(newLeaf(p))
|
args.add(newLeaf(p))
|
||||||
inc p.idx
|
inc p.idx
|
||||||
|
fields = parseMarkdownCodeblockFields(p)
|
||||||
else:
|
else:
|
||||||
args = nil
|
args = nil
|
||||||
var n = newLeaf("")
|
var n = newLeaf("")
|
||||||
while true:
|
while true:
|
||||||
case currentTok(p).kind
|
if currentTok(p).kind == tkEof:
|
||||||
of tkEof:
|
rstMessage(p, meMissingClosing,
|
||||||
rstMessage(p, meExpected, "```")
|
"$1 (started at line $2)" % [baseSym, $line])
|
||||||
break
|
break
|
||||||
of tkPunct, tkAdornment:
|
elif nextTok(p).kind in {tkPunct, tkAdornment} and
|
||||||
if currentTok(p).symbol == "```":
|
nextTok(p).symbol[0] == baseSym[0] and
|
||||||
inc p.idx
|
nextTok(p).symbol.len >= baseSym.len:
|
||||||
|
inc p.idx, 2
|
||||||
break
|
break
|
||||||
else:
|
elif currentTok(p).kind == tkIndent:
|
||||||
n.text.add(currentTok(p).symbol)
|
n.text.add "\n"
|
||||||
|
if currentTok(p).ival > baseCol:
|
||||||
|
n.text.add " ".repeat(currentTok(p).ival - baseCol)
|
||||||
|
elif currentTok(p).ival < baseCol:
|
||||||
|
rstMessage(p, mwRstStyle,
|
||||||
|
"unexpected de-indentation in Markdown code block")
|
||||||
inc p.idx
|
inc p.idx
|
||||||
else:
|
else:
|
||||||
n.text.add(currentTok(p).symbol)
|
n.text.add(currentTok(p).symbol)
|
||||||
|
|
@ -1644,7 +1715,7 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode =
|
||||||
var lb = newRstNode(rnLiteralBlock)
|
var lb = newRstNode(rnLiteralBlock)
|
||||||
lb.add(n)
|
lb.add(n)
|
||||||
result.add(args)
|
result.add(args)
|
||||||
result.add(PRstNode(nil))
|
result.add(fields)
|
||||||
result.add(lb)
|
result.add(lb)
|
||||||
|
|
||||||
proc parseMarkdownLink(p: var RstParser; father: PRstNode): bool =
|
proc parseMarkdownLink(p: var RstParser; father: PRstNode): bool =
|
||||||
|
|
@ -1730,6 +1801,12 @@ proc parseFootnoteName(p: var RstParser, reference: bool): PRstNode =
|
||||||
inc i
|
inc i
|
||||||
p.idx = i
|
p.idx = i
|
||||||
|
|
||||||
|
proc isMarkdownCodeBlock(p: RstParser): bool =
|
||||||
|
result = (roSupportMarkdown in p.s.options and
|
||||||
|
currentTok(p).kind in {tkPunct, tkAdornment} and
|
||||||
|
currentTok(p).symbol[0] == '`' and # tilde ~ is not supported
|
||||||
|
currentTok(p).symbol.len >= 3)
|
||||||
|
|
||||||
proc parseInline(p: var RstParser, father: PRstNode) =
|
proc parseInline(p: var RstParser, father: PRstNode) =
|
||||||
var n: PRstNode # to be used in `if` condition
|
var n: PRstNode # to be used in `if` condition
|
||||||
let saveIdx = p.idx
|
let saveIdx = p.idx
|
||||||
|
|
@ -1755,8 +1832,7 @@ proc parseInline(p: var RstParser, father: PRstNode) =
|
||||||
addAnchorRst(p, name = linkName(n), refn = refn, reset = true,
|
addAnchorRst(p, name = linkName(n), refn = refn, reset = true,
|
||||||
anchorType=manualInlineAnchor)
|
anchorType=manualInlineAnchor)
|
||||||
father.add(n)
|
father.add(n)
|
||||||
elif roSupportMarkdown in p.s.options and currentTok(p).symbol == "```":
|
elif isMarkdownCodeBlock(p):
|
||||||
inc p.idx
|
|
||||||
father.add(parseMarkdownCodeblock(p))
|
father.add(parseMarkdownCodeblock(p))
|
||||||
elif isInlineMarkupStart(p, "``"):
|
elif isInlineMarkupStart(p, "``"):
|
||||||
var n = newRstNode(rnInlineLiteral)
|
var n = newRstNode(rnInlineLiteral)
|
||||||
|
|
@ -1816,8 +1892,7 @@ proc parseInline(p: var RstParser, father: PRstNode) =
|
||||||
return
|
return
|
||||||
parseWordOrRef(p, father)
|
parseWordOrRef(p, father)
|
||||||
of tkAdornment, tkOther, tkWhite:
|
of tkAdornment, tkOther, tkWhite:
|
||||||
if roSupportMarkdown in p.s.options and currentTok(p).symbol == "```":
|
if isMarkdownCodeBlock(p):
|
||||||
inc p.idx
|
|
||||||
father.add(parseMarkdownCodeblock(p))
|
father.add(parseMarkdownCodeblock(p))
|
||||||
return
|
return
|
||||||
if roSupportSmilies in p.s.options:
|
if roSupportSmilies in p.s.options:
|
||||||
|
|
@ -2194,7 +2269,7 @@ proc findPipe(p: RstParser, start: int): bool =
|
||||||
proc whichSection(p: RstParser): RstNodeKind =
|
proc whichSection(p: RstParser): RstNodeKind =
|
||||||
if currentTok(p).kind in {tkAdornment, tkPunct}:
|
if currentTok(p).kind in {tkAdornment, tkPunct}:
|
||||||
# for punctuation sequences that can be both tkAdornment and tkPunct
|
# for punctuation sequences that can be both tkAdornment and tkPunct
|
||||||
if roSupportMarkdown in p.s.options and currentTok(p).symbol == "```":
|
if isMarkdownCodeBlock(p):
|
||||||
return rnCodeBlock
|
return rnCodeBlock
|
||||||
elif currentTok(p).symbol == "::":
|
elif currentTok(p).symbol == "::":
|
||||||
return rnLiteralBlock
|
return rnLiteralBlock
|
||||||
|
|
@ -2633,7 +2708,9 @@ proc parseSimpleTable(p: var RstParser): PRstNode =
|
||||||
# fix rnTableDataCell -> rnTableHeaderCell for previous table rows:
|
# fix rnTableDataCell -> rnTableHeaderCell for previous table rows:
|
||||||
for nRow in 0 ..< result.sons.len:
|
for nRow in 0 ..< result.sons.len:
|
||||||
for nCell in 0 ..< result.sons[nRow].len:
|
for nCell in 0 ..< result.sons[nRow].len:
|
||||||
result.sons[nRow].sons[nCell].kind = rnTableHeaderCell
|
template cell: PRstNode = result.sons[nRow].sons[nCell]
|
||||||
|
cell = PRstNode(kind: rnTableHeaderCell, sons: cell.sons,
|
||||||
|
span: cell.span, anchor: cell.anchor)
|
||||||
if currentTok(p).kind == tkEof: break
|
if currentTok(p).kind == tkEof: break
|
||||||
let tabRow = parseSimpleTableRow(p, cols, colChar)
|
let tabRow = parseSimpleTableRow(p, cols, colChar)
|
||||||
result.add tabRow
|
result.add tabRow
|
||||||
|
|
@ -2892,6 +2969,14 @@ proc parseSection(p: var RstParser, result: PRstNode) =
|
||||||
if currInd(p) == currentTok(p).ival:
|
if currInd(p) == currentTok(p).ival:
|
||||||
inc p.idx
|
inc p.idx
|
||||||
elif currentTok(p).ival > currInd(p):
|
elif currentTok(p).ival > currInd(p):
|
||||||
|
if roPreferMarkdown in p.s.options: # Markdown => normal paragraphs
|
||||||
|
if currentTok(p).ival - currInd(p) >= 4:
|
||||||
|
rstMessage(p, mwRstStyle,
|
||||||
|
"Markdown indented code not implemented")
|
||||||
|
pushInd(p, currentTok(p).ival)
|
||||||
|
parseSection(p, result)
|
||||||
|
popInd(p)
|
||||||
|
else: # RST mode => block quotes
|
||||||
pushInd(p, currentTok(p).ival)
|
pushInd(p, currentTok(p).ival)
|
||||||
var a = newRstNodeA(p, rnBlockQuote)
|
var a = newRstNodeA(p, rnBlockQuote)
|
||||||
parseSection(p, a)
|
parseSection(p, a)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,12 @@ block: # Nim tokenizing
|
||||||
@[("\"\"\"ok1\\nok2\\nok3\"\"\"", gtLongStringLit)
|
@[("\"\"\"ok1\\nok2\\nok3\"\"\"", gtLongStringLit)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
test "whitespace at beginning of line is preserved":
|
||||||
|
check(" discard 1".tokenize(langNim) ==
|
||||||
|
@[(" ", gtWhitespace), ("discard", gtKeyword), (" ", gtWhitespace),
|
||||||
|
("1", gtDecNumber)
|
||||||
|
])
|
||||||
|
|
||||||
block: # Cmd (shell) tokenizing
|
block: # Cmd (shell) tokenizing
|
||||||
test "cmd with dollar and output":
|
test "cmd with dollar and output":
|
||||||
check(
|
check(
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,11 @@ import unittest, strutils
|
||||||
import std/private/miscdollars
|
import std/private/miscdollars
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
const preferMarkdown = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled}
|
||||||
|
const preferRst = {roSupportMarkdown, roNimFile, roSandboxDisabled}
|
||||||
|
|
||||||
proc toAst(input: string,
|
proc toAst(input: string,
|
||||||
rstOptions: RstParseOptions = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled},
|
rstOptions: RstParseOptions = preferMarkdown,
|
||||||
error: ref string = nil,
|
error: ref string = nil,
|
||||||
warnings: ref seq[string] = nil): string =
|
warnings: ref seq[string] = nil): string =
|
||||||
## If `error` is nil then no errors should be generated.
|
## If `error` is nil then no errors should be generated.
|
||||||
|
|
@ -451,7 +454,7 @@ suite "RST parsing":
|
||||||
> - y
|
> - y
|
||||||
>
|
>
|
||||||
> Paragraph.
|
> Paragraph.
|
||||||
""".toAst == dedent"""
|
""".toAst(rstOptions = preferRst) == dedent"""
|
||||||
rnMarkdownBlockQuote
|
rnMarkdownBlockQuote
|
||||||
rnMarkdownBlockQuoteItem quotationDepth=1
|
rnMarkdownBlockQuoteItem quotationDepth=1
|
||||||
rnInner
|
rnInner
|
||||||
|
|
@ -468,6 +471,93 @@ suite "RST parsing":
|
||||||
rnLeaf '.'
|
rnLeaf '.'
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
test "Markdown code blocks with more > 3 backticks":
|
||||||
|
check(dedent"""
|
||||||
|
````
|
||||||
|
let a = 1
|
||||||
|
```
|
||||||
|
````""".toAst ==
|
||||||
|
dedent"""
|
||||||
|
rnCodeBlock
|
||||||
|
[nil]
|
||||||
|
[nil]
|
||||||
|
rnLiteralBlock
|
||||||
|
rnLeaf '
|
||||||
|
let a = 1
|
||||||
|
```'
|
||||||
|
""")
|
||||||
|
|
||||||
|
test "Markdown code blocks with Nim-specific arguments":
|
||||||
|
check(dedent"""
|
||||||
|
```nim number-lines=1 test
|
||||||
|
let a = 1
|
||||||
|
```""".toAst ==
|
||||||
|
dedent"""
|
||||||
|
rnCodeBlock
|
||||||
|
rnDirArg
|
||||||
|
rnLeaf 'nim'
|
||||||
|
rnFieldList
|
||||||
|
rnField
|
||||||
|
rnFieldName
|
||||||
|
rnLeaf 'number-lines'
|
||||||
|
rnFieldBody
|
||||||
|
rnLeaf '1'
|
||||||
|
rnField
|
||||||
|
rnFieldName
|
||||||
|
rnLeaf 'test'
|
||||||
|
rnFieldBody
|
||||||
|
rnLiteralBlock
|
||||||
|
rnLeaf '
|
||||||
|
let a = 1'
|
||||||
|
""")
|
||||||
|
|
||||||
|
check(dedent"""
|
||||||
|
```nim test = "nim c $1" number-lines = 1
|
||||||
|
let a = 1
|
||||||
|
```""".toAst ==
|
||||||
|
dedent"""
|
||||||
|
rnCodeBlock
|
||||||
|
rnDirArg
|
||||||
|
rnLeaf 'nim'
|
||||||
|
rnFieldList
|
||||||
|
rnField
|
||||||
|
rnFieldName
|
||||||
|
rnLeaf 'test'
|
||||||
|
rnFieldBody
|
||||||
|
rnLeaf '"nim c $1"'
|
||||||
|
rnField
|
||||||
|
rnFieldName
|
||||||
|
rnLeaf 'number-lines'
|
||||||
|
rnFieldBody
|
||||||
|
rnLeaf '1'
|
||||||
|
rnLiteralBlock
|
||||||
|
rnLeaf '
|
||||||
|
let a = 1'
|
||||||
|
""")
|
||||||
|
|
||||||
|
test "additional indentation < 4 spaces is handled fine":
|
||||||
|
check(dedent"""
|
||||||
|
Indentation
|
||||||
|
|
||||||
|
```nim
|
||||||
|
let a = 1
|
||||||
|
```""".toAst ==
|
||||||
|
dedent"""
|
||||||
|
rnInner
|
||||||
|
rnParagraph
|
||||||
|
rnLeaf 'Indentation'
|
||||||
|
rnParagraph
|
||||||
|
rnCodeBlock
|
||||||
|
rnDirArg
|
||||||
|
rnLeaf 'nim'
|
||||||
|
[nil]
|
||||||
|
rnLiteralBlock
|
||||||
|
rnLeaf '
|
||||||
|
let a = 1'
|
||||||
|
""")
|
||||||
|
# | |
|
||||||
|
# | \ indentation of exactly two spaces before 'let a = 1'
|
||||||
|
|
||||||
test "option list has priority over definition list":
|
test "option list has priority over definition list":
|
||||||
check(dedent"""
|
check(dedent"""
|
||||||
--defusages
|
--defusages
|
||||||
|
|
@ -562,7 +652,7 @@ suite "RST parsing":
|
||||||
|
|
||||||
notAcomment1
|
notAcomment1
|
||||||
notAcomment2
|
notAcomment2
|
||||||
someParagraph""".toAst ==
|
someParagraph""".toAst(rstOptions = preferRst) ==
|
||||||
dedent"""
|
dedent"""
|
||||||
rnInner
|
rnInner
|
||||||
rnBlockQuote
|
rnBlockQuote
|
||||||
|
|
@ -574,6 +664,25 @@ suite "RST parsing":
|
||||||
rnLeaf 'someParagraph'
|
rnLeaf 'someParagraph'
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
test "check that additional line right after .. ends comment (Markdown mode)":
|
||||||
|
# in Markdown small indentation does not matter so this should
|
||||||
|
# just be split to 2 paragraphs.
|
||||||
|
check(dedent"""
|
||||||
|
..
|
||||||
|
|
||||||
|
notAcomment1
|
||||||
|
notAcomment2
|
||||||
|
someParagraph""".toAst ==
|
||||||
|
dedent"""
|
||||||
|
rnInner
|
||||||
|
rnInner
|
||||||
|
rnLeaf 'notAcomment1'
|
||||||
|
rnLeaf ' '
|
||||||
|
rnLeaf 'notAcomment2'
|
||||||
|
rnParagraph
|
||||||
|
rnLeaf 'someParagraph'
|
||||||
|
""")
|
||||||
|
|
||||||
test "but blank lines after 2nd non-empty line don't end the comment":
|
test "but blank lines after 2nd non-empty line don't end the comment":
|
||||||
check(dedent"""
|
check(dedent"""
|
||||||
..
|
..
|
||||||
|
|
@ -592,7 +701,7 @@ suite "RST parsing":
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
||||||
someBlockQuote""".toAst ==
|
someBlockQuote""".toAst(rstOptions = preferRst) ==
|
||||||
dedent"""
|
dedent"""
|
||||||
rnInner
|
rnInner
|
||||||
rnAdmonition adType=note
|
rnAdmonition adType=note
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,13 @@ import ../../lib/packages/docutils/rst
|
||||||
import unittest, strutils, strtabs
|
import unittest, strutils, strtabs
|
||||||
import std/private/miscdollars
|
import std/private/miscdollars
|
||||||
|
|
||||||
|
const
|
||||||
|
NoSandboxOpts = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled}
|
||||||
|
preferMarkdown = {roPreferMarkdown, roSupportMarkdown, roNimFile}
|
||||||
|
preferRst = {roSupportMarkdown, roNimFile}
|
||||||
|
|
||||||
proc toHtml(input: string,
|
proc toHtml(input: string,
|
||||||
rstOptions: RstParseOptions = {roPreferMarkdown, roSupportMarkdown, roNimFile},
|
rstOptions: RstParseOptions = preferMarkdown,
|
||||||
error: ref string = nil,
|
error: ref string = nil,
|
||||||
warnings: ref seq[string] = nil): string =
|
warnings: ref seq[string] = nil): string =
|
||||||
## If `error` is nil then no errors should be generated.
|
## If `error` is nil then no errors should be generated.
|
||||||
|
|
@ -47,9 +52,6 @@ proc optionListLabel(opt: string): string =
|
||||||
opt &
|
opt &
|
||||||
"</span></tt></div>"
|
"</span></tt></div>"
|
||||||
|
|
||||||
const
|
|
||||||
NoSandboxOpts = {roPreferMarkdown, roSupportMarkdown, roNimFile, roSandboxDisabled}
|
|
||||||
|
|
||||||
|
|
||||||
suite "YAML syntax highlighting":
|
suite "YAML syntax highlighting":
|
||||||
test "Basics":
|
test "Basics":
|
||||||
|
|
@ -1180,7 +1182,7 @@ Test1
|
||||||
"input(8, 4) Warning: language 'anotherLang' not supported"
|
"input(8, 4) Warning: language 'anotherLang' not supported"
|
||||||
])
|
])
|
||||||
check(output == "<pre class = \"listing\">anything</pre>" &
|
check(output == "<pre class = \"listing\">anything</pre>" &
|
||||||
"<p><pre class = \"listing\">\nsomeCode\n</pre> </p>")
|
"<p><pre class = \"listing\">\nsomeCode</pre> </p>")
|
||||||
|
|
||||||
test "RST admonitions":
|
test "RST admonitions":
|
||||||
# check that all admonitions are implemented
|
# check that all admonitions are implemented
|
||||||
|
|
@ -1321,7 +1323,7 @@ Test1
|
||||||
That was a transition.
|
That was a transition.
|
||||||
"""
|
"""
|
||||||
let output1 = input1.toHtml(
|
let output1 = input1.toHtml(
|
||||||
NoSandboxOpts
|
preferRst
|
||||||
)
|
)
|
||||||
doAssert "<p id=\"target000\"" in output1
|
doAssert "<p id=\"target000\"" in output1
|
||||||
doAssert "<ul id=\"target001\"" in output1
|
doAssert "<ul id=\"target001\"" in output1
|
||||||
|
|
@ -1543,7 +1545,7 @@ Test1
|
||||||
"""<td>text</td></tr>""" & "\n</tbody></table>")
|
"""<td>text</td></tr>""" & "\n</tbody></table>")
|
||||||
|
|
||||||
test "Field list: body after newline":
|
test "Field list: body after newline":
|
||||||
let output = dedent """
|
let output = dedent"""
|
||||||
:field:
|
:field:
|
||||||
text1""".toHtml
|
text1""".toHtml
|
||||||
check "<table class=\"docinfo\"" in output
|
check "<table class=\"docinfo\"" in output
|
||||||
|
|
|
||||||
|
|
@ -107,18 +107,18 @@ proc nimCompileFold*(desc, input: string, outputDir = "bin", mode = "c", options
|
||||||
let cmd = findNim().quoteShell() & " " & mode & " -o:" & output & " " & options & " " & input
|
let cmd = findNim().quoteShell() & " " & mode & " -o:" & output & " " & options & " " & input
|
||||||
execFold(desc, cmd)
|
execFold(desc, cmd)
|
||||||
|
|
||||||
proc getRst2html(): seq[string] =
|
proc getMd2html(): seq[string] =
|
||||||
for a in walkDirRecFilter("doc"):
|
for a in walkDirRecFilter("doc"):
|
||||||
let path = a.path
|
let path = a.path
|
||||||
if a.kind == pcFile and path.splitFile.ext == ".rst" and path.lastPathPart notin
|
if a.kind == pcFile and path.splitFile.ext == ".md" and path.lastPathPart notin
|
||||||
["docs.rst", "nimfix.rst",
|
["docs.md", "nimfix.md",
|
||||||
"docstyle.rst" # docstyle.rst shouldn't be converted to html separately;
|
"docstyle.md" # docstyle.md shouldn't be converted to html separately;
|
||||||
# it's included in contributing.rst.
|
# it's included in contributing.md.
|
||||||
]:
|
]:
|
||||||
# maybe we should still show nimfix, could help reviving it
|
# maybe we should still show nimfix, could help reviving it
|
||||||
# `docs` is redundant with `overview`, might as well remove that file?
|
# `docs` is redundant with `overview`, might as well remove that file?
|
||||||
result.add path
|
result.add path
|
||||||
doAssert "doc/manual/var_t_return.rst".unixToNativePath in result # sanity check
|
doAssert "doc/manual/var_t_return.md".unixToNativePath in result # sanity check
|
||||||
|
|
||||||
const
|
const
|
||||||
rstPdfList = """
|
rstPdfList = """
|
||||||
|
|
@ -253,13 +253,13 @@ proc buildDocPackages(nimArgs, destPath: string) =
|
||||||
|
|
||||||
proc buildDoc(nimArgs, destPath: string) =
|
proc buildDoc(nimArgs, destPath: string) =
|
||||||
# call nim for the documentation:
|
# call nim for the documentation:
|
||||||
let rst2html = getRst2html()
|
let rst2html = getMd2html()
|
||||||
var
|
var
|
||||||
commands = newSeq[string](rst2html.len + len(doc0) + len(doc) + withoutIndex.len)
|
commands = newSeq[string](rst2html.len + len(doc0) + len(doc) + withoutIndex.len)
|
||||||
i = 0
|
i = 0
|
||||||
let nim = findNim().quoteShell()
|
let nim = findNim().quoteShell()
|
||||||
for d in items(rst2html):
|
for d in items(rst2html):
|
||||||
commands[i] = nim & " rst2html $# --git.url:$# -o:$# --index:on $#" %
|
commands[i] = nim & " md2html $# --git.url:$# -o:$# --index:on $#" %
|
||||||
[nimArgs, gitUrl,
|
[nimArgs, gitUrl,
|
||||||
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
||||||
i.inc
|
i.inc
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue