jekyll 4.2.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +350 -347
  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 +169 -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 -365
  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 -260
  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 -270
  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