diff --git a/docs/_docs/configuration.md b/docs/_docs/configuration.md
index 7789d52f..057e4ee2 100644
--- a/docs/_docs/configuration.md
+++ b/docs/_docs/configuration.md
@@ -305,6 +305,18 @@ class="flag">flags (specified on the command-line) that control them.
--profile
+
+
+ Strict Front Matter
+
+ Cause a build to fail if there is a YAML syntax error in a page's front matter.
+
+ |
+
+ strict_front_matter: BOOL
+ --strict_front_matter
+ |
+
@@ -601,12 +613,13 @@ collections:
output: true
# Handling Reading
-safe: false
-include: [".htaccess"]
-exclude: ["Gemfile", "Gemfile.lock", "node_modules", "vendor/bundle/", "vendor/cache/", "vendor/gems/", "vendor/ruby/"]
-keep_files: [".git", ".svn"]
-encoding: "utf-8"
-markdown_ext: "markdown,mkdown,mkdn,mkd,md"
+safe: false
+include: [".htaccess"]
+exclude: ["Gemfile", "Gemfile.lock", "node_modules", "vendor/bundle/", "vendor/cache/", "vendor/gems/", "vendor/ruby/"]
+keep_files: [".git", ".svn"]
+encoding: "utf-8"
+markdown_ext: "markdown,mkdown,mkdn,mkd,md"
+strict_front_matter: false
# Filtering Content
show_drafts: null
diff --git a/lib/jekyll/command.rb b/lib/jekyll/command.rb
index 9150d24d..f9f243dd 100644
--- a/lib/jekyll/command.rb
+++ b/lib/jekyll/command.rb
@@ -46,6 +46,7 @@ module Jekyll
# c - the Jekyll::Command to add these options to
#
# Returns nothing
+ # rubocop:disable Metrics/MethodLength
def add_build_options(c)
c.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]",
Array, "Custom configuration file"
@@ -66,7 +67,10 @@ module Jekyll
c.option "quiet", "-q", "--quiet", "Silence output."
c.option "verbose", "-V", "--verbose", "Print verbose output."
c.option "incremental", "-I", "--incremental", "Enable incremental rebuild."
+ c.option "strict_front_matter", "--strict_front_matter",
+ "Fail if errors are present in front matter"
end
+ # rubocop:enable Metrics/MethodLength
end
end
end
diff --git a/lib/jekyll/configuration.rb b/lib/jekyll/configuration.rb
index 86bee3c1..153d98fe 100644
--- a/lib/jekyll/configuration.rb
+++ b/lib/jekyll/configuration.rb
@@ -6,71 +6,72 @@ module Jekyll
# Strings rather than symbols are used for compatibility with YAML.
DEFAULTS = Configuration[{
# Where things are
- "source" => Dir.pwd,
- "destination" => File.join(Dir.pwd, "_site"),
- "plugins_dir" => "_plugins",
- "layouts_dir" => "_layouts",
- "data_dir" => "_data",
- "includes_dir" => "_includes",
- "collections" => {},
+ "source" => Dir.pwd,
+ "destination" => File.join(Dir.pwd, "_site"),
+ "plugins_dir" => "_plugins",
+ "layouts_dir" => "_layouts",
+ "data_dir" => "_data",
+ "includes_dir" => "_includes",
+ "collections" => {},
# Handling Reading
- "safe" => false,
- "include" => [".htaccess"],
- "exclude" => %w(
+ "safe" => false,
+ "include" => [".htaccess"],
+ "exclude" => %w(
Gemfile Gemfile.lock node_modules vendor/bundle/ vendor/cache/ vendor/gems/
vendor/ruby/
),
- "keep_files" => [".git", ".svn"],
- "encoding" => "utf-8",
- "markdown_ext" => "markdown,mkdown,mkdn,mkd,md",
+ "keep_files" => [".git", ".svn"],
+ "encoding" => "utf-8",
+ "markdown_ext" => "markdown,mkdown,mkdn,mkd,md",
+ "strict_front_matter" => false,
# Filtering Content
- "show_drafts" => nil,
- "limit_posts" => 0,
- "future" => false,
- "unpublished" => false,
+ "show_drafts" => nil,
+ "limit_posts" => 0,
+ "future" => false,
+ "unpublished" => false,
# Plugins
- "whitelist" => [],
- "plugins" => [],
+ "whitelist" => [],
+ "plugins" => [],
# Conversion
- "markdown" => "kramdown",
- "highlighter" => "rouge",
- "lsi" => false,
- "excerpt_separator" => "\n\n",
- "incremental" => false,
+ "markdown" => "kramdown",
+ "highlighter" => "rouge",
+ "lsi" => false,
+ "excerpt_separator" => "\n\n",
+ "incremental" => false,
# Serving
- "detach" => false, # default to not detaching the server
- "port" => "4000",
- "host" => "127.0.0.1",
- "baseurl" => "",
- "show_dir_listing" => false,
+ "detach" => false, # default to not detaching the server
+ "port" => "4000",
+ "host" => "127.0.0.1",
+ "baseurl" => "",
+ "show_dir_listing" => false,
# Output Configuration
- "permalink" => "date",
- "paginate_path" => "/page:num",
- "timezone" => nil, # use the local timezone
+ "permalink" => "date",
+ "paginate_path" => "/page:num",
+ "timezone" => nil, # use the local timezone
- "quiet" => false,
- "verbose" => false,
- "defaults" => [],
+ "quiet" => false,
+ "verbose" => false,
+ "defaults" => [],
- "liquid" => {
+ "liquid" => {
"error_mode" => "warn",
},
- "rdiscount" => {
+ "rdiscount" => {
"extensions" => [],
},
- "redcarpet" => {
+ "redcarpet" => {
"extensions" => [],
},
- "kramdown" => {
+ "kramdown" => {
"auto_ids" => true,
"toc_levels" => "1..6",
"entity_output" => "as_char",
diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb
index 34741c8f..16745dd5 100644
--- a/lib/jekyll/convertible.rb
+++ b/lib/jekyll/convertible.rb
@@ -48,8 +48,10 @@ module Jekyll
end
rescue SyntaxError => e
Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}"
+ raise e if self.site.config["strict_front_matter"]
rescue => e
Jekyll.logger.warn "Error reading file #{filename}: #{e.message}"
+ raise e if self.site.config["strict_front_matter"]
end
self.data ||= {}
diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb
index a37ca1e4..90cfd1be 100644
--- a/lib/jekyll/document.rb
+++ b/lib/jekyll/document.rb
@@ -259,11 +259,8 @@ module Jekyll
merge_defaults
read_content(opts)
read_post_data
- rescue SyntaxError => e
- Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{e.message}"
rescue => e
- raise e if e.is_a? Jekyll::Errors::FatalException
- Jekyll.logger.error "Error:", "could not read file #{path}: #{e.message}"
+ handle_read_error(e)
end
end
end
@@ -457,6 +454,19 @@ module Jekyll
generate_excerpt
end
+ private
+ def handle_read_error(error)
+ if error.is_a? SyntaxError
+ Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{error.message}"
+ else
+ Jekyll.logger.error "Error:", "could not read file #{path}: #{error.message}"
+ end
+
+ if site.config["strict_front_matter"] || error.is_a?(Jekyll::Errors::FatalException)
+ raise error
+ end
+ end
+
private
def populate_title
if relative_path =~ DATE_FILENAME_MATCHER
diff --git a/test/source/_broken/bad_post.md b/test/source/_broken/bad_post.md
new file mode 100644
index 00000000..f895dd26
--- /dev/null
+++ b/test/source/_broken/bad_post.md
@@ -0,0 +1,4 @@
+---
+bad yaml: [
+---
+Real content starts here
diff --git a/test/test_convertible.rb b/test/test_convertible.rb
index 82d64374..6e6defa6 100644
--- a/test/test_convertible.rb
+++ b/test/test_convertible.rb
@@ -33,6 +33,14 @@ class TestConvertible < JekyllUnitTest
assert_match(%r!#{File.join(@base, name)}!, out)
end
+ should "raise for broken front matter with `strict_front_matter` set" do
+ name = "broken_front_matter2.erb"
+ @convertible.site.config["strict_front_matter"] = true
+ assert_raises do
+ @convertible.read_yaml(@base, name)
+ end
+ end
+
should "not allow ruby objects in YAML" do
out = capture_stderr do
@convertible.read_yaml(@base, "exploit_front_matter.erb")
diff --git a/test/test_site.rb b/test/test_site.rb
index 65032ebd..d039cb8a 100644
--- a/test/test_site.rb
+++ b/test/test_site.rb
@@ -280,6 +280,24 @@ class TestSite < JekyllUnitTest
Site.new(site_configuration("destination" => File.join(source_dir, "..")))
end
end
+
+ should "raise for bad frontmatter if strict_front_matter is set" do
+ site = Site.new(site_configuration(
+ "collections" => ["broken"],
+ "strict_front_matter" => true
+ ))
+ assert_raises do
+ site.process
+ end
+ end
+
+ should "not raise for bad frontmatter if strict_front_matter is not set" do
+ site = Site.new(site_configuration(
+ "collections" => ["broken"],
+ "strict_front_matter" => false
+ ))
+ site.process
+ end
end
context "with orphaned files in destination" do