2019-10-12 21:52:04 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2015-12-23 02:04:40 +05:30
|
|
|
require 'spec_helper'
|
|
|
|
|
2020-07-28 23:09:34 +05:30
|
|
|
RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
|
2015-12-23 02:04:40 +05:30
|
|
|
include FilterSpecHelper
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
shared_examples "XSS prevention" do |lang|
|
|
|
|
it "escapes HTML tags" do
|
|
|
|
# This is how a script tag inside a code block is presented to this filter
|
|
|
|
# after Markdown rendering.
|
|
|
|
result = filter(%{<pre lang="#{lang}"><code><script>alert(1)</script></code></pre>})
|
|
|
|
|
|
|
|
expect(result.to_html).not_to include("<script>alert(1)</script>")
|
|
|
|
expect(result.to_html).to include("alert(1)")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
context "when no language is specified" do
|
|
|
|
it "highlights as plaintext" do
|
|
|
|
result = filter('<pre><code>def fun end</code></pre>')
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre>')
|
2016-08-24 12:49:21 +05:30
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
include_examples "XSS prevention", ""
|
2015-12-23 02:04:40 +05:30
|
|
|
end
|
|
|
|
|
2020-10-24 23:57:45 +05:30
|
|
|
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
|
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
context "when a valid language is specified" do
|
|
|
|
it "highlights as that language" do
|
2017-08-17 22:00:37 +05:30
|
|
|
result = filter('<pre><code lang="ruby">def fun end</code></pre>')
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight 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>')
|
2016-08-24 12:49:21 +05:30
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
include_examples "XSS prevention", "ruby"
|
2016-08-24 12:49:21 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
context "when an invalid language is specified" do
|
|
|
|
it "highlights as plaintext" do
|
2017-08-17 22:00:37 +05:30
|
|
|
result = filter('<pre><code lang="gnuplot">This is a test</code></pre>')
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2017-08-17 22:00:37 +05:30
|
|
|
expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">This is a test</span></code></pre>')
|
2016-08-24 12:49:21 +05:30
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
include_examples "XSS prevention", "gnuplot"
|
2016-08-24 12:49:21 +05:30
|
|
|
end
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
context "languages that should be passed through" do
|
2019-07-07 11:18:12 +05:30
|
|
|
let(:delimiter) { described_class::PARAMS_DELIMITER }
|
|
|
|
let(:data_attr) { described_class::LANG_PARAMS_ATTR }
|
|
|
|
|
|
|
|
%w(math mermaid plantuml suggestion).each do |lang|
|
2018-03-17 18:26:18 +05:30
|
|
|
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 #{lang}" lang="#{lang}" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>})
|
|
|
|
end
|
|
|
|
|
|
|
|
include_examples "XSS prevention", lang
|
|
|
|
end
|
2019-07-07 11:18:12 +05:30
|
|
|
|
|
|
|
context "when #{lang} has extra params" do
|
|
|
|
let(:lang_params) { 'foo-bar-kux' }
|
|
|
|
|
|
|
|
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>})
|
|
|
|
|
|
|
|
expect(result.to_html).to eq(%{<pre class="code highlight js-syntax-highlight #{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
|
|
|
|
include_examples "XSS prevention",
|
|
|
|
"#{lang}#{described_class::PARAMS_DELIMITER}<script>alert(1)</script>"
|
|
|
|
include_examples "XSS prevention",
|
|
|
|
"#{lang}#{described_class::PARAMS_DELIMITER}<script>alert(1)</script>"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'when multiple param delimiters are used' do
|
|
|
|
let(:lang) { 'suggestion' }
|
|
|
|
let(:lang_params) { '-1+10' }
|
|
|
|
|
2019-09-04 21:01:54 +05:30
|
|
|
it "delimits on the first appearance" do
|
2019-07-07 11:18:12 +05:30
|
|
|
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 #{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
|
2018-03-17 18:26:18 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
context "when Rouge lexing fails" do
|
2016-08-24 12:49:21 +05:30
|
|
|
before do
|
2020-01-01 13:55:28 +05:30
|
|
|
allow_next_instance_of(Rouge::Lexers::Ruby) do |instance|
|
|
|
|
allow(instance).to receive(:stream_tokens).and_raise(StandardError)
|
|
|
|
end
|
2016-08-24 12:49:21 +05:30
|
|
|
end
|
2015-12-23 02:04:40 +05:30
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
it "highlights as plaintext" do
|
2017-08-17 22:00:37 +05:30
|
|
|
result = filter('<pre><code lang="ruby">This is a test</code></pre>')
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
context "when Rouge lexing fails after a retry" do
|
|
|
|
before do
|
2020-01-01 13:55:28 +05:30
|
|
|
allow_next_instance_of(Rouge::Lexers::PlainText) do |instance|
|
|
|
|
allow(instance).to receive(:stream_tokens).and_raise(StandardError)
|
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
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>')
|
2016-08-24 12:49:21 +05:30
|
|
|
end
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
include_examples "XSS prevention", "ruby"
|
2015-12-23 02:04:40 +05:30
|
|
|
end
|
|
|
|
end
|