diff --git a/docs/content/content/markdown-extras.md b/docs/content/content/markdown-extras.md new file mode 100644 index 00000000000..ef7f57f31c0 --- /dev/null +++ b/docs/content/content/markdown-extras.md @@ -0,0 +1,49 @@ +--- +aliases: +- /doc/supported-formats/ +lastmod: 2016-07-22 +date: 2016-07-22 +menu: + main: + parent: content +prev: /content/summaries +next: /content/example +title: Markdown Extras +weight: 66 +toc: false +--- + +Hugo provides some convenient markdown extensions. + +## Task lists + +Hugo supports GitHub styled task lists (TODO lists) for the Blackfriday renderer (md-files). See [Blackfriday config](/overview/configuration/#configure-blackfriday-rendering) for how to turn it off. + +Example: + +```markdown +- [ ] a task list item +- [ ] list syntax required +- [ ] incomplete +- [x] completed +``` + +Renders as: + +- [ ] a task list item +- [ ] list syntax required +- [ ] incomplete +- [x] completed + + +And produces this HTML: + +```html + + +``` diff --git a/docs/content/content/summaries.md b/docs/content/content/summaries.md index 208bb96e588..6353f4c2529 100644 --- a/docs/content/content/summaries.md +++ b/docs/content/content/summaries.md @@ -4,9 +4,9 @@ date: 2013-07-01 menu: main: parent: content -next: /content/example notoc: true prev: /content/ordering +next: /content/markdown-extras title: Summaries weight: 65 --- diff --git a/docs/content/overview/configuration.md b/docs/content/overview/configuration.md index 8127c5823ce..849e4ed45df 100644 --- a/docs/content/overview/configuration.md +++ b/docs/content/overview/configuration.md @@ -1,14 +1,14 @@ --- aliases: - /doc/configuration/ -lastmod: 2015-12-08 +lastmod: 2016-07-22 date: 2013-07-01 linktitle: Configuration menu: main: parent: getting started next: /overview/source-directory -notoc: true +toc: true prev: /overview/usage title: Configuring Hugo weight: 40 @@ -195,6 +195,18 @@ But Hugo does expose some options---as listed in the table below, matched with t + + +taskLists +true + + + +Purpose: +Turn off GitHub styled automatic task/TODO list generation. + + + smartypants true diff --git a/helpers/content.go b/helpers/content.go index 49d3469c58e..53176de64da 100644 --- a/helpers/content.go +++ b/helpers/content.go @@ -51,6 +51,7 @@ type Blackfriday struct { HrefTargetBlank bool SmartDashes bool LatexDashes bool + TaskLists bool PlainIDAnchors bool SourceRelativeLinksEval bool SourceRelativeLinksProjectFolder string @@ -68,6 +69,7 @@ func NewBlackfriday(c ConfigProvider) *Blackfriday { "smartDashes": true, "latexDashes": true, "plainIDAnchors": true, + "taskLists": true, "sourceRelativeLinks": false, "sourceRelativeLinksProjectFolder": "/docs/content", } diff --git a/helpers/content_renderer.go b/helpers/content_renderer.go index 60ed46e7371..1cec1753906 100644 --- a/helpers/content_renderer.go +++ b/helpers/content_renderer.go @@ -72,6 +72,44 @@ func (renderer *HugoHTMLRenderer) Image(out *bytes.Buffer, link []byte, title [] } } +// ListItem adds task list support to the Blackfriday renderer. +func (renderer *HugoHTMLRenderer) ListItem(out *bytes.Buffer, text []byte, flags int) { + if !renderer.Config.TaskLists { + renderer.Renderer.ListItem(out, text, flags) + return + } + + switch { + case bytes.HasPrefix(text, []byte("[ ] ")): + text = append([]byte(``), text[3:]...) + + case bytes.HasPrefix(text, []byte("[x] ")) || bytes.HasPrefix(text, []byte("[X] ")): + text = append([]byte(``), text[3:]...) + } + + renderer.Renderer.ListItem(out, text, flags) +} + +// List adds task list support to the Blackfriday renderer. +func (renderer *HugoHTMLRenderer) List(out *bytes.Buffer, text func() bool, flags int) { + if !renderer.Config.TaskLists { + renderer.Renderer.List(out, text, flags) + return + } + marker := out.Len() + renderer.Renderer.List(out, text, flags) + if out.Len() > marker { + list := out.Bytes()[marker:] + if bytes.Contains(list, []byte("task-list-item")) { + // Rewrite the buffer from the marker + out.Truncate(marker) + // May be either dl, ul or ol + list := append(list[:4], append([]byte(` class="task-list"`), list[4:]...)...) + out.Write(list) + } + } +} + // HugoMmarkHTMLRenderer wraps a mmark.Renderer, typically a mmark.html // Enabling Hugo to customise the rendering experience type HugoMmarkHTMLRenderer struct { diff --git a/helpers/content_renderer_test.go b/helpers/content_renderer_test.go index f96cf0ad564..7baaadb20f4 100644 --- a/helpers/content_renderer_test.go +++ b/helpers/content_renderer_test.go @@ -88,3 +88,44 @@ func TestCodeFence(t *testing.T) { } } } + +func TestBlackfridayTaskList(t *testing.T) { + for i, this := range []struct { + markdown string + taskListEnabled bool + expect string + }{ + {` +TODO: + +- [x] On1 +- [X] On2 +- [ ] Off + +END +`, true, `

TODO:

+ + + +

END

+`}, + {`- [x] On1`, false, ` +`}, + } { + blackFridayConfig := NewBlackfriday(viper.GetViper()) + blackFridayConfig.TaskLists = this.taskListEnabled + ctx := &RenderingContext{Content: []byte(this.markdown), PageFmt: "markdown", Config: blackFridayConfig} + + result := string(RenderBytes(ctx)) + + if result != this.expect { + t.Errorf("[%d] got \n%v but expected \n%v", i, result, this.expect) + } + } +}