Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-01-20 12:16:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-01-20 12:16:11 +0300
commitedaa33dee2ff2f7ea3fac488d41558eb5f86d68c (patch)
tree11f143effbfeba52329fb7afbd05e6e2a3790241 /spec/lib/banzai
parentd8a5691316400a0f7ec4f83832698f1988eb27c1 (diff)
Add latest changes from gitlab-org/gitlab@14-7-stable-eev14.7.0-rc42
Diffstat (limited to 'spec/lib/banzai')
-rw-r--r--spec/lib/banzai/filter/footnote_filter_spec.rb46
-rw-r--r--spec/lib/banzai/filter/markdown_filter_spec.rb153
-rw-r--r--spec/lib/banzai/filter/plantuml_filter_spec.rb72
-rw-r--r--spec/lib/banzai/filter/references/issue_reference_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb5
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb47
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb238
-rw-r--r--spec/lib/banzai/pipeline/full_pipeline_spec.rb41
-rw-r--r--spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb156
-rw-r--r--spec/lib/banzai/reference_parser/merge_request_parser_spec.rb8
10 files changed, 243 insertions, 525 deletions
diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb
index d41f5e8633d..5ac7d3af733 100644
--- a/spec/lib/banzai/filter/footnote_filter_spec.rb
+++ b/spec/lib/banzai/filter/footnote_filter_spec.rb
@@ -56,52 +56,6 @@ RSpec.describe Banzai::Filter::FootnoteFilter do
it 'properly adds the necessary ids and classes' do
expect(doc.to_html).to eq filtered_footnote.strip
end
-
- context 'using ruby-based HTML renderer' do
- # first[^1] and second[^second]
- # [^1]: one
- # [^second]: two
- let(:footnote) do
- <<~EOF
- <p>first<sup><a href="#fn1" id="fnref1">1</a></sup> and second<sup><a href="#fn2" id="fnref2">2</a></sup></p>
- <p>same reference<sup><a href="#fn1" id="fnref1">1</a></sup></p>
- <ol>
- <li id="fn1">
- <p>one <a href="#fnref1">↩</a></p>
- </li>
- <li id="fn2">
- <p>two <a href="#fnref2">↩</a></p>
- </li>
- </ol>
- EOF
- end
-
- let(:filtered_footnote) do
- <<~EOF
- <p>first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup></p>
- <p>same reference<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup></p>
- <section class="footnotes"><ol>
- <li id="fn1-#{identifier}">
- <p>one <a href="#fnref1-#{identifier}" class="footnote-backref">↩</a></p>
- </li>
- <li id="fn2-#{identifier}">
- <p>two <a href="#fnref2-#{identifier}" class="footnote-backref">↩</a></p>
- </li>
- </ol></section>
- EOF
- end
-
- let(:doc) { filter(footnote) }
- let(:identifier) { link_node[:id].delete_prefix('fnref1-') }
-
- before do
- stub_feature_flags(use_cmark_renderer: false)
- end
-
- it 'properly adds the necessary ids and classes' do
- expect(doc.to_html).to eq filtered_footnote
- end
- end
end
context 'when detecting footnotes' do
diff --git a/spec/lib/banzai/filter/markdown_filter_spec.rb b/spec/lib/banzai/filter/markdown_filter_spec.rb
index 1c9b894e885..e3c8d121587 100644
--- a/spec/lib/banzai/filter/markdown_filter_spec.rb
+++ b/spec/lib/banzai/filter/markdown_filter_spec.rb
@@ -5,125 +5,90 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::MarkdownFilter do
include FilterSpecHelper
- shared_examples_for 'renders correct markdown' do
- describe 'markdown engine from context' do
- it 'defaults to CommonMark' do
- expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
- expect(instance).to receive(:render).and_return('test')
- end
-
- filter('test')
+ describe 'markdown engine from context' do
+ it 'defaults to CommonMark' do
+ expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
+ expect(instance).to receive(:render).and_return('test')
end
- it 'uses CommonMark' do
- expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
- expect(instance).to receive(:render).and_return('test')
- end
+ filter('test')
+ end
- filter('test', { markdown_engine: :common_mark })
+ it 'uses CommonMark' do
+ expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
+ expect(instance).to receive(:render).and_return('test')
end
+
+ filter('test', { markdown_engine: :common_mark })
end
+ end
- describe 'code block' do
- context 'using CommonMark' do
- before do
- stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
- end
-
- it 'adds language to lang attribute when specified' do
- result = filter("```html\nsome code\n```", no_sourcepos: true)
-
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- expect(result).to start_with('<pre lang="html"><code>')
- else
- expect(result).to start_with('<pre><code lang="html">')
- end
- end
-
- it 'does not add language to lang attribute when not specified' do
- result = filter("```\nsome code\n```", no_sourcepos: true)
-
- expect(result).to start_with('<pre><code>')
- end
-
- it 'works with utf8 chars in language' do
- result = filter("```日\nsome code\n```", no_sourcepos: true)
-
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- expect(result).to start_with('<pre lang="日"><code>')
- else
- expect(result).to start_with('<pre><code lang="日">')
- end
- end
-
- it 'works with additional language parameters' do
- result = filter("```ruby:red gem foo\nsome code\n```", no_sourcepos: true)
-
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- expect(result).to start_with('<pre lang="ruby:red" data-meta="gem foo"><code>')
- else
- expect(result).to start_with('<pre><code lang="ruby:red gem foo">')
- end
- end
+ describe 'code block' do
+ context 'using CommonMark' do
+ before do
+ stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
end
- end
- describe 'source line position' do
- context 'using CommonMark' do
- before do
- stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
- end
+ it 'adds language to lang attribute when specified' do
+ result = filter("```html\nsome code\n```", no_sourcepos: true)
- it 'defaults to add data-sourcepos' do
- result = filter('test')
+ expect(result).to start_with('<pre lang="html"><code>')
+ end
- expect(result).to eq '<p data-sourcepos="1:1-1:4">test</p>'
- end
+ it 'does not add language to lang attribute when not specified' do
+ result = filter("```\nsome code\n```", no_sourcepos: true)
- it 'disables data-sourcepos' do
- result = filter('test', no_sourcepos: true)
+ expect(result).to start_with('<pre><code>')
+ end
+
+ it 'works with utf8 chars in language' do
+ result = filter("```日\nsome code\n```", no_sourcepos: true)
- expect(result).to eq '<p>test</p>'
- end
+ expect(result).to start_with('<pre lang="日"><code>')
+ end
+
+ it 'works with additional language parameters' do
+ result = filter("```ruby:red gem foo\nsome code\n```", no_sourcepos: true)
+
+ expect(result).to start_with('<pre lang="ruby:red" data-meta="gem foo"><code>')
end
end
+ end
- describe 'footnotes in tables' do
- it 'processes footnotes in table cells' do
- text = <<-MD.strip_heredoc
- | Column1 |
- | --------- |
- | foot [^1] |
+ describe 'source line position' do
+ context 'using CommonMark' do
+ before do
+ stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
+ end
- [^1]: a footnote
- MD
+ it 'defaults to add data-sourcepos' do
+ result = filter('test')
- result = filter(text, no_sourcepos: true)
+ expect(result).to eq '<p data-sourcepos="1:1-1:4">test</p>'
+ end
- expect(result).to include('<td>foot <sup')
+ it 'disables data-sourcepos' do
+ result = filter('test', no_sourcepos: true)
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- expect(result).to include('<section class="footnotes" data-footnotes>')
- else
- expect(result).to include('<section class="footnotes">')
- end
+ expect(result).to eq '<p>test</p>'
end
end
end
- context 'using ruby-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: false)
- end
+ describe 'footnotes in tables' do
+ it 'processes footnotes in table cells' do
+ text = <<-MD.strip_heredoc
+ | Column1 |
+ | --------- |
+ | foot [^1] |
- it_behaves_like 'renders correct markdown'
- end
+ [^1]: a footnote
+ MD
- context 'using c-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: true)
- end
+ result = filter(text, no_sourcepos: true)
- it_behaves_like 'renders correct markdown'
+ expect(result).to include('<td>foot <sup')
+ expect(result).to include('<section class="footnotes" data-footnotes>')
+ end
end
end
diff --git a/spec/lib/banzai/filter/plantuml_filter_spec.rb b/spec/lib/banzai/filter/plantuml_filter_spec.rb
index e1e02c09fbe..2d1a01116e0 100644
--- a/spec/lib/banzai/filter/plantuml_filter_spec.rb
+++ b/spec/lib/banzai/filter/plantuml_filter_spec.rb
@@ -5,67 +5,33 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::PlantumlFilter do
include FilterSpecHelper
- shared_examples_for 'renders correct markdown' do
- it 'replaces plantuml pre tag with img tag' do
- stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
+ it 'replaces plantuml pre tag with img tag' do
+ stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
- input = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
- else
- '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
- end
+ input = '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ output = '<div class="imageblock"><div class="content"><img class="plantuml" src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq"></div></div>'
+ doc = filter(input)
- output = '<div class="imageblock"><div class="content"><img class="plantuml" src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq"></div></div>'
- doc = filter(input)
-
- expect(doc.to_s).to eq output
- end
-
- it 'does not replace plantuml pre tag with img tag if disabled' do
- stub_application_setting(plantuml_enabled: false)
-
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- input = '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
- output = '<pre lang="plantuml"><code>Bob -&gt; Sara : Hello</code></pre>'
- else
- input = '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
- output = '<pre><code lang="plantuml">Bob -&gt; Sara : Hello</code></pre>'
- end
-
- doc = filter(input)
-
- expect(doc.to_s).to eq output
- end
-
- it 'does not replace plantuml pre tag with img tag if url is invalid' do
- stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid")
+ expect(doc.to_s).to eq output
+ end
- input = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
- else
- '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
- end
+ it 'does not replace plantuml pre tag with img tag if disabled' do
+ stub_application_setting(plantuml_enabled: false)
- output = '<div class="listingblock"><div class="content"><pre class="plantuml plantuml-error"> Error: cannot connect to PlantUML server at "invalid"</pre></div></div>'
- doc = filter(input)
+ input = '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ output = '<pre lang="plantuml"><code>Bob -&gt; Sara : Hello</code></pre>'
+ doc = filter(input)
- expect(doc.to_s).to eq output
- end
+ expect(doc.to_s).to eq output
end
- context 'using ruby-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: false)
- end
-
- it_behaves_like 'renders correct markdown'
- end
+ it 'does not replace plantuml pre tag with img tag if url is invalid' do
+ stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid")
- context 'using c-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: true)
- end
+ input = '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ output = '<div class="listingblock"><div class="content"><pre class="plantuml plantuml-error"> Error: cannot connect to PlantUML server at "invalid"</pre></div></div>'
+ doc = filter(input)
- it_behaves_like 'renders correct markdown'
+ expect(doc.to_s).to eq output
end
end
diff --git a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
index 14c1542b724..b3523a25116 100644
--- a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
@@ -122,6 +122,7 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter do
expect(link).to have_attribute('data-reference-format')
expect(link.attr('data-reference-format')).to eq('+')
+ expect(link.attr('href')).to eq(issue_url)
end
it 'includes a data-reference-format attribute for URL references' do
@@ -130,6 +131,7 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter do
expect(link).to have_attribute('data-reference-format')
expect(link.attr('data-reference-format')).to eq('+')
+ expect(link.attr('href')).to eq(issue_url)
end
it 'supports an :only_path context' do
diff --git a/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb b/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
index 3c488820853..e5809ac6949 100644
--- a/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
@@ -51,6 +51,7 @@ RSpec.describe Banzai::Filter::References::MergeRequestReferenceFilter do
context 'internal reference' do
let(:reference) { merge.to_reference }
+ let(:merge_request_url) { urls.project_merge_request_url(project, merge) }
it 'links to a valid reference' do
doc = reference_filter("See #{reference}")
@@ -115,14 +116,16 @@ RSpec.describe Banzai::Filter::References::MergeRequestReferenceFilter do
expect(link).to have_attribute('data-reference-format')
expect(link.attr('data-reference-format')).to eq('+')
+ expect(link.attr('href')).to eq(merge_request_url)
end
it 'includes a data-reference-format attribute for URL references' do
- doc = reference_filter("Merge #{urls.project_merge_request_url(project, merge)}+")
+ doc = reference_filter("Merge #{merge_request_url}+")
link = doc.css('a').first
expect(link).to have_attribute('data-reference-format')
expect(link.attr('data-reference-format')).to eq('+')
+ expect(link.attr('href')).to eq(merge_request_url)
end
it 'supports an :only_path context' do
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index 24e787bddd5..039ca36af6e 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -177,53 +177,6 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
expect(act.to_html).to eq exp
end
end
-
- context 'using ruby-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: false)
- end
-
- it 'allows correct footnote id property on links' do
- exp = %q(<a href="#fn1" id="fnref1">foo/bar.md</a>)
- act = filter(exp)
-
- expect(act.to_html).to eq exp
- end
-
- it 'allows correct footnote id property on li element' do
- exp = %q(<ol><li id="fn1">footnote</li></ol>)
- act = filter(exp)
-
- expect(act.to_html).to eq exp
- end
-
- it 'removes invalid id for footnote links' do
- exp = %q(<a href="#fn1">link</a>)
-
- %w[fnrefx test xfnref1].each do |id|
- act = filter(%(<a href="#fn1" id="#{id}">link</a>))
-
- expect(act.to_html).to eq exp
- end
- end
-
- it 'removes invalid id for footnote li' do
- exp = %q(<ol><li>footnote</li></ol>)
-
- %w[fnx test xfn1].each do |id|
- act = filter(%(<ol><li id="#{id}">footnote</li></ol>))
-
- expect(act.to_html).to eq exp
- end
- end
-
- it 'allows footnotes numbered higher than 9' do
- exp = %q(<a href="#fn15" id="fnref15">link</a><ol><li id="fn15">footnote</li></ol>)
- act = filter(exp)
-
- expect(act.to_html).to eq exp
- end
- end
end
end
end
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index ef46fd62486..aee4bd93207 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -19,202 +19,150 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
end
end
- shared_examples_for 'renders correct markdown' do
- context "when no language is specified" do
- it "highlights as plaintext" do
- result = filter('<pre><code>def fun end</code></pre>')
+ context "when no language is specified" do
+ it "highlights as plaintext" do
+ result = filter('<pre><code>def fun end</code></pre>')
- expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre><copy-code></copy-code></div>')
- end
-
- include_examples "XSS prevention", ""
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre><copy-code></copy-code></div>')
end
- context "when contains mermaid diagrams" do
- it "ignores mermaid blocks" do
- result = filter('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
+ include_examples "XSS prevention", ""
+ end
- expect(result.to_html).to eq('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
- end
+ context "when contains mermaid diagrams" do
+ it "ignores mermaid blocks" do
+ result = filter('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
+
+ expect(result.to_html).to eq('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
end
+ end
- context "when a valid language is specified" do
- it "highlights as that language" do
- result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- filter('<pre lang="ruby"><code>def fun end</code></pre>')
- else
- filter('<pre><code lang="ruby">def fun end</code></pre>')
- end
+ context "when <pre> contains multiple <code> tags" do
+ it "ignores the block" do
+ result = filter('<pre><code>one</code> and <code>two</code></pre>')
- expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre><copy-code></copy-code></div>')
- end
+ expect(result.to_html).to eq('<pre><code>one</code> and <code>two</code></pre>')
+ end
+ end
- include_examples "XSS prevention", "ruby"
+ context "when a valid language is specified" do
+ it "highlights as that language" do
+ result = filter('<pre lang="ruby"><code>def fun end</code></pre>')
+
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="k">def</span> <span class="nf">fun</span> <span class="k">end</span></span></code></pre><copy-code></copy-code></div>')
end
- context "when an invalid language is specified" do
- it "highlights as plaintext" do
- result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- filter('<pre lang="gnuplot"><code>This is a test</code></pre>')
- else
- filter('<pre><code lang="gnuplot">This is a test</code></pre>')
- end
+ include_examples "XSS prevention", "ruby"
+ end
- expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
- end
+ context "when an invalid language is specified" do
+ it "highlights as plaintext" do
+ result = filter('<pre lang="gnuplot"><code>This is a test</code></pre>')
- include_examples "XSS prevention", "gnuplot"
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
end
- context "languages that should be passed through" do
- let(:delimiter) { described_class::LANG_PARAMS_DELIMITER }
- let(:data_attr) { described_class::LANG_PARAMS_ATTR }
+ include_examples "XSS prevention", "gnuplot"
+ end
- %w(math mermaid plantuml suggestion).each do |lang|
- context "when #{lang} is specified" do
- it "highlights as plaintext but with the correct language attribute and class" do
- result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- filter(%{<pre lang="#{lang}"><code>This is a test</code></pre>})
- else
- filter(%{<pre><code lang="#{lang}">This is a test</code></pre>})
- end
+ context "languages that should be passed through" do
+ let(:delimiter) { described_class::LANG_PARAMS_DELIMITER }
+ let(:data_attr) { described_class::LANG_PARAMS_ATTR }
- expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
- end
+ %w(math mermaid plantuml suggestion).each do |lang|
+ context "when #{lang} is specified" do
+ it "highlights as plaintext but with the correct language attribute and class" do
+ result = filter(%{<pre lang="#{lang}"><code>This is a test</code></pre>})
- include_examples "XSS prevention", lang
+ expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
end
- context "when #{lang} has extra params" do
- let(:lang_params) { 'foo-bar-kux' }
-
- let(:xss_lang) do
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- "#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
- else
- "#{lang}#{described_class::LANG_PARAMS_DELIMITER}&lt;script&gt;alert(1)&lt;/script&gt;"
- end
- end
-
- it "includes data-lang-params tag with extra information" do
- result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- filter(%{<pre lang="#{lang}" data-meta="#{lang_params}"><code>This is a test</code></pre>})
- else
- filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}">This is a test</code></pre>})
- end
-
- expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
- end
-
- include_examples "XSS prevention", lang
-
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- include_examples "XSS prevention",
- "#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
- else
- include_examples "XSS prevention",
- "#{lang}#{described_class::LANG_PARAMS_DELIMITER}&lt;script&gt;alert(1)&lt;/script&gt;"
- end
-
- include_examples "XSS prevention",
- "#{lang} data-meta=\"foo-bar-kux\"<script>alert(1)</script>"
- end
+ include_examples "XSS prevention", lang
end
- context 'when multiple param delimiters are used' do
- let(:lang) { 'suggestion' }
- let(:lang_params) { '-1+10' }
+ context "when #{lang} has extra params" do
+ let(:lang_params) { 'foo-bar-kux' }
+ let(:xss_lang) { "#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;" }
- let(:expected_result) do
- %{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params} more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>}
- end
-
- context 'when delimiter is space' do
- it 'delimits on the first appearance' do
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- result = filter(%{<pre lang="#{lang}" data-meta="#{lang_params} more-things"><code>This is a test</code></pre>})
+ it "includes data-lang-params tag with extra information" do
+ result = filter(%{<pre lang="#{lang}" data-meta="#{lang_params}"><code>This is a test</code></pre>})
- expect(result.to_html.delete("\n")).to eq(expected_result)
- else
- result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}#{delimiter}more-things">This is a test</code></pre>})
-
- expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}#{delimiter}more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
- end
- end
+ expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>})
end
- context 'when delimiter is colon' do
- it 'delimits on the first appearance' do
- result = filter(%{<pre lang="#{lang}#{delimiter}#{lang_params} more-things"><code>This is a test</code></pre>})
+ include_examples "XSS prevention", lang
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- expect(result.to_html.delete("\n")).to eq(expected_result)
- else
- expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code><span id=\"LC1\" class=\"line\" lang=\"plaintext\">This is a test</span></code></pre><copy-code></copy-code></div>})
- end
- end
- end
+ include_examples "XSS prevention",
+ "#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
+
+ include_examples "XSS prevention",
+ "#{lang} data-meta=\"foo-bar-kux\"<script>alert(1)</script>"
end
end
- context "when sourcepos metadata is available" do
- it "includes it in the highlighted code block" do
- result = filter('<pre data-sourcepos="1:1-3:3"><code lang="plaintext">This is a test</code></pre>')
+ context 'when multiple param delimiters are used' do
+ let(:lang) { 'suggestion' }
+ let(:lang_params) { '-1+10' }
- expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
+ let(:expected_result) do
+ %{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params} more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>}
end
- end
- context "when Rouge lexing fails" do
- before do
- allow_next_instance_of(Rouge::Lexers::Ruby) do |instance|
- allow(instance).to receive(:stream_tokens).and_raise(StandardError)
+ context 'when delimiter is space' do
+ it 'delimits on the first appearance' do
+ result = filter(%{<pre lang="#{lang}" data-meta="#{lang_params} more-things"><code>This is a test</code></pre>})
+
+ expect(result.to_html.delete("\n")).to eq(expected_result)
end
end
- it "highlights as plaintext" do
- result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- filter('<pre lang="ruby"><code>This is a test</code></pre>')
- else
- filter('<pre><code lang="ruby">This is a test</code></pre>')
- end
+ context 'when delimiter is colon' do
+ it 'delimits on the first appearance' do
+ result = filter(%{<pre lang="#{lang}#{delimiter}#{lang_params} more-things"><code>This is a test</code></pre>})
- expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight" lang="" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre><copy-code></copy-code></div>')
+ expect(result.to_html.delete("\n")).to eq(expected_result)
+ end
end
-
- include_examples "XSS prevention", "ruby"
end
+ end
- context "when Rouge lexing fails after a retry" do
- before do
- allow_next_instance_of(Rouge::Lexers::PlainText) do |instance|
- allow(instance).to receive(:stream_tokens).and_raise(StandardError)
- end
- end
+ context "when sourcepos metadata is available" do
+ it "includes it in the highlighted code block" do
+ result = filter('<pre data-sourcepos="1:1-3:3"><code lang="plaintext">This is a test</code></pre>')
- it "does not add highlighting classes" do
- result = filter('<pre><code>This is a test</code></pre>')
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre><copy-code></copy-code></div>')
+ end
+ end
- expect(result.to_html).to eq('<pre><code>This is a test</code></pre>')
+ context "when Rouge lexing fails" do
+ before do
+ allow_next_instance_of(Rouge::Lexers::Ruby) do |instance|
+ allow(instance).to receive(:stream_tokens).and_raise(StandardError)
end
+ end
+
+ it "highlights as plaintext" do
+ result = filter('<pre lang="ruby"><code>This is a test</code></pre>')
- include_examples "XSS prevention", "ruby"
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight" lang="" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre><copy-code></copy-code></div>')
end
+
+ include_examples "XSS prevention", "ruby"
end
- context 'using ruby-based HTML renderer' do
+ context "when Rouge lexing fails after a retry" do
before do
- stub_feature_flags(use_cmark_renderer: false)
+ allow_next_instance_of(Rouge::Lexers::PlainText) do |instance|
+ allow(instance).to receive(:stream_tokens).and_raise(StandardError)
+ end
end
- it_behaves_like 'renders correct markdown'
- end
+ it "does not add highlighting classes" do
+ result = filter('<pre><code>This is a test</code></pre>')
- context 'using c-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: true)
+ expect(result.to_html).to eq('<pre><code>This is a test</code></pre>')
end
- it_behaves_like 'renders correct markdown'
+ include_examples "XSS prevention", "ruby"
end
end
diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
index 620b7d97a5b..376edfb99fc 100644
--- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
@@ -65,47 +65,6 @@ RSpec.describe Banzai::Pipeline::FullPipeline do
expect(html.lines.map(&:strip).join("\n")).to eq filtered_footnote.strip
end
-
- context 'using ruby-based HTML renderer' do
- let(:html) { described_class.to_html(footnote_markdown, project: project) }
- let(:identifier) { html[/.*fnref1-(\d+).*/, 1] }
- let(:footnote_markdown) do
- <<~EOF
- first[^1] and second[^second] and twenty[^twenty]
- [^1]: one
- [^second]: two
- [^twenty]: twenty
- EOF
- end
-
- let(:filtered_footnote) do
- <<~EOF
- <p dir="auto">first<sup class="footnote-ref"><a href="#fn1-#{identifier}" id="fnref1-#{identifier}">1</a></sup> and second<sup class="footnote-ref"><a href="#fn2-#{identifier}" id="fnref2-#{identifier}">2</a></sup> and twenty<sup class="footnote-ref"><a href="#fn3-#{identifier}" id="fnref3-#{identifier}">3</a></sup></p>
-
- <section class="footnotes"><ol>
- <li id="fn1-#{identifier}">
- <p>one <a href="#fnref1-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
- </li>
- <li id="fn2-#{identifier}">
- <p>two <a href="#fnref2-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
- </li>
- <li id="fn3-#{identifier}">
- <p>twenty <a href="#fnref3-#{identifier}" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
- </li>
- </ol></section>
- EOF
- end
-
- before do
- stub_feature_flags(use_cmark_renderer: false)
- end
-
- it 'properly adds the necessary ids and classes' do
- stub_commonmark_sourcepos_disabled
-
- expect(html.lines.map(&:strip).join("\n")).to eq filtered_footnote
- end
- end
end
describe 'links are detected as malicious' do
diff --git a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
index c8cd9d4fcac..80392fe264f 100644
--- a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
@@ -5,117 +5,93 @@ require 'spec_helper'
RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
using RSpec::Parameterized::TableSyntax
- shared_examples_for 'renders correct markdown' do
- describe 'CommonMark tests', :aggregate_failures do
- it 'converts all reference punctuation to literals' do
- reference_chars = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS
- markdown = reference_chars.split('').map {|char| char.prepend("\\") }.join
- punctuation = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS.split('')
- punctuation = punctuation.delete_if {|char| char == '&' }
- punctuation << '&amp;'
-
- result = described_class.call(markdown, project: project)
- output = result[:output].to_html
-
- punctuation.each { |char| expect(output).to include("<span>#{char}</span>") }
- expect(result[:escaped_literals]).to be_truthy
- end
+ describe 'backslash escapes', :aggregate_failures do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
- it 'ensure we handle all the GitLab reference characters', :eager_load do
- reference_chars = ObjectSpace.each_object(Class).map do |klass|
- next unless klass.included_modules.include?(Referable)
- next unless klass.respond_to?(:reference_prefix)
- next unless klass.reference_prefix.length == 1
+ it 'converts all reference punctuation to literals' do
+ reference_chars = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS
+ markdown = reference_chars.split('').map {|char| char.prepend("\\") }.join
+ punctuation = Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS.split('')
+ punctuation = punctuation.delete_if {|char| char == '&' }
+ punctuation << '&amp;'
- klass.reference_prefix
- end.compact
+ result = described_class.call(markdown, project: project)
+ output = result[:output].to_html
- reference_chars.all? do |char|
- Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS.include?(char)
- end
- end
+ punctuation.each { |char| expect(output).to include("<span>#{char}</span>") }
+ expect(result[:escaped_literals]).to be_truthy
+ end
- it 'does not convert non-reference punctuation to spans' do
- markdown = %q(\"\'\*\+\,\-\.\/\:\;\<\=\>\?\[\]\_\`\{\|\}) + %q[\(\)\\\\]
+ it 'ensure we handle all the GitLab reference characters', :eager_load do
+ reference_chars = ObjectSpace.each_object(Class).map do |klass|
+ next unless klass.included_modules.include?(Referable)
+ next unless klass.respond_to?(:reference_prefix)
+ next unless klass.reference_prefix.length == 1
- result = described_class.call(markdown, project: project)
- output = result[:output].to_html
+ klass.reference_prefix
+ end.compact
- expect(output).not_to include('<span>')
- expect(result[:escaped_literals]).to be_falsey
+ reference_chars.all? do |char|
+ Banzai::Filter::MarkdownPreEscapeFilter::REFERENCE_CHARACTERS.include?(char)
end
+ end
- it 'does not convert other characters to literals' do
- markdown = %q(\→\A\a\ \3\φ\«)
- expected = '\→\A\a\ \3\φ\«'
-
- result = correct_html_included(markdown, expected)
- expect(result[:escaped_literals]).to be_falsey
- end
+ it 'does not convert non-reference punctuation to spans' do
+ markdown = %q(\"\'\*\+\,\-\.\/\:\;\<\=\>\?\[\]\_\`\{\|\}) + %q[\(\)\\\\]
- describe 'backslash escapes do not work in code blocks, code spans, autolinks, or raw HTML' do
- where(:markdown, :expected) do
- %q(`` \@\! ``) | %q(<code>\@\!</code>)
- %q( \@\!) | %Q(<code>\\@\\!\n</code>)
- %Q(~~~\n\\@\\!\n~~~) | %Q(<code>\\@\\!\n</code>)
- %q(<http://example.com?find=\@>) | %q(<a href="http://example.com?find=%5C@">http://example.com?find=\@</a>)
- %q[<a href="/bar\@)">] | %q[<a href="/bar%5C@)">]
- end
-
- with_them do
- it { correct_html_included(markdown, expected) }
- end
- end
+ result = described_class.call(markdown, project: project)
+ output = result[:output].to_html
- describe 'work in all other contexts, including URLs and link titles, link references, and info strings in fenced code blocks' do
- let(:markdown) { %Q(``` foo\\@bar\nfoo\n```) }
-
- it 'renders correct html' do
- if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
- correct_html_included(markdown, %Q(<pre data-sourcepos="1:1-3:3" lang="foo@bar"><code>foo\n</code></pre>))
- else
- correct_html_included(markdown, %Q(<code lang="foo@bar">foo\n</code>))
- end
- end
-
- where(:markdown, :expected) do
- %q![foo](/bar\@ "\@title")! | %q(<a href="/bar@" title="@title">foo</a>)
- %Q![foo]\n\n[foo]: /bar\\@ "\\@title"! | %q(<a href="/bar@" title="@title">foo</a>)
- end
-
- with_them do
- it { correct_html_included(markdown, expected) }
- end
- end
+ expect(output).not_to include('<span>')
+ expect(result[:escaped_literals]).to be_falsey
end
- end
-
- describe 'backslash escapes' do
- let_it_be(:project) { create(:project, :public) }
- let_it_be(:issue) { create(:issue, project: project) }
-
- def correct_html_included(markdown, expected)
- result = described_class.call(markdown, {})
- expect(result[:output].to_html).to include(expected)
+ it 'does not convert other characters to literals' do
+ markdown = %q(\→\A\a\ \3\φ\«)
+ expected = '\→\A\a\ \3\φ\«'
- result
+ result = correct_html_included(markdown, expected)
+ expect(result[:escaped_literals]).to be_falsey
end
- context 'using ruby-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: false)
+ describe 'backslash escapes do not work in code blocks, code spans, autolinks, or raw HTML' do
+ where(:markdown, :expected) do
+ %q(`` \@\! ``) | %q(<code>\@\!</code>)
+ %q( \@\!) | %Q(<code>\\@\\!\n</code>)
+ %Q(~~~\n\\@\\!\n~~~) | %Q(<code>\\@\\!\n</code>)
+ %q(<http://example.com?find=\@>) | %q(<a href="http://example.com?find=%5C@">http://example.com?find=\@</a>)
+ %q[<a href="/bar\@)">] | %q[<a href="/bar%5C@)">]
end
- it_behaves_like 'renders correct markdown'
+ with_them do
+ it { correct_html_included(markdown, expected) }
+ end
end
- context 'using c-based HTML renderer' do
- before do
- stub_feature_flags(use_cmark_renderer: true)
+ describe 'work in all other contexts, including URLs and link titles, link references, and info strings in fenced code blocks' do
+ let(:markdown) { %Q(``` foo\\@bar\nfoo\n```) }
+
+ it 'renders correct html' do
+ correct_html_included(markdown, %Q(<pre data-sourcepos="1:1-3:3" lang="foo@bar"><code>foo\n</code></pre>))
+ end
+
+ where(:markdown, :expected) do
+ %q![foo](/bar\@ "\@title")! | %q(<a href="/bar@" title="@title">foo</a>)
+ %Q![foo]\n\n[foo]: /bar\\@ "\\@title"! | %q(<a href="/bar@" title="@title">foo</a>)
end
- it_behaves_like 'renders correct markdown'
+ with_them do
+ it { correct_html_included(markdown, expected) }
+ end
end
end
+
+ def correct_html_included(markdown, expected)
+ result = described_class.call(markdown, {})
+
+ expect(result[:output].to_html).to include(expected)
+
+ result
+ end
end
diff --git a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
index 04c35c8b082..3fbda7f3239 100644
--- a/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/merge_request_parser_spec.rb
@@ -23,14 +23,6 @@ RSpec.describe Banzai::ReferenceParser::MergeRequestParser do
end
it_behaves_like "referenced feature visibility", "merge_requests"
-
- context 'when optimize_merge_request_parser feature flag is off' do
- before do
- stub_feature_flags(optimize_merge_request_parser: false)
- end
-
- it_behaves_like "referenced feature visibility", "merge_requests"
- end
end
end