From 6a477b9bfc5bf9b32c9a961269066694d1216dce Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 27 Apr 2016 23:38:33 +0200 Subject: [PATCH] Add blockquote fence syntax to Markdown --- doc/markdown/markdown.md | 34 ++++- lib/banzai/filter/blockquote_fence_filter.rb | 50 +++++++ lib/banzai/pipeline/pre_process_pipeline.rb | 3 +- spec/fixtures/blockquote_fence_after.md | 115 +++++++++++++++ spec/fixtures/blockquote_fence_before.md | 131 ++++++++++++++++++ .../filter/blockquote_fence_filter_spec.rb | 14 ++ 6 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 lib/banzai/filter/blockquote_fence_filter.rb create mode 100644 spec/fixtures/blockquote_fence_after.md create mode 100644 spec/fixtures/blockquote_fence_before.md create mode 100644 spec/lib/banzai/filter/blockquote_fence_filter_spec.rb diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index 236eb7b12c4..fb2dd582754 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -7,11 +7,12 @@ * [Newlines](#newlines) * [Multiple underscores in words](#multiple-underscores-in-words) * [URL auto-linking](#url-auto-linking) +* [Multiline Blockquote](#multiline-blockquote) * [Code and Syntax Highlighting](#code-and-syntax-highlighting) * [Inline Diff](#inline-diff) * [Emoji](#emoji) * [Special GitLab references](#special-gitlab-references) -* [Task lists](#task-lists) +* [Task Lists](#task-lists) **[Standard Markdown](#standard-markdown)** @@ -89,6 +90,37 @@ GFM will autolink almost any URL you copy and paste into your text. * irc://irc.freenode.net/gitlab * http://localhost:3000 +## Multiline Blockquote + +On top of standard Markdown [blockquotes](#blockquotes), which require prepending `>` to quoted lines, +GFM supports multiline blockquotes fenced by >>>. + +```no-highlight +>>> +If you paste a message from somewhere else + +that + +spans + +multiple lines, + +you can quote that without having to manually prepend `>` to every line! +>>> +``` + +>>> +If you paste a message from somewhere else + +that + +spans + +multiple lines, + +you can quote that without having to manually prepend `>` to every line! +>>> + ## Code and Syntax Highlighting _GitLab uses the [Rouge Ruby library][rouge] for syntax highlighting. For a diff --git a/lib/banzai/filter/blockquote_fence_filter.rb b/lib/banzai/filter/blockquote_fence_filter.rb new file mode 100644 index 00000000000..fb815c2d837 --- /dev/null +++ b/lib/banzai/filter/blockquote_fence_filter.rb @@ -0,0 +1,50 @@ +module Banzai + module Filter + class BlockquoteFenceFilter < HTML::Pipeline::TextFilter + REGEX = %r{ + (? + # Code blocks: + # ``` + # Anything, including ignored `>>>` blocks + # ``` + ^```.+?\n```$ + ) + | + (? + # HTML: + # + # Anything, including ignored `>>>` blocks + # + ^<[^>]+?>.+?\n<\/[^>]+?>$ + ) + | + ( + ^>>>\n(? + (?: + (?!^```|^<[^>]+?>). + | + \g + | + \g + ) + +?)\n>>>$ + ) + }mx.freeze + + def initialize(text, context = nil, result = nil) + super text, context, result + @text = @text.delete "\r" + end + + def call + @text.gsub(REGEX) do + if $~[:quote] + $~[:quote].gsub(/^/, "> ").gsub(/^> $/, ">") + else + $~[0] + end + end + end + end + end +end diff --git a/lib/banzai/pipeline/pre_process_pipeline.rb b/lib/banzai/pipeline/pre_process_pipeline.rb index 50dc978b452..6cf219661d3 100644 --- a/lib/banzai/pipeline/pre_process_pipeline.rb +++ b/lib/banzai/pipeline/pre_process_pipeline.rb @@ -3,7 +3,8 @@ module Banzai class PreProcessPipeline < BasePipeline def self.filters FilterArray[ - Filter::YamlFrontMatterFilter + Filter::YamlFrontMatterFilter, + Filter::BlockquoteFenceFilter, ] end diff --git a/spec/fixtures/blockquote_fence_after.md b/spec/fixtures/blockquote_fence_after.md new file mode 100644 index 00000000000..5ab136f76c3 --- /dev/null +++ b/spec/fixtures/blockquote_fence_after.md @@ -0,0 +1,115 @@ +Single `>>>` inside code block: + +``` +# Code +>>> +# Code +``` + +Double `>>>` inside code block: + +``` +# Code +>>> +# Code +>>> +# Code +``` + +Blockquote outside code block: + +> Quote + +Code block inside blockquote: + +> Quote +> +> ``` +> # Code +> ``` +> +> Quote + +Single `>>>` inside code block inside blockquote: + +> Quote +> +> ``` +> # Code +> >>> +> # Code +> ``` +> +> Quote + +Double `>>>` inside code block inside blockquote: + +> Quote +> +> ``` +> # Code +> >>> +> # Code +> >>> +> # Code +> ``` +> +> Quote + +Single `>>>` inside HTML: + +
+# Code
+>>>
+# Code
+
+ +Double `>>>` inside HTML: + +
+# Code
+>>>
+# Code
+>>>
+# Code
+
+ +Blockquote outside HTML: + +> Quote + +HTML inside blockquote: + +> Quote +> +>
+> # Code
+> 
+> +> Quote + +Single `>>>` inside HTML inside blockquote: + +> Quote +> +>
+> # Code
+> >>>
+> # Code
+> 
+> +> Quote + +Double `>>>` inside HTML inside blockquote: + +> Quote +> +>
+> # Code
+> >>>
+> # Code
+> >>>
+> # Code
+> 
+> +> Quote diff --git a/spec/fixtures/blockquote_fence_before.md b/spec/fixtures/blockquote_fence_before.md new file mode 100644 index 00000000000..e6689b6c5dd --- /dev/null +++ b/spec/fixtures/blockquote_fence_before.md @@ -0,0 +1,131 @@ +Single `>>>` inside code block: + +``` +# Code +>>> +# Code +``` + +Double `>>>` inside code block: + +``` +# Code +>>> +# Code +>>> +# Code +``` + +Blockquote outside code block: + +>>> +Quote +>>> + +Code block inside blockquote: + +>>> +Quote + +``` +# Code +``` + +Quote +>>> + +Single `>>>` inside code block inside blockquote: + +>>> +Quote + +``` +# Code +>>> +# Code +``` + +Quote +>>> + +Double `>>>` inside code block inside blockquote: + +>>> +Quote + +``` +# Code +>>> +# Code +>>> +# Code +``` + +Quote +>>> + +Single `>>>` inside HTML: + +
+# Code
+>>>
+# Code
+
+ +Double `>>>` inside HTML: + +
+# Code
+>>>
+# Code
+>>>
+# Code
+
+ +Blockquote outside HTML: + +>>> +Quote +>>> + +HTML inside blockquote: + +>>> +Quote + +
+# Code
+
+ +Quote +>>> + +Single `>>>` inside HTML inside blockquote: + +>>> +Quote + +
+# Code
+>>>
+# Code
+
+ +Quote +>>> + +Double `>>>` inside HTML inside blockquote: + +>>> +Quote + +
+# Code
+>>>
+# Code
+>>>
+# Code
+
+ +Quote +>>> diff --git a/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb new file mode 100644 index 00000000000..19543bde838 --- /dev/null +++ b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb @@ -0,0 +1,14 @@ +require 'rails_helper' + +describe Banzai::Filter::BlockquoteFenceFilter, lib: true do + include FilterSpecHelper + + it 'convers blockquote fences to blockquote lines' do + content = File.read(Rails.root.join('spec/fixtures/blockquote_fence_before.md')) + expected = File.read(Rails.root.join('spec/fixtures/blockquote_fence_after.md')) + + output = filter(content) + + expect(output).to eq(expected) + end +end