Skip to content
Snippets Groups Projects
Commit 134c848c authored by Douwe Maan's avatar Douwe Maan
Browse files

Autolink URLs and emails in blobs and diffs

parent faa2947f
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -185,6 +185,11 @@ $dark-il: #de935f;
color: $dark-highlight-color !important;
}
 
// Links to URLs, emails, or dependencies
.line a {
color: $dark-na;
}
.hll { background-color: $dark-hll-bg; }
.c { color: $dark-c; } /* Comment */
.err { color: $dark-err; } /* Error */
Loading
Loading
Loading
Loading
@@ -185,6 +185,11 @@ $monokai-gi: #a6e22e;
color: $black !important;
}
 
// Links to URLs, emails, or dependencies
.line a {
color: $monokai-k;
}
.hll { background-color: $monokai-hll; }
.c { color: $monokai-c; } /* Comment */
.err { color: $monokai-err-color; background-color: $monokai-err-bg; } /* Error */
Loading
Loading
Loading
Loading
@@ -188,6 +188,11 @@ $solarized-dark-il: #2aa198;
background-color: $solarized-dark-highlight !important;
}
 
// Links to URLs, emails, or dependencies
.line a {
color: $solarized-dark-kd;
}
/* Solarized Dark
 
For use with Jekyll and Pygments
Loading
Loading
Loading
Loading
@@ -196,6 +196,11 @@ $solarized-light-il: #2aa198;
background-color: $solarized-light-highlight !important;
}
 
// Links to URLs, emails, or dependencies
.line a {
color: $solarized-light-kd;
}
/* Solarized Light
 
For use with Jekyll and Pygments
Loading
Loading
Loading
Loading
@@ -203,6 +203,11 @@ $white-gc-bg: #eaf2f5;
background-color: $white-highlight !important;
}
 
// Links to URLs, emails, or dependencies
.line a {
color: $white-nb;
}
.hll { background-color: $white-hll-bg; }
.c { color: $white-c; font-style: italic; }
.err { color: $white-err; background-color: $white-err-bg; }
Loading
Loading
Loading
Loading
@@ -54,15 +54,13 @@ module Banzai
#
# `@doc` will be re-parsed with the HTML String from Rinku.
def rinku_parse
# Convert the options from a Hash to a String that Rinku expects
options = tag_options(link_options)
# NOTE: We don't parse email links because it will erroneously match
# external Commit and CommitRange references.
#
# The final argument tells Rinku to link short URLs that don't include a
# period (e.g., http://localhost:3000/)
rinku = Rinku.auto_link(html, :urls, options, IGNORE_PARENTS.to_a, 1)
mode = context[:autolink_emails] ? :all : :urls
rinku = Rinku.auto_link(html, mode, tag_options(link_options), IGNORE_PARENTS.to_a, 1)
 
return if rinku == html
 
Loading
Loading
@@ -111,9 +109,9 @@ module Banzai
# order to be output literally rather than escaped.
match.gsub!(/((?:&[\w#]+;)+)\z/, '')
dropped = ($1 || '').html_safe
match = ERB::Util.html_escape_once(match)
 
options = link_options.merge(href: match)
content_tag(:a, match, options) + dropped
%{<a href="#{match}" #{tag_options(link_options)}>#{match}</a>#{dropped}}.html_safe
end
 
def autolink_filter(text)
Loading
Loading
module Banzai
module Pipeline
class AutolinkPipeline < BasePipeline
def self.filters
@filters ||= FilterArray[
Filter::AutolinkFilter,
Filter::ExternalLinkFilter
]
end
end
end
end
Loading
Loading
@@ -21,16 +21,8 @@ module Gitlab
end
 
def highlight(text, continue: true, plain: false)
if plain
hl_lexer = Rouge::Lexers::PlainText
continue = false
else
hl_lexer = self.lexer
end
@formatter.format(hl_lexer.lex(text, continue: continue), tag: hl_lexer.tag).html_safe
rescue
@formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe
highlighted_text = highlight_text(text, continue: continue, plain: plain)
autolink_strings(highlighted_text)
end
 
def lexer
Loading
Loading
@@ -50,5 +42,41 @@ module Gitlab
 
Rouge::Lexer.find_fancy(language_name)
end
def highlight_text(text, continue: true, plain: false)
if plain
highlight_plain(text)
else
highlight_rich(text, continue: continue)
end
end
def highlight_plain(text)
@formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe
end
def highlight_rich(text, continue: true)
@formatter.format(lexer.lex(text, continue: continue), tag: lexer.tag).html_safe
rescue
highlight_plain(text)
end
def autolink_strings(highlighted_text)
doc = Nokogiri::HTML::DocumentFragment.parse(highlighted_text)
# Files without highlighting have all text in `span.line`.
# Files with highlighting have strings and comments in `span`s with a
# `class` starting with `c` or `s`.
doc.xpath('.//span[@class="line" or starts-with(@class, "c") or starts-with(@class, "s")]/text()').each do |node|
content = node.to_html
html = Banzai.render(content, pipeline: :autolink, autolink_emails: true)
next if html == content
node.replace(html)
end
doc.to_html.html_safe
end
end
end
Loading
Loading
@@ -9,7 +9,7 @@ describe Gitlab::Highlight, lib: true do
 
describe '.highlight_lines' do
let(:lines) do
Gitlab::Highlight.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb')
described_class.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb')
end
 
it 'highlights all the lines properly' do
Loading
Loading
@@ -57,4 +57,69 @@ describe Gitlab::Highlight, lib: true do
end
end
end
describe '#highlight' do
subject { described_class.highlight(file_name, file_content) }
context "plain text file" do
let(:file_name) { "example.txt" }
let(:file_content) do
<<-CONTENT.strip_heredoc
URL: http://www.google.com
Email: hello@example.com
CONTENT
end
it "links URLs" do
expect(subject).to include(%{<a href="http://www.google.com" rel="nofollow noreferrer" target="_blank">http://www.google.com</a>})
end
it "links emails" do
expect(subject).to include(%{<a href="mailto:hello@example.com">hello@example.com</a>})
end
end
context "file with highlighting" do
let(:file_name) { "example.rb" }
let(:file_content) do
<<-CONTENT.strip_heredoc
# URL in comment: http://www.google.com
# Email in comment: hello@example.com
"URL in string: http://www.google.com"
"Email in string: hello@example.com"
# <http://www.google.com>
# <url>http://www.google.com</url>
CONTENT
end
context "in a comment" do
it "links URLs" do
expect(subject).to include(%{URL in comment: <a href="http://www.google.com" rel="nofollow noreferrer" target="_blank">http://www.google.com</a>})
end
it "links emails" do
expect(subject).to include(%{Email in comment: <a href="mailto:hello@example.com">hello@example.com</a>})
end
end
context "in a string" do
it "links URLs" do
expect(subject).to include(%{URL in string: <a href="http://www.google.com" rel="nofollow noreferrer" target="_blank">http://www.google.com</a>})
end
it "links emails" do
expect(subject).to include(%{Email in string: <a href="mailto:hello@example.com">hello@example.com</a>})
end
end
context 'in HTML/XML tags' do
it "links URLs" do
expect(subject).to include(%{&lt;<a href="http://www.google.com" rel="nofollow noreferrer" target="_blank">http://www.google.com</a>&gt;})
expect(subject).to include(%{&lt;url&gt;<a href="http://www.google.com" rel="nofollow noreferrer" target="_blank">http://www.google.com</a>&lt;/url&gt;})
end
end
end
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment