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)
+ }
+ }
+}