Skip to content
This repository was archived by the owner on Nov 1, 2017. It is now read-only.

Commit d5189d0

Browse files
committed
Pull Summary out, update Filter, fix tests
1 parent 75cfb82 commit d5189d0

5 files changed

Lines changed: 114 additions & 115 deletions

File tree

lib/task_list.rb

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
require 'task_list/summary'
12
require 'task_list/version'
23

34
# encoding: utf-8
@@ -28,26 +29,4 @@ def complete?
2829
checkbox_text == Complete
2930
end
3031
end
31-
32-
class Summary < Struct.new(:items)
33-
# Public: returns true if there are any TaskList::Item objects.
34-
def items?
35-
item_count > 0
36-
end
37-
38-
# Public: returns the number of TaskList::Item objects.
39-
def item_count
40-
items.size
41-
end
42-
43-
# Public: returns the number of complete TaskList::Item objects.
44-
def complete_count
45-
items.select{ |i| i.complete? }.size
46-
end
47-
48-
# Public: returns the number of incomplete TaskList::Item objects.
49-
def incomplete_count
50-
items.select{ |i| !i.complete? }.size
51-
end
52-
end
5332
end

lib/task_list/filter.rb

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,30 @@ def self.filter(*args)
2323
# - [ ] incomplete
2424
# - [x] complete
2525
# ```
26+
#
27+
# Results
28+
# -------
29+
#
30+
# The following keys are written to the result hash:
31+
# :task_list_items - An array of TaskList::Item objects.
2632
class Filter < HTML::Pipeline::Filter
2733

34+
Incomplete = "[ ]".freeze
35+
Complete = "[x]".freeze
36+
37+
# Pattern used to identify all task list items.
38+
# Useful when you need iterate over all items.
39+
ItemPattern = /
40+
^
41+
(?:\s*[-+*]|(?:\d+\.))? # optional list prefix
42+
\s* # optional whitespace prefix
43+
( # checkbox
44+
#{Regexp.escape(Complete)}|
45+
#{Regexp.escape(Incomplete)}
46+
)
47+
(?=\s) # followed by whitespace
48+
/x
49+
2850
ListSelector = [
2951
# select UL/OL
3052
".//li[starts-with(text(),'[ ]')]/..",
@@ -52,6 +74,14 @@ def next_index
5274
@index += 1
5375
end
5476

77+
# List of `TaskList::Item` objects that were recognized in the document.
78+
# This is available in the result hash as `:task_list_items`.
79+
#
80+
# Returns an Array of TaskList::Item objects.
81+
def task_list_items
82+
result[:task_list_items] ||= []
83+
end
84+
5585
# Renders the item checkbox in a span including the item index and state.
5686
#
5787
# Returns an HTML-safe String.
@@ -77,7 +107,7 @@ def render_item_checkbox(item)
77107
def render_task_list_item(item)
78108
Nokogiri::HTML.fragment <<-html, 'utf-8'
79109
<label>#{
80-
item.source.sub(TaskList::ItemPattern, render_item_checkbox(item))
110+
item.source.sub(ItemPattern, render_item_checkbox(item))
81111
}</label>
82112
html
83113
end
@@ -106,8 +136,10 @@ def filter_list(node)
106136
else
107137
[li, li.inner_html]
108138
end
109-
if match = TaskList.item?(inner)
139+
if match = (inner.chomp =~ ItemPattern && $1)
110140
item = TaskList::Item.new(next_index, match, inner)
141+
task_list_items << item
142+
111143
add_css_class(li, 'task-list-item')
112144
outer.inner_html = render_task_list_item(item)
113145
end

lib/task_list/summary.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# encoding: utf-8
2+
require 'html/pipeline'
3+
require 'task_list'
4+
5+
class TaskList
6+
# Provides a summary of provided TaskList `items`.
7+
#
8+
# `items` is an Array of TaskList::Item objects.
9+
class Summary < Struct.new(:items)
10+
# Public: returns true if there are any TaskList::Item objects.
11+
def items?
12+
item_count > 0
13+
end
14+
15+
# Public: returns the number of TaskList::Item objects.
16+
def item_count
17+
items.size
18+
end
19+
20+
# Public: returns the number of complete TaskList::Item objects.
21+
def complete_count
22+
items.select{ |i| i.complete? }.size
23+
end
24+
25+
# Public: returns the number of incomplete TaskList::Item objects.
26+
def incomplete_count
27+
items.select{ |i| !i.complete? }.size
28+
end
29+
end
30+
end

test/task_list/summary_test.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 < Test::Unit::TestCase
6+
def setup
7+
@complete = make_item 1, "[x]", "complete"
8+
@incomplete = make_item 2, "[ ]", "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(index = 1, checkbox_text = "[ ]", source = "an item!")
34+
TaskList::Item.new(index, checkbox_text, source)
35+
end
36+
37+
def make_summary(items)
38+
TaskList::Summary.new(items)
39+
end
40+
end

test/task_list_test.rb

Lines changed: 9 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,21 @@
11
# encoding: utf-8
22
require File.expand_path('../test_helper', __FILE__)
33
require 'task_list'
4+
require 'task_list/filter'
45

56
class TaskListTest < Test::Unit::TestCase
6-
7-
def test_updates_task_list_item_by_index
8-
text = <<-md
9-
- [ ] index 1, incomplete
10-
- [x] index 2, complete
11-
md
12-
13-
assert_match "- [x] index 1, incomplete", update(text, 1, true).source
14-
assert_match "- [ ] index 2, complete", update(text, 2, false).source
15-
end
16-
17-
def test_updates_task_lists_in_numbered_lists
18-
text = <<-md
19-
1. [ ] index 1, incomplete
20-
14. [x] index 2, complete
21-
md
22-
23-
assert_match "1. [x] index 1, incomplete", update(text, 1, true).source
24-
assert_match "14. [ ] index 2, complete", update(text, 2, false).source
25-
end
26-
27-
def test_updates_ignore_task_lists_in_code_fences
28-
text = <<-md
29-
```
30-
- [ ] should not be indexed
31-
- [x] nor this
32-
```
33-
34-
- [ ] index 1, incomplete
35-
- [x] index 2, complete
36-
md
37-
38-
assert_match "- [x] index 1, incomplete", update(text, 1, true).source
39-
assert_match "- [ ] index 2, complete", update(text, 2, false).source
40-
end
41-
42-
def test_updates_ignores_items_in_paras
43-
text = <<-md
44-
here's a paragraph:
45-
46-
[ ] should not be indexed
47-
[x] nor this
48-
49-
- [ ] index 1, incomplete
50-
- [x] index 2, complete
51-
md
52-
53-
assert_match "- [x] index 1, incomplete", update(text, 1, true).source
54-
assert_match "- [ ] index 2, complete", update(text, 2, false).source
55-
end
56-
57-
def test_update_cleans_carriage_returns_for_matches
58-
text = <<-md
59-
``` markdown\r
60-
- [ ] foo\r
61-
```\r
62-
\r
63-
- [ ] index 1, incomplete\r
64-
- [x] index 2, complete\r
65-
md
66-
67-
assert_match "- [x] index 1, incomplete", update(text, 1, true).source
68-
assert_match "- [ ] index 2, complete", update(text, 2, false).source
69-
end
70-
71-
def test_task_list_for_nil_body
72-
assert task_list(nil).items.empty?, "no task list items are expected"
7+
class Record < Struct.new(:body)
8+
def task_list_items
9+
[]
10+
end
7311
end
7412

75-
def test_task_list_summary
76-
summary = task_list("").summary
77-
assert !summary.items?, "no task list items are expected"
78-
79-
text = <<-md
80-
- [ ] one
81-
- [x] two
82-
83-
```
84-
- [ ] don't count me yo
85-
- [x] nor me
86-
```
87-
md
88-
89-
summary = task_list(text).summary
90-
assert summary.items?, "task list items are expected"
91-
assert_equal 2, summary.item_count
92-
assert_equal 1, summary.complete_count
93-
assert_equal 1, summary.incomplete_count
13+
def test_has_summary
14+
assert summary = task_list("- [ ] one").summary, "summary expected"
15+
assert_kind_of TaskList::Summary, summary
9416
end
9517

9618
def task_list(text)
97-
TaskList.new(text)
98-
end
99-
100-
def update(text, index, checked)
101-
task_list(text).update(index, checked)
19+
TaskList.new(Record.new(text))
10220
end
10321
end

0 commit comments

Comments
 (0)