html: Add support for #+TOC keyword
org mode allows rendering the toc anywhere in the html document using the `TOC` keyword [1]. There's more options but `#+TOC: headlines $n` should be enough for starters. Note that org mode still requires setting `#+OPTIONS: toc:nil` to disable the default toc [1] https://orgmode.org/manual/Table-of-Contents.html
This commit is contained in:
parent
bf7f957af2
commit
7c239a7aeb
4 changed files with 63 additions and 6 deletions
|
@ -55,6 +55,7 @@ var listItemStatuses = map[string]string{
|
||||||
}
|
}
|
||||||
|
|
||||||
var cleanHeadlineTitleForHTMLAnchorRegexp = regexp.MustCompile(`</?a[^>]*>`) // nested a tags are not valid HTML
|
var cleanHeadlineTitleForHTMLAnchorRegexp = regexp.MustCompile(`</?a[^>]*>`) // nested a tags are not valid HTML
|
||||||
|
var tocHeadlineMaxLvlRegexp = regexp.MustCompile(`headlines\s+(\d+)`)
|
||||||
|
|
||||||
func NewHTMLWriter() *HTMLWriter {
|
func NewHTMLWriter() *HTMLWriter {
|
||||||
defaultConfig := New()
|
defaultConfig := New()
|
||||||
|
@ -100,7 +101,10 @@ func (w *HTMLWriter) Before(d *Document) {
|
||||||
}
|
}
|
||||||
w.WriteString(fmt.Sprintf(`<h1 class="title">%s</h1>`+"\n", title))
|
w.WriteString(fmt.Sprintf(`<h1 class="title">%s</h1>`+"\n", title))
|
||||||
}
|
}
|
||||||
w.WriteOutline(d)
|
if w.document.GetOption("toc") != "nil" {
|
||||||
|
maxLvl, _ := strconv.Atoi(w.document.GetOption("toc"))
|
||||||
|
w.WriteOutline(d, maxLvl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) After(d *Document) {
|
func (w *HTMLWriter) After(d *Document) {
|
||||||
|
@ -168,6 +172,11 @@ func (w *HTMLWriter) WriteDrawer(d Drawer) {
|
||||||
func (w *HTMLWriter) WriteKeyword(k Keyword) {
|
func (w *HTMLWriter) WriteKeyword(k Keyword) {
|
||||||
if k.Key == "HTML" {
|
if k.Key == "HTML" {
|
||||||
w.WriteString(k.Value + "\n")
|
w.WriteString(k.Value + "\n")
|
||||||
|
} else if k.Key == "TOC" {
|
||||||
|
if m := tocHeadlineMaxLvlRegexp.FindStringSubmatch(k.Value); m != nil {
|
||||||
|
maxLvl, _ := strconv.Atoi(m[1])
|
||||||
|
w.WriteOutline(w.document, maxLvl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,9 +216,8 @@ func (w *HTMLWriter) WriteFootnotes(d *Document) {
|
||||||
w.WriteString("</div>\n</div>\n")
|
w.WriteString("</div>\n</div>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) WriteOutline(d *Document) {
|
func (w *HTMLWriter) WriteOutline(d *Document, maxLvl int) {
|
||||||
if w.document.GetOption("toc") != "nil" && len(d.Outline.Children) != 0 {
|
if len(d.Outline.Children) != 0 {
|
||||||
maxLvl, _ := strconv.Atoi(w.document.GetOption("toc"))
|
|
||||||
w.WriteString("<nav>\n<ul>\n")
|
w.WriteString("<nav>\n<ul>\n")
|
||||||
for _, section := range d.Outline.Children {
|
for _, section := range d.Outline.Children {
|
||||||
w.writeSection(section, maxLvl)
|
w.writeSection(section, maxLvl)
|
||||||
|
|
31
org/testdata/keywords.html
vendored
31
org/testdata/keywords.html
vendored
|
@ -1,3 +1,8 @@
|
||||||
|
<div id="outline-container-headline-1" class="outline-2">
|
||||||
|
<h2 id="headline-1">
|
||||||
|
captions, custom attributes and more
|
||||||
|
</h2>
|
||||||
|
<div id="outline-text-headline-1" class="outline-text-2">
|
||||||
<figure>
|
<figure>
|
||||||
<div class="src src-sh a b c d" id="it">
|
<div class="src src-sh a b c d" id="it">
|
||||||
<div class="highlight">
|
<div class="highlight">
|
||||||
|
@ -26,3 +31,29 @@ named block
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p>#not a comment because there's no space after the hashtag</p>
|
<p>#not a comment because there's no space after the hashtag</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="outline-container-headline-2" class="outline-2">
|
||||||
|
<h2 id="headline-2">
|
||||||
|
table of contents
|
||||||
|
</h2>
|
||||||
|
<div id="outline-text-headline-2" class="outline-text-2">
|
||||||
|
<p>A table of contents can be rendered anywhere in the document by using</p>
|
||||||
|
<div class="src src-org">
|
||||||
|
<div class="highlight">
|
||||||
|
<pre>
|
||||||
|
#+TOC: headlines $n
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>Where <code class="verbatim">$n</code> is the max headline lvl that will be included. You can use <code class="verbatim">headlines 0</code> to include all headlines.</p>
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#headline-1">captions, custom attributes and more</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#headline-2">table of contents</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
11
org/testdata/keywords.org
vendored
11
org/testdata/keywords.org
vendored
|
@ -1,4 +1,5 @@
|
||||||
|
#+OPTIONS: toc:nil
|
||||||
|
* captions, custom attributes and more
|
||||||
#+CAPTION: and _multiple_
|
#+CAPTION: and _multiple_
|
||||||
#+CAPTION: lines of *captions*!
|
#+CAPTION: lines of *captions*!
|
||||||
#+ATTR_HTML: :class a b
|
#+ATTR_HTML: :class a b
|
||||||
|
@ -23,3 +24,11 @@ named block
|
||||||
|
|
||||||
# comments must have whitespace after the hashtag
|
# comments must have whitespace after the hashtag
|
||||||
#not a comment because there's no space after the hashtag
|
#not a comment because there's no space after the hashtag
|
||||||
|
|
||||||
|
* table of contents
|
||||||
|
A table of contents can be rendered anywhere in the document by using
|
||||||
|
#+begin_src org
|
||||||
|
,#+TOC: headlines $n
|
||||||
|
#+end_src
|
||||||
|
Where =$n= is the max headline lvl that will be included. You can use =headlines 0= to include all headlines.
|
||||||
|
#+TOC: headlines 0
|
||||||
|
|
11
org/testdata/keywords.pretty_org
vendored
11
org/testdata/keywords.pretty_org
vendored
|
@ -1,4 +1,5 @@
|
||||||
|
#+OPTIONS: toc:nil
|
||||||
|
* captions, custom attributes and more
|
||||||
#+CAPTION: and _multiple_
|
#+CAPTION: and _multiple_
|
||||||
#+CAPTION: lines of *captions*!
|
#+CAPTION: lines of *captions*!
|
||||||
#+ATTR_HTML: :class a b
|
#+ATTR_HTML: :class a b
|
||||||
|
@ -23,3 +24,11 @@ named block
|
||||||
|
|
||||||
# comments must have whitespace after the hashtag
|
# comments must have whitespace after the hashtag
|
||||||
#not a comment because there's no space after the hashtag
|
#not a comment because there's no space after the hashtag
|
||||||
|
|
||||||
|
* table of contents
|
||||||
|
A table of contents can be rendered anywhere in the document by using
|
||||||
|
#+BEGIN_SRC org
|
||||||
|
,#+TOC: headlines $n
|
||||||
|
#+END_SRC
|
||||||
|
Where =$n= is the max headline lvl that will be included. You can use =headlines 0= to include all headlines.
|
||||||
|
#+TOC: headlines 0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue