summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Miller <travis@travismiller.com>2018-12-07 22:05:40 +0000
committerDouwe Maan <douwe@gitlab.com>2018-12-07 22:05:40 +0000
commit17634d72ee42bf5c22f557978e1d4d7530912691 (patch)
tree055a38ddfa3ec98931f0fe551af102ba5ebc7343
parentabeeb24c5b2db3629d627538dc2f27fb02e01f66 (diff)
downloadgitlab-ce-17634d72ee42bf5c22f557978e1d4d7530912691.tar.gz
Changed frontmatter filtering to support YAML, JSON, TOML, and arbitrary languages
-rw-r--r--changelogs/unreleased/52007-frontmatter-toml-json.yml5
-rw-r--r--lib/banzai/filter/front_matter_filter.rb34
-rw-r--r--lib/banzai/filter/yaml_front_matter_filter.rb27
-rw-r--r--lib/banzai/pipeline/pre_process_pipeline.rb2
-rw-r--r--spec/lib/banzai/filter/front_matter_filter_spec.rb140
-rw-r--r--spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb53
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