jekyll 3.9.1 → 4.0.0.pre.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +27 -50
- data/LICENSE +1 -1
- data/README.markdown +46 -17
- data/lib/blank_template/_config.yml +3 -0
- data/lib/blank_template/_layouts/default.html +12 -0
- data/lib/blank_template/_sass/main.scss +9 -0
- data/lib/blank_template/assets/css/main.scss +4 -0
- data/lib/blank_template/index.md +8 -0
- data/lib/jekyll.rb +5 -0
- data/lib/jekyll/cache.rb +183 -0
- data/lib/jekyll/cleaner.rb +2 -1
- data/lib/jekyll/collection.rb +78 -8
- data/lib/jekyll/command.rb +31 -6
- data/lib/jekyll/commands/build.rb +11 -20
- data/lib/jekyll/commands/clean.rb +2 -0
- data/lib/jekyll/commands/doctor.rb +15 -8
- data/lib/jekyll/commands/help.rb +1 -1
- data/lib/jekyll/commands/new.rb +37 -39
- data/lib/jekyll/commands/new_theme.rb +30 -28
- data/lib/jekyll/commands/serve.rb +46 -80
- data/lib/jekyll/commands/serve/live_reload_reactor.rb +6 -10
- data/lib/jekyll/commands/serve/servlet.rb +9 -11
- data/lib/jekyll/configuration.rb +26 -26
- data/lib/jekyll/converters/identity.rb +18 -0
- data/lib/jekyll/converters/markdown.rb +49 -40
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +1 -10
- data/lib/jekyll/converters/smartypants.rb +34 -14
- data/lib/jekyll/convertible.rb +11 -13
- data/lib/jekyll/deprecator.rb +1 -3
- data/lib/jekyll/document.rb +44 -41
- data/lib/jekyll/drops/collection_drop.rb +2 -3
- data/lib/jekyll/drops/document_drop.rb +2 -1
- data/lib/jekyll/drops/drop.rb +3 -6
- data/lib/jekyll/drops/excerpt_drop.rb +4 -0
- data/lib/jekyll/drops/site_drop.rb +4 -13
- data/lib/jekyll/drops/unified_payload_drop.rb +1 -0
- data/lib/jekyll/drops/url_drop.rb +1 -0
- data/lib/jekyll/entry_filter.rb +2 -1
- data/lib/jekyll/excerpt.rb +45 -34
- data/lib/jekyll/external.rb +10 -5
- data/lib/jekyll/filters.rb +72 -31
- data/lib/jekyll/filters/date_filters.rb +6 -3
- data/lib/jekyll/filters/grouping_filters.rb +1 -2
- data/lib/jekyll/filters/url_filters.rb +6 -1
- data/lib/jekyll/frontmatter_defaults.rb +35 -19
- data/lib/jekyll/hooks.rb +2 -3
- data/lib/jekyll/liquid_extensions.rb +0 -2
- data/lib/jekyll/liquid_renderer.rb +13 -1
- data/lib/jekyll/liquid_renderer/file.rb +14 -3
- data/lib/jekyll/liquid_renderer/table.rb +67 -65
- data/lib/jekyll/log_adapter.rb +5 -1
- data/lib/jekyll/page.rb +10 -11
- data/lib/jekyll/page_without_a_file.rb +0 -4
- data/lib/jekyll/plugin.rb +5 -11
- data/lib/jekyll/plugin_manager.rb +2 -0
- data/lib/jekyll/reader.rb +38 -8
- data/lib/jekyll/readers/data_reader.rb +7 -9
- data/lib/jekyll/readers/layout_reader.rb +2 -12
- data/lib/jekyll/readers/post_reader.rb +29 -17
- data/lib/jekyll/readers/static_file_reader.rb +1 -1
- data/lib/jekyll/readers/theme_assets_reader.rb +7 -5
- data/lib/jekyll/regenerator.rb +4 -12
- data/lib/jekyll/renderer.rb +14 -25
- data/lib/jekyll/site.rb +78 -34
- data/lib/jekyll/static_file.rb +47 -11
- data/lib/jekyll/stevenson.rb +2 -3
- data/lib/jekyll/tags/highlight.rb +22 -52
- data/lib/jekyll/tags/include.rb +22 -38
- data/lib/jekyll/tags/link.rb +11 -7
- data/lib/jekyll/tags/post_url.rb +17 -16
- data/lib/jekyll/theme.rb +12 -23
- data/lib/jekyll/theme_builder.rb +91 -89
- data/lib/jekyll/url.rb +3 -2
- data/lib/jekyll/utils.rb +5 -4
- data/lib/jekyll/utils/ansi.rb +1 -1
- data/lib/jekyll/utils/exec.rb +0 -1
- data/lib/jekyll/utils/internet.rb +2 -4
- data/lib/jekyll/utils/platforms.rb +8 -8
- data/lib/jekyll/utils/thread_event.rb +1 -5
- data/lib/jekyll/utils/win_tz.rb +1 -1
- data/lib/jekyll/version.rb +1 -1
- data/lib/site_template/.gitignore +2 -0
- data/lib/site_template/404.html +1 -0
- data/lib/site_template/_config.yml +17 -5
- data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +5 -1
- data/lib/site_template/{about.md → about.markdown} +0 -0
- data/lib/site_template/{index.md → index.markdown} +0 -0
- data/lib/theme_template/gitignore.erb +1 -0
- data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -0
- metadata +85 -51
- data/lib/jekyll/converters/markdown/rdiscount_parser.rb +0 -37
- data/lib/jekyll/converters/markdown/redcarpet_parser.rb +0 -112
- data/lib/jekyll/utils/rouge.rb +0 -22
data/lib/jekyll/stevenson.rb
CHANGED
@@ -16,9 +16,8 @@ module Jekyll
|
|
16
16
|
severity ||= UNKNOWN
|
17
17
|
@logdev = logdevice(severity)
|
18
18
|
|
19
|
-
if @logdev.nil? || severity < @level
|
20
|
-
|
21
|
-
end
|
19
|
+
return true if @logdev.nil? || severity < @level
|
20
|
+
|
22
21
|
progname ||= @progname
|
23
22
|
if message.nil?
|
24
23
|
if block_given?
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Jekyll
|
4
4
|
module Tags
|
5
|
-
class HighlightBlock < Liquid::
|
5
|
+
class HighlightBlock < Liquid::Raw
|
6
6
|
include Liquid::StandardFilters
|
7
7
|
|
8
8
|
# The regular expression syntax checker. Start with the language specifier.
|
@@ -10,7 +10,7 @@ module Jekyll
|
|
10
10
|
# forms: name, name=value, or name="<quoted list>"
|
11
11
|
#
|
12
12
|
# <quoted list> is a space-separated list of numbers
|
13
|
-
SYNTAX = %r!^([a-zA-Z0-9.+#_-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)
|
13
|
+
SYNTAX = %r!^([a-zA-Z0-9.+#_-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$!.freeze
|
14
14
|
|
15
15
|
def initialize(tag_name, markup, tokens)
|
16
16
|
super
|
@@ -18,29 +18,29 @@ module Jekyll
|
|
18
18
|
@lang = Regexp.last_match(1).downcase
|
19
19
|
@highlight_options = parse_options(Regexp.last_match(2))
|
20
20
|
else
|
21
|
-
raise SyntaxError,
|
22
|
-
Syntax Error in tag 'highlight' while parsing the following markup:
|
21
|
+
raise SyntaxError, <<~MSG
|
22
|
+
Syntax Error in tag 'highlight' while parsing the following markup:
|
23
23
|
|
24
|
-
|
24
|
+
#{markup}
|
25
25
|
|
26
|
-
Valid syntax: highlight <lang> [linenos]
|
27
|
-
MSG
|
26
|
+
Valid syntax: highlight <lang> [linenos]
|
27
|
+
MSG
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
LEADING_OR_TRAILING_LINE_TERMINATORS = %r!\A(\n|\r)+|(\n|\r)+\z!.freeze
|
32
|
+
|
31
33
|
def render(context)
|
32
34
|
prefix = context["highlighter_prefix"] || ""
|
33
35
|
suffix = context["highlighter_suffix"] || ""
|
34
|
-
code
|
35
|
-
|
36
|
-
is_safe = !!context.registers[:site].safe
|
36
|
+
code = @body.gsub(LEADING_OR_TRAILING_LINE_TERMINATORS, "")
|
37
37
|
|
38
38
|
output =
|
39
39
|
case context.registers[:site].highlighter
|
40
|
-
when "pygments"
|
41
|
-
render_pygments(code, is_safe)
|
42
40
|
when "rouge"
|
43
41
|
render_rouge(code)
|
42
|
+
when "pygments"
|
43
|
+
render_pygments(code, context)
|
44
44
|
else
|
45
45
|
render_codehighlighter(code)
|
46
46
|
end
|
@@ -49,23 +49,9 @@ MSG
|
|
49
49
|
prefix + rendered_output + suffix
|
50
50
|
end
|
51
51
|
|
52
|
-
def sanitized_opts(opts, is_safe)
|
53
|
-
if is_safe
|
54
|
-
Hash[[
|
55
|
-
[:startinline, opts.fetch(:startinline, nil)],
|
56
|
-
[:hl_lines, opts.fetch(:hl_lines, nil)],
|
57
|
-
[:linenos, opts.fetch(:linenos, nil)],
|
58
|
-
[:encoding, opts.fetch(:encoding, "utf-8")],
|
59
|
-
[:cssclass, opts.fetch(:cssclass, nil)],
|
60
|
-
].reject { |f| f.last.nil? }]
|
61
|
-
else
|
62
|
-
opts
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
52
|
private
|
67
53
|
|
68
|
-
OPTIONS_REGEX = %r!(?:\w="[^"]*"|\w=\w|\w)
|
54
|
+
OPTIONS_REGEX = %r!(?:\w="[^"]*"|\w=\w|\w)+!.freeze
|
69
55
|
|
70
56
|
def parse_options(input)
|
71
57
|
options = {}
|
@@ -75,7 +61,7 @@ MSG
|
|
75
61
|
input.scan(OPTIONS_REGEX) do |opt|
|
76
62
|
key, value = opt.split("=")
|
77
63
|
# If a quoted list, convert to array
|
78
|
-
if value
|
64
|
+
if value&.include?('"')
|
79
65
|
value.delete!('"')
|
80
66
|
value = value.split
|
81
67
|
end
|
@@ -86,33 +72,15 @@ MSG
|
|
86
72
|
options
|
87
73
|
end
|
88
74
|
|
89
|
-
def render_pygments(code,
|
90
|
-
Jekyll
|
91
|
-
|
92
|
-
|
93
|
-
code,
|
94
|
-
:lexer => @lang,
|
95
|
-
:options => sanitized_opts(@highlight_options, is_safe)
|
96
|
-
)
|
97
|
-
|
98
|
-
if highlighted_code.nil?
|
99
|
-
Jekyll.logger.error <<-MSG
|
100
|
-
There was an error highlighting your code:
|
101
|
-
|
102
|
-
#{code}
|
103
|
-
|
104
|
-
While attempting to convert the above code, Pygments.rb returned an unacceptable value.
|
105
|
-
This is usually a timeout problem solved by running `jekyll build` again.
|
106
|
-
MSG
|
107
|
-
raise ArgumentError, "Pygments.rb returned an unacceptable value "\
|
108
|
-
"when attempting to highlight some code."
|
109
|
-
end
|
110
|
-
|
111
|
-
highlighted_code.sub('<div class="highlight"><pre>', "").sub("</pre></div>", "")
|
75
|
+
def render_pygments(code, _context)
|
76
|
+
Jekyll.logger.warn "Warning:", "Highlight Tag no longer supports rendering with Pygments."
|
77
|
+
Jekyll.logger.warn "", "Using the default highlighter, Rouge, instead."
|
78
|
+
render_rouge(code)
|
112
79
|
end
|
113
80
|
|
114
81
|
def render_rouge(code)
|
115
|
-
|
82
|
+
require "rouge"
|
83
|
+
formatter = ::Rouge::Formatters::HTMLLegacy.new(
|
116
84
|
:line_numbers => @highlight_options[:linenos],
|
117
85
|
:wrap => false,
|
118
86
|
:css_class => "highlight",
|
@@ -135,6 +103,8 @@ MSG
|
|
135
103
|
"<figure class=\"highlight\"><pre><code #{code_attributes}>"\
|
136
104
|
"#{code.chomp}</code></pre></figure>"
|
137
105
|
end
|
106
|
+
|
107
|
+
def ensure_valid_markup(tag_name, markup, parse_context); end
|
138
108
|
end
|
139
109
|
end
|
140
110
|
end
|
data/lib/jekyll/tags/include.rb
CHANGED
@@ -2,28 +2,19 @@
|
|
2
2
|
|
3
3
|
module Jekyll
|
4
4
|
module Tags
|
5
|
-
class IncludeTagError < StandardError
|
6
|
-
attr_accessor :path
|
7
|
-
|
8
|
-
def initialize(msg, path)
|
9
|
-
super(msg)
|
10
|
-
@path = path
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
5
|
class IncludeTag < Liquid::Tag
|
15
6
|
VALID_SYNTAX = %r!
|
16
7
|
([\w-]+)\s*=\s*
|
17
8
|
(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))
|
18
|
-
!x
|
9
|
+
!x.freeze
|
19
10
|
VARIABLE_SYNTAX = %r!
|
20
11
|
(?<variable>[^{]*(\{\{\s*[\w\-\.]+\s*(\|.*)?\}\}[^\s{}]*)+)
|
21
12
|
(?<params>.*)
|
22
|
-
!mx
|
13
|
+
!mx.freeze
|
23
14
|
|
24
|
-
FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z
|
25
|
-
VALID_FILENAME_CHARS = %r!^[\w
|
26
|
-
INVALID_SEQUENCES = %r![./]{2,}
|
15
|
+
FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze
|
16
|
+
VALID_FILENAME_CHARS = %r!^[\w/\.-]+$!.freeze
|
17
|
+
INVALID_SEQUENCES = %r![./]{2,}!.freeze
|
27
18
|
|
28
19
|
def initialize(tag_name, markup, tokens)
|
29
20
|
super
|
@@ -50,9 +41,9 @@ module Jekyll
|
|
50
41
|
markup = markup[match.end(0)..-1]
|
51
42
|
|
52
43
|
value = if match[2]
|
53
|
-
match[2].gsub(
|
44
|
+
match[2].gsub('\\"', '"')
|
54
45
|
elsif match[3]
|
55
|
-
match[3].gsub(
|
46
|
+
match[3].gsub("\\'", "'")
|
56
47
|
elsif match[4]
|
57
48
|
context[match[4]]
|
58
49
|
end
|
@@ -64,31 +55,31 @@ module Jekyll
|
|
64
55
|
|
65
56
|
def validate_file_name(file)
|
66
57
|
if file =~ INVALID_SEQUENCES || file !~ VALID_FILENAME_CHARS
|
67
|
-
raise ArgumentError,
|
68
|
-
Invalid syntax for include tag. File contains invalid characters or sequences:
|
58
|
+
raise ArgumentError, <<~MSG
|
59
|
+
Invalid syntax for include tag. File contains invalid characters or sequences:
|
69
60
|
|
70
|
-
|
61
|
+
#{file}
|
71
62
|
|
72
|
-
Valid syntax:
|
63
|
+
Valid syntax:
|
73
64
|
|
74
|
-
|
65
|
+
#{syntax_example}
|
75
66
|
|
76
|
-
MSG
|
67
|
+
MSG
|
77
68
|
end
|
78
69
|
end
|
79
70
|
|
80
71
|
def validate_params
|
81
72
|
unless @params =~ FULL_VALID_SYNTAX
|
82
|
-
raise ArgumentError,
|
83
|
-
Invalid syntax for include tag:
|
73
|
+
raise ArgumentError, <<~MSG
|
74
|
+
Invalid syntax for include tag:
|
84
75
|
|
85
|
-
|
76
|
+
#{@params}
|
86
77
|
|
87
|
-
Valid syntax:
|
78
|
+
Valid syntax:
|
88
79
|
|
89
|
-
|
80
|
+
#{syntax_example}
|
90
81
|
|
91
|
-
MSG
|
82
|
+
MSG
|
92
83
|
end
|
93
84
|
end
|
94
85
|
|
@@ -99,13 +90,7 @@ MSG
|
|
99
90
|
|
100
91
|
# Render the variable if required
|
101
92
|
def render_variable(context)
|
102
|
-
if @file =~ VARIABLE_SYNTAX
|
103
|
-
partial = context.registers[:site]
|
104
|
-
.liquid_renderer
|
105
|
-
.file("(variable)")
|
106
|
-
.parse(@file)
|
107
|
-
partial.render!(context)
|
108
|
-
end
|
93
|
+
Liquid::Template.parse(@file).render(context) if @file =~ VARIABLE_SYNTAX
|
109
94
|
end
|
110
95
|
|
111
96
|
def tag_includes_dirs(context)
|
@@ -147,7 +132,7 @@ MSG
|
|
147
132
|
end
|
148
133
|
|
149
134
|
def add_include_to_dependency(site, path, context)
|
150
|
-
if context.registers[:page]
|
135
|
+
if context.registers[:page]&.key?("path")
|
151
136
|
site.regenerator.add_dependency(
|
152
137
|
site.in_source_dir(context.registers[:page]["path"]),
|
153
138
|
path
|
@@ -191,7 +176,7 @@ MSG
|
|
191
176
|
|
192
177
|
# This method allows to modify the file content by inheriting from the class.
|
193
178
|
def read_file(file, context)
|
194
|
-
File.read(file,
|
179
|
+
File.read(file, file_read_opts(context))
|
195
180
|
end
|
196
181
|
|
197
182
|
private
|
@@ -224,7 +209,6 @@ MSG
|
|
224
209
|
else
|
225
210
|
File.join(site.config["collections_dir"], page_payload["path"])
|
226
211
|
end
|
227
|
-
resource_path.sub!(%r!/#excerpt\z!, "")
|
228
212
|
site.in_source_dir File.dirname(resource_path)
|
229
213
|
end
|
230
214
|
end
|
data/lib/jekyll/tags/link.rb
CHANGED
@@ -3,9 +3,11 @@
|
|
3
3
|
module Jekyll
|
4
4
|
module Tags
|
5
5
|
class Link < Liquid::Tag
|
6
|
+
include Jekyll::Filters::URLFilters
|
7
|
+
|
6
8
|
class << self
|
7
9
|
def tag_name
|
8
|
-
|
10
|
+
name.split("::").last.downcase
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
@@ -16,19 +18,21 @@ module Jekyll
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def render(context)
|
21
|
+
@context = context
|
19
22
|
site = context.registers[:site]
|
23
|
+
relative_path = Liquid::Template.parse(@relative_path).render(context)
|
20
24
|
|
21
25
|
site.each_site_file do |item|
|
22
|
-
return item
|
26
|
+
return relative_url(item) if item.relative_path == relative_path
|
23
27
|
# This takes care of the case for static files that have a leading /
|
24
|
-
return item
|
28
|
+
return relative_url(item) if item.relative_path == "/#{relative_path}"
|
25
29
|
end
|
26
30
|
|
27
|
-
raise ArgumentError,
|
28
|
-
Could not find document '#{
|
31
|
+
raise ArgumentError, <<~MSG
|
32
|
+
Could not find document '#{relative_path}' in tag '#{self.class.tag_name}'.
|
29
33
|
|
30
|
-
Make sure the document exists and the path is correct.
|
31
|
-
MSG
|
34
|
+
Make sure the document exists and the path is correct.
|
35
|
+
MSG
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
data/lib/jekyll/tags/post_url.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Jekyll
|
4
4
|
module Tags
|
5
5
|
class PostComparer
|
6
|
-
MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)
|
6
|
+
MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!.freeze
|
7
7
|
|
8
8
|
attr_reader :path, :date, :slug, :name
|
9
9
|
|
@@ -13,7 +13,7 @@ module Jekyll
|
|
13
13
|
all, @path, @date, @slug = *name.sub(%r!^/!, "").match(MATCHER)
|
14
14
|
unless all
|
15
15
|
raise Jekyll::Errors::InvalidPostNameError,
|
16
|
-
|
16
|
+
"'#{name}' does not contain valid date and/or title."
|
17
17
|
end
|
18
18
|
|
19
19
|
escaped_slug = Regexp.escape(slug)
|
@@ -22,8 +22,10 @@ module Jekyll
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def post_date
|
25
|
-
@post_date ||= Utils.parse_date(
|
26
|
-
|
25
|
+
@post_date ||= Utils.parse_date(
|
26
|
+
date,
|
27
|
+
"'#{date}' does not contain valid date and/or title."
|
28
|
+
)
|
27
29
|
end
|
28
30
|
|
29
31
|
def ==(other)
|
@@ -38,6 +40,7 @@ module Jekyll
|
|
38
40
|
end
|
39
41
|
|
40
42
|
private
|
43
|
+
|
41
44
|
# Construct the directory-aware post slug for a Jekyll::Post
|
42
45
|
#
|
43
46
|
# other - the Jekyll::Post
|
@@ -60,13 +63,11 @@ module Jekyll
|
|
60
63
|
begin
|
61
64
|
@post = PostComparer.new(@orig_post)
|
62
65
|
rescue StandardError => e
|
63
|
-
raise Jekyll::Errors::PostURLError,
|
64
|
-
Could not parse name of post "#{@orig_post}" in tag 'post_url'.
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#{e.class}: #{e.message}
|
69
|
-
MSG
|
66
|
+
raise Jekyll::Errors::PostURLError, <<~MSG
|
67
|
+
Could not parse name of post "#{@orig_post}" in tag 'post_url'.
|
68
|
+
Make sure the post exists and the name is correct.
|
69
|
+
#{e.class}: #{e.message}
|
70
|
+
MSG
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
@@ -82,6 +83,7 @@ MSG
|
|
82
83
|
|
83
84
|
site.posts.docs.each do |p|
|
84
85
|
next unless @post.deprecated_equality p
|
86
|
+
|
85
87
|
Jekyll::Deprecator.deprecation_message "A call to "\
|
86
88
|
"'{% post_url #{@post.name} %}' did not match " \
|
87
89
|
"a post using the new matching method of checking name " \
|
@@ -90,11 +92,10 @@ MSG
|
|
90
92
|
return p.url
|
91
93
|
end
|
92
94
|
|
93
|
-
raise Jekyll::Errors::PostURLError,
|
94
|
-
Could not find post "#{@orig_post}" in tag 'post_url'.
|
95
|
-
|
96
|
-
|
97
|
-
MSG
|
95
|
+
raise Jekyll::Errors::PostURLError, <<~MSG
|
96
|
+
Could not find post "#{@orig_post}" in tag 'post_url'.
|
97
|
+
Make sure the post exists and the name is correct.
|
98
|
+
MSG
|
98
99
|
end
|
99
100
|
end
|
100
101
|
end
|
data/lib/jekyll/theme.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Jekyll
|
4
4
|
class Theme
|
5
5
|
extend Forwardable
|
6
|
-
attr_reader
|
6
|
+
attr_reader :name
|
7
7
|
def_delegator :gemspec, :version, :version
|
8
8
|
|
9
9
|
def initialize(name)
|
@@ -23,23 +23,24 @@ module Jekyll
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def includes_path
|
26
|
-
@includes_path ||= path_for "_includes"
|
26
|
+
@includes_path ||= path_for "_includes"
|
27
27
|
end
|
28
28
|
|
29
29
|
def layouts_path
|
30
|
-
@layouts_path ||= path_for "_layouts"
|
30
|
+
@layouts_path ||= path_for "_layouts"
|
31
31
|
end
|
32
32
|
|
33
33
|
def sass_path
|
34
|
-
@sass_path ||= path_for "_sass"
|
34
|
+
@sass_path ||= path_for "_sass"
|
35
35
|
end
|
36
36
|
|
37
37
|
def assets_path
|
38
|
-
@assets_path ||= path_for "assets"
|
38
|
+
@assets_path ||= path_for "assets"
|
39
39
|
end
|
40
40
|
|
41
41
|
def configure_sass
|
42
42
|
return unless sass_path
|
43
|
+
|
43
44
|
External.require_with_graceful_fail("sass") unless defined?(Sass)
|
44
45
|
Sass.load_paths << sass_path
|
45
46
|
end
|
@@ -56,33 +57,21 @@ module Jekyll
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def realpath_for(folder)
|
59
|
-
# This resolves all symlinks for the theme subfolder and then ensures
|
60
|
-
#
|
61
|
-
#
|
60
|
+
# This resolves all symlinks for the theme subfolder and then ensures that the directory
|
61
|
+
# remains inside the theme root. This prevents the use of symlinks for theme subfolders to
|
62
|
+
# escape the theme root.
|
62
63
|
# However, symlinks are allowed to point to other directories within the theme.
|
63
64
|
Jekyll.sanitized_path(root, File.realpath(Jekyll.sanitized_path(root, folder.to_s)))
|
64
|
-
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
|
65
|
-
|
65
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
|
66
|
+
Jekyll.logger.warn "Invalid theme folder:", folder
|
66
67
|
nil
|
67
68
|
end
|
68
69
|
|
69
|
-
def log_realpath_exception(err, folder)
|
70
|
-
return if err.is_a?(Errno::ENOENT)
|
71
|
-
|
72
|
-
case err
|
73
|
-
when Errno::EACCES
|
74
|
-
Jekyll.logger.error "Theme error:", "Directory '#{folder}' is not accessible."
|
75
|
-
when Errno::ELOOP
|
76
|
-
Jekyll.logger.error "Theme error:",
|
77
|
-
"Directory '#{folder}' includes a symbolic link loop."
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
70
|
def gemspec
|
82
71
|
@gemspec ||= Gem::Specification.find_by_name(name)
|
83
72
|
rescue Gem::LoadError
|
84
73
|
raise Jekyll::Errors::MissingDependencyException,
|
85
|
-
|
74
|
+
"The #{name} theme could not be found."
|
86
75
|
end
|
87
76
|
end
|
88
77
|
end
|