1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# frozen_string_literal: true
# Finds the correct checkbox in the passed in markdown/html and toggles it's state,
# returning the updated markdown/html.
# We don't care if the text has changed above or below the specific checkbox, as long
# the checkbox still exists at exactly the same line number and the text is equal.
# If successful, new values are available in `updated_markdown` and `updated_markdown_html`
#
# Note: once we've removed RedCarpet support, we can remove the `index` and `sourcepos`
# parameters
class TaskListToggleService
attr_reader :updated_markdown, :updated_markdown_html
def initialize(markdown, markdown_html, line_source:, line_number:, currently_checked:, index:, sourcepos: false)
@markdown, @markdown_html = markdown, markdown_html
@line_source, @line_number = line_source, line_number
@currently_checked = currently_checked
@index, @use_sourcepos = index, sourcepos
@updated_markdown, @updated_markdown_html = nil
end
def execute
return false unless markdown && markdown_html
!!(toggle_markdown && toggle_html)
end
private
attr_reader :markdown, :markdown_html, :index, :currently_checked
attr_reader :line_source, :line_number, :use_sourcepos
def toggle_markdown
source_lines = markdown.split("\n")
markdown_task = source_lines[line_number - 1]
return unless markdown_task == line_source
return unless source_checkbox = Taskable::ITEM_PATTERN.match(markdown_task)
if TaskList::Item.new(source_checkbox[1]).complete?
markdown_task.sub!(Taskable::COMPLETE_PATTERN, '[ ]') if currently_checked
else
markdown_task.sub!(Taskable::INCOMPLETE_PATTERN, '[x]') unless currently_checked
end
source_lines[line_number - 1] = markdown_task
@updated_markdown = source_lines.join("\n")
end
def toggle_html
html = Nokogiri::HTML.fragment(markdown_html)
html_checkbox = get_html_checkbox(html)
return unless html_checkbox
if currently_checked
html_checkbox.remove_attribute('checked')
else
html_checkbox[:checked] = 'checked'
end
@updated_markdown_html = html.to_html
end
def get_html_checkbox(html)
if use_sourcepos
html.css(".task-list-item[data-sourcepos^='#{line_number}:'] > input.task-list-item-checkbox").first
else
html.css('.task-list-item-checkbox')[index - 1]
end
end
end
|