jekyll 4.0.1 → 4.2.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.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +350 -163
  3. data/LICENSE +21 -21
  4. data/README.markdown +86 -90
  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 -103
  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 -173
  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 -42
  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 -354
  26. data/lib/jekyll/configuration.rb +313 -316
  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 -130
  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 -254
  33. data/lib/jekyll/deprecator.rb +50 -50
  34. data/lib/jekyll/document.rb +544 -522
  35. data/lib/jekyll/drops/collection_drop.rb +20 -20
  36. data/lib/jekyll/drops/document_drop.rb +70 -69
  37. data/lib/jekyll/drops/drop.rb +293 -215
  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 -132
  44. data/lib/jekyll/entry_filter.rb +121 -110
  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 -68
  51. data/lib/jekyll/filters.rb +535 -454
  52. data/lib/jekyll/frontmatter_defaults.rb +240 -245
  53. data/lib/jekyll/generator.rb +5 -5
  54. data/lib/jekyll/hooks.rb +107 -106
  55. data/lib/jekyll/inclusion.rb +32 -0
  56. data/lib/jekyll/layout.rb +67 -62
  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 -75
  60. data/lib/jekyll/liquid_renderer.rb +80 -77
  61. data/lib/jekyll/log_adapter.rb +151 -151
  62. data/lib/jekyll/mime.types +866 -866
  63. data/lib/jekyll/page.rb +217 -186
  64. data/lib/jekyll/page_excerpt.rb +25 -0
  65. data/lib/jekyll/page_without_a_file.rb +14 -14
  66. data/lib/jekyll/path_manager.rb +74 -31
  67. data/lib/jekyll/plugin.rb +92 -92
  68. data/lib/jekyll/plugin_manager.rb +115 -115
  69. data/lib/jekyll/profiler.rb +58 -0
  70. data/lib/jekyll/publisher.rb +23 -23
  71. data/lib/jekyll/reader.rb +192 -187
  72. data/lib/jekyll/readers/collection_reader.rb +23 -22
  73. data/lib/jekyll/readers/data_reader.rb +79 -75
  74. data/lib/jekyll/readers/layout_reader.rb +62 -61
  75. data/lib/jekyll/readers/page_reader.rb +25 -24
  76. data/lib/jekyll/readers/post_reader.rb +85 -84
  77. data/lib/jekyll/readers/static_file_reader.rb +25 -24
  78. data/lib/jekyll/readers/theme_assets_reader.rb +52 -51
  79. data/lib/jekyll/regenerator.rb +195 -195
  80. data/lib/jekyll/related_posts.rb +52 -52
  81. data/lib/jekyll/renderer.rb +265 -267
  82. data/lib/jekyll/site.rb +551 -527
  83. data/lib/jekyll/static_file.rb +208 -203
  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 -221
  87. data/lib/jekyll/tags/link.rb +42 -41
  88. data/lib/jekyll/tags/post_url.rb +106 -107
  89. data/lib/jekyll/theme.rb +86 -80
  90. data/lib/jekyll/theme_builder.rb +121 -121
  91. data/lib/jekyll/url.rb +167 -164
  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 -82
  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 -206
  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 -19
  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 +20 -38
@@ -1,316 +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",
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
- def style_to_permalink(permalink_style)
273
- case permalink_style.to_sym
274
- when :pretty
275
- "/:categories/:year/:month/:day/:title/"
276
- when :none
277
- "/:categories/:title:output_ext"
278
- when :date
279
- "/:categories/:year/:month/:day/:title:output_ext"
280
- when :ordinal
281
- "/:categories/:year/:y_day/:title:output_ext"
282
- when :weekdate
283
- "/:categories/:year/W:week/:short_day/:title:output_ext"
284
- else
285
- permalink_style.to_s
286
- end
287
- end
288
-
289
- def check_include_exclude(config)
290
- %w(include exclude).each do |option|
291
- next unless config.key?(option)
292
- next if config[option].is_a?(Array)
293
-
294
- raise Jekyll::Errors::InvalidConfigurationError,
295
- "'#{option}' should be set as an array, but was: #{config[option].inspect}."
296
- end
297
- end
298
-
299
- # Private: Checks if the `plugins` config is a String
300
- #
301
- # config - the config hash
302
- #
303
- # Raises a Jekyll::Errors::InvalidConfigurationError if the config `plugins`
304
- # is not an Array.
305
- def check_plugins(config)
306
- return unless config.key?("plugins")
307
- return if config["plugins"].is_a?(Array)
308
-
309
- Jekyll.logger.error "'plugins' should be set as an array of gem-names, but was: " \
310
- "#{config["plugins"].inspect}. Use 'plugins_dir' instead to set the directory " \
311
- "for your non-gemified Ruby plugins."
312
- raise Jekyll::Errors::InvalidConfigurationError,
313
- "'plugins' should be set as an array, but was: #{config["plugins"].inspect}."
314
- end
315
- end
316
- 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