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

Commit a62378d

Browse files
committed
Merge pull request #21 from github/filter-refactor
Rewrite Filter: use XPath function
2 parents f28a494 + 901e0cf commit a62378d

File tree

3 files changed

+21
-35
lines changed

3 files changed

+21
-35
lines changed

lib/task_list/filter.rb

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,16 @@ class Filter < HTML::Pipeline::Filter
4747
(?=\s) # followed by whitespace
4848
/x
4949

50-
ListSelector = [
51-
# select UL/OL
52-
".//li[starts-with(text(),'[ ]')]/..",
53-
".//li[starts-with(text(),'[x]')]/..",
54-
# and those wrapped in Ps
55-
".//li/p[1][starts-with(text(),'[ ]')]/../..",
56-
".//li/p[1][starts-with(text(),'[x]')]/../.."
57-
].join(' | ').freeze
58-
59-
# Selects all LIs from a TaskList UL/OL
60-
ItemSelector = ".//li".freeze
50+
ListItemSelector = ".//li[task_list_item(.)]".freeze
51+
52+
class XPathSelectorFunction
53+
def self.task_list_item(nodes)
54+
nodes if nodes.text =~ ItemPattern
55+
end
56+
end
6157

6258
# Selects first P tag of an LI, if present
63-
ItemParaSelector = ".//p[1]".freeze
59+
ItemParaSelector = "./p[1]".freeze
6460

6561
# List of `TaskList::Item` objects that were recognized in the document.
6662
# This is available in the result hash as `:task_list_items`.
@@ -100,20 +96,22 @@ def render_task_list_item(item)
10096
#
10197
# Returns an Array of Nokogiri::XML::Element objects for ordered and
10298
# unordered lists.
103-
def task_lists
104-
doc.xpath(ListSelector)
99+
def list_items
100+
doc.xpath(ListItemSelector, XPathSelectorFunction)
105101
end
106102

107-
# Public: filters a Nokogiri::XML::Element ordered/unordered list, marking
108-
# up the list items in order to add behavior and include metadata.
103+
# Filters the source for task list items.
109104
#
110-
# Modifies the provided node.
105+
# Each item is wrapped in HTML to identify, style, and layer
106+
# useful behavior on top of.
107+
#
108+
# Modifications apply to the parsed document directly.
111109
#
112110
# Returns nothing.
113-
def filter_list(node)
114-
add_css_class(node, 'task-list')
111+
def filter!
112+
list_items.reverse.each do |li|
113+
add_css_class(li.parent, 'task-list')
115114

116-
node.xpath(ItemSelector).reverse.each do |li|
117115
outer, inner =
118116
if p = li.xpath(ItemParaSelector)[0]
119117
[p, p.inner_html]
@@ -131,20 +129,6 @@ def filter_list(node)
131129
end
132130
end
133131

134-
# Filters the source for task list items.
135-
#
136-
# Each item is wrapped in HTML to identify, style, and layer
137-
# useful behavior on top of.
138-
#
139-
# Modifications apply to the parsed document directly.
140-
#
141-
# Returns nothing.
142-
def filter!
143-
task_lists.each do |node|
144-
filter_list node
145-
end
146-
end
147-
148132
def call
149133
filter!
150134
doc
@@ -154,6 +138,7 @@ def call
154138
# names.
155139
def add_css_class(node, *new_class_names)
156140
class_names = (node['class'] || '').split(' ')
141+
return if new_class_names.all? { |klass| class_names.include?(klass) }
157142
class_names.concat(new_class_names)
158143
node['class'] = class_names.uniq.join(' ')
159144
end

lib/task_list/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
class TaskList
2-
VERSION = [0, 2, 1].join('.')
2+
VERSION = [0, 3, 0].join('.')
33
end

test/task_list/filter_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def test_handles_complicated_nested_items
100100
- [ ] two.two
101101
- [ ] three
102102
md
103+
103104
assert_equal 6 + 2, filter(text)[:output].css('.task-list-item .task-list-item').size
104105
assert_equal 2, filter(text)[:output].css('.task-list-item .task-list-item .task-list-item').size
105106
end

0 commit comments

Comments
 (0)