Merge branch 'rs-relative-link-filter' into 'master'
Minor RelativeLinkFilter cleanup See merge request !649
This commit is contained in:
commit
947231a461
|
@ -68,9 +68,9 @@ module Gitlab
|
||||||
reference_class: html_options[:class],
|
reference_class: html_options[:class],
|
||||||
|
|
||||||
# RelativeLinkFilter
|
# RelativeLinkFilter
|
||||||
ref: @ref,
|
ref: @ref,
|
||||||
requested_path: @path,
|
requested_path: @path,
|
||||||
project_wiki: @project_wiki
|
project_wiki: @project_wiki
|
||||||
}
|
}
|
||||||
|
|
||||||
result = pipeline.call(text, context)
|
result = pipeline.call(text, context)
|
||||||
|
|
|
@ -9,19 +9,18 @@ module Gitlab
|
||||||
# :commit
|
# :commit
|
||||||
# :project
|
# :project
|
||||||
# :project_wiki
|
# :project_wiki
|
||||||
# :requested_path
|
|
||||||
# :ref
|
# :ref
|
||||||
|
# :requested_path
|
||||||
class RelativeLinkFilter < HTML::Pipeline::Filter
|
class RelativeLinkFilter < HTML::Pipeline::Filter
|
||||||
|
|
||||||
def call
|
def call
|
||||||
if linkable_files?
|
return doc unless linkable_files?
|
||||||
doc.search('a').each do |el|
|
|
||||||
process_link_attr el.attribute('href')
|
|
||||||
end
|
|
||||||
|
|
||||||
doc.search('img').each do |el|
|
doc.search('a').each do |el|
|
||||||
process_link_attr el.attribute('src')
|
process_link_attr el.attribute('href')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
doc.search('img').each do |el|
|
||||||
|
process_link_attr el.attribute('src')
|
||||||
end
|
end
|
||||||
|
|
||||||
doc
|
doc
|
||||||
|
@ -40,6 +39,8 @@ module Gitlab
|
||||||
if uri.relative? && uri.path.present?
|
if uri.relative? && uri.path.present?
|
||||||
html_attr.value = rebuild_relative_uri(uri).to_s
|
html_attr.value = rebuild_relative_uri(uri).to_s
|
||||||
end
|
end
|
||||||
|
rescue URI::Error
|
||||||
|
# noop
|
||||||
end
|
end
|
||||||
|
|
||||||
def rebuild_relative_uri(uri)
|
def rebuild_relative_uri(uri)
|
||||||
|
@ -85,12 +86,25 @@ module Gitlab
|
||||||
repository.tree(current_sha, path).entries.any?
|
repository.tree(current_sha, path).entries.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check if the path is pointing to a directory(tree) or a file(blob)
|
# Get the type of the given path
|
||||||
# eg. doc/api is directory and doc/README.md is file.
|
#
|
||||||
|
# path - String path to check
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# path_type('doc/README.md') # => 'blob'
|
||||||
|
# path_type('doc/logo.png') # => 'raw'
|
||||||
|
# path_type('doc/api') # => 'tree'
|
||||||
|
#
|
||||||
|
# Returns a String
|
||||||
def path_type(path)
|
def path_type(path)
|
||||||
return 'tree' if repository.tree(current_sha, path).entries.any?
|
if repository.tree(current_sha, path).entries.any?
|
||||||
return 'raw' if repository.blob_at(current_sha, path).try(:image?)
|
'tree'
|
||||||
'blob'
|
elsif repository.blob_at(current_sha, path).try(:image?)
|
||||||
|
'raw'
|
||||||
|
else
|
||||||
|
'blob'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_sha
|
def current_sha
|
||||||
|
|
|
@ -2,119 +2,114 @@ require 'spec_helper'
|
||||||
|
|
||||||
module Gitlab::Markdown
|
module Gitlab::Markdown
|
||||||
describe RelativeLinkFilter do
|
describe RelativeLinkFilter do
|
||||||
include ActionView::Helpers::TagHelper
|
def filter(doc)
|
||||||
|
described_class.call(doc, {
|
||||||
let!(:project) { create(:project) }
|
commit: project.commit,
|
||||||
|
project: project,
|
||||||
let(:commit) { project.commit }
|
project_wiki: project_wiki,
|
||||||
let(:project_path) { project.path_with_namespace }
|
ref: ref,
|
||||||
let(:repository) { project.repository }
|
requested_path: requested_path
|
||||||
let(:ref) { 'markdown' }
|
})
|
||||||
|
|
||||||
let(:project_wiki) { nil }
|
|
||||||
let(:requested_path) { '/' }
|
|
||||||
let(:blob) { RepoHelpers.sample_blob }
|
|
||||||
|
|
||||||
let(:context) do
|
|
||||||
{
|
|
||||||
commit: commit,
|
|
||||||
project: project,
|
|
||||||
project_wiki: project_wiki,
|
|
||||||
requested_path: requested_path,
|
|
||||||
ref: ref
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def image(path)
|
||||||
|
%(<img src="#{path}" />)
|
||||||
|
end
|
||||||
|
|
||||||
|
def link(path)
|
||||||
|
%(<a href="#{path}">#{path}</a>)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:project) { create(:project) }
|
||||||
|
let(:project_path) { project.path_with_namespace }
|
||||||
|
let(:ref) { 'markdown' }
|
||||||
|
let(:project_wiki) { nil }
|
||||||
|
let(:requested_path) { '/' }
|
||||||
|
|
||||||
shared_examples :preserve_unchanged do
|
shared_examples :preserve_unchanged do
|
||||||
|
it 'does not modify any relative URL in anchor' do
|
||||||
it "should not modify any relative url in anchor" do
|
doc = filter(link('README.md'))
|
||||||
doc = tag(:a, href: 'README.md')
|
expect(doc.at_css('a')['href']).to eq 'README.md'
|
||||||
expect( filter(doc) ).to match '"README.md"'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not modify any relative url in image" do
|
it 'does not modify any relative URL in image' do
|
||||||
doc = tag(:img, src: 'files/images/logo-black.png')
|
doc = filter(image('files/images/logo-black.png'))
|
||||||
expect( filter(doc) ).to match '"files/images/logo-black.png"'
|
expect(doc.at_css('img')['src']).to eq 'files/images/logo-black.png'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
shared_examples :relative_to_requested do
|
shared_examples :relative_to_requested do
|
||||||
|
it 'rebuilds URL relative to the requested path' do
|
||||||
it "should rebuild url relative to the requested path" do
|
doc = filter(link('users.md'))
|
||||||
expect( filter(tag(:a, href: 'users.md')) ).to \
|
expect(doc.at_css('a')['href']).
|
||||||
match %("/#{project_path}/blob/#{ref}/doc/api/users.md")
|
to eq "/#{project_path}/blob/#{ref}/doc/api/users.md"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a project_wiki' do
|
||||||
context "with a project_wiki" do
|
|
||||||
let(:project_wiki) { double('ProjectWiki') }
|
let(:project_wiki) { double('ProjectWiki') }
|
||||||
|
|
||||||
include_examples :preserve_unchanged
|
include_examples :preserve_unchanged
|
||||||
end
|
end
|
||||||
|
|
||||||
context "without a repository" do
|
context 'without a repository' do
|
||||||
let!(:project) { create(:empty_project) }
|
let(:project) { create(:empty_project) }
|
||||||
|
|
||||||
include_examples :preserve_unchanged
|
include_examples :preserve_unchanged
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with an empty repository" do
|
context 'with an empty repository' do
|
||||||
let!(:project) { create(:project_empty_repo) }
|
let(:project) { create(:project_empty_repo) }
|
||||||
|
|
||||||
include_examples :preserve_unchanged
|
include_examples :preserve_unchanged
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not raise an exception on invalid URIs' do
|
||||||
|
act = link("://foo")
|
||||||
|
expect { filter(act) }.not_to raise_error
|
||||||
|
end
|
||||||
|
|
||||||
context "with a valid repository" do
|
context 'with a valid repository' do
|
||||||
|
it 'rebuilds relative URL for a file in the repo' do
|
||||||
it "should rebuild relative url for a file in the repo" do
|
doc = filter(link('doc/api/README.md'))
|
||||||
expect( filter(tag(:a, href: 'doc/api/README.md')) ).to \
|
expect(doc.at_css('a')['href']).
|
||||||
match %("/#{project_path}/blob/#{ref}/doc/api/README.md")
|
to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should rebuild relative url for a file in the repo with an anchor" do
|
it 'rebuilds relative URL for a file in the repo with an anchor' do
|
||||||
expect( filter(tag(:a, href: 'README.md#section')) ).to \
|
doc = filter(link('README.md#section'))
|
||||||
match %("/#{project_path}/blob/#{ref}/README.md#section")
|
expect(doc.at_css('a')['href']).
|
||||||
|
to eq "/#{project_path}/blob/#{ref}/README.md#section"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should rebuild relative url for a directory in the repo" do
|
it 'rebuilds relative URL for a directory in the repo' do
|
||||||
expect( filter(tag(:a, href: 'doc/api/')) ).to \
|
doc = filter(link('doc/api/'))
|
||||||
match %("/#{project_path}/tree/#{ref}/doc/api")
|
expect(doc.at_css('a')['href']).
|
||||||
|
to eq "/#{project_path}/tree/#{ref}/doc/api"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should rebuild relative url for an image in the repo" do
|
it 'rebuilds relative URL for an image in the repo' do
|
||||||
expect( filter(tag(:img, src: 'files/images/logo-black.png')) ).to \
|
doc = filter(link('files/images/logo-black.png'))
|
||||||
match %("/#{project_path}/raw/#{ref}/files/images/logo-black.png")
|
expect(doc.at_css('a')['href']).
|
||||||
|
to eq "/#{project_path}/raw/#{ref}/files/images/logo-black.png"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not modify relative url with an anchor only" do
|
it 'does not modify relative URL with an anchor only' do
|
||||||
doc = tag(:a, href: '#section-1')
|
doc = filter(link('#section-1'))
|
||||||
expect( filter(doc) ).to match %("#section-1")
|
expect(doc.at_css('a')['href']).to eq '#section-1'
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should not modify absolute url" do
|
it 'does not modify absolute URL' do
|
||||||
expect( filter(tag(:a, href: 'http://example.org')) ).to \
|
doc = filter(link('http://example.com'))
|
||||||
match %("http://example.org")
|
expect(doc.at_css('a')['href']).to eq 'http://example.com'
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when requested path is a file in the repo" do
|
context 'when requested path is a file in the repo' do
|
||||||
let(:requested_path) { 'doc/api/README.md' }
|
let(:requested_path) { 'doc/api/README.md' }
|
||||||
|
|
||||||
include_examples :relative_to_requested
|
include_examples :relative_to_requested
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when requested path is a directory in the repo" do
|
context 'when requested path is a directory in the repo' do
|
||||||
let(:requested_path) { 'doc/api' }
|
let(:requested_path) { 'doc/api' }
|
||||||
|
|
||||||
include_examples :relative_to_requested
|
include_examples :relative_to_requested
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def filter(doc)
|
|
||||||
described_class.call(doc, context).to_s
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue