summaryrefslogtreecommitdiff
path: root/lib/banzai
diff options
context:
space:
mode:
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/custom_emoji_filter.rb4
-rw-r--r--lib/banzai/filter/references/abstract_reference_filter.rb8
-rw-r--r--lib/banzai/filter/references/label_reference_filter.rb4
-rw-r--r--lib/banzai/filter/references/milestone_reference_filter.rb4
-rw-r--r--lib/banzai/filter/task_list_filter.rb86
-rw-r--r--lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb2
-rw-r--r--lib/banzai/reference_redactor.rb4
7 files changed, 98 insertions, 14 deletions
diff --git a/lib/banzai/filter/custom_emoji_filter.rb b/lib/banzai/filter/custom_emoji_filter.rb
index ae95c7f66b6..b589d264526 100644
--- a/lib/banzai/filter/custom_emoji_filter.rb
+++ b/lib/banzai/filter/custom_emoji_filter.rb
@@ -29,7 +29,7 @@ module Banzai
@emoji_pattern ||=
/(?<=[^[:alnum:]:]|\n|^)
:(#{CustomEmoji::NAME_REGEXP}):
- (?=[^[:alnum:]:]|$)/x
+ (?=[^[:alnum:]:]|$)/xo
end
def custom_emoji_name_element_filter(text)
@@ -58,7 +58,7 @@ module Banzai
end
def custom_emoji_candidates
- doc.to_html.scan(/:(#{CustomEmoji::NAME_REGEXP}):/).flatten
+ doc.to_html.scan(/:(#{CustomEmoji::NAME_REGEXP}):/o).flatten
end
def all_custom_emoji
diff --git a/lib/banzai/filter/references/abstract_reference_filter.rb b/lib/banzai/filter/references/abstract_reference_filter.rb
index 521fd7bf4cc..1ca38d2612d 100644
--- a/lib/banzai/filter/references/abstract_reference_filter.rb
+++ b/lib/banzai/filter/references/abstract_reference_filter.rb
@@ -240,11 +240,11 @@ module Banzai
object_parent_type = parent.is_a?(Group) ? :group : :project
{
- original: escape_html_entities(text),
- link: link_content,
- link_reference: link_reference,
+ original: escape_html_entities(text),
+ link: link_content,
+ link_reference: link_reference,
object_parent_type => parent.id,
- object_sym => object.id
+ object_sym => object.id
}
end
diff --git a/lib/banzai/filter/references/label_reference_filter.rb b/lib/banzai/filter/references/label_reference_filter.rb
index a019ae0108e..6020c7b7f58 100644
--- a/lib/banzai/filter/references/label_reference_filter.rb
+++ b/lib/banzai/filter/references/label_reference_filter.rb
@@ -12,13 +12,13 @@ module Banzai
return Label.none unless parent.is_a?(Project) || parent.is_a?(Group)
labels = find_labels(parent)
- label_ids = ids.map {|y| y[:label_id]}.compact
+ label_ids = ids.map { |y| y[:label_id] }.compact
unless label_ids.empty?
id_relation = labels.where(id: label_ids)
end
- label_names = ids.map {|y| y[:label_name]}.compact
+ label_names = ids.map { |y| y[:label_name] }.compact
unless label_names.empty?
label_relation = labels.where(title: label_names)
end
diff --git a/lib/banzai/filter/references/milestone_reference_filter.rb b/lib/banzai/filter/references/milestone_reference_filter.rb
index 609aaf885ba..77658f72d34 100644
--- a/lib/banzai/filter/references/milestone_reference_filter.rb
+++ b/lib/banzai/filter/references/milestone_reference_filter.rb
@@ -11,12 +11,12 @@ module Banzai
def parent_records(parent, ids)
return Milestone.none unless valid_context?(parent)
- milestone_iids = ids.map {|y| y[:milestone_iid]}.compact
+ milestone_iids = ids.map { |y| y[:milestone_iid] }.compact
unless milestone_iids.empty?
iid_relation = find_milestones(parent, true).where(iid: milestone_iids)
end
- milestone_names = ids.map {|y| y[:milestone_name]}.compact
+ milestone_names = ids.map { |y| y[:milestone_name] }.compact
unless milestone_names.empty?
milestone_relation = find_milestones(parent, false).where(name: milestone_names)
end
diff --git a/lib/banzai/filter/task_list_filter.rb b/lib/banzai/filter/task_list_filter.rb
index 896f67cb875..e8a7677b102 100644
--- a/lib/banzai/filter/task_list_filter.rb
+++ b/lib/banzai/filter/task_list_filter.rb
@@ -8,9 +8,93 @@ require 'task_list/filter'
# - app/assets/javascripts/behaviors/markdown/nodes/task_list_item.js
module Banzai
module Filter
+ # TaskList filter replaces task list item markers (`[ ]`, `[x]`, and `[~]`)
+ # with checkboxes, marked up with metadata and behavior.
+ #
+ # This should be run on the HTML generated by the Markdown filter, after the
+ # SanitizationFilter.
+ #
+ # Syntax
+ # ------
+ #
+ # Task list items must be in a list format:
+ #
+ # ```
+ # - [ ] incomplete
+ # - [x] complete
+ # - [~] inapplicable
+ # ```
+ #
+ # This class overrides TaskList::Filter in the `deckar01-task_list` gem
+ # to add support for inapplicable task items
class TaskListFilter < TaskList::Filter
+ extend ::Gitlab::Utils::Override
+
+ XPATH = 'descendant-or-self::li[input[@data-inapplicable]] | descendant-or-self::li[p[input[@data-inapplicable]]]'
+ INAPPLICABLE = '[~]'
+ INAPPLICABLEPATTERN = /\[~\]/.freeze
+
+ # Pattern used to identify all task list items.
+ # Useful when you need iterate over all items.
+ NEWITEMPATTERN = /
+ ^
+ (?:\s*[-+*]|(?:\d+\.))? # optional list prefix
+ \s* # optional whitespace prefix
+ ( # checkbox
+ #{CompletePattern}|
+ #{IncompletePattern}|
+ #{INAPPLICABLEPATTERN}
+ )
+ (?=\s) # followed by whitespace
+ /x.freeze
+
+ # Force the gem's constant to use our new one
+ superclass.send(:remove_const, :ItemPattern) # rubocop: disable GitlabSecurity/PublicSend
+ superclass.const_set(:ItemPattern, NEWITEMPATTERN)
+
+ def inapplicable?(item)
+ !!(item.checkbox_text =~ INAPPLICABLEPATTERN)
+ end
+
+ override :render_item_checkbox
def render_item_checkbox(item)
- "<task-button></task-button>#{super}"
+ %(<task-button></task-button><input type="checkbox"
+ class="task-list-item-checkbox"
+ #{'checked="checked"' if item.complete?}
+ #{'data-inapplicable' if inapplicable?(item)}
+ disabled="disabled"/>)
+ end
+
+ override :render_task_list_item
+ def render_task_list_item(item)
+ source = item.source
+
+ if inapplicable?(item)
+ # Add a `<s>` tag around the list item text. However because of the
+ # way tasks are built, the source can include an embedded sublist, like
+ # `[~] foobar\n<ol><li....`
+ # The `<s>` should only be added to the main text.
+ source = source.partition("#{INAPPLICABLE} ")
+ text = source.last.partition(/\<(ol|ul)/)
+ text[0] = "<s>#{text[0]}</s>"
+ source[-1] = text.join
+ source = source.join
+ end
+
+ Nokogiri::HTML.fragment \
+ source.sub(ItemPattern, render_item_checkbox(item)), 'utf-8'
+ end
+
+ override :call
+ def call
+ super
+
+ # add class to li for any inapplicable checkboxes
+ doc.xpath(XPATH).each do |li|
+ li.add_class('inapplicable')
+ end
+
+ doc
end
end
end
diff --git a/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb b/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb
index 01ee3f5d9e8..eef2b2674dd 100644
--- a/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb
+++ b/lib/banzai/pipeline/incident_management/timeline_event_pipeline.rb
@@ -11,9 +11,9 @@ module Banzai
def self.filters
@filters ||= FilterArray[
*super,
+ Filter::SanitizationFilter,
*Banzai::Pipeline::GfmPipeline.reference_filters,
Filter::EmojiFilter,
- Filter::SanitizationFilter,
Filter::ExternalLinkFilter,
Filter::ImageLinkFilter
]
diff --git a/lib/banzai/reference_redactor.rb b/lib/banzai/reference_redactor.rb
index c19f992078a..0c031ace977 100644
--- a/lib/banzai/reference_redactor.rb
+++ b/lib/banzai/reference_redactor.rb
@@ -41,8 +41,8 @@ module Banzai
nodes_for_document = entry[:nodes]
doc_data = {
- document: entry[:document],
- total_reference_count: nodes_for_document.count,
+ document: entry[:document],
+ total_reference_count: nodes_for_document.count,
visible_reference_count: nodes_for_document.count
}