# module Kramdown::Converter::MathEngine::SsKaTeX

Consider this a lightweight alternative to `MathjaxNode`. Uses KaTeX and ExecJS (via ::SsKaTeX) instead of MathJax and Node.js. Javascript execution context initialization is done only once. As a result, the performance is reasonable.

### Constants

AVAILABLE

  Indicate whether `SsKaTeX` may be available.

  This test is incomplete; it cannot test the existence of katex_js nor the availability of a specific js_run because those depend on configuration not given here. This test mainly indicates whether static dependencies such as the `sskatex` and `execjs` gems are available.

DEBUG_LOGGER

  A logger that routes messages to the debug channel only. No need to create this dynamically.

KTXC

  Class-level cache for ::SsKaTeX converter state, queried by configuration. Note: `KTXC` contents may become stale if the contents of used JS files change while the configuration remains unchanged.

### Public Class Methods

call(converter, el, opts) click to toggle source

The function used by kramdown for rendering TeX math to HTML

       # File lib/kramdown/converter/math_engine/sskatex.rb
    82 def call(converter, el, opts)
    83   display_mode = el.options[:category]
    84   ans = katex_conv(converter).call(el.value, display_mode == :block, &logger(converter))
    85   attr = el.attr.dup
    86   attr.delete('xmlns')
    87   attr.delete('display')
    88   ans.insert(ans =~ /[[:space:]>]/, converter.html_attributes(attr))
    89   ans = ' ' * opts[:indent] << ans << "\n" if display_mode == :block
    90   ans
    91 end

### Private Class Methods

katex_conv(converter) click to toggle source

Given a `Kramdown::Converter::Base` object converter, return a ::SsKaTeX converter sktx that has been configured with converter's `math_engine_opts`, but not for logging. Cache sktx for reuse, without references to converter.

       # File lib/kramdown/converter/math_engine/sskatex.rb
    70 def katex_conv(converter)
    71   config = converter.options[:math_engine_opts]
    72     # Could .reject { |key, _| [:verbose, :debug].include?(key.to_sym) }
    73     # because the JS engine setup can be reused for different logging settings.
    74     # But then the +math_engine_opts+ dict would be essentially dup'ed every time,
    75     # and late activation of logging would miss the initialization if the engine is reused.
    76   KTXC[config] ||= ::SsKaTeX.new(config)
    77 end

logger(converter) click to toggle source

Given a `Kramdown::Converter::Base` object converter, retrieves the logging options and builds an object usable for ::SsKaTeX#logger. The result is either `nil` (no logging) or a `Proc` object which, when given a level (either `:verbose` or `:debug`) and a block, decides whether logging is enabled, and if so, evaluates the given block for the message and routes that message to the appropriate channels. With `level == :verbose+`, messages are passed to converter.warning if the converter's `:verbose` option is set. All messages are passed to `warn` if the converter's `:debug` option is set.

Note that the returned logger may contain references to the given converter and is not affected by subsequent changes in the converter's logging options.

       # File lib/kramdown/converter/math_engine/sskatex.rb
    51 def logger(converter)
    52   config = converter.options[:math_engine_opts]
    53   debug = config[:debug]
    54   if config[:verbose]
    55     # Need a closure
    56     lambda do |level, &expr|
    57       verbose = (level == :verbose)
    58       msg = expr.call if debug || verbose
    59       warn(msg) if debug
    60       converter.warning(msg) if verbose
    61     end
    62   elsif debug
    63     DEBUG_LOGGER
    64   end
    65 end