gitlab-org--gitlab-foss/lib/gitlab/gfm/reference_unfolder.rb

75 lines
1.9 KiB
Ruby
Raw Normal View History

module Gitlab
module Gfm
##
# Class than unfolds local references in text.
#
#
class ReferenceUnfolder
def initialize(text, project)
@text = text
@project = project
@original = markdown(text)
end
def unfold(from_project)
return @text unless @text =~ references_pattern
unfolded = @text.gsub(references_pattern) do |reference|
unfold_reference(reference, Regexp.last_match, from_project)
end
unless substitution_valid?(unfolded)
raise StandardError, 'Invalid references unfolding!'
end
unfolded
end
private
def unfold_reference(reference, match, from_project)
before = @text[0...match.begin(0)]
after = @text[match.end(0)...@text.length]
referable = find_referable(reference)
return reference unless referable
cross_reference = referable.to_reference(from_project)
new_text = before + cross_reference + after
substitution_valid?(new_text) ? cross_reference : reference
end
def references_pattern
return @pattern if @pattern
patterns = Gitlab::ReferenceExtractor::REFERABLES.map do |ref|
ref.to_s.classify.constantize.try(:reference_pattern)
end
@pattern = Regexp.union(patterns.compact)
end
def referables
return @referables if @referables
extractor = Gitlab::ReferenceExtractor.new(@project)
extractor.analyze(@text)
@referables = extractor.all
end
def find_referable(reference)
referables.find { |ref| ref.to_reference == reference }
end
def substitution_valid?(substituted)
@original == markdown(substituted)
end
def markdown(text)
helper = Class.new.extend(GitlabMarkdownHelper)
helper.markdown(text, project: @project, no_original_data: true)
end
end
end
end