summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrett Walker <bwalker@gitlab.com>2019-03-28 18:45:59 -0500
committerBrett Walker <bwalker@gitlab.com>2019-04-03 12:16:12 -0500
commitcbbc1207bd90eda33b159eb398ae53544f9a6891 (patch)
tree7edde7e3c0ea432e4bb962952a72edf9eea4dab2
parent9f6ab1a5953eff45da9b8d2a5fcb92fe7b44a95d (diff)
downloadgitlab-ce-58717-checkbox-in-issue-description-cannot-be-checked-if-the-description-contains-a-blockquote.tar.gz
-rw-r--r--app/services/issuable_base_service.rb3
-rw-r--r--app/services/task_list_toggle_service.rb13
-rw-r--r--changelogs/unreleased/58717-checkbox-in-issue-description-cannot-be-checked-if-the-description-contains-a-blockquote.yml5
-rw-r--r--spec/services/task_list_toggle_service_spec.rb35
4 files changed, 44 insertions, 12 deletions
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 04dfcfbc22d..f363cb03a3f 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -272,7 +272,8 @@ class IssuableBaseService < BaseService
tasklist_toggler = TaskListToggleService.new(issuable.description, issuable.description_html,
line_source: update_task_params[:line_source],
line_number: update_task_params[:line_number].to_i,
- toggle_as_checked: update_task_params[:checked])
+ toggle_as_checked: update_task_params[:checked],
+ index: update_task_params[:index])
unless tasklist_toggler.execute
# if we make it here, the data is much newer than we thought it was - fail fast
diff --git a/app/services/task_list_toggle_service.rb b/app/services/task_list_toggle_service.rb
index f6602a35033..800787e5c51 100644
--- a/app/services/task_list_toggle_service.rb
+++ b/app/services/task_list_toggle_service.rb
@@ -8,10 +8,11 @@
class TaskListToggleService
attr_reader :updated_markdown, :updated_markdown_html
- def initialize(markdown, markdown_html, line_source:, line_number:, toggle_as_checked:)
+ def initialize(markdown, markdown_html, line_source:, line_number:, toggle_as_checked:, index:)
@markdown, @markdown_html = markdown, markdown_html
@line_source, @line_number = line_source, line_number
@toggle_as_checked = toggle_as_checked
+ @index = index
@updated_markdown, @updated_markdown_html = nil
end
@@ -26,6 +27,7 @@ class TaskListToggleService
attr_reader :markdown, :markdown_html, :toggle_as_checked
attr_reader :line_source, :line_number
+ attr_reader :index
def toggle_markdown
source_lines = markdown.split("\n")
@@ -64,9 +66,12 @@ class TaskListToggleService
@updated_markdown_html = html.to_html
end
- # When using CommonMark, we should be able to use the embedded `sourcepos` attribute to
- # target the exact line in the DOM.
+ # At the moment, we can't use the CommonMark `sourcepos`
+ # html.css(".task-list-item[data-sourcepos^='#{line_number}:'] input.task-list-item-checkbox").first
+ # because special tags that change the line numbering (like the GitLab blockquote) will
+ # cause it to break.
+ # Use the indexed checkbox instead to target the exact line in the DOM.
def get_html_checkbox(html)
- html.css(".task-list-item[data-sourcepos^='#{line_number}:'] input.task-list-item-checkbox").first
+ html.css('.task-list-item-checkbox')[index - 1]
end
end
diff --git a/changelogs/unreleased/58717-checkbox-in-issue-description-cannot-be-checked-if-the-description-contains-a-blockquote.yml b/changelogs/unreleased/58717-checkbox-in-issue-description-cannot-be-checked-if-the-description-contains-a-blockquote.yml
new file mode 100644
index 00000000000..7c1dde260b7
--- /dev/null
+++ b/changelogs/unreleased/58717-checkbox-in-issue-description-cannot-be-checked-if-the-description-contains-a-blockquote.yml
@@ -0,0 +1,5 @@
+---
+title: Allow task lists that follow a blockquote to work correctly
+merge_request: 26748
+author:
+type: fixed
diff --git a/spec/services/task_list_toggle_service_spec.rb b/spec/services/task_list_toggle_service_spec.rb
index b1260cf740a..3c69757aac4 100644
--- a/spec/services/task_list_toggle_service_spec.rb
+++ b/spec/services/task_list_toggle_service_spec.rb
@@ -52,7 +52,7 @@ describe TaskListToggleService do
it 'checks Task 1' do
toggler = described_class.new(markdown, markdown_html,
toggle_as_checked: true,
- line_source: '* [ ] Task 1', line_number: 1)
+ line_source: '* [ ] Task 1', line_number: 1, index: 1)
expect(toggler.execute).to be_truthy
expect(toggler.updated_markdown.lines[0]).to eq "* [x] Task 1\n"
@@ -62,7 +62,7 @@ describe TaskListToggleService do
it 'unchecks Item 1' do
toggler = described_class.new(markdown, markdown_html,
toggle_as_checked: false,
- line_source: '1. [X] Item 1', line_number: 6)
+ line_source: '1. [X] Item 1', line_number: 6, index: 3)
expect(toggler.execute).to be_truthy
expect(toggler.updated_markdown.lines[5]).to eq "1. [ ] Item 1\n"
@@ -72,7 +72,7 @@ describe TaskListToggleService do
it 'checks task in loose list' do
toggler = described_class.new(markdown, markdown_html,
toggle_as_checked: true,
- line_source: '- [ ] loose list', line_number: 9)
+ line_source: '- [ ] loose list', line_number: 9, index: 5)
expect(toggler.execute).to be_truthy
expect(toggler.updated_markdown.lines[8]).to eq "- [x] loose list\n"
@@ -82,7 +82,7 @@ describe TaskListToggleService do
it 'returns false if line_source does not match the text' do
toggler = described_class.new(markdown, markdown_html,
toggle_as_checked: false,
- line_source: '* [x] Task Added', line_number: 2)
+ line_source: '* [x] Task Added', line_number: 2, index: 2)
expect(toggler.execute).to be_falsey
end
@@ -91,7 +91,7 @@ describe TaskListToggleService do
rn_markdown = markdown.gsub("\n", "\r\n")
toggler = described_class.new(rn_markdown, markdown_html,
toggle_as_checked: true,
- line_source: '* [ ] Task 1', line_number: 1)
+ line_source: '* [ ] Task 1', line_number: 1, index: 1)
expect(toggler.execute).to be_truthy
expect(toggler.updated_markdown.lines[0]).to eq "* [x] Task 1\r\n"
@@ -101,7 +101,7 @@ describe TaskListToggleService do
it 'returns false if markdown is nil' do
toggler = described_class.new(nil, markdown_html,
toggle_as_checked: false,
- line_source: '* [x] Task Added', line_number: 2)
+ line_source: '* [x] Task Added', line_number: 2, index: 2)
expect(toggler.execute).to be_falsey
end
@@ -109,8 +109,29 @@ describe TaskListToggleService do
it 'returns false if markdown_html is nil' do
toggler = described_class.new(markdown, nil,
toggle_as_checked: false,
- line_source: '* [x] Task Added', line_number: 2)
+ line_source: '* [x] Task Added', line_number: 2, index: 2)
expect(toggler.execute).to be_falsey
end
+
+ it 'properly handles a GitLab blockquote' do
+ markdown =
+ <<-EOT.strip_heredoc
+ >>>
+ gitlab blockquote
+ >>>
+
+ * [ ] Task 1
+ * [x] Task 2
+ EOT
+
+ markdown_html = Banzai::Pipeline::FullPipeline.call(markdown, project: nil)[:output].to_html
+ toggler = described_class.new(markdown, markdown_html,
+ toggle_as_checked: true,
+ line_source: '* [ ] Task 1', line_number: 5, index: 1)
+
+ expect(toggler.execute).to be_truthy
+ expect(toggler.updated_markdown.lines[4]).to eq "* [x] Task 1\n"
+ expect(toggler.updated_markdown_html).to include('disabled checked> Task 1')
+ end
end