summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/markdown/markdown.md34
-rw-r--r--lib/banzai/filter/blockquote_fence_filter.rb50
-rw-r--r--lib/banzai/pipeline/pre_process_pipeline.rb3
-rw-r--r--spec/fixtures/blockquote_fence_after.md115
-rw-r--r--spec/fixtures/blockquote_fence_before.md131
-rw-r--r--spec/lib/banzai/filter/blockquote_fence_filter_spec.rb14
6 files changed, 345 insertions, 2 deletions
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 <code>>>></code>.
+
+```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>
+ # Code blocks:
+ # ```
+ # Anything, including ignored `>>>` blocks
+ # ```
+ ^```.+?\n```$
+ )
+ |
+ (?<html>
+ # HTML:
+ # <tag>
+ # Anything, including ignored `>>>` blocks
+ # </tag>
+ ^<[^>]+?>.+?\n<\/[^>]+?>$
+ )
+ |
+ (
+ ^>>>\n(?<quote>
+ (?:
+ (?!^```|^<[^>]+?>).
+ |
+ \g<code>
+ |
+ \g<html>
+ )
+ +?)\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:
+
+<pre>
+# Code
+>>>
+# Code
+</pre>
+
+Double `>>>` inside HTML:
+
+<pre>
+# Code
+>>>
+# Code
+>>>
+# Code
+</pre>
+
+Blockquote outside HTML:
+
+> Quote
+
+HTML inside blockquote:
+
+> Quote
+>
+> <pre>
+> # Code
+> </pre>
+>
+> Quote
+
+Single `>>>` inside HTML inside blockquote:
+
+> Quote
+>
+> <pre>
+> # Code
+> >>>
+> # Code
+> </pre>
+>
+> Quote
+
+Double `>>>` inside HTML inside blockquote:
+
+> Quote
+>
+> <pre>
+> # Code
+> >>>
+> # Code
+> >>>
+> # Code
+> </pre>
+>
+> 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:
+
+<pre>
+# Code
+>>>
+# Code
+</pre>
+
+Double `>>>` inside HTML:
+
+<pre>
+# Code
+>>>
+# Code
+>>>
+# Code
+</pre>
+
+Blockquote outside HTML:
+
+>>>
+Quote
+>>>
+
+HTML inside blockquote:
+
+>>>
+Quote
+
+<pre>
+# Code
+</pre>
+
+Quote
+>>>
+
+Single `>>>` inside HTML inside blockquote:
+
+>>>
+Quote
+
+<pre>
+# Code
+>>>
+# Code
+</pre>
+
+Quote
+>>>
+
+Double `>>>` inside HTML inside blockquote:
+
+>>>
+Quote
+
+<pre>
+# Code
+>>>
+# Code
+>>>
+# Code
+</pre>
+
+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