shithub: hugo

Download patch

ref: eaf2f9bce5537a1dcbdb32dc62b9827e5a99585b
parent: 76bf2dcdd23f4cedb425f66503916a58698986dd
author: Bjørn Erik Pedersen <[email protected]>
date: Fri Sep 9 09:08:20 EDT 2016

Add TODO list support for Blackfriday

* Add CSS class to TODO list and list items
* Add a flag to turn task list support off

Fixes #2269


--- /dev/null
+++ b/docs/content/content/markdown-extras.md
@@ -1,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
+
+<ul class="task-list">
+<li><input type="checkbox" disabled="" class="task-list-item"> a task list item</li>
+<li><input type="checkbox" disabled="" class="task-list-item"> list syntax required</li>
+<li><input type="checkbox" disabled="" class="task-list-item"> incomplete</li>
+<li><input type="checkbox" checked="" disabled="" class="task-list-item"> completed</li>
+</ul>
+```
--- a/docs/content/content/summaries.md
+++ b/docs/content/content/summaries.md
@@ -4,9 +4,9 @@
 menu:
   main:
     parent: content
-next: /content/example
 notoc: true
 prev: /content/ordering
+next: /content/markdown-extras
 title: Summaries
 weight: 65
 ---
--- a/docs/content/overview/configuration.md
+++ b/docs/content/overview/configuration.md
@@ -1,7 +1,7 @@
 ---
 aliases:
 - /doc/configuration/
-lastmod: 2015-12-08
+lastmod: 2016-07-22
 date: 2013-07-01
 linktitle: Configuration
 menu:
@@ -8,7 +8,7 @@
   main:
     parent: getting started
 next: /overview/source-directory
-notoc: true
+toc: true
 prev: /overview/usage
 title: Configuring Hugo
 weight: 40
@@ -195,6 +195,18 @@
 </thead>
 
 <tbody>
+
+<tr>
+<td><code><strong>taskLists</strong></code></td>
+<td><code>true</code></td>
+<td><code></code></td>
+</tr>
+<tr>
+<td class="purpose-title">Purpose:</td>
+<td class="purpose-description" colspan="2">Turn off GitHub styled automatic task/TODO list generation.
+</td>
+</tr>
+
 <tr>
 <td><code><strong>smartypants</strong></code></td>
 <td><code>true</code></td>
--- a/helpers/content.go
+++ b/helpers/content.go
@@ -51,6 +51,7 @@
 	HrefTargetBlank                  bool
 	SmartDashes                      bool
 	LatexDashes                      bool
+	TaskLists                        bool
 	PlainIDAnchors                   bool
 	SourceRelativeLinksEval          bool
 	SourceRelativeLinksProjectFolder string
@@ -68,6 +69,7 @@
 		"smartDashes":                      true,
 		"latexDashes":                      true,
 		"plainIDAnchors":                   true,
+		"taskLists":                        true,
 		"sourceRelativeLinks":              false,
 		"sourceRelativeLinksProjectFolder": "/docs/content",
 	}
--- a/helpers/content_renderer.go
+++ b/helpers/content_renderer.go
@@ -72,6 +72,44 @@
 	}
 }
 
+// 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(`<input type="checkbox" disabled class="task-list-item">`), text[3:]...)
+
+	case bytes.HasPrefix(text, []byte("[x] ")) || bytes.HasPrefix(text, []byte("[X] ")):
+		text = append([]byte(`<input type="checkbox" checked disabled class="task-list-item">`), 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 {
--- a/helpers/content_renderer_test.go
+++ b/helpers/content_renderer_test.go
@@ -88,3 +88,44 @@
 		}
 	}
 }
+
+func TestBlackfridayTaskList(t *testing.T) {
+	for i, this := range []struct {
+		markdown        string
+		taskListEnabled bool
+		expect          string
+	}{
+		{`
+TODO:
+
+- [x] On1
+- [X] On2
+- [ ] Off
+
+END
+`, true, `<p>TODO:</p>
+
+<ul class="task-list">
+<li><input type="checkbox" checked disabled class="task-list-item"> On1</li>
+<li><input type="checkbox" checked disabled class="task-list-item"> On2</li>
+<li><input type="checkbox" disabled class="task-list-item"> Off</li>
+</ul>
+
+<p>END</p>
+`},
+		{`- [x] On1`, false, `<ul>
+<li>[x] On1</li>
+</ul>
+`},
+	} {
+		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)
+		}
+	}
+}