diff options
Diffstat (limited to 'spec/lib/banzai/filter/math_filter_spec.rb')
-rw-r--r-- | spec/lib/banzai/filter/math_filter_spec.rb | 298 |
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$ <b>test</b>' | '<math>1/2</math> <b>test</b>' + '$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 |