# frozen_string_literal: true require 'task_list' require 'task_list/filter' # Contains functionality for objects that can have task lists in their # descriptions. Task list items can be added with Markdown like "* [x] Fix # bugs". # # Used by MergeRequest and Issue module Taskable COMPLETED = 'completed' INCOMPLETE = 'incomplete' COMPLETE_PATTERN = /(\[[xX]\])/.freeze INCOMPLETE_PATTERN = /(\[\s\])/.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 (\s.+) # followed by whitespace and some text. }x.freeze def self.get_tasks(content) content.to_s.scan(ITEM_PATTERN).map do |prefix, checkbox, label| TaskList::Item.new("#{prefix} #{checkbox}", label.strip) end end def self.get_updated_tasks(old_content:, new_content:) old_tasks = get_tasks(old_content) new_tasks = get_tasks(new_content) new_tasks.select.with_index do |new_task, i| old_task = old_tasks[i] next unless old_task new_task.source == old_task.source && new_task.complete? != old_task.complete? end end # Called by `TaskList::Summary` def task_list_items return [] if description.blank? @task_list_items ||= Taskable.get_tasks(description) # rubocop:disable Gitlab/ModuleWithInstanceVariables end def tasks @tasks ||= TaskList.new(self) end # Return true if this object's description has any task list items. def tasks? tasks.summary.items? end # Return a string that describes the current state of this Taskable's task # list items, e.g. "12 of 20 tasks completed" def task_status(short: false) return '' if description.blank? prep, completed = if short ['/', ''] else [' of ', ' completed'] end sum = tasks.summary "#{sum.complete_count}#{prep}#{sum.item_count} #{'task'.pluralize(sum.item_count)}#{completed}" end # Return a short string that describes the current state of this Taskable's # task list items -- for small screens def task_status_short task_status(short: true) end def task_completion_status @task_completion_status ||= { count: tasks.summary.item_count, completed_count: tasks.summary.complete_count } end end