diff --git a/Gemfile b/Gemfile index 52bd1018..3d96eae4 100644 --- a/Gemfile +++ b/Gemfile @@ -20,3 +20,5 @@ gem 'color_pound_spec_reporter' # HTTP bindings to libcurl - https://github.com/taf2/curb gem 'curb' + +gem "nokogiri", "~> 1.13.10" diff --git a/Gemfile.lock b/Gemfile.lock index 7095e7d0..a458656b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -55,15 +55,20 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) + mini_portile2 (2.8.1) minitest (5.14.2) minitest-reporters (1.4.2) ansi builder minitest (>= 5.0) ruby-progressbar + nokogiri (1.13.10) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (5.0.0) + racc (1.6.2) rake (13.0.1) rb-fsevent (0.10.4) rb-inotify (0.10.1) @@ -92,7 +97,8 @@ DEPENDENCIES kramdown-parser-gfm minitest minitest-reporters + nokogiri (~> 1.13.10) rake BUNDLED WITH - 2.1.4 + 2.3.26 diff --git a/_plugins/mark_external_links.rb b/_plugins/mark_external_links.rb new file mode 100644 index 00000000..71ec106e --- /dev/null +++ b/_plugins/mark_external_links.rb @@ -0,0 +1,56 @@ +# This file is based on code from https://github.com/riboseinc/jekyll-external-links + +require 'nokogiri' +require 'uri' + +# Given hostname and content, updates any found elements as follows: +# +# - Adds `rel` attribute +# - Adds css class for external link icon +# +# Only processes external links where `href` starts with "http" +# and target host does not start with given site hostname. +def process_content(site_hostname, content, marker_css, link_selector) + content = Nokogiri::HTML(content) + content.css(link_selector).each do |a| + next unless a.get_attribute('href') =~ /\Ahttp/i + next if a.get_attribute('href') =~ /\Ahttp(s)?:\/\/#{site_hostname}\//i + next if a.inner_html.include? "icon-ext" + next if a.inner_html.include? "fa" # another icon is part of the link, e.g fa-github + next if a.inner_html.include? a.get_attribute('href') # plain links + a.set_attribute('rel', 'external') + a.set_attribute('class', marker_css) + end + return content.to_s +end + +def mark_links_in_page_or_document(page_or_document) + site_hostname = URI(page_or_document.site.config['url']).host + + # The link is marked as external by: + # (1) setting the rel attribute to external and + # (2) appending specified marker css class. + marker_css = "icon-ext" + + # Determines which links to mark. E.g., usually we don’t want to mark navigational links. + link_selector = 'a:not(.internal-link)' + + # Do not process assets or other non-HTML files + unless (page_or_document.respond_to?(:asset_file?) and + page_or_document.asset_file?) or + page_or_document.output_ext != ".html" + page_or_document.output = process_content( + site_hostname, + page_or_document.output, + marker_css, + link_selector) + end +end + +Jekyll::Hooks.register :documents, :post_render do |doc| + mark_links_in_page_or_document(doc) +end + +Jekyll::Hooks.register :pages, :post_render do |page| + mark_links_in_page_or_document(page) +end diff --git a/assets/css/all.sass b/assets/css/all.sass index 26d6f7af..d9708f53 100644 --- a/assets/css/all.sass +++ b/assets/css/all.sass @@ -175,6 +175,16 @@ a color: #ccc cursor: help +.icon-ext + &:after + position: relative + top: -0.5em + font-size: 0.7em + content: "↗" + color: #aaaaaa + display: inline-block + text-decoration: none + .backlink-box position: relative font-size: 0.9em