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>2022-11-17 14:33:21 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-11-17 14:33:21 +0300
commit7021455bd1ed7b125c55eb1b33c5a01f2bc55ee0 (patch)
tree5bdc2229f5198d516781f8d24eace62fc7e589e9 /lib/banzai
parent185b095e93520f96e9cfc31d9c3e69b498cdab7c (diff)
Add latest changes from gitlab-org/gitlab@15-6-stable-eev15.6.0-rc42
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/external_link_filter.rb12
-rw-r--r--lib/banzai/filter/footnote_filter.rb28
-rw-r--r--lib/banzai/filter/kroki_filter.rb21
-rw-r--r--lib/banzai/filter/math_filter.rb36
-rw-r--r--lib/banzai/filter/plantuml_filter.rb10
-rw-r--r--lib/banzai/filter/repository_link_filter.rb1
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb50
-rw-r--r--lib/banzai/filter/table_of_contents_filter.rb16
-rw-r--r--lib/banzai/pipeline/ascii_doc_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb4
-rw-r--r--lib/banzai/reference_parser/base_parser.rb10
-rw-r--r--lib/banzai/reference_parser/commit_parser.rb7
-rw-r--r--lib/banzai/reference_parser/commit_range_parser.rb7
13 files changed, 117 insertions, 87 deletions
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index d1a0f8e5859..0a76c84efe5 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -22,12 +22,12 @@ module Banzai
addressable_uri = nil
end
- unless internal_url?(addressable_uri)
- punycode_autolink_node!(addressable_uri, node)
- sanitize_link_text!(node)
- add_malicious_tooltip!(addressable_uri, node)
- add_nofollow!(addressable_uri, node)
- end
+ next if internal_url?(addressable_uri)
+
+ punycode_autolink_node!(addressable_uri, node)
+ sanitize_link_text!(node)
+ add_malicious_tooltip!(addressable_uri, node)
+ add_nofollow!(addressable_uri, node)
end
doc
diff --git a/lib/banzai/filter/footnote_filter.rb b/lib/banzai/filter/footnote_filter.rb
index f5c4b788ad8..f10efdccdf1 100644
--- a/lib/banzai/filter/footnote_filter.rb
+++ b/lib/banzai/filter/footnote_filter.rb
@@ -44,25 +44,25 @@ module Banzai
node_xpath = Gitlab::Utils::Nokogiri.css_to_xpath(css)
footnote_node = doc.at_xpath(node_xpath)
- if footnote_node || modified_footnotes[ref_num]
- link_node[:href] += rand_suffix
- link_node[:id] += rand_suffix
+ next unless footnote_node || modified_footnotes[ref_num]
- # Sanitization stripped off class - add it back in
- link_node.parent.append_class('footnote-ref')
+ link_node[:href] += rand_suffix
+ link_node[:id] += rand_suffix
- unless modified_footnotes[ref_num]
- footnote_node[:id] += rand_suffix
- backref_node = footnote_node.at_css("a[href=\"##{fnref_id(ref_num)}\"]")
+ # Sanitization stripped off class - add it back in
+ link_node.parent.append_class('footnote-ref')
- if backref_node
- backref_node[:href] += rand_suffix
- backref_node.append_class('footnote-backref')
- end
+ next if modified_footnotes[ref_num]
- modified_footnotes[ref_num] = true
- end
+ footnote_node[:id] += rand_suffix
+ backref_node = footnote_node.at_css("a[href=\"##{fnref_id(ref_num)}\"]")
+
+ if backref_node
+ backref_node[:href] += rand_suffix
+ backref_node.append_class('footnote-backref')
end
+
+ modified_footnotes[ref_num] = true
end
doc
diff --git a/lib/banzai/filter/kroki_filter.rb b/lib/banzai/filter/kroki_filter.rb
index 713ff2439fc..26f42c6b194 100644
--- a/lib/banzai/filter/kroki_filter.rb
+++ b/lib/banzai/filter/kroki_filter.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require "nokogiri"
-require "asciidoctor/extensions/asciidoctor_kroki/extension"
+require 'nokogiri'
+require 'asciidoctor/extensions/asciidoctor_kroki/version'
+require 'asciidoctor/extensions/asciidoctor_kroki/extension'
module Banzai
module Filter
@@ -31,16 +32,16 @@ module Banzai
img_tag = Nokogiri::HTML::DocumentFragment.parse(%(<img src="#{image_src}" />))
img_tag = img_tag.children.first
- unless img_tag.nil?
- lazy_load = diagram_src.length > MAX_CHARACTER_LIMIT
- img_tag.set_attribute('hidden', '') if lazy_load
- img_tag.set_attribute('class', 'js-render-kroki')
+ next if img_tag.nil?
- img_tag.set_attribute('data-diagram', diagram_type)
- img_tag.set_attribute('data-diagram-src', "data:text/plain;base64,#{Base64.strict_encode64(diagram_src)}")
+ lazy_load = diagram_src.length > MAX_CHARACTER_LIMIT
+ img_tag.set_attribute('hidden', '') if lazy_load
+ img_tag.set_attribute('class', 'js-render-kroki')
- node.parent.replace(img_tag)
- end
+ img_tag.set_attribute('data-diagram', diagram_type)
+ img_tag.set_attribute('data-diagram-src', "data:text/plain;base64,#{Base64.strict_encode64(diagram_src)}")
+
+ node.parent.replace(img_tag)
end
doc
diff --git a/lib/banzai/filter/math_filter.rb b/lib/banzai/filter/math_filter.rb
index 1ca4b2c89db..1d854d6599b 100644
--- a/lib/banzai/filter/math_filter.rb
+++ b/lib/banzai/filter/math_filter.rb
@@ -10,7 +10,7 @@ module Banzai
# HTML filter that implements our math syntax, adding class="code math"
#
class MathFilter < HTML::Pipeline::Filter
- CSS_MATH = 'pre.code.language-math'
+ CSS_MATH = 'pre[lang="math"] > code'
XPATH_MATH = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_MATH).freeze
CSS_CODE = 'code'
XPATH_CODE = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_CODE).freeze
@@ -32,7 +32,7 @@ module Banzai
# Corresponds to the $$\n...\n$$ syntax
DOLLAR_DISPLAY_BLOCK_PATTERN = %r{
^(?<matched>\$\$\ *\n(?<math>.*)\n\$\$\ *)$
- }x.freeze
+ }mx.freeze
# Order dependent. Handle the `$$` syntax before the `$` syntax
DOLLAR_MATH_PIPELINE = [
@@ -107,27 +107,27 @@ module Banzai
# We need a sibling before and after.
# They should end and start with $ respectively.
- if closing && opening &&
- closing.text? && opening.text? &&
- closing.content.first == DOLLAR_SIGN &&
- opening.content.last == DOLLAR_SIGN
-
- code[:class] = MATH_CLASSES
- code[STYLE_ATTRIBUTE] = 'inline'
- closing.content = closing.content[1..]
- opening.content = opening.content[0..-2]
-
- @nodes_count += 1
- break if @nodes_count >= RENDER_NODES_LIMIT
- end
+ next unless closing && opening &&
+ closing.text? && opening.text? &&
+ closing.content.first == DOLLAR_SIGN &&
+ opening.content.last == DOLLAR_SIGN
+
+ code[:class] = MATH_CLASSES
+ code[STYLE_ATTRIBUTE] = 'inline'
+ closing.content = closing.content[1..]
+ opening.content = opening.content[0..-2]
+
+ @nodes_count += 1
+ break if @nodes_count >= RENDER_NODES_LIMIT
end
end
# corresponds to the "```math...```" syntax
def process_math_codeblock
- doc.xpath(XPATH_MATH).each do |el|
- el[STYLE_ATTRIBUTE] = 'display'
- el[:class] += " #{TAG_CLASS}"
+ doc.xpath(XPATH_MATH).each do |node|
+ pre_node = node.parent
+ pre_node[STYLE_ATTRIBUTE] = 'display'
+ pre_node[:class] = TAG_CLASS
end
end
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index 82f6247cf03..6a1fa64fb76 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -17,12 +17,12 @@ module Banzai
img_tag = Nokogiri::HTML::DocumentFragment.parse(
Asciidoctor::PlantUml::Processor.plantuml_content(node.content, {})).css('img').first
- unless img_tag.nil?
- img_tag.set_attribute('data-diagram', 'plantuml')
- img_tag.set_attribute('data-diagram-src', "data:text/plain;base64,#{Base64.strict_encode64(node.content)}")
+ next if img_tag.nil?
- node.parent.replace(img_tag)
- end
+ img_tag.set_attribute('data-diagram', 'plantuml')
+ img_tag.set_attribute('data-diagram-src', "data:text/plain;base64,#{Base64.strict_encode64(node.content)}")
+
+ node.parent.replace(img_tag)
end
doc
diff --git a/lib/banzai/filter/repository_link_filter.rb b/lib/banzai/filter/repository_link_filter.rb
index f5cf1833304..e95da735647 100644
--- a/lib/banzai/filter/repository_link_filter.rb
+++ b/lib/banzai/filter/repository_link_filter.rb
@@ -101,6 +101,7 @@ module Banzai
if uri.relative? && uri.path.present?
html_attr.value = rebuild_relative_uri(uri).to_s
+ html_attr.parent.add_class('gfm')
end
rescue URI::Error, Addressable::URI::InvalidURIError
# noop
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 7175e99f1c7..766715d9e39 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
require 'rouge/plugins/common_mark'
-require "asciidoctor/extensions/asciidoctor_kroki/extension"
+require 'asciidoctor/extensions/asciidoctor_kroki/version'
+require 'asciidoctor/extensions/asciidoctor_kroki/extension'
# Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/nodes/code_block.js
module Banzai
@@ -13,8 +14,9 @@ module Banzai
LANG_PARAMS_DELIMITER = ':'
LANG_PARAMS_ATTR = 'data-lang-params'
+ CSS_CLASSES = 'code highlight js-syntax-highlight'
- CSS = 'pre:not([data-math-style]):not([data-mermaid-style]):not([data-kroki-style]) > code:only-child'
+ CSS = 'pre:not([data-kroki-style]) > code:only-child'
XPATH = Gitlab::Utils::Nokogiri.css_to_xpath(CSS).freeze
def call
@@ -26,9 +28,9 @@ module Banzai
end
def highlight_node(node)
- css_classes = +'code highlight js-syntax-highlight'
+ return if node.parent&.parent.nil?
+
lang, lang_params = parse_lang_params(node)
- sourcepos = node.parent.attr('data-sourcepos')
retried = false
if use_rouge?(lang)
@@ -41,7 +43,6 @@ module Banzai
begin
code = Rouge::Formatters::HTMLGitlab.format(lex(lexer, node.text), tag: language)
- css_classes << " language-#{language}" if language
rescue StandardError
# Gracefully handle syntax highlighter bugs/errors to ensure users can
# still access an issue/comment/etc. First, retry with the plain text
@@ -56,16 +57,26 @@ module Banzai
retry
end
- sourcepos_attr = sourcepos ? "data-sourcepos=\"#{escape_once(sourcepos)}\"" : ''
+ # maintain existing attributes already added. e.g math and mermaid nodes
+ node.children = code
+ pre_node = node.parent
+
+ # ensure there are no extra children, such as a text node that might
+ # show up from an XSS attack
+ pre_node.children = node
+
+ pre_node[:lang] = language
+ pre_node.add_class(CSS_CLASSES)
+ pre_node.add_class("language-#{language}") if language
+ pre_node.set_attribute('data-canonical-lang', escape_once(lang)) if lang != language
+ pre_node.set_attribute(LANG_PARAMS_ATTR, escape_once(lang_params)) if lang_params.present?
+ pre_node.set_attribute('v-pre', 'true')
+ pre_node.remove_attribute('data-meta')
- highlighted = %(<div class="gl-relative markdown-code-block js-markdown-code"><pre #{sourcepos_attr} class="#{css_classes}"
- lang="#{language}"
- #{lang != language ? "data-canonical-lang=\"#{escape_once(lang)}\"" : ""}
- #{lang_params}
- v-pre="true"><code>#{code}</code></pre><copy-code></copy-code></div>)
+ highlighted = %(<div class="gl-relative markdown-code-block js-markdown-code">#{pre_node.to_html}<copy-code></copy-code></div>)
# Extracted to a method to measure it
- replace_parent_pre_element(node, highlighted)
+ replace_pre_element(pre_node, highlighted)
end
private
@@ -93,9 +104,8 @@ module Banzai
language, language_params = language.split(LANG_PARAMS_DELIMITER, 2)
language_params = [node.attr('data-meta'), language_params].compact.join(' ')
- formatted_language_params = format_language_params(language_params)
- [language, formatted_language_params]
+ [language, language_params]
end
# Separate method so it can be instrumented.
@@ -107,20 +117,14 @@ module Banzai
(Rouge::Lexer.find(language) || Rouge::Lexers::PlainText).new
end
- # Replace the parent `pre` element with the entire highlighted block
- def replace_parent_pre_element(node, highlighted)
- node.parent.replace(highlighted)
+ # Replace the `pre` element with the entire highlighted block
+ def replace_pre_element(pre_node, highlighted)
+ pre_node.replace(highlighted)
end
def use_rouge?(language)
(%w(math suggestion) + ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES).exclude?(language)
end
-
- def format_language_params(language_params)
- return if language_params.blank?
-
- %(#{LANG_PARAMS_ATTR}="#{escape_once(language_params)}")
- end
end
end
end
diff --git a/lib/banzai/filter/table_of_contents_filter.rb b/lib/banzai/filter/table_of_contents_filter.rb
index 1c794a81d9d..d76009d08e1 100644
--- a/lib/banzai/filter/table_of_contents_filter.rb
+++ b/lib/banzai/filter/table_of_contents_filter.rb
@@ -33,17 +33,17 @@ module Banzai
header_root = current_header = HeaderNode.new
doc.xpath(XPATH).each do |node|
- if header_content = node.children.first
- id = string_to_anchor(node.text[0...255])
+ next unless header_content = node.children.first
- uniq = headers[id] > 0 ? "-#{headers[id]}" : ''
- headers[id] += 1
- href = "#{id}#{uniq}"
+ id = string_to_anchor(node.text[0...255])
- current_header = HeaderNode.new(node: node, href: href, previous_header: current_header)
+ uniq = headers[id] > 0 ? "-#{headers[id]}" : ''
+ headers[id] += 1
+ href = "#{id}#{uniq}"
- header_content.add_previous_sibling(anchor_tag(href))
- end
+ current_header = HeaderNode.new(node: node, href: href, previous_header: current_header)
+
+ header_content.add_previous_sibling(anchor_tag(href))
end
push_toc(header_root.children, root: true)
diff --git a/lib/banzai/pipeline/ascii_doc_pipeline.rb b/lib/banzai/pipeline/ascii_doc_pipeline.rb
index b652d8d89cf..afd5802de22 100644
--- a/lib/banzai/pipeline/ascii_doc_pipeline.rb
+++ b/lib/banzai/pipeline/ascii_doc_pipeline.rb
@@ -7,13 +7,13 @@ module Banzai
FilterArray[
Filter::AsciiDocSanitizationFilter,
Filter::AssetProxyFilter,
- Filter::SyntaxHighlightFilter,
Filter::ExternalLinkFilter,
Filter::PlantumlFilter,
Filter::ColorFilter,
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
Filter::WikiLinkFilter,
+ Filter::SyntaxHighlightFilter,
Filter::AsciiDocPostProcessingFilter
]
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 5e7c2f64c92..9b73e413d44 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -17,7 +17,6 @@ module Banzai
Filter::SanitizationFilter,
Filter::KrokiFilter,
Filter::AssetProxyFilter,
- Filter::SyntaxHighlightFilter,
Filter::MathFilter,
Filter::ColorFilter,
Filter::MermaidFilter,
@@ -37,7 +36,8 @@ module Banzai
Filter::CustomEmojiFilter,
Filter::TaskListFilter,
Filter::InlineDiffFilter,
- Filter::SetDirectionFilter
+ Filter::SetDirectionFilter,
+ Filter::SyntaxHighlightFilter
]
end
diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb
index 831baa9a778..19d91876892 100644
--- a/lib/banzai/reference_parser/base_parser.rb
+++ b/lib/banzai/reference_parser/base_parser.rb
@@ -66,6 +66,8 @@ module Banzai
projects = lazy { projects_for_nodes(nodes) }
project_attr = 'data-project'
+ preload_associations(projects, user)
+
nodes.select do |node|
if node.has_attribute?(project_attr)
can_read_reference?(user, projects[node], node)
@@ -261,6 +263,14 @@ module Banzai
hash[key] = {}
end
end
+
+ # For any preloading of project associations
+ # needed to avoid N+1s.
+ # Note: `projects` param is a hash of { node => project }.
+ # See #projects_for_nodes for more information.
+ def preload_associations(projects, user)
+ ::Preloaders::ProjectPolicyPreloader.new(projects.values, user).execute
+ end
end
end
end
diff --git a/lib/banzai/reference_parser/commit_parser.rb b/lib/banzai/reference_parser/commit_parser.rb
index 88896970bc6..c51f4976c28 100644
--- a/lib/banzai/reference_parser/commit_parser.rb
+++ b/lib/banzai/reference_parser/commit_parser.rb
@@ -32,6 +32,13 @@ module Banzai
commits
end
+ def nodes_visible_to_user(user, nodes)
+ projects = lazy { projects_for_nodes(nodes) }
+ user.preloaded_member_roles_for_projects(projects.values) if user
+
+ super
+ end
+
private
def can_read_reference?(user, ref_project, node)
diff --git a/lib/banzai/reference_parser/commit_range_parser.rb b/lib/banzai/reference_parser/commit_range_parser.rb
index fb4a392105f..3d09bc83151 100644
--- a/lib/banzai/reference_parser/commit_range_parser.rb
+++ b/lib/banzai/reference_parser/commit_range_parser.rb
@@ -38,6 +38,13 @@ module Banzai
range.valid_commits? ? range : nil
end
+ def nodes_visible_to_user(user, nodes)
+ projects = lazy { projects_for_nodes(nodes) }
+ user.preloaded_member_roles_for_projects(projects.values) if user
+
+ super
+ end
+
private
def can_read_reference?(user, ref_project, node)