jekyll/lib/jekyll/commands/doctor.rb

178 lines
5.9 KiB
Ruby

# frozen_string_literal: true
module Jekyll
module Commands
class Doctor < Command
class << self
def init_with_program(prog)
prog.command(:doctor) do |c|
c.syntax "doctor"
c.description "Search site and print specific deprecation warnings"
c.alias(:hyde)
c.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]", Array,
"Custom configuration file"
c.action do |_, options|
Jekyll::Commands::Doctor.process(options)
end
end
end
def process(options)
site = Jekyll::Site.new(configuration_from_options(options))
site.reset
site.read
site.generate
if healthy?(site)
Jekyll.logger.info "Your test results", "are in. Everything looks fine."
else
abort
end
end
def healthy?(site)
[
fsnotify_buggy?(site),
!deprecated_relative_permalinks(site),
!conflicting_urls(site),
!urls_only_differ_by_case(site),
proper_site_url?(site),
properly_gathered_posts?(site),
].all?
end
def properly_gathered_posts?(site)
return true if site.config["collections_dir"].empty?
posts_at_root = site.in_source_dir("_posts")
return true unless File.directory?(posts_at_root)
Jekyll.logger.warn "Warning:",
"Detected '_posts' directory outside custom `collections_dir`!"
Jekyll.logger.warn "",
"Please move '#{posts_at_root}' into the custom directory at " \
"'#{site.in_source_dir(site.config["collections_dir"])}'"
false
end
def deprecated_relative_permalinks(site)
if site.config["relative_permalinks"]
Jekyll::Deprecator.deprecation_message "Your site still uses relative permalinks, " \
"which was removed in Jekyll v3.0.0."
true
end
end
def conflicting_urls(site)
conflicting_urls = false
destination_map(site).each do |dest, paths|
next unless paths.size > 1
conflicting_urls = true
Jekyll.logger.warn "Conflict:",
"The following destination is shared by multiple files."
Jekyll.logger.warn "", "The written file may end up with unexpected contents."
Jekyll.logger.warn "", dest.to_s.cyan
paths.each { |path| Jekyll.logger.warn "", " - #{path}" }
Jekyll.logger.warn ""
end
conflicting_urls
end
def fsnotify_buggy?(_site)
return true unless Utils::Platforms.osx?
if Dir.pwd != `pwd`.strip
Jekyll.logger.error <<~STR
We have detected that there might be trouble using fsevent on your
operating system, you can read https://github.com/thibaudgg/rb-fsevent/wiki/no-fsevents-fired-(OSX-bug)
for possible workarounds or you can work around it immediately
with `--force-polling`.
STR
false
end
true
end
def urls_only_differ_by_case(site)
urls_only_differ_by_case = false
urls = case_insensitive_urls(site.pages + site.docs_to_write, site.dest)
urls.each_value do |real_urls|
next unless real_urls.uniq.size > 1
urls_only_differ_by_case = true
Jekyll.logger.warn "Warning:", "The following URLs only differ by case. On a " \
"case-insensitive file system one of the URLs will be " \
"overwritten by the other: #{real_urls.join(", ")}"
end
urls_only_differ_by_case
end
def proper_site_url?(site)
url = site.config["url"]
[
url_exists?(url),
url_valid?(url),
url_absolute(url),
].all?
end
private
def destination_map(site)
{}.tap do |result|
site.each_site_file do |thing|
next if allow_used_permalink?(thing)
dest_path = thing.destination(site.dest)
(result[dest_path] ||= []) << thing.path
end
end
end
def allow_used_permalink?(item)
defined?(JekyllRedirectFrom) && item.is_a?(JekyllRedirectFrom::RedirectPage)
end
def case_insensitive_urls(things, destination)
things.each_with_object({}) do |thing, memo|
dest = thing.destination(destination)
(memo[dest.downcase] ||= []) << dest
end
end
def url_exists?(url)
return true unless url.nil? || url.empty?
Jekyll.logger.warn "Warning:", "You didn't set an URL in the config file, you may " \
"encounter problems with some plugins."
false
end
def url_valid?(url)
Addressable::URI.parse(url)
true
# Addressable::URI#parse only raises a TypeError
# https://github.com/sporkmonger/addressable/blob/0a0e96acb17225f9b1c9cab0bad332b448934c9a/lib/addressable/uri.rb#L103
rescue TypeError
Jekyll.logger.warn "Warning:", "The site URL does not seem to be valid, " \
"check the value of `url` in your config file."
false
end
def url_absolute(url)
return true if url.is_a?(String) && Addressable::URI.parse(url).absolute?
Jekyll.logger.warn "Warning:", "Your site URL does not seem to be absolute, " \
"check the value of `url` in your config file."
false
end
end
end
end
end