diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2016-09-09 13:08:20 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-09 13:08:20 +0200 |
commit | eaf2f9bce5537a1dcbdb32dc62b9827e5a99585b (patch) | |
tree | 1ba3b7e24d8e5a68575e324be1a28471b050f48b | |
parent | 76bf2dcdd23f4cedb425f66503916a58698986dd (diff) |
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
-rw-r--r-- | docs/content/content/markdown-extras.md | 49 | ||||
-rw-r--r-- | docs/content/content/summaries.md | 2 | ||||
-rw-r--r-- | docs/content/overview/configuration.md | 16 | ||||
-rw-r--r-- | helpers/content.go | 2 | ||||
-rw-r--r-- | helpers/content_renderer.go | 38 | ||||
-rw-r--r-- | helpers/content_renderer_test.go | 41 |
6 files changed, 145 insertions, 3 deletions
diff --git a/docs/content/content/markdown-extras.md b/docs/content/content/markdown-extras.md new file mode 100644 index 000000000..ef7f57f31 --- /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 + +<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> +``` diff --git a/docs/content/content/summaries.md b/docs/content/content/summaries.md index 208bb96e5..6353f4c25 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 8127c5823..849e4ed45 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 </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> diff --git a/helpers/content.go b/helpers/content.go index 49d3469c5..53176de64 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 02a9e9c83..6bd2212e1 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(`<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 { diff --git a/helpers/content_renderer_test.go b/helpers/content_renderer_test.go index f96cf0ad5..7baaadb20 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, `<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) + } + } +} |