Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/banzai/filter/custom_emoji_filter.rb')
-rw-r--r--lib/banzai/filter/custom_emoji_filter.rb62
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/banzai/filter/custom_emoji_filter.rb b/lib/banzai/filter/custom_emoji_filter.rb
new file mode 100644
index 00000000000..1ee8f4e31e8
--- /dev/null
+++ b/lib/banzai/filter/custom_emoji_filter.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class CustomEmojiFilter < HTML::Pipeline::Filter
+ IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
+
+ def call
+ return doc unless context[:project]
+ return doc unless Feature.enabled?(:custom_emoji, context[:project])
+
+ doc.search(".//text()").each do |node|
+ content = node.to_html
+
+ next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)
+ next unless content.include?(':')
+ next unless namespace && namespace.custom_emoji.any?
+
+ html = custom_emoji_name_element_filter(content)
+
+ node.replace(html) unless html == content
+ end
+
+ doc
+ end
+
+ def custom_emoji_pattern
+ @emoji_pattern ||=
+ /(?<=[^[:alnum:]:]|\n|^)
+ :(#{CustomEmoji::NAME_REGEXP}):
+ (?=[^[:alnum:]:]|$)/x
+ end
+
+ def custom_emoji_name_element_filter(text)
+ text.gsub(custom_emoji_pattern) do |match|
+ name = Regexp.last_match[1]
+ custom_emoji = all_custom_emoji[name]
+
+ if custom_emoji
+ Gitlab::Emoji.custom_emoji_tag(custom_emoji.name, custom_emoji.url)
+ else
+ match
+ end
+ end
+ end
+
+ private
+
+ def namespace
+ context[:project].namespace.root_ancestor
+ end
+
+ def custom_emoji_candidates
+ doc.to_html.scan(/:(#{CustomEmoji::NAME_REGEXP}):/).flatten
+ end
+
+ def all_custom_emoji
+ @all_custom_emoji ||= namespace.custom_emoji.by_name(custom_emoji_candidates).index_by(&:name)
+ end
+ end
+ end
+end