shithub: hugo

Download patch

ref: fbf8bcacc464e9bfbc816fa6d097e6371662ce02
parent: bb3769822635963c35900fb307520e6bed7ff931
author: bep <[email protected]>
date: Fri Nov 28 16:16:57 EST 2014

Add configurable support for angled quotes

The flag `HTML_SMARTYPANTS_ANGLED_QUOTES` was added to Blackfriday on Black Friday. This configures rendering of double quotes as angled left and right quotes (&laquo;
&raquo;).

Typical use cases would be either or, or combined, but never in the same
document. As an example would be a person from Norway; he has a blog in both
English and Norwegian (his native tongue); he would then configure Blackfriday
to use angled quotes for the Norwegian section, but keep them as reqular
double quotes for the English.

This commit adds configuration support for this new flag, configuration that can be set in the site configuration, but overridden in page front matter.

Fixes #605

--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -136,6 +136,7 @@
 	viper.SetDefault("FootnoteAnchorPrefix", "")
 	viper.SetDefault("FootnoteReturnLinkContents", "")
 	viper.SetDefault("NewContentEditor", "")
+	viper.SetDefault("Blackfriday", map[string]bool{"angledQuotes": false})
 
 	if hugoCmdV.PersistentFlags().Lookup("buildDrafts").Changed {
 		viper.Set("BuildDrafts", Draft)
--- a/helpers/content.go
+++ b/helpers/content.go
@@ -77,15 +77,15 @@
 	return template.HTML(string(b))
 }
 
-func GetHtmlRenderer(defaultFlags int, documentId string) blackfriday.Renderer {
+func GetHtmlRenderer(defaultFlags int, ctx RenderingContext) blackfriday.Renderer {
 	renderParameters := blackfriday.HtmlRendererParameters{
 		FootnoteAnchorPrefix:       viper.GetString("FootnoteAnchorPrefix"),
 		FootnoteReturnLinkContents: viper.GetString("FootnoteReturnLinkContents"),
 	}
 
-	if len(documentId) != 0 {
-		renderParameters.FootnoteAnchorPrefix = documentId + ":" + renderParameters.FootnoteAnchorPrefix
-		renderParameters.HeaderIDSuffix = ":" + documentId
+	if len(ctx.DocumentId) != 0 {
+		renderParameters.FootnoteAnchorPrefix = ctx.DocumentId + ":" + renderParameters.FootnoteAnchorPrefix
+		renderParameters.HeaderIDSuffix = ":" + ctx.DocumentId
 	}
 
 	htmlFlags := defaultFlags
@@ -95,6 +95,16 @@
 	htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
 	htmlFlags |= blackfriday.HTML_FOOTNOTE_RETURN_LINKS
 
+	var angledQuotes bool
+
+	if m, ok := ctx.ConfigFlags["angledQuotes"]; ok {
+		angledQuotes = m
+	}
+
+	if angledQuotes {
+		htmlFlags |= blackfriday.HTML_SMARTYPANTS_ANGLED_QUOTES
+	}
+
 	return blackfriday.HtmlRendererWithParameters(htmlFlags, "", "", renderParameters)
 }
 
@@ -106,14 +116,14 @@
 		blackfriday.EXTENSION_HEADER_IDS | blackfriday.EXTENSION_AUTO_HEADER_IDS
 }
 
-func MarkdownRender(content []byte, documentId string) []byte {
-	return blackfriday.Markdown(content, GetHtmlRenderer(0, documentId),
+func MarkdownRender(ctx RenderingContext) []byte {
+	return blackfriday.Markdown(ctx.Content, GetHtmlRenderer(0, ctx),
 		GetMarkdownExtensions())
 }
 
-func MarkdownRenderWithTOC(content []byte, documentId string) []byte {
-	return blackfriday.Markdown(content,
-		GetHtmlRenderer(blackfriday.HTML_TOC, documentId),
+func MarkdownRenderWithTOC(ctx RenderingContext) []byte {
+	return blackfriday.Markdown(ctx.Content,
+		GetHtmlRenderer(blackfriday.HTML_TOC, ctx),
 		GetMarkdownExtensions())
 }
 
@@ -153,25 +163,32 @@
 	return
 }
 
-func RenderBytesWithTOC(content []byte, pagefmt string, documentId string) []byte {
-	switch pagefmt {
+type RenderingContext struct {
+	Content     []byte
+	PageFmt     string
+	DocumentId  string
+	ConfigFlags map[string]bool
+}
+
+func RenderBytesWithTOC(ctx RenderingContext) []byte {
+	switch ctx.PageFmt {
 	default:
-		return MarkdownRenderWithTOC(content, documentId)
+		return MarkdownRenderWithTOC(ctx)
 	case "markdown":
-		return MarkdownRenderWithTOC(content, documentId)
+		return MarkdownRenderWithTOC(ctx)
 	case "rst":
-		return []byte(GetRstContent(content))
+		return []byte(GetRstContent(ctx.Content))
 	}
 }
 
-func RenderBytes(content []byte, pagefmt string, documentId string) []byte {
-	switch pagefmt {
+func RenderBytes(ctx RenderingContext) []byte {
+	switch ctx.PageFmt {
 	default:
-		return MarkdownRender(content, documentId)
+		return MarkdownRender(ctx)
 	case "markdown":
-		return MarkdownRender(content, documentId)
+		return MarkdownRender(ctx)
 	case "rst":
-		return []byte(GetRstContent(content))
+		return []byte(GetRstContent(ctx.Content))
 	}
 }
 
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -17,10 +17,11 @@
 	"bytes"
 	"errors"
 	"fmt"
-	"github.com/spf13/cast"
 	"github.com/spf13/hugo/helpers"
-	"github.com/spf13/hugo/hugofs"
 	"github.com/spf13/hugo/parser"
+
+	"github.com/spf13/cast"
+	"github.com/spf13/hugo/hugofs"
 	"github.com/spf13/hugo/source"
 	"github.com/spf13/hugo/tpl"
 	jww "github.com/spf13/jwalterweatherman"
@@ -173,13 +174,34 @@
 }
 
 func (p *Page) renderBytes(content []byte) []byte {
-	return helpers.RenderBytes(content, p.guessMarkupType(), p.UniqueId())
+	return helpers.RenderBytes(
+		helpers.RenderingContext{Content: content, PageFmt: p.guessMarkupType(),
+			DocumentId: p.UniqueId(), ConfigFlags: p.getRenderingConfigFlags()})
 }
 
 func (p *Page) renderContent(content []byte) []byte {
-	return helpers.RenderBytesWithTOC(content, p.guessMarkupType(), p.UniqueId())
+	return helpers.RenderBytesWithTOC(helpers.RenderingContext{Content: content, PageFmt: p.guessMarkupType(),
+		DocumentId: p.UniqueId(), ConfigFlags: p.getRenderingConfigFlags()})
 }
 
+func (p *Page) getRenderingConfigFlags() map[string]bool {
+	flags := make(map[string]bool)
+
+	pageParam := p.GetParam("blackfriday")
+	siteParam := viper.GetStringMap("blackfriday")
+
+	flags = cast.ToStringMapBool(siteParam)
+
+	if pageParam != nil {
+		pageFlags := cast.ToStringMapBool(pageParam)
+		for key, value := range pageFlags {
+			flags[key] = value
+		}
+	}
+
+	return flags
+}
+
 func newPage(filename string) *Page {
 	page := Page{contentType: "",
 		Source: Source{File: *source.NewFile(filename)},
@@ -472,6 +494,8 @@
 		return cast.ToTime(v)
 	case []string:
 		return helpers.SliceToLower(v.([]string))
+	case map[interface{}]interface{}:
+		return v
 	}
 	return nil
 }
--- a/hugolib/shortcode.go
+++ b/hugolib/shortcode.go
@@ -212,7 +212,9 @@
 		}
 
 		if sc.doMarkup {
-			newInner := helpers.RenderBytes([]byte(inner), p.guessMarkupType(), p.UniqueId())
+			newInner := helpers.RenderBytes(helpers.RenderingContext{
+				Content: []byte(inner), PageFmt: p.guessMarkupType(),
+				DocumentId: p.UniqueId(), ConfigFlags: p.getRenderingConfigFlags()})
 
 			// If the type is “unknown” or “markdown”, we assume the markdown
 			// generation has been performed. Given the input: `a line`, markdown
--- a/tpl/template.go
+++ b/tpl/template.go
@@ -618,7 +618,7 @@
 }
 
 func Markdownify(text string) template.HTML {
-	return template.HTML(helpers.RenderBytes([]byte(text), "markdown", ""))
+	return template.HTML(helpers.RenderBytes(helpers.RenderingContext{Content: []byte(text), PageFmt: "markdown"}))
 }
 
 func refPage(page interface{}, ref, methodName string) template.HTML {