jekyll 4.2.1 → 4.3.2

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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +474 -350
  3. data/LICENSE +21 -21
  4. data/README.markdown +83 -86
  5. data/exe/jekyll +57 -57
  6. data/lib/blank_template/_config.yml +3 -3
  7. data/lib/blank_template/_layouts/default.html +12 -12
  8. data/lib/blank_template/_sass/{main.scss → base.scss} +9 -9
  9. data/lib/blank_template/assets/css/main.scss +4 -4
  10. data/lib/blank_template/index.md +8 -8
  11. data/lib/jekyll/cache.rb +186 -190
  12. data/lib/jekyll/cleaner.rb +111 -111
  13. data/lib/jekyll/collection.rb +310 -309
  14. data/lib/jekyll/command.rb +105 -105
  15. data/lib/jekyll/commands/build.rb +82 -93
  16. data/lib/jekyll/commands/clean.rb +44 -45
  17. data/lib/jekyll/commands/doctor.rb +177 -177
  18. data/lib/jekyll/commands/help.rb +34 -34
  19. data/lib/jekyll/commands/new.rb +168 -169
  20. data/lib/jekyll/commands/new_theme.rb +39 -40
  21. data/lib/jekyll/commands/serve/live_reload_reactor.rb +119 -122
  22. data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
  23. data/lib/jekyll/commands/serve/mime_types_charset.json +71 -0
  24. data/lib/jekyll/commands/serve/servlet.rb +206 -202
  25. data/lib/jekyll/commands/serve/websockets.rb +81 -81
  26. data/lib/jekyll/commands/serve.rb +367 -362
  27. data/lib/jekyll/configuration.rb +313 -313
  28. data/lib/jekyll/converter.rb +54 -54
  29. data/lib/jekyll/converters/identity.rb +41 -41
  30. data/lib/jekyll/converters/markdown/kramdown_parser.rb +197 -199
  31. data/lib/jekyll/converters/markdown.rb +113 -113
  32. data/lib/jekyll/converters/smartypants.rb +70 -70
  33. data/lib/jekyll/convertible.rb +257 -257
  34. data/lib/jekyll/deprecator.rb +50 -50
  35. data/lib/jekyll/document.rb +543 -544
  36. data/lib/jekyll/drops/collection_drop.rb +20 -20
  37. data/lib/jekyll/drops/document_drop.rb +74 -70
  38. data/lib/jekyll/drops/drop.rb +293 -293
  39. data/lib/jekyll/drops/excerpt_drop.rb +23 -19
  40. data/lib/jekyll/drops/jekyll_drop.rb +32 -32
  41. data/lib/jekyll/drops/site_drop.rb +66 -66
  42. data/lib/jekyll/drops/static_file_drop.rb +14 -14
  43. data/lib/jekyll/drops/theme_drop.rb +36 -0
  44. data/lib/jekyll/drops/unified_payload_drop.rb +30 -26
  45. data/lib/jekyll/drops/url_drop.rb +140 -140
  46. data/lib/jekyll/entry_filter.rb +117 -121
  47. data/lib/jekyll/errors.rb +20 -20
  48. data/lib/jekyll/excerpt.rb +200 -201
  49. data/lib/jekyll/external.rb +75 -79
  50. data/lib/jekyll/filters/date_filters.rb +110 -110
  51. data/lib/jekyll/filters/grouping_filters.rb +64 -64
  52. data/lib/jekyll/filters/url_filters.rb +98 -98
  53. data/lib/jekyll/filters.rb +532 -535
  54. data/lib/jekyll/frontmatter_defaults.rb +238 -240
  55. data/lib/jekyll/generator.rb +5 -5
  56. data/lib/jekyll/hooks.rb +107 -107
  57. data/lib/jekyll/inclusion.rb +32 -32
  58. data/lib/jekyll/layout.rb +55 -67
  59. data/lib/jekyll/liquid_extensions.rb +22 -22
  60. data/lib/jekyll/liquid_renderer/file.rb +77 -77
  61. data/lib/jekyll/liquid_renderer/table.rb +45 -55
  62. data/lib/jekyll/liquid_renderer.rb +80 -80
  63. data/lib/jekyll/log_adapter.rb +151 -151
  64. data/lib/jekyll/mime.types +939 -866
  65. data/lib/jekyll/page.rb +215 -217
  66. data/lib/jekyll/page_excerpt.rb +25 -25
  67. data/lib/jekyll/page_without_a_file.rb +14 -14
  68. data/lib/jekyll/path_manager.rb +74 -74
  69. data/lib/jekyll/plugin.rb +92 -92
  70. data/lib/jekyll/plugin_manager.rb +123 -115
  71. data/lib/jekyll/profiler.rb +51 -58
  72. data/lib/jekyll/publisher.rb +23 -23
  73. data/lib/jekyll/reader.rb +209 -192
  74. data/lib/jekyll/readers/collection_reader.rb +23 -23
  75. data/lib/jekyll/readers/data_reader.rb +113 -79
  76. data/lib/jekyll/readers/layout_reader.rb +62 -62
  77. data/lib/jekyll/readers/page_reader.rb +25 -25
  78. data/lib/jekyll/readers/post_reader.rb +85 -85
  79. data/lib/jekyll/readers/static_file_reader.rb +25 -25
  80. data/lib/jekyll/readers/theme_assets_reader.rb +52 -52
  81. data/lib/jekyll/regenerator.rb +195 -195
  82. data/lib/jekyll/related_posts.rb +52 -52
  83. data/lib/jekyll/renderer.rb +263 -265
  84. data/lib/jekyll/site.rb +576 -551
  85. data/lib/jekyll/static_file.rb +205 -208
  86. data/lib/jekyll/stevenson.rb +60 -60
  87. data/lib/jekyll/tags/highlight.rb +114 -110
  88. data/lib/jekyll/tags/include.rb +275 -275
  89. data/lib/jekyll/tags/link.rb +42 -42
  90. data/lib/jekyll/tags/post_url.rb +106 -106
  91. data/lib/jekyll/theme.rb +90 -86
  92. data/lib/jekyll/theme_builder.rb +121 -121
  93. data/lib/jekyll/url.rb +167 -167
  94. data/lib/jekyll/utils/ansi.rb +57 -57
  95. data/lib/jekyll/utils/exec.rb +26 -26
  96. data/lib/jekyll/utils/internet.rb +37 -37
  97. data/lib/jekyll/utils/platforms.rb +67 -67
  98. data/lib/jekyll/utils/thread_event.rb +31 -31
  99. data/lib/jekyll/utils/win_tz.rb +46 -75
  100. data/lib/jekyll/utils.rb +371 -367
  101. data/lib/jekyll/version.rb +5 -5
  102. data/lib/jekyll.rb +195 -195
  103. data/lib/site_template/.gitignore +5 -5
  104. data/lib/site_template/404.html +25 -25
  105. data/lib/site_template/_config.yml +55 -55
  106. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
  107. data/lib/site_template/about.markdown +18 -18
  108. data/lib/site_template/index.markdown +6 -6
  109. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
  110. data/lib/theme_template/Gemfile +4 -4
  111. data/lib/theme_template/LICENSE.txt.erb +21 -21
  112. data/lib/theme_template/README.md.erb +50 -52
  113. data/lib/theme_template/_layouts/default.html +1 -1
  114. data/lib/theme_template/_layouts/page.html +5 -5
  115. data/lib/theme_template/_layouts/post.html +5 -5
  116. data/lib/theme_template/example/_config.yml.erb +1 -1
  117. data/lib/theme_template/example/_post.md +12 -12
  118. data/lib/theme_template/example/index.html +14 -14
  119. data/lib/theme_template/example/style.scss +7 -7
  120. data/lib/theme_template/gitignore.erb +6 -6
  121. data/lib/theme_template/theme.gemspec.erb +16 -16
  122. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
  123. data/rubocop/jekyll/no_p_allowed.rb +23 -23
  124. data/rubocop/jekyll/no_puts_allowed.rb +23 -23
  125. data/rubocop/jekyll.rb +5 -5
  126. metadata +64 -18
@@ -1,313 +1,313 @@
1
- # frozen_string_literal: true
2
-
3
- module Jekyll
4
- class Configuration < Hash
5
- # Default options. Overridden by values in _config.yml.
6
- # Strings rather than symbols are used for compatibility with YAML.
7
- DEFAULTS = {
8
- # Where things are
9
- "source" => Dir.pwd,
10
- "destination" => File.join(Dir.pwd, "_site"),
11
- "collections_dir" => "",
12
- "cache_dir" => ".jekyll-cache",
13
- "plugins_dir" => "_plugins",
14
- "layouts_dir" => "_layouts",
15
- "data_dir" => "_data",
16
- "includes_dir" => "_includes",
17
- "collections" => {},
18
-
19
- # Handling Reading
20
- "safe" => false,
21
- "include" => [".htaccess"],
22
- "exclude" => [],
23
- "keep_files" => [".git", ".svn"],
24
- "encoding" => "utf-8",
25
- "markdown_ext" => "markdown,mkdown,mkdn,mkd,md",
26
- "strict_front_matter" => false,
27
-
28
- # Filtering Content
29
- "show_drafts" => nil,
30
- "limit_posts" => 0,
31
- "future" => false,
32
- "unpublished" => false,
33
-
34
- # Plugins
35
- "whitelist" => [],
36
- "plugins" => [],
37
-
38
- # Conversion
39
- "markdown" => "kramdown",
40
- "highlighter" => "rouge",
41
- "lsi" => false,
42
- "excerpt_separator" => "\n\n",
43
- "incremental" => false,
44
-
45
- # Serving
46
- "detach" => false, # default to not detaching the server
47
- "port" => "4000",
48
- "host" => "127.0.0.1",
49
- "baseurl" => nil, # this mounts at /, i.e. no subdirectory
50
- "show_dir_listing" => false,
51
-
52
- # Output Configuration
53
- "permalink" => "date",
54
- "paginate_path" => "/page:num",
55
- "timezone" => nil, # use the local timezone
56
-
57
- "quiet" => false,
58
- "verbose" => false,
59
- "defaults" => [],
60
-
61
- "liquid" => {
62
- "error_mode" => "warn",
63
- "strict_filters" => false,
64
- "strict_variables" => false,
65
- },
66
-
67
- "kramdown" => {
68
- "auto_ids" => true,
69
- "toc_levels" => (1..6).to_a,
70
- "entity_output" => "as_char",
71
- "smart_quotes" => "lsquo,rsquo,ldquo,rdquo",
72
- "input" => "GFM",
73
- "hard_wrap" => false,
74
- "guess_lang" => true,
75
- "footnote_nr" => 1,
76
- "show_warnings" => false,
77
- },
78
- }.each_with_object(Configuration.new) { |(k, v), hsh| hsh[k] = v.freeze }.freeze
79
-
80
- class << self
81
- # Static: Produce a Configuration ready for use in a Site.
82
- # It takes the input, fills in the defaults where values do not exist.
83
- #
84
- # user_config - a Hash or Configuration of overrides.
85
- #
86
- # Returns a Configuration filled with defaults.
87
- def from(user_config)
88
- Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
89
- .add_default_collections.add_default_excludes
90
- end
91
- end
92
-
93
- # Public: Turn all keys into string
94
- #
95
- # Return a copy of the hash where all its keys are strings
96
- def stringify_keys
97
- each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v }
98
- end
99
-
100
- def get_config_value_with_override(config_key, override)
101
- override[config_key] || self[config_key] || DEFAULTS[config_key]
102
- end
103
-
104
- # Public: Directory of the Jekyll source folder
105
- #
106
- # override - the command-line options hash
107
- #
108
- # Returns the path to the Jekyll source directory
109
- def source(override)
110
- get_config_value_with_override("source", override)
111
- end
112
-
113
- def quiet(override = {})
114
- get_config_value_with_override("quiet", override)
115
- end
116
- alias_method :quiet?, :quiet
117
-
118
- def verbose(override = {})
119
- get_config_value_with_override("verbose", override)
120
- end
121
- alias_method :verbose?, :verbose
122
-
123
- def safe_load_file(filename)
124
- case File.extname(filename)
125
- when %r!\.toml!i
126
- Jekyll::External.require_with_graceful_fail("tomlrb") unless defined?(Tomlrb)
127
- Tomlrb.load_file(filename)
128
- when %r!\.ya?ml!i
129
- SafeYAML.load_file(filename) || {}
130
- else
131
- raise ArgumentError,
132
- "No parser for '#{filename}' is available. Use a .y(a)ml or .toml file instead."
133
- end
134
- end
135
-
136
- # Public: Generate list of configuration files from the override
137
- #
138
- # override - the command-line options hash
139
- #
140
- # Returns an Array of config files
141
- def config_files(override)
142
- # Adjust verbosity quickly
143
- Jekyll.logger.adjust_verbosity(
144
- :quiet => quiet?(override),
145
- :verbose => verbose?(override)
146
- )
147
-
148
- # Get configuration from <source>/_config.yml or <source>/<config_file>
149
- config_files = override["config"]
150
- if config_files.to_s.empty?
151
- default = %w(yml yaml toml).find(-> { "yml" }) do |ext|
152
- File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}"))
153
- end
154
- config_files = Jekyll.sanitized_path(source(override), "_config.#{default}")
155
- @default_config_file = true
156
- end
157
- Array(config_files)
158
- end
159
-
160
- # Public: Read configuration and return merged Hash
161
- #
162
- # file - the path to the YAML file to be read in
163
- #
164
- # Returns this configuration, overridden by the values in the file
165
- def read_config_file(file)
166
- file = File.expand_path(file)
167
- next_config = safe_load_file(file)
168
-
169
- unless next_config.is_a?(Hash)
170
- raise ArgumentError, "Configuration file: (INVALID) #{file}".yellow
171
- end
172
-
173
- Jekyll.logger.info "Configuration file:", file
174
- next_config
175
- rescue SystemCallError
176
- if @default_config_file ||= nil
177
- Jekyll.logger.warn "Configuration file:", "none"
178
- {}
179
- else
180
- Jekyll.logger.error "Fatal:", "The configuration file '#{file}' could not be found."
181
- raise LoadError, "The Configuration file '#{file}' could not be found."
182
- end
183
- end
184
-
185
- # Public: Read in a list of configuration files and merge with this hash
186
- #
187
- # files - the list of configuration file paths
188
- #
189
- # Returns the full configuration, with the defaults overridden by the values in the
190
- # configuration files
191
- def read_config_files(files)
192
- configuration = clone
193
-
194
- begin
195
- files.each do |config_file|
196
- next if config_file.nil? || config_file.empty?
197
-
198
- new_config = read_config_file(config_file)
199
- configuration = Utils.deep_merge_hashes(configuration, new_config)
200
- end
201
- rescue ArgumentError => e
202
- Jekyll.logger.warn "WARNING:", "Error reading configuration. Using defaults (and options)."
203
- warn e
204
- end
205
-
206
- configuration.validate.add_default_collections
207
- end
208
-
209
- # Public: Split a CSV string into an array containing its values
210
- #
211
- # csv - the string of comma-separated values
212
- #
213
- # Returns an array of the values contained in the CSV
214
- def csv_to_array(csv)
215
- csv.split(",").map(&:strip)
216
- end
217
-
218
- # Public: Ensure the proper options are set in the configuration
219
- #
220
- # Returns the configuration Hash
221
- def validate
222
- config = clone
223
-
224
- check_plugins(config)
225
- check_include_exclude(config)
226
-
227
- config
228
- end
229
-
230
- def add_default_collections
231
- config = clone
232
-
233
- # It defaults to `{}`, so this is only if someone sets it to null manually.
234
- return config if config["collections"].nil?
235
-
236
- # Ensure we have a hash.
237
- if config["collections"].is_a?(Array)
238
- config["collections"] = config["collections"].each_with_object({}) do |collection, hash|
239
- hash[collection] = {}
240
- end
241
- end
242
-
243
- config["collections"] = Utils.deep_merge_hashes(
244
- { "posts" => {} }, config["collections"]
245
- ).tap do |collections|
246
- collections["posts"]["output"] = true
247
- if config["permalink"]
248
- collections["posts"]["permalink"] ||= style_to_permalink(config["permalink"])
249
- end
250
- end
251
-
252
- config
253
- end
254
-
255
- DEFAULT_EXCLUDES = %w(
256
- .sass-cache .jekyll-cache
257
- gemfiles Gemfile Gemfile.lock
258
- node_modules
259
- vendor/bundle/ vendor/cache/ vendor/gems/ vendor/ruby/
260
- ).freeze
261
-
262
- def add_default_excludes
263
- config = clone
264
- return config if config["exclude"].nil?
265
-
266
- config["exclude"].concat(DEFAULT_EXCLUDES).uniq!
267
- config
268
- end
269
-
270
- private
271
-
272
- STYLE_TO_PERMALINK = {
273
- :none => "/:categories/:title:output_ext",
274
- :date => "/:categories/:year/:month/:day/:title:output_ext",
275
- :ordinal => "/:categories/:year/:y_day/:title:output_ext",
276
- :pretty => "/:categories/:year/:month/:day/:title/",
277
- :weekdate => "/:categories/:year/W:week/:short_day/:title:output_ext",
278
- }.freeze
279
-
280
- private_constant :STYLE_TO_PERMALINK
281
-
282
- def style_to_permalink(permalink_style)
283
- STYLE_TO_PERMALINK[permalink_style.to_sym] || permalink_style.to_s
284
- end
285
-
286
- def check_include_exclude(config)
287
- %w(include exclude).each do |option|
288
- next unless config.key?(option)
289
- next if config[option].is_a?(Array)
290
-
291
- raise Jekyll::Errors::InvalidConfigurationError,
292
- "'#{option}' should be set as an array, but was: #{config[option].inspect}."
293
- end
294
- end
295
-
296
- # Private: Checks if the `plugins` config is a String
297
- #
298
- # config - the config hash
299
- #
300
- # Raises a Jekyll::Errors::InvalidConfigurationError if the config `plugins`
301
- # is not an Array.
302
- def check_plugins(config)
303
- return unless config.key?("plugins")
304
- return if config["plugins"].is_a?(Array)
305
-
306
- Jekyll.logger.error "'plugins' should be set as an array of gem-names, but was: " \
307
- "#{config["plugins"].inspect}. Use 'plugins_dir' instead to set the directory " \
308
- "for your non-gemified Ruby plugins."
309
- raise Jekyll::Errors::InvalidConfigurationError,
310
- "'plugins' should be set as an array, but was: #{config["plugins"].inspect}."
311
- end
312
- end
313
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class Configuration < Hash
5
+ # Default options. Overridden by values in _config.yml.
6
+ # Strings rather than symbols are used for compatibility with YAML.
7
+ DEFAULTS = {
8
+ # Where things are
9
+ "source" => Dir.pwd,
10
+ "destination" => File.join(Dir.pwd, "_site"),
11
+ "collections_dir" => "",
12
+ "cache_dir" => ".jekyll-cache",
13
+ "plugins_dir" => "_plugins",
14
+ "layouts_dir" => "_layouts",
15
+ "data_dir" => "_data",
16
+ "includes_dir" => "_includes",
17
+ "collections" => {},
18
+
19
+ # Handling Reading
20
+ "safe" => false,
21
+ "include" => [".htaccess"],
22
+ "exclude" => [],
23
+ "keep_files" => [".git", ".svn"],
24
+ "encoding" => "utf-8",
25
+ "markdown_ext" => "markdown,mkdown,mkdn,mkd,md",
26
+ "strict_front_matter" => false,
27
+
28
+ # Filtering Content
29
+ "show_drafts" => nil,
30
+ "limit_posts" => 0,
31
+ "future" => false,
32
+ "unpublished" => false,
33
+
34
+ # Plugins
35
+ "whitelist" => [],
36
+ "plugins" => [],
37
+
38
+ # Conversion
39
+ "markdown" => "kramdown",
40
+ "highlighter" => "rouge",
41
+ "lsi" => false,
42
+ "excerpt_separator" => "\n\n",
43
+ "incremental" => false,
44
+
45
+ # Serving
46
+ "detach" => false, # default to not detaching the server
47
+ "port" => "4000",
48
+ "host" => "127.0.0.1",
49
+ "baseurl" => nil, # this mounts at /, i.e. no subdirectory
50
+ "show_dir_listing" => false,
51
+
52
+ # Output Configuration
53
+ "permalink" => "date",
54
+ "paginate_path" => "/page:num",
55
+ "timezone" => nil, # use the local timezone
56
+
57
+ "quiet" => false,
58
+ "verbose" => false,
59
+ "defaults" => [],
60
+
61
+ "liquid" => {
62
+ "error_mode" => "warn",
63
+ "strict_filters" => false,
64
+ "strict_variables" => false,
65
+ },
66
+
67
+ "kramdown" => {
68
+ "auto_ids" => true,
69
+ "toc_levels" => (1..6).to_a,
70
+ "entity_output" => "as_char",
71
+ "smart_quotes" => "lsquo,rsquo,ldquo,rdquo",
72
+ "input" => "GFM",
73
+ "hard_wrap" => false,
74
+ "guess_lang" => true,
75
+ "footnote_nr" => 1,
76
+ "show_warnings" => false,
77
+ },
78
+ }.each_with_object(Configuration.new) { |(k, v), hsh| hsh[k] = v.freeze }.freeze
79
+
80
+ class << self
81
+ # Static: Produce a Configuration ready for use in a Site.
82
+ # It takes the input, fills in the defaults where values do not exist.
83
+ #
84
+ # user_config - a Hash or Configuration of overrides.
85
+ #
86
+ # Returns a Configuration filled with defaults.
87
+ def from(user_config)
88
+ Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
89
+ .add_default_collections.add_default_excludes
90
+ end
91
+ end
92
+
93
+ # Public: Turn all keys into string
94
+ #
95
+ # Return a copy of the hash where all its keys are strings
96
+ def stringify_keys
97
+ each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v }
98
+ end
99
+
100
+ def get_config_value_with_override(config_key, override)
101
+ override[config_key] || self[config_key] || DEFAULTS[config_key]
102
+ end
103
+
104
+ # Public: Directory of the Jekyll source folder
105
+ #
106
+ # override - the command-line options hash
107
+ #
108
+ # Returns the path to the Jekyll source directory
109
+ def source(override)
110
+ get_config_value_with_override("source", override)
111
+ end
112
+
113
+ def quiet(override = {})
114
+ get_config_value_with_override("quiet", override)
115
+ end
116
+ alias_method :quiet?, :quiet
117
+
118
+ def verbose(override = {})
119
+ get_config_value_with_override("verbose", override)
120
+ end
121
+ alias_method :verbose?, :verbose
122
+
123
+ def safe_load_file(filename)
124
+ case File.extname(filename)
125
+ when %r!\.toml!i
126
+ Jekyll::External.require_with_graceful_fail("tomlrb") unless defined?(Tomlrb)
127
+ Tomlrb.load_file(filename)
128
+ when %r!\.ya?ml!i
129
+ SafeYAML.load_file(filename) || {}
130
+ else
131
+ raise ArgumentError,
132
+ "No parser for '#{filename}' is available. Use a .y(a)ml or .toml file instead."
133
+ end
134
+ end
135
+
136
+ # Public: Generate list of configuration files from the override
137
+ #
138
+ # override - the command-line options hash
139
+ #
140
+ # Returns an Array of config files
141
+ def config_files(override)
142
+ # Adjust verbosity quickly
143
+ Jekyll.logger.adjust_verbosity(
144
+ :quiet => quiet?(override),
145
+ :verbose => verbose?(override)
146
+ )
147
+
148
+ # Get configuration from <source>/_config.yml or <source>/<config_file>
149
+ config_files = override["config"]
150
+ if config_files.to_s.empty?
151
+ default = %w(yml yaml toml).find(-> { "yml" }) do |ext|
152
+ File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}"))
153
+ end
154
+ config_files = Jekyll.sanitized_path(source(override), "_config.#{default}")
155
+ @default_config_file = true
156
+ end
157
+ Array(config_files)
158
+ end
159
+
160
+ # Public: Read configuration and return merged Hash
161
+ #
162
+ # file - the path to the YAML file to be read in
163
+ #
164
+ # Returns this configuration, overridden by the values in the file
165
+ def read_config_file(file)
166
+ file = File.expand_path(file)
167
+ next_config = safe_load_file(file)
168
+
169
+ unless next_config.is_a?(Hash)
170
+ raise ArgumentError, "Configuration file: (INVALID) #{file}".yellow
171
+ end
172
+
173
+ Jekyll.logger.info "Configuration file:", file
174
+ next_config
175
+ rescue SystemCallError
176
+ if @default_config_file ||= nil
177
+ Jekyll.logger.warn "Configuration file:", "none"
178
+ {}
179
+ else
180
+ Jekyll.logger.error "Fatal:", "The configuration file '#{file}' could not be found."
181
+ raise LoadError, "The Configuration file '#{file}' could not be found."
182
+ end
183
+ end
184
+
185
+ # Public: Read in a list of configuration files and merge with this hash
186
+ #
187
+ # files - the list of configuration file paths
188
+ #
189
+ # Returns the full configuration, with the defaults overridden by the values in the
190
+ # configuration files
191
+ def read_config_files(files)
192
+ configuration = clone
193
+
194
+ begin
195
+ files.each do |config_file|
196
+ next if config_file.nil? || config_file.empty?
197
+
198
+ new_config = read_config_file(config_file)
199
+ configuration = Utils.deep_merge_hashes(configuration, new_config)
200
+ end
201
+ rescue ArgumentError => e
202
+ Jekyll.logger.warn "WARNING:", "Error reading configuration. Using defaults (and options)."
203
+ warn e
204
+ end
205
+
206
+ configuration.validate.add_default_collections
207
+ end
208
+
209
+ # Public: Split a CSV string into an array containing its values
210
+ #
211
+ # csv - the string of comma-separated values
212
+ #
213
+ # Returns an array of the values contained in the CSV
214
+ def csv_to_array(csv)
215
+ csv.split(",").map(&:strip)
216
+ end
217
+
218
+ # Public: Ensure the proper options are set in the configuration
219
+ #
220
+ # Returns the configuration Hash
221
+ def validate
222
+ config = clone
223
+
224
+ check_plugins(config)
225
+ check_include_exclude(config)
226
+
227
+ config
228
+ end
229
+
230
+ def add_default_collections
231
+ config = clone
232
+
233
+ # It defaults to `{}`, so this is only if someone sets it to null manually.
234
+ return config if config["collections"].nil?
235
+
236
+ # Ensure we have a hash.
237
+ if config["collections"].is_a?(Array)
238
+ config["collections"] = config["collections"].each_with_object({}) do |collection, hash|
239
+ hash[collection] = {}
240
+ end
241
+ end
242
+
243
+ config["collections"] = Utils.deep_merge_hashes(
244
+ { "posts" => {} }, config["collections"]
245
+ ).tap do |collections|
246
+ collections["posts"]["output"] = true
247
+ if config["permalink"]
248
+ collections["posts"]["permalink"] ||= style_to_permalink(config["permalink"])
249
+ end
250
+ end
251
+
252
+ config
253
+ end
254
+
255
+ DEFAULT_EXCLUDES = %w(
256
+ .sass-cache .jekyll-cache
257
+ gemfiles Gemfile Gemfile.lock
258
+ node_modules
259
+ vendor/bundle/ vendor/cache/ vendor/gems/ vendor/ruby/
260
+ ).freeze
261
+
262
+ def add_default_excludes
263
+ config = clone
264
+ return config if config["exclude"].nil?
265
+
266
+ config["exclude"].concat(DEFAULT_EXCLUDES).uniq!
267
+ config
268
+ end
269
+
270
+ private
271
+
272
+ STYLE_TO_PERMALINK = {
273
+ :none => "/:categories/:title:output_ext",
274
+ :date => "/:categories/:year/:month/:day/:title:output_ext",
275
+ :ordinal => "/:categories/:year/:y_day/:title:output_ext",
276
+ :pretty => "/:categories/:year/:month/:day/:title/",
277
+ :weekdate => "/:categories/:year/W:week/:short_day/:title:output_ext",
278
+ }.freeze
279
+
280
+ private_constant :STYLE_TO_PERMALINK
281
+
282
+ def style_to_permalink(permalink_style)
283
+ STYLE_TO_PERMALINK[permalink_style.to_sym] || permalink_style.to_s
284
+ end
285
+
286
+ def check_include_exclude(config)
287
+ %w(include exclude).each do |option|
288
+ next unless config.key?(option)
289
+ next if config[option].is_a?(Array)
290
+
291
+ raise Jekyll::Errors::InvalidConfigurationError,
292
+ "'#{option}' should be set as an array, but was: #{config[option].inspect}."
293
+ end
294
+ end
295
+
296
+ # Private: Checks if the `plugins` config is a String
297
+ #
298
+ # config - the config hash
299
+ #
300
+ # Raises a Jekyll::Errors::InvalidConfigurationError if the config `plugins`
301
+ # is not an Array.
302
+ def check_plugins(config)
303
+ return unless config.key?("plugins")
304
+ return if config["plugins"].is_a?(Array)
305
+
306
+ Jekyll.logger.error "'plugins' should be set as an array of gem-names, but was: " \
307
+ "#{config["plugins"].inspect}. Use 'plugins_dir' instead to set " \
308
+ "the directory for your non-gemified Ruby plugins."
309
+ raise Jekyll::Errors::InvalidConfigurationError,
310
+ "'plugins' should be set as an array, but was: #{config["plugins"].inspect}."
311
+ end
312
+ end
313
+ end