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