Skip to content

Commit da821a9

Browse files
jhollingworthclehner
authored andcommitted
Github Task Lists
Add support for Github Task Lists under the gfm flag. Changes to API * list(*string* body, *boolean* ordered, *boolean* taskList) * listitem(*string* text, [*boolean* checked]). `checked` is defined when you have a list item which starts with `[ ] ` or `[x] `.If defined its a boolean depending on whether the `x` is present. When checked is defined we add a input type type `checkbox` to the list item and add the class `task-list-item-checkbox`. `taskList` is true if a list has any list items where `checked` is defined. When true we add the class `task-list` to the list. Resolves markedjs#107
1 parent 75f22af commit da821a9

File tree

4 files changed

+60
-11
lines changed

4 files changed

+60
-11
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ This code will output the following HTML:
188188
- html(*string* html)
189189
- heading(*string* text, *number* level)
190190
- hr()
191-
- list(*string* body, *boolean* ordered)
191+
- list(*string* body, *boolean* ordered, *boolean* taskList)
192+
- `taskList` true when `gfm` is `true` and there is a list item with a check box
192193
- listitem(*string* text)
193194
- paragraph(*string* text)
194195
- table(*string* header, *string* body)
@@ -211,7 +212,8 @@ This code will output the following HTML:
211212
- codespan(*string* code)
212213
- br()
213214
- del(*string* text)
214-
- link(*string* href, *string* title, *string* text)
215+
- link(*string* href, *string* title, *string* text, [*boolean* checked]).
216+
- `checked` only defined when `gfm` is `true` and there is a check box at the start of the list item (e.g. `* [ ] foo`).
215217
- image(*string* href, *string* title, *string* text)
216218

217219
### gfm

lib/marked.js

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ var block = {
2727
text: /^[^\n]+/
2828
};
2929

30+
block.checkbox = /^\[([ x])\] +/;
3031
block.bullet = /(?:[*+-]|\d+\.)/;
3132
block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
3233
block.item = replace(block.item, 'gm')
@@ -156,7 +157,8 @@ Lexer.prototype.token = function(src, top, bq) {
156157
, item
157158
, space
158159
, i
159-
, l;
160+
, l
161+
, checked;
160162

161163
while (src) {
162164
// newline
@@ -303,6 +305,17 @@ Lexer.prototype.token = function(src, top, bq) {
303305
space = item.length;
304306
item = item.replace(/^ *([*+-]|\d+\.) +/, '');
305307

308+
if (this.options.gfm) {
309+
checked = block.checkbox.exec(item);
310+
311+
if (checked) {
312+
checked = checked[1] === 'x';
313+
item = item.replace(block.checkbox, '');
314+
} else {
315+
checked = undefined;
316+
}
317+
}
318+
306319
// Outdent whatever the
307320
// list item contains. Hacky.
308321
if (~item.indexOf('\n ')) {
@@ -332,6 +345,7 @@ Lexer.prototype.token = function(src, top, bq) {
332345
}
333346

334347
this.tokens.push({
348+
checked: checked,
335349
type: loose
336350
? 'loose_item_start'
337351
: 'list_item_start'
@@ -878,13 +892,23 @@ Renderer.prototype.hr = function() {
878892
return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
879893
};
880894

881-
Renderer.prototype.list = function(body, ordered) {
895+
Renderer.prototype.list = function(body, ordered, taskList) {
882896
var type = ordered ? 'ol' : 'ul';
883-
return '<' + type + '>\n' + body + '</' + type + '>\n';
897+
var classes = taskList ? ' class="task-list"' : '';
898+
return '<' + type + classes + '>\n' + body + '</' + type + '>\n';
884899
};
885900

886-
Renderer.prototype.listitem = function(text) {
887-
return '<li>' + text + '</li>\n';
901+
Renderer.prototype.listitem = function(text, checked) {
902+
if (checked === undefined) {
903+
return '<li>' + text + '</li>\n';
904+
}
905+
906+
return '<li class="task-list-item">'
907+
+ '<input type="checkbox" class="task-list-item-checkbox"'
908+
+ (checked ? ' checked' : '')
909+
+ '> '
910+
+ text
911+
+ '</li>\n';
888912
};
889913

890914
Renderer.prototype.paragraph = function(text) {
@@ -1108,24 +1132,30 @@ Parser.prototype.tok = function() {
11081132
}
11091133
case 'list_start': {
11101134
var body = ''
1135+
, taskList = false
11111136
, ordered = this.token.ordered;
11121137

11131138
while (this.next().type !== 'list_end') {
1139+
if (this.token.checked !== undefined) {
1140+
taskList = true;
1141+
}
1142+
11141143
body += this.tok();
11151144
}
11161145

1117-
return this.renderer.list(body, ordered);
1146+
return this.renderer.list(body, ordered, taskList);
11181147
}
11191148
case 'list_item_start': {
1120-
var body = '';
1149+
var body = ''
1150+
, checked = this.token.checked;
11211151

11221152
while (this.next().type !== 'list_item_end') {
11231153
body += this.token.type === 'text'
11241154
? this.parseText()
11251155
: this.tok();
11261156
}
11271157

1128-
return this.renderer.listitem(body);
1158+
return this.renderer.listitem(body, checked);
11291159
}
11301160
case 'loose_item_start': {
11311161
var body = '';
@@ -1134,7 +1164,7 @@ Parser.prototype.tok = function() {
11341164
body += this.tok();
11351165
}
11361166

1137-
return this.renderer.listitem(body);
1167+
return this.renderer.listitem(body, checked);
11381168
}
11391169
case 'html': {
11401170
var html = !this.token.pre && !this.options.pedantic

test/tests/gfm_task_list.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<ul class="task-list">
2+
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox"> foo</li>
3+
<li>bar</li>
4+
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox" checked> baz</li>
5+
<li>[] bam
6+
<ul class="task-list">
7+
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox"> bim</li>
8+
<li class="task-list-item"><input type="checkbox" class="task-list-item-checkbox"> lim</li>
9+
</ul>
10+
</li>
11+
</ul>

test/tests/gfm_task_list.text

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
* [ ] foo
2+
* bar
3+
* [x] baz
4+
* [] bam
5+
* [ ] bim
6+
* [ ] lim

0 commit comments

Comments
 (0)