/
theme.rb
90 lines (73 loc) · 2.43 KB
/
theme.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# frozen_string_literal: true
module Jekyll
class Theme
extend Forwardable
attr_reader :name
def_delegator :gemspec, :version, :version
def initialize(name)
@name = name.downcase.strip
Jekyll.logger.debug "Theme:", name
Jekyll.logger.debug "Theme source:", root
end
def root
# Must use File.realpath to resolve symlinks created by rbenv
# Otherwise, Jekyll.sanitized path with prepend the unresolved root
@root ||= File.realpath(gemspec.full_gem_path)
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
raise "Path #{gemspec.full_gem_path} does not exist, is not accessible or includes " \
"a symbolic link loop"
end
# The name of theme directory
def basename
@basename ||= File.basename(root)
end
def includes_path
@includes_path ||= path_for "_includes"
end
def layouts_path
@layouts_path ||= path_for "_layouts"
end
def sass_path
@sass_path ||= path_for "_sass"
end
def assets_path
@assets_path ||= path_for "assets"
end
def data_path
@data_path ||= path_for "_data"
end
def runtime_dependencies
gemspec.runtime_dependencies
end
private
def path_for(folder)
path = realpath_for(folder)
path if path && File.directory?(path)
end
def realpath_for(folder)
# This resolves all symlinks for the theme subfolder and then ensures that the directory
# remains inside the theme root. This prevents the use of symlinks for theme subfolders to
# escape the theme root.
# However, symlinks are allowed to point to other directories within the theme.
Jekyll.sanitized_path(root, File.realpath(Jekyll.sanitized_path(root, folder.to_s)))
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP => e
log_realpath_exception(e, folder)
nil
end
def log_realpath_exception(err, folder)
return if err.is_a?(Errno::ENOENT)
case err
when Errno::EACCES
Jekyll.logger.error "Theme error:", "Directory '#{folder}' is not accessible."
when Errno::ELOOP
Jekyll.logger.error "Theme error:", "Directory '#{folder}' includes a symbolic link loop."
end
end
def gemspec
@gemspec ||= Gem::Specification.find_by_name(name)
rescue Gem::LoadError
raise Jekyll::Errors::MissingDependencyException,
"The #{name} theme could not be found."
end
end
end