jekyll 4.2.1 → 4.2.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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +350 -350
  3. data/LICENSE +21 -21
  4. data/README.markdown +86 -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 +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 +190 -190
  12. data/lib/jekyll/cleaner.rb +111 -111
  13. data/lib/jekyll/collection.rb +309 -309
  14. data/lib/jekyll/command.rb +105 -105
  15. data/lib/jekyll/commands/build.rb +93 -93
  16. data/lib/jekyll/commands/clean.rb +45 -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 +172 -169
  20. data/lib/jekyll/commands/new_theme.rb +40 -40
  21. data/lib/jekyll/commands/serve/live_reload_reactor.rb +122 -122
  22. data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
  23. data/lib/jekyll/commands/serve/servlet.rb +202 -202
  24. data/lib/jekyll/commands/serve/websockets.rb +81 -81
  25. data/lib/jekyll/commands/serve.rb +362 -362
  26. data/lib/jekyll/configuration.rb +313 -313
  27. data/lib/jekyll/converter.rb +54 -54
  28. data/lib/jekyll/converters/identity.rb +41 -41
  29. data/lib/jekyll/converters/markdown/kramdown_parser.rb +199 -199
  30. data/lib/jekyll/converters/markdown.rb +113 -113
  31. data/lib/jekyll/converters/smartypants.rb +70 -70
  32. data/lib/jekyll/convertible.rb +257 -257
  33. data/lib/jekyll/deprecator.rb +50 -50
  34. data/lib/jekyll/document.rb +544 -544
  35. data/lib/jekyll/drops/collection_drop.rb +20 -20
  36. data/lib/jekyll/drops/document_drop.rb +70 -70
  37. data/lib/jekyll/drops/drop.rb +293 -293
  38. data/lib/jekyll/drops/excerpt_drop.rb +19 -19
  39. data/lib/jekyll/drops/jekyll_drop.rb +32 -32
  40. data/lib/jekyll/drops/site_drop.rb +66 -66
  41. data/lib/jekyll/drops/static_file_drop.rb +14 -14
  42. data/lib/jekyll/drops/unified_payload_drop.rb +26 -26
  43. data/lib/jekyll/drops/url_drop.rb +140 -140
  44. data/lib/jekyll/entry_filter.rb +121 -121
  45. data/lib/jekyll/errors.rb +20 -20
  46. data/lib/jekyll/excerpt.rb +201 -201
  47. data/lib/jekyll/external.rb +79 -79
  48. data/lib/jekyll/filters/date_filters.rb +110 -110
  49. data/lib/jekyll/filters/grouping_filters.rb +64 -64
  50. data/lib/jekyll/filters/url_filters.rb +98 -98
  51. data/lib/jekyll/filters.rb +535 -535
  52. data/lib/jekyll/frontmatter_defaults.rb +240 -240
  53. data/lib/jekyll/generator.rb +5 -5
  54. data/lib/jekyll/hooks.rb +107 -107
  55. data/lib/jekyll/inclusion.rb +32 -32
  56. data/lib/jekyll/layout.rb +67 -67
  57. data/lib/jekyll/liquid_extensions.rb +22 -22
  58. data/lib/jekyll/liquid_renderer/file.rb +77 -77
  59. data/lib/jekyll/liquid_renderer/table.rb +55 -55
  60. data/lib/jekyll/liquid_renderer.rb +80 -80
  61. data/lib/jekyll/log_adapter.rb +151 -151
  62. data/lib/jekyll/mime.types +866 -866
  63. data/lib/jekyll/page.rb +217 -217
  64. data/lib/jekyll/page_excerpt.rb +25 -25
  65. data/lib/jekyll/page_without_a_file.rb +14 -14
  66. data/lib/jekyll/path_manager.rb +74 -74
  67. data/lib/jekyll/plugin.rb +92 -92
  68. data/lib/jekyll/plugin_manager.rb +115 -115
  69. data/lib/jekyll/profiler.rb +58 -58
  70. data/lib/jekyll/publisher.rb +23 -23
  71. data/lib/jekyll/reader.rb +192 -192
  72. data/lib/jekyll/readers/collection_reader.rb +23 -23
  73. data/lib/jekyll/readers/data_reader.rb +79 -79
  74. data/lib/jekyll/readers/layout_reader.rb +62 -62
  75. data/lib/jekyll/readers/page_reader.rb +25 -25
  76. data/lib/jekyll/readers/post_reader.rb +85 -85
  77. data/lib/jekyll/readers/static_file_reader.rb +25 -25
  78. data/lib/jekyll/readers/theme_assets_reader.rb +52 -52
  79. data/lib/jekyll/regenerator.rb +195 -195
  80. data/lib/jekyll/related_posts.rb +52 -52
  81. data/lib/jekyll/renderer.rb +265 -265
  82. data/lib/jekyll/site.rb +551 -551
  83. data/lib/jekyll/static_file.rb +208 -208
  84. data/lib/jekyll/stevenson.rb +60 -60
  85. data/lib/jekyll/tags/highlight.rb +110 -110
  86. data/lib/jekyll/tags/include.rb +275 -275
  87. data/lib/jekyll/tags/link.rb +42 -42
  88. data/lib/jekyll/tags/post_url.rb +106 -106
  89. data/lib/jekyll/theme.rb +86 -86
  90. data/lib/jekyll/theme_builder.rb +121 -121
  91. data/lib/jekyll/url.rb +167 -167
  92. data/lib/jekyll/utils/ansi.rb +57 -57
  93. data/lib/jekyll/utils/exec.rb +26 -26
  94. data/lib/jekyll/utils/internet.rb +37 -37
  95. data/lib/jekyll/utils/platforms.rb +67 -67
  96. data/lib/jekyll/utils/thread_event.rb +31 -31
  97. data/lib/jekyll/utils/win_tz.rb +75 -75
  98. data/lib/jekyll/utils.rb +367 -367
  99. data/lib/jekyll/version.rb +5 -5
  100. data/lib/jekyll.rb +195 -195
  101. data/lib/site_template/.gitignore +5 -5
  102. data/lib/site_template/404.html +25 -25
  103. data/lib/site_template/_config.yml +55 -55
  104. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
  105. data/lib/site_template/about.markdown +18 -18
  106. data/lib/site_template/index.markdown +6 -6
  107. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
  108. data/lib/theme_template/Gemfile +4 -4
  109. data/lib/theme_template/LICENSE.txt.erb +21 -21
  110. data/lib/theme_template/README.md.erb +52 -52
  111. data/lib/theme_template/_layouts/default.html +1 -1
  112. data/lib/theme_template/_layouts/page.html +5 -5
  113. data/lib/theme_template/_layouts/post.html +5 -5
  114. data/lib/theme_template/example/_config.yml.erb +1 -1
  115. data/lib/theme_template/example/_post.md +12 -12
  116. data/lib/theme_template/example/index.html +14 -14
  117. data/lib/theme_template/example/style.scss +7 -7
  118. data/lib/theme_template/gitignore.erb +6 -6
  119. data/lib/theme_template/theme.gemspec.erb +16 -16
  120. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
  121. data/rubocop/jekyll/no_p_allowed.rb +23 -23
  122. data/rubocop/jekyll/no_puts_allowed.rb +23 -23
  123. data/rubocop/jekyll.rb +5 -5
  124. metadata +3 -3
@@ -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 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