summaryrefslogtreecommitdiff
path: root/lib/banzai
diff options
context:
space:
mode:
authorTimothy Andrew <mail@timothyandrew.net>2016-06-08 10:29:20 +0530
committerTimothy Andrew <mail@timothyandrew.net>2016-06-09 10:04:15 +0530
commit8e71c19a6940b8d82c70ee9b2550b62b5169eb54 (patch)
tree2769fcd2159b446b04e3bde00a074aac160cf884 /lib/banzai
parent30524901e28176e96e7c0d1a710508367ff99d9f (diff)
downloadgitlab-ce-8e71c19a6940b8d82c70ee9b2550b62b5169eb54.tar.gz
Implement the correct linking behaviour in `WikiLinkFilter`.
Original Comments ================= - Linking behaves as per rules documented here: https://gitlab.com/gitlab-org/gitlab-ce/blob/16568-document-wiki-linking-behavior/doc/markdown/wiki.md - All links (to other wiki pages) are rewritten to be at the level of the app root. We can't use links relative to the current page ('./foo', 'foo', '../foo'), because they won't work in the markdown preview, where the current page is suffixed with `/edit` - Move existing `WikiLinkFilter` specs to `WikiPipeline` spec. It makes sense to run these tests on the combined output of the pipeline, rather than a single filter, since we can catch issues with conflicting filters. - Add more tests to cover the new linking @rymai's Review =============== - Classes nested under `WikiLinkFilter` should declare `WikiLinkFilter`'s inherit, so nothing changes if the nested class is loaded first. - Add a blank line after a guard clause - Use keyword arguments for the `Rewriter` constructor - Invert a condition - use `if` instead of `unless` - Inline a `let` in `WikiPipeline` spec - it was only used in a single place - Change out of date spec names - Add a comment for every rewrite rule in `Rewriter`
Diffstat (limited to 'lib/banzai')
-rw-r--r--lib/banzai/filter/wiki_link_filter.rb32
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb40
2 files changed, 46 insertions, 26 deletions
diff --git a/lib/banzai/filter/wiki_link_filter.rb b/lib/banzai/filter/wiki_link_filter.rb
index 7dc771afd71..37a2779d453 100644
--- a/lib/banzai/filter/wiki_link_filter.rb
+++ b/lib/banzai/filter/wiki_link_filter.rb
@@ -2,7 +2,8 @@ require 'uri'
module Banzai
module Filter
- # HTML filter that "fixes" relative links to files in a repository.
+ # HTML filter that "fixes" links to pages/files in a wiki.
+ # Rewrite rules are documented in the `WikiPipeline` spec.
#
# Context options:
# :project_wiki
@@ -25,36 +26,15 @@ module Banzai
end
def process_link_attr(html_attr)
- return if html_attr.blank? || file_reference?(html_attr) || hierarchical_link?(html_attr)
+ return if html_attr.blank?
- uri = URI(html_attr.value)
- if uri.relative? && uri.path.present?
- html_attr.value = rebuild_wiki_uri(uri).to_s
- end
+ html_attr.value = apply_rewrite_rules(html_attr.value)
rescue URI::Error
# noop
end
- def rebuild_wiki_uri(uri)
- uri.path = ::File.join(project_wiki_base_path, uri.path)
- uri
- end
-
- def project_wiki
- context[:project_wiki]
- end
-
- def file_reference?(html_attr)
- !File.extname(html_attr.value).blank?
- end
-
- # Of the form `./link`, `../link`, or similar
- def hierarchical_link?(html_attr)
- html_attr.value[0] == '.'
- end
-
- def project_wiki_base_path
- project_wiki && project_wiki.wiki_base_path
+ def apply_rewrite_rules(link_string)
+ Rewriter.new(link_string, wiki: context[:project_wiki], slug: context[:page_slug]).apply_rules
end
end
end
diff --git a/lib/banzai/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
new file mode 100644
index 00000000000..2e2c8da311e
--- /dev/null
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -0,0 +1,40 @@
+module Banzai
+ module Filter
+ class WikiLinkFilter < HTML::Pipeline::Filter
+ class Rewriter
+ def initialize(link_string, wiki:, slug:)
+ @uri = Addressable::URI.parse(link_string)
+ @wiki_base_path = wiki && wiki.wiki_base_path
+ @slug = slug
+ end
+
+ def apply_rules
+ apply_file_link_rules!
+ apply_hierarchical_link_rules!
+ apply_relative_link_rules!
+ @uri.to_s
+ end
+
+ private
+
+ # Of the form 'file.md'
+ def apply_file_link_rules!
+ @uri = Addressable::URI.join(@slug, @uri) if @uri.extname.present?
+ end
+
+ # Of the form `./link`, `../link`, or similar
+ def apply_hierarchical_link_rules!
+ @uri = Addressable::URI.join(@slug, @uri) if @uri.to_s[0] == '.'
+ end
+
+ # Any link _not_ of the form `http://example.com/`
+ def apply_relative_link_rules!
+ if @uri.relative? && @uri.path.present?
+ link = ::File.join(@wiki_base_path, @uri.path)
+ @uri = Addressable::URI.parse(link)
+ end
+ end
+ end
+ end
+ end
+end