summaryrefslogtreecommitdiff
path: root/spec/lib/banzai/filter/math_filter_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/banzai/filter/math_filter_spec.rb')
-rw-r--r--spec/lib/banzai/filter/math_filter_spec.rb298
1 files changed, 178 insertions, 120 deletions
diff --git a/spec/lib/banzai/filter/math_filter_spec.rb b/spec/lib/banzai/filter/math_filter_spec.rb
index 128f8532d39..dd116eb1109 100644
--- a/spec/lib/banzai/filter/math_filter_spec.rb
+++ b/spec/lib/banzai/filter/math_filter_spec.rb
@@ -3,128 +3,179 @@
require 'spec_helper'
RSpec.describe Banzai::Filter::MathFilter do
+ using RSpec::Parameterized::TableSyntax
include FilterSpecHelper
- it 'leaves regular inline code unchanged' do
- input = "<code>2+2</code>"
- doc = filter(input)
-
- expect(doc.to_s).to eq input
- end
-
- it 'removes surrounding dollar signs and adds class code, math and js-render-math' do
- doc = filter("$<code>2+2</code>$")
-
- expect(doc.to_s).to eq '<code class="code math js-render-math" data-math-style="inline">2+2</code>'
- end
-
- it 'only removes surrounding dollar signs' do
- doc = filter("test $<code>2+2</code>$ test")
- before = doc.xpath('descendant-or-self::text()[1]').first
- after = doc.xpath('descendant-or-self::text()[3]').first
-
- expect(before.to_s).to eq 'test '
- expect(after.to_s).to eq ' test'
- end
-
- it 'only removes surrounding single dollar sign' do
- doc = filter("test $$<code>2+2</code>$$ test")
- before = doc.xpath('descendant-or-self::text()[1]').first
- after = doc.xpath('descendant-or-self::text()[3]').first
-
- expect(before.to_s).to eq 'test $'
- expect(after.to_s).to eq '$ test'
- end
-
- it 'adds data-math-style inline attribute to inline math' do
- doc = filter('$<code>2+2</code>$')
- code = doc.xpath('descendant-or-self::code').first
-
- expect(code['data-math-style']).to eq 'inline'
- end
-
- it 'adds class code and math to inline math' do
- doc = filter('$<code>2+2</code>$')
- code = doc.xpath('descendant-or-self::code').first
-
- expect(code[:class]).to include("code")
- expect(code[:class]).to include("math")
- end
-
- it 'adds js-render-math class to inline math' do
- doc = filter('$<code>2+2</code>$')
- code = doc.xpath('descendant-or-self::code').first
-
- expect(code[:class]).to include("js-render-math")
- end
-
- # Cases with faulty syntax. Should be a no-op
-
- it 'ignores cases with missing dolar sign at the end' do
- input = "test $<code>2+2</code> test"
- doc = filter(input)
-
- expect(doc.to_s).to eq input
- end
-
- it 'ignores cases with missing dolar sign at the beginning' do
- input = "test <code>2+2</code>$ test"
- doc = filter(input)
-
- expect(doc.to_s).to eq input
- end
-
- it 'ignores dollar signs if it is not adjacent' do
- input = '<p>We check strictly $<code>2+2</code> and <code>2+2</code>$ </p>'
- doc = filter(input)
-
- expect(doc.to_s).to eq input
- end
-
- it 'ignores dollar signs if they are inside another element' do
- input = '<p>We check strictly <em>$</em><code>2+2</code><em>$</em></p>'
- doc = filter(input)
-
- expect(doc.to_s).to eq input
- end
-
- # Display math
-
- it 'adds data-math-style display attribute to display math' do
- doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
- pre = doc.xpath('descendant-or-self::pre').first
-
- expect(pre['data-math-style']).to eq 'display'
- end
-
- it 'adds js-render-math class to display math' do
- doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
- pre = doc.xpath('descendant-or-self::pre').first
-
- expect(pre[:class]).to include("js-render-math")
- end
-
- it 'ignores code blocks that are not math' do
- input = '<pre class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code>2+2</code></pre>'
- doc = filter(input)
-
- expect(doc.to_s).to eq input
- end
-
- it 'requires the pre to contain both code and math' do
- input = '<pre class="highlight js-syntax-highlight language-plaintext language-math" v-pre="true"><code>2+2</code></pre>'
- doc = filter(input)
-
- expect(doc.to_s).to eq input
- end
-
- it 'dollar signs around to display math' do
- doc = filter('$<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>$')
- before = doc.xpath('descendant-or-self::text()[1]').first
- after = doc.xpath('descendant-or-self::text()[3]').first
-
- expect(before.to_s).to eq '$'
- expect(after.to_s).to eq '$'
+ shared_examples 'inline math' do
+ it 'removes surrounding dollar signs and adds class code, math and js-render-math' do
+ doc = filter(text)
+ expected = result_template.gsub('<math>', '<code class="code math js-render-math" data-math-style="inline">')
+ expected.gsub!('</math>', '</code>')
+
+ expect(doc.to_s).to eq expected
+ end
+ end
+
+ shared_examples 'display math' do
+ let_it_be(:template_prefix_with_pre) { '<pre class="code math js-render-math" data-math-style="display"><code>' }
+ let_it_be(:template_prefix_with_code) { '<code class="code math js-render-math" data-math-style="display">' }
+ let(:use_pre_tags) { false }
+
+ it 'removes surrounding dollar signs and adds class code, math and js-render-math' do
+ doc = filter(text)
+
+ template_prefix = use_pre_tags ? template_prefix_with_pre : template_prefix_with_code
+ template_suffix = "</code>#{'</pre>' if use_pre_tags}"
+ expected = result_template.gsub('<math>', template_prefix)
+ expected.gsub!('</math>', template_suffix)
+
+ expect(doc.to_s).to eq expected
+ end
+ end
+
+ describe 'inline math using $...$ syntax' do
+ context 'with valid syntax' do
+ where(:text, :result_template) do
+ '$2+2$' | '<math>2+2</math>'
+ '$22+1$ and $22 + a^2$' | '<math>22+1</math> and <math>22 + a^2</math>'
+ '$22 and $2+2$' | '$22 and <math>2+2</math>'
+ '$2+2$ $22 and flightjs/Flight$22 $2+2$' | '<math>2+2</math> $22 and flightjs/Flight$22 <math>2+2</math>'
+ '$1/2$ &lt;b&gt;test&lt;/b&gt;' | '<math>1/2</math> &lt;b&gt;test&lt;/b&gt;'
+ '$a!$' | '<math>a!</math>'
+ '$x$' | '<math>x</math>'
+ end
+
+ with_them do
+ it_behaves_like 'inline math'
+ end
+ end
+
+ it 'does not handle dollar literals properly' do
+ doc = filter('$20+30\$$')
+ expected = '<code class="code math js-render-math" data-math-style="inline">20+30\\</code>$'
+
+ expect(doc.to_s).to eq expected
+ end
+ end
+
+ describe 'inline math using $`...`$ syntax' do
+ context 'with valid syntax' do
+ where(:text, :result_template) do
+ '$<code>2+2</code>$' | '<math>2+2</math>'
+ '$<code>22+1</code>$ and $<code>22 + a^2</code>$' | '<math>22+1</math> and <math>22 + a^2</math>'
+ '$22 and $<code>2+2</code>$' | '$22 and <math>2+2</math>'
+ '$<code>2+2</code>$ $22 and flightjs/Flight$22 $<code>2+2</code>$' | '<math>2+2</math> $22 and flightjs/Flight$22 <math>2+2</math>'
+ 'test $$<code>2+2</code>$$ test' | 'test $<math>2+2</math>$ test'
+ end
+
+ with_them do
+ it_behaves_like 'inline math'
+ end
+ end
+ end
+
+ describe 'inline display math using $$...$$ syntax' do
+ context 'with valid syntax' do
+ where(:text, :result_template) do
+ '$$2+2$$' | '<math>2+2</math>'
+ '$$ 2+2 $$' | '<math>2+2</math>'
+ '$$22+1$$ and $$22 + a^2$$' | '<math>22+1</math> and <math>22 + a^2</math>'
+ '$22 and $$2+2$$' | '$22 and <math>2+2</math>'
+ '$$2+2$$ $22 and flightjs/Flight$22 $$2+2$$' | '<math>2+2</math> $22 and flightjs/Flight$22 <math>2+2</math>'
+ 'flightjs/Flight$22 and $$a^2 + b^2 = c^2$$' | 'flightjs/Flight$22 and <math>a^2 + b^2 = c^2</math>'
+ '$$a!$$' | '<math>a!</math>'
+ '$$x$$' | '<math>x</math>'
+ '$$20,000 and $$30,000' | '<math>20,000 and</math>30,000'
+ end
+
+ with_them do
+ it_behaves_like 'display math'
+ end
+ end
+ end
+
+ describe 'block display math using $$\n...\n$$ syntax' do
+ context 'with valid syntax' do
+ where(:text, :result_template) do
+ "$$\n2+2\n$$" | "<math>2+2</math>"
+ end
+
+ with_them do
+ it_behaves_like 'display math' do
+ let(:use_pre_tags) { true }
+ end
+ end
+ end
+ end
+
+ describe 'display math using ```math...``` syntax' do
+ it 'adds data-math-style display attribute to display math' do
+ doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
+ pre = doc.xpath('descendant-or-self::pre').first
+
+ expect(pre['data-math-style']).to eq 'display'
+ end
+
+ it 'adds js-render-math class to display math' do
+ doc = filter('<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>')
+ pre = doc.xpath('descendant-or-self::pre').first
+
+ expect(pre[:class]).to include("js-render-math")
+ end
+
+ it 'ignores code blocks that are not math' do
+ input = '<pre class="code highlight js-syntax-highlight language-plaintext" v-pre="true"><code>2+2</code></pre>'
+ doc = filter(input)
+
+ expect(doc.to_s).to eq input
+ end
+
+ it 'requires the pre to contain both code and math' do
+ input = '<pre class="highlight js-syntax-highlight language-plaintext language-math" v-pre="true"><code>2+2</code></pre>'
+ doc = filter(input)
+
+ expect(doc.to_s).to eq input
+ end
+
+ it 'dollar signs around to display math' do
+ doc = filter('$<pre class="code highlight js-syntax-highlight language-math" v-pre="true"><code>2+2</code></pre>$')
+ before = doc.xpath('descendant-or-self::text()[1]').first
+ after = doc.xpath('descendant-or-self::text()[3]').first
+
+ expect(before.to_s).to eq '$'
+ expect(after.to_s).to eq '$'
+ end
+ end
+
+ describe 'unrecognized syntax' do
+ where(:text) do
+ [
+ '<code>2+2</code>',
+ 'test $<code>2+2</code> test',
+ 'test <code>2+2</code>$ test',
+ '<em>$</em><code>2+2</code><em>$</em>',
+ '$20,000 and $30,000',
+ '$20,000 in $USD',
+ '$ a^2 $',
+ "test $$\n2+2\n$$",
+ "$\n$",
+ '$$$'
+ ]
+ end
+
+ with_them do
+ it 'is ignored' do
+ expect(filter(text).to_s).to eq text
+ end
+ end
+ end
+
+ it 'handles multiple styles in one text block' do
+ doc = filter('$<code>2+2</code>$ + $3+3$ + $$4+4$$')
+
+ expect(doc.search('.js-render-math').count).to eq(3)
+ expect(doc.search('[data-math-style="inline"]').count).to eq(2)
+ expect(doc.search('[data-math-style="display"]').count).to eq(1)
end
it 'limits how many elements can be marked as math' do
@@ -134,4 +185,11 @@ RSpec.describe Banzai::Filter::MathFilter do
expect(doc.search('.js-render-math').count).to eq(2)
end
+
+ it 'does not recognize new syntax when feature flag is off' do
+ stub_feature_flags(markdown_dollar_math: false)
+ doc = filter('$1+2$')
+
+ expect(doc.to_s).to eq '$1+2$'
+ end
end