Commit 52c3179b authored by Marin Jankovski's avatar Marin Jankovski

Do not replace links inside code blocks, less code for the same amount of work.

parent f4865881
...@@ -59,90 +59,59 @@ module GitlabMarkdownHelper ...@@ -59,90 +59,59 @@ module GitlabMarkdownHelper
end end
end end
# text - whole text from a markdown file def create_relative_links(text)
# 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
def create_relative_links(text, project, ref, requested_path)
@path_to_satellite = project.satellite.path
project_path_with_namespace = project.path_with_namespace
paths = extract_paths(text) paths = extract_paths(text)
paths.each do |file_path|
original_file_path = extract(file_path)
new_path = rebuild_path(project_path_with_namespace, original_file_path, requested_path, ref)
if reference_path?(file_path)
# Replacing old string with a new one that contains updated path
# eg. [some document]: document.md will be replaced with [some document] /namespace/project/master/blob/document.md
text.gsub!(file_path, file_path.gsub(original_file_path, "/#{new_path}"))
else
# 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
end
text
end
def extract_paths(markdown_text) paths.uniq.each do |file_path|
all_markdown_paths = pick_out_paths(markdown_text) new_path = rebuild_path(file_path)
paths = remove_empty(all_markdown_paths) # Finds quoted path so we don't replace other mentions of the string
select_relative(paths) # eg. "doc/api" will be replaced and "/home/doc/api/text" won't
text.gsub!("\"#{file_path}\"", "\"/#{new_path}\"")
end end
# Split the markdown text to each line and find all paths, this will match anything with - ]("some_text") and [some text]: file.md text
def pick_out_paths(markdown_text)
inline_paths = markdown_text.split("\n").map { |text| text.scan(/\]\(([^(]+)\)/) }
reference_paths = markdown_text.split("\n").map { |text| text.scan(/\[.*\]:.*/) }
inline_paths + reference_paths
end end
# Removes any empty result produced by not matching the regexp def extract_paths(text)
def remove_empty(paths) links = substitute_links(text)
paths.reject{|l| l.empty? }.flatten image_links = substitute_image_links(text)
links + image_links
end end
# If a path is a reference style link we need to omit ]: def substitute_links(text)
def extract(path) links = text.scan(/<a href=\"([^"]*)\">/)
path.split("]: ").last relative_links = links.flatten.reject{ |link| link_to_ignore? link }
relative_links
end end
# Reject any path that contains ignored protocol def substitute_image_links(text)
# eg. reject "https://gitlab.org} but accept "doc/api/README.md" links = text.scan(/<img src=\"([^"]*)\"/)
def select_relative(paths) relative_links = links.flatten.reject{ |link| link_to_ignore? link }
paths.reject{|path| ignored_protocols.map{|protocol| path.include?(protocol)}.any?} relative_links
end end
# Check whether a path is a reference-style link def link_to_ignore?(link)
def reference_path?(path) ignored_protocols.map{ |protocol| link.include?(protocol) }.any?
path.include?("]: ")
end end
def ignored_protocols def ignored_protocols
["http://","https://", "ftp://", "mailto:"] ["http://","https://", "ftp://", "mailto:"]
end end
def rebuild_path(path_with_namespace, path, requested_path, ref) def rebuild_path(path)
path.gsub!(/(#.*)/, "") path.gsub!(/(#.*)/, "")
id = $1 || "" id = $1 || ""
file_path = relative_file_path(path, requested_path) file_path = relative_file_path(path)
[ [
path_with_namespace, Gitlab.config.gitlab.relative_url_root,
path_with_ref(file_path, ref), @project.path_with_namespace,
path_with_ref(file_path),
file_path file_path
].compact.join("/").gsub(/\/*$/, '') + id ].compact.join("/").gsub(/^\/*|\/*$/, '') + id
end
# Checks if the path exists in the repo
# eg. checks if doc/README.md exists, if not then link to blob
def path_with_ref(path, ref)
if file_exists?(path)
"#{local_path(path)}/#{correct_ref(ref)}"
else
"blob/#{correct_ref(ref)}"
end
end end
def relative_file_path(path, requested_path) def relative_file_path(path)
requested_path = @path
nested_path = build_nested_path(path, requested_path) nested_path = build_nested_path(path, requested_path)
return nested_path if file_exists?(nested_path) return nested_path if file_exists?(nested_path)
path path
...@@ -166,6 +135,16 @@ module GitlabMarkdownHelper ...@@ -166,6 +135,16 @@ module GitlabMarkdownHelper
end end
end end
# Checks if the path exists in the repo
# eg. checks if doc/README.md exists, if not then link to blob
def path_with_ref(path)
if file_exists?(path)
"#{local_path(path)}/#{correct_ref}"
else
"blob/#{correct_ref}"
end
end
def file_exists?(path) def file_exists?(path)
return false if path.nil? return false if path.nil?
return @repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any? return @repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any?
...@@ -179,10 +158,6 @@ module GitlabMarkdownHelper ...@@ -179,10 +158,6 @@ module GitlabMarkdownHelper
return "blob" return "blob"
end end
def current_ref
@commit.nil? ? "master" : @commit.id
end
def current_sha def current_sha
if @commit if @commit
@commit.id @commit.id
...@@ -192,7 +167,7 @@ module GitlabMarkdownHelper ...@@ -192,7 +167,7 @@ module GitlabMarkdownHelper
end end
# We will assume that if no ref exists we can point to master # We will assume that if no ref exists we can point to master
def correct_ref(ref) def correct_ref
ref ? ref : "master" @ref ? @ref : "master"
end end
end end
...@@ -45,23 +45,8 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML ...@@ -45,23 +45,8 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML
end end
end end
def preprocess(full_document)
if is_wiki?
full_document
elsif @project
h.create_relative_links(full_document, @project, @ref, @request_path)
else
full_document
end
end
def postprocess(full_document) def postprocess(full_document)
full_document = h.create_relative_links(full_document)
h.gfm(full_document) h.gfm(full_document)
end end
def is_wiki?
if @template.instance_variable_get("@project_wiki")
@template.instance_variable_get("@page")
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