72 lines
2.1 KiB
Ruby
72 lines
2.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# This service passes Markdown content through our GFM rewriter classes
|
|
# which rewrite references to GitLab objects and uploads within the content
|
|
# based on their visibility by the `target_parent`.
|
|
class MarkdownContentRewriterService
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
REWRITERS = [Gitlab::Gfm::ReferenceRewriter, Gitlab::Gfm::UploadsRewriter].freeze
|
|
|
|
def initialize(current_user, object, field, source_parent, target_parent)
|
|
@current_user = current_user
|
|
@source_parent = source_parent
|
|
@target_parent = target_parent
|
|
@object = object
|
|
@field = field
|
|
|
|
validate_parameters!
|
|
|
|
@content = object[field].dup.presence
|
|
@html_field = object.cached_markdown_fields.html_field(field)
|
|
@content_html = object.cached_html_for(field)
|
|
|
|
@rewriters =
|
|
REWRITERS.map do |rewriter_class|
|
|
rewriter_class.new(@content, content_html, source_parent, current_user)
|
|
end
|
|
|
|
@result = {
|
|
field => nil,
|
|
html_field => nil
|
|
}.with_indifferent_access
|
|
end
|
|
|
|
def execute
|
|
return result unless content
|
|
|
|
unless safe_to_copy_markdown?
|
|
rewriters.each do |rewriter|
|
|
rewriter.rewrite(target_parent)
|
|
end
|
|
end
|
|
|
|
result[field] = content
|
|
result[html_field] = content_html if safe_to_copy_markdown?
|
|
result[:skip_markdown_cache_validation] = safe_to_copy_markdown?
|
|
|
|
result
|
|
end
|
|
|
|
def safe_to_copy_markdown?
|
|
strong_memoize(:safe_to_copy_markdown) do
|
|
rewriters.none?(&:needs_rewrite?)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def validate_parameters!
|
|
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39654#note_399095117
|
|
raise ArgumentError, 'The rewriter classes require that `source_parent` is a `Project`' \
|
|
unless source_parent.is_a?(Project)
|
|
|
|
if object.cached_markdown_fields[field].nil?
|
|
raise ArgumentError, 'The `field` attribute does not contain cached markdown'
|
|
end
|
|
end
|
|
|
|
attr_reader :current_user, :content, :source_parent,
|
|
:target_parent, :rewriters, :content_html,
|
|
:field, :html_field, :object, :result
|
|
end
|