deckar01-task_list 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +142 -0
- data/Rakefile +9 -0
- data/app/assets/javascripts/task_list.coffee +237 -0
- data/app/assets/stylesheets/task_list.scss +20 -0
- data/bower.json +28 -0
- data/config.ru +30 -0
- data/lib/task_list.rb +44 -0
- data/lib/task_list/filter.rb +149 -0
- data/lib/task_list/railtie.rb +20 -0
- data/lib/task_list/summary.rb +30 -0
- data/lib/task_list/version.rb +3 -0
- data/script/bootstrap +13 -0
- data/script/cibuild +6 -0
- data/script/testsuite +19 -0
- data/task_list.gemspec +30 -0
- data/test/functional/helpers/remote.coffee +3 -0
- data/test/functional/test_task_lists_behavior.html +103 -0
- data/test/index.html +12 -0
- data/test/run-qunit.coffee +50 -0
- data/test/task_list/filter_test.rb +142 -0
- data/test/task_list/summary_test.rb +40 -0
- data/test/task_list_test.rb +33 -0
- data/test/test_helper.rb +3 -0
- data/test/unit/test_events.coffee +96 -0
- data/test/unit/test_updates.coffee +566 -0
- data/test/units.coffee +2 -0
- data/test/units.css +1 -0
- metadata +227 -0
data/test/index.html
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<link rel="stylesheet" href="/assets/units.css">
|
6
|
+
<script type="text/javascript" src="/assets/units.js"></script>
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<div id="qunit"></div>
|
10
|
+
<div id="qunit-fixture"></div>
|
11
|
+
</body>
|
12
|
+
</html>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
fs = require 'fs'
|
2
|
+
print = (s) -> fs.write "/dev/stderr", s, 'w'
|
3
|
+
|
4
|
+
page = new WebPage()
|
5
|
+
page.onConsoleMessage = (msg) -> console.error msg
|
6
|
+
|
7
|
+
timeoutId = null
|
8
|
+
deferTimeout = ->
|
9
|
+
clearTimeout timeoutId if timeoutId
|
10
|
+
timeoutId = setTimeout ->
|
11
|
+
console.error "Timeout"
|
12
|
+
phantom.exit 1
|
13
|
+
, 3000
|
14
|
+
|
15
|
+
page.open phantom.args[0], ->
|
16
|
+
deferTimeout()
|
17
|
+
|
18
|
+
setInterval ->
|
19
|
+
tests = page.evaluate ->
|
20
|
+
tests = document.getElementById('qunit-tests')?.children
|
21
|
+
return unless tests
|
22
|
+
for test in tests when test.className isnt 'running' and not test.recorded
|
23
|
+
test.recorded = true
|
24
|
+
if test.className is 'pass'
|
25
|
+
'.'
|
26
|
+
else if test.className is 'fail'
|
27
|
+
'F'
|
28
|
+
|
29
|
+
return unless tests
|
30
|
+
for test in tests when test
|
31
|
+
deferTimeout()
|
32
|
+
print test
|
33
|
+
|
34
|
+
result = page.evaluate ->
|
35
|
+
result = document.getElementById('qunit-testresult')
|
36
|
+
tests = document.getElementById('qunit-tests').children
|
37
|
+
|
38
|
+
if result.innerText.match /completed/
|
39
|
+
console.error ""
|
40
|
+
|
41
|
+
for test in tests when test.className is 'fail'
|
42
|
+
console.error test.innerText
|
43
|
+
|
44
|
+
console.error result.innerText
|
45
|
+
return parseInt result.getElementsByClassName('failed')[0].innerText
|
46
|
+
|
47
|
+
return
|
48
|
+
|
49
|
+
phantom.exit result if result?
|
50
|
+
, 100
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path('../../test_helper', __FILE__)
|
3
|
+
require 'task_list/filter'
|
4
|
+
|
5
|
+
class TaskList::FilterTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@pipeline = HTML::Pipeline.new [
|
8
|
+
HTML::Pipeline::MarkdownFilter,
|
9
|
+
TaskList::Filter
|
10
|
+
], {}, {}
|
11
|
+
|
12
|
+
@context = {}
|
13
|
+
@item_selector = "input.task-list-item-checkbox[type=checkbox]"
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_filters_items_in_a_list
|
17
|
+
text = <<-md
|
18
|
+
- [ ] incomplete
|
19
|
+
- [x] complete
|
20
|
+
md
|
21
|
+
assert_equal 2, filter(text)[:output].css(@item_selector).size
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_filters_items_with_HTML_contents
|
25
|
+
text = <<-md
|
26
|
+
- [ ] incomplete **with bold** text
|
27
|
+
- [x] complete __with italic__ text
|
28
|
+
md
|
29
|
+
assert_equal 2, filter(text)[:output].css(@item_selector).size
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_filters_items_in_a_list_wrapped_in_paras
|
33
|
+
# See issue #7951 for details.
|
34
|
+
text = <<-md
|
35
|
+
- [ ] one
|
36
|
+
- [ ] this one will be wrapped in a para
|
37
|
+
|
38
|
+
- [ ] this one too, wtf
|
39
|
+
md
|
40
|
+
assert_equal 3, filter(text)[:output].css(@item_selector).size
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_populates_result_with_task_list_items
|
44
|
+
text = <<-md
|
45
|
+
- [ ] incomplete
|
46
|
+
- [x] complete
|
47
|
+
md
|
48
|
+
|
49
|
+
result = filter(text)
|
50
|
+
assert !result[:task_list_items].empty?
|
51
|
+
incomplete, complete = result[:task_list_items]
|
52
|
+
|
53
|
+
assert incomplete
|
54
|
+
assert !incomplete.complete?
|
55
|
+
|
56
|
+
assert complete
|
57
|
+
assert complete.complete?
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_skips_lists_in_code_blocks
|
61
|
+
code = <<-md
|
62
|
+
```
|
63
|
+
- [ ] incomplete
|
64
|
+
- [x] complete
|
65
|
+
```
|
66
|
+
md
|
67
|
+
|
68
|
+
assert filter(code)[:output].css(@item_selector).empty?,
|
69
|
+
"should not have any task list items"
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_handles_encoding_correctly
|
73
|
+
unicode = "中文"
|
74
|
+
text = <<-md
|
75
|
+
- [ ] #{unicode}
|
76
|
+
md
|
77
|
+
assert item = filter(text)[:output].css('.task-list-item').pop
|
78
|
+
assert_equal unicode, item.text.strip
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_handles_nested_items
|
82
|
+
text = <<-md
|
83
|
+
- [ ] one
|
84
|
+
- [ ] one.one
|
85
|
+
md
|
86
|
+
assert item = filter(text)[:output].css('.task-list-item .task-list-item').pop
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_handles_complicated_nested_items
|
90
|
+
text = <<-md
|
91
|
+
- [ ] one
|
92
|
+
- [ ] one.one
|
93
|
+
- [x] one.two
|
94
|
+
- [ ] one.two.one
|
95
|
+
- [ ] one.two.two
|
96
|
+
- [ ] one.three
|
97
|
+
- [ ] one.four
|
98
|
+
- [ ] two
|
99
|
+
- [x] two.one
|
100
|
+
- [ ] two.two
|
101
|
+
- [ ] three
|
102
|
+
md
|
103
|
+
|
104
|
+
assert_equal 6 + 2, filter(text)[:output].css('.task-list-item .task-list-item').size
|
105
|
+
assert_equal 2, filter(text)[:output].css('.task-list-item .task-list-item .task-list-item').size
|
106
|
+
end
|
107
|
+
|
108
|
+
# NOTE: This is an edge case experienced regularly by users using a Swiss
|
109
|
+
# German keyboard.
|
110
|
+
# See: https://github.com/github/github/pull/18362
|
111
|
+
def test_non_breaking_space_between_brackets
|
112
|
+
text = "- [\xC2\xA0] ok"
|
113
|
+
assert item = filter(text)[:output].css('.task-list-item').pop, "item expected"
|
114
|
+
assert_equal 'ok', item.text.strip
|
115
|
+
end
|
116
|
+
|
117
|
+
# See: https://github.com/github/github/pull/18362
|
118
|
+
def test_non_breaking_space_between_brackets_in_paras
|
119
|
+
text = <<-md
|
120
|
+
- [\xC2\xA0] one
|
121
|
+
- [\xC2\xA0] this one will be wrapped in a para
|
122
|
+
|
123
|
+
- [\xC2\xA0] this one too, wtf
|
124
|
+
md
|
125
|
+
assert_equal 3, filter(text)[:output].css(@item_selector).size
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_capital_X
|
129
|
+
text = <<-md
|
130
|
+
- [x] lower case
|
131
|
+
- [X] capital
|
132
|
+
md
|
133
|
+
assert_equal 2, filter(text)[:output].css("[checked]").size
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
|
138
|
+
def filter(input, context = @context, result = nil)
|
139
|
+
result ||= {}
|
140
|
+
@pipeline.call(input, context, result)
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path('../../test_helper', __FILE__)
|
3
|
+
require 'task_list/summary'
|
4
|
+
|
5
|
+
class TaskList::SummaryTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@complete = make_item "[x]", "complete"
|
8
|
+
@incomplete = make_item "[ ]", "incomplete"
|
9
|
+
@items = [@complete, @incomplete]
|
10
|
+
@summary = make_summary @items
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_no_items
|
14
|
+
summary = make_summary []
|
15
|
+
assert !summary.items?, "no task list items are expected"
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_items
|
19
|
+
assert @summary.items?, "task list items are expected"
|
20
|
+
assert_equal 2, @summary.item_count
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_complete_count
|
24
|
+
assert_equal 1, @summary.complete_count
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_incomplete_count
|
28
|
+
assert_equal 1, @summary.incomplete_count
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def make_item(checkbox_text = "[ ]", source = "an item!")
|
34
|
+
TaskList::Item.new(checkbox_text, source)
|
35
|
+
end
|
36
|
+
|
37
|
+
def make_summary(items)
|
38
|
+
TaskList::Summary.new(items)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path('../test_helper', __FILE__)
|
3
|
+
require 'task_list'
|
4
|
+
require 'task_list/filter'
|
5
|
+
|
6
|
+
class TaskListTest < Minitest::Test
|
7
|
+
class Record < Struct.new(:body)
|
8
|
+
def task_list_items
|
9
|
+
[]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_has_summary
|
14
|
+
assert summary = task_list("- [ ] one").summary, "summary expected"
|
15
|
+
assert_kind_of TaskList::Summary, summary
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_complete_item
|
19
|
+
item = TaskList::Item.new("[x]", "complete")
|
20
|
+
assert item.complete?, "expected to be complete"
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_incomplete_item
|
24
|
+
item = TaskList::Item.new("[ ]", "incomplete")
|
25
|
+
assert !item.complete?, "expected to be incomplete"
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def task_list(text)
|
31
|
+
TaskList.new(Record.new(text))
|
32
|
+
end
|
33
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#= require task_list
|
2
|
+
|
3
|
+
module "TaskList events",
|
4
|
+
setup: ->
|
5
|
+
@container = $ '<div>', class: 'js-task-list-container'
|
6
|
+
|
7
|
+
@list = $ '<ul>', class: 'task-list'
|
8
|
+
@item = $ '<li>', class: 'task-list-item'
|
9
|
+
@checkbox = $ '<input>',
|
10
|
+
type: 'checkbox'
|
11
|
+
class: 'task-list-item-checkbox'
|
12
|
+
disabled: true
|
13
|
+
checked: false
|
14
|
+
|
15
|
+
@field = $ '<textarea>', class: 'js-task-list-field', "- [ ] text"
|
16
|
+
|
17
|
+
@item.append @checkbox
|
18
|
+
@list.append @item
|
19
|
+
@container.append @list
|
20
|
+
|
21
|
+
@container.append @field
|
22
|
+
|
23
|
+
$('#qunit-fixture').append(@container)
|
24
|
+
@container.taskList()
|
25
|
+
|
26
|
+
teardown: ->
|
27
|
+
$(document).off 'tasklist:enabled'
|
28
|
+
$(document).off 'tasklist:disabled'
|
29
|
+
$(document).off 'tasklist:change'
|
30
|
+
$(document).off 'tasklist:changed'
|
31
|
+
|
32
|
+
asyncTest "triggers a tasklist:change event before making task list item changes", ->
|
33
|
+
expect 1
|
34
|
+
|
35
|
+
@field.on 'tasklist:change', (event, index, checked) ->
|
36
|
+
ok true
|
37
|
+
|
38
|
+
setTimeout ->
|
39
|
+
start()
|
40
|
+
, 20
|
41
|
+
|
42
|
+
@checkbox.click()
|
43
|
+
|
44
|
+
asyncTest "triggers a tasklist:changed event once a task list item changes", ->
|
45
|
+
expect 1
|
46
|
+
|
47
|
+
@field.on 'tasklist:changed', (event, index, checked) ->
|
48
|
+
ok true
|
49
|
+
|
50
|
+
setTimeout ->
|
51
|
+
start()
|
52
|
+
, 20
|
53
|
+
|
54
|
+
@checkbox.click()
|
55
|
+
|
56
|
+
asyncTest "can cancel a tasklist:changed event", ->
|
57
|
+
expect 2
|
58
|
+
|
59
|
+
@field.on 'tasklist:change', (event, index, checked) ->
|
60
|
+
ok true
|
61
|
+
event.preventDefault()
|
62
|
+
|
63
|
+
@field.on 'tasklist:changed', (event, index, checked) ->
|
64
|
+
ok false
|
65
|
+
|
66
|
+
before = @checkbox.val()
|
67
|
+
setTimeout =>
|
68
|
+
equal before, @checkbox.val()
|
69
|
+
start()
|
70
|
+
, 20
|
71
|
+
|
72
|
+
@checkbox.click()
|
73
|
+
|
74
|
+
asyncTest "enables task list items when a .js-task-list-field is present", ->
|
75
|
+
expect 1
|
76
|
+
|
77
|
+
$(document).on 'tasklist:enabled', (event) ->
|
78
|
+
ok true
|
79
|
+
|
80
|
+
@container.taskList()
|
81
|
+
setTimeout ->
|
82
|
+
start()
|
83
|
+
, 20
|
84
|
+
|
85
|
+
asyncTest "doesn't enable task list items when a .js-task-list-field is absent", ->
|
86
|
+
expect 0
|
87
|
+
|
88
|
+
$(document).on 'tasklist:enabled', (event) ->
|
89
|
+
ok true
|
90
|
+
|
91
|
+
@field.remove()
|
92
|
+
|
93
|
+
@container.taskList()
|
94
|
+
setTimeout ->
|
95
|
+
start()
|
96
|
+
, 20
|
@@ -0,0 +1,566 @@
|
|
1
|
+
#= require task_list
|
2
|
+
|
3
|
+
module "TaskList updates",
|
4
|
+
setup: ->
|
5
|
+
@container = $ '<div>', class: 'js-task-list-container'
|
6
|
+
|
7
|
+
@list = $ '<ul>', class: 'task-list'
|
8
|
+
|
9
|
+
@completeItem = $ '<li>', class: 'task-list-item'
|
10
|
+
@completeCheckbox = $ '<input>',
|
11
|
+
type: 'checkbox'
|
12
|
+
class: 'task-list-item-checkbox'
|
13
|
+
disabled: true
|
14
|
+
checked: true
|
15
|
+
|
16
|
+
@incompleteItem = $ '<li>', class: 'task-list-item'
|
17
|
+
@incompleteCheckbox = $ '<input>',
|
18
|
+
type: 'checkbox'
|
19
|
+
class: 'task-list-item-checkbox'
|
20
|
+
disabled: true
|
21
|
+
checked: false
|
22
|
+
|
23
|
+
# non-breaking space. See: https://github.com/github/task-lists/pull/14
|
24
|
+
@nbsp = String.fromCharCode(160)
|
25
|
+
@incompleteNBSPItem = $ '<li>', class: 'task-list-item'
|
26
|
+
@incompleteNBSPCheckbox = $ '<input>',
|
27
|
+
type: 'checkbox'
|
28
|
+
class: 'task-list-item-checkbox'
|
29
|
+
disabled: true
|
30
|
+
checked: false
|
31
|
+
|
32
|
+
@blockquote = $ '<blockquote>'
|
33
|
+
|
34
|
+
@quotedList = $ '<ul>', class: 'task-list'
|
35
|
+
|
36
|
+
@quotedCompleteItem = $ '<li>', class: 'task-list-item'
|
37
|
+
@quotedCompleteCheckbox = $ '<input>',
|
38
|
+
type: 'checkbox'
|
39
|
+
class: 'task-list-item-checkbox'
|
40
|
+
disabled: true
|
41
|
+
checked: true
|
42
|
+
|
43
|
+
@quotedIncompleteItem = $ '<li>', class: 'task-list-item'
|
44
|
+
@quotedIncompleteCheckbox = $ '<input>',
|
45
|
+
type: 'checkbox'
|
46
|
+
class: 'task-list-item-checkbox'
|
47
|
+
disabled: true
|
48
|
+
checked: false
|
49
|
+
|
50
|
+
@innerBlockquote = $ '<blockquote>'
|
51
|
+
|
52
|
+
@innerList = $ '<ul>', class: 'task-list'
|
53
|
+
|
54
|
+
@innerCompleteItem = $ '<li>', class: 'task-list-item'
|
55
|
+
@innerCompleteCheckbox = $ '<input>',
|
56
|
+
type: 'checkbox'
|
57
|
+
class: 'task-list-item-checkbox'
|
58
|
+
disabled: true
|
59
|
+
checked: true
|
60
|
+
|
61
|
+
@innerIncompleteItem = $ '<li>', class: 'task-list-item'
|
62
|
+
@innerIncompleteCheckbox = $ '<input>',
|
63
|
+
type: 'checkbox'
|
64
|
+
class: 'task-list-item-checkbox'
|
65
|
+
disabled: true
|
66
|
+
checked: false
|
67
|
+
|
68
|
+
@orderedList = $ '<ol>', class: 'task-list'
|
69
|
+
|
70
|
+
@orderedCompleteItem = $ '<li>', class: 'task-list-item'
|
71
|
+
@orderedCompleteCheckbox = $ '<input>',
|
72
|
+
type: 'checkbox'
|
73
|
+
class: 'task-list-item-checkbox'
|
74
|
+
disabled: true
|
75
|
+
checked: true
|
76
|
+
|
77
|
+
@orderedIncompleteItem = $ '<li>', class: 'task-list-item'
|
78
|
+
@orderedIncompleteCheckbox = $ '<input>',
|
79
|
+
type: 'checkbox'
|
80
|
+
class: 'task-list-item-checkbox'
|
81
|
+
disabled: true
|
82
|
+
checked: false
|
83
|
+
|
84
|
+
@field = $ '<textarea>', class: 'js-task-list-field', text: """
|
85
|
+
- [x] complete
|
86
|
+
- [ ] incomplete
|
87
|
+
- [#{@nbsp}] incompleteNBSP
|
88
|
+
> - [x] quoted complete
|
89
|
+
> - [ ] quoted incomplete
|
90
|
+
>> - [x] inner complete
|
91
|
+
> > - [ ] inner incomplete
|
92
|
+
> 0. [x] ordered complete
|
93
|
+
> 0. [ ] ordered incomplete
|
94
|
+
"""
|
95
|
+
|
96
|
+
@changes =
|
97
|
+
toComplete: """
|
98
|
+
- [ ] complete
|
99
|
+
- [ ] incomplete
|
100
|
+
- [#{@nbsp}] incompleteNBSP
|
101
|
+
> - [x] quoted complete
|
102
|
+
> - [ ] quoted incomplete
|
103
|
+
>> - [x] inner complete
|
104
|
+
> > - [ ] inner incomplete
|
105
|
+
> 0. [x] ordered complete
|
106
|
+
> 0. [ ] ordered incomplete
|
107
|
+
"""
|
108
|
+
toQuotedComplete: """
|
109
|
+
- [x] complete
|
110
|
+
- [ ] incomplete
|
111
|
+
- [#{@nbsp}] incompleteNBSP
|
112
|
+
> - [ ] quoted complete
|
113
|
+
> - [ ] quoted incomplete
|
114
|
+
>> - [x] inner complete
|
115
|
+
> > - [ ] inner incomplete
|
116
|
+
> 0. [x] ordered complete
|
117
|
+
> 0. [ ] ordered incomplete
|
118
|
+
"""
|
119
|
+
toInnerComplete: """
|
120
|
+
- [x] complete
|
121
|
+
- [ ] incomplete
|
122
|
+
- [#{@nbsp}] incompleteNBSP
|
123
|
+
> - [x] quoted complete
|
124
|
+
> - [ ] quoted incomplete
|
125
|
+
>> - [ ] inner complete
|
126
|
+
> > - [ ] inner incomplete
|
127
|
+
> 0. [x] ordered complete
|
128
|
+
> 0. [ ] ordered incomplete
|
129
|
+
"""
|
130
|
+
toOrderedComplete: """
|
131
|
+
- [x] complete
|
132
|
+
- [ ] incomplete
|
133
|
+
- [#{@nbsp}] incompleteNBSP
|
134
|
+
> - [x] quoted complete
|
135
|
+
> - [ ] quoted incomplete
|
136
|
+
>> - [x] inner complete
|
137
|
+
> > - [ ] inner incomplete
|
138
|
+
> 0. [ ] ordered complete
|
139
|
+
> 0. [ ] ordered incomplete
|
140
|
+
"""
|
141
|
+
toIncomplete: """
|
142
|
+
- [x] complete
|
143
|
+
- [x] incomplete
|
144
|
+
- [#{@nbsp}] incompleteNBSP
|
145
|
+
> - [x] quoted complete
|
146
|
+
> - [ ] quoted incomplete
|
147
|
+
>> - [x] inner complete
|
148
|
+
> > - [ ] inner incomplete
|
149
|
+
> 0. [x] ordered complete
|
150
|
+
> 0. [ ] ordered incomplete
|
151
|
+
"""
|
152
|
+
toQuotedIncomplete: """
|
153
|
+
- [x] complete
|
154
|
+
- [ ] incomplete
|
155
|
+
- [#{@nbsp}] incompleteNBSP
|
156
|
+
> - [x] quoted complete
|
157
|
+
> - [x] quoted incomplete
|
158
|
+
>> - [x] inner complete
|
159
|
+
> > - [ ] inner incomplete
|
160
|
+
> 0. [x] ordered complete
|
161
|
+
> 0. [ ] ordered incomplete
|
162
|
+
"""
|
163
|
+
toInnerIncomplete: """
|
164
|
+
- [x] complete
|
165
|
+
- [ ] incomplete
|
166
|
+
- [#{@nbsp}] incompleteNBSP
|
167
|
+
> - [x] quoted complete
|
168
|
+
> - [ ] quoted incomplete
|
169
|
+
>> - [x] inner complete
|
170
|
+
> > - [x] inner incomplete
|
171
|
+
> 0. [x] ordered complete
|
172
|
+
> 0. [ ] ordered incomplete
|
173
|
+
"""
|
174
|
+
toOrderedIncomplete: """
|
175
|
+
- [x] complete
|
176
|
+
- [ ] incomplete
|
177
|
+
- [#{@nbsp}] incompleteNBSP
|
178
|
+
> - [x] quoted complete
|
179
|
+
> - [ ] quoted incomplete
|
180
|
+
>> - [x] inner complete
|
181
|
+
> > - [ ] inner incomplete
|
182
|
+
> 0. [x] ordered complete
|
183
|
+
> 0. [x] ordered incomplete
|
184
|
+
"""
|
185
|
+
toIncompleteNBSP: """
|
186
|
+
- [x] complete
|
187
|
+
- [ ] incomplete
|
188
|
+
- [x] incompleteNBSP
|
189
|
+
> - [x] quoted complete
|
190
|
+
> - [ ] quoted incomplete
|
191
|
+
>> - [x] inner complete
|
192
|
+
> > - [ ] inner incomplete
|
193
|
+
> 0. [x] ordered complete
|
194
|
+
> 0. [ ] ordered incomplete
|
195
|
+
"""
|
196
|
+
|
197
|
+
@completeItem.append @completeCheckbox
|
198
|
+
@list.append @completeItem
|
199
|
+
@completeItem.expectedIndex = 1
|
200
|
+
|
201
|
+
@incompleteItem.append @incompleteCheckbox
|
202
|
+
@list.append @incompleteItem
|
203
|
+
@incompleteItem.expectedIndex = 2
|
204
|
+
|
205
|
+
@incompleteNBSPItem.append @incompleteNBSPCheckbox
|
206
|
+
@list.append @incompleteNBSPItem
|
207
|
+
@incompleteNBSPItem.expectedIndex = 3
|
208
|
+
|
209
|
+
@container.append @list
|
210
|
+
@container.append @field
|
211
|
+
|
212
|
+
@quotedCompleteItem.append @quotedCompleteCheckbox
|
213
|
+
@quotedList.append @quotedCompleteItem
|
214
|
+
@quotedCompleteItem.expectedIndex = 4
|
215
|
+
|
216
|
+
@quotedIncompleteItem.append @quotedIncompleteCheckbox
|
217
|
+
@quotedList.append @quotedIncompleteItem
|
218
|
+
@quotedIncompleteItem.expectedIndex = 5
|
219
|
+
|
220
|
+
@blockquote.append @quotedList
|
221
|
+
|
222
|
+
@innerCompleteItem.append @innerCompleteCheckbox
|
223
|
+
@innerList.append @innerCompleteItem
|
224
|
+
@innerCompleteItem.expectedIndex = 6
|
225
|
+
|
226
|
+
@innerIncompleteItem.append @innerIncompleteCheckbox
|
227
|
+
@innerList.append @innerIncompleteItem
|
228
|
+
@innerIncompleteItem.expectedIndex = 7
|
229
|
+
|
230
|
+
@innerBlockquote.append @innerList
|
231
|
+
@innerBlockquote.append @innerField
|
232
|
+
|
233
|
+
@blockquote.append @innerBlockquote
|
234
|
+
|
235
|
+
@container.append @blockquote
|
236
|
+
|
237
|
+
@orderedCompleteItem.append @orderedCompleteCheckbox
|
238
|
+
@orderedList.append @orderedCompleteItem
|
239
|
+
@orderedCompleteItem.expectedIndex = 8
|
240
|
+
|
241
|
+
@orderedIncompleteItem.append @orderedIncompleteCheckbox
|
242
|
+
@orderedList.append @orderedIncompleteItem
|
243
|
+
@orderedIncompleteItem.expectedIndex = 9
|
244
|
+
|
245
|
+
@container.append @orderedList
|
246
|
+
|
247
|
+
@blockquote.append @field
|
248
|
+
|
249
|
+
$('#qunit-fixture').append(@container)
|
250
|
+
@container.taskList()
|
251
|
+
|
252
|
+
teardown: ->
|
253
|
+
$(document).off 'tasklist:changed'
|
254
|
+
|
255
|
+
asyncTest "updates the source, marking the incomplete item as complete", ->
|
256
|
+
expect 3
|
257
|
+
|
258
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
259
|
+
ok checked
|
260
|
+
equal index, @incompleteItem.expectedIndex
|
261
|
+
equal @field.val(), @changes.toIncomplete
|
262
|
+
|
263
|
+
setTimeout ->
|
264
|
+
start()
|
265
|
+
, 20
|
266
|
+
|
267
|
+
@incompleteCheckbox.click()
|
268
|
+
|
269
|
+
asyncTest "updates the source, marking the complete item as incomplete", ->
|
270
|
+
expect 3
|
271
|
+
|
272
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
273
|
+
ok !checked
|
274
|
+
equal index, @completeItem.expectedIndex
|
275
|
+
equal @field.val(), @changes.toComplete
|
276
|
+
|
277
|
+
setTimeout ->
|
278
|
+
start()
|
279
|
+
, 20
|
280
|
+
|
281
|
+
@completeCheckbox.click()
|
282
|
+
|
283
|
+
# See: https://github.com/github/task-lists/pull/14
|
284
|
+
asyncTest "updates the source for items with non-breaking spaces", ->
|
285
|
+
expect 3
|
286
|
+
|
287
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
288
|
+
ok checked
|
289
|
+
equal index, @incompleteNBSPItem.expectedIndex
|
290
|
+
equal @field.val(), @changes.toIncompleteNBSP
|
291
|
+
|
292
|
+
setTimeout ->
|
293
|
+
start()
|
294
|
+
, 20
|
295
|
+
|
296
|
+
@incompleteNBSPCheckbox.click()
|
297
|
+
|
298
|
+
asyncTest "updates the source of a quoted item, marking the incomplete item as complete", ->
|
299
|
+
expect 3
|
300
|
+
|
301
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
302
|
+
ok checked
|
303
|
+
equal index, @quotedIncompleteItem.expectedIndex
|
304
|
+
equal @field.val(), @changes.toQuotedIncomplete
|
305
|
+
|
306
|
+
setTimeout ->
|
307
|
+
start()
|
308
|
+
, 20
|
309
|
+
|
310
|
+
@quotedIncompleteCheckbox.click()
|
311
|
+
|
312
|
+
asyncTest "updates the source of a quoted item, marking the complete item as incomplete", ->
|
313
|
+
expect 3
|
314
|
+
|
315
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
316
|
+
ok !checked
|
317
|
+
equal index, @quotedCompleteItem.expectedIndex
|
318
|
+
equal @field.val(), @changes.toQuotedComplete
|
319
|
+
|
320
|
+
setTimeout ->
|
321
|
+
start()
|
322
|
+
, 20
|
323
|
+
|
324
|
+
@quotedCompleteCheckbox.click()
|
325
|
+
|
326
|
+
asyncTest "updates the source of a quoted quoted item, marking the incomplete item as complete", ->
|
327
|
+
expect 3
|
328
|
+
|
329
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
330
|
+
ok checked
|
331
|
+
equal index, @innerIncompleteItem.expectedIndex
|
332
|
+
equal @field.val(), @changes.toInnerIncomplete
|
333
|
+
|
334
|
+
setTimeout ->
|
335
|
+
start()
|
336
|
+
, 20
|
337
|
+
|
338
|
+
@innerIncompleteCheckbox.click()
|
339
|
+
|
340
|
+
asyncTest "updates the source of a quoted quoted item, marking the complete item as incomplete", ->
|
341
|
+
expect 3
|
342
|
+
|
343
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
344
|
+
ok !checked
|
345
|
+
equal index, @innerCompleteItem.expectedIndex
|
346
|
+
equal @field.val(), @changes.toInnerComplete
|
347
|
+
|
348
|
+
setTimeout ->
|
349
|
+
start()
|
350
|
+
, 20
|
351
|
+
|
352
|
+
@innerCompleteCheckbox.click()
|
353
|
+
|
354
|
+
asyncTest "updates the source of an ordered list item, marking the incomplete item as complete", ->
|
355
|
+
expect 3
|
356
|
+
|
357
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
358
|
+
ok checked
|
359
|
+
equal index, @orderedIncompleteItem.expectedIndex
|
360
|
+
equal @field.val(), @changes.toOrderedIncomplete
|
361
|
+
|
362
|
+
setTimeout ->
|
363
|
+
start()
|
364
|
+
, 20
|
365
|
+
|
366
|
+
@orderedIncompleteCheckbox.click()
|
367
|
+
|
368
|
+
asyncTest "updates the source of an ordered list item, marking the complete item as incomplete", ->
|
369
|
+
expect 3
|
370
|
+
|
371
|
+
@field.on 'tasklist:changed', (event, index, checked) =>
|
372
|
+
ok !checked
|
373
|
+
equal index, @orderedCompleteItem.expectedIndex
|
374
|
+
equal @field.val(), @changes.toOrderedComplete
|
375
|
+
|
376
|
+
setTimeout ->
|
377
|
+
start()
|
378
|
+
, 20
|
379
|
+
|
380
|
+
@orderedCompleteCheckbox.click()
|
381
|
+
|
382
|
+
asyncTest "update ignores items that look like Task List items but lack list prefix", ->
|
383
|
+
expect 3
|
384
|
+
|
385
|
+
$('#qunit-fixture').empty()
|
386
|
+
|
387
|
+
container = $ '<div>', class: 'js-task-list-container'
|
388
|
+
|
389
|
+
list = $ '<ul>', class: 'task-list'
|
390
|
+
|
391
|
+
item1 = $ '<li>', class: 'task-list-item'
|
392
|
+
item1Checkbox = $ '<input>',
|
393
|
+
type: 'checkbox'
|
394
|
+
class: 'task-list-item-checkbox'
|
395
|
+
disabled: true
|
396
|
+
checked: false
|
397
|
+
|
398
|
+
item2 = $ '<li>', class: 'task-list-item'
|
399
|
+
item2Checkbox = $ '<input>',
|
400
|
+
type: 'checkbox'
|
401
|
+
class: 'task-list-item-checkbox'
|
402
|
+
disabled: true
|
403
|
+
checked: false
|
404
|
+
|
405
|
+
field = $ '<textarea>', class: 'js-task-list-field', text: """
|
406
|
+
[ ] one
|
407
|
+
[ ] two
|
408
|
+
- [ ] three
|
409
|
+
- [ ] four
|
410
|
+
"""
|
411
|
+
|
412
|
+
changes = """
|
413
|
+
[ ] one
|
414
|
+
[ ] two
|
415
|
+
- [ ] three
|
416
|
+
- [x] four
|
417
|
+
"""
|
418
|
+
|
419
|
+
item1.append item1Checkbox
|
420
|
+
list.append item1
|
421
|
+
item1.expectedIndex = 1
|
422
|
+
|
423
|
+
item2.append item2Checkbox
|
424
|
+
list.append item2
|
425
|
+
item2.expectedIndex = 2
|
426
|
+
|
427
|
+
container.append list
|
428
|
+
container.append field
|
429
|
+
|
430
|
+
$('#qunit-fixture').append(container)
|
431
|
+
container.taskList()
|
432
|
+
|
433
|
+
field.on 'tasklist:changed', (event, index, checked) =>
|
434
|
+
ok checked
|
435
|
+
equal index, item2.expectedIndex
|
436
|
+
equal field.val(), changes
|
437
|
+
|
438
|
+
setTimeout ->
|
439
|
+
start()
|
440
|
+
, 20
|
441
|
+
|
442
|
+
item2Checkbox.click()
|
443
|
+
|
444
|
+
asyncTest "update ignores items that look like Task List items but are links", ->
|
445
|
+
expect 3
|
446
|
+
|
447
|
+
$('#qunit-fixture').empty()
|
448
|
+
|
449
|
+
container = $ '<div>', class: 'js-task-list-container'
|
450
|
+
|
451
|
+
list = $ '<ul>', class: 'task-list'
|
452
|
+
|
453
|
+
item1 = $ '<li>', class: 'task-list-item'
|
454
|
+
item1Checkbox = $ '<input>',
|
455
|
+
type: 'checkbox'
|
456
|
+
class: 'task-list-item-checkbox'
|
457
|
+
disabled: true
|
458
|
+
checked: false
|
459
|
+
|
460
|
+
item2 = $ '<li>', class: 'task-list-item'
|
461
|
+
item2Checkbox = $ '<input>',
|
462
|
+
type: 'checkbox'
|
463
|
+
class: 'task-list-item-checkbox'
|
464
|
+
disabled: true
|
465
|
+
checked: false
|
466
|
+
|
467
|
+
field = $ '<textarea>', class: 'js-task-list-field', text: """
|
468
|
+
- [ ] (link)
|
469
|
+
- [ ] [reference]
|
470
|
+
- [ ] () collapsed
|
471
|
+
- [ ] [] collapsed reference
|
472
|
+
- [ ] \\(escaped item)
|
473
|
+
- [ ] item
|
474
|
+
"""
|
475
|
+
|
476
|
+
changes = """
|
477
|
+
- [ ] (link)
|
478
|
+
- [ ] [reference]
|
479
|
+
- [ ] () collapsed
|
480
|
+
- [ ] [] collapsed reference
|
481
|
+
- [ ] \\(escaped item)
|
482
|
+
- [x] item
|
483
|
+
"""
|
484
|
+
|
485
|
+
item1.append item1Checkbox
|
486
|
+
list.append item1
|
487
|
+
item1.expectedIndex = 1
|
488
|
+
|
489
|
+
item2.append item2Checkbox
|
490
|
+
list.append item2
|
491
|
+
item2.expectedIndex = 2
|
492
|
+
|
493
|
+
container.append list
|
494
|
+
container.append field
|
495
|
+
|
496
|
+
$('#qunit-fixture').append(container)
|
497
|
+
container.taskList()
|
498
|
+
|
499
|
+
field.on 'tasklist:changed', (event, index, checked) =>
|
500
|
+
ok checked
|
501
|
+
equal index, item2.expectedIndex
|
502
|
+
equal field.val(), changes
|
503
|
+
|
504
|
+
setTimeout ->
|
505
|
+
start()
|
506
|
+
, 20
|
507
|
+
|
508
|
+
item2Checkbox.click()
|
509
|
+
|
510
|
+
asyncTest "updates items followed by links", ->
|
511
|
+
expect 3
|
512
|
+
|
513
|
+
$('#qunit-fixture').empty()
|
514
|
+
|
515
|
+
container = $ '<div>', class: 'js-task-list-container'
|
516
|
+
|
517
|
+
list = $ '<ul>', class: 'task-list'
|
518
|
+
|
519
|
+
item1 = $ '<li>', class: 'task-list-item'
|
520
|
+
item1Checkbox = $ '<input>',
|
521
|
+
type: 'checkbox'
|
522
|
+
class: 'task-list-item-checkbox'
|
523
|
+
disabled: true
|
524
|
+
checked: false
|
525
|
+
|
526
|
+
item2 = $ '<li>', class: 'task-list-item'
|
527
|
+
item2Checkbox = $ '<input>',
|
528
|
+
type: 'checkbox'
|
529
|
+
class: 'task-list-item-checkbox'
|
530
|
+
disabled: true
|
531
|
+
checked: false
|
532
|
+
|
533
|
+
field = $ '<textarea>', class: 'js-task-list-field', text: """
|
534
|
+
- [ ] [link label](link)
|
535
|
+
- [ ] [reference label][reference]
|
536
|
+
"""
|
537
|
+
|
538
|
+
changes = """
|
539
|
+
- [ ] [link label](link)
|
540
|
+
- [x] [reference label][reference]
|
541
|
+
"""
|
542
|
+
|
543
|
+
item1.append item1Checkbox
|
544
|
+
list.append item1
|
545
|
+
item1.expectedIndex = 1
|
546
|
+
|
547
|
+
item2.append item2Checkbox
|
548
|
+
list.append item2
|
549
|
+
item2.expectedIndex = 2
|
550
|
+
|
551
|
+
container.append list
|
552
|
+
container.append field
|
553
|
+
|
554
|
+
$('#qunit-fixture').append(container)
|
555
|
+
container.taskList()
|
556
|
+
|
557
|
+
field.on 'tasklist:changed', (event, index, checked) =>
|
558
|
+
ok checked
|
559
|
+
equal index, item2.expectedIndex
|
560
|
+
equal field.val(), changes
|
561
|
+
|
562
|
+
setTimeout ->
|
563
|
+
start()
|
564
|
+
, 20
|
565
|
+
|
566
|
+
item2Checkbox.click()
|