Commit b883d94f authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'relative_links_in_documentation' of /home/git/repositories/gitlab/gitlabhq

parents 10fac475 f40e0171
No related merge requests found
......@@ -34,7 +34,8 @@ module GitlabMarkdownHelper
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
filter_html: true,
with_toc_data: true,
hard_wrap: true)
hard_wrap: true,
safe_links_only: true)
@markdown = Redcarpet::Markdown.new(gitlab_renderer,
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
no_intra_emphasis: true,
......@@ -57,4 +58,97 @@ module GitlabMarkdownHelper
wiki_page.formatted_content.html_safe
end
end
# text - whole text from a markdown file
# project_path_with_namespace - namespace/projectname, eg. gitlabhq/gitlabhq
# ref - name of the branch or reference, eg. stable
# requested_path - path of request, eg. doc/api/README.md, used in special case when path is pointing to the .md file were the original request is coming from
# wiki - whether the markdown is from wiki or not
def create_relative_links(text, project_path_with_namespace, ref, requested_path, wiki = false)
paths = extract_paths(text)
paths.each do |file_path|
new_path = rebuild_path(project_path_with_namespace, file_path, requested_path, ref)
# Replacing old string with a new one with brackets ]() to prevent replacing occurence of a word
# e.g. If we have a markdown like [test](test) this will replace ](test) and not the word test
text.gsub!("](#{file_path})", "](/#{new_path})")
end
text
end
def extract_paths(markdown_text)
all_markdown_paths = pick_out_paths(markdown_text)
paths = remove_empty(all_markdown_paths)
select_relative(paths)
end
# Split the markdown text to each line and find all paths, this will match anything with - ]("some_text")
def pick_out_paths(markdown_text)
markdown_text.split("\n").map { |text| text.scan(/\]\(([^(]+)\)/) }
end
# Removes any empty result produced by not matching the regexp
def remove_empty(paths)
paths.reject{|l| l.empty? }.flatten
end
# Reject any path that contains ignored protocol
# eg. reject "https://gitlab.org} but accept "doc/api/README.md"
def select_relative(paths)
paths.reject{|path| ignored_protocols.map{|protocol| path.include?(protocol)}.any?}
end
def ignored_protocols
["http://","https://", "ftp://", "mailto:"]
end
def rebuild_path(path_with_namespace, path, requested_path, ref)
file_path = relative_file_path(path, requested_path)
[
path_with_namespace,
path_with_ref(file_path, ref),
file_path
].compact.join("/")
end
# Checks if the path exists in the repo
# eg. checks if doc/README.md exists, if it doesn't then it is a wiki link
def path_with_ref(path, ref)
if file_exists?(path)
"#{local_path(path)}/#{correct_ref(ref)}"
else
"wikis"
end
end
def relative_file_path(path, requested_path)
nested_path = build_nested_path(path, requested_path)
return nested_path if file_exists?(nested_path)
path
end
# Covering a special case, when the link is referencing file in the same directory eg:
# 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
def build_nested_path(path, request_path)
return path unless request_path
base = request_path.split("/")
base.pop
(base + [path]).join("/")
end
def file_exists?(path)
return false if path.nil? || path.empty?
File.exists?(Rails.root.join(path))
end
# Check if the path is pointing to a directory(tree) or a file(blob)
# eg. doc/api is directory and doc/README.md is file
def local_path(path)
File.directory?(Rails.root.join(path)) ? "tree" : "blob"
end
# We will assume that if no ref exists we can point to master
def correct_ref(ref)
ref ? ref : "master"
end
end
Feature: Project markdown render
Background:
Given I sign in as a user
And I own project "Delta"
Given I visit project source page
Scenario: I browse files from master branch
Then I should see files from repository in master
And I should see rendered README which contains correct links
And I click on Gitlab API in README
Then I should see correct document rendered
Scenario: I view README in master branch
Then I should see files from repository in master
And I should see rendered README which contains correct links
And I click on Rake tasks in README
Then I should see correct directory rendered
Scenario: I navigate to doc directory to view documentation in master
And I navigate to the doc/api/README
And I see correct file rendered
And I click on users in doc/api/README
Then I should see the correct document file
Scenario: I navigate to doc directory to view user doc in master
And I navigate to the doc/api/README
And I see correct file rendered
And I click on raketasks in doc/api/README
Then I should see correct directory rendered
Scenario: I browse files from markdown branch
When I visit markdown branch
Then I should see files from repository in markdown branch
And I should see rendered README which contains correct links
And I click on Gitlab API in README
Then I should see correct document rendered for markdown branch
Scenario: I browse directory from markdown branch
When I visit markdown branch
Then I should see files from repository in markdown branch
And I should see rendered README which contains correct links
And I click on Rake tasks in README
Then I should see correct directory rendered for markdown branch
Scenario: I navigate to doc directory to view documentation in markdown branch
When I visit markdown branch
And I navigate to the doc/api/README
And I see correct file rendered in markdown branch
And I click on users in doc/api/README
Then I should see the users document file in markdown branch
Scenario: I navigate to doc directory to view user doc in markdown branch
When I visit markdown branch
And I navigate to the doc/api/README
And I see correct file rendered in markdown branch
And I click on raketasks in doc/api/README
Then I should see correct directory rendered for markdown branch
Scenario: I create a wiki page with different links
Given I go to wiki page
And I add various links to the wiki page
Then Wiki page should have added links
And I click on test link
Then I see new wiki page named test
When I go back to wiki page home
And I click on GitLab API doc link
Then I see Gitlab API document
When I go back to wiki page home
And I click on Rake tasks link
Then I see Rake tasks directory
class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
And 'I own project "Delta"' do
@project = Project.find_by_name "Delta"
@project ||= create(:project_with_code, name: "Delta", namespace: @user.namespace)
@project.team << [@user, :master]
end
Then 'I should see files from repository in master' do
current_path.should == project_tree_path(@project, "master")
page.should have_content "Gemfile"
page.should have_content "app"
page.should have_content "README"
end
And 'I should see rendered README which contains correct links' do
page.should have_content "Welcome to GitLab GitLab is a free project and repository management application"
page.should have_link "GitLab API doc"
page.should have_link "GitLab API website"
page.should have_link "Rake tasks"
page.should have_link "backup and restore procedure"
end
And 'I click on Gitlab API in README' do
click_link "GitLab API doc"
end
Then 'I should see correct document rendered' do
current_path.should == project_blob_path(@project, "master/doc/api/README.md")
page.should have_content "All API requests require authentication"
end
And 'I click on Rake tasks in README' do
click_link "Rake tasks"
end
Then 'I should see correct directory rendered' do
current_path.should == project_tree_path(@project, "master/doc/raketasks")
page.should have_content "backup_restore.md"
page.should have_content "maintenance.md"
end
And 'I navigate to the doc/api/README' do
click_link "doc"
click_link "api"
click_link "README.md"
end
And 'I see correct file rendered' do
current_path.should == project_blob_path(@project, "master/doc/api/README.md")
page.should have_content "Contents"
page.should have_link "Users"
page.should have_link "Rake tasks"
end
And 'I click on users in doc/api/README' do
click_link "Users"
end
Then 'I should see the correct document file' do
current_path.should == project_blob_path(@project, "master/doc/api/users.md")
page.should have_content "Get a list of users."
end
And 'I click on raketasks in doc/api/README' do
click_link "Rake tasks"
end
When 'I visit markdown branch' do
visit project_tree_path(@project, "markdown")
end
Then 'I should see files from repository in markdown branch' do
current_path.should == project_tree_path(@project, "markdown")
page.should have_content "Gemfile"
page.should have_content "app"
page.should have_content "README"
end
And 'I see correct file rendered in markdown branch' do
current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
page.should have_content "Contents"
page.should have_link "Users"
page.should have_link "Rake tasks"
end
Then 'I should see correct document rendered for markdown branch' do
current_path.should == project_blob_path(@project, "markdown/doc/api/README.md")
page.should have_content "All API requests require authentication"
end
Then 'I should see correct directory rendered for markdown branch' do
current_path.should == project_tree_path(@project, "markdown/doc/raketasks")
page.should have_content "backup_restore.md"
page.should have_content "maintenance.md"
end
Then 'I should see the users document file in markdown branch' do
current_path.should == project_blob_path(@project, "markdown/doc/api/users.md")
page.should have_content "Get a list of users."
end
Given 'I go to wiki page' do
click_link "Wiki"
current_path.should == project_wiki_path(@project, "home")
end
And 'I add various links to the wiki page' do
fill_in "wiki[content]", with: "[test](test)\n[GitLab API doc](doc/api/README.md)\n[Rake tasks](doc/raketasks)\n"
fill_in "wiki[message]", with: "Adding links to wiki"
click_button "Create page"
end
Then 'Wiki page should have added links' do
current_path.should == project_wiki_path(@project, "home")
page.should have_content "test GitLab API doc Rake tasks"
end
And 'I click on test link' do
click_link "test"
end
Then 'I see new wiki page named test' do
current_path.should == project_wiki_path(@project, "test")
page.should have_content "Editing page"
end
When 'I go back to wiki page home' do
visit project_wiki_path(@project, "home")
current_path.should == project_wiki_path(@project, "home")
end
And 'I click on GitLab API doc link' do
click_link "GitLab API"
end
Then 'I see Gitlab API document' do
current_path.should == project_blob_path(@project, "master/doc/api/README.md")
page.should have_content "Status codes"
end
And 'I click on Rake tasks link' do
click_link "Rake tasks"
end
Then 'I see Rake tasks directory' do
current_path.should == project_tree_path(@project, "master/doc/raketasks")
page.should have_content "backup_restore.md"
page.should have_content "maintenance.md"
end
end
\ No newline at end of file
......@@ -6,6 +6,8 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
def initialize(template, options = {})
@template = template
@project = @template.instance_variable_get("@project")
@ref = @template.instance_variable_get("@ref")
@request_path = @template.instance_variable_get("@path")
super options
end
......@@ -32,7 +34,15 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
h.link_to_gfm(content, link, title: title)
end
def preprocess(full_document)
h.create_relative_links(full_document, @project.path_with_namespace, @ref, @request_path, is_wiki?)
end
def postprocess(full_document)
h.gfm(full_document)
end
def is_wiki?
@template.instance_variable_get("@wiki")
end
end
......@@ -406,6 +406,30 @@ describe GitlabMarkdownHelper do
it "should generate absolute urls for emoji" do
markdown(":smile:").should include("src=\"#{url_to_image("emoji/smile")}")
end
it "should handle relative urls for a file in master" do
actual = "[GitLab API doc](doc/api/README.md)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/blob/master/doc/api/README.md\">GitLab API doc</a></p>\n"
markdown(actual).should match(expected)
end
it "should handle relative urls for a directory in master" do
actual = "[GitLab API doc](doc/api)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/tree/master/doc/api\">GitLab API doc</a></p>\n"
markdown(actual).should match(expected)
end
it "should handle absolute urls" do
actual = "[GitLab](https://www.gitlab.com)\n"
expected = "<p><a href=\"https://www.gitlab.com\">GitLab</a></p>\n"
markdown(actual).should match(expected)
end
it "should handle wiki urls" do
actual = "[Link](test/link)\n"
expected = "<p><a href=\"/#{project.path_with_namespace}/wikis/test/link\">Link</a></p>\n"
markdown(actual).should match(expected)
end
end
describe "#render_wiki_content" do
......
......@@ -3,7 +3,7 @@ require 'spec_helper'
describe 'Gitlab::Satellite::MergeAction' do
before(:each) do
# TestEnv.init(mailer: false, init_repos: true, repos: true)
@master = ['master', 'bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a']
@master = ['master', 'b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828']
@one_after_stable = ['stable', '6ea87c47f0f8a24ae031c3fff17bc913889ecd00'] #this commit sha is one after stable
@wiki_branch = ['wiki', '635d3e09b72232b6e92a38de6cc184147e5bcb41'] #this is the commit sha where the wiki branch goes off from master
@conflicting_metior = ['metior', '313d96e42b313a0af5ab50fa233bf43e27118b3f'] #this branch conflicts with the wiki branch
......
......@@ -132,17 +132,17 @@ describe Project do
it "should close merge request if last commit from source branch was pushed to target branch" do
@merge_request.reloaded_commits
@merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/stable", @key.user)
@merge_request.last_commit.id.should == "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828"
project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828", "refs/heads/stable", @key.user)
@merge_request.reload
@merge_request.merged?.should be_true
end
it "should update merge request commits with new one if pushed to source branch" do
@merge_request.last_commit.should == nil
project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user)
project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828", "refs/heads/master", @key.user)
@merge_request.reload
@merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
@merge_request.last_commit.id.should == "b1e6a9dbf1c85e6616497a5e7bad9143a4bd0828"
end
end
......
No preview for this file type
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