diff options
author | Robert Speicher <robert@gitlab.com> | 2016-07-10 20:30:41 +0000 |
---|---|---|
committer | Robert Speicher <robert@gitlab.com> | 2016-07-10 20:30:41 +0000 |
commit | e90a9b0159611195a512811517bb9d6237c8ffab (patch) | |
tree | e61a546339e2f8eb4943d975f11ad307808b4d2b | |
parent | 1a9adb2d34fc6e59785f2854ecfe5f8ac87a8386 (diff) | |
parent | 6ba884530f6d1132621e1050175ab3384ebdcbb5 (diff) | |
download | gitlab-ce-e90a9b0159611195a512811517bb9d6237c8ffab.tar.gz |
Merge branch 'blockquote-fence-filter' into 'master'
Add blockquote fence syntax to Markdown
Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/16564
Before Markdown rendering happens, this will transform this:
```
Let me quote this here email:
>>>
Dear friend,
How are you?
Greetings,
Me
>>>
```
Into this, saving me from having to prefix all of those lines with `>` manually when I copy some multiline text from another medium:
```
Let me quote this here email:
> Dear friend,
>
> How are you?
>
> Greetings,
>
> Me
```
See merge request !3954
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | doc/markdown/markdown.md | 34 | ||||
-rw-r--r-- | lib/banzai/filter/blockquote_fence_filter.rb | 71 | ||||
-rw-r--r-- | lib/banzai/pipeline/pre_process_pipeline.rb | 3 | ||||
-rw-r--r-- | spec/fixtures/blockquote_fence_after.md | 115 | ||||
-rw-r--r-- | spec/fixtures/blockquote_fence_before.md | 131 | ||||
-rw-r--r-- | spec/lib/banzai/filter/blockquote_fence_filter_spec.rb | 14 |
7 files changed, 367 insertions, 2 deletions
diff --git a/CHANGELOG b/CHANGELOG index 3188ff68f56..0eb7595fbfa 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -18,6 +18,7 @@ v 8.10.0 (unreleased) - Fix MR-auto-close text added to description. !4836 - Fix issue, preventing users w/o push access to sort tags !5105 (redetection) - Add Spring EmojiOne updates. + - Add syntax for multiline blockquote using `>>>` fence !3954 - Fix viewing notification settings when a project is pending deletion - Fix pagination when sorting by columns with lots of ties (like priority) - The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020 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..d2c4b1e4d76 --- /dev/null +++ b/lib/banzai/filter/blockquote_fence_filter.rb @@ -0,0 +1,71 @@ +module Banzai + module Filter + class BlockquoteFenceFilter < HTML::Pipeline::TextFilter + REGEX = %r{ + (?<code> + # Code blocks: + # ``` + # Anything, including `>>>` blocks which are ignored by this filter + # ``` + + ^``` + .+? + \n```$ + ) + | + (?<html> + # HTML block: + # <tag> + # Anything, including `>>>` blocks which are ignored by this filter + # </tag> + + ^<[^>]+?>\n + .+? + \n<\/[^>]+?>$ + ) + | + (?: + # Blockquote: + # >>> + # Anything, including code and HTML blocks + # >>> + + ^>>>\n + (?<quote> + (?: + # Any character that doesn't introduce a code or HTML block + (?! + ^``` + | + ^<[^>]+?>\n + ) + . + | + # A code block + \g<code> + | + # An HTML block + \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..2652a842c0e --- /dev/null +++ b/spec/fixtures/blockquote_fence_after.md @@ -0,0 +1,115 @@ +Single `>>>` inside code block: + +``` +# Code +>>> +# Code +``` + +Double `>>>` inside code block: + +```txt +# 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..d52eec72896 --- /dev/null +++ b/spec/fixtures/blockquote_fence_before.md @@ -0,0 +1,131 @@ +Single `>>>` inside code block: + +``` +# Code +>>> +# Code +``` + +Double `>>>` inside code block: + +```txt +# 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..2799249ae3e --- /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 'converts 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 |