summaryrefslogtreecommitdiff
path: root/spec/lib/banzai/filter
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-11-18 13:16:36 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-11-18 13:16:36 +0000
commit311b0269b4eb9839fa63f80c8d7a58f32b8138a0 (patch)
tree07e7870bca8aed6d61fdcc810731c50d2c40af47 /spec/lib/banzai/filter
parent27909cef6c4170ed9205afa7426b8d3de47cbb0c (diff)
downloadgitlab-ce-311b0269b4eb9839fa63f80c8d7a58f32b8138a0.tar.gz
Add latest changes from gitlab-org/gitlab@14-5-stable-eev14.5.0-rc42
Diffstat (limited to 'spec/lib/banzai/filter')
-rw-r--r--spec/lib/banzai/filter/emoji_filter_spec.rb6
-rw-r--r--spec/lib/banzai/filter/footnote_filter_spec.rb88
-rw-r--r--spec/lib/banzai/filter/markdown_filter_spec.rb153
-rw-r--r--spec/lib/banzai/filter/plantuml_filter_spec.rb73
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb64
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb232
6 files changed, 431 insertions, 185 deletions
diff --git a/spec/lib/banzai/filter/emoji_filter_spec.rb b/spec/lib/banzai/filter/emoji_filter_spec.rb
index cb0b470eaa1..d621f63211b 100644
--- a/spec/lib/banzai/filter/emoji_filter_spec.rb
+++ b/spec/lib/banzai/filter/emoji_filter_spec.rb
@@ -28,9 +28,9 @@ RSpec.describe Banzai::Filter::EmojiFilter do
it 'replaces name versions of trademark, copyright, and registered trademark' do
doc = filter('<p>:tm: :copyright: :registered:</p>')
- expect(doc.css('gl-emoji')[0].text).to eq '™'
- expect(doc.css('gl-emoji')[1].text).to eq '©'
- expect(doc.css('gl-emoji')[2].text).to eq '®'
+ expect(doc.css('gl-emoji')[0].text).to eq '™️'
+ expect(doc.css('gl-emoji')[1].text).to eq '©️'
+ expect(doc.css('gl-emoji')[2].text).to eq '®️'
end
it 'correctly encodes the URL' do
diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb
index 01b7319fab1..54faa748d53 100644
--- a/spec/lib/banzai/filter/footnote_filter_spec.rb
+++ b/spec/lib/banzai/filter/footnote_filter_spec.rb
@@ -5,34 +5,42 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::FootnoteFilter do
include FilterSpecHelper
- # first[^1] and second[^second]
+ # rubocop:disable Style/AsciiComments
+ # first[^1] and second[^second] and third[^_😄_]
# [^1]: one
# [^second]: two
+ # [^_😄_]: three
+ # rubocop:enable Style/AsciiComments
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>
+ <<~EOF.strip_heredoc
+ <p>first<sup><a href="#fn-1" id="fnref-1">1</a></sup> and second<sup><a href="#fn-second" id="fnref-second">2</a></sup> and third<sup><a href="#fn-_%F0%9F%98%84_" id="fnref-_%F0%9F%98%84_">3</a></sup></p>
+
<ol>
- <li id="fn1">
- <p>one <a href="#fnref1">↩</a></p>
+ <li id="fn-1">
+ <p>one <a href="#fnref-1" aria-label="Back to content">↩</a></p>
</li>
- <li id="fn2">
- <p>two <a href="#fnref2">↩</a></p>
+ <li id="fn-second">
+ <p>two <a href="#fnref-second" aria-label="Back to content">↩</a></p>
+ </li>\n<li id="fn-_%F0%9F%98%84_">
+ <p>three <a href="#fnref-_%F0%9F%98%84_" aria-label="Back to content">↩</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>
+ <<~EOF.strip_heredoc
+ <p>first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref="">1</a></sup> and second<sup class="footnote-ref"><a href="#fn-second-#{identifier}" id="fnref-second-#{identifier}" data-footnote-ref="">2</a></sup> and third<sup class="footnote-ref"><a href="#fn-_%F0%9F%98%84_-#{identifier}" id="fnref-_%F0%9F%98%84_-#{identifier}" data-footnote-ref="">3</a></sup></p>
+
+ <section class=\"footnotes\" data-footnotes><ol>
+ <li id="fn-1-#{identifier}">
+ <p>one <a href="#fnref-1-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
+ </li>
+ <li id="fn-second-#{identifier}">
+ <p>two <a href="#fnref-second-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
</li>
- <li id="fn2-#{identifier}">
- <p>two <a href="#fnref2-#{identifier}" class="footnote-backref">↩</a></p>
+ <li id="fn-_%F0%9F%98%84_-#{identifier}">
+ <p>three <a href="#fnref-_%F0%9F%98%84_-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
</li>
</ol></section>
EOF
@@ -41,10 +49,56 @@ RSpec.describe Banzai::Filter::FootnoteFilter do
context 'when footnotes exist' do
let(:doc) { filter(footnote) }
let(:link_node) { doc.css('sup > a').first }
- let(:identifier) { link_node[:id].delete_prefix('fnref1-') }
+ let(:identifier) { link_node[:id].delete_prefix('fnref-1-') }
it 'properly adds the necessary ids and classes' do
expect(doc.to_html).to eq filtered_footnote
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
end
diff --git a/spec/lib/banzai/filter/markdown_filter_spec.rb b/spec/lib/banzai/filter/markdown_filter_spec.rb
index c5e84a0c1e7..a310de5c015 100644
--- a/spec/lib/banzai/filter/markdown_filter_spec.rb
+++ b/spec/lib/banzai/filter/markdown_filter_spec.rb
@@ -5,90 +5,125 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::MarkdownFilter do
include FilterSpecHelper
- 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')
+ 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')
end
- filter('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
- it 'uses CommonMark' do
- expect_next_instance_of(Banzai::Filter::MarkdownEngines::CommonMark) do |instance|
- expect(instance).to receive(:render).and_return('test')
+ filter('test', { markdown_engine: :common_mark })
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)
+ 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)
+ 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)
+ 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)
+ 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
end
+ end
- it 'adds language to lang attribute when specified' do
- result = filter("```html\nsome code\n```", no_sourcepos: true)
-
- expect(result).to start_with('<pre><code lang="html">')
- 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
+ describe 'source line position' do
+ context 'using CommonMark' do
+ before do
+ stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
+ end
- it 'works with utf8 chars in language' do
- result = filter("```日\nsome code\n```", no_sourcepos: true)
+ it 'defaults to add data-sourcepos' do
+ result = filter('test')
- expect(result).to start_with('<pre><code lang="日">')
- end
+ expect(result).to eq '<p data-sourcepos="1:1-1:4">test</p>'
+ end
- it 'works with additional language parameters' do
- result = filter("```ruby:red gem\nsome code\n```", no_sourcepos: true)
+ it 'disables data-sourcepos' do
+ result = filter('test', no_sourcepos: true)
- expect(result).to start_with('<pre><code lang="ruby:red gem">')
+ expect(result).to eq '<p>test</p>'
+ end
end
end
- end
- describe 'source line position' do
- context 'using CommonMark' do
- before do
- stub_const('Banzai::Filter::MarkdownFilter::DEFAULT_ENGINE', :common_mark)
- end
+ describe 'footnotes in tables' do
+ it 'processes footnotes in table cells' do
+ text = <<-MD.strip_heredoc
+ | Column1 |
+ | --------- |
+ | foot [^1] |
- it 'defaults to add data-sourcepos' do
- result = filter('test')
+ [^1]: a footnote
+ MD
- expect(result).to eq '<p data-sourcepos="1:1-1:4">test</p>'
- end
+ result = filter(text, no_sourcepos: true)
- it 'disables data-sourcepos' do
- result = filter('test', no_sourcepos: true)
+ expect(result).to include('<td>foot <sup')
- expect(result).to eq '<p>test</p>'
+ if Feature.enabled?(:use_cmark_renderer)
+ expect(result).to include('<section class="footnotes" data-footnotes>')
+ else
+ expect(result).to include('<section class="footnotes">')
+ end
end
end
end
- describe 'footnotes in tables' do
- it 'processes footnotes in table cells' do
- text = <<-MD.strip_heredoc
- | Column1 |
- | --------- |
- | foot [^1] |
-
- [^1]: a footnote
- MD
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
- result = filter(text, no_sourcepos: true)
+ it_behaves_like 'renders correct markdown'
+ end
- expect(result).to include('<td>foot <sup')
- expect(result).to include('<section class="footnotes">')
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
end
+
+ it_behaves_like 'renders correct markdown'
end
end
diff --git a/spec/lib/banzai/filter/plantuml_filter_spec.rb b/spec/lib/banzai/filter/plantuml_filter_spec.rb
index 5ad94c74514..d1a3b5689a8 100644
--- a/spec/lib/banzai/filter/plantuml_filter_spec.rb
+++ b/spec/lib/banzai/filter/plantuml_filter_spec.rb
@@ -5,30 +5,67 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::PlantumlFilter do
include FilterSpecHelper
- it 'replaces plantuml pre tag with img tag' do
- stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
- input = '<pre><code lang="plantuml">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)
+ 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")
- expect(doc.to_s).to eq output
+ input = if Feature.enabled?(:use_cmark_renderer)
+ '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ else
+ '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
+ end
+
+ 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)
+ 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")
+
+ input = if Feature.enabled?(:use_cmark_renderer)
+ '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
+ else
+ '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
+ end
+
+ 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)
+
+ expect(doc.to_s).to eq output
+ end
end
- it 'does not replace plantuml pre tag with img tag if disabled' do
- stub_application_setting(plantuml_enabled: false)
- input = '<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
- output = '<pre><code lang="plantuml">Bob -&gt; Sara : Hello</code></pre>'
- doc = filter(input)
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
- expect(doc.to_s).to eq output
+ 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")
- input = '<pre><code lang="plantuml">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)
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
+ end
- expect(doc.to_s).to eq output
+ it_behaves_like 'renders correct markdown'
end
end
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index f880fe06ce3..8eb8e5cf800 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -45,10 +45,10 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
it 'allows `text-align` property in `style` attribute on table elements' do
html = <<~HTML
- <table>
- <tr><th style="text-align: center">Head</th></tr>
- <tr><td style="text-align: right">Body</th></tr>
- </table>
+ <table>
+ <tr><th style="text-align: center">Head</th></tr>
+ <tr><td style="text-align: right">Body</th></tr>
+ </table>
HTML
doc = filter(html)
@@ -140,14 +140,14 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
describe 'footnotes' do
it 'allows correct footnote id property on links' do
- exp = %q(<a href="#fn1" id="fnref1">foo/bar.md</a>)
+ exp = %q(<a href="#fn-first" id="fnref-first">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>)
+ exp = %q(<ol><li id="fn-last">footnote</li></ol>)
act = filter(exp)
expect(act.to_html).to eq exp
@@ -156,7 +156,7 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
it 'removes invalid id for footnote links' do
exp = %q(<a href="#fn1">link</a>)
- %w[fnrefx test xfnref1].each do |id|
+ %w[fnrefx test xfnref-1].each do |id|
act = filter(%(<a href="#fn1" id="#{id}">link</a>))
expect(act.to_html).to eq exp
@@ -166,18 +166,58 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
it 'removes invalid id for footnote li' do
exp = %q(<ol><li>footnote</li></ol>)
- %w[fnx test xfn1].each do |id|
+ %w[fnx test xfn-1].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)
+ context 'using ruby-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: false)
+ end
- expect(act.to_html).to eq exp
+ 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
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index 7e45ecdd135..dfe022b51d2 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -11,130 +11,210 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
# after Markdown rendering.
result = filter(%{<pre lang="#{lang}"><code>&lt;script&gt;alert(1)&lt;/script&gt;</code></pre>})
- expect(result.to_html).not_to include("<script>alert(1)</script>")
- expect(result.to_html).to include("alert(1)")
+ # `(1)` symbols are wrapped by lexer tags.
+ expect(result.to_html).not_to match(%r{<script>alert.*<\/script>})
+
+ # `<>` stands for lexer tags like <span ...>, not &lt;s above.
+ expect(result.to_html).to match(%r{alert(<.*>)?\((<.*>)?1(<.*>)?\)})
end
end
- context "when no language is specified" do
- it "highlights as plaintext" do
- result = filter('<pre><code>def fun end</code></pre>')
+ 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>')
- expect(result.to_html).to eq('<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>')
- end
+ expect(result.to_html).to eq('<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>')
+ end
- include_examples "XSS prevention", ""
- end
+ include_examples "XSS prevention", ""
+ end
- context "when contains mermaid diagrams" do
- it "ignores mermaid blocks" do
- result = filter('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
+ 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>')
+ expect(result.to_html).to eq('<pre data-mermaid-style="display"><code>mermaid code</code></pre>')
+ end
end
- end
- context "when a valid language is specified" do
- it "highlights as that language" do
- result = filter('<pre><code lang="ruby">def fun end</code></pre>')
+ context "when a valid language is specified" do
+ it "highlights as that language" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ filter('<pre lang="ruby"><code>def fun end</code></pre>')
+ else
+ filter('<pre><code lang="ruby">def fun end</code></pre>')
+ end
+
+ expect(result.to_html).to eq('<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>')
+ end
- expect(result.to_html).to eq('<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>')
+ include_examples "XSS prevention", "ruby"
end
- include_examples "XSS prevention", "ruby"
- end
+ context "when an invalid language is specified" do
+ it "highlights as plaintext" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ filter('<pre lang="gnuplot"><code>This is a test</code></pre>')
+ else
+ filter('<pre><code lang="gnuplot">This is a test</code></pre>')
+ end
- context "when an invalid language is specified" do
- it "highlights as plaintext" do
- result = filter('<pre><code lang="gnuplot">This is a test</code></pre>')
+ expect(result.to_html).to eq('<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>')
+ end
- expect(result.to_html).to eq('<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>')
+ include_examples "XSS prevention", "gnuplot"
end
- include_examples "XSS prevention", "gnuplot"
- end
+ context "languages that should be passed through" do
+ let(:delimiter) { described_class::LANG_PARAMS_DELIMITER }
+ let(:data_attr) { described_class::LANG_PARAMS_ATTR }
- context "languages that should be passed through" do
- let(:delimiter) { described_class::PARAMS_DELIMITER }
- let(:data_attr) { described_class::LANG_PARAMS_ATTR }
+ %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)
+ filter(%{<pre lang="#{lang}"><code>This is a test</code></pre>})
+ else
+ filter(%{<pre><code lang="#{lang}">This is a test</code></pre>})
+ 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><code lang="#{lang}">This is a test</code></pre>})
+ expect(result.to_html).to eq(%{<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>})
+ end
- expect(result.to_html).to eq(%{<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>})
+ include_examples "XSS prevention", lang
end
- include_examples "XSS prevention", lang
+ context "when #{lang} has extra params" do
+ let(:lang_params) { 'foo-bar-kux' }
+
+ let(:xss_lang) do
+ if Feature.enabled?(:use_cmark_renderer)
+ "#{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)
+ 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).to eq(%{<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>})
+ end
+
+ include_examples "XSS prevention", lang
+
+ if Feature.enabled?(:use_cmark_renderer)
+ 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
end
- context "when #{lang} has extra params" do
- let(:lang_params) { 'foo-bar-kux' }
+ context 'when multiple param delimiters are used' do
+ let(:lang) { 'suggestion' }
+ let(:lang_params) { '-1+10' }
- it "includes data-lang-params tag with extra information" do
- result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}">This is a test</code></pre>})
+ let(:expected_result) do
+ %{<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>}
+ end
- expect(result.to_html).to eq(%{<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>})
+ context 'when delimiter is space' do
+ it 'delimits on the first appearance' do
+ if Feature.enabled?(:use_cmark_renderer)
+ result = filter(%{<pre lang="#{lang}" data-meta="#{lang_params} more-things"><code>This is a test</code></pre>})
+
+ expect(result.to_html).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).to eq(%{<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>})
+ end
+ end
end
- include_examples "XSS prevention", lang
- include_examples "XSS prevention",
- "#{lang}#{described_class::PARAMS_DELIMITER}&lt;script&gt;alert(1)&lt;/script&gt;"
- include_examples "XSS prevention",
- "#{lang}#{described_class::PARAMS_DELIMITER}<script>alert(1)</script>"
+ 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>})
+
+ if Feature.enabled?(:use_cmark_renderer)
+ expect(result.to_html).to eq(expected_result)
+ else
+ expect(result.to_html).to eq(%{<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>})
+ end
+ end
+ end
end
end
- context 'when multiple param delimiters are used' do
- let(:lang) { 'suggestion' }
- let(:lang_params) { '-1+10' }
+ 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 "delimits on the first appearance" do
- result = filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}#{delimiter}more-things">This is a test</code></pre>})
-
- expect(result.to_html).to eq(%{<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>})
+ expect(result.to_html).to eq('<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>')
end
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 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
- expect(result.to_html).to eq('<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>')
- end
- end
+ it "highlights as plaintext" do
+ result = if Feature.enabled?(:use_cmark_renderer)
+ 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 Rouge lexing fails" do
- before do
- allow_next_instance_of(Rouge::Lexers::Ruby) do |instance|
- allow(instance).to receive(:stream_tokens).and_raise(StandardError)
+ expect(result.to_html).to eq('<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>')
end
+
+ include_examples "XSS prevention", "ruby"
end
- it "highlights as plaintext" do
- result = filter('<pre><code lang="ruby">This is a test</code></pre>')
+ 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
- expect(result.to_html).to eq('<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>')
- end
+ it "does not add highlighting classes" do
+ result = filter('<pre><code>This is a test</code></pre>')
+
+ expect(result.to_html).to eq('<pre><code>This is a test</code></pre>')
+ end
- include_examples "XSS prevention", "ruby"
+ include_examples "XSS prevention", "ruby"
+ end
end
- context "when Rouge lexing fails after a retry" do
+ context 'using ruby-based HTML renderer' do
before do
- allow_next_instance_of(Rouge::Lexers::PlainText) do |instance|
- allow(instance).to receive(:stream_tokens).and_raise(StandardError)
- end
+ stub_feature_flags(use_cmark_renderer: false)
end
- it "does not add highlighting classes" do
- result = filter('<pre><code>This is a test</code></pre>')
+ it_behaves_like 'renders correct markdown'
+ end
- expect(result.to_html).to eq('<pre><code>This is a test</code></pre>')
+ context 'using c-based HTML renderer' do
+ before do
+ stub_feature_flags(use_cmark_renderer: true)
end
- include_examples "XSS prevention", "ruby"
+ it_behaves_like 'renders correct markdown'
end
end