mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Reuse the BlackFriday instance when possible
This is in heavy use in rendering, so this makes a difference: ```bash benchmark old ns/op new ns/op delta BenchmarkSiteBuilding/TOML,num_langs=1,num_pages=500,tags_per_page=5,shortcodes,render-4 124551144 107743429 -13.49% benchmark old allocs new allocs delta BenchmarkSiteBuilding/TOML,num_langs=1,num_pages=500,tags_per_page=5,shortcodes,render-4 528684 435118 -17.70% benchmark old bytes new bytes delta BenchmarkSiteBuilding/TOML,num_langs=1,num_pages=500,tags_per_page=5,shortcodes,render-4 53306848 45147832 -15.31% ```
This commit is contained in:
parent
2511498608
commit
db4b7a5c67
6 changed files with 36 additions and 33 deletions
|
@ -41,7 +41,7 @@ var SummaryDivider = []byte("<!--more-->")
|
||||||
|
|
||||||
// ContentSpec provides functionality to render markdown content.
|
// ContentSpec provides functionality to render markdown content.
|
||||||
type ContentSpec struct {
|
type ContentSpec struct {
|
||||||
blackfriday map[string]interface{}
|
BlackFriday *BlackFriday
|
||||||
footnoteAnchorPrefix string
|
footnoteAnchorPrefix string
|
||||||
footnoteReturnLinkContents string
|
footnoteReturnLinkContents string
|
||||||
// SummaryLength is the length of the summary that Hugo extracts from a content.
|
// SummaryLength is the length of the summary that Hugo extracts from a content.
|
||||||
|
@ -56,8 +56,9 @@ type ContentSpec struct {
|
||||||
// NewContentSpec returns a ContentSpec initialized
|
// NewContentSpec returns a ContentSpec initialized
|
||||||
// with the appropriate fields from the given config.Provider.
|
// with the appropriate fields from the given config.Provider.
|
||||||
func NewContentSpec(cfg config.Provider) (*ContentSpec, error) {
|
func NewContentSpec(cfg config.Provider) (*ContentSpec, error) {
|
||||||
|
bf := newBlackfriday(cfg.GetStringMap("blackfriday"))
|
||||||
spec := &ContentSpec{
|
spec := &ContentSpec{
|
||||||
blackfriday: cfg.GetStringMap("blackfriday"),
|
BlackFriday: bf,
|
||||||
footnoteAnchorPrefix: cfg.GetString("footnoteAnchorPrefix"),
|
footnoteAnchorPrefix: cfg.GetString("footnoteAnchorPrefix"),
|
||||||
footnoteReturnLinkContents: cfg.GetString("footnoteReturnLinkContents"),
|
footnoteReturnLinkContents: cfg.GetString("footnoteReturnLinkContents"),
|
||||||
summaryLength: cfg.GetInt("summaryLength"),
|
summaryLength: cfg.GetInt("summaryLength"),
|
||||||
|
@ -93,8 +94,8 @@ func NewContentSpec(cfg config.Provider) (*ContentSpec, error) {
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blackfriday holds configuration values for Blackfriday rendering.
|
// BlackFriday holds configuration values for BlackFriday rendering.
|
||||||
type Blackfriday struct {
|
type BlackFriday struct {
|
||||||
Smartypants bool
|
Smartypants bool
|
||||||
SmartypantsQuotesNBSP bool
|
SmartypantsQuotesNBSP bool
|
||||||
AngledQuotes bool
|
AngledQuotes bool
|
||||||
|
@ -109,7 +110,7 @@ type Blackfriday struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
|
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
|
||||||
func (c ContentSpec) NewBlackfriday() *Blackfriday {
|
func newBlackfriday(config map[string]interface{}) *BlackFriday {
|
||||||
defaultParam := map[string]interface{}{
|
defaultParam := map[string]interface{}{
|
||||||
"smartypants": true,
|
"smartypants": true,
|
||||||
"angledQuotes": false,
|
"angledQuotes": false,
|
||||||
|
@ -130,13 +131,13 @@ func (c ContentSpec) NewBlackfriday() *Blackfriday {
|
||||||
siteConfig[k] = v
|
siteConfig[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.blackfriday != nil {
|
if config != nil {
|
||||||
for k, v := range c.blackfriday {
|
for k, v := range config {
|
||||||
siteConfig[k] = v
|
siteConfig[k] = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
combinedConfig := &Blackfriday{}
|
combinedConfig := &BlackFriday{}
|
||||||
if err := mapstructure.Decode(siteConfig, combinedConfig); err != nil {
|
if err := mapstructure.Decode(siteConfig, combinedConfig); err != nil {
|
||||||
jww.FATAL.Printf("Failed to get site rendering config\n%s", err.Error())
|
jww.FATAL.Printf("Failed to get site rendering config\n%s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -434,7 +435,7 @@ type RenderingContext struct {
|
||||||
PageFmt string
|
PageFmt string
|
||||||
DocumentID string
|
DocumentID string
|
||||||
DocumentName string
|
DocumentName string
|
||||||
Config *Blackfriday
|
Config *BlackFriday
|
||||||
RenderTOC bool
|
RenderTOC bool
|
||||||
Cfg config.Provider
|
Cfg config.Provider
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
|
|
||||||
// Renders a codeblock using Blackfriday
|
// Renders a codeblock using Blackfriday
|
||||||
func (c ContentSpec) render(input string) string {
|
func (c ContentSpec) render(input string) string {
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
render := c.getHTMLRenderer(0, ctx)
|
render := c.getHTMLRenderer(0, ctx)
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
@ -34,7 +34,7 @@ func (c ContentSpec) render(input string) string {
|
||||||
|
|
||||||
// Renders a codeblock using Mmark
|
// Renders a codeblock using Mmark
|
||||||
func (c ContentSpec) renderWithMmark(input string) string {
|
func (c ContentSpec) renderWithMmark(input string) string {
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
render := c.getMmarkHTMLRenderer(0, ctx)
|
render := c.getMmarkHTMLRenderer(0, ctx)
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
@ -128,7 +128,7 @@ END`, true, `<ul class="task-list">
|
||||||
<p>END</p>
|
<p>END</p>
|
||||||
`},
|
`},
|
||||||
} {
|
} {
|
||||||
blackFridayConfig := c.NewBlackfriday()
|
blackFridayConfig := c.BlackFriday
|
||||||
blackFridayConfig.TaskLists = this.taskListEnabled
|
blackFridayConfig.TaskLists = this.taskListEnabled
|
||||||
ctx := &RenderingContext{Content: []byte(this.markdown), PageFmt: "markdown", Config: blackFridayConfig}
|
ctx := &RenderingContext{Content: []byte(this.markdown), PageFmt: "markdown", Config: blackFridayConfig}
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,7 @@ func TestTruncateWordsByRune(t *testing.T) {
|
||||||
|
|
||||||
func TestGetHTMLRendererFlags(t *testing.T) {
|
func TestGetHTMLRendererFlags(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
renderer := c.getHTMLRenderer(blackfriday.HTML_USE_XHTML, ctx)
|
renderer := c.getHTMLRenderer(blackfriday.HTML_USE_XHTML, ctx)
|
||||||
flags := renderer.GetFlags()
|
flags := renderer.GetFlags()
|
||||||
if flags&blackfriday.HTML_USE_XHTML != blackfriday.HTML_USE_XHTML {
|
if flags&blackfriday.HTML_USE_XHTML != blackfriday.HTML_USE_XHTML {
|
||||||
|
@ -186,7 +186,7 @@ func TestGetHTMLRendererAllFlags(t *testing.T) {
|
||||||
{blackfriday.HTML_SMARTYPANTS_LATEX_DASHES},
|
{blackfriday.HTML_SMARTYPANTS_LATEX_DASHES},
|
||||||
}
|
}
|
||||||
defaultFlags := blackfriday.HTML_USE_XHTML
|
defaultFlags := blackfriday.HTML_USE_XHTML
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Config.AngledQuotes = true
|
ctx.Config.AngledQuotes = true
|
||||||
ctx.Config.Fractions = true
|
ctx.Config.Fractions = true
|
||||||
ctx.Config.HrefTargetBlank = true
|
ctx.Config.HrefTargetBlank = true
|
||||||
|
@ -209,7 +209,7 @@ func TestGetHTMLRendererAllFlags(t *testing.T) {
|
||||||
|
|
||||||
func TestGetHTMLRendererAnchors(t *testing.T) {
|
func TestGetHTMLRendererAnchors(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.DocumentID = "testid"
|
ctx.DocumentID = "testid"
|
||||||
ctx.Config.PlainIDAnchors = false
|
ctx.Config.PlainIDAnchors = false
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ func TestGetHTMLRendererAnchors(t *testing.T) {
|
||||||
|
|
||||||
func TestGetMmarkHTMLRenderer(t *testing.T) {
|
func TestGetMmarkHTMLRenderer(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.DocumentID = "testid"
|
ctx.DocumentID = "testid"
|
||||||
ctx.Config.PlainIDAnchors = false
|
ctx.Config.PlainIDAnchors = false
|
||||||
actualRenderer := c.getMmarkHTMLRenderer(0, ctx)
|
actualRenderer := c.getMmarkHTMLRenderer(0, ctx)
|
||||||
|
@ -257,7 +257,7 @@ func TestGetMmarkHTMLRenderer(t *testing.T) {
|
||||||
|
|
||||||
func TestGetMarkdownExtensionsMasksAreRemovedFromExtensions(t *testing.T) {
|
func TestGetMarkdownExtensionsMasksAreRemovedFromExtensions(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Config.Extensions = []string{"headerId"}
|
ctx.Config.Extensions = []string{"headerId"}
|
||||||
ctx.Config.ExtensionsMask = []string{"noIntraEmphasis"}
|
ctx.Config.ExtensionsMask = []string{"noIntraEmphasis"}
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ func TestGetMarkdownExtensionsByDefaultAllExtensionsAreEnabled(t *testing.T) {
|
||||||
testFlag int
|
testFlag int
|
||||||
}
|
}
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Config.Extensions = []string{""}
|
ctx.Config.Extensions = []string{""}
|
||||||
ctx.Config.ExtensionsMask = []string{""}
|
ctx.Config.ExtensionsMask = []string{""}
|
||||||
allExtensions := []data{
|
allExtensions := []data{
|
||||||
|
@ -304,7 +304,7 @@ func TestGetMarkdownExtensionsByDefaultAllExtensionsAreEnabled(t *testing.T) {
|
||||||
|
|
||||||
func TestGetMarkdownExtensionsAddingFlagsThroughRenderingContext(t *testing.T) {
|
func TestGetMarkdownExtensionsAddingFlagsThroughRenderingContext(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Config.Extensions = []string{"definitionLists"}
|
ctx.Config.Extensions = []string{"definitionLists"}
|
||||||
ctx.Config.ExtensionsMask = []string{""}
|
ctx.Config.ExtensionsMask = []string{""}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ func TestGetMarkdownExtensionsAddingFlagsThroughRenderingContext(t *testing.T) {
|
||||||
|
|
||||||
func TestGetMarkdownRenderer(t *testing.T) {
|
func TestGetMarkdownRenderer(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Content = []byte("testContent")
|
ctx.Content = []byte("testContent")
|
||||||
actualRenderedMarkdown := c.markdownRender(ctx)
|
actualRenderedMarkdown := c.markdownRender(ctx)
|
||||||
expectedRenderedMarkdown := []byte("<p>testContent</p>\n")
|
expectedRenderedMarkdown := []byte("<p>testContent</p>\n")
|
||||||
|
@ -327,7 +327,7 @@ func TestGetMarkdownRenderer(t *testing.T) {
|
||||||
|
|
||||||
func TestGetMarkdownRendererWithTOC(t *testing.T) {
|
func TestGetMarkdownRendererWithTOC(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{RenderTOC: true, Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{RenderTOC: true, Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Content = []byte("testContent")
|
ctx.Content = []byte("testContent")
|
||||||
actualRenderedMarkdown := c.markdownRender(ctx)
|
actualRenderedMarkdown := c.markdownRender(ctx)
|
||||||
expectedRenderedMarkdown := []byte("<nav>\n</nav>\n\n<p>testContent</p>\n")
|
expectedRenderedMarkdown := []byte("<nav>\n</nav>\n\n<p>testContent</p>\n")
|
||||||
|
@ -342,7 +342,7 @@ func TestGetMmarkExtensions(t *testing.T) {
|
||||||
testFlag int
|
testFlag int
|
||||||
}
|
}
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Config.Extensions = []string{"tables"}
|
ctx.Config.Extensions = []string{"tables"}
|
||||||
ctx.Config.ExtensionsMask = []string{""}
|
ctx.Config.ExtensionsMask = []string{""}
|
||||||
allExtensions := []data{
|
allExtensions := []data{
|
||||||
|
@ -371,7 +371,7 @@ func TestGetMmarkExtensions(t *testing.T) {
|
||||||
|
|
||||||
func TestMmarkRender(t *testing.T) {
|
func TestMmarkRender(t *testing.T) {
|
||||||
c := newTestContentSpec()
|
c := newTestContentSpec()
|
||||||
ctx := &RenderingContext{Cfg: c.cfg, Config: c.NewBlackfriday()}
|
ctx := &RenderingContext{Cfg: c.cfg, Config: c.BlackFriday}
|
||||||
ctx.Content = []byte("testContent")
|
ctx.Content = []byte("testContent")
|
||||||
actualRenderedMarkdown := c.mmarkRender(ctx)
|
actualRenderedMarkdown := c.mmarkRender(ctx)
|
||||||
expectedRenderedMarkdown := []byte("<p>testContent</p>\n")
|
expectedRenderedMarkdown := []byte("<p>testContent</p>\n")
|
||||||
|
|
|
@ -210,7 +210,7 @@ func loadDefaultSettingsFor(v *viper.Viper) error {
|
||||||
v.SetDefault("paginate", 10)
|
v.SetDefault("paginate", 10)
|
||||||
v.SetDefault("paginatePath", "page")
|
v.SetDefault("paginatePath", "page")
|
||||||
v.SetDefault("summaryLength", 70)
|
v.SetDefault("summaryLength", 70)
|
||||||
v.SetDefault("blackfriday", c.NewBlackfriday())
|
v.SetDefault("blackfriday", c.BlackFriday)
|
||||||
v.SetDefault("rSSUri", "index.xml")
|
v.SetDefault("rSSUri", "index.xml")
|
||||||
v.SetDefault("rssLimit", -1)
|
v.SetDefault("rssLimit", -1)
|
||||||
v.SetDefault("sectionPagesMenu", "")
|
v.SetDefault("sectionPagesMenu", "")
|
||||||
|
|
|
@ -168,7 +168,7 @@ type Page struct {
|
||||||
plainWords []string
|
plainWords []string
|
||||||
|
|
||||||
// rendering configuration
|
// rendering configuration
|
||||||
renderingConfig *helpers.Blackfriday
|
renderingConfig *helpers.BlackFriday
|
||||||
|
|
||||||
// menus
|
// menus
|
||||||
pageMenus PageMenus
|
pageMenus PageMenus
|
||||||
|
@ -700,19 +700,21 @@ func (p *Page) renderContent(content []byte) []byte {
|
||||||
Config: p.getRenderingConfig()})
|
Config: p.getRenderingConfig()})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Page) getRenderingConfig() *helpers.Blackfriday {
|
func (p *Page) getRenderingConfig() *helpers.BlackFriday {
|
||||||
p.renderingConfigInit.Do(func() {
|
p.renderingConfigInit.Do(func() {
|
||||||
p.renderingConfig = p.s.ContentSpec.NewBlackfriday()
|
bfParam := p.GetParam("blackfriday")
|
||||||
|
if bfParam == nil {
|
||||||
|
p.renderingConfig = p.s.ContentSpec.BlackFriday
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Create a copy so we can modify it.
|
||||||
|
bf := *p.s.ContentSpec.BlackFriday
|
||||||
|
p.renderingConfig = &bf
|
||||||
|
|
||||||
if p.Language() == nil {
|
if p.Language() == nil {
|
||||||
panic(fmt.Sprintf("nil language for %s with source lang %s", p.BaseFileName(), p.lang))
|
panic(fmt.Sprintf("nil language for %s with source lang %s", p.BaseFileName(), p.lang))
|
||||||
}
|
}
|
||||||
|
|
||||||
bfParam := p.GetParam("blackfriday")
|
|
||||||
if bfParam == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pageParam := cast.ToStringMap(bfParam)
|
pageParam := cast.ToStringMap(bfParam)
|
||||||
if err := mapstructure.Decode(pageParam, &p.renderingConfig); err != nil {
|
if err := mapstructure.Decode(pageParam, &p.renderingConfig); err != nil {
|
||||||
p.s.Log.FATAL.Printf("Failed to get rendering config for %s:\n%s", p.BaseFileName(), err.Error())
|
p.s.Log.FATAL.Printf("Failed to get rendering config for %s:\n%s", p.BaseFileName(), err.Error())
|
||||||
|
|
|
@ -98,7 +98,7 @@ func (ns *Namespace) Markdownify(s interface{}) (template.HTML, error) {
|
||||||
Cfg: ns.deps.Cfg,
|
Cfg: ns.deps.Cfg,
|
||||||
Content: []byte(ss),
|
Content: []byte(ss),
|
||||||
PageFmt: "markdown",
|
PageFmt: "markdown",
|
||||||
Config: ns.deps.ContentSpec.NewBlackfriday(),
|
Config: ns.deps.ContentSpec.BlackFriday,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue