Hacker News

Jektex 0.2.0 – A Jekyll plugin for LaTeX rendering is now ~10x faster

Features

  • Renders LaTeX formulas during Jekyll rendering
  • Works without any client-side JavaScript
  • Is faster than any other server-side Jekyll LaTeX renderer
  • Supports user-defined global macros
  • Has I/O-efficient caching system
  • Dynamically informs about the number of expressions during rendering
  • Is very easy to setup
  • Doesn't interfere with Jekyll workflow and project structure
  • Marks invalid expressions in document, printing its location during rendering
  • Leaves LaTeX inside code blocks and inline code untouched, so you can write about LaTeX
  • Renders formulas inside raw HTML blocks, which kramdown skips
  • Is highly configurable with sensible defaults
  • Makes sure that cache does not contain expression rendered with outdated configuration
  • Supports two major LaTeX notations

Jektex supports both the built-in Kramdown math notation, and the newer LaTeX-only math notation.

Inline formula

Put formula between two pairs of dollar signs ($$) inside of paragraph.

Lorem ipsum dolor sit amet, consectetur $$e^{i\theta}=\cos(\theta)+i\sin(\theta)$$ adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Display formula

Put formula between two pairs of dollar signs ($$) and surround it with two empty lines.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

$$
\left[ \frac{-\hbar^2}{2\mu}\nabla^2 + V(\mathbf{r},t)\right] \Psi(\mathbf{r},t)
$$

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Why Jektex does not use conventional single $ for inline formulas and double $$ for display mode?

This is how kramdown (Jekyll's markdown parser) works so I decided to respect this convention. It makes this plugin more consistent and universal. See this issue for more context.

Formulas inside raw HTML blocks

Kramdown does not process markdown inside block-level HTML tags, so it leaves formulas like $$\beta$$ unconverted. Jektex finds these leftover $$ formulas after the conversion and renders them itself.

A formula standing alone on its line renders in display mode, a formula inside text flow renders inline:

The inline formula $$e^{i\theta}$$ sits in text flow.

$$
\left[ \frac{-\hbar^2}{2\mu}\nabla^2 + V(\mathbf{r},t)\right] \Psi(\mathbf{r},t)
$$

This applies only to markdown source files and never inside pre, code, script and similar tags. You can prevent rendering of a specific formula by escaping it as \$$ or by putting it in a code span. If you prefer kramdown to process the content of an HTML block itself, give the tag the markdown="1" attribute.

Inline formula

Put formula between two escaped brackets \( \). Its position in the text does not matter.

Lorem ipsum dolor sit amet, consectetur \(e^{i\theta}=\cos(\theta)+i\sin(\theta)\) adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Display formula

Put formula between two escaped square brackets \[ \]. Its position in the text does not matter.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

\[
\left[ \frac{-\hbar^2}{2\mu}\nabla^2 + V(\mathbf{r},t)\right] \Psi(\mathbf{r},t)
\]

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

There is a built in macro for jektex logo. You can use it as \jektex.

Configuration

Jektex is highly configurable via your _config.yml file. Unknown options and invalid values are reported during the build and fall back to their defaults.

Disabling cache

You can disable caching with the disable_disk_cache option. Caching is enabled by default. This is Jekyll's own option, so unlike the options below it belongs at the top level of _config.yml, not under the jektex key:

disable_disk_cache: true

You can find more information on Jekyll's official website.

Setting cache location

By default, Jektex cache will be saved in .jekyll-cache directory. This results in its deletion when you call jekyll clean. To prevent cache deletion or to change the cache location, you can specify cache_dir in _config.yml:

jektex:
  cache_dir: ".jektex-cache"

Ignoring files

By default, Jektex tries to render LaTeX in all files rendered by Jekyll. This can sometimes be undesirable, for example when rendering an RSS feed with excerpts containing LaTeX. Jektex solves this by using the ignore option:

jektex:
  ignore: ["*.xml", "README.md", "_drafts/*"]

You can use conventional wild cards using *. This example configuration ignores all .xml files, README.md and all files in the _drafts directory.

Another way to ignore specific posts is setting the jektex attribute in front matter to false:

---
title: "How Jektex works"
category: "Development"
jektex: false
layout: post
---

Setting jektex tag to true or not setting at all will result in Jektex rendering LaTeX expressions in that post.

Using macros

You can define global macros:

jektex:
  macros:
    - ["\\Q", "\\mathbb{Q}"]
    - ["\\C", "\\mathbb{C}"]

And yes, you have to escape the backslash (\) with another backslash. This is due to the yaml specification.

You can define macros with parameters:

jektex:
  macros:
    - ["\\vec", "\\mathbf{#1}"]
    - ["\\addBar", "\\bar{#1}"]

This simulates behaviour of LaTeX \newcommand.

Silencing Jektex output

Jektex periodically informs the user about rendered/cached equations. If this is not desired, you can set the silent option (false by default).

jektex:
  silent: true

KaTeX options

You can pass any KaTeX rendering option to the renderer through the katex_options key. Write the keys exactly as the KaTeX documentation spells them:

jektex:
  katex_options:
    trust: false
    output: htmlAndMathml
    strict: warn

The most useful options are:

  • trust toggles features KaTeX deems potentially unsafe (false by default), namely \url, \href, \includegraphics, \htmlClass, \htmlId, \htmlStyle and \htmlData.
  • output: html halves the size of every rendered formula by omitting the invisible MathML copy. Be aware that the MathML is what screen readers use.
  • maxExpand limits macro expansion and protects your build from runaway recursive macros.

Jektex controls displayMode, macros, throwOnError and globalGroup itself, so these keys are ignored (define your macros with the macros option above). Values of the documented KaTeX options are checked: an invalid value is reported and KaTeX's own default is used instead. Option names jektex does not know (for example ones added by newer KaTeX versions) are passed through unchecked.

Changing any KaTeX option invalidates the cache and the next build re-renders everything once.

Complete examples

Recommended config:

jektex:
  cache_dir: ".jektex-cache"
  ignore: ["*.xml"]
  silent: false
  katex_options:
    trust: false
  macros:
    - ["\\Q", "\\mathbb{Q}"]
    - ["\\C", "\\mathbb{C}"]

Having no configuration is equivalent to this:

jektex:
  cache_dir: ".jekyll-cache"
  ignore: []
  silent: false
  katex_options: {}
  macros: []

Installation

This plugin is available as a RubyGem.

Using bundler

Add Jektex to your Gemfile:

group :jekyll_plugins do
  gem "jektex"
end

and run bundle install.

Without bundler

Run gem install jektex.

After installation

Add Jektex to your plugin list in your _config.yml file:

plugins:
  - jektex

and don't forget to add katex.min.css to your HTML head:

It is much better practice to download the css file and load it as an asset from your server directly. You can find more information on KaTeX's website.

Feel free to report any bugs or even make feature request in issues on official repository. I am opened for pull requests as well.

Comments

No comments yet. Start the discussion.