From aa2cc670fe2c9de772c82d90df4ee2d8a77c23fc Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 27 Apr 2015 18:54:13 -0400 Subject: [PATCH] Add Gitlab::Markdown::AutolinkFilter --- app/helpers/gitlab_markdown_helper.rb | 4 +- lib/gitlab/markdown.rb | 4 +- lib/gitlab/markdown/autolink_filter.rb | 95 ++++++++++++++++++ lib/redcarpet/render/gitlab_html.rb | 18 +--- .../gitlab/markdown/autolink_filter_spec.rb | 98 +++++++++++++++++++ 5 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 lib/gitlab/markdown/autolink_filter.rb create mode 100644 spec/lib/gitlab/markdown/autolink_filter_spec.rb diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 48d754dcf7..7dbffaae5f 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -34,9 +34,8 @@ module GitlabMarkdownHelper # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, { - safe_links_only: true, # Handled further down the line by HTML::Pipeline::SanitizationFilter - escape_html: false + escape_html: false }.merge(options)) # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use @@ -44,7 +43,6 @@ module GitlabMarkdownHelper no_intra_emphasis: true, tables: true, fenced_code_blocks: true, - autolink: true, strikethrough: true, lax_spacing: true, space_after_headers: true, diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index ffb7e16aed..beb97bbdf4 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -30,6 +30,7 @@ module Gitlab # => "\":trollface:\" module Markdown # Provide autoload paths for filters to prevent a circular dependency error + autoload :AutolinkFilter, 'gitlab/markdown/autolink_filter' autoload :CommitRangeReferenceFilter, 'gitlab/markdown/commit_range_reference_filter' autoload :CommitReferenceFilter, 'gitlab/markdown/commit_reference_filter' autoload :EmojiFilter, 'gitlab/markdown/emoji_filter' @@ -122,6 +123,7 @@ module Gitlab Gitlab::Markdown::EmojiFilter, Gitlab::Markdown::TableOfContentsFilter, + Gitlab::Markdown::AutolinkFilter, Gitlab::Markdown::UserReferenceFilter, Gitlab::Markdown::IssueReferenceFilter, @@ -130,7 +132,7 @@ module Gitlab Gitlab::Markdown::SnippetReferenceFilter, Gitlab::Markdown::CommitRangeReferenceFilter, Gitlab::Markdown::CommitReferenceFilter, - Gitlab::Markdown::LabelReferenceFilter, + Gitlab::Markdown::LabelReferenceFilter ] end diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/gitlab/markdown/autolink_filter.rb new file mode 100644 index 0000000000..97cfc1893a --- /dev/null +++ b/lib/gitlab/markdown/autolink_filter.rb @@ -0,0 +1,95 @@ +require 'html/pipeline/filter' +require 'uri' + +module Gitlab + module Markdown + # HTML Filter for auto-linking URLs in HTML. + # + # Based on HTML::Pipeline::AutolinkFilter + # + # Context options: + # :autolink - Boolean, skips all processing done by this filter when false + # :link_attr - Hash of attributes for the generated links + # + class AutolinkFilter < HTML::Pipeline::Filter + include ActionView::Helpers::TagHelper + + # Pattern to match text that should be autolinked. + # + # A URI scheme begins with a letter and may contain letters, numbers, + # plus, period and hyphen. Schemes are case-insensitive but we're being + # picky here and allowing only lowercase for autolinks. + # + # See http://en.wikipedia.org/wiki/URI_scheme + # + # The negative lookbehind ensures that users can paste a URL followed by a + # period or comma for punctuation without those characters being included + # in the generated link. + SCHEME_PATTERN = %r{([a-z][a-z0-9_\+\.\-]+:\/\/[^\s]+)(?See #{link}" + expect(filter(act).to_html).to eq exp + end + end + end + + context 'other schemes' do + let(:link) { 'foo://bar.baz/' } + + it 'autolinks smb' do + link = 'smb:///Volumes/shared/foo.pdf' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'autolinks irc' do + link = 'irc://irc.freenode.net/git' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'does not include trailing punctuation' do + doc = filter("See #{link}.") + expect(doc.at_css('a').text).to eq link + + doc = filter("See #{link}, ok?") + expect(doc.at_css('a').text).to eq link + end + + it 'accepts link_attr options' do + doc = filter("See #{link}", link_attr: {class: 'custom'}) + expect(doc.at_css('a')['class']).to eq 'custom' + end + + described_class::IGNORE_PARENTS.each do |elem| + it "ignores valid links contained inside '#{elem}' element" do + exp = act = "<#{elem}>See #{link}" + expect(filter(act).to_html).to eq exp + end + end + end + end +end