Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds KaTeX math engine via the 'katex' ruby gem #489

Merged
merged 1 commit into from
Feb 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ before_install:
- sudo apt-get install texlive-latex-base texlive-latex-recommended texlive-fonts-recommended texlive-latex-extra tidy
- gem install rake
- gem install minitest coderay stringex ritex execjs sskatex
- "ruby -e 'exit RUBY_VERSION < \"2.3\" ? 0 : 1' || gem install katex -v 0.3.0"
- gem install rouge
- gem install prawn prawn-table
- (ruby --version | grep jruby) || gem install itextomml
Expand Down
15 changes: 13 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ EOF
s.add_development_dependency 'ritex', '~> 1.0'
s.add_development_dependency 'itextomml', '~> 1.5'
s.add_development_dependency 'execjs', '~> 2.7'
s.add_development_dependency 'sskatex', '>= 0.9.23'
s.add_development_dependency 'sskatex', '>= 0.9.37'
s.add_development_dependency 'katex', '~> 0.3.0'

#### Documentation

Expand Down Expand Up @@ -293,14 +294,24 @@ XJS
end

desc "Update kramdown SsKaTeX test reference outputs"
task update_katex_tests: [:test_sskatex_deps] do
task update_sskatex_tests: [:test_sskatex_deps] do
# Not framed in terms of rake file tasks to prevent accidental overwrites.
stems = ['test/testcases/block/15_math/sskatex',
'test/testcases/span/math/sskatex']
stems.each do |stem|
ruby "-Ilib bin/kramdown --math-engine sskatex #{stem}.text >#{stem}.html.19"
end
end

desc "Update kramdown KaTeX test reference outputs"
task :update_katex_tests do
# Not framed in terms of rake file tasks to prevent accidental overwrites.
stems = ['test/testcases/block/15_math/katex',
'test/testcases/span/math/katex']
stems.each do |stem|
ruby "-Ilib bin/kramdown --math-engine katex #{stem}.text >#{stem}.html.19"
end
end
end

task :gemspec => ['dev:gemspec']
Expand Down
7 changes: 4 additions & 3 deletions doc/converter/html.page
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,10 @@ For proper functionality, the HTML template must be configured to link to the en
and CSS. Note that the CSS includes references to webfonts.

Also available are precompiling versions to eliminate the need for client-side Javascript. Those are
[Mathjax-Node](../math_engine/mathjaxnode.html) and [SsKaTeX](../math_engine/sskatex.html). Each one
requires a Javascript engine installed where kramdown runs, in order to perform the precompilation.
The resulting pages still require CSS and fonts, but no Javascript anymore.
[Mathjax-Node](../math_engine/mathjaxnode.html), [KaTeX](../math_engine/katex.html), and
[SsKaTeX](../math_engine/sskatex.html). Each one requires a Javascript engine installed where
kramdown runs, in order to perform the precompilation. The resulting pages still require CSS and
fonts, but no Javascript anymore.

Alternative math engines are [Ritex](../math_engine/ritex.html) and
[itex2MML](../math_engine/itex2mml.html) both of which output MathML.
Expand Down
1 change: 1 addition & 0 deletions doc/documentation.template
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* [Coderay](syntax_highlighter/coderay.html)
* [Rouge](syntax_highlighter/rouge.html)
* Math Engines
* [KaTeX](math_engine/katex.html)
* [MathJax](math_engine/mathjax.html)
* [Ritex](math_engine/ritex.html)
* [itex2MML](math_engine/itex2mml.html)
Expand Down
29 changes: 29 additions & 0 deletions doc/math_engine/katex.page
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reformat the documentation to 100 columns. And you also need to link to this page on the documentation.page.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

title: KaTeX
---

## Math Engine KaTeX

This math engine uses [KaTeX] via the [katex rubygem][katex-gem] to convert TeX math formulas into
KaTeX HTML (using [ExecJS] under the hood).

This eliminates the need for client-side math-rendering JavaScript. Your HTML templates still need
to include the KaTeX CSS (see the [gem's documentation][katex-gem#assets] on this).

A typical KaTeX configuration looks like this:

~~~ yaml
math_engine: katex
math_engine_opts: {}
~~~

`math_engine_opts` are passed directly to `Katex.render`. See the gem's [documentation][katex-gem]
for more information.

If you need to sanitize the output, see [this example][sanitize-example] for inspiration.

[KaTeX]: https://khan.github.io/KaTeX/
[ExecJS]: https://github.com/rails/execjs
[katex-gem]: https://github.com/glebm/katex-ruby
[katex-gem#assets]: https://github.com/glebm/katex-ruby#assets
[sanitize-example]: https://github.com/thredded/thredded-markdown_katex/blob/2f5e748c90265526171a6da99557f637d2b717ec/lib/thredded/markdown_katex.rb#L48-L91
2 changes: 1 addition & 1 deletion lib/kramdown/converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module Converter

configurable(:math_engine)

['Mathjax', "MathjaxNode", "SsKaTeX", "Ritex", "Itex2MML"].each do |klass_name|
["Mathjax", "MathjaxNode", "Katex", "SsKaTeX", "Ritex", "Itex2MML"].each do |klass_name|
kn_down = klass_name.downcase.intern
add_math_engine(kn_down) do |converter, el, opts|
require "kramdown/converter/math_engine/#{kn_down}"
Expand Down
35 changes: 35 additions & 0 deletions lib/kramdown/converter/math_engine/katex.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2018 Gleb Mazovetskiy <glex.spb@gmail.com>
#
# This file is part of kramdown which is licensed under the MIT.
#++

module Kramdown::Converter::MathEngine
# Uses the KaTeX gem for converting math formulas to KaTeX HTML.
module Katex
AVAILABLE = begin
require 'katex'
true
rescue LoadError
false
end

def self.call(converter, el, opts)
display_mode = el.options[:category] == :block
result = ::Katex.render(
el.value,
display_mode: display_mode,
throw_on_error: false,
**converter.options[:math_engine_opts]
)
attr = el.attr.dup
attr.delete('xmlns')
attr.delete('display')
result.insert(result =~ /[[:space:]>]/, converter.html_attributes(attr))
result = "#{' ' * opts[:indent]}#{result}\n" if display_mode
result
end
end
end
40 changes: 27 additions & 13 deletions test/test_files.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ class TestFiles < Minitest::Test
warn("Skipping MathjaxNode tests as MathjaxNode is not available")
end

KATEX_AVAILABLE = begin
/ class="katex"/ === Kramdown::Document.
new('$$a$$', {:math_engine => :sskatex}).to_html or
warn("Skipping SsKaTeX tests as SsKaTeX is not available.")
rescue
warn("Skipping SsKaTeX tests as default SsKaTeX config does not work.")
end or warn("Run \"rake dev:test_sskatex_deps\" to see why.")
SSKATEX_AVAILABLE = begin
/ class="katex"/ === Kramdown::Document.
new('$$a$$', {:math_engine => :sskatex}).to_html or
warn("Skipping SsKaTeX tests as SsKaTeX is not available.")
rescue
warn("Skipping SsKaTeX tests as default SsKaTeX config does not work.")
end or warn("Run \"rake dev:test_sskatex_deps\" to see why.")

KATEX_AVAILABLE = RUBY_VERSION >= '2.3'

EXCLUDE_KD_FILES = [('test/testcases/block/04_header/with_auto_ids.text' if RUBY_VERSION <= '1.8.6'), # bc of dep stringex not working
('test/testcases/span/03_codespan/rouge/' if RUBY_VERSION < '2.0'), #bc of rouge
Expand All @@ -59,8 +61,10 @@ class TestFiles < Minitest::Test
('test/testcases/block/15_math/mathjaxnode_notexhints.text' unless MATHJAX_NODE_AVAILABLE),
('test/testcases/block/15_math/mathjaxnode_semantics.text' unless MATHJAX_NODE_AVAILABLE),
('test/testcases/span/math/mathjaxnode.text' unless MATHJAX_NODE_AVAILABLE),
('test/testcases/block/15_math/sskatex.text' unless KATEX_AVAILABLE),
('test/testcases/span/math/sskatex.text' unless KATEX_AVAILABLE),
('test/testcases/block/15_math/sskatex.text' unless SSKATEX_AVAILABLE),
('test/testcases/span/math/sskatex.text' unless SSKATEX_AVAILABLE),
('test/testcases/block/15_math/katex.text' unless KATEX_AVAILABLE),
('test/testcases/span/math/katex.text' unless KATEX_AVAILABLE),
].compact

# Generate test methods for kramdown-to-xxx conversion
Expand Down Expand Up @@ -109,6 +113,8 @@ class TestFiles < Minitest::Test
'test/testcases/block/15_math/mathjax_preview_as_code.html', # bc of mathjax preview
'test/testcases/span/math/sskatex.html', # bc of tidy
'test/testcases/block/15_math/sskatex.html', # bc of tidy
'test/testcases/span/math/katex.html', # bc of tidy
'test/testcases/block/15_math/katex.html', # bc of tidy
'test/testcases/span/05_html/mark_element.html', # bc of tidy
'test/testcases/block/09_html/xml.html', # bc of tidy
'test/testcases/span/05_html/xml.html', # bc of tidy
Expand Down Expand Up @@ -217,6 +223,8 @@ def tidy_output(out)
'test/testcases/span/math/mathjaxnode.text', # bc of tidy
'test/testcases/block/15_math/sskatex.text', # bc of tidy
'test/testcases/span/math/sskatex.text', # bc of tidy
'test/testcases/block/15_math/katex.text', # bc of tidy
'test/testcases/span/math/katex.text', # bc of tidy
'test/testcases/span/01_link/link_defs_with_ial.text', # bc of attribute ordering
'test/testcases/span/05_html/mark_element.text', # bc of tidy
'test/testcases/block/09_html/xml.text', # bc of tidy
Expand Down Expand Up @@ -270,6 +278,8 @@ def tidy_output(out)
'test/testcases/span/math/mathjaxnode.html', # bc of tidy
'test/testcases/block/15_math/sskatex.html', # bc of tidy
'test/testcases/span/math/sskatex.html', # bc of tidy
'test/testcases/block/15_math/katex.html', # bc of tidy
'test/testcases/span/math/katex.html', # bc of tidy
'test/testcases/block/15_math/mathjax_preview.html', # bc of mathjax preview
'test/testcases/block/15_math/mathjax_preview_simple.html', # bc of mathjax preview
'test/testcases/block/15_math/mathjax_preview_as_code.html', # bc of mathjax preview
Expand Down Expand Up @@ -375,8 +385,10 @@ def tidy_output(out)
('test/testcases/block/15_math/mathjaxnode_notexhints.text' unless MATHJAX_NODE_AVAILABLE),
('test/testcases/block/15_math/mathjaxnode_semantics.text' unless MATHJAX_NODE_AVAILABLE),
('test/testcases/span/math/mathjaxnode.text' unless MATHJAX_NODE_AVAILABLE),
('test/testcases/block/15_math/sskatex.text' unless KATEX_AVAILABLE),
('test/testcases/span/math/sskatex.text' unless KATEX_AVAILABLE),
('test/testcases/block/15_math/sskatex.text' unless SSKATEX_AVAILABLE),
('test/testcases/span/math/sskatex.text' unless SSKATEX_AVAILABLE),
('test/testcases/block/15_math/katex.text' unless KATEX_AVAILABLE),
('test/testcases/span/math/katex.text' unless KATEX_AVAILABLE),
].compact

# Generate test methods for gfm-to-html conversion
Expand Down Expand Up @@ -408,8 +420,10 @@ def tidy_output(out)
].compact

EXCLUDE_MODIFY = ['test/testcases/block/06_codeblock/rouge/multiple.text', # bc of HTMLFormater in options
('test/testcases/block/15_math/sskatex.text' unless KATEX_AVAILABLE),
('test/testcases/span/math/sskatex.text' unless KATEX_AVAILABLE),
('test/testcases/block/15_math/sskatex.text' unless SSKATEX_AVAILABLE),
('test/testcases/span/math/sskatex.text' unless SSKATEX_AVAILABLE),
('test/testcases/block/15_math/katex.text' unless KATEX_AVAILABLE),
('test/testcases/span/math/katex.text' unless KATEX_AVAILABLE),
].compact

# Generate test methods for asserting that converters don't modify the document tree.
Expand Down
2 changes: 2 additions & 0 deletions test/testcases/block/15_math/katex.html.19
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi mathvariant="normal">Δ</mi><mo>=</mo><mfrac><mrow><mn>1</mn></mrow><mrow><mn>2</mn></mrow></mfrac><mrow><mo fence="true">∣</mo><mtable><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>a</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>b</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>d</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>e</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>f</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>g</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>h</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>i</mi></mrow></mstyle></mtd></mtr></mtable><mo fence="true">∣</mo></mrow></mrow><annotation encoding="application/x-tex">\Delta = \frac{1}{2}
\begin{vmatrix}a &amp; b &amp; c \\ d &amp; e &amp; f \\ g &amp; h &amp; i\end{vmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="strut" style="height:2.08597em;"></span><span class="strut bottom" style="height:3.636em;vertical-align:-1.5500299999999998em;"></span><span class="base"><span class="mord mathrm">Δ</span><span class="mrel">=</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.32144em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathrm">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathrm">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.08597em;"><span style="top:-1.05597em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-1.6619700000000002em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.26797em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.87397em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-3.47997em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-4.08597em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500299999999998em;"></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">a</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">d</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit" style="margin-right:0.03588em;">g</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">b</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">e</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">h</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">c</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit" style="margin-right:0.10764em;">f</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.08597em;"><span style="top:-1.05597em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-1.6619700000000002em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.26797em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-2.87397em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-3.47997em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span><span style="top:-4.08597em;"><span class="pstrut" style="height:2.606em;"></span><span class="delimsizinginner delim-size1"><span>∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500299999999998em;"></span></span></span></span></span></span></span></span></span></span>
1 change: 1 addition & 0 deletions test/testcases/block/15_math/katex.options
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:math_engine: :katex
2 changes: 2 additions & 0 deletions test/testcases/block/15_math/katex.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
$$\Delta = \frac{1}{2}
\begin{vmatrix}a & b & c \\ d & e & f \\ g & h & i\end{vmatrix}$$
Loading