class 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:

“`

“`

Results


The following keys are written to the result hash:

:task_list_items - An array of TaskList::Item objects.

Constants

Complete
CompletePattern
Incomplete
IncompletePattern
ItemParaSelector

Selects first P tag of an LI, if present

ItemPattern

Pattern used to identify all task list items. Useful when you need iterate over all items.

ListItemSelector

Public Instance Methods

add_css_class(node, *new_class_names) click to toggle source

Private: adds a CSS class name to a node, respecting existing class names.

# File lib/task_list/filter.rb, line 144
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
call() click to toggle source
# File lib/task_list/filter.rb, line 137
def call
  filter!
  doc
end
filter!() click to toggle source

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/task_list/filter.rb, line 114
def filter!
  list_items(doc).reverse.each do |li|
    next if list_items(li.parent).empty?

    add_css_class(li.parent, 'task-list')

    outer, inner =
      if p = li.xpath(ItemParaSelector)[0]
        [p, p.inner_html]
      else
        [li, li.inner_html]
      end
    if match = (inner.chomp =~ ItemPattern && $1)
      item = 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
end
list_items(container) click to toggle source

Public: Select all task list items within `container`.

Returns an Array of Nokogiri::XML::Element objects for ordered and unordered lists. The container can either be the entire document (as returned by `#doc`) or an Element object.

# File lib/task_list/filter.rb, line 102
def list_items(container)
  container.xpath(ListItemSelector, XPathSelectorFunction)
end
render_item_checkbox(item) click to toggle source

Renders the item checkbox in a span including the item state.

Returns an HTML-safe String.

# File lib/task_list/filter.rb, line 74
def render_item_checkbox(item)
  %Q(<input type="checkbox"
    class="task-list-item-checkbox"
    #{'checked="checked"' if item.complete?}
    disabled="disabled"
  />)
end
render_task_list_item(item) click to toggle source

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/task_list/filter.rb, line 92
def render_task_list_item(item)
  Nokogiri::HTML.fragment          item.source.sub(ItemPattern, render_item_checkbox(item)), 'utf-8'
end
task_list_items() click to toggle source

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/task_list/filter.rb, line 67
def task_list_items
  result[:task_list_items] ||= []
end