diff --git a/lib/perron/resource/separator.rb b/lib/perron/resource/separator.rb index afa241c..263e60a 100644 --- a/lib/perron/resource/separator.rb +++ b/lib/perron/resource/separator.rb @@ -19,12 +19,21 @@ def frontmatter def parsed(content) if content =~ /\A---\s*(.*?)\s*---\s*(.*)/m - @frontmatter = YAML.safe_load($1, permitted_classes: [Date, Time]) || {} - @content = $2.strip - else - @frontmatter = {} - @content = content + parsed_yaml = YAML.safe_load($1, permitted_classes: [Date, Time]) + + # A `---` at the start of the body (a thematic break) followed by + # another `---` also matches, but parses to a string or an array + # rather than a mapping. Only treat it as frontmatter when it is one. + if parsed_yaml.nil? || parsed_yaml.is_a?(Hash) + @frontmatter = parsed_yaml || {} + @content = $2.strip + + return + end end + + @frontmatter = {} + @content = content end end end diff --git a/test/perron/resource/separator_test.rb b/test/perron/resource/separator_test.rb index a4280ad..db52c4a 100644 --- a/test/perron/resource/separator_test.rb +++ b/test/perron/resource/separator_test.rb @@ -60,6 +60,30 @@ def test_parses_yaml_list_syntax assert_equal ["alice", "bob"], separator.frontmatter.authors end + def test_treats_a_leading_thematic_break_as_content_not_frontmatter + content = <<~CONTENT + --- + + An intro paragraph. + + --- + + The rest of the post. + CONTENT + separator = Perron::Resource::Separator.new(content) + + assert_equal content, separator.content + assert_empty separator.frontmatter.to_h + end + + def test_ignores_a_scalar_between_the_fences + content = "---\nJust a sentence, not a mapping\n---\nBody\n" + separator = Perron::Resource::Separator.new(content) + + assert_equal content, separator.content + assert_empty separator.frontmatter.to_h + end + def test_parses_mixed_types_in_frontmatter content = <<~CONTENT ---