diff options
author | Douwe Maan <douwe@gitlab.com> | 2018-12-07 22:05:40 +0000 |
---|---|---|
committer | Douwe Maan <douwe@gitlab.com> | 2018-12-07 22:05:40 +0000 |
commit | d27ecfab7b89c0d784cf6066b2b08dbfb2b96bd1 (patch) | |
tree | 055a38ddfa3ec98931f0fe551af102ba5ebc7343 | |
parent | abeeb24c5b2db3629d627538dc2f27fb02e01f66 (diff) | |
parent | 17634d72ee42bf5c22f557978e1d4d7530912691 (diff) | |
download | gitlab-ce-d27ecfab7b89c0d784cf6066b2b08dbfb2b96bd1.tar.gz |
Merge branch '52007-frontmatter-toml-json' into 'master'
Changed frontmatter filtering to support YAML, JSON, TOML, and arbitrary languages
Closes #52007
See merge request gitlab-org/gitlab-ce!23331
-rw-r--r-- | changelogs/unreleased/52007-frontmatter-toml-json.yml | 5 | ||||
-rw-r--r-- | lib/banzai/filter/front_matter_filter.rb | 34 | ||||
-rw-r--r-- | lib/banzai/filter/yaml_front_matter_filter.rb | 27 | ||||
-rw-r--r-- | lib/banzai/pipeline/pre_process_pipeline.rb | 2 | ||||
-rw-r--r-- | spec/lib/banzai/filter/front_matter_filter_spec.rb | 140 | ||||
-rw-r--r-- | spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb | 53 |
6 files changed, 180 insertions, 81 deletions
diff --git a/changelogs/unreleased/52007-frontmatter-toml-json.yml b/changelogs/unreleased/52007-frontmatter-toml-json.yml new file mode 100644 index 00000000000..bdada19f3a7 --- /dev/null +++ b/changelogs/unreleased/52007-frontmatter-toml-json.yml @@ -0,0 +1,5 @@ +--- +title: Changed frontmatter filtering to support YAML, JSON, TOML, and arbitrary languages +merge_request: 23331 +author: Travis Miller +type: changed diff --git a/lib/banzai/filter/front_matter_filter.rb b/lib/banzai/filter/front_matter_filter.rb new file mode 100644 index 00000000000..a27d18facd1 --- /dev/null +++ b/lib/banzai/filter/front_matter_filter.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Banzai + module Filter + class FrontMatterFilter < HTML::Pipeline::Filter + DELIM_LANG = { + '---' => 'yaml', + '+++' => 'toml', + ';;;' => 'json' + }.freeze + + DELIM = Regexp.union(DELIM_LANG.keys) + + PATTERN = %r{ + \A(?:[^\r\n]*coding:[^\r\n]*)? # optional encoding line + \s* + ^(?<delim>#{DELIM})[ \t]*(?<lang>\S*) # opening front matter marker (optional language specifier) + \s* + ^(?<front_matter>.*?) # front matter (not greedy) + \s* + ^\k<delim> # closing front matter marker + \s* + }mx + + def call + html.sub(PATTERN) do |_match| + lang = $~[:lang].presence || DELIM_LANG[$~[:delim]] + + ["```#{lang}", $~[:front_matter], "```", "\n"].join("\n") + end + end + end + end +end diff --git a/lib/banzai/filter/yaml_front_matter_filter.rb b/lib/banzai/filter/yaml_front_matter_filter.rb deleted file mode 100644 index 295964dd75d..00000000000 --- a/lib/banzai/filter/yaml_front_matter_filter.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -module Banzai - module Filter - class YamlFrontMatterFilter < HTML::Pipeline::Filter - DELIM = '---'.freeze - - # Hat-tip to Middleman: https://git.io/v2e0z - PATTERN = %r{ - \A(?:[^\r\n]*coding:[^\r\n]*\r?\n)? - (?<start>#{DELIM})[ ]*\r?\n - (?<frontmatter>.*?)[ ]*\r?\n? - ^(?<stop>#{DELIM})[ ]*\r?\n? - \r?\n? - (?<content>.*) - }mx.freeze - - def call - match = PATTERN.match(html) - - return html unless match - - "```yaml\n#{match['frontmatter']}\n```\n\n#{match['content']}" - end - end - end -end diff --git a/lib/banzai/pipeline/pre_process_pipeline.rb b/lib/banzai/pipeline/pre_process_pipeline.rb index c937f783180..4c2b4ca1665 100644 --- a/lib/banzai/pipeline/pre_process_pipeline.rb +++ b/lib/banzai/pipeline/pre_process_pipeline.rb @@ -5,7 +5,7 @@ module Banzai class PreProcessPipeline < BasePipeline def self.filters FilterArray[ - Filter::YamlFrontMatterFilter, + Filter::FrontMatterFilter, Filter::BlockquoteFenceFilter, ] end diff --git a/spec/lib/banzai/filter/front_matter_filter_spec.rb b/spec/lib/banzai/filter/front_matter_filter_spec.rb new file mode 100644 index 00000000000..3071dc7cf21 --- /dev/null +++ b/spec/lib/banzai/filter/front_matter_filter_spec.rb @@ -0,0 +1,140 @@ +require 'rails_helper' + +describe Banzai::Filter::FrontMatterFilter do + include FilterSpecHelper + + it 'allows for `encoding:` before the front matter' do + content = <<~MD + # encoding: UTF-8 + --- + foo: foo + bar: bar + --- + + # Header + + Content + MD + + output = filter(content) + + expect(output).not_to match 'encoding' + end + + it 'converts YAML front matter to a fenced code block' do + content = <<~MD + --- + foo: :foo_symbol + bar: :bar_symbol + --- + + # Header + + Content + MD + + output = filter(content) + + aggregate_failures do + expect(output).not_to include '---' + expect(output).to include "```yaml\nfoo: :foo_symbol\n" + end + end + + it 'converts TOML frontmatter to a fenced code block' do + content = <<~MD + +++ + foo = :foo_symbol + bar = :bar_symbol + +++ + + # Header + + Content + MD + + output = filter(content) + + aggregate_failures do + expect(output).not_to include '+++' + expect(output).to include "```toml\nfoo = :foo_symbol\n" + end + end + + it 'converts JSON front matter to a fenced code block' do + content = <<~MD + ;;; + { + "foo": ":foo_symbol", + "bar": ":bar_symbol" + } + ;;; + + # Header + + Content + MD + + output = filter(content) + + aggregate_failures do + expect(output).not_to include ';;;' + expect(output).to include "```json\n{\n \"foo\": \":foo_symbol\",\n" + end + end + + it 'converts arbitrary front matter to a fenced code block' do + content = <<~MD + ---arbitrary + foo = :foo_symbol + bar = :bar_symbol + --- + + # Header + + Content + MD + + output = filter(content) + + aggregate_failures do + expect(output).not_to include '---arbitrary' + expect(output).to include "```arbitrary\nfoo = :foo_symbol\n" + end + end + + context 'on content without front matter' do + it 'returns the content unmodified' do + content = <<~MD + # This is some Markdown + + It has no YAML front matter to parse. + MD + + expect(filter(content)).to eq content + end + end + + context 'on front matter without content' do + it 'converts YAML front matter to a fenced code block' do + content = <<~MD + --- + foo: :foo_symbol + bar: :bar_symbol + --- + MD + + output = filter(content) + + aggregate_failures do + expect(output).to eq <<~MD + ```yaml + foo: :foo_symbol + bar: :bar_symbol + ``` + + MD + end + end + end +end diff --git a/spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb b/spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb deleted file mode 100644 index 9f1b862ef19..00000000000 --- a/spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb +++ /dev/null @@ -1,53 +0,0 @@ -require 'rails_helper' - -describe Banzai::Filter::YamlFrontMatterFilter do - include FilterSpecHelper - - it 'allows for `encoding:` before the frontmatter' do - content = <<-MD.strip_heredoc - # encoding: UTF-8 - --- - foo: foo - --- - - # Header - - Content - MD - - output = filter(content) - - expect(output).not_to match 'encoding' - end - - it 'converts YAML frontmatter to a fenced code block' do - content = <<-MD.strip_heredoc - --- - bar: :bar_symbol - --- - - # Header - - Content - MD - - output = filter(content) - - aggregate_failures do - expect(output).not_to include '---' - expect(output).to include "```yaml\nbar: :bar_symbol\n```" - end - end - - context 'on content without frontmatter' do - it 'returns the content unmodified' do - content = <<-MD.strip_heredoc - # This is some Markdown - - It has no YAML frontmatter to parse. - MD - - expect(filter(content)).to eq content - end - end -end |