diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js index a5e2ee463a9d1ce070c7057a7a42e115e41f9604..52fa90c77917c272d275d1de72e8c40d5c282834 100644 --- a/app/assets/javascripts/lib/utils/text_markdown.js +++ b/app/assets/javascripts/lib/utils/text_markdown.js @@ -9,7 +9,7 @@ const LINK_TAG_PATTERN = '[{text}](url)'; // a bullet point character (*+-) and an optional checkbox ([ ] [x]) // OR a number with a . after it and an optional checkbox ([ ] [x]) // followed by one or more whitespace characters -const LIST_LINE_HEAD_PATTERN = /^(?\s*)(?((?[*+-])|(?\d+\.))( \[([xX ])\])?\s)(?.)?/; +const LIST_LINE_HEAD_PATTERN = /^(?\s*)(?((?[*+-])|(?\d+\.))( \[([xX\s])\])?\s)(?.)?/; // detect a horizontal rule that might be mistaken for a list item (not full pattern for an
) const HR_PATTERN = /^((\s{0,3}-+\s*-+\s*-+\s*[\s-]*)|(\s{0,3}\*+\s*\*+\s*\*+\s*[\s*]*))$/; diff --git a/app/models/concerns/taskable.rb b/app/models/concerns/taskable.rb index e41a0ca28f928e3c5432afedb3f0c91e8909e3e4..904c96b11b310cb174e94cad774884db00dfd4d6 100644 --- a/app/models/concerns/taskable.rb +++ b/app/models/concerns/taskable.rb @@ -11,14 +11,16 @@ module Taskable COMPLETED = 'completed' INCOMPLETE = 'incomplete' - COMPLETE_PATTERN = /(\[[xX]\])/.freeze - INCOMPLETE_PATTERN = /(\[\s\])/.freeze + COMPLETE_PATTERN = /\[[xX]\]/.freeze + INCOMPLETE_PATTERN = /\[[[:space:]]\]/.freeze ITEM_PATTERN = %r{ ^ (?:(?:>\s{0,4})*) # optional blockquote characters ((?:\s*(?:[-+*]|(?:\d+\.)))+) # list prefix (one or more) required - task item has to be always in a list \s+ # whitespace prefix has to be always presented for a list item - (\[\s\]|\[[xX]\]) # checkbox + ( # checkbox + #{COMPLETE_PATTERN}|#{INCOMPLETE_PATTERN} + ) (\s.+) # followed by whitespace and some text. }x.freeze diff --git a/spec/frontend/lib/utils/text_markdown_spec.js b/spec/frontend/lib/utils/text_markdown_spec.js index 9949327d28adb26516b6233dba1c2363e577ea6a..103305f079780df4da0ffeeb3f627126510b67a4 100644 --- a/spec/frontend/lib/utils/text_markdown_spec.js +++ b/spec/frontend/lib/utils/text_markdown_spec.js @@ -183,6 +183,7 @@ describe('init markdown', () => { ${'- [ ] item'} | ${'- [ ] item\n- [ ] '} ${'- [x] item'} | ${'- [x] item\n- [ ] '} ${'- [X] item'} | ${'- [X] item\n- [ ] '} + ${'- [ ] nbsp (U+00A0)'} | ${'- [ ] nbsp (U+00A0)\n- [ ] '} ${'- item\n - second'} | ${'- item\n - second\n - '} ${'- - -'} | ${'- - -'} ${'- --'} | ${'- --'} diff --git a/spec/models/concerns/taskable_spec.rb b/spec/models/concerns/taskable_spec.rb index 6b41174a046179a99bb68bd7e07521ebbcef0fd6..140f6cda51cc028483a98ee55fade94535a8cfd6 100644 --- a/spec/models/concerns/taskable_spec.rb +++ b/spec/models/concerns/taskable_spec.rb @@ -13,6 +13,10 @@ - [x] Second item * [x] First item * [ ] Second item + + [ ] No-break space (U+00A0) + + [ ] Figure space (U+2007) + + [ ] Narrow no-break space (U+202F) + + [ ] Thin space (U+2009) MARKDOWN end @@ -21,7 +25,11 @@ TaskList::Item.new('- [ ]', 'First item'), TaskList::Item.new('- [x]', 'Second item'), TaskList::Item.new('* [x]', 'First item'), - TaskList::Item.new('* [ ]', 'Second item') + TaskList::Item.new('* [ ]', 'Second item'), + TaskList::Item.new('+ [ ]', 'No-break space (U+00A0)'), + TaskList::Item.new('+ [ ]', 'Figure space (U+2007)'), + TaskList::Item.new('+ [ ]', 'Narrow no-break space (U+202F)'), + TaskList::Item.new('+ [ ]', 'Thin space (U+2009)') ] end diff --git a/spec/services/task_list_toggle_service_spec.rb b/spec/services/task_list_toggle_service_spec.rb index 81f80ee926a4b3018c0df237d243a13ea1b3ac20..f889f29821307813e66215b436492c67dbb42609 100644 --- a/spec/services/task_list_toggle_service_spec.rb +++ b/spec/services/task_list_toggle_service_spec.rb @@ -16,6 +16,8 @@ - [ ] loose list with an embedded paragraph + + + [ ] No-break space (U+00A0) EOT end @@ -40,12 +42,17 @@ -
    -
  • +
      +
    • loose list

      with an embedded paragraph

    +
      +
    • + No-break space (U+00A0) +
    • +
    EOT end @@ -79,6 +86,16 @@ expect(toggler.updated_markdown_html).to include('disabled checked> loose list') end + it 'checks task with no-break space' do + toggler = described_class.new(markdown, markdown_html, + toggle_as_checked: true, + line_source: '+ [ ] No-break space (U+00A0)', line_number: 13) + + expect(toggler.execute).to be_truthy + expect(toggler.updated_markdown.lines[12]).to eq "+ [x] No-break space (U+00A0)" + expect(toggler.updated_markdown_html).to include('disabled checked> No-break space (U+00A0)') + end + it 'returns false if line_source does not match the text' do toggler = described_class.new(markdown, markdown_html, toggle_as_checked: false,