class HTML::Pipeline::TaskList::Filter
TaskList
filter replaces task list item markers (`[ ]` and `[x]`) with checkboxes, marked up with metadata and behavior.
This should be run on the HTML
generated by the Markdown filter, after the SanitizationFilter.
Syntax
Task list items must be in a list format:
“`
-
incomplete
- x
-
complete
“`
Results
The following keys are written to the result hash:
:task_list_items - An array of TaskList::Item objects.
Constants
- COMPLETE
- COMPLETE_PATTERN
- INCOMPLETE
- INCOMPLETE_PATTERN
- ITEM_PARA_SELECTOR
Selects first P tag of an LI, if present
- ITEM_PATTERN
Pattern used to identify all task list items. Useful when you need iterate over all items.
- LIST_ITEM_SELECTOR
Public Instance Methods
Private: adds a CSS class name to a node, respecting existing class names.
# File lib/html/pipeline/task_list/filter.rb, line 159 def add_css_class(node, *new_class_names) class_names = (node['class'] || '').split(' ') return if new_class_names.all? { |klass| class_names.include?(klass) } class_names.concat(new_class_names) node['class'] = class_names.uniq.join(' ') end
# File lib/html/pipeline/task_list/filter.rb, line 152 def call filter! doc end
Filters the source for task list items.
Each item is wrapped in HTML
to identify, style, and layer useful behavior on top of.
Modifications apply to the parsed document directly.
Returns nothing.
# File lib/html/pipeline/task_list/filter.rb, line 133 def filter! list_items.reverse.each do |li| add_css_class(li.parent, 'task-list') outer, inner = item_selector(li) unless (match = (inner.chomp =~ ITEM_PATTERN && Regexp.last_match(1))) next end item = HTML::Pipeline::TaskList::Item.new(match, inner) # prepend because we're iterating in reverse task_list_items.unshift item add_css_class(li, 'task-list-item') outer.inner_html = render_task_list_item(item) end end
Public: Select all task lists from the `doc`.
Returns an Array of Nokogiri::XML::Element objects for ordered and unordered lists.
# File lib/html/pipeline/task_list/filter.rb, line 121 def list_items doc.xpath(LIST_ITEM_SELECTOR, XPathSelectorFunction) end
Renders the item checkbox in a span including the item state.
Returns an HTML-safe String.
# File lib/html/pipeline/task_list/filter.rb, line 94 def render_item_checkbox(item) %(<input type="checkbox" class="task-list-item-checkbox" #{'checked="checked"' if item.complete?} disabled="disabled" />) end
Public: Marks up the task list item checkbox with metadata and behavior.
NOTE: produces a string that, when assigned to a Node's `inner_html`, will corrupt the string contents' encodings. Instead, we parse the rendered HTML
and explicitly set its encoding so that assignment will not change the encodings.
See [this pull](github.com/github/github/pull/8505) for details.
Returns the marked up task list item Nokogiri::XML::NodeSet object.
# File lib/html/pipeline/task_list/filter.rb, line 112 def render_task_list_item(item) Nokogiri::HTML.fragment \ item.source.sub(ITEM_PATTERN, render_item_checkbox(item)), 'utf-8' end
List of `TaskList::Item` objects that were recognized in the document. This is available in the result hash as `:task_list_items`.
Returns an Array of TaskList::Item objects.
# File lib/html/pipeline/task_list/filter.rb, line 87 def task_list_items result[:task_list_items] ||= [] end
Private Instance Methods
# File lib/html/pipeline/task_list/filter.rb, line 169 def item_selector(item) if (p = item.xpath(ITEM_PARA_SELECTOR)[0]) [p, p.inner_html] else [item, item.inner_html] end end