Commit 619f04c1 authored by Robert Speicher's avatar Robert Speicher

Allow relative links to go up one directory level

parent bdfe6b96
......@@ -59,25 +59,44 @@ module Gitlab
end
def relative_file_path(path)
nested_path = build_nested_path(path, context[:requested_path])
nested_path = build_relative_path(path, context[:requested_path])
file_exists?(nested_path) ? nested_path : path
end
# Covering a special case, when the link is referencing file in the same
# directory.
# If we are at doc/api/README.md and the README.md contains relative
# links like [Users](users.md), this takes the request
# path(doc/api/README.md) and replaces the README.md with users.md so the
# path looks like doc/api/users.md.
# If we are at doc/api and the README.md shown in below the tree view
# this takes the request path(doc/api) and adds users.md so the path
# looks like doc/api/users.md
def build_nested_path(path, request_path)
# Convert a relative path into its correct location based on the currently
# requested path
#
# path - Relative path String
# request_path - Currently-requested path String
#
# Examples:
#
# # File in the same directory as the current path
# build_relative_path("users.md", "doc/api/README.md")
# # => "doc/api/users.md"
#
# # File in the same directory, which is also the current path
# build_relative_path("users.md", "doc/api")
# # => "doc/api/users.md"
#
# # Going up one level to a different directory
# build_relative_path("../update/7.14-to-8.0.md", "doc/api/README.md")
# # => "doc/update/7.14-to-8.0.md"
#
# Returns a String
def build_relative_path(path, request_path)
return request_path if path.empty?
return path unless request_path
parts = request_path.split('/')
parts.pop if path_type(request_path) != 'tree'
# Allow for going up one directory
if parts.length > 1 && path.start_with?('../')
parts.pop
path.sub!('../', '')
end
parts.push(path).join('/')
end
......
......@@ -4,14 +4,16 @@ require 'spec_helper'
module Gitlab::Markdown
describe RelativeLinkFilter do
def filter(doc)
described_class.call(doc, {
def filter(doc, contexts = {})
contexts.reverse_merge!({
commit: project.commit,
project: project,
project_wiki: project_wiki,
ref: ref,
requested_path: requested_path
})
described_class.call(doc, contexts)
end
def image(path)
......@@ -75,6 +77,14 @@ module Gitlab::Markdown
to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
end
it 'rebuilds relative URL for a file in the repo up one directory' do
relative_link = link('../api/README.md')
doc = filter(relative_link, requested_path: 'doc/update/7.14-to-8.0.md')
expect(doc.at_css('a')['href']).
to eq "/#{project_path}/blob/#{ref}/doc/api/README.md"
end
it 'rebuilds relative URL for a file in the repo with an anchor' do
doc = filter(link('README.md#section'))
expect(doc.at_css('a')['href']).
......@@ -108,8 +118,8 @@ module Gitlab::Markdown
escaped = Addressable::URI.escape(path)
# Stub these methods so the file doesn't actually need to be in the repo
allow_any_instance_of(described_class).to receive(:file_exists?).
and_return(true)
allow_any_instance_of(described_class).
to receive(:file_exists?).and_return(true)
allow_any_instance_of(described_class).
to receive(:image?).with(path).and_return(true)
......
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