Allow customizing header level offset
Allows consumers to specify `TopLevelHLevel` to `HTMLWriter`, which works identically to Org's official [`:html-toplevel-hlevel` / `org-html-toplevel-hlevel`](https://orgmode.org/manual/Publishing-options.html) property. Fixes #94.
This commit is contained in:
parent
1849701ba7
commit
97d5ac5933
2 changed files with 69 additions and 4 deletions
|
@ -21,6 +21,21 @@ type HTMLWriter struct {
|
|||
ExtendingWriter Writer
|
||||
HighlightCodeBlock func(source, lang string, inline bool, params map[string]string) string
|
||||
PrettyRelativeLinks bool
|
||||
// TopLevelHLevel determines what HTML heading to use for a
|
||||
// level-1 Org headline, and by extension further headings.
|
||||
//
|
||||
// For example, a value of 1 means a top-level Org headline will be
|
||||
// rendered as an <h1> element, a level-2 Org headline will be
|
||||
// rendered as an <h2> element, and so on.
|
||||
//
|
||||
// A value of 2 (default) means a top-level Org headline will be
|
||||
// rendered as an <h2> element, a level-2 Org headline will be
|
||||
// rendered as an <h3> element, and so on.
|
||||
//
|
||||
// This setting and its default behavior match Org's
|
||||
// :html-toplevel-hlevel export property and the associated
|
||||
// org-html-toplevel-hlevel variable.
|
||||
TopLevelHLevel int
|
||||
|
||||
strings.Builder
|
||||
document *Document
|
||||
|
@ -72,6 +87,7 @@ func NewHTMLWriter() *HTMLWriter {
|
|||
}
|
||||
return fmt.Sprintf("<div class=\"highlight\">\n<pre>\n%s\n</pre>\n</div>", html.EscapeString(source))
|
||||
},
|
||||
TopLevelHLevel: 2,
|
||||
footnotes: &footnotes{
|
||||
mapping: map[string]int{},
|
||||
},
|
||||
|
@ -272,8 +288,10 @@ func (w *HTMLWriter) WriteHeadline(h Headline) {
|
|||
return
|
||||
}
|
||||
|
||||
w.WriteString(fmt.Sprintf(`<div id="outline-container-%s" class="outline-%d">`, h.ID(), h.Lvl+1) + "\n")
|
||||
w.WriteString(fmt.Sprintf(`<h%d id="%s">`, h.Lvl+1, h.ID()) + "\n")
|
||||
level := (h.Lvl - 1) + w.TopLevelHLevel
|
||||
|
||||
w.WriteString(fmt.Sprintf(`<div id="outline-container-%s" class="outline-%d">`, h.ID(), level) + "\n")
|
||||
w.WriteString(fmt.Sprintf(`<h%d id="%s">`, level, h.ID()) + "\n")
|
||||
if w.document.GetOption("todo") != "nil" && h.Status != "" {
|
||||
w.WriteString(fmt.Sprintf(`<span class="todo">%s</span>`, h.Status) + "\n")
|
||||
}
|
||||
|
@ -290,9 +308,9 @@ func (w *HTMLWriter) WriteHeadline(h Headline) {
|
|||
w.WriteString("   ")
|
||||
w.WriteString(fmt.Sprintf(`<span class="tags">%s</span>`, strings.Join(tags, " ")))
|
||||
}
|
||||
w.WriteString(fmt.Sprintf("\n</h%d>\n", h.Lvl+1))
|
||||
w.WriteString(fmt.Sprintf("\n</h%d>\n", level))
|
||||
if content := w.WriteNodesAsString(h.Children...); content != "" {
|
||||
w.WriteString(fmt.Sprintf(`<div id="outline-text-%s" class="outline-text-%d">`, h.ID(), h.Lvl+1) + "\n" + content + "</div>\n")
|
||||
w.WriteString(fmt.Sprintf(`<div id="outline-text-%s" class="outline-text-%d">`, h.ID(), level) + "\n" + content + "</div>\n")
|
||||
}
|
||||
w.WriteString("</div>\n")
|
||||
}
|
||||
|
|
|
@ -56,3 +56,50 @@ func TestPrettyRelativeLinks(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
var topLevelHLevelTests = map[struct {
|
||||
TopLevelHLevel int
|
||||
input string
|
||||
}]string{
|
||||
{1, "* Top-level headline"}: "<h1 id=\"headline-1\">\nTop-level headline\n</h1>",
|
||||
{1, "** Second-level headline"}: "<h2 id=\"headline-1\">\nSecond-level headline\n</h2>",
|
||||
{1, "*** Third-level headline"}: "<h3 id=\"headline-1\">\nThird-level headline\n</h3>",
|
||||
{1, "**** Fourth-level headline"}: "<h4 id=\"headline-1\">\nFourth-level headline\n</h4>",
|
||||
{1, "***** Fifth-level headline"}: "<h5 id=\"headline-1\">\nFifth-level headline\n</h5>",
|
||||
{1, "****** Sixth-level headline"}: "<h6 id=\"headline-1\">\nSixth-level headline\n</h6>",
|
||||
|
||||
{2, "* Top-level headline"}: "<h2 id=\"headline-1\">\nTop-level headline\n</h2>",
|
||||
{2, "** Second-level headline"}: "<h3 id=\"headline-1\">\nSecond-level headline\n</h3>",
|
||||
{2, "*** Third-level headline"}: "<h4 id=\"headline-1\">\nThird-level headline\n</h4>",
|
||||
{2, "**** Fourth-level headline"}: "<h5 id=\"headline-1\">\nFourth-level headline\n</h5>",
|
||||
{2, "***** Fifth-level headline"}: "<h6 id=\"headline-1\">\nFifth-level headline\n</h6>",
|
||||
|
||||
{3, "* Top-level headline"}: "<h3 id=\"headline-1\">\nTop-level headline\n</h3>",
|
||||
{3, "** Second-level headline"}: "<h4 id=\"headline-1\">\nSecond-level headline\n</h4>",
|
||||
{3, "*** Third-level headline"}: "<h5 id=\"headline-1\">\nThird-level headline\n</h5>",
|
||||
{3, "**** Fourth-level headline"}: "<h6 id=\"headline-1\">\nFourth-level headline\n</h6>",
|
||||
|
||||
{4, "* Top-level headline"}: "<h4 id=\"headline-1\">\nTop-level headline\n</h4>",
|
||||
{4, "** Second-level headline"}: "<h5 id=\"headline-1\">\nSecond-level headline\n</h5>",
|
||||
{4, "*** Third-level headline"}: "<h6 id=\"headline-1\">\nThird-level headline\n</h6>",
|
||||
|
||||
{5, "* Top-level headline"}: "<h5 id=\"headline-1\">\nTop-level headline\n</h5>",
|
||||
{5, "** Second-level headline"}: "<h6 id=\"headline-1\">\nSecond-level headline\n</h6>",
|
||||
|
||||
{6, "* Top-level headline"}: "<h6 id=\"headline-1\">\nTop-level headline\n</h6>",
|
||||
}
|
||||
|
||||
func TestTopLevelHLevel(t *testing.T) {
|
||||
for org, expected := range topLevelHLevelTests {
|
||||
t.Run(org.input, func(t *testing.T) {
|
||||
writer := NewHTMLWriter()
|
||||
writer.TopLevelHLevel = org.TopLevelHLevel
|
||||
actual, err := New().Silent().Parse(strings.NewReader(org.input), "./topLevelHLevelTests.org").Write(writer)
|
||||
if err != nil {
|
||||
t.Errorf("TopLevelHLevel=%d %s\n got error: %s", org.TopLevelHLevel, org.input, err)
|
||||
} else if actual := strings.TrimSpace(actual); !strings.Contains(actual, expected) {
|
||||
t.Errorf("TopLevelHLevel=%d %s:\n%s'", org.TopLevelHLevel, org.input, diff(actual, expected))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue