mirror of
https://github.com/gohugoio/hugo.git
synced 2025-04-07 12:55:53 +00:00
Continue with TOC integration and page refactor. Updated a few tests to match new generated output.
This commit is contained in:
parent
f45c6bc38a
commit
1da3fd039a
2 changed files with 411 additions and 354 deletions
|
@ -38,6 +38,7 @@ type Page struct {
|
||||||
rawContent []byte
|
rawContent []byte
|
||||||
Content template.HTML
|
Content template.HTML
|
||||||
Summary template.HTML
|
Summary template.HTML
|
||||||
|
TableOfContents template.HTML
|
||||||
Truncated bool
|
Truncated bool
|
||||||
plain string // TODO should be []byte
|
plain string // TODO should be []byte
|
||||||
Params map[string]interface{}
|
Params map[string]interface{}
|
||||||
|
@ -75,7 +76,7 @@ type Pages []*Page
|
||||||
|
|
||||||
func (p *Page) Plain() string {
|
func (p *Page) Plain() string {
|
||||||
if len(p.plain) == 0 {
|
if len(p.plain) == 0 {
|
||||||
p.plain = StripHTML(StripShortcodes(string(p.rawContent)))
|
p.plain = StripHTML(StripShortcodes(string(p.renderBytes(p.rawContent))))
|
||||||
}
|
}
|
||||||
return p.plain
|
return p.plain
|
||||||
}
|
}
|
||||||
|
@ -96,6 +97,10 @@ func (p *Page) setSummary() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stripEmptyNav(in []byte) []byte {
|
||||||
|
return bytes.Replace(in, []byte("<nav>\n</nav>\n\n"), []byte(``), -1)
|
||||||
|
}
|
||||||
|
|
||||||
func bytesToHTML(b []byte) template.HTML {
|
func bytesToHTML(b []byte) template.HTML {
|
||||||
return template.HTML(string(b))
|
return template.HTML(string(b))
|
||||||
}
|
}
|
||||||
|
@ -104,16 +109,27 @@ func (p *Page) renderBytes(content []byte) []byte {
|
||||||
return renderBytes(content, p.guessMarkupType())
|
return renderBytes(content, p.guessMarkupType())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Page) renderString(content string) []byte {
|
func (p *Page) renderContent(content []byte) []byte {
|
||||||
return renderBytes([]byte(content), p.guessMarkupType())
|
return renderBytesWithTOC(content, p.guessMarkupType())
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderBytesWithTOC(content []byte, pagefmt string) []byte {
|
||||||
|
switch pagefmt {
|
||||||
|
default:
|
||||||
|
return markdownRenderWithTOC(content)
|
||||||
|
case "markdown":
|
||||||
|
return markdownRenderWithTOC(content)
|
||||||
|
case "rst":
|
||||||
|
return []byte(getRstContent(content))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderBytes(content []byte, pagefmt string) []byte {
|
func renderBytes(content []byte, pagefmt string) []byte {
|
||||||
switch pagefmt {
|
switch pagefmt {
|
||||||
default:
|
default:
|
||||||
return blackfriday.MarkdownCommon(content)
|
return markdownRender(content)
|
||||||
case "markdown":
|
case "markdown":
|
||||||
return blackfriday.MarkdownCommon(content)
|
return markdownRender(content)
|
||||||
case "rst":
|
case "rst":
|
||||||
return []byte(getRstContent(content))
|
return []byte(getRstContent(content))
|
||||||
}
|
}
|
||||||
|
@ -553,7 +569,9 @@ func (page *Page) Convert() error {
|
||||||
markupType := page.guessMarkupType()
|
markupType := page.guessMarkupType()
|
||||||
switch markupType {
|
switch markupType {
|
||||||
case "markdown", "rst":
|
case "markdown", "rst":
|
||||||
page.Content = bytesToHTML(page.renderString(string(RemoveSummaryDivider(page.rawContent))))
|
tmpContent, tmpTableOfContents := extractTOC(page.renderContent(RemoveSummaryDivider(page.rawContent)))
|
||||||
|
page.Content = bytesToHTML(tmpContent)
|
||||||
|
page.TableOfContents = bytesToHTML(tmpTableOfContents)
|
||||||
case "html":
|
case "html":
|
||||||
page.Content = bytesToHTML(page.rawContent)
|
page.Content = bytesToHTML(page.rawContent)
|
||||||
default:
|
default:
|
||||||
|
@ -562,19 +580,58 @@ func (page *Page) Convert() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lazily generate the TOC
|
func markdownRender(content []byte) []byte {
|
||||||
func (page *Page) TableOfContents() template.HTML {
|
htmlFlags := 0
|
||||||
return tableOfContentsFromBytes([]byte(page.Content))
|
htmlFlags |= blackfriday.HTML_SKIP_SCRIPT
|
||||||
|
htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
|
||||||
|
renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
|
||||||
|
|
||||||
|
return blackfriday.Markdown(content, renderer, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableOfContentsFromBytes(content []byte) template.HTML {
|
func markdownRenderWithTOC(content []byte) []byte {
|
||||||
htmlFlags := 0
|
htmlFlags := 0
|
||||||
htmlFlags |= blackfriday.HTML_SKIP_SCRIPT
|
htmlFlags |= blackfriday.HTML_SKIP_SCRIPT
|
||||||
htmlFlags |= blackfriday.HTML_TOC
|
htmlFlags |= blackfriday.HTML_TOC
|
||||||
htmlFlags |= blackfriday.HTML_OMIT_CONTENTS
|
htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS
|
||||||
renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
|
renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
|
||||||
|
|
||||||
return template.HTML(string(blackfriday.Markdown(RemoveSummaryDivider(content), renderer, 0)))
|
return blackfriday.Markdown(content, renderer, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractTOC(content []byte) (newcontent []byte, toc []byte) {
|
||||||
|
origContent := make([]byte, len(content))
|
||||||
|
copy(origContent, content)
|
||||||
|
first := []byte(`<nav>
|
||||||
|
<ul>`)
|
||||||
|
|
||||||
|
last := []byte(`</ul>
|
||||||
|
</nav>`)
|
||||||
|
|
||||||
|
replacement := []byte(`<nav id="TableOfContents">
|
||||||
|
<ul>`)
|
||||||
|
|
||||||
|
startOfTOC := bytes.Index(content, first)
|
||||||
|
|
||||||
|
peekEnd := len(content)
|
||||||
|
if peekEnd > 70+startOfTOC {
|
||||||
|
peekEnd = 70 + startOfTOC
|
||||||
|
}
|
||||||
|
|
||||||
|
if startOfTOC < 0 {
|
||||||
|
return stripEmptyNav(content), toc
|
||||||
|
}
|
||||||
|
// Need to peek ahead to see if this nav element is actually the right one.
|
||||||
|
correctNav := bytes.Index(content[startOfTOC:peekEnd], []byte(`#toc_0`))
|
||||||
|
if correctNav < 0 { // no match found
|
||||||
|
return content, toc
|
||||||
|
}
|
||||||
|
lengthOfTOC := bytes.Index(content[startOfTOC:], last) + len(last)
|
||||||
|
endOfTOC := startOfTOC + lengthOfTOC
|
||||||
|
|
||||||
|
newcontent = append(content[:startOfTOC], content[endOfTOC:]...)
|
||||||
|
toc = append(replacement, origContent[startOfTOC+len(first):endOfTOC]...)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReaderToBytes(lines io.Reader) []byte {
|
func ReaderToBytes(lines io.Reader) []byte {
|
||||||
|
|
|
@ -98,7 +98,7 @@ func TestRenderThing(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{PAGE_SIMPLE_TITLE, TEMPLATE_TITLE, "simple template"},
|
{PAGE_SIMPLE_TITLE, TEMPLATE_TITLE, "simple template"},
|
||||||
{PAGE_SIMPLE_TITLE, TEMPLATE_FUNC, "simple-template"},
|
{PAGE_SIMPLE_TITLE, TEMPLATE_FUNC, "simple-template"},
|
||||||
{PAGE_WITH_MD, TEMPLATE_CONTENT, "<h1>heading 1</h1>\n\n<p>text</p>\n\n<h2>heading 2</h2>\n\n<p>more text</p>\n"},
|
{PAGE_WITH_MD, TEMPLATE_CONTENT, "\n\n<h1 id=\"toc_0\">heading 1</h1>\n\n<p>text</p>\n\n<h2 id=\"toc_1\">heading 2</h2>\n\n<p>more text</p>\n"},
|
||||||
{SIMPLE_PAGE_RFC3339_DATE, TEMPLATE_DATE, "2013-05-17 16:59:30 +0000 UTC"},
|
{SIMPLE_PAGE_RFC3339_DATE, TEMPLATE_DATE, "2013-05-17 16:59:30 +0000 UTC"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,14 +265,14 @@ func TestSkipRender(t *testing.T) {
|
||||||
doc string
|
doc string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{"sect/doc1.html", "<h1>title</h1>\n\n<p>some <em>content</em></p>\n"},
|
{"sect/doc1.html", "\n\n<h1 id=\"toc_0\">title</h1>\n\n<p>some <em>content</em></p>\n"},
|
||||||
{"sect/doc2.html", "<!doctype html><html><body>more content</body></html>"},
|
{"sect/doc2.html", "<!doctype html><html><body>more content</body></html>"},
|
||||||
{"sect/doc3.html", "<h1>doc3</h1>\n\n<p><em>some</em> content</p>\n"},
|
{"sect/doc3.html", "\n\n<h1 id=\"toc_0\">doc3</h1>\n\n<p><em>some</em> content</p>\n"},
|
||||||
{"sect/doc4.html", "<h1>doc4</h1>\n\n<p><em>some content</em></p>\n"},
|
{"sect/doc4.html", "\n\n<h1 id=\"toc_0\">doc4</h1>\n\n<p><em>some content</em></p>\n"},
|
||||||
{"sect/doc5.html", "<!doctype html><html><head><script src=\"script.js\"></script></head><body>body5</body></html>"},
|
{"sect/doc5.html", "<!doctype html><html><head><script src=\"script.js\"></script></head><body>body5</body></html>"},
|
||||||
{"sect/doc6.html", "<!doctype html><html><head><script src=\"http://auth/bub/script.js\"></script></head><body>body5</body></html>"},
|
{"sect/doc6.html", "<!doctype html><html><head><script src=\"http://auth/bub/script.js\"></script></head><body>body5</body></html>"},
|
||||||
{"doc7.html", "<html><body>doc7 content</body></html>"},
|
{"doc7.html", "<html><body>doc7 content</body></html>"},
|
||||||
{"sect/doc8.html", "<h1>title</h1>\n\n<p>some <em>content</em></p>\n"},
|
{"sect/doc8.html", "\n\n<h1 id=\"toc_0\">title</h1>\n\n<p>some <em>content</em></p>\n"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
Loading…
Add table
Reference in a new issue