Skip to content

Commit 1460bad

Browse files
committed
Detect external links by host instead of url prefix
1 parent 7958afa commit 1460bad

3 files changed

Lines changed: 31 additions & 3 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ This plugin adds `rel`, `title`, `new tab icon` and `target` to all external lin
1616
```
1717

1818
## Usage
19-
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.
19+
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`).
20+
21+
- 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.
22+
- The `www.` prefix is ignored when comparing hosts.
23+
- Skip a specific link by adding `data-no-external="true"`, e.g. `<a href="...." data-no-external="true">...</a>`.
2024
2125
### Configuration
2226
You can override the default configuration by adding the following section to your Jekyll site's `_config.yml`:

lib/jekyll-external-link-accessibility.rb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
require 'jekyll-external-link-accessibility/hooks'
22
require 'nokogiri'
3+
require 'uri'
34

45
module Jekyll
56
class ExternalLinkAccessibility
7+
EXTERNAL_SCHEMES = %w[http:// https:// //].freeze
8+
69
def self.modify_links(page)
710
config = page.site.config
11+
site_host = host_for(config['url'])
812
doc = Nokogiri::HTML5(page.output)
913
doc.css('.post-content a, .post-excerpt a').each do |a|
1014
next if a['href'].nil? || a['href'].empty? || a['href'].start_with?('#') || a['data-no-external'] == 'true'
1115

12-
if a['href'].start_with?('http') || a['href'].start_with?('/')
16+
if external_link?(a['href'], site_host)
1317
a['rel'] = external_link_rel(config: config) unless a['rel']
1418
a['target'] = external_link_target(config: config) unless a['target']
1519
a['title'] = external_link_title(config: config) unless a['title']
@@ -30,6 +34,26 @@ def self.modify_links(page)
3034
page.output = doc.to_html
3135
end
3236

37+
# A link is external only when it points to a different host than the site.
38+
# Relative links ("/blog/...") and absolute links to our own domain are internal,
39+
# so they keep their link equity and stay in the same tab.
40+
def self.external_link?(href, site_host)
41+
return false unless href.start_with?(*EXTERNAL_SCHEMES)
42+
43+
link_host = host_for(href)
44+
return true if link_host.nil?
45+
46+
link_host != site_host
47+
end
48+
49+
# Returns the host without a leading "www." so www and non-www match.
50+
def self.host_for(url)
51+
host = URI.parse(url.to_s).host
52+
host&.downcase&.sub(/\Awww\./, '')
53+
rescue URI::InvalidURIError
54+
nil
55+
end
56+
3357
def self.external_link_rel(config:)
3458
config.dig('external_links', 'rel') || 'external nofollow noopener noreferrer'
3559
end

lib/jekyll-external-link-accessibility/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
module Jekyll
44
class ExternalLinkAccessibility
5-
VERSION = '0.1.0'
5+
VERSION = '0.2.0'
66
end
77
end

0 commit comments

Comments
 (0)