Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TODO list support for Blackfriday #2296

Merged
merged 6 commits into from Sep 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 49 additions & 0 deletions 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>
```
2 changes: 1 addition & 1 deletion docs/content/content/summaries.md
Expand Up @@ -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
---
Expand Down
16 changes: 14 additions & 2 deletions 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
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 2 additions & 0 deletions helpers/content.go
Expand Up @@ -51,6 +51,7 @@ type Blackfriday struct {
HrefTargetBlank bool
SmartDashes bool
LatexDashes bool
TaskLists bool
PlainIDAnchors bool
SourceRelativeLinksEval bool
SourceRelativeLinksProjectFolder string
Expand All @@ -68,6 +69,7 @@ func NewBlackfriday(c ConfigProvider) *Blackfriday {
"smartDashes": true,
"latexDashes": true,
"plainIDAnchors": true,
"taskLists": true,
"sourceRelativeLinks": false,
"sourceRelativeLinksProjectFolder": "/docs/content",
}
Expand Down
38 changes: 38 additions & 0 deletions helpers/content_renderer.go
Expand Up @@ -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 {
Expand Down
41 changes: 41 additions & 0 deletions helpers/content_renderer_test.go
Expand Up @@ -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)
}
}
}