jekyll 3.9.3 → 4.4.1
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 +511 -89
- data/LICENSE +1 -1
- data/README.markdown +48 -27
- data/lib/blank_template/_config.yml +3 -0
- data/lib/blank_template/_layouts/default.html +12 -0
- data/lib/blank_template/_sass/base.scss +9 -0
- data/lib/blank_template/assets/css/main.scss +4 -0
- data/lib/blank_template/index.md +8 -0
- data/lib/jekyll/cache.rb +186 -0
- data/lib/jekyll/cleaner.rb +8 -7
- data/lib/jekyll/collection.rb +84 -11
- data/lib/jekyll/command.rb +33 -6
- data/lib/jekyll/commands/build.rb +8 -28
- data/lib/jekyll/commands/clean.rb +3 -2
- data/lib/jekyll/commands/doctor.rb +46 -35
- data/lib/jekyll/commands/help.rb +1 -1
- data/lib/jekyll/commands/new.rb +44 -50
- data/lib/jekyll/commands/new_theme.rb +27 -28
- data/lib/jekyll/commands/serve/live_reload_reactor.rb +9 -16
- data/lib/jekyll/commands/serve/servlet.rb +21 -22
- data/lib/jekyll/commands/serve/websockets.rb +1 -1
- data/lib/jekyll/commands/serve.rb +75 -97
- data/lib/jekyll/configuration.rb +66 -158
- data/lib/jekyll/converters/identity.rb +18 -0
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +83 -33
- data/lib/jekyll/converters/markdown.rb +49 -40
- data/lib/jekyll/converters/smartypants.rb +34 -14
- data/lib/jekyll/convertible.rb +36 -34
- data/lib/jekyll/deprecator.rb +2 -4
- data/lib/jekyll/document.rb +107 -72
- data/lib/jekyll/drops/collection_drop.rb +3 -4
- data/lib/jekyll/drops/document_drop.rb +9 -3
- data/lib/jekyll/drops/drop.rb +115 -33
- data/lib/jekyll/drops/excerpt_drop.rb +8 -0
- data/lib/jekyll/drops/site_drop.rb +9 -8
- data/lib/jekyll/drops/static_file_drop.rb +4 -4
- data/lib/jekyll/drops/theme_drop.rb +39 -0
- data/lib/jekyll/drops/unified_payload_drop.rb +7 -2
- data/lib/jekyll/drops/url_drop.rb +55 -3
- data/lib/jekyll/entry_filter.rb +42 -51
- data/lib/jekyll/excerpt.rb +48 -38
- data/lib/jekyll/external.rb +20 -19
- 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 +50 -15
- data/lib/jekyll/filters.rb +211 -50
- data/lib/jekyll/frontmatter_defaults.rb +45 -36
- data/lib/jekyll/hooks.rb +26 -26
- data/lib/jekyll/inclusion.rb +32 -0
- data/lib/jekyll/layout.rb +12 -19
- data/lib/jekyll/liquid_extensions.rb +0 -2
- data/lib/jekyll/liquid_renderer/file.rb +24 -3
- data/lib/jekyll/liquid_renderer/table.rb +26 -77
- data/lib/jekyll/liquid_renderer.rb +31 -16
- data/lib/jekyll/log_adapter.rb +5 -1
- data/lib/jekyll/page.rb +51 -23
- data/lib/jekyll/page_excerpt.rb +25 -0
- data/lib/jekyll/page_without_a_file.rb +0 -4
- data/lib/jekyll/path_manager.rb +74 -0
- data/lib/jekyll/plugin.rb +5 -11
- data/lib/jekyll/plugin_manager.rb +15 -5
- data/lib/jekyll/profiler.rb +51 -0
- data/lib/jekyll/reader.rb +65 -10
- data/lib/jekyll/readers/collection_reader.rb +1 -0
- data/lib/jekyll/readers/data_reader.rb +48 -10
- data/lib/jekyll/readers/layout_reader.rb +3 -12
- data/lib/jekyll/readers/page_reader.rb +5 -5
- data/lib/jekyll/readers/post_reader.rb +32 -19
- data/lib/jekyll/readers/static_file_reader.rb +4 -4
- data/lib/jekyll/readers/theme_assets_reader.rb +8 -5
- data/lib/jekyll/regenerator.rb +4 -12
- data/lib/jekyll/related_posts.rb +1 -1
- data/lib/jekyll/renderer.rb +34 -49
- data/lib/jekyll/site.rb +151 -58
- data/lib/jekyll/static_file.rb +64 -28
- data/lib/jekyll/stevenson.rb +4 -8
- data/lib/jekyll/tags/highlight.rb +44 -57
- data/lib/jekyll/tags/include.rb +114 -80
- data/lib/jekyll/tags/link.rb +12 -7
- data/lib/jekyll/tags/post_url.rb +33 -30
- data/lib/jekyll/theme.rb +20 -18
- data/lib/jekyll/theme_builder.rb +91 -89
- data/lib/jekyll/url.rb +18 -10
- data/lib/jekyll/utils/ansi.rb +2 -2
- data/lib/jekyll/utils/exec.rb +0 -1
- data/lib/jekyll/utils/internet.rb +2 -4
- data/lib/jekyll/utils/platforms.rb +37 -52
- data/lib/jekyll/utils/thread_event.rb +1 -5
- data/lib/jekyll/utils.rb +29 -28
- data/lib/jekyll/version.rb +1 -1
- data/lib/jekyll.rb +9 -14
- data/lib/site_template/.gitignore +2 -0
- data/lib/site_template/404.html +2 -1
- 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/theme_template/README.md.erb +1 -3
- data/lib/theme_template/gitignore.erb +1 -0
- data/lib/theme_template/theme.gemspec.erb +1 -4
- data/rubocop/jekyll/assert_equal_literal_actual.rb +150 -0
- data/rubocop/jekyll/no_p_allowed.rb +5 -6
- data/rubocop/jekyll/no_puts_allowed.rb +5 -6
- metadata +149 -37
- 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/site_template/{about.md → about.markdown} +0 -0
- /data/lib/site_template/{index.md → index.markdown} +0 -0
|
@@ -7,13 +7,13 @@ module Jekyll
|
|
|
7
7
|
|
|
8
8
|
mutable false
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
delegate_method_as :site_data, :data
|
|
11
|
+
delegate_methods :time, :pages, :static_files, :tags, :categories
|
|
12
12
|
|
|
13
|
-
private
|
|
13
|
+
private delegate_method_as :config, :fallback_data
|
|
14
14
|
|
|
15
15
|
def [](key)
|
|
16
|
-
if @obj.collections.key?(key)
|
|
16
|
+
if key != "posts" && @obj.collections.key?(key)
|
|
17
17
|
@obj.collections[key].docs
|
|
18
18
|
else
|
|
19
19
|
super(key)
|
|
@@ -21,7 +21,7 @@ module Jekyll
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def key?(key)
|
|
24
|
-
(@obj.collections.key?(key)
|
|
24
|
+
(key != "posts" && @obj.collections.key?(key)) || super
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def posts
|
|
@@ -41,9 +41,9 @@ module Jekyll
|
|
|
41
41
|
# `Site#documents` cannot be memoized so that `Site#docs_to_write` can access the
|
|
42
42
|
# latest state of the attribute.
|
|
43
43
|
#
|
|
44
|
-
# Since this method will be called after `Site#pre_render` hook,
|
|
45
|
-
#
|
|
46
|
-
#
|
|
44
|
+
# Since this method will be called after `Site#pre_render` hook, the `Site#documents`
|
|
45
|
+
# array shouldn't thereafter change and can therefore be safely memoized to prevent
|
|
46
|
+
# additional computation of `Site#documents`.
|
|
47
47
|
def documents
|
|
48
48
|
@documents ||= @obj.documents
|
|
49
49
|
end
|
|
@@ -54,6 +54,7 @@ module Jekyll
|
|
|
54
54
|
# We should remove this in 4.0 and switch to `{{ post.related_posts }}`.
|
|
55
55
|
def related_posts
|
|
56
56
|
return nil unless @current_document.is_a?(Jekyll::Document)
|
|
57
|
+
|
|
57
58
|
@current_document.related_posts
|
|
58
59
|
end
|
|
59
60
|
attr_writer :current_document
|
|
@@ -4,11 +4,11 @@ module Jekyll
|
|
|
4
4
|
module Drops
|
|
5
5
|
class StaticFileDrop < Drop
|
|
6
6
|
extend Forwardable
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
delegate_methods :name, :extname, :modified_time, :basename
|
|
8
|
+
delegate_method_as :relative_path, :path
|
|
9
|
+
delegate_method_as :type, :collection
|
|
10
10
|
|
|
11
|
-
private
|
|
11
|
+
private delegate_method_as :data, :fallback_data
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module Drops
|
|
5
|
+
class ThemeDrop < Drop
|
|
6
|
+
delegate_method_as :runtime_dependencies, :dependencies
|
|
7
|
+
|
|
8
|
+
def root
|
|
9
|
+
@root ||= ENV["JEKYLL_ENV"] == "development" ? @obj.root : ""
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def authors
|
|
13
|
+
@authors ||= gemspec.authors.join(", ")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def version
|
|
17
|
+
@version ||= gemspec.version.to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def description
|
|
21
|
+
@description ||= gemspec.description || gemspec.summary
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def metadata
|
|
25
|
+
@metadata ||= gemspec.metadata
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def gemspec
|
|
31
|
+
@gemspec ||= @obj.send(:gemspec)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def fallback_data
|
|
35
|
+
@fallback_data ||= {}
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -5,8 +5,8 @@ module Jekyll
|
|
|
5
5
|
class UnifiedPayloadDrop < Drop
|
|
6
6
|
mutable true
|
|
7
7
|
|
|
8
|
-
attr_accessor :
|
|
9
|
-
|
|
8
|
+
attr_accessor :content, :page, :layout, :paginator,
|
|
9
|
+
:highlighter_prefix, :highlighter_suffix
|
|
10
10
|
|
|
11
11
|
def jekyll
|
|
12
12
|
JekyllDrop.global
|
|
@@ -16,7 +16,12 @@ module Jekyll
|
|
|
16
16
|
@site_drop ||= SiteDrop.new(@obj)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def theme
|
|
20
|
+
@theme_drop ||= ThemeDrop.new(@obj.theme) if @obj.theme
|
|
21
|
+
end
|
|
22
|
+
|
|
19
23
|
private
|
|
24
|
+
|
|
20
25
|
def fallback_data
|
|
21
26
|
@fallback_data ||= {}
|
|
22
27
|
end
|
|
@@ -7,8 +7,8 @@ module Jekyll
|
|
|
7
7
|
|
|
8
8
|
mutable false
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
delegate_method :output_ext
|
|
11
|
+
delegate_method_as :cleaned_relative_path, :path
|
|
12
12
|
|
|
13
13
|
def collection
|
|
14
14
|
@obj.collection.label
|
|
@@ -35,53 +35,105 @@ module Jekyll
|
|
|
35
35
|
category_set.to_a.join("/")
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
# Similar to output from #categories, but each category will be downcased and
|
|
39
|
+
# all non-alphanumeric characters of the category replaced with a hyphen.
|
|
40
|
+
def slugified_categories
|
|
41
|
+
Array(@obj.data["categories"]).each_with_object(Set.new) do |category, set|
|
|
42
|
+
set << Utils.slugify(category.to_s)
|
|
43
|
+
end.to_a.join("/")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# CCYY
|
|
38
47
|
def year
|
|
39
48
|
@obj.date.strftime("%Y")
|
|
40
49
|
end
|
|
41
50
|
|
|
51
|
+
# MM: 01..12
|
|
42
52
|
def month
|
|
43
53
|
@obj.date.strftime("%m")
|
|
44
54
|
end
|
|
45
55
|
|
|
56
|
+
# DD: 01..31
|
|
46
57
|
def day
|
|
47
58
|
@obj.date.strftime("%d")
|
|
48
59
|
end
|
|
49
60
|
|
|
61
|
+
# hh: 00..23
|
|
50
62
|
def hour
|
|
51
63
|
@obj.date.strftime("%H")
|
|
52
64
|
end
|
|
53
65
|
|
|
66
|
+
# mm: 00..59
|
|
54
67
|
def minute
|
|
55
68
|
@obj.date.strftime("%M")
|
|
56
69
|
end
|
|
57
70
|
|
|
71
|
+
# ss: 00..59
|
|
58
72
|
def second
|
|
59
73
|
@obj.date.strftime("%S")
|
|
60
74
|
end
|
|
61
75
|
|
|
76
|
+
# D: 1..31
|
|
62
77
|
def i_day
|
|
63
78
|
@obj.date.strftime("%-d")
|
|
64
79
|
end
|
|
65
80
|
|
|
81
|
+
# M: 1..12
|
|
66
82
|
def i_month
|
|
67
83
|
@obj.date.strftime("%-m")
|
|
68
84
|
end
|
|
69
85
|
|
|
86
|
+
# MMM: Jan..Dec
|
|
70
87
|
def short_month
|
|
71
88
|
@obj.date.strftime("%b")
|
|
72
89
|
end
|
|
73
90
|
|
|
91
|
+
# MMMM: January..December
|
|
92
|
+
def long_month
|
|
93
|
+
@obj.date.strftime("%B")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# YY: 00..99
|
|
74
97
|
def short_year
|
|
75
98
|
@obj.date.strftime("%y")
|
|
76
99
|
end
|
|
77
100
|
|
|
101
|
+
# CCYYw, ISO week year
|
|
102
|
+
# may differ from CCYY for the first days of January and last days of December
|
|
103
|
+
def w_year
|
|
104
|
+
@obj.date.strftime("%G")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# WW: 01..53
|
|
108
|
+
# %W and %U do not comply with ISO 8601-1
|
|
109
|
+
def week
|
|
110
|
+
@obj.date.strftime("%V")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# d: 1..7 (Monday..Sunday)
|
|
114
|
+
def w_day
|
|
115
|
+
@obj.date.strftime("%u")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# dd: Mon..Sun
|
|
119
|
+
def short_day
|
|
120
|
+
@obj.date.strftime("%a")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# ddd: Monday..Sunday
|
|
124
|
+
def long_day
|
|
125
|
+
@obj.date.strftime("%A")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# DDD: 001..366
|
|
78
129
|
def y_day
|
|
79
130
|
@obj.date.strftime("%j")
|
|
80
131
|
end
|
|
81
132
|
|
|
82
133
|
private
|
|
134
|
+
|
|
83
135
|
def fallback_data
|
|
84
|
-
{}
|
|
136
|
+
@fallback_data ||= {}
|
|
85
137
|
end
|
|
86
138
|
end
|
|
87
139
|
end
|
data/lib/jekyll/entry_filter.rb
CHANGED
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
module Jekyll
|
|
4
4
|
class EntryFilter
|
|
5
5
|
attr_reader :site
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
].freeze
|
|
6
|
+
|
|
7
|
+
SPECIAL_LEADING_CHAR_REGEX = %r!\A#{Regexp.union([".", "_", "#", "~"])}!o.freeze
|
|
9
8
|
|
|
10
9
|
def initialize(site, base_directory = nil)
|
|
11
10
|
@site = site
|
|
@@ -31,12 +30,24 @@ module Jekyll
|
|
|
31
30
|
|
|
32
31
|
def filter(entries)
|
|
33
32
|
entries.reject do |e|
|
|
34
|
-
# Reject this entry if it is a
|
|
33
|
+
# Reject this entry if it is just a "dot" representation.
|
|
34
|
+
# e.g.: '.', '..', '_movies/.', 'music/..', etc
|
|
35
|
+
next true if e.end_with?(".")
|
|
36
|
+
|
|
37
|
+
# Check if the current entry is explicitly included and cache the result
|
|
38
|
+
included = included?(e)
|
|
39
|
+
|
|
40
|
+
# Reject current entry if it is excluded but not explicitly included as well.
|
|
41
|
+
next true if excluded?(e) && !included
|
|
42
|
+
|
|
43
|
+
# Reject current entry if it is a symlink.
|
|
35
44
|
next true if symlink?(e)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
|
|
46
|
+
# Do not reject current entry if it is explicitly included.
|
|
47
|
+
next false if included
|
|
48
|
+
|
|
49
|
+
# Reject current entry if it is special or a backup file.
|
|
50
|
+
special?(e) || backup?(e)
|
|
40
51
|
end
|
|
41
52
|
end
|
|
42
53
|
|
|
@@ -46,16 +57,16 @@ module Jekyll
|
|
|
46
57
|
end
|
|
47
58
|
|
|
48
59
|
def special?(entry)
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
SPECIAL_LEADING_CHAR_REGEX.match?(entry) ||
|
|
61
|
+
SPECIAL_LEADING_CHAR_REGEX.match?(File.basename(entry))
|
|
51
62
|
end
|
|
52
63
|
|
|
53
64
|
def backup?(entry)
|
|
54
|
-
entry
|
|
65
|
+
entry.end_with?("~")
|
|
55
66
|
end
|
|
56
67
|
|
|
57
68
|
def excluded?(entry)
|
|
58
|
-
glob_include?(site.exclude, relative_to_source(entry)).tap do |excluded|
|
|
69
|
+
glob_include?(site.exclude - site.include, relative_to_source(entry)).tap do |excluded|
|
|
59
70
|
if excluded
|
|
60
71
|
Jekyll.logger.debug(
|
|
61
72
|
"EntryFilter:",
|
|
@@ -75,50 +86,30 @@ module Jekyll
|
|
|
75
86
|
end
|
|
76
87
|
|
|
77
88
|
# --
|
|
78
|
-
#
|
|
79
|
-
# @param [<Anything>] entry the entry you want to validate.
|
|
80
|
-
# Check if a path is outside of our given root.
|
|
89
|
+
# Check if given path is outside of current site's configured source directory.
|
|
81
90
|
# --
|
|
82
91
|
def symlink_outside_site_source?(entry)
|
|
83
|
-
!
|
|
84
|
-
site.in_source_dir
|
|
85
|
-
)
|
|
92
|
+
!File.realpath(entry).start_with?(site.in_source_dir)
|
|
86
93
|
end
|
|
87
94
|
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
95
|
+
# Check if an entry matches a specific pattern.
|
|
96
|
+
# Returns true if path matches against any glob pattern, else false.
|
|
97
|
+
def glob_include?(enumerator, entry)
|
|
98
|
+
entry_with_source = PathManager.join(site.source, entry)
|
|
99
|
+
entry_is_directory = File.directory?(entry_with_source)
|
|
100
|
+
|
|
101
|
+
enumerator.any? do |pattern|
|
|
102
|
+
case pattern
|
|
103
|
+
when String
|
|
104
|
+
pattern_with_source = PathManager.join(site.source, pattern)
|
|
105
|
+
|
|
106
|
+
File.fnmatch?(pattern_with_source, entry_with_source) ||
|
|
107
|
+
entry_with_source.start_with?(pattern_with_source) ||
|
|
108
|
+
(pattern_with_source == "#{entry_with_source}/" if entry_is_directory)
|
|
109
|
+
when Regexp
|
|
110
|
+
pattern.match?(entry_with_source)
|
|
103
111
|
else
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
# If it's a directory they want to exclude, AKA
|
|
107
|
-
# ends with a "/" then we will go on to check and
|
|
108
|
-
# see if the entry falls within that path and
|
|
109
|
-
# exclude it if that's the case.
|
|
110
|
-
|
|
111
|
-
if entry.end_with?("/")
|
|
112
|
-
entry_path.in_path?(
|
|
113
|
-
item
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
else
|
|
117
|
-
File.fnmatch?(item, entry_path) ||
|
|
118
|
-
entry_path.to_path.start_with?(
|
|
119
|
-
item
|
|
120
|
-
)
|
|
121
|
-
end
|
|
112
|
+
false
|
|
122
113
|
end
|
|
123
114
|
end
|
|
124
115
|
end
|
data/lib/jekyll/excerpt.rb
CHANGED
|
@@ -4,14 +4,14 @@ module Jekyll
|
|
|
4
4
|
class Excerpt
|
|
5
5
|
extend Forwardable
|
|
6
6
|
|
|
7
|
-
attr_accessor :doc
|
|
8
|
-
attr_accessor :content, :ext
|
|
7
|
+
attr_accessor :content, :doc, :ext
|
|
9
8
|
attr_writer :output
|
|
10
9
|
|
|
11
|
-
def_delegators :@doc,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
def_delegators :@doc,
|
|
11
|
+
:site, :name, :ext, :extname,
|
|
12
|
+
:collection, :related_posts, :type,
|
|
13
|
+
:coffeescript_file?, :yaml_file?,
|
|
14
|
+
:url, :next_doc, :previous_doc
|
|
15
15
|
|
|
16
16
|
private :coffeescript_file?, :yaml_file?
|
|
17
17
|
|
|
@@ -48,14 +48,14 @@ module Jekyll
|
|
|
48
48
|
#
|
|
49
49
|
# Returns the relative_path for the doc this excerpt belongs to with #excerpt appended
|
|
50
50
|
def relative_path
|
|
51
|
-
File.join(doc.relative_path, "#excerpt")
|
|
51
|
+
@relative_path ||= File.join(doc.relative_path, "#excerpt")
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
# Check if excerpt includes a string
|
|
55
55
|
#
|
|
56
56
|
# Returns true if the string passed in
|
|
57
57
|
def include?(something)
|
|
58
|
-
|
|
58
|
+
output&.include?(something) || content.include?(something)
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
# The UID for this doc (useful in feeds).
|
|
@@ -76,7 +76,7 @@ module Jekyll
|
|
|
76
76
|
|
|
77
77
|
# Returns the shorthand String identifier of this doc.
|
|
78
78
|
def inspect
|
|
79
|
-
"
|
|
79
|
+
"<#{self.class} id=#{id}>"
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
def output
|
|
@@ -88,6 +88,8 @@ module Jekyll
|
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
def render_with_liquid?
|
|
91
|
+
return false if data["render_with_liquid"] == false
|
|
92
|
+
|
|
91
93
|
!(coffeescript_file? || yaml_file? || !Utils.has_liquid_construct?(content))
|
|
92
94
|
end
|
|
93
95
|
|
|
@@ -128,36 +130,47 @@ module Jekyll
|
|
|
128
130
|
#
|
|
129
131
|
# Returns excerpt String
|
|
130
132
|
|
|
131
|
-
LIQUID_TAG_REGEX = %r!{%-?\s*(\w+)\s*.*?-?%}!m
|
|
132
|
-
MKDWN_LINK_REF_REGEX = %r!^ {0,3}\[[^\]]+\]
|
|
133
|
+
LIQUID_TAG_REGEX = %r!{%-?\s*(\w+)\s*.*?-?%}!m.freeze
|
|
134
|
+
MKDWN_LINK_REF_REGEX = %r!^ {0,3}(?:(\[[^\]]+\])(:.+))$!.freeze
|
|
133
135
|
|
|
134
136
|
def extract_excerpt(doc_content)
|
|
135
137
|
head, _, tail = doc_content.to_s.partition(doc.excerpt_separator)
|
|
138
|
+
return head if tail.empty?
|
|
136
139
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
head = sanctify_liquid_tags(head) if head.include?("{%")
|
|
141
|
+
definitions = extract_markdown_link_reference_definitions(head, tail)
|
|
142
|
+
return head if definitions.empty?
|
|
140
143
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
tag_names = head.scan(LIQUID_TAG_REGEX)
|
|
144
|
-
tag_names.flatten!
|
|
145
|
-
tag_names.reverse_each do |tag_name|
|
|
146
|
-
next unless liquid_block?(tag_name)
|
|
147
|
-
next if head =~ endtag_regex_stash(tag_name)
|
|
144
|
+
head << "\n\n" << definitions.join("\n")
|
|
145
|
+
end
|
|
148
146
|
|
|
149
|
-
|
|
150
|
-
head << "\n{% end#{tag_name} %}"
|
|
151
|
-
end
|
|
152
|
-
print_build_warning if modified
|
|
153
|
-
end
|
|
147
|
+
private
|
|
154
148
|
|
|
155
|
-
|
|
149
|
+
# append appropriate closing tag(s) (for each Liquid block), to the `head` if the
|
|
150
|
+
# partitioning resulted in leaving the closing tag somewhere in the `tail` partition.
|
|
151
|
+
def sanctify_liquid_tags(head)
|
|
152
|
+
modified = false
|
|
153
|
+
tag_names = head.scan(LIQUID_TAG_REGEX)
|
|
154
|
+
tag_names.flatten!
|
|
155
|
+
tag_names.reverse_each do |tag_name|
|
|
156
|
+
next unless liquid_block?(tag_name)
|
|
157
|
+
next if endtag_regex_stash(tag_name).match?(head)
|
|
158
|
+
|
|
159
|
+
modified = true
|
|
160
|
+
head << "\n{% end#{tag_name} %}"
|
|
161
|
+
end
|
|
156
162
|
|
|
157
|
-
|
|
163
|
+
print_build_warning if modified
|
|
164
|
+
head
|
|
158
165
|
end
|
|
159
166
|
|
|
160
|
-
|
|
167
|
+
def extract_markdown_link_reference_definitions(head, tail)
|
|
168
|
+
[].tap do |definitions|
|
|
169
|
+
tail.scan(MKDWN_LINK_REF_REGEX).each do |segments|
|
|
170
|
+
definitions << segments.join if head.include?(segments[0])
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
161
174
|
|
|
162
175
|
def endtag_regex_stash(tag_name)
|
|
163
176
|
@endtag_regex_stash ||= {}
|
|
@@ -171,20 +184,17 @@ module Jekyll
|
|
|
171
184
|
Liquid::Template.tags[tag_name].ancestors.include?(Liquid::Block)
|
|
172
185
|
rescue NoMethodError
|
|
173
186
|
Jekyll.logger.error "Error:",
|
|
174
|
-
|
|
175
|
-
"parsed."
|
|
187
|
+
"A Liquid tag in the excerpt of #{doc.relative_path} couldn't be parsed."
|
|
176
188
|
raise
|
|
177
189
|
end
|
|
178
190
|
|
|
179
191
|
def print_build_warning
|
|
180
192
|
Jekyll.logger.warn "Warning:", "Excerpt modified in #{doc.relative_path}!"
|
|
181
|
-
Jekyll.logger.warn "", "Found a Liquid block containing the excerpt separator" \
|
|
182
|
-
|
|
183
|
-
Jekyll.logger.warn "", "The block has been modified with the appropriate"
|
|
184
|
-
|
|
185
|
-
Jekyll.logger.warn "", "
|
|
186
|
-
" excerpt_separator in the document's front matter" \
|
|
187
|
-
" if the generated excerpt is unsatisfactory."
|
|
193
|
+
Jekyll.logger.warn "", "Found a Liquid block containing the excerpt separator " \
|
|
194
|
+
"#{doc.excerpt_separator.inspect}."
|
|
195
|
+
Jekyll.logger.warn "", "The block has been modified with the appropriate closing tag."
|
|
196
|
+
Jekyll.logger.warn "", "Feel free to define a custom excerpt or excerpt_separator in the"
|
|
197
|
+
Jekyll.logger.warn "", "document's Front Matter if the generated excerpt is unsatisfactory."
|
|
188
198
|
end
|
|
189
199
|
end
|
|
190
200
|
end
|
data/lib/jekyll/external.rb
CHANGED
|
@@ -9,6 +9,7 @@ module Jekyll
|
|
|
9
9
|
#
|
|
10
10
|
def blessed_gems
|
|
11
11
|
%w(
|
|
12
|
+
jekyll-compose
|
|
12
13
|
jekyll-docs
|
|
13
14
|
jekyll-import
|
|
14
15
|
)
|
|
@@ -21,13 +22,11 @@ module Jekyll
|
|
|
21
22
|
#
|
|
22
23
|
def require_if_present(names)
|
|
23
24
|
Array(names).each do |name|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
false
|
|
30
|
-
end
|
|
25
|
+
require name
|
|
26
|
+
rescue LoadError
|
|
27
|
+
Jekyll.logger.debug "Couldn't load #{name}. Skipping."
|
|
28
|
+
yield(name, version_constraint(name)) if block_given?
|
|
29
|
+
false
|
|
31
30
|
end
|
|
32
31
|
end
|
|
33
32
|
|
|
@@ -41,6 +40,7 @@ module Jekyll
|
|
|
41
40
|
# RubyGems.
|
|
42
41
|
def version_constraint(gem_name)
|
|
43
42
|
return "= #{Jekyll::VERSION}" if gem_name.to_s.eql?("jekyll-docs")
|
|
43
|
+
|
|
44
44
|
"> 0"
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -53,20 +53,21 @@ module Jekyll
|
|
|
53
53
|
#
|
|
54
54
|
def require_with_graceful_fail(names)
|
|
55
55
|
Array(names).each do |name|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
Jekyll.logger.debug "Requiring:", name.to_s
|
|
57
|
+
require name
|
|
58
|
+
rescue LoadError => e
|
|
59
|
+
Jekyll.logger.error "Dependency Error:", <<~MSG
|
|
60
|
+
Yikes! It looks like you don't have #{name} or one of its dependencies installed.
|
|
61
|
+
In order to use Jekyll as currently configured, you'll need to install this gem.
|
|
62
|
+
|
|
63
|
+
If you've run Jekyll with `bundle exec`, ensure that you have included the #{name}
|
|
64
|
+
gem in your Gemfile as well.
|
|
63
65
|
|
|
64
|
-
The full error message from Ruby is: '#{e.message}'
|
|
66
|
+
The full error message from Ruby is: '#{e.message}'
|
|
65
67
|
|
|
66
|
-
If you run into trouble, you can find helpful resources at https://jekyllrb.com/help/!
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
end
|
|
68
|
+
If you run into trouble, you can find helpful resources at https://jekyllrb.com/help/!
|
|
69
|
+
MSG
|
|
70
|
+
raise Jekyll::Errors::MissingDependencyException, name
|
|
70
71
|
end
|
|
71
72
|
end
|
|
72
73
|
end
|
|
@@ -45,6 +45,7 @@ module Jekyll
|
|
|
45
45
|
# Returns the formatted String.
|
|
46
46
|
def date_to_xmlschema(date)
|
|
47
47
|
return date if date.to_s.empty?
|
|
48
|
+
|
|
48
49
|
time(date).xmlschema
|
|
49
50
|
end
|
|
50
51
|
|
|
@@ -60,10 +61,12 @@ module Jekyll
|
|
|
60
61
|
# Returns the formatted String.
|
|
61
62
|
def date_to_rfc822(date)
|
|
62
63
|
return date if date.to_s.empty?
|
|
64
|
+
|
|
63
65
|
time(date).rfc822
|
|
64
66
|
end
|
|
65
67
|
|
|
66
68
|
private
|
|
69
|
+
|
|
67
70
|
# month_type: Notations that evaluate to 'Month' via `Time#strftime` ("%b", "%B")
|
|
68
71
|
# type: nil (default) or "ordinal"
|
|
69
72
|
# style: nil (default) or "US"
|
|
@@ -71,17 +74,18 @@ module Jekyll
|
|
|
71
74
|
# Returns a stringified date or the empty input.
|
|
72
75
|
def stringify_date(date, month_type, type = nil, style = nil)
|
|
73
76
|
return date if date.to_s.empty?
|
|
77
|
+
|
|
74
78
|
time = time(date)
|
|
75
79
|
if type == "ordinal"
|
|
76
80
|
day = time.day
|
|
77
81
|
ordinal_day = "#{day}#{ordinal(day)}"
|
|
78
82
|
return time.strftime("#{month_type} #{ordinal_day}, %Y") if style == "US"
|
|
83
|
+
|
|
79
84
|
return time.strftime("#{ordinal_day} #{month_type} %Y")
|
|
80
85
|
end
|
|
81
86
|
time.strftime("%d #{month_type} %Y")
|
|
82
87
|
end
|
|
83
88
|
|
|
84
|
-
private
|
|
85
89
|
def ordinal(number)
|
|
86
90
|
return "th" if (11..13).cover?(number)
|
|
87
91
|
|
|
@@ -93,12 +97,11 @@ module Jekyll
|
|
|
93
97
|
end
|
|
94
98
|
end
|
|
95
99
|
|
|
96
|
-
private
|
|
97
100
|
def time(input)
|
|
98
101
|
date = Liquid::Utils.to_date(input)
|
|
99
102
|
unless date.respond_to?(:to_time)
|
|
100
103
|
raise Errors::InvalidDateError,
|
|
101
|
-
|
|
104
|
+
"Invalid Date: '#{input.inspect}' is not a valid datetime."
|
|
102
105
|
end
|
|
103
106
|
date.to_time.dup.localtime
|
|
104
107
|
end
|
|
@@ -41,16 +41,15 @@ module Jekyll
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
private
|
|
44
|
+
|
|
44
45
|
def parse_expression(str)
|
|
45
46
|
Liquid::Variable.new(str, Liquid::ParseContext.new)
|
|
46
47
|
end
|
|
47
48
|
|
|
48
|
-
private
|
|
49
49
|
def groupable?(element)
|
|
50
50
|
element.respond_to?(:group_by)
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
private
|
|
54
53
|
def grouped_array(groups)
|
|
55
54
|
groups.each_with_object([]) do |item, array|
|
|
56
55
|
array << {
|