Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ This plugin adds `rel`, `title`, `new tab icon` and `target` to all external lin
```

## Usage
The plugin automatically edits all links on all posts. You can however skip the check on some links, by adding the `data-no-external` attribute and setting it to `true`, e.g `<a href="...." data-no-external="true">...</a>` to the link.
The plugin automatically edits external links on all posts. A link is considered external only when it points to a host other than your site's `url` (set in `_config.yml`).

- Relative links (`/blog/...`) and absolute links to your own domain are left untouched, so they keep their link equity and open in the same tab.
- The `www.` prefix is ignored when comparing hosts.
- Skip a specific link by adding `data-no-external="true"`, e.g. `<a href="...." data-no-external="true">...</a>`.

### Configuration
You can override the default configuration by adding the following section to your Jekyll site's `_config.yml`:
Expand Down
26 changes: 25 additions & 1 deletion lib/jekyll-external-link-accessibility.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
require 'jekyll-external-link-accessibility/hooks'
require 'nokogiri'
require 'uri'

module Jekyll
class ExternalLinkAccessibility
EXTERNAL_SCHEMES = %w[http:// https:// //].freeze

def self.modify_links(page)
config = page.site.config
site_host = host_for(config['url'])
doc = Nokogiri::HTML5(page.output)
doc.css('.post-content a, .post-excerpt a').each do |a|
next if a['href'].nil? || a['href'].empty? || a['href'].start_with?('#') || a['data-no-external'] == 'true'

if a['href'].start_with?('http') || a['href'].start_with?('/')
if external_link?(a['href'], site_host)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still want to open internal links in new tabs but without the nofollow.

Like.. you are reading an article, you click an internal link and it opens a new tab, so you are not taken away from the place you were reading.

a['rel'] = external_link_rel(config: config) unless a['rel']
a['target'] = external_link_target(config: config) unless a['target']
a['title'] = external_link_title(config: config) unless a['title']
Expand All @@ -30,6 +34,26 @@ def self.modify_links(page)
page.output = doc.to_html
end

# A link is external only when it points to a different host than the site.
# Relative links ("/blog/...") and absolute links to our own domain are internal,
# so they keep their link equity and stay in the same tab.
def self.external_link?(href, site_host)
return false unless href.start_with?(*EXTERNAL_SCHEMES)

link_host = host_for(href)
return true if link_host.nil?

link_host != site_host
end

# Returns the host without a leading "www." so www and non-www match.
def self.host_for(url)
host = URI.parse(url.to_s).host
host&.downcase&.sub(/\Awww\./, '')
rescue URI::InvalidURIError
nil
end

def self.external_link_rel(config:)
config.dig('external_links', 'rel') || 'external nofollow noopener noreferrer'
end
Expand Down
4 changes: 3 additions & 1 deletion lib/jekyll-external-link-accessibility/hooks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
end

Jekyll::Hooks.register :pages, :post_render do |page|
next if %w[.scss .json .xml].include?(page.extname)
# Only rewrite HTML pages. Running the HTML parser over .xml (rss/sitemap),
# .json, .txt, etc. would wrap them in <html><body> and corrupt them.
next unless ['.html', '.htm'].include?(page.extname)
Jekyll::ExternalLinkAccessibility.modify_links(page)
end
2 changes: 1 addition & 1 deletion lib/jekyll-external-link-accessibility/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module Jekyll
class ExternalLinkAccessibility
VERSION = '0.1.0'
VERSION = '0.2.0'
end
end