diff --git a/lib/qiita/markdown.rb b/lib/qiita/markdown.rb index e1447c2..837b8eb 100644 --- a/lib/qiita/markdown.rb +++ b/lib/qiita/markdown.rb @@ -36,6 +36,7 @@ require "qiita/markdown/filters/html_toc" require "qiita/markdown/filters/image_link" require "qiita/markdown/filters/inline_code_color" +require "qiita/markdown/filters/inline_math" require "qiita/markdown/filters/mention" require "qiita/markdown/filters/qiita_marker" require "qiita/markdown/filters/simplify" diff --git a/lib/qiita/markdown/filters/inline_math.rb b/lib/qiita/markdown/filters/inline_math.rb new file mode 100644 index 0000000..11ebbc3 --- /dev/null +++ b/lib/qiita/markdown/filters/inline_math.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Qiita + module Markdown + module Filters + class InlineMath < HTML::Pipeline::Filter + def call + doc.search(".//code").each do |code| + opening = code.previous + closing = code.next + replace_with_math_span(code, opening, closing) if inline_math_code?(opening, closing) + end + + doc + end + + private + + def inline_math_code?(opening, closing) + opening.present? && closing.present? && valid_opening?(opening) && valid_closing?(closing) + end + + def valid_opening?(opening) + opening.text? && opening.content.end_with?("$") && !opening.content.end_with?("$$") + end + + def valid_closing?(closing) + closing.text? && closing.content.start_with?("$") && !closing.content.start_with?("$$") + end + + def replace_with_math_span(code, opening, closing) + span = Nokogiri::XML::Node.new("span", doc) + span.add_child(Nokogiri::XML::Text.new("$#{code.text}$", doc)) + code.replace(span) + opening.content = opening.content.delete_suffix("$") + opening.remove if opening.content.empty? + closing.content = closing.content.delete_prefix("$") + closing.remove if closing.content.empty? + end + end + end + end +end diff --git a/lib/qiita/markdown/processor.rb b/lib/qiita/markdown/processor.rb index 704087e..fdbbc0f 100644 --- a/lib/qiita/markdown/processor.rb +++ b/lib/qiita/markdown/processor.rb @@ -24,6 +24,7 @@ def self.default_filters Filters::GroupMention, Filters::ExternalLink, Filters::InlineCodeColor, + Filters::InlineMath, Filters::FinalSanitizer, ] end diff --git a/spec/qiita/markdown/filters/inline_math_spec.rb b/spec/qiita/markdown/filters/inline_math_spec.rb new file mode 100644 index 0000000..adc9b73 --- /dev/null +++ b/spec/qiita/markdown/filters/inline_math_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +describe Qiita::Markdown::Filters::InlineMath do + subject(:filter) do + described_class.new(html) + end + + context "with dollar signs" do + let(:html) do + <<~HTML +
+ $A = B$ +
+ HTML + end + + it "replaces to with dollars" do + expect(filter.call.to_html).to eq( + <<~HTML, +
+ $A = B$ +
+ HTML + ) + end + end + + context "with dollar signs with surrounding text" do + let(:html) do + <<~HTML +
+ Some text before$A = B$Some text after +
+ HTML + end + + it "replaces to with dollars" do + expect(filter.call.to_html).to eq( + <<~HTML, +
+ Some text before$A = B$Some text after +
+ HTML + ) + end + end + + context "with double dollar signs" do + let(:html) do + <<~HTML +
+ $$ + A = B + $$ +
+ HTML + end + + it "does not replace " do + expect(filter.call.to_html).to eq(html) + end + end + + context "without dollar signs" do + let(:html) do + <<~HTML +
+ A = B +
+ HTML + end + + it "does not replace " do + expect(filter.call.to_html).to eq(html) + end + end +end