Commit 9124ebce authored by Grzegorz Bizon's avatar Grzegorz Bizon

Use internal reference extractor in banzai unfold pipeline

parent 3c493c24
...@@ -72,30 +72,22 @@ module Issues ...@@ -72,30 +72,22 @@ module Issues
end end
def add_moved_from_note def add_moved_from_note
SystemNoteService.noteable_moved(:from, @issue_new, @project_new, @issue_old, @current_user) SystemNoteService.noteable_moved(:from, @issue_new, @project_new,
@issue_old, @current_user)
end end
def add_moved_to_note def add_moved_to_note
SystemNoteService.noteable_moved(:to, @issue_old, @project_old, @issue_new, @current_user) SystemNoteService.noteable_moved(:to, @issue_old, @project_old,
@issue_new, @current_user)
end end
def rewrite_references(noteable) def rewrite_references(noteable)
references = noteable.all_references content = noteable_content(noteable).dup
new_content = noteable_content(noteable).dup context = { pipeline: :reference_unfold,
cross_project_mentionables = [:issues, :merge_requests, :milestones, project: @project_old, new_project: @project_new }
:snippets, :commits, :commit_ranges]
cross_project_mentionables.each do |type| new_content = Banzai.render_result(content, context)
referables = references.public_send(type) new_content[:output].to_s
context = { objects: referables, project: @project_new,
pipeline: :reference_unfold }
new_content = Banzai.render_result(new_content, context)
new_content = new_content[:output].to_s
end
new_content
end end
def noteable_content(noteable) def noteable_content(noteable)
......
require 'html/pipeline/filter'
module Banzai module Banzai
module Filter module Filter
## ##
# Filter than unfolds local references. # Filter than unfolds local references.
# #
# Replaces all local references with project cross reference version
# in all objects passed to this filter in context.
#
# Requires objects array with each element implementing `Referable`.
# #
class ReferenceUnfoldFilter < ReferenceFilter class ReferenceUnfoldFilter < HTML::Pipeline::Filter
def initialize(*) def initialize(*)
super super
@objects = context[:objects] unless result[:references].is_a?(Hash)
@project = context[:project] raise StandardError, 'References not processed!'
unless @objects.all? { |object| object.respond_to?(:to_reference) }
raise StandardError, "No `to_reference` method implemented in one of the objects !"
end end
unless @project.kind_of?(Project) @text = context[:text].dup
raise StandardError, 'No valid project passed in context!' @new_project = context[:new_project]
end @referables = result[:references].values.flatten
end end
def call def call
@objects.each do |object| @referables.each do |referable|
pattern = /#{Regexp.escape(object.to_reference)}/ pattern = /#{Regexp.escape(referable.to_reference)}/
replace_text_nodes_matching(pattern) do |content| @text.gsub!(pattern, referable.to_reference(@new_project))
content.gsub(pattern, object.to_reference(@project))
end
end end
doc @text
end end
private private
def validate def validate
needs :project needs :project
needs :objects needs :new_project
needs :text
end end
end end
end end
......
...@@ -2,7 +2,19 @@ module Banzai ...@@ -2,7 +2,19 @@ module Banzai
module Pipeline module Pipeline
class ReferenceUnfoldPipeline < BasePipeline class ReferenceUnfoldPipeline < BasePipeline
def self.filters def self.filters
[Filter::ReferenceUnfoldFilter] 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
end end
......
...@@ -2,58 +2,61 @@ require 'spec_helper' ...@@ -2,58 +2,61 @@ require 'spec_helper'
describe Banzai::Pipeline::ReferenceUnfoldPipeline do describe Banzai::Pipeline::ReferenceUnfoldPipeline do
let(:text) { 'some text' } let(:text) { 'some text' }
let(:project) { create(:project) } let(:old_project) { create(:project) }
let(:objects) { [] } let(:new_project) { create(:project) }
let(:pipeline_context) do
{ project: old_project, new_project: new_project }
end
let(:result) do let(:result) do
described_class.to_html(text, project: project, objects: objects) described_class.to_document(text, pipeline_context)
end end
context 'invalid initializers' do context 'invalid initializers' do
subject { -> { result } } subject { -> { result } }
context 'project context is invalid' do context 'project context is missing' do
let(:project) { nil } let(:pipeline_context) { { new_project: new_project } }
it { is_expected.to raise_error StandardError, /No valid project/ } it { is_expected.to raise_error ArgumentError, /Missing context keys/ }
end end
context 'objects context is invalid' do context 'new project context is missing' do
let(:objects) { ['issue'] } let(:pipeline_context) { { project: old_project } }
it { is_expected.to raise_error StandardError, /No `to_reference` method/ } it { is_expected.to raise_error ArgumentError, /Missing context keys/ }
end end
end end
context 'multiple issues and merge requests referenced' do context 'multiple issues and merge requests referenced' do
subject { result } subject { result[:output] }
let(:main_project) { create(:project) }
let(:issue_first) { create(:issue, project: main_project) }
let(:issue_second) { create(:issue, project: main_project) }
let(:merge_request) { create(:merge_request, source_project: main_project) }
let(:objects) { [issue_first, issue_second, merge_request] } 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 context 'plain text description' do
let(:text) { 'Description that references #1, #2 and !1' } let(:text) { 'Description that references #1, #2 and !1' }
it { is_expected.to include issue_first.to_reference(project) } it { is_expected.to include issue_first.to_reference(new_project) }
it { is_expected.to include issue_second.to_reference(project) } it { is_expected.to include issue_second.to_reference(new_project) }
it { is_expected.to include merge_request.to_reference(project) } it { is_expected.to include merge_request.to_reference(new_project) }
end end
context 'description with ignored elements' do context 'description with ignored elements' do
let(:text) do let(:text) do
<<-EOF "Hi. This references #1, but not `#2`\n" +
Hi. This references #1, but not `#2` '<pre>and not !1</pre>'
<pre>and not !1</pre> end
EOF
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 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 issue_first.to_reference(project) } it { is_expected.to include url }
it { is_expected.to_not include issue_second.to_reference(project) }
it { is_expected.to_not include merge_request.to_reference(project) }
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment