diff options
author | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-03-11 13:49:04 +0300 |
---|---|---|
committer | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-03-17 09:39:16 +0300 |
commit | 4354bfaba55c9238d5245fe2f5823665790c9817 (patch) | |
tree | 08da489b53d7b5168d0432031dd32da70ca5218d /lib/gitlab/gfm | |
parent | fd8394faae25b54c4d9ac485a0ce746cffec3a0f (diff) |
Add implementation of reference unfolder using banzai
Diffstat (limited to 'lib/gitlab/gfm')
-rw-r--r-- | lib/gitlab/gfm/reference_unfolder.rb | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/lib/gitlab/gfm/reference_unfolder.rb b/lib/gitlab/gfm/reference_unfolder.rb index 4969e8ebe85..57871c36eb4 100644 --- a/lib/gitlab/gfm/reference_unfolder.rb +++ b/lib/gitlab/gfm/reference_unfolder.rb @@ -8,23 +8,66 @@ module Gitlab def initialize(text, project) @text = text @project = project + @original = markdown(text) end def unfold(from_project) - referables.each_with_object(@text.dup) do |referable, text| - next unless referable.respond_to?(:to_reference) + return @text unless @text =~ references_pattern - pattern = /#{Regexp.escape(referable.to_reference)}/ - text.gsub!(pattern, referable.to_reference(from_project)) + 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) - extractor.all + @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 |