summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <robert@gitlab.com>2016-03-05 00:17:58 +0000
committerRobert Speicher <robert@gitlab.com>2016-03-05 00:17:58 +0000
commit0c7626f3a5c5970a68cb6cba64b46e7d8b81687f (patch)
treea2715dfa53edf631bb7023188b5024f4a2d2fb8e
parent2f6ded6df9eeea8b38861a99dd93d5bba1ab7b0a (diff)
parent8eaeda081615346e1d428e9f4f4402d3bb24b9f1 (diff)
downloadgitlab-ce-0c7626f3a5c5970a68cb6cba64b46e7d8b81687f.tar.gz
Merge branch 'rs-frontmatter-pre' into 'master'
Properly display YAML front matter in Markdown See merge request !3072
-rw-r--r--app/helpers/gitlab_markdown_helper.rb2
-rw-r--r--lib/banzai.rb4
-rw-r--r--lib/banzai/filter/yaml_front_matter_filter.rb28
-rw-r--r--lib/banzai/pipeline/pre_process_pipeline.rb17
-rw-r--r--lib/banzai/renderer.rb6
-rw-r--r--spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb53
6 files changed, 110 insertions, 0 deletions
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 89d2a648494..2f760af02fd 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -50,6 +50,8 @@ module GitlabMarkdownHelper
context[:project] ||= @project
+ text = Banzai.pre_process(text, context)
+
html = Banzai.render(text, context)
context.merge!(
diff --git a/lib/banzai.rb b/lib/banzai.rb
index 093382261ae..b467413a7dd 100644
--- a/lib/banzai.rb
+++ b/lib/banzai.rb
@@ -7,6 +7,10 @@ module Banzai
Renderer.render_result(text, context)
end
+ def self.pre_process(text, context)
+ Renderer.pre_process(text, context)
+ end
+
def self.post_process(html, context)
Renderer.post_process(html, context)
end
diff --git a/lib/banzai/filter/yaml_front_matter_filter.rb b/lib/banzai/filter/yaml_front_matter_filter.rb
new file mode 100644
index 00000000000..e4e2f3f228d
--- /dev/null
+++ b/lib/banzai/filter/yaml_front_matter_filter.rb
@@ -0,0 +1,28 @@
+require 'html/pipeline/filter'
+require 'yaml'
+
+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
new file mode 100644
index 00000000000..50dc978b452
--- /dev/null
+++ b/lib/banzai/pipeline/pre_process_pipeline.rb
@@ -0,0 +1,17 @@
+module Banzai
+ module Pipeline
+ class PreProcessPipeline < BasePipeline
+ def self.filters
+ FilterArray[
+ Filter::YamlFrontMatterFilter
+ ]
+ end
+
+ def self.transform_context(context)
+ context.merge(
+ pre_process: true
+ )
+ end
+ end
+ end
+end
diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb
index 891c0fd7749..ae714c87dc5 100644
--- a/lib/banzai/renderer.rb
+++ b/lib/banzai/renderer.rb
@@ -31,6 +31,12 @@ module Banzai
Pipeline[context[:pipeline]].call(text, context)
end
+ def self.pre_process(text, context)
+ pipeline = Pipeline[:pre_process]
+
+ pipeline.to_html(text, context)
+ end
+
# Perform post-processing on an HTML String
#
# This method is used to perform state-dependent changes to a String of
diff --git a/spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb b/spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb
new file mode 100644
index 00000000000..fe70eada7eb
--- /dev/null
+++ b/spec/lib/banzai/filter/yaml_front_matter_filter_spec.rb
@@ -0,0 +1,53 @@
+require 'rails_helper'
+
+describe Banzai::Filter::YamlFrontMatterFilter, lib: true 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