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:

“`

“`

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

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/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
call() click to toggle source
# File lib/html/pipeline/task_list/filter.rb, line 152
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/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
list_items() click to toggle source

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

Private Instance Methods

item_selector(item) click to toggle source
# 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