module Himekami module Markdown module Filters class Checkbox < HTML::Pipeline::Filter def call doc.search("li").each do |li| if List.has_checkbox?(li) li = List.new(li) li.convert! end end doc end class List LI_ATTR_CLASS = 'task-list-item'.freeze CHECKBOX_ATTR_CLASS = 'task-list-item-checkbox'.freeze CHECKBOX_OPEN = "[ ] ".freeze CHECKBOX_CLOSED = "[x] ".freeze CHECKBOX_PATTERN = /(\[ \]|\[x\])\s+/ class << self def has_checkbox?(node) node.text.start_with?(CHECKBOX_OPEN, CHECKBOX_CLOSED) end end def initialize(node) @node = node end def convert! add_css_class text_node add_checkbox_html end private def text_node return @node.children.find { |node| node.name == 'p' }.children.first if @node.children.any? { |node| node.name == 'p' } @node.children.first end def add_css_class @node['class'] = LI_ATTR_CLASS if @node['class'].nil? || !@node['class'].include?(LI_ATTR_CLASS) end def remove_md text_node.content = text_node.content.sub(CHECKBOX_PATTERN, '').strip end def add_checkbox_html html = open_checkbox? ? render_open_checkbox_html : render_closed_checkbox_html remove_md text_node.add_previous_sibling(html) end def render_open_checkbox_html '' end def render_closed_checkbox_html '' end def open_checkbox? text_node.content.start_with?(CHECKBOX_OPEN) end end end end end end