Move reference unfolder for GFM to separate class
This commit is contained in:
parent
cd0f194508
commit
fd8394faae
|
@ -83,11 +83,8 @@ module Issues
|
|||
|
||||
def rewrite_references(noteable)
|
||||
content = noteable_content(noteable).dup
|
||||
context = { pipeline: :reference_unfold,
|
||||
project: @project_old, new_project: @project_new }
|
||||
|
||||
new_content = Banzai.render_result(content, context)
|
||||
new_content[:output].to_s
|
||||
unfolder = Gitlab::Gfm::ReferenceUnfolder.new(content, @project_old)
|
||||
unfolder.unfold(@project_new)
|
||||
end
|
||||
|
||||
def noteable_content(noteable)
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
require 'html/pipeline/filter'
|
||||
|
||||
module Banzai
|
||||
module Filter
|
||||
##
|
||||
# Filter than unfolds local references.
|
||||
#
|
||||
#
|
||||
class ReferenceUnfoldFilter < HTML::Pipeline::Filter
|
||||
def initialize(*)
|
||||
super
|
||||
|
||||
unless result[:references].is_a?(Hash)
|
||||
raise StandardError, 'References not processed!'
|
||||
end
|
||||
|
||||
@text = context[:text].dup
|
||||
@new_project = context[:new_project]
|
||||
@referables = result[:references].values.flatten
|
||||
end
|
||||
|
||||
def call
|
||||
@referables.each do |referable|
|
||||
next unless referable.respond_to?(:to_reference)
|
||||
|
||||
pattern = /#{Regexp.escape(referable.to_reference)}/
|
||||
@text.gsub!(pattern, referable.to_reference(@new_project))
|
||||
end
|
||||
|
||||
@text
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate
|
||||
needs :project
|
||||
needs :new_project
|
||||
needs :text
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
module Banzai
|
||||
module Pipeline
|
||||
class ReferenceUnfoldPipeline < BasePipeline
|
||||
def self.filters
|
||||
FullPipeline.filters +
|
||||
[Filter::ReferenceGathererFilter,
|
||||
Filter::ReferenceUnfoldFilter]
|
||||
end
|
||||
|
||||
def self.call(text, context = {})
|
||||
context = context.merge(text: text)
|
||||
super
|
||||
end
|
||||
|
||||
class << self
|
||||
alias_method :to_document, :call
|
||||
alias_method :to_html, :call
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
module Gitlab
|
||||
module Gfm
|
||||
##
|
||||
# Class than unfolds local references in text.
|
||||
#
|
||||
#
|
||||
class ReferenceUnfolder
|
||||
def initialize(text, project)
|
||||
@text = text
|
||||
@project = project
|
||||
end
|
||||
|
||||
def unfold(from_project)
|
||||
referables.each_with_object(@text.dup) do |referable, text|
|
||||
next unless referable.respond_to?(:to_reference)
|
||||
|
||||
pattern = /#{Regexp.escape(referable.to_reference)}/
|
||||
text.gsub!(pattern, referable.to_reference(from_project))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def referables
|
||||
extractor = Gitlab::ReferenceExtractor.new(@project)
|
||||
extractor.analyze(@text)
|
||||
extractor.all
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
module Gitlab
|
||||
# Extract possible GFM references from an arbitrary String for further processing.
|
||||
class ReferenceExtractor < Banzai::ReferenceExtractor
|
||||
REFERABLES = %i(user issue label milestone merge_request snippet commit commit_range)
|
||||
attr_accessor :project, :current_user, :author
|
||||
|
||||
def initialize(project, current_user = nil, author = nil)
|
||||
|
@ -17,7 +18,7 @@ module Gitlab
|
|||
super(text, context.merge(project: project))
|
||||
end
|
||||
|
||||
%i(user label milestone merge_request snippet commit commit_range).each do |type|
|
||||
REFERABLES.each do |type|
|
||||
define_method("#{type}s") do
|
||||
@references[type] ||= references(type, reference_context)
|
||||
end
|
||||
|
@ -31,6 +32,11 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
def all
|
||||
REFERABLES.each { |referable| send(referable.to_s.pluralize) }
|
||||
@references.values.flatten
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def reference_context
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Banzai::Pipeline::ReferenceUnfoldPipeline do
|
||||
let(:text) { 'some text' }
|
||||
let(:old_project) { create(:project) }
|
||||
let(:new_project) { create(:project) }
|
||||
let(:pipeline_context) do
|
||||
{ project: old_project, new_project: new_project }
|
||||
end
|
||||
|
||||
let(:result) do
|
||||
described_class.to_document(text, pipeline_context)
|
||||
end
|
||||
|
||||
context 'invalid initializers' do
|
||||
subject { -> { result } }
|
||||
|
||||
context 'project context is missing' do
|
||||
let(:pipeline_context) { { new_project: new_project } }
|
||||
it { is_expected.to raise_error ArgumentError, /Missing context keys/ }
|
||||
end
|
||||
|
||||
context 'new project context is missing' do
|
||||
let(:pipeline_context) { { project: old_project } }
|
||||
it { is_expected.to raise_error ArgumentError, /Missing context keys/ }
|
||||
end
|
||||
end
|
||||
|
||||
context 'multiple issues and merge requests referenced' do
|
||||
subject { result[:output] }
|
||||
|
||||
let!(:issue_first) { create(:issue, project: old_project) }
|
||||
let!(:issue_second) { create(:issue, project: old_project) }
|
||||
let!(:merge_request) { create(:merge_request, source_project: old_project) }
|
||||
|
||||
context 'plain text description' do
|
||||
let(:text) { 'Description that references #1, #2 and !1' }
|
||||
|
||||
it { is_expected.to include issue_first.to_reference(new_project) }
|
||||
it { is_expected.to include issue_second.to_reference(new_project) }
|
||||
it { is_expected.to include merge_request.to_reference(new_project) }
|
||||
end
|
||||
|
||||
context 'description with ignored elements' do
|
||||
let(:text) do
|
||||
"Hi. This references #1, but not `#2`\n" +
|
||||
'<pre>and not !1</pre>'
|
||||
end
|
||||
|
||||
it { is_expected.to include issue_first.to_reference(new_project) }
|
||||
it { is_expected.to_not include issue_second.to_reference(new_project) }
|
||||
it { is_expected.to_not include merge_request.to_reference(new_project) }
|
||||
end
|
||||
|
||||
context 'description ambigous elements' do
|
||||
let(:url) { 'http://gitlab.com/#1' }
|
||||
let(:text) { "This references #1, but not #{url}" }
|
||||
|
||||
it { is_expected.to include url }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Gfm::ReferenceUnfolder do
|
||||
let(:text) { 'some text' }
|
||||
let(:old_project) { create(:project) }
|
||||
let(:new_project) { create(:project) }
|
||||
|
||||
describe '#unfold' do
|
||||
subject { described_class.new(text, old_project).unfold(new_project) }
|
||||
|
||||
context 'multiple issues and merge requests referenced' do
|
||||
let!(:issue_first) { create(:issue, project: old_project) }
|
||||
let!(:issue_second) { create(:issue, project: old_project) }
|
||||
let!(:merge_request) { create(:merge_request, source_project: old_project) }
|
||||
|
||||
context 'plain text description' do
|
||||
let(:text) { 'Description that references #1, #2 and !1' }
|
||||
|
||||
it { is_expected.to include issue_first.to_reference(new_project) }
|
||||
it { is_expected.to include issue_second.to_reference(new_project) }
|
||||
it { is_expected.to include merge_request.to_reference(new_project) }
|
||||
end
|
||||
|
||||
context 'description with ignored elements' do
|
||||
let(:text) do
|
||||
"Hi. This references #1, but not `#2`\n" +
|
||||
'<pre>and not !1</pre>'
|
||||
end
|
||||
|
||||
it { is_expected.to include issue_first.to_reference(new_project) }
|
||||
it { is_expected.to_not include issue_second.to_reference(new_project) }
|
||||
it { is_expected.to_not include merge_request.to_reference(new_project) }
|
||||
end
|
||||
|
||||
context 'description ambigous elements' do
|
||||
let(:url) { 'http://gitlab.com/#1' }
|
||||
let(:text) { "This references #1, but not #{url}" }
|
||||
|
||||
it { is_expected.to include url }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -122,4 +122,16 @@ describe Gitlab::ReferenceExtractor, lib: true do
|
|||
expect(extracted).to match_array([issue])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#all' do
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
let(:label) { create(:label, project: project) }
|
||||
let(:text) { "Ref. #{issue.to_reference} and #{label.to_reference}" }
|
||||
|
||||
before { subject.analyze(text) }
|
||||
|
||||
it 'returns all referables' do
|
||||
expect(subject.all).to match_array([issue, label])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue