diff --git a/middleman-core/features/front-matter.feature b/middleman-core/features/front-matter.feature
index 83795236..64bcb94b 100644
--- a/middleman-core/features/front-matter.feature
+++ b/middleman-core/features/front-matter.feature
@@ -28,13 +28,18 @@ Feature: YAML Front Matter
Then I should not see "layout: false"
Then I should not see "title: Pandoc likes trailing dots..."
+ Scenario: Rendering Haml (yaml)
+ Given the Server is running at "frontmatter-app"
+ When I go to "/front-matter-haml.html"
+ Then I should see "
This is the title
"
+ Then I should not see "---"
Scenario: YAML not on first line, no encoding
Given the Server is running at "frontmatter-app"
When I go to "/front-matter-line-2.html"
Then I should see ""
Then I should see "---"
-
+
Scenario: YAML not on first line, with encoding
Given the Server is running at "frontmatter-app"
When I go to "/front-matter-encoding.html"
diff --git a/middleman-core/fixtures/frontmatter-app/config.rb b/middleman-core/fixtures/frontmatter-app/config.rb
index e69de29b..c65e50e1 100644
--- a/middleman-core/fixtures/frontmatter-app/config.rb
+++ b/middleman-core/fixtures/frontmatter-app/config.rb
@@ -0,0 +1 @@
+config[:frontmatter_delims][:yaml] << %w(\\--- \\---)
diff --git a/middleman-core/fixtures/frontmatter-app/source/front-matter-haml.html.haml b/middleman-core/fixtures/frontmatter-app/source/front-matter-haml.html.haml
new file mode 100644
index 00000000..13bbf11e
--- /dev/null
+++ b/middleman-core/fixtures/frontmatter-app/source/front-matter-haml.html.haml
@@ -0,0 +1,6 @@
+\---
+layout: false
+title: This is the title
+\---
+
+%h1= current_page.data.title
diff --git a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb
index b9f82b36..6fa6e37c 100644
--- a/middleman-core/fixtures/frontmatter-neighbor-app/config.rb
+++ b/middleman-core/fixtures/frontmatter-neighbor-app/config.rb
@@ -15,7 +15,7 @@ class NeighborFrontmatter < ::Middleman::Extension
next unless file
- fmdata = ::Middleman::Util::Data.parse(file[:full_path], :yaml).first
+ fmdata = ::Middleman::Util::Data.parse(file[:full_path], app.config[:frontmatter_delims], :yaml).first
opts = fmdata.extract!(:layout, :layout_engine, :renderer_options, :directory_index, :content_type)
opts[:renderer_options].symbolize_keys! if opts.key?(:renderer_options)
ignored = fmdata.delete(:ignored)
diff --git a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb
index 93cd8f1f..a7e0fc55 100644
--- a/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb
+++ b/middleman-core/fixtures/frontmatter-settings-neighbor-app/config.rb
@@ -26,7 +26,7 @@ class NeighborFrontmatter < ::Middleman::Extension
end
def apply_neighbor_data(resource, file)
- fmdata = ::Middleman::Util::Data.parse(file[:full_path], :yaml).first
+ fmdata = ::Middleman::Util::Data.parse(file[:full_path], app.config[:frontmatter_delims], :yaml).first
opts = fmdata.extract!(:layout, :layout_engine, :renderer_options, :directory_index, :content_type)
opts[:renderer_options].symbolize_keys! if opts.key?(:renderer_options)
ignored = fmdata.delete(:ignored)
diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb
index 4e46ed82..7277474b 100644
--- a/middleman-core/lib/middleman-core/application.rb
+++ b/middleman-core/lib/middleman-core/application.rb
@@ -185,6 +185,12 @@ module Middleman
end
}, 'Callbacks that can exclude paths from the sitemap'
+ # Set textual delimiters that denote the start and end of frontmatter
+ define_setting :frontmatter_delims, {
+ json: [%w(;;; ;;;)],
+ yaml: [%w(--- ---), %w(--- ...)]
+ }, 'Allowed frontmatter delimiters'
+
define_setting :watcher_disable, false, 'If the Listen watcher should not run'
define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode'
define_setting :watcher_latency, nil, 'The Listen watcher latency'
diff --git a/middleman-core/lib/middleman-core/core_extensions/data.rb b/middleman-core/lib/middleman-core/core_extensions/data.rb
index 9169410a..f1762e43 100644
--- a/middleman-core/lib/middleman-core/core_extensions/data.rb
+++ b/middleman-core/lib/middleman-core/core_extensions/data.rb
@@ -99,10 +99,10 @@ module Middleman
basename = File.basename(data_path, extension)
if %w(.yaml .yml).include?(extension)
- data, postscript = ::Middleman::Util::Data.parse(file[:full_path], :yaml)
+ data, postscript = ::Middleman::Util::Data.parse(file[:full_path], @app.config[:frontmatter_delims], :yaml)
data[:postscript] = postscript if !postscript.nil? && data.is_a?(Hash)
elsif extension == '.json'
- data, _postscript = ::Middleman::Util::Data.parse(file[:full_path], :json)
+ data, _postscript = ::Middleman::Util::Data.parse(file[:full_path], @app.config[:frontmatter_delims], :json)
else
return
end
diff --git a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb
index a133d0ef..b1488c1a 100644
--- a/middleman-core/lib/middleman-core/core_extensions/front_matter.rb
+++ b/middleman-core/lib/middleman-core/core_extensions/front_matter.rb
@@ -65,7 +65,10 @@ module Middleman::CoreExtensions
return [{}, nil] unless file
- @cache[file[:full_path]] ||= ::Middleman::Util::Data.parse(file[:full_path])
+ @cache[file[:full_path]] ||= ::Middleman::Util::Data.parse(
+ file[:full_path],
+ app.config[:frontmatter_delims]
+ )
end
Contract ArrayOf[IsA['Middleman::SourceFile']], ArrayOf[IsA['Middleman::SourceFile']] => Any
diff --git a/middleman-core/lib/middleman-core/util/data.rb b/middleman-core/lib/middleman-core/util/data.rb
index 5ed00a4f..d2668dda 100644
--- a/middleman-core/lib/middleman-core/util/data.rb
+++ b/middleman-core/lib/middleman-core/util/data.rb
@@ -14,7 +14,7 @@ module Middleman::Util::Data
# @param [String] path
# @return [Array]
Contract Pathname, Maybe[Symbol] => [Hash, Maybe[String]]
- def parse(full_path, known_type=nil)
+ def parse(full_path, frontmatter_delims, known_type=nil)
return [{}, nil] if Middleman::Util.binary?(full_path)
# Avoid weird race condition when a file is renamed
@@ -24,16 +24,22 @@ module Middleman::Util::Data
return [{}, nil]
end
- /
+ start_delims, stop_delims = frontmatter_delims
+ .values
+ .flatten(1)
+ .transpose
+ .map(&Regexp.method(:union))
+
+ match = /
\A(?:[^\r\n]*coding:[^\r\n]*\r?\n)?
- (?---|;;;)[ ]*\r?\n
+ (?#{start_delims})[ ]*\r?\n
(?.*?)[ ]*\r?\n?
- ^(?---|\.\.\.|;;;)[ ]*\r?\n?
+ ^(?#{stop_delims})[ ]*\r?\n?
\r?\n?
(?.*)
- /mx =~ content
+ /mx.match(content) || {}
- unless frontmatter
+ unless match[:frontmatter]
case known_type
when :yaml
return [parse_yaml(content, full_path), nil]
@@ -42,13 +48,22 @@ module Middleman::Util::Data
end
end
- case [start, stop]
- when %w(--- ---), %w(--- ...)
- [parse_yaml(frontmatter, full_path), additional_content]
- when %w(;;; ;;;)
- [parse_json("{#{frontmatter}}", full_path), additional_content]
+ case [match[:start], match[:stop]]
+ when *frontmatter_delims[:yaml]
+ [
+ parse_yaml(match[:frontmatter], full_path),
+ match[:additional_content]
+ ]
+ when *frontmatter_delims[:json]
+ [
+ parse_json("{#{match[:frontmatter]}}", full_path),
+ match[:additional_content]
+ ]
else
- [{}, content]
+ [
+ {},
+ content
+ ]
end
end