diff --git a/lib/gollum-lib/filter/yaml.rb b/lib/gollum-lib/filter/yaml.rb index 4c1003fa..efb204a4 100644 --- a/lib/gollum-lib/filter/yaml.rb +++ b/lib/gollum-lib/filter/yaml.rb @@ -10,7 +10,7 @@ def extract(data) data.gsub!(YAML_FRONT_MATTER_REGEXP) do @markup.metadata ||= {} begin - frontmatter = ::YAML.safe_load(sanitize(Regexp.last_match[1])) + frontmatter = sanitize_frontmatter(::YAML.safe_load(Regexp.last_match[1])) @markup.metadata.merge!(frontmatter) if frontmatter.respond_to?(:keys) && frontmatter.respond_to?(:values) rescue ::Psych::SyntaxError, ::Psych::DisallowedClass, ::Psych::BadAlias => error @markup.metadata['errors'] ||= [] @@ -24,4 +24,23 @@ def extract(data) def process(data) data end + + private + + def sanitize_frontmatter(obj) + case obj + when Hash + obj.map do |k, v| + [sanitize(k.to_s), sanitize_frontmatter(v)] + end.to_h + when Array + obj.map! do |v| + sanitize_frontmatter(v) + end + when String + sanitize(obj) + else + obj + end + end end diff --git a/test/filter/test_yaml.rb b/test/filter/test_yaml.rb new file mode 100644 index 00000000..ef20f6b4 --- /dev/null +++ b/test/filter/test_yaml.rb @@ -0,0 +1,75 @@ +path = File.join(File.dirname(__FILE__), "..", "helper") +require File.expand_path(path) + +context "Gollum::Filter::YAML" do + setup do + @page = mock_page + @markup = Gollum::Markup.new(@page) + @filter = Gollum::Filter::YAML.new(@markup) + end + + def filter(content) + @filter.process(@filter.extract(content)) + end + + test 'process yaml' do + markup = <<~EOF + --- + Literal Scalar: | + abc + + 123 + Folded Scalar: > + abc + + 123 + Escaped: "abc\n\n123" + --- + + # Markdown content here + EOF + + result = {"Escaped"=> "abc\n" + "123", + "Folded Scalar" => "abc\n" + "123\n", + "Literal Scalar" => "abc\n" + "\n" + "123\n" + } + + assert_equal "# Markdown content here\n", filter(markup) + assert_nil @markup.metadata['errors'] + assert_equal result, @markup.metadata + end + + test 'escape yaml' do + markup = <<~EOF + --- + BadStuffInKey: foo + Literal Scalar: | + + + 123 + Folded Scalar: > + >abc + + <123 + Escaped: "abc" + NestedBadStuff: + Baz: + - [1, ""] + - [1, 2, 3] + --- + + # Markdown content here + EOF + + result = {"Escaped"=> "abc", + "Folded Scalar" => ">abc\n" + "<123\n", + "Literal Scalar" => "\n" + "\n" + "123\n", + "BadStuffInKey" => "foo", + "NestedBadStuff"=> {"Baz"=>[[1, ""], [1, 2, 3]]} + } + filter(markup) + assert_nil @markup.metadata['errors'] + assert_equal result, @markup.metadata + end + +end \ No newline at end of file diff --git a/test/helper.rb b/test/helper.rb index 9c50c72b..56655d38 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -88,6 +88,10 @@ def metadata(val={}) val end + def sanitizer + Gollum::Sanitization.new(Gollum::Markup.to_xml_opts) + end + attr_reader :repo_is_bare attr_reader :base_path end