mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Wordpress summaries
Allow full control of summaries which can be rendered as html rather than text. Using a `<!--more-->` html comment in your markdown / rst you can indiciate where the summary should end and have the summary converted to html. Signed-off-by: Noah Campbell <noahcampbell@gmail.com> Conflicts: hugolib/page_test.go
This commit is contained in:
parent
7b1f0960e3
commit
9930011ea2
3 changed files with 77 additions and 22 deletions
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/kr/pretty"
|
"github.com/kr/pretty"
|
||||||
"html/template"
|
"html/template"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -28,6 +29,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var sanitizeRegexp = regexp.MustCompile("[^a-zA-Z0-9./_-]")
|
var sanitizeRegexp = regexp.MustCompile("[^a-zA-Z0-9./_-]")
|
||||||
|
var summaryLength = 70
|
||||||
|
var summaryDivider = []byte("<!--more-->")
|
||||||
|
|
||||||
// TODO: Make these wrappers private
|
// TODO: Make these wrappers private
|
||||||
// Wrapper around Fprintf taking verbose flag in account.
|
// Wrapper around Fprintf taking verbose flag in account.
|
||||||
|
@ -329,3 +332,32 @@ func TruncateWordsToWholeSentence(s string, max int) string {
|
||||||
func MakePermalink(domain string, path string) string {
|
func MakePermalink(domain string, path string) string {
|
||||||
return strings.TrimRight(domain, "/") + "/" + strings.TrimLeft(path, "/")
|
return strings.TrimRight(domain, "/") + "/" + strings.TrimLeft(path, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSummaryString(content []byte) ([]byte, bool) {
|
||||||
|
if (bytes.Contains(content, summaryDivider)) {
|
||||||
|
return bytes.Split(content, summaryDivider)[0], false
|
||||||
|
} else {
|
||||||
|
plainContent := StripHTML(StripShortcodes(string(content)))
|
||||||
|
return []byte(TruncateWordsToWholeSentence(plainContent, summaryLength)), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRstContent(content []byte) string {
|
||||||
|
cleanContent := bytes.Replace(content, summaryDivider, []byte(""), 1)
|
||||||
|
|
||||||
|
cmd := exec.Command("rst2html.py", "--leave-comments")
|
||||||
|
cmd.Stdin = bytes.NewReader(cleanContent)
|
||||||
|
var out bytes.Buffer
|
||||||
|
cmd.Stdout = &out
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rstLines := strings.Split(out.String(), "\n")
|
||||||
|
for i, line := range rstLines {
|
||||||
|
if strings.HasPrefix(line, "<body>") {
|
||||||
|
rstLines = (rstLines[i+1 : len(rstLines)-3])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(rstLines, "\n")
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"launchpad.net/goyaml"
|
"launchpad.net/goyaml"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -55,8 +54,6 @@ type Page struct {
|
||||||
Node
|
Node
|
||||||
}
|
}
|
||||||
|
|
||||||
const summaryLength = 70
|
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
FileName, OutFile, Extension string
|
FileName, OutFile, Extension string
|
||||||
}
|
}
|
||||||
|
@ -476,27 +473,25 @@ func (page *Page) parse(reader io.Reader) error {
|
||||||
func (page *Page) convertMarkdown(lines io.Reader) {
|
func (page *Page) convertMarkdown(lines io.Reader) {
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
b.ReadFrom(lines)
|
b.ReadFrom(lines)
|
||||||
content := string(blackfriday.MarkdownCommon(b.Bytes()))
|
content := b.Bytes()
|
||||||
page.Content = template.HTML(content)
|
page.Content = template.HTML(string(blackfriday.MarkdownCommon(content)))
|
||||||
page.Summary = template.HTML(TruncateWordsToWholeSentence(StripHTML(StripShortcodes(content)), summaryLength))
|
summary, plain := getSummaryString(content)
|
||||||
|
if plain {
|
||||||
|
page.Summary = template.HTML(string(summary))
|
||||||
|
} else {
|
||||||
|
page.Summary = template.HTML(string(blackfriday.MarkdownCommon(summary)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (page *Page) convertRestructuredText(lines io.Reader) {
|
func (page *Page) convertRestructuredText(lines io.Reader) {
|
||||||
cmd := exec.Command("rst2html.py")
|
b := new(bytes.Buffer)
|
||||||
cmd.Stdin = lines
|
b.ReadFrom(lines)
|
||||||
var out bytes.Buffer
|
content := b.Bytes()
|
||||||
cmd.Stdout = &out
|
page.Content = template.HTML(getRstContent(content))
|
||||||
if err := cmd.Run(); err != nil {
|
summary, plain := getSummaryString(content)
|
||||||
fmt.Println(err)
|
if plain {
|
||||||
}
|
page.Summary = template.HTML(string(summary))
|
||||||
|
} else {
|
||||||
rstLines := strings.Split(out.String(), "\n")
|
page.Summary = template.HTML(getRstContent(summary))
|
||||||
for i, line := range rstLines {
|
|
||||||
if strings.HasPrefix(line, "<body>") {
|
|
||||||
rstLines = (rstLines[i+1 : len(rstLines)-3])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
content := strings.Join(rstLines, "\n")
|
|
||||||
page.Content = template.HTML(content)
|
|
||||||
page.Summary = template.HTML(TruncateWordsToWholeSentence(StripHTML(StripShortcodes(content)), summaryLength))
|
|
||||||
}
|
|
||||||
|
|
|
@ -91,6 +91,15 @@ layout: buzfoo
|
||||||
---
|
---
|
||||||
type and layout set`
|
type and layout set`
|
||||||
|
|
||||||
|
var SIMPLE_PAGE_WITH_SUMMARY_DELIMITER = `---
|
||||||
|
title: Simple
|
||||||
|
---
|
||||||
|
Simple Page
|
||||||
|
|
||||||
|
<!--more-->
|
||||||
|
Some more text
|
||||||
|
`
|
||||||
|
|
||||||
func checkError(t *testing.T, err error, expected string) {
|
func checkError(t *testing.T, err error, expected string) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("err is nil")
|
t.Fatalf("err is nil")
|
||||||
|
@ -130,6 +139,12 @@ func checkPageContent(t *testing.T, page *Page, content string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkPageSummary(t *testing.T, page *Page, summary string) {
|
||||||
|
if page.Summary != template.HTML(summary) {
|
||||||
|
t.Fatalf("Page summary is: `%s`. Expected `%s`", page.Summary, summary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func checkPageType(t *testing.T, page *Page, pageType string) {
|
func checkPageType(t *testing.T, page *Page, pageType string) {
|
||||||
if page.Type() != pageType {
|
if page.Type() != pageType {
|
||||||
t.Fatalf("Page type is: %s. Expected: %s", page.Type(), pageType)
|
t.Fatalf("Page type is: %s. Expected: %s", page.Type(), pageType)
|
||||||
|
@ -149,6 +164,19 @@ func TestCreateNewPage(t *testing.T) {
|
||||||
}
|
}
|
||||||
checkPageTitle(t, p, "Simple")
|
checkPageTitle(t, p, "Simple")
|
||||||
checkPageContent(t, p, "<p>Simple Page</p>\n")
|
checkPageContent(t, p, "<p>Simple Page</p>\n")
|
||||||
|
checkPageSummary(t, p, "Simple Page")
|
||||||
|
checkPageType(t, p, "page")
|
||||||
|
checkPageLayout(t, p, "page/single.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPageWithDelimiter(t *testing.T) {
|
||||||
|
p, err := ReadFrom(strings.NewReader(SIMPLE_PAGE_WITH_SUMMARY_DELIMITER), "simple")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to create a page with frontmatter and body content: %s", err)
|
||||||
|
}
|
||||||
|
checkPageTitle(t, p, "Simple")
|
||||||
|
checkPageContent(t, p, "<p>Simple Page</p>\n\n<!--more-->\n\n<p>Some more text</p>\n")
|
||||||
|
checkPageSummary(t, p, "<p>Simple Page</p>\n")
|
||||||
checkPageType(t, p, "page")
|
checkPageType(t, p, "page")
|
||||||
checkPageLayout(t, p, "page/single.html")
|
checkPageLayout(t, p, "page/single.html")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue