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-07-20 12:55:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 12:55:51 +0300
commite8d2c2579383897a1dd7f9debd359abe8ae8373d (patch)
treec42be41678c2586d49a75cabce89322082698334 /lib/banzai
parentfc845b37ec3a90aaa719975f607740c22ba6a113 (diff)
Add latest changes from gitlab-org/gitlab@14-1-stable-eev14.1.0-rc42
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/references/label_reference_filter.rb20
-rw-r--r--lib/banzai/filter/references/milestone_reference_filter.rb101
-rw-r--r--lib/banzai/filter/upload_link_filter.rb19
-rw-r--r--lib/banzai/filter/wiki_link_filter.rb19
-rw-r--r--lib/banzai/reference_extractor.rb4
-rw-r--r--lib/banzai/reference_parser/base_parser.rb12
-rw-r--r--lib/banzai/reference_parser/commit_parser.rb2
-rw-r--r--lib/banzai/reference_parser/commit_range_parser.rb2
-rw-r--r--lib/banzai/reference_parser/external_issue_parser.rb2
-rw-r--r--lib/banzai/reference_parser/issuable_parser.rb2
-rw-r--r--lib/banzai/reference_parser/user_parser.rb2
11 files changed, 125 insertions, 60 deletions
diff --git a/lib/banzai/filter/references/label_reference_filter.rb b/lib/banzai/filter/references/label_reference_filter.rb
index 12afece6e53..3ae9c5f8d90 100644
--- a/lib/banzai/filter/references/label_reference_filter.rb
+++ b/lib/banzai/filter/references/label_reference_filter.rb
@@ -11,13 +11,21 @@ module Banzai
def parent_records(parent, ids)
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_names = ids.map {|y| y[:label_name]}.compact
- id_relation = labels.where(id: label_ids)
- label_relation = labels.where(title: label_names)
+ labels = find_labels(parent)
+ label_ids = ids.map {|y| y[:label_id]}.compact
- Label.from_union([id_relation, label_relation])
+ unless label_ids.empty?
+ id_relation = labels.where(id: label_ids)
+ end
+
+ label_names = ids.map {|y| y[:label_name]}.compact
+ unless label_names.empty?
+ label_relation = labels.where(title: label_names)
+ end
+
+ return Label.none if (relation = [id_relation, label_relation].compact).empty?
+
+ Label.from_union(relation)
end
def find_object(parent_object, id)
diff --git a/lib/banzai/filter/references/milestone_reference_filter.rb b/lib/banzai/filter/references/milestone_reference_filter.rb
index 31a961f3e73..d992e667056 100644
--- a/lib/banzai/filter/references/milestone_reference_filter.rb
+++ b/lib/banzai/filter/references/milestone_reference_filter.rb
@@ -10,19 +10,55 @@ module Banzai
self.reference_type = :milestone
self.object_class = Milestone
- # Links to project milestones contain the IID, but when we're handling
- # 'regular' references, we need to use the global ID to disambiguate
- # between group and project milestones.
- def find_object(parent, id)
- return unless valid_context?(parent)
+ def parent_records(parent, ids)
+ return Milestone.none unless valid_context?(parent)
- find_milestone_with_finder(parent, id: id)
+ 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
+ unless milestone_names.empty?
+ milestone_relation = find_milestones(parent, false).where(name: milestone_names)
+ end
+
+ return Milestone.none if (relation = [iid_relation, milestone_relation].compact).empty?
+
+ Milestone.from_union(relation).includes(:project, :group)
+ end
+
+ def find_object(parent_object, id)
+ key = reference_cache.records_per_parent[parent_object].keys.find do |k|
+ k[:milestone_iid] == id[:milestone_iid] || k[:milestone_name] == id[:milestone_name]
+ end
+
+ reference_cache.records_per_parent[parent_object][key] if key
end
- def find_object_from_link(parent, iid)
- return unless valid_context?(parent)
+ # Transform a symbol extracted from the text to a meaningful value
+ #
+ # This method has the contract that if a string `ref` refers to a
+ # record `record`, then `parse_symbol(ref) == record_identifier(record)`.
+ #
+ # This contract is slightly broken here, as we only have either the milestone_iid
+ # or the milestone_name, but not both. But below, we have both pieces of information.
+ # But it's accounted for in `find_object`
+ def parse_symbol(symbol, match_data)
+ if symbol
+ # when parsing links, there is no `match_data[:milestone_iid]`, but `symbol`
+ # holds the iid
+ { milestone_iid: symbol.to_i, milestone_name: nil }
+ else
+ { milestone_iid: match_data[:milestone_iid]&.to_i, milestone_name: match_data[:milestone_name]&.tr('"', '') }
+ end
+ end
- find_milestone_with_finder(parent, iid: iid)
+ # This method has the contract that if a string `ref` refers to a
+ # record `record`, then `class.parse_symbol(ref) == record_identifier(record)`.
+ # See note in `parse_symbol` above
+ def record_identifier(record)
+ { milestone_iid: record.iid, milestone_name: record.name }
end
def valid_context?(parent)
@@ -50,12 +86,14 @@ module Banzai
return super(text, pattern) if pattern != Milestone.reference_pattern
milestones = {}
- unescaped_html = unescape_html_entities(text).gsub(pattern) do |match|
- milestone = find_milestone($~[:project], $~[:namespace], $~[:milestone_iid], $~[:milestone_name])
- if milestone
- milestones[milestone.id] = yield match, milestone.id, $~[:project], $~[:namespace], $~
- "#{REFERENCE_PLACEHOLDER}#{milestone.id}"
+ unescaped_html = unescape_html_entities(text).gsub(pattern).with_index do |match, index|
+ ident = identifier($~)
+ milestone = yield match, ident, $~[:project], $~[:namespace], $~
+
+ if milestone != match
+ milestones[index] = milestone
+ "#{REFERENCE_PLACEHOLDER}#{index}"
else
match
end
@@ -66,31 +104,10 @@ module Banzai
escape_with_placeholders(unescaped_html, milestones)
end
- def find_milestone(project_ref, namespace_ref, milestone_id, milestone_name)
- project_path = reference_cache.full_project_path(namespace_ref, project_ref)
-
- # Returns group if project is not found by path
- parent = parent_from_ref(project_path)
+ def find_milestones(parent, find_by_iid = false)
+ finder_params = milestone_finder_params(parent, find_by_iid)
- return unless parent
-
- milestone_params = milestone_params(milestone_id, milestone_name)
-
- find_milestone_with_finder(parent, milestone_params)
- end
-
- def milestone_params(iid, name)
- if name
- { name: name.tr('"', '') }
- else
- { iid: iid.to_i }
- end
- end
-
- def find_milestone_with_finder(parent, params)
- finder_params = milestone_finder_params(parent, params[:iid].present?)
-
- MilestonesFinder.new(finder_params).find_by(params)
+ MilestonesFinder.new(finder_params).execute
end
def milestone_finder_params(parent, find_by_iid)
@@ -131,6 +148,14 @@ module Banzai
def object_link_title(object, matches)
nil
end
+
+ def parent
+ project || group
+ end
+
+ def requires_unescaping?
+ true
+ end
end
end
end
diff --git a/lib/banzai/filter/upload_link_filter.rb b/lib/banzai/filter/upload_link_filter.rb
index 2572481c8fc..b110c59a4f1 100644
--- a/lib/banzai/filter/upload_link_filter.rb
+++ b/lib/banzai/filter/upload_link_filter.rb
@@ -45,13 +45,15 @@ module Banzai
return
end
- html_attr.value =
+ path =
if context[:only_path]
path
else
Addressable::URI.join(Gitlab.config.gitlab.base_url, path).to_s
end
+ replace_html_attr_value(html_attr, path)
+
if html_attr.name == 'href'
html_attr.parent.set_attribute('data-link', 'true')
end
@@ -59,6 +61,21 @@ module Banzai
html_attr.parent.add_class('gfm')
end
+ def replace_html_attr_value(html_attr, path)
+ if path != html_attr.value
+ preserve_original_link(html_attr, html_attr.parent)
+ end
+
+ html_attr.value = path
+ end
+
+ def preserve_original_link(html_attr, node)
+ return if html_attr.blank?
+ return if node.value?('data-canonical-src')
+
+ node.set_attribute('data-canonical-src', html_attr.value)
+ end
+
def group
context[:group]
end
diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb
index 2b95d87ff8e..0736181d940 100644
--- a/lib/banzai/filter/wiki_link_filter.rb
+++ b/lib/banzai/filter/wiki_link_filter.rb
@@ -36,7 +36,7 @@ module Banzai
protected
def process_link(link_attr, node)
- process_link_attr(link_attr)
+ process_link_attr(link_attr, node)
remove_unsafe_links({ node: node }, remove_invalid_links: false)
end
@@ -44,14 +44,27 @@ module Banzai
!context[:wiki].nil?
end
- def process_link_attr(html_attr)
+ def process_link_attr(html_attr, node)
return if html_attr.blank?
- html_attr.value = apply_rewrite_rules(html_attr.value)
+ rewritten_value = apply_rewrite_rules(html_attr.value)
+
+ if html_attr.value != rewritten_value
+ preserve_original_link(html_attr, node)
+ end
+
+ html_attr.value = rewritten_value
rescue URI::Error, Addressable::URI::InvalidURIError
# noop
end
+ def preserve_original_link(html_attr, node)
+ return if html_attr.blank?
+ return if node.value?('data-canonical-src')
+
+ node.set_attribute('data-canonical-src', html_attr.value)
+ end
+
def apply_rewrite_rules(link_string)
Rewriter.new(link_string, wiki: context[:wiki], slug: context[:page_slug]).apply_rules
end
diff --git a/lib/banzai/reference_extractor.rb b/lib/banzai/reference_extractor.rb
index 3fc3ae02088..af0dcad107e 100644
--- a/lib/banzai/reference_extractor.rb
+++ b/lib/banzai/reference_extractor.rb
@@ -11,11 +11,11 @@ module Banzai
@texts_and_contexts << { text: text, context: context }
end
- def references(type, project, current_user = nil)
+ def references(type, project, current_user, ids_only: false)
context = RenderContext.new(project, current_user)
processor = Banzai::ReferenceParser[type].new(context)
- processor.process(html_documents)
+ processor.process(html_documents, ids_only: ids_only)
end
def reset_memoized_values
diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb
index 3dfea8ee895..0c015ba00c7 100644
--- a/lib/banzai/reference_parser/base_parser.rb
+++ b/lib/banzai/reference_parser/base_parser.rb
@@ -76,9 +76,11 @@ module Banzai
end
# Returns an Array of objects referenced by any of the given HTML nodes.
- def referenced_by(nodes)
+ def referenced_by(nodes, options = {})
ids = unique_attribute_values(nodes, self.class.data_attribute)
+ return ids if options.fetch(:ids_only, false)
+
if ids.empty?
references_relation.none
else
@@ -194,7 +196,7 @@ module Banzai
# Processes the list of HTML documents and returns an Array containing all
# the references.
- def process(documents)
+ def process(documents, ids_only: false)
type = self.class.reference_type
reference_options = self.class.reference_options
@@ -202,17 +204,17 @@ module Banzai
Querying.css(document, "a[data-reference-type='#{type}'].gfm", reference_options).to_a
end
- gather_references(nodes)
+ gather_references(nodes, ids_only: ids_only)
end
# Gathers the references for the given HTML nodes. Returns visible
# references and a list of nodes which are not visible to the user
- def gather_references(nodes)
+ def gather_references(nodes, ids_only: false)
nodes = nodes_user_can_reference(current_user, nodes)
visible = nodes_visible_to_user(current_user, nodes)
not_visible = nodes - visible
- { visible: referenced_by(visible), not_visible: not_visible }
+ { visible: referenced_by(visible, ids_only: ids_only), not_visible: not_visible }
end
# Returns a Hash containing the projects for a given list of HTML nodes.
diff --git a/lib/banzai/reference_parser/commit_parser.rb b/lib/banzai/reference_parser/commit_parser.rb
index 0bfb6a92020..88896970bc6 100644
--- a/lib/banzai/reference_parser/commit_parser.rb
+++ b/lib/banzai/reference_parser/commit_parser.rb
@@ -5,7 +5,7 @@ module Banzai
class CommitParser < BaseParser
self.reference_type = :commit
- def referenced_by(nodes)
+ def referenced_by(nodes, options = {})
commit_ids = commit_ids_per_project(nodes)
projects = find_projects_for_hash_keys(commit_ids)
diff --git a/lib/banzai/reference_parser/commit_range_parser.rb b/lib/banzai/reference_parser/commit_range_parser.rb
index 480eefd5c4d..fb4a392105f 100644
--- a/lib/banzai/reference_parser/commit_range_parser.rb
+++ b/lib/banzai/reference_parser/commit_range_parser.rb
@@ -5,7 +5,7 @@ module Banzai
class CommitRangeParser < BaseParser
self.reference_type = :commit_range
- def referenced_by(nodes)
+ def referenced_by(nodes, options = {})
range_ids = commit_range_ids_per_project(nodes)
projects = find_projects_for_hash_keys(range_ids)
diff --git a/lib/banzai/reference_parser/external_issue_parser.rb b/lib/banzai/reference_parser/external_issue_parser.rb
index 029b09dcd25..e8ee337064a 100644
--- a/lib/banzai/reference_parser/external_issue_parser.rb
+++ b/lib/banzai/reference_parser/external_issue_parser.rb
@@ -5,7 +5,7 @@ module Banzai
class ExternalIssueParser < BaseParser
self.reference_type = :external_issue
- def referenced_by(nodes)
+ def referenced_by(nodes, options = {})
issue_ids = issue_ids_per_project(nodes)
projects = find_projects_for_hash_keys(issue_ids)
issues = []
diff --git a/lib/banzai/reference_parser/issuable_parser.rb b/lib/banzai/reference_parser/issuable_parser.rb
index f8c26288017..efcaa6664b6 100644
--- a/lib/banzai/reference_parser/issuable_parser.rb
+++ b/lib/banzai/reference_parser/issuable_parser.rb
@@ -13,7 +13,7 @@ module Banzai
end
end
- def referenced_by(nodes)
+ def referenced_by(nodes, options = {})
records = records_for_nodes(nodes)
nodes.map { |node| records[node] }.compact.uniq
diff --git a/lib/banzai/reference_parser/user_parser.rb b/lib/banzai/reference_parser/user_parser.rb
index 36c41c6615f..c40ca9dc7cd 100644
--- a/lib/banzai/reference_parser/user_parser.rb
+++ b/lib/banzai/reference_parser/user_parser.rb
@@ -5,7 +5,7 @@ module Banzai
class UserParser < BaseParser
self.reference_type = :user
- def referenced_by(nodes)
+ def referenced_by(nodes, options = {})
group_ids = []
user_ids = []
project_ids = []