mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 06:42:08 -05:00
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
This commit is contained in:
parent
76bf2dcdd2
commit
eaf2f9bce5
6 changed files with 145 additions and 3 deletions
49
docs/content/content/markdown-extras.md
Normal file
49
docs/content/content/markdown-extras.md
Normal file
|
@ -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>
|
||||||
|
```
|
|
@ -4,9 +4,9 @@ date: 2013-07-01
|
||||||
menu:
|
menu:
|
||||||
main:
|
main:
|
||||||
parent: content
|
parent: content
|
||||||
next: /content/example
|
|
||||||
notoc: true
|
notoc: true
|
||||||
prev: /content/ordering
|
prev: /content/ordering
|
||||||
|
next: /content/markdown-extras
|
||||||
title: Summaries
|
title: Summaries
|
||||||
weight: 65
|
weight: 65
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
---
|
---
|
||||||
aliases:
|
aliases:
|
||||||
- /doc/configuration/
|
- /doc/configuration/
|
||||||
lastmod: 2015-12-08
|
lastmod: 2016-07-22
|
||||||
date: 2013-07-01
|
date: 2013-07-01
|
||||||
linktitle: Configuration
|
linktitle: Configuration
|
||||||
menu:
|
menu:
|
||||||
main:
|
main:
|
||||||
parent: getting started
|
parent: getting started
|
||||||
next: /overview/source-directory
|
next: /overview/source-directory
|
||||||
notoc: true
|
toc: true
|
||||||
prev: /overview/usage
|
prev: /overview/usage
|
||||||
title: Configuring Hugo
|
title: Configuring Hugo
|
||||||
weight: 40
|
weight: 40
|
||||||
|
@ -195,6 +195,18 @@ But Hugo does expose some options---as listed in the table below, matched with t
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<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>
|
<tr>
|
||||||
<td><code><strong>smartypants</strong></code></td>
|
<td><code><strong>smartypants</strong></code></td>
|
||||||
<td><code>true</code></td>
|
<td><code>true</code></td>
|
||||||
|
|
|
@ -51,6 +51,7 @@ type Blackfriday struct {
|
||||||
HrefTargetBlank bool
|
HrefTargetBlank bool
|
||||||
SmartDashes bool
|
SmartDashes bool
|
||||||
LatexDashes bool
|
LatexDashes bool
|
||||||
|
TaskLists bool
|
||||||
PlainIDAnchors bool
|
PlainIDAnchors bool
|
||||||
SourceRelativeLinksEval bool
|
SourceRelativeLinksEval bool
|
||||||
SourceRelativeLinksProjectFolder string
|
SourceRelativeLinksProjectFolder string
|
||||||
|
@ -68,6 +69,7 @@ func NewBlackfriday(c ConfigProvider) *Blackfriday {
|
||||||
"smartDashes": true,
|
"smartDashes": true,
|
||||||
"latexDashes": true,
|
"latexDashes": true,
|
||||||
"plainIDAnchors": true,
|
"plainIDAnchors": true,
|
||||||
|
"taskLists": true,
|
||||||
"sourceRelativeLinks": false,
|
"sourceRelativeLinks": false,
|
||||||
"sourceRelativeLinksProjectFolder": "/docs/content",
|
"sourceRelativeLinksProjectFolder": "/docs/content",
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// HugoMmarkHTMLRenderer wraps a mmark.Renderer, typically a mmark.html
|
||||||
// Enabling Hugo to customise the rendering experience
|
// Enabling Hugo to customise the rendering experience
|
||||||
type HugoMmarkHTMLRenderer struct {
|
type HugoMmarkHTMLRenderer struct {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue