merged better html links #850
This commit is contained in:
parent
831a8c8db4
commit
3e25d5f247
13 changed files with 559 additions and 56 deletions
|
|
@ -9,11 +9,14 @@
|
|||
|
||||
## This module implements a generator of HTML/Latex from
|
||||
## `reStructuredText`:idx: (see http://docutils.sourceforge.net/rst.html for
|
||||
## information on this markup syntax). You can generate HTML output through the
|
||||
## convenience proc ``rstToHtml``, which provided an input string with rst
|
||||
## markup returns a string with the generated HTML. The final output is meant
|
||||
## to be embedded inside a full document you provide yourself, so it won't
|
||||
## contain the usual ``<header>`` or ``<body>`` parts.
|
||||
## information on this markup syntax) and is used by the compiler's `docgen
|
||||
## tools <docgen.html>`_.
|
||||
##
|
||||
## You can generate HTML output through the convenience proc ``rstToHtml``,
|
||||
## which provided an input string with rst markup returns a string with the
|
||||
## generated HTML. The final output is meant to be embedded inside a full
|
||||
## document you provide yourself, so it won't contain the usual ``<header>`` or
|
||||
## ``<body>`` parts.
|
||||
##
|
||||
## You can also create a ``TRstGenerator`` structure and populate it with the
|
||||
## other lower level methods to finally build complete documents. This requires
|
||||
|
|
@ -50,6 +53,9 @@ type
|
|||
msgHandler*: TMsgHandler
|
||||
filename*: string
|
||||
meta*: array[TMetaEnum, string]
|
||||
currentSection: string ## \
|
||||
## Stores the empty string or the last headline/overline found in the rst
|
||||
## document, so it can be used as a prettier name for term index generation.
|
||||
|
||||
PDoc = var TRstGenerator ## Alias to type less.
|
||||
|
||||
|
|
@ -104,6 +110,7 @@ proc initRstGenerator*(g: var TRstGenerator, target: TOutputTarget,
|
|||
g.theIndex = ""
|
||||
g.options = options
|
||||
g.findFile = findFile
|
||||
g.currentSection = ""
|
||||
g.msgHandler = msgHandler
|
||||
|
||||
let s = config["split.item.toc"]
|
||||
|
|
@ -227,20 +234,44 @@ proc renderAux(d: PDoc, n: PRstNode, frmtA, frmtB: string, result: var string) =
|
|||
|
||||
# ---------------- index handling --------------------------------------------
|
||||
|
||||
proc setIndexTerm*(d: var TRstGenerator, id, term: string) =
|
||||
proc quoteIndexColumn(text: string): string =
|
||||
## Returns a safe version of `text` for serialization to the ``.idx`` file.
|
||||
##
|
||||
## The returned version can be put without worries in a line based tab
|
||||
## separated column text file. The following character sequence replacements
|
||||
## will be performed for that goal:
|
||||
##
|
||||
## * ``"\\"`` => ``"\\\\"``
|
||||
## * ``"\n"`` => ``"\\n"``
|
||||
## * ``"\t"`` => ``"\\t"``
|
||||
result = text.replace("\\", "\\\\").replace("\n", "\\n").replace("\t", "\\t")
|
||||
|
||||
proc unquoteIndexColumn(text: string): string =
|
||||
## Returns the unquoted version generated by ``quoteIndexColumn``.
|
||||
result = text.replace("\\t", "\t").replace("\\n", "\n").replace("\\\\", "\\")
|
||||
|
||||
proc setIndexTerm*(d: var TRstGenerator, id, term: string,
|
||||
linkTitle, linkDesc = "") =
|
||||
## Adds a `term` to the index using the specified hyperlink identifier.
|
||||
##
|
||||
## The ``d.theIndex`` string will be used to append the term in the format
|
||||
## ``term<tab>file#id``. The anchor will be the based on the name of the file
|
||||
## currently being parsed plus the `id`, which will be appended after a hash.
|
||||
## If `linkTitle` or `linkDesc` are not the empty string, two additional
|
||||
## columns with their contents will be added.
|
||||
##
|
||||
## The index won't be written to disk unless you call ``writeIndexFile``.
|
||||
## The index won't be written to disk unless you call ``writeIndexFile``. The
|
||||
## purpose of the index is documented in the `docgen tools guide
|
||||
## <docgen.html#index-switch>`_.
|
||||
d.theIndex.add(term)
|
||||
d.theIndex.add('\t')
|
||||
let htmlFile = changeFileExt(extractFilename(d.filename), HtmlExt)
|
||||
d.theIndex.add(htmlFile)
|
||||
d.theIndex.add('#')
|
||||
d.theIndex.add(id)
|
||||
if linkTitle.len > 0 or linkDesc.len > 0:
|
||||
d.theIndex.add('\t' & linkTitle.quoteIndexColumn)
|
||||
d.theIndex.add('\t' & linkDesc.quoteIndexColumn)
|
||||
d.theIndex.add("\n")
|
||||
|
||||
proc hash(n: PRstNode): int =
|
||||
|
|
@ -256,7 +287,7 @@ proc renderIndexTerm(d: PDoc, n: PRstNode, result: var string) =
|
|||
let id = rstnodeToRefname(n) & '_' & $abs(hash(n))
|
||||
var term = ""
|
||||
renderAux(d, n, term)
|
||||
setIndexTerm(d, id, term)
|
||||
setIndexTerm(d, id, term, d.currentSection)
|
||||
dispA(d.target, result, "<span id=\"$1\">$2</span>", "$2\\label{$1}",
|
||||
[id, term])
|
||||
|
||||
|
|
@ -264,13 +295,22 @@ type
|
|||
TIndexEntry {.pure, final.} = object
|
||||
keyword: string
|
||||
link: string
|
||||
linkTitle: string ## If not nil, contains a prettier text for the href
|
||||
linkDesc: string ## If not nil, the title attribute of the final href
|
||||
|
||||
proc cmp(a, b: TIndexEntry): int =
|
||||
## Sorts two ``TIndexEntry`` first by `keyword` field, then by `link`.
|
||||
result = cmpIgnoreStyle(a.keyword, b.keyword)
|
||||
if result == 0:
|
||||
result = cmpIgnoreStyle(a.link, b.link)
|
||||
|
||||
proc `<-`(a: var TIndexEntry, b: TIndexEntry) =
|
||||
shallowCopy a.keyword, b.keyword
|
||||
shallowCopy a.link, b.link
|
||||
if b.linkTitle.isNil: a.linkTitle = nil
|
||||
else: shallowCopy a.linkTitle, b.linkTitle
|
||||
if b.linkDesc.isNil: a.linkDesc = nil
|
||||
else: shallowCopy a.linkDesc, b.linkDesc
|
||||
|
||||
proc sortIndex(a: var openArray[TIndexEntry]) =
|
||||
# we use shellsort here; fast and simple
|
||||
|
|
@ -307,6 +347,15 @@ proc mergeIndexes*(dir: string): string =
|
|||
setLen(a, L+1)
|
||||
a[L].keyword = line.substr(0, s-1)
|
||||
a[L].link = line.substr(s+1)
|
||||
if a[L].link.find('\t') > 0:
|
||||
let extraCols = a[L].link.split('\t')
|
||||
a[L].link = extraCols[0]
|
||||
assert extraCols.len == 3
|
||||
a[L].linkTitle = extraCols[1].unquoteIndexColumn
|
||||
a[L].linkDesc = extraCols[2].unquoteIndexColumn
|
||||
else:
|
||||
a[L].linkTitle = nil
|
||||
a[L].linkDesc = nil
|
||||
inc L
|
||||
sortIndex(a)
|
||||
result = ""
|
||||
|
|
@ -316,9 +365,17 @@ proc mergeIndexes*(dir: string): string =
|
|||
[a[i].keyword])
|
||||
var j = i
|
||||
while j < L and a[i].keyword == a[j].keyword:
|
||||
result.addf(
|
||||
"<li><a class=\"reference external\" href=\"$1\">$1</a></li>\n",
|
||||
[a[j].link])
|
||||
let
|
||||
url = a[j].link
|
||||
text = if not a[j].linkTitle.isNil: a[j].linkTitle else: url
|
||||
desc = if not a[j].linkDesc.isNil: a[j].linkDesc else: ""
|
||||
if desc.len > 0:
|
||||
result.addf("""<li><a class="reference external"
|
||||
title="$3" href="$1">$2</a></li>
|
||||
""", [url, text, desc])
|
||||
else:
|
||||
result.addf("""<li><a class="reference external" href="$1">$2</a></li>
|
||||
""", [url, text])
|
||||
inc j
|
||||
result.add("</ul></dd>\n")
|
||||
i = j
|
||||
|
|
@ -328,6 +385,7 @@ proc mergeIndexes*(dir: string): string =
|
|||
proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
|
||||
var tmp = ""
|
||||
for i in countup(0, len(n) - 1): renderRstToOut(d, n.sons[i], tmp)
|
||||
d.currentSection = tmp
|
||||
var refname = rstnodeToRefname(n)
|
||||
if d.hasToc:
|
||||
var length = len(d.tocPart)
|
||||
|
|
@ -349,14 +407,17 @@ proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
|
|||
|
||||
proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
|
||||
if d.meta[metaTitle].len == 0:
|
||||
d.currentSection = d.meta[metaTitle]
|
||||
for i in countup(0, len(n)-1):
|
||||
renderRstToOut(d, n.sons[i], d.meta[metaTitle])
|
||||
elif d.meta[metaSubtitle].len == 0:
|
||||
d.currentSection = d.meta[metaSubtitle]
|
||||
for i in countup(0, len(n)-1):
|
||||
renderRstToOut(d, n.sons[i], d.meta[metaSubtitle])
|
||||
else:
|
||||
var tmp = ""
|
||||
for i in countup(0, len(n) - 1): renderRstToOut(d, n.sons[i], tmp)
|
||||
d.currentSection = tmp
|
||||
dispA(d.target, result, "<h$1 id=\"$2\"><center>$3</center></h$1>",
|
||||
"\\rstov$4{$3}\\label{$2}\n", [$n.level,
|
||||
rstnodeToRefname(n), tmp, $chr(n.level - 1 + ord('A'))])
|
||||
|
|
@ -716,6 +777,8 @@ proc defaultConfig*(): PStringTable =
|
|||
template setConfigVar(key, val: expr) =
|
||||
result[key] = val
|
||||
|
||||
# If you need to modify these values, it might be worth updating the template
|
||||
# file in config/nimdoc.cfg.
|
||||
setConfigVar("split.item.toc", "20")
|
||||
setConfigVar("doc.section", """
|
||||
<div class="section" id="$sectionID">
|
||||
|
|
@ -733,13 +796,14 @@ $content
|
|||
</li>
|
||||
""")
|
||||
setConfigVar("doc.item", """
|
||||
<dt id="$itemID"><pre>$header</pre></dt>
|
||||
<dt id="$itemID"><a name="$itemSymOrIDEnc"></a><pre>$header</pre></dt>
|
||||
<dd>
|
||||
$desc
|
||||
</dd>
|
||||
""")
|
||||
setConfigVar("doc.item.toc", """
|
||||
<li><a class="reference" href="#$itemID">$name</a></li>
|
||||
<li><a class="reference" href="#$itemSymOrIDEnc"
|
||||
title="$header_plain">$name</a></li>
|
||||
""")
|
||||
setConfigVar("doc.toc", """
|
||||
<div class="navigation" id="navigation">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue