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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-18 13:34:06 +0300
commit859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch)
treed7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /lib/banzai
parent446d496a6d000c73a304be52587cd9bbc7493136 (diff)
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/asset_proxy_filter.rb4
-rw-r--r--lib/banzai/filter/custom_emoji_filter.rb62
-rw-r--r--lib/banzai/filter/feature_flag_reference_filter.rb33
-rw-r--r--lib/banzai/filter/markdown_post_escape_filter.rb40
-rw-r--r--lib/banzai/filter/markdown_pre_escape_filter.rb43
-rw-r--r--lib/banzai/filter/plantuml_filter.rb2
-rw-r--r--lib/banzai/filter/truncate_source_filter.rb4
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb4
-rw-r--r--lib/banzai/pipeline/plain_markdown_pipeline.rb4
-rw-r--r--lib/banzai/pipeline/single_line_pipeline.rb3
-rw-r--r--lib/banzai/reference_parser/feature_flag_parser.rb19
11 files changed, 212 insertions, 6 deletions
diff --git a/lib/banzai/filter/asset_proxy_filter.rb b/lib/banzai/filter/asset_proxy_filter.rb
index 55dc426edaf..4c14ee7299b 100644
--- a/lib/banzai/filter/asset_proxy_filter.rb
+++ b/lib/banzai/filter/asset_proxy_filter.rb
@@ -59,7 +59,9 @@ module Banzai
end
def self.determine_allowlist(application_settings)
- application_settings.asset_proxy_whitelist.presence || [Gitlab.config.gitlab.host]
+ application_settings.try(:asset_proxy_allowlist).presence ||
+ application_settings.try(:asset_proxy_whitelist).presence ||
+ [Gitlab.config.gitlab.host]
end
end
end
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
diff --git a/lib/banzai/filter/feature_flag_reference_filter.rb b/lib/banzai/filter/feature_flag_reference_filter.rb
new file mode 100644
index 00000000000..c11576901ce
--- /dev/null
+++ b/lib/banzai/filter/feature_flag_reference_filter.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class FeatureFlagReferenceFilter < IssuableReferenceFilter
+ self.reference_type = :feature_flag
+
+ def self.object_class
+ Operations::FeatureFlag
+ end
+
+ def self.object_sym
+ :feature_flag
+ end
+
+ def parent_records(parent, ids)
+ parent.operations_feature_flags.where(iid: ids.to_a)
+ end
+
+ def url_for_object(feature_flag, project)
+ ::Gitlab::Routing.url_helpers.edit_project_feature_flag_url(
+ project,
+ feature_flag.iid,
+ only_path: context[:only_path]
+ )
+ end
+
+ def object_link_title(object, matches)
+ object.name
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/markdown_post_escape_filter.rb b/lib/banzai/filter/markdown_post_escape_filter.rb
new file mode 100644
index 00000000000..ad32e9afbf5
--- /dev/null
+++ b/lib/banzai/filter/markdown_post_escape_filter.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ class MarkdownPostEscapeFilter < HTML::Pipeline::Filter
+ LITERAL_KEYWORD = MarkdownPreEscapeFilter::LITERAL_KEYWORD
+ LITERAL_REGEX = %r{#{LITERAL_KEYWORD}-(.*?)-#{LITERAL_KEYWORD}}.freeze
+ NOT_LITERAL_REGEX = %r{#{LITERAL_KEYWORD}-((%5C|\\).+?)-#{LITERAL_KEYWORD}}.freeze
+ SPAN_REGEX = %r{<span>(.*?)</span>}.freeze
+
+ def call
+ return doc unless result[:escaped_literals]
+
+ # For any literals that actually didn't get escape processed
+ # (for example in code blocks), remove the special sequence.
+ html.gsub!(NOT_LITERAL_REGEX, '\1')
+
+ # Replace any left over literal sequences with `span` so that our
+ # reference processing is short-circuited
+ html.gsub!(LITERAL_REGEX, '<span>\1</span>')
+
+ # Since literals are converted in links, we need to remove any surrounding `span`.
+ # Note: this could have been done in the renderer,
+ # Banzai::Renderer::CommonMark::HTML. However, we eventually want to use
+ # the built-in compiled renderer, rather than the ruby version, for speed.
+ # So let's do this work here.
+ doc.css('a').each do |node|
+ node.attributes['href'].value = node.attributes['href'].value.gsub(SPAN_REGEX, '\1') if node.attributes['href']
+ node.attributes['title'].value = node.attributes['title'].value.gsub(SPAN_REGEX, '\1') if node.attributes['title']
+ end
+
+ doc.css('code').each do |node|
+ node.attributes['lang'].value = node.attributes['lang'].value.gsub(SPAN_REGEX, '\1') if node.attributes['lang']
+ end
+
+ doc
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/markdown_pre_escape_filter.rb b/lib/banzai/filter/markdown_pre_escape_filter.rb
new file mode 100644
index 00000000000..9fd77c48659
--- /dev/null
+++ b/lib/banzai/filter/markdown_pre_escape_filter.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ # In order to allow a user to short-circuit our reference shortcuts
+ # (such as # or !), the user should be able to escape them, like \#.
+ # CommonMark supports this, however it removes all information about
+ # what was actually a literal. In order to short-circuit the reference,
+ # we must surround backslash escaped ASCII punctuation with a custom sequence.
+ # This way CommonMark will properly handle the backslash escaped chars
+ # but we will maintain knowledge (the sequence) that it was a literal.
+ #
+ # We need to surround the character, not just prefix it. It could
+ # get converted into an entity by CommonMark and we wouldn't know how many
+ # characters there are. The entire literal needs to be surrounded with
+ # a `span` tag, which short-circuits our reference processing.
+ #
+ # We can't use a custom HTML tag since we could be initially surrounding
+ # text in an href, and then CommonMark will not be able to parse links
+ # properly. So we use `cmliteral-` and `-cmliteral`
+ #
+ # https://spec.commonmark.org/0.29/#backslash-escapes
+ #
+ # This filter does the initial surrounding, and MarkdownPostEscapeFilter
+ # does the conversion into span tags.
+ class MarkdownPreEscapeFilter < HTML::Pipeline::TextFilter
+ ASCII_PUNCTUATION = %r{([\\][!"#$%&'()*+,-./:;<=>?@\[\\\]^_`{|}~])}.freeze
+ LITERAL_KEYWORD = 'cmliteral'
+
+ def call
+ return @text unless Feature.enabled?(:honor_escaped_markdown, context[:group] || context[:project]&.group)
+
+ @text.gsub(ASCII_PUNCTUATION) do |match|
+ # The majority of markdown does not have literals. If none
+ # are found, we can bypass the post filter
+ result[:escaped_literals] = true
+
+ "#{LITERAL_KEYWORD}-#{match}-#{LITERAL_KEYWORD}"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index 1a75cd14b11..37d4126c1ba 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -9,7 +9,7 @@ module Banzai
#
class PlantumlFilter < HTML::Pipeline::Filter
def call
- return doc unless doc.at('pre > code[lang="plantuml"]') && settings.plantuml_enabled
+ return doc unless settings.plantuml_enabled? && doc.at('pre > code[lang="plantuml"]')
plantuml_setup
diff --git a/lib/banzai/filter/truncate_source_filter.rb b/lib/banzai/filter/truncate_source_filter.rb
index c903b83d868..44f88b253d9 100644
--- a/lib/banzai/filter/truncate_source_filter.rb
+++ b/lib/banzai/filter/truncate_source_filter.rb
@@ -6,7 +6,9 @@ module Banzai
def call
return text unless context.key?(:limit)
- text.truncate_bytes(context[:limit])
+ # Use three dots instead of the ellipsis Unicode character because
+ # some clients show the raw Unicode value in the merge commit.
+ text.truncate_bytes(context[:limit], omission: '...')
end
end
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 344afc9b33c..e5ec0a0a006 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -34,6 +34,7 @@ module Banzai
Filter::FootnoteFilter,
*reference_filters,
Filter::EmojiFilter,
+ Filter::CustomEmojiFilter,
Filter::TaskListFilter,
Filter::InlineDiffFilter,
Filter::SetDirectionFilter
@@ -61,7 +62,8 @@ module Banzai
Filter::CommitReferenceFilter,
Filter::LabelReferenceFilter,
Filter::MilestoneReferenceFilter,
- Filter::AlertReferenceFilter
+ Filter::AlertReferenceFilter,
+ Filter::FeatureFlagReferenceFilter
]
end
diff --git a/lib/banzai/pipeline/plain_markdown_pipeline.rb b/lib/banzai/pipeline/plain_markdown_pipeline.rb
index b64f13cde47..1da0f72996b 100644
--- a/lib/banzai/pipeline/plain_markdown_pipeline.rb
+++ b/lib/banzai/pipeline/plain_markdown_pipeline.rb
@@ -5,7 +5,9 @@ module Banzai
class PlainMarkdownPipeline < BasePipeline
def self.filters
FilterArray[
- Filter::MarkdownFilter
+ Filter::MarkdownPreEscapeFilter,
+ Filter::MarkdownFilter,
+ Filter::MarkdownPostEscapeFilter
]
end
end
diff --git a/lib/banzai/pipeline/single_line_pipeline.rb b/lib/banzai/pipeline/single_line_pipeline.rb
index a2fe6d52a90..4bf98099662 100644
--- a/lib/banzai/pipeline/single_line_pipeline.rb
+++ b/lib/banzai/pipeline/single_line_pipeline.rb
@@ -24,7 +24,8 @@ module Banzai
Filter::SnippetReferenceFilter,
Filter::CommitRangeReferenceFilter,
Filter::CommitReferenceFilter,
- Filter::AlertReferenceFilter
+ Filter::AlertReferenceFilter,
+ Filter::FeatureFlagReferenceFilter
]
end
diff --git a/lib/banzai/reference_parser/feature_flag_parser.rb b/lib/banzai/reference_parser/feature_flag_parser.rb
new file mode 100644
index 00000000000..6092b0f7e66
--- /dev/null
+++ b/lib/banzai/reference_parser/feature_flag_parser.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Banzai
+ module ReferenceParser
+ class FeatureFlagParser < BaseParser
+ self.reference_type = :feature_flag
+
+ def references_relation
+ Operations::FeatureFlag
+ end
+
+ private
+
+ def can_read_reference?(user, feature_flag, node)
+ can?(user, :read_feature_flag, feature_flag)
+ end
+ end
+ end
+end