Skip to content

Commit c705b8f

Browse files
authored
Add filter math2svg (#118)
1 parent 14651cc commit c705b8f

File tree

7 files changed

+689
-0
lines changed

7 files changed

+689
-0
lines changed

.tools/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ RUN apt-get -q --no-allow-insecure-repositories update \
1919
lmodern \
2020
luarocks \
2121
make \
22+
nodejs \
23+
npm \
2224
python-is-python3 \
2325
python3 \
2426
python3-matplotlib \
@@ -38,6 +40,9 @@ ARG plantuml_jar=plantuml.1.2018.9.jar
3840
RUN wget https://sourceforge.net/projects/plantuml/files/${plantuml_jar} \
3941
--quiet --output-document=/root/${plantuml_jar}
4042
ENV PLANTUML=/root/$plantuml_jar
43+
44+
RUN npm install --global mathjax-node-cli
45+
4146
ENV DIFF="diff -u"
4247
ENV LC_ALL="C.UTF-8"
4348
ENV LANG="C.UTF-8"

math2svg/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
DIFF ?= diff --strip-trailing-cr -u
2+
3+
test: sample.md math2svg.lua
4+
@pandoc \
5+
--mathml --lua-filter=math2svg.lua \
6+
-M math2svg_font='Gyre-Pagella' \
7+
--to=html sample.yaml $< \
8+
| $(DIFF) expected.html -
9+
10+
expected: sample.md math2svg.lua
11+
pandoc \
12+
--mathml --lua-filter=math2svg.lua \
13+
-M math2svg_tex2svg='/usr/local/bin/tex2svg' \
14+
-M math2svg_font='Gyre-Pagella' \
15+
--output=expected.html sample.yaml $<
16+
17+
.PHONY: test

math2svg/README.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
# math2svg
2+
3+
4+
## Description
5+
6+
This [Lua filter][pandoc.lua-filters] for [Pandoc][pandoc] converts
7+
[LaTeX math][latex.math] to [MathJax][mathjax] generated
8+
[scalable vector graphics (SVG)][svg] for insertion into the output document
9+
in a standalone manner.
10+
SVG output is in any of the [available MathJax fonts][mathjax.fonts].
11+
12+
This is useful when a CSS paged media engine (such as [Prince XML][prince])
13+
cannot process complex JavaScript as required by MathJax.
14+
See: <https://www.print-css.rocks> for information about CSS paged media,
15+
a [W3C standard][w3c].
16+
17+
No Internet connection is required when generating or viewing SVG formulas,
18+
resulting in both absolute privacy and offline, standalone robustness.
19+
20+
21+
## Requirements
22+
23+
First, use the package manager of your operating system to install `pandoc`,
24+
`nodejs` and `npm`. `brew` and `choco` are recommended package managers for
25+
respectively macOS and Windows. See: <https://pandoc.org/installing.html>
26+
27+
```bash
28+
$ sudo apt install pandoc nodejs npm
29+
$ sudo dnf install pandoc nodejs npm
30+
$ sudo yum install pandoc nodejs npm
31+
$ brew install pandoc nodejs npm
32+
> choco install pandoc nodejs npm
33+
```
34+
35+
Then, by means of node's package manager `npm`, install the `mathjax-node-cli`
36+
package. This package comes with the `tex2svg` executable.
37+
Leave out the `sudo` on Windows.
38+
39+
```bash
40+
$ sudo npm install --global mathjax-node-cli
41+
> npm install --global mathjax-node-cli
42+
```
43+
44+
45+
## Usage
46+
47+
To be used as a [Pandoc Lua filter][pandoc.lua-filters].
48+
[MathML][mathml] should be set as a fallback with
49+
the `--mathml` argument.
50+
51+
```bash
52+
pandoc --mathml --filter='math2svg.lua'
53+
```
54+
55+
The math2svg filter is entirely configurable over
56+
[`--metadata` key value pairs](pandoc.metadata).
57+
Nine configuration keys are available with sensible default values.
58+
Hence, depending on your system and intentions, not all keys are necessarily
59+
required.
60+
61+
|key|default value|
62+
|:--|:-----------:|
63+
|`math2svg_tex2svg`|`''`|
64+
|`math2svg_display2svg`|`true`|
65+
|`math2svg_inline2svg`|`false`|
66+
|`math2svg_speech`|`false`|
67+
|`math2svg_linebreaks`|`true`|
68+
|`math2svg_font`|`'TeX'`|
69+
|`math2svg_ex`|`6`|
70+
|`math2svg_width`|`100`|
71+
|`math2svg_extensions`|`''`|
72+
73+
74+
### Key value `math2svg_tex2svg`
75+
This string key value is only required when, on your system, the path to the
76+
`tex2svg` executable of the `mathjax-node-cli` package is not present in the
77+
`$PATH` environment variable.
78+
79+
The full path to `tex2svg` can be found with the following command on \*nix,
80+
respectively Windows:
81+
82+
```bash
83+
$ which -a tex2svg
84+
> where tex2svg
85+
```
86+
87+
### Key values `math2svg_display2svg` and `math2svg_inline2svg`
88+
These boolean key values specify whether display math, respectively inline math,
89+
should be converted to [SVG][svg] by the filter.
90+
The defaults convert display math to SVG, whereas inline math falls back to
91+
[MathML][mathml] when `--mathml` was specified at `pandoc` evocation.
92+
These defaults offer the following benefits:
93+
94+
- MathML output gets generated much faster than SVG output.
95+
- Moreover, MathML is well suited for inline math as line heights are kept
96+
small.
97+
98+
99+
### Key value `math2svg_speech`
100+
This boolean key value controls whether textual annotations for speech
101+
generation are added to SVG formula. The default is `false`.
102+
103+
### Key value `math2svg_linebreaks`
104+
This boolean key value automatic switches automatic line breaking.
105+
The default is `true`.
106+
107+
108+
### Key value `math2svg_font`
109+
This string key value allows to specify a [MathJax font][mathjax.fonts]
110+
different from the default `'TeX'` font.
111+
The string should correspond to the local directory name of the font in the
112+
`mathjax-node-cli` installation directory.
113+
For example, the key value string for the font in
114+
`/usr/local/lib/node_modules/mathjax-node-cli/node_modules/mathjax/fonts/HTML-CSS/Gyre-Pagella/`
115+
would simply be `Gyre-Pagella`.
116+
117+
118+
### Key value `math2svg_ex`
119+
This positive integer key value sets the `ex` unit in pixels.
120+
The default value is `6` pixels.
121+
122+
123+
### Key value `math2svg_width`
124+
This positive integer key value sets the container width in `ex` units for line
125+
breaking and tags. The default value is `100` ex.
126+
127+
128+
### Key value `math2svg_extensions`
129+
This string key value allows to load one or more comma separated
130+
[MathJax extensions for TeX and LaTeX][mathjax.tex.ext] present on the system.
131+
These MathJaX extensions reside in a subdirectory of the `mathjax-node-cli`
132+
installation directory.
133+
134+
Take for example, the installation directory of the extensions is
135+
`/usr/local/lib/node_modules/mathjax-node-cli/node_modules/mathjax/unpacked/extensions/`
136+
It contains a subdirectory `TeX` with the extension file `AMSmath.js`.
137+
This MathJaX extension can be loaded by specifying the string `'TeX/AMSmath'`
138+
as the value of the `math2svg_extensions` key.
139+
140+
141+
### Adding `header-includes`
142+
It might turn out useful to systematically include LaTeX macros, for example as
143+
shown below, a series of `\newcommand`.
144+
145+
```latex
146+
---
147+
header-includes: |
148+
\newcommand{\j}{\text{j}}
149+
\newcommand{\e}[1]{\,\text{e}^{#1}}
150+
...
151+
```
152+
153+
This may be achieved either by adding a [YAML][yaml] block with the
154+
[`header-includes`][pandoc.header-includes] key value at the top of the input
155+
document, or by having a separate YAML document loaded before the input
156+
document. In the latter case, simply evoke `pandoc` as follows:
157+
158+
```bash
159+
pandoc --mathml --filter='math2svg.lua' header-includes.yaml input.md
160+
```
161+
162+
163+
## Adding equation numbers with CSS
164+
165+
When automatic equation numbers are desired, these need to be added using
166+
[cascading style sheets (CSS)](https://en.wikipedia.org/wiki/CSS),
167+
as JavaScript is not available in CSS paged media.
168+
169+
Below example CSS code centers display math whilst adding equation numbers
170+
to the right.
171+
172+
```css
173+
span.math.display {
174+
display: flex;
175+
justify-content: flex-end;
176+
align-items: center;
177+
}
178+
179+
span.math.display svg {
180+
margin: 0 auto;
181+
max-width: 85%;
182+
}
183+
184+
span.math.display:after {
185+
counter-increment: equation;
186+
content: '(' counter(equation) ')';
187+
font-weight: bold;
188+
}
189+
```
190+
191+
192+
## Privacy
193+
194+
No Internet connection is established when creating MathJax SVG code using
195+
the `tex2svg` command of [`mathjax-node-cli`][mathjax.node.cli].
196+
Nor will any Internet connection be established when viewing an SVG formula.
197+
198+
Hence, formulas in SVG can be created and viewed offline whilst remaining
199+
private.
200+
201+
For code auditing, see also:
202+
203+
- <https://github.com/mathjax/MathJax-node>
204+
- <https://github.com/pkra/mathjax-node-sre>
205+
- <https://github.com/mathjax/mathjax-node-cli>
206+
207+
208+
## License
209+
210+
Copyright (c) 2020-2021 Serge Y. Stroobandt
211+
212+
MIT License
213+
214+
Permission is hereby granted, free of charge, to any person obtaining a copy
215+
of this software and associated documentation files (the "Software"), to deal
216+
in the Software without restriction, including without limitation the rights
217+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
218+
copies of the Software, and to permit persons to whom the Software is
219+
furnished to do so, subject to the following conditions:
220+
221+
The above copyright notice and this permission notice shall be included in all
222+
copies or substantial portions of the Software.
223+
224+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
225+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
226+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
227+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
228+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
229+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
230+
SOFTWARE.
231+
232+
233+
## Contact
234+
235+
```bash
236+
$ echo c2VyZ2VAc3Ryb29iYW5kdC5jb20K |base64 -d
237+
```
238+
239+
240+
[latex.math]: https://en.wikibooks.org/wiki/LaTeX/Mathematics
241+
242+
[mathjax]: https://www.mathjax.org/
243+
[mathjax.fonts]: https://docs.mathjax.org/en/latest/output/fonts.html
244+
[mathjax.node.cli]: https://github.com/mathjax/mathjax-node-cli
245+
[mathjax.tex.ext]: https://docs.mathjax.org/en/latest/input/tex/extensions.html
246+
[mathml]: https://en.wikipedia.org/wiki/MathML
247+
248+
[pandoc]: https://pandoc.org/
249+
[pandoc.header-includes]: https://pandoc.org/MANUAL.html#metadata-blocks
250+
[pandoc.lua-filters]: https://pandoc.org/lua-filters.html
251+
[pandoc.metadata]: https://pandoc.org/MANUAL.html#reader-options
252+
[prince]: https://www.princexml.com
253+
254+
[svg]: https://en.wikipedia.org/wiki/Scalable_Vector_Graphics
255+
256+
[w3c]: https://www.w3.org/TR/css-page-3/
257+
258+
[yaml]: https://en.wikipedia.org/wiki/YAML

0 commit comments

Comments
 (0)