RST: implement admonitions (#16438)
This commit is contained in:
parent
626c2bc658
commit
2bdc479622
6 changed files with 239 additions and 54 deletions
|
|
@ -52,6 +52,15 @@ doc.file = """
|
||||||
\usepackage{hyperref}
|
\usepackage{hyperref}
|
||||||
\usepackage{enumitem}
|
\usepackage{enumitem}
|
||||||
|
|
||||||
|
\usepackage{xcolor}
|
||||||
|
\usepackage[tikz]{mdframed}
|
||||||
|
\usetikzlibrary{shadows}
|
||||||
|
\mdfsetup{%
|
||||||
|
linewidth=3,
|
||||||
|
topline=false,
|
||||||
|
rightline=false,
|
||||||
|
bottomline=false}
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
\title{$title $version}
|
\title{$title $version}
|
||||||
\author{$author}
|
\author{$author}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ Modified by Boyd Greenfield and narimiran
|
||||||
--primary-background: #fff;
|
--primary-background: #fff;
|
||||||
--secondary-background: ghostwhite;
|
--secondary-background: ghostwhite;
|
||||||
--third-background: #e8e8e8;
|
--third-background: #e8e8e8;
|
||||||
|
--info-background: #50c050;
|
||||||
|
--warning-background: #c0a000;
|
||||||
|
--error-background: #e04040;
|
||||||
--border: #dde;
|
--border: #dde;
|
||||||
--text: #222;
|
--text: #222;
|
||||||
--anchor: #07b;
|
--anchor: #07b;
|
||||||
|
|
@ -39,6 +42,9 @@ Modified by Boyd Greenfield and narimiran
|
||||||
--primary-background: #171921;
|
--primary-background: #171921;
|
||||||
--secondary-background: #1e202a;
|
--secondary-background: #1e202a;
|
||||||
--third-background: #2b2e3b;
|
--third-background: #2b2e3b;
|
||||||
|
--info-background: #008000;
|
||||||
|
--warning-background: #807000;
|
||||||
|
--error-background: #c03000;
|
||||||
--border: #0e1014;
|
--border: #0e1014;
|
||||||
--text: #fff;
|
--text: #fff;
|
||||||
--anchor: #8be9fd;
|
--anchor: #8be9fd;
|
||||||
|
|
@ -609,6 +615,34 @@ table.borderless td, table.borderless th {
|
||||||
The right padding separates the table cells. */
|
The right padding separates the table cells. */
|
||||||
padding: 0 0.5em 0 0 !important; }
|
padding: 0 0.5em 0 0 !important; }
|
||||||
|
|
||||||
|
.admonition {
|
||||||
|
padding: 0.3em;
|
||||||
|
background-color: var(--secondary-background);
|
||||||
|
border-left: 0.4em solid #7f7f84;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
-webkit-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
|
||||||
|
-moz-box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
|
||||||
|
box-shadow: 0 5px 8px -6px rgba(0,0,0,.2);
|
||||||
|
}
|
||||||
|
.admonition-info {
|
||||||
|
border-color: var(--info-background);
|
||||||
|
}
|
||||||
|
.admonition-info-text {
|
||||||
|
color: var(--info-background);
|
||||||
|
}
|
||||||
|
.admonition-warning {
|
||||||
|
border-color: var(--warning-background);
|
||||||
|
}
|
||||||
|
.admonition-warning-text {
|
||||||
|
color: var(--warning-background);
|
||||||
|
}
|
||||||
|
.admonition-error {
|
||||||
|
border-color: var(--error-background);
|
||||||
|
}
|
||||||
|
.admonition-error-text {
|
||||||
|
color: var(--error-background);
|
||||||
|
}
|
||||||
|
|
||||||
.first {
|
.first {
|
||||||
/* Override more specific margin styles with "! important". */
|
/* Override more specific margin styles with "! important". */
|
||||||
margin-top: 0 !important; }
|
margin-top: 0 !important; }
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,18 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## This module implements a `reStructuredText`:idx: parser. A large
|
## This module implements a `reStructuredText`:idx: (RST) parser. A large
|
||||||
## subset is implemented. Some features of the `markdown`:idx: wiki syntax are
|
## subset is implemented. Some features of the `markdown`:idx: syntax are
|
||||||
## also supported.
|
## also supported. Nim can output the result to HTML (command ``rst2html``)
|
||||||
|
## or Latex (command ``rst2tex``).
|
||||||
##
|
##
|
||||||
## Supported RST features:
|
## If you are new to RST please consider reading the following:
|
||||||
|
##
|
||||||
|
## 1) a short `quick introduction`_
|
||||||
|
## 2) an `RST reference`_: a comprehensive cheatsheet for RST
|
||||||
|
## 3) a more formal 50-page `RST specification`_.
|
||||||
|
##
|
||||||
|
## Supported standard RST features:
|
||||||
##
|
##
|
||||||
## * body elements
|
## * body elements
|
||||||
## + sections
|
## + sections
|
||||||
|
|
@ -25,20 +32,29 @@
|
||||||
## + option lists
|
## + option lists
|
||||||
## + indented literal blocks
|
## + indented literal blocks
|
||||||
## + simple tables
|
## + simple tables
|
||||||
## + directives
|
## + directives (see official documentation in `RST directives list`_):
|
||||||
## - image, figure
|
## - ``image``, ``figure`` for including images and videos
|
||||||
## - code-block
|
## - ``code``
|
||||||
## - substitution definitions: replace and image
|
## - ``contents`` (table of contents), ``container``, ``raw``
|
||||||
## - ... a few more
|
## - ``include``
|
||||||
|
## - admonitions: "attention", "caution", "danger", "error", "hint",
|
||||||
|
## "important", "note", "tip", "warning", "admonition"
|
||||||
|
## - substitution definitions: `replace` and `image`
|
||||||
## + comments
|
## + comments
|
||||||
## * inline markup
|
## * inline markup
|
||||||
## + *emphasis*, **strong emphasis**, `interpreted text`,
|
## + *emphasis*, **strong emphasis**,
|
||||||
## ``inline literals``, hyperlink references, substitution references,
|
## ``inline literals``, hyperlink references, substitution references,
|
||||||
## standalone hyperlinks
|
## standalone hyperlinks
|
||||||
|
## + \`interpreted text\` with roles ``:literal:``, ``:strong:``,
|
||||||
|
## ``emphasis``, ``:sub:``/``:subscript:``, ``:sup:``/``:supscript:``
|
||||||
|
## (see `RST roles list`_ for description).
|
||||||
##
|
##
|
||||||
## Additional features:
|
## Additional features:
|
||||||
##
|
##
|
||||||
|
## * directives: ``code-block``, ``title``, ``index``
|
||||||
## * ***triple emphasis*** (bold and italic) using \*\*\*
|
## * ***triple emphasis*** (bold and italic) using \*\*\*
|
||||||
|
## * ``:idx:`` role for \`interpreted text\` to include the link to this
|
||||||
|
## text into an index (example: `Nim index`_).
|
||||||
##
|
##
|
||||||
## Optional additional features, turned on by ``options: RstParseOption`` in
|
## Optional additional features, turned on by ``options: RstParseOption`` in
|
||||||
## `rstParse proc <#rstParse,string,string,int,int,bool,RstParseOptions,FindFileHandler,MsgHandler>`_:
|
## `rstParse proc <#rstParse,string,string,int,int,bool,RstParseOptions,FindFileHandler,MsgHandler>`_:
|
||||||
|
|
@ -51,7 +67,11 @@
|
||||||
## * using ``1`` as auto-enumerator in enumerated lists like RST ``#``
|
## * using ``1`` as auto-enumerator in enumerated lists like RST ``#``
|
||||||
## (auto-enumerator ``1`` can not be used with ``#`` in the same list)
|
## (auto-enumerator ``1`` can not be used with ``#`` in the same list)
|
||||||
##
|
##
|
||||||
## **Note:** By default nim has ``roSupportMarkdown`` turned **on**.
|
## .. Note:: By default Nim has ``roSupportMarkdown`` and
|
||||||
|
## ``roSupportRawDirective`` turned **on**.
|
||||||
|
##
|
||||||
|
## .. warning:: Using Nim-specific features can cause other RST implementations
|
||||||
|
## to fail on your document.
|
||||||
##
|
##
|
||||||
## Limitations:
|
## Limitations:
|
||||||
##
|
##
|
||||||
|
|
@ -61,14 +81,32 @@
|
||||||
## - no quoted literal blocks
|
## - no quoted literal blocks
|
||||||
## - no doctest blocks
|
## - no doctest blocks
|
||||||
## - no grid tables
|
## - no grid tables
|
||||||
## - directives: no support for admonitions (notes, caution)
|
## - some directives are missing (check official `RST directives list`_):
|
||||||
|
## ``parsed-literal``, ``sidebar``, ``topic``, ``math``, ``rubric``,
|
||||||
|
## ``epigraph``, ``highlights``, ``pull-quote``, ``compound``,
|
||||||
|
## ``table``, ``csv-table``, ``list-table``, ``section-numbering``,
|
||||||
|
## ``header``, ``footer``, ``meta``, ``class``
|
||||||
|
## - no ``role`` directives and no custom interpreted text roles
|
||||||
|
## - some standard roles are not supported (check `RST roles list`_)
|
||||||
## - no footnotes & citations support
|
## - no footnotes & citations support
|
||||||
## - no inline internal targets
|
## - no inline internal targets
|
||||||
## * inline markup
|
## * inline markup
|
||||||
## - no simple-inline-markup
|
## - no simple-inline-markup
|
||||||
## - no embedded URI and aliases
|
## - no embedded URI and aliases
|
||||||
##
|
##
|
||||||
## **Note:** Import ``packages/docutils/rst`` to use this module
|
## .. _quick introduction: https://docutils.sourceforge.io/docs/user/rst/quickstart.html
|
||||||
|
## .. _RST reference: https://docutils.sourceforge.io/docs/user/rst/quickref.html
|
||||||
|
## .. _RST specification: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html
|
||||||
|
## .. _RST directives list: https://docutils.sourceforge.io/docs/ref/rst/directives.html
|
||||||
|
## .. _RST roles list: https://docutils.sourceforge.io/docs/ref/rst/roles.html
|
||||||
|
## .. _Nim index: https://nim-lang.org/docs/theindex.html
|
||||||
|
##
|
||||||
|
## See `Nim DocGen Tools Guide <docgen.html>`_ for the details about
|
||||||
|
## ``nim doc``, ``nim rst2html`` and ``nim rst2tex`` commands.
|
||||||
|
##
|
||||||
|
## .. note:: Import ``packages/docutils/rst`` to use this module.
|
||||||
|
##
|
||||||
|
## See also `packages/docutils/rstgen module <rstgen.html>`_.
|
||||||
|
|
||||||
import
|
import
|
||||||
os, strutils, rstast
|
os, strutils, rstast
|
||||||
|
|
@ -947,6 +985,7 @@ proc getDirective(p: var RstParser): string =
|
||||||
result = "" # error
|
result = "" # error
|
||||||
else:
|
else:
|
||||||
result = ""
|
result = ""
|
||||||
|
result = result.toLowerAscii()
|
||||||
|
|
||||||
proc parseComment(p: var RstParser): PRstNode =
|
proc parseComment(p: var RstParser): PRstNode =
|
||||||
case currentTok(p).kind
|
case currentTok(p).kind
|
||||||
|
|
@ -968,21 +1007,6 @@ proc parseComment(p: var RstParser): PRstNode =
|
||||||
while currentTok(p).kind notin {tkIndent, tkEof}: inc p.idx
|
while currentTok(p).kind notin {tkIndent, tkEof}: inc p.idx
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
type
|
|
||||||
DirKind = enum # must be ordered alphabetically!
|
|
||||||
dkNone, dkAuthor, dkAuthors, dkCode, dkCodeBlock, dkContainer, dkContents,
|
|
||||||
dkFigure, dkImage, dkInclude, dkIndex, dkRaw, dkTitle
|
|
||||||
|
|
||||||
const
|
|
||||||
DirIds: array[0..12, string] = ["", "author", "authors", "code",
|
|
||||||
"code-block", "container", "contents", "figure", "image", "include",
|
|
||||||
"index", "raw", "title"]
|
|
||||||
|
|
||||||
proc getDirKind(s: string): DirKind =
|
|
||||||
let i = find(DirIds, s)
|
|
||||||
if i >= 0: result = DirKind(i)
|
|
||||||
else: result = dkNone
|
|
||||||
|
|
||||||
proc parseLine(p: var RstParser, father: PRstNode) =
|
proc parseLine(p: var RstParser, father: PRstNode) =
|
||||||
while true:
|
while true:
|
||||||
case currentTok(p).kind
|
case currentTok(p).kind
|
||||||
|
|
@ -1191,7 +1215,8 @@ proc whichSection(p: RstParser): RstNodeKind =
|
||||||
result = rnMarkdownTable
|
result = rnMarkdownTable
|
||||||
elif currentTok(p).symbol == "|" and isLineBlock(p):
|
elif currentTok(p).symbol == "|" and isLineBlock(p):
|
||||||
result = rnLineBlock
|
result = rnLineBlock
|
||||||
elif match(p, tokenAfterNewline(p), "ai"):
|
elif match(p, tokenAfterNewline(p), "ai") and
|
||||||
|
isAdornmentHeadline(p, tokenAfterNewline(p)):
|
||||||
result = rnHeadline
|
result = rnHeadline
|
||||||
elif predNL(p) and
|
elif predNL(p) and
|
||||||
currentTok(p).symbol in ["+", "*", "-"] and nextTok(p).kind == tkWhite:
|
currentTok(p).symbol in ["+", "*", "-"] and nextTok(p).kind == tkWhite:
|
||||||
|
|
@ -1664,8 +1689,8 @@ proc parseDirective(p: var RstParser, flags: DirFlags): PRstNode =
|
||||||
## Parses arguments and options for a directive block.
|
## Parses arguments and options for a directive block.
|
||||||
##
|
##
|
||||||
## A directive block will always have three sons: the arguments for the
|
## A directive block will always have three sons: the arguments for the
|
||||||
## directive (rnDirArg), the options (rnFieldList) and the block
|
## directive (rnDirArg), the options (rnFieldList) and the directive
|
||||||
## (rnLineBlock). This proc parses the two first nodes, the block is left to
|
## content block. This proc parses the two first nodes, the 3rd is left to
|
||||||
## the outer `parseDirective` call.
|
## the outer `parseDirective` call.
|
||||||
##
|
##
|
||||||
## Both rnDirArg and rnFieldList children nodes might be nil, so you need to
|
## Both rnDirArg and rnFieldList children nodes might be nil, so you need to
|
||||||
|
|
@ -1703,12 +1728,20 @@ proc indFollows(p: RstParser): bool =
|
||||||
|
|
||||||
proc parseDirective(p: var RstParser, flags: DirFlags,
|
proc parseDirective(p: var RstParser, flags: DirFlags,
|
||||||
contentParser: SectionParser): PRstNode =
|
contentParser: SectionParser): PRstNode =
|
||||||
## Returns a generic rnDirective tree.
|
## A helper proc that does main work for specific directive procs.
|
||||||
|
## Always returns a generic rnDirective tree with these 3 children:
|
||||||
##
|
##
|
||||||
## The children are rnDirArg, rnFieldList and rnLineBlock. Any might be nil.
|
## 1) rnDirArg
|
||||||
|
## 2) rnFieldList
|
||||||
|
## 3) a node returned by `contentParser`.
|
||||||
|
##
|
||||||
|
## .. warning:: Any of the 3 children may be nil.
|
||||||
result = parseDirective(p, flags)
|
result = parseDirective(p, flags)
|
||||||
if not isNil(contentParser) and indFollows(p):
|
if not isNil(contentParser):
|
||||||
pushInd(p, currentTok(p).ival)
|
var nextIndent = p.tok[tokenAfterNewline(p)-1].ival
|
||||||
|
if nextIndent <= currInd(p): # parse only this line
|
||||||
|
nextIndent = currentTok(p).col
|
||||||
|
pushInd(p, nextIndent)
|
||||||
var content = contentParser(p)
|
var content = contentParser(p)
|
||||||
popInd(p)
|
popInd(p)
|
||||||
result.add(content)
|
result.add(content)
|
||||||
|
|
@ -1814,7 +1847,7 @@ proc dirCodeBlock(p: var RstParser, nimExtension = false): PRstNode =
|
||||||
n.add(newRstNode(rnLeaf, readFile(path)))
|
n.add(newRstNode(rnLeaf, readFile(path)))
|
||||||
result.sons[2] = n
|
result.sons[2] = n
|
||||||
|
|
||||||
# Extend the field block if we are using our custom extension.
|
# Extend the field block if we are using our custom Nim extension.
|
||||||
if nimExtension:
|
if nimExtension:
|
||||||
# Create a field block if the input block didn't have any.
|
# Create a field block if the input block didn't have any.
|
||||||
if result.sons[1].isNil: result.sons[1] = newRstNode(rnFieldList)
|
if result.sons[1].isNil: result.sons[1] = newRstNode(rnFieldList)
|
||||||
|
|
@ -1856,6 +1889,11 @@ proc dirIndex(p: var RstParser): PRstNode =
|
||||||
result = parseDirective(p, {}, parseSectionWrapper)
|
result = parseDirective(p, {}, parseSectionWrapper)
|
||||||
result.kind = rnIndex
|
result.kind = rnIndex
|
||||||
|
|
||||||
|
proc dirAdmonition(p: var RstParser, d: string): PRstNode =
|
||||||
|
result = parseDirective(p, {}, parseSectionWrapper)
|
||||||
|
result.kind = rnAdmonition
|
||||||
|
result.text = d
|
||||||
|
|
||||||
proc dirRawAux(p: var RstParser, result: var PRstNode, kind: RstNodeKind,
|
proc dirRawAux(p: var RstParser, result: var PRstNode, kind: RstNodeKind,
|
||||||
contentParser: SectionParser) =
|
contentParser: SectionParser) =
|
||||||
var filename = getFieldValue(result, "file")
|
var filename = getFieldValue(result, "file")
|
||||||
|
|
@ -1891,29 +1929,42 @@ proc dirRaw(p: var RstParser): PRstNode =
|
||||||
else:
|
else:
|
||||||
dirRawAux(p, result, rnRaw, parseSectionWrapper)
|
dirRawAux(p, result, rnRaw, parseSectionWrapper)
|
||||||
|
|
||||||
|
proc selectDir(p: var RstParser, d: string): PRstNode =
|
||||||
|
result = nil
|
||||||
|
case d
|
||||||
|
of "admonition", "attention", "caution": result = dirAdmonition(p, d)
|
||||||
|
of "code": result = dirCodeBlock(p)
|
||||||
|
of "code-block": result = dirCodeBlock(p, nimExtension = true)
|
||||||
|
of "container": result = dirContainer(p)
|
||||||
|
of "contents": result = dirContents(p)
|
||||||
|
of "danger", "error": result = dirAdmonition(p, d)
|
||||||
|
of "figure": result = dirFigure(p)
|
||||||
|
of "hint": result = dirAdmonition(p, d)
|
||||||
|
of "image": result = dirImage(p)
|
||||||
|
of "important": result = dirAdmonition(p, d)
|
||||||
|
of "include": result = dirInclude(p)
|
||||||
|
of "index": result = dirIndex(p)
|
||||||
|
of "note": result = dirAdmonition(p, d)
|
||||||
|
of "raw":
|
||||||
|
if roSupportRawDirective in p.s.options:
|
||||||
|
result = dirRaw(p)
|
||||||
|
else:
|
||||||
|
rstMessage(p, meInvalidDirective, d)
|
||||||
|
of "tip": result = dirAdmonition(p, d)
|
||||||
|
of "title": result = dirTitle(p)
|
||||||
|
of "warning": result = dirAdmonition(p, d)
|
||||||
|
else:
|
||||||
|
rstMessage(p, meInvalidDirective, d)
|
||||||
|
|
||||||
proc parseDotDot(p: var RstParser): PRstNode =
|
proc parseDotDot(p: var RstParser): PRstNode =
|
||||||
|
# parse "explicit markup blocks"
|
||||||
result = nil
|
result = nil
|
||||||
var col = currentTok(p).col
|
var col = currentTok(p).col
|
||||||
inc p.idx
|
inc p.idx
|
||||||
var d = getDirective(p)
|
var d = getDirective(p)
|
||||||
if d != "":
|
if d != "":
|
||||||
pushInd(p, col)
|
pushInd(p, col)
|
||||||
case getDirKind(d)
|
result = selectDir(p, d)
|
||||||
of dkInclude: result = dirInclude(p)
|
|
||||||
of dkImage: result = dirImage(p)
|
|
||||||
of dkFigure: result = dirFigure(p)
|
|
||||||
of dkTitle: result = dirTitle(p)
|
|
||||||
of dkContainer: result = dirContainer(p)
|
|
||||||
of dkContents: result = dirContents(p)
|
|
||||||
of dkRaw:
|
|
||||||
if roSupportRawDirective in p.s.options:
|
|
||||||
result = dirRaw(p)
|
|
||||||
else:
|
|
||||||
rstMessage(p, meInvalidDirective, d)
|
|
||||||
of dkCode: result = dirCodeBlock(p)
|
|
||||||
of dkCodeBlock: result = dirCodeBlock(p, nimExtension = true)
|
|
||||||
of dkIndex: result = dirIndex(p)
|
|
||||||
else: rstMessage(p, meInvalidDirective, d)
|
|
||||||
popInd(p)
|
popInd(p)
|
||||||
elif match(p, p.idx, " _"):
|
elif match(p, p.idx, " _"):
|
||||||
# hyperlink target:
|
# hyperlink target:
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,11 @@ type
|
||||||
rnLabel, # used for footnotes and other things
|
rnLabel, # used for footnotes and other things
|
||||||
rnFootnote, # a footnote
|
rnFootnote, # a footnote
|
||||||
rnCitation, # similar to footnote
|
rnCitation, # similar to footnote
|
||||||
rnStandaloneHyperlink, rnHyperlink, rnRef, rnDirective, # a directive
|
rnStandaloneHyperlink, rnHyperlink, rnRef,
|
||||||
rnDirArg, rnRaw, rnTitle, rnContents, rnImage, rnFigure, rnCodeBlock,
|
rnDirective, # a general directive
|
||||||
|
rnDirArg, # a directive argument (for some directives).
|
||||||
|
# here are directives that are not rnDirective:
|
||||||
|
rnRaw, rnTitle, rnContents, rnImage, rnFigure, rnCodeBlock, rnAdmonition,
|
||||||
rnRawHtml, rnRawLatex,
|
rnRawHtml, rnRawLatex,
|
||||||
rnContainer, # ``container`` directive
|
rnContainer, # ``container`` directive
|
||||||
rnIndex, # index directve:
|
rnIndex, # index directve:
|
||||||
|
|
@ -70,6 +73,7 @@ type
|
||||||
kind*: RstNodeKind ## the node's kind
|
kind*: RstNodeKind ## the node's kind
|
||||||
text*: string ## valid for leafs in the AST; and the title of
|
text*: string ## valid for leafs in the AST; and the title of
|
||||||
## the document or the section; and rnEnumList
|
## the document or the section; and rnEnumList
|
||||||
|
## and rnAdmonition
|
||||||
level*: int ## valid for some node kinds
|
level*: int ## valid for some node kinds
|
||||||
sons*: RstNodeSeq ## the node's sons
|
sons*: RstNodeSeq ## the node's sons
|
||||||
|
|
||||||
|
|
@ -316,3 +320,17 @@ proc renderRstToJson*(node: PRstNode): string =
|
||||||
## "sons":optional node array
|
## "sons":optional node array
|
||||||
## }
|
## }
|
||||||
renderRstToJsonNode(node).pretty
|
renderRstToJsonNode(node).pretty
|
||||||
|
|
||||||
|
proc renderRstToStr*(node: PRstNode, indent=0): string =
|
||||||
|
## Writes the parsed RST `node` into a compact string
|
||||||
|
## representation in the format (one line per every sub-node):
|
||||||
|
## ``indent - kind - text - level (if non-zero)``
|
||||||
|
## (suitable for debugging of RST parsing).
|
||||||
|
if node == nil:
|
||||||
|
result.add " ".repeat(indent) & "[nil]\n"
|
||||||
|
return
|
||||||
|
result.add " ".repeat(indent) & $node.kind & "\t" &
|
||||||
|
(if node.text == "": "" else: "'" & node.text & "'") &
|
||||||
|
(if node.level == 0: "" else: "\tlevel=" & $node.level) & "\n"
|
||||||
|
for son in node.sons:
|
||||||
|
result.add renderRstToStr(son, indent=indent+2)
|
||||||
|
|
|
||||||
|
|
@ -1079,6 +1079,29 @@ proc renderEnumList(d: PDoc, n: PRstNode, result: var string) =
|
||||||
"\\begin{enumerate}" & specifier & "$1\\end{enumerate}\n",
|
"\\begin{enumerate}" & specifier & "$1\\end{enumerate}\n",
|
||||||
result)
|
result)
|
||||||
|
|
||||||
|
proc renderAdmonition(d: PDoc, n: PRstNode, result: var string) =
|
||||||
|
var
|
||||||
|
htmlCls = "admonition_warning"
|
||||||
|
texSz = "\\large"
|
||||||
|
texColor = "orange"
|
||||||
|
case n.text
|
||||||
|
of "hint", "note", "tip":
|
||||||
|
htmlCls = "admonition-info"; texSz = "\\normalsize"; texColor = "green"
|
||||||
|
of "attention", "admonition", "important", "warning":
|
||||||
|
htmlCls = "admonition-warning"; texSz = "\\large"; texColor = "orange"
|
||||||
|
of "danger", "error":
|
||||||
|
htmlCls = "admonition-error"; texSz = "\\Large"; texColor = "red"
|
||||||
|
else: discard
|
||||||
|
let txt = n.text.capitalizeAscii()
|
||||||
|
let htmlHead = "<div class=\"admonition " & htmlCls & "\">"
|
||||||
|
renderAux(d, n,
|
||||||
|
htmlHead & "<span class=\"" & htmlCls & "-text\"><b>" & txt &
|
||||||
|
":</b></span>\n" & "$1</div>\n",
|
||||||
|
"\n\n\\begin{mdframed}[linecolor=" & texColor & "]\n" &
|
||||||
|
"{" & texSz & "\\color{" & texColor & "}{\\textbf{" & txt & ":}}} " &
|
||||||
|
"$1\n\\end{mdframed}\n",
|
||||||
|
result)
|
||||||
|
|
||||||
proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
|
proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -1143,6 +1166,7 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
|
||||||
of rnBlockQuote:
|
of rnBlockQuote:
|
||||||
renderAux(d, n, "<blockquote><p>$1</p></blockquote>\n",
|
renderAux(d, n, "<blockquote><p>$1</p></blockquote>\n",
|
||||||
"\\begin{quote}$1\\end{quote}\n", result)
|
"\\begin{quote}$1\\end{quote}\n", result)
|
||||||
|
of rnAdmonition: renderAdmonition(d, n, result)
|
||||||
of rnTable, rnGridTable, rnMarkdownTable:
|
of rnTable, rnGridTable, rnMarkdownTable:
|
||||||
renderAux(d, n,
|
renderAux(d, n,
|
||||||
"<table border=\"1\" class=\"docutils\">$1</table>",
|
"<table border=\"1\" class=\"docutils\">$1</table>",
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,55 @@ Test1
|
||||||
assert count(output1, "<ul ") == 1
|
assert count(output1, "<ul ") == 1
|
||||||
assert count(output1, "</ul>") == 1
|
assert count(output1, "</ul>") == 1
|
||||||
|
|
||||||
|
test "RST admonitions":
|
||||||
|
# check that all admonitions are implemented
|
||||||
|
let input0 = dedent """
|
||||||
|
.. admonition:: endOf admonition
|
||||||
|
.. attention:: endOf attention
|
||||||
|
.. caution:: endOf caution
|
||||||
|
.. danger:: endOf danger
|
||||||
|
.. error:: endOf error
|
||||||
|
.. hint:: endOf hint
|
||||||
|
.. important:: endOf important
|
||||||
|
.. note:: endOf note
|
||||||
|
.. tip:: endOf tip
|
||||||
|
.. warning:: endOf warning
|
||||||
|
"""
|
||||||
|
let output0 = rstToHtml(input0, {roSupportMarkdown}, defaultConfig())
|
||||||
|
for a in ["admonition", "attention", "caution", "danger", "error", "hint",
|
||||||
|
"important", "note", "tip", "warning" ]:
|
||||||
|
assert "endOf " & a & "</div>" in output0
|
||||||
|
|
||||||
|
# Test that admonition does not swallow up the next paragraph.
|
||||||
|
let input1 = dedent """
|
||||||
|
.. error:: endOfError
|
||||||
|
|
||||||
|
Test paragraph.
|
||||||
|
"""
|
||||||
|
let output1 = rstToHtml(input1, {roSupportMarkdown}, defaultConfig())
|
||||||
|
assert "endOfError</div>" in output1
|
||||||
|
assert "<p>Test paragraph. </p>" in output1
|
||||||
|
assert "class=\"admonition admonition-error\"" in output1
|
||||||
|
|
||||||
|
# Test that second line is parsed as continuation of the first line.
|
||||||
|
let input2 = dedent """
|
||||||
|
.. error:: endOfError
|
||||||
|
Test2p.
|
||||||
|
|
||||||
|
Test paragraph.
|
||||||
|
"""
|
||||||
|
let output2 = rstToHtml(input2, {roSupportMarkdown}, defaultConfig())
|
||||||
|
assert "endOfError Test2p.</div>" in output2
|
||||||
|
assert "<p>Test paragraph. </p>" in output2
|
||||||
|
assert "class=\"admonition admonition-error\"" in output2
|
||||||
|
|
||||||
|
let input3 = dedent """
|
||||||
|
.. note:: endOfNote
|
||||||
|
"""
|
||||||
|
let output3 = rstToHtml(input3, {roSupportMarkdown}, defaultConfig())
|
||||||
|
assert "endOfNote</div>" in output3
|
||||||
|
assert "class=\"admonition admonition-info\"" in output3
|
||||||
|
|
||||||
suite "RST/Code highlight":
|
suite "RST/Code highlight":
|
||||||
test "Basic Python code highlight":
|
test "Basic Python code highlight":
|
||||||
let pythonCode = """
|
let pythonCode = """
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue