diff options
author | Munken <mm.munk@gmail.com> | 2016-12-09 00:15:08 +0000 |
---|---|---|
committer | Munken <mm.munk@gmail.com> | 2016-12-14 16:50:54 +0000 |
commit | 2d170a20dc4cd3423ac7994c797cae8fbed263ba (patch) | |
tree | 273aeac77c48c027600afb2da40eee739dd6872e /lib | |
parent | e3f5c4c5f66c42ebf3c25c4d23507b56843b006d (diff) | |
download | gitlab-ce-2d170a20dc4cd3423ac7994c797cae8fbed263ba.tar.gz |
Render math in Asciidoc and Markdown with KaTeX using code blocks
Diffstat (limited to 'lib')
-rw-r--r-- | lib/banzai/filter/inline_math_filter.rb | 27 | ||||
-rw-r--r-- | lib/banzai/filter/math_filter.rb | 51 | ||||
-rw-r--r-- | lib/banzai/filter/syntax_highlight_filter.rb | 3 | ||||
-rw-r--r-- | lib/banzai/pipeline/gfm_pipeline.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/asciidoc.rb | 31 | ||||
-rw-r--r-- | lib/gitlab/gon_helper.rb | 2 | ||||
-rw-r--r-- | lib/rouge/lexers/math.rb | 6 |
7 files changed, 87 insertions, 35 deletions
diff --git a/lib/banzai/filter/inline_math_filter.rb b/lib/banzai/filter/inline_math_filter.rb deleted file mode 100644 index 1bbe602237a..00000000000 --- a/lib/banzai/filter/inline_math_filter.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'uri' - -module Banzai - module Filter - # HTML filter that adds class="code math" and removes the dolar sign in $`2+2`$. - # - class InlineMathFilter < HTML::Pipeline::Filter - def call - doc.xpath("descendant-or-self::text()[substring(., string-length(.)) = '$']"\ - "/following-sibling::*[name() = 'code']"\ - "/following-sibling::text()[starts-with(.,'$')]").each do |el| - closing = el - code = el.previous - code[:class] = 'code math' - opening = code.previous - - closing.content = closing.content[1..-1] - opening.content = opening.content[0..-2] - - closing - end - - doc - end - end - end -end diff --git a/lib/banzai/filter/math_filter.rb b/lib/banzai/filter/math_filter.rb new file mode 100644 index 00000000000..cb037f89337 --- /dev/null +++ b/lib/banzai/filter/math_filter.rb @@ -0,0 +1,51 @@ +require 'uri' + +module Banzai + module Filter + # HTML filter that adds class="code math" and removes the dollar sign in $`2+2`$. + # + class MathFilter < HTML::Pipeline::Filter + # This picks out <code>...</code>. + INLINE_MATH = 'descendant-or-self::code'.freeze + + # Pick out a code block which is declared math + DISPLAY_MATH = "descendant-or-self::pre[contains(@class, 'math') and contains(@class, 'code')]".freeze + + # Attribute indicating inline or display math. + STYLE_ATTRIBUTE = 'data-math-style'.freeze + + # Class used for tagging elements that should be rendered + TAG_CLASS = 'js-render-math'.freeze + + INLINE_CLASSES = "code math #{TAG_CLASS}".freeze + + DOLLAR_SIGN = '$'.freeze + + def call + doc.xpath(INLINE_MATH).each do |code| + closing = code.next + opening = code.previous + + # We need a sibling before and after. + # They should end and start with $ respectively. + if closing && opening && + closing.content.first == DOLLAR_SIGN && + opening.content.last == DOLLAR_SIGN + + code[:class] = INLINE_CLASSES + code[STYLE_ATTRIBUTE] = 'inline' + closing.content = closing.content[1..-1] + opening.content = opening.content[0..-2] + end + end + + doc.xpath(DISPLAY_MATH).each do |el| + el[STYLE_ATTRIBUTE] = 'display' + el[:class] += " #{TAG_CLASS}" + end + + doc + end + end + end +end diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb index e7f6b715ba8..026b81ac175 100644 --- a/lib/banzai/filter/syntax_highlight_filter.rb +++ b/lib/banzai/filter/syntax_highlight_filter.rb @@ -48,9 +48,6 @@ module Banzai end def lexer_for(language) - if language == 'math' - return Rouge::Lexers::Math.new - end (Rouge::Lexer.find(language) || Rouge::Lexers::PlainText).new end diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb index 2c81cbe56b3..5a1f873496c 100644 --- a/lib/banzai/pipeline/gfm_pipeline.rb +++ b/lib/banzai/pipeline/gfm_pipeline.rb @@ -6,7 +6,7 @@ module Banzai Filter::SyntaxHighlightFilter, Filter::SanitizationFilter, - Filter::InlineMathFilter, + Filter::MathFilter, Filter::UploadLinkFilter, Filter::VideoLinkFilter, Filter::ImageLinkFilter, diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb index 9667df4ffb8..f77f412da56 100644 --- a/lib/gitlab/asciidoc.rb +++ b/lib/gitlab/asciidoc.rb @@ -1,4 +1,5 @@ require 'asciidoctor' +require 'asciidoctor/converter/html5' module Gitlab # Parser/renderer for the AsciiDoc format that uses Asciidoctor and filters @@ -23,7 +24,7 @@ module Gitlab def self.render(input, context, asciidoc_opts = {}) asciidoc_opts.reverse_merge!( safe: :secure, - backend: :html5, + backend: :gitlab_html5, attributes: [] ) asciidoc_opts[:attributes].unshift(*DEFAULT_ADOC_ATTRS) @@ -36,3 +37,31 @@ module Gitlab end end end + +module Gitlab + module Asciidoc + class Html5Converter < Asciidoctor::Converter::Html5Converter + extend Asciidoctor::Converter::Config + + register_for 'gitlab_html5' + + def stem(node) + return super unless node.style.to_sym == :latexmath + + %(<pre#{id_attribute(node)} class="code math js-render-math #{node.role}" data-math-style="display"><code>#{node.content}</code></pre>) + end + + def inline_quoted(node) + return super unless node.type.to_sym == :latexmath + + %(<code#{id_attribute(node)} class="code math js-render-math #{node.role}" data-math-style="inline">#{node.text}</code>) + end + + private + + def id_attribute(node) + node.id ? %( id="#{node.id}") : nil + end + end + end +end diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index 2c21804fe7a..4d4e04e9e35 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -8,6 +8,8 @@ module Gitlab gon.shortcuts_path = help_page_path('shortcuts') gon.user_color_scheme = Gitlab::ColorSchemes.for_user(current_user).css_class gon.award_menu_url = emojis_path + gon.katex_css_url = ActionController::Base.helpers.asset_path('katex.css') + gon.katex_js_url = ActionController::Base.helpers.asset_path('katex.js') if current_user gon.current_user_id = current_user.id diff --git a/lib/rouge/lexers/math.rb b/lib/rouge/lexers/math.rb index ae980da8283..80784adfd76 100644 --- a/lib/rouge/lexers/math.rb +++ b/lib/rouge/lexers/math.rb @@ -1,13 +1,13 @@ module Rouge module Lexers class Math < Lexer - title "Plain Text" + title "A passthrough lexer used for LaTeX input" desc "A boring lexer that doesn't highlight anything" tag 'math' mimetypes 'text/plain' - default_options :token => 'Text' + default_options token: 'Text' def token @token ||= Token[option :token] @@ -18,4 +18,4 @@ module Rouge end end end -end
\ No newline at end of file +end |