Skip to content

Add option to validate links #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ You can configure this plugin in `_config.yml` under the `relative_links` key. T
relative_links:
enabled: true
collections: false
validate_links: false
```

### Excluding files
Expand Down Expand Up @@ -104,3 +105,14 @@ File | Link
### Disabling

Even if the plugin is enabled (e.g., via the `:jekyll_plugins` group in your Gemfile) you can disable it by setting the `enabled` key to `false`.

### Validating Links

By default, the plugin doesn't validate if linked files exist. It will silently keep the original Markdown links when the target file doesn't exist.

Setting the `validate_links` option to `true` enables link validation, causing Jekyll to raise an error when attempting to link to a nonexistent file, similar to Jekyll's native `{% link %}` tag.

```yml
relative_links:
validate_links: true
```
13 changes: 13 additions & 0 deletions lib/jekyll-relative-links/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Generator < Jekyll::Generator
CONFIG_KEY = "relative_links"
ENABLED_KEY = "enabled"
COLLECTIONS_KEY = "collections"
VALIDATE_LINKS_KEY = "validate_links"
LOG_KEY = "Relative Links:"

safe true
Expand Down Expand Up @@ -45,6 +46,7 @@ def generate(site)
end
end

# rubocop:disable Metrics/AbcSize
def replace_relative_links!(document)
url_base = File.dirname(document.relative_path)
return document if document.content.nil?
Expand All @@ -55,6 +57,12 @@ def replace_relative_links!(document)

path = path_from_root(link.path, url_base)
url = url_for_path(path)

if url.nil? && validate_links?
source = document.relative_path
raise "Invalid reference to '#{link.path}' in '#{source}'"
end

next original unless url

link.path = url
Expand All @@ -65,6 +73,7 @@ def replace_relative_links!(document)
rescue ArgumentError => e
raise e unless e.to_s.start_with?("invalid byte sequence in UTF-8")
end
# rubocop:enable Metrics/AbcSize

private

Expand Down Expand Up @@ -151,6 +160,10 @@ def collections?
option(COLLECTIONS_KEY) == true
end

def validate_links?
option(VALIDATE_LINKS_KEY) == true
end

def excluded?(document)
return false unless option("exclude")

Expand Down
37 changes: 37 additions & 0 deletions spec/jekyll-relative-links/generator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,43 @@
end
end

context "link validation" do
it "knows when validation is enabled" do
plugin_config = { "validate_links" => true }
generator = described_class.new({ "relative_links" => plugin_config })
expect(generator.send(:validate_links?)).to be true
end

it "knows when validation is disabled" do
plugin_config = { "validate_links" => false }
generator = described_class.new({ "relative_links" => plugin_config })
expect(generator.send(:validate_links?)).to be false
end

it "has validation disabled by default" do
generator = described_class.new({})
expect(generator.send(:validate_links?)).to be false
end

context "when validation is enabled" do
let(:plugin_config) { { "validate_links" => true } }

before do
site.reset
site.read
subject.instance_variable_set :@site, site
end

it "raises an error when a file doesn't exist" do
page.content = "[Missing](./nonexistent.md)"

expect do
subject.replace_relative_links!(page)
end.to raise_error(%r!Invalid reference to './nonexistent.md' in 'page.md'!)
end
end
end

context "a page without content" do
before { page_by_path(site, "page.md").content = nil }

Expand Down