From 619f04c196731b2a274802dfb4b4d3c3664e5465 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 18 Sep 2015 14:03:42 -0400 Subject: Allow relative links to go up one directory level --- lib/gitlab/markdown/relative_link_filter.rb | 41 ++++++++++++++++------ .../gitlab/markdown/relative_link_filter_spec.rb | 18 +++++++--- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/lib/gitlab/markdown/relative_link_filter.rb b/lib/gitlab/markdown/relative_link_filter.rb index 8c5cf51bfe1..d613c205509 100644 --- a/lib/gitlab/markdown/relative_link_filter.rb +++ b/lib/gitlab/markdown/relative_link_filter.rb @@ -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 diff --git a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb index 7f4d67e403f..ab9c2008ea7 100644 --- a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb +++ b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb @@ -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) -- cgit v1.2.1 From 2b94f5fb06ef061fb49a7dadcbb95c0954bc9860 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 20 Sep 2015 19:21:33 -0400 Subject: Allow RelativeLinkFilter to go up multiple directories --- lib/gitlab/markdown/relative_link_filter.rb | 3 +-- spec/lib/gitlab/markdown/relative_link_filter_spec.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/markdown/relative_link_filter.rb b/lib/gitlab/markdown/relative_link_filter.rb index d613c205509..6ee3d1ce039 100644 --- a/lib/gitlab/markdown/relative_link_filter.rb +++ b/lib/gitlab/markdown/relative_link_filter.rb @@ -91,8 +91,7 @@ module Gitlab 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?('../') + while parts.length > 1 && path.start_with?('../') parts.pop path.sub!('../', '') end diff --git a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb index ab9c2008ea7..027336ceb73 100644 --- a/spec/lib/gitlab/markdown/relative_link_filter_spec.rb +++ b/spec/lib/gitlab/markdown/relative_link_filter_spec.rb @@ -85,6 +85,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 multiple directories' do + relative_link = link('../../../api/README.md') + doc = filter(relative_link, requested_path: 'doc/foo/bar/baz/README.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']). -- cgit v1.2.1