├── Setup.hs ├── math-samples.png ├── stack.yaml ├── .gitignore ├── pandoc-tex2svg.cabal ├── README.md ├── math-samples.md ├── LICENSE ├── pandoc-tex2svg.hs └── math-samples.html /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /math-samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgm/pandoc-tex2svg/HEAD/math-samples.png -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-7.9 2 | packages: 3 | - '.' 4 | extra-deps: 5 | - pandoc-types-1.17.0.4 6 | flags: {} 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-* 3 | cabal-dev 4 | *.o 5 | *.hi 6 | *.chi 7 | *.chs.h 8 | *.dyn_o 9 | *.dyn_hi 10 | .hpc 11 | .hsenv 12 | .cabal-sandbox/ 13 | cabal.sandbox.config 14 | *.prof 15 | *.aux 16 | *.hp 17 | *.eventlog 18 | .stack-work/ 19 | cabal.project.local 20 | -------------------------------------------------------------------------------- /pandoc-tex2svg.cabal: -------------------------------------------------------------------------------- 1 | name: pandoc-tex2svg 2 | version: 0.1.0.0 3 | synopsis: Pandoc filter to convert tex math to SVG 4 | description: Please see README.md 5 | homepage: https://github.com/githubuser/pandoc-tex2svg#readme 6 | license: BSD3 7 | license-file: LICENSE 8 | author: John MacFarlane 9 | maintainer: jgm@berkeley.edu 10 | copyright: 2016 John MacFarlane 11 | category: Text 12 | build-type: Simple 13 | -- extra-source-files: 14 | cabal-version: >=1.10 15 | 16 | executable pandoc-tex2svg 17 | hs-source-dirs: . 18 | main-is: pandoc-tex2svg.hs 19 | ghc-options: -threaded -rtsopts -with-rtsopts=-N 20 | build-depends: base, pandoc-types > 1.17 && < 1.18, process, containers, 21 | directory 22 | default-language: Haskell2010 23 | 24 | source-repository head 25 | type: git 26 | location: https://github.com/githubuser/pandoc-tex2svg 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pandoc-tex2svg 2 | ============== 3 | 4 | pandoc-tex2svg is a pandoc filter that renders math as SVG. 5 | It can be used with HTML5 based output formats, including 6 | EPUB and HTML-based slide shows like reveal.js. 7 | 8 | Here's an example of its output: 9 | [math-samples.html](math-samples.html). This renders 10 | like this in a modern browser: 11 | 12 | ![rendered version of math-samples.html](math-samples.png) 13 | 14 | The filter uses `tex2svg` from 15 | [MathJax-node](https://github.com/mathjax/MathJax-node). 16 | To install using npm, 17 | 18 | npm install -g mathjax-node 19 | 20 | `tex2svg` is assumed to be in the path. Note that the default 21 | install does not put it in the path; you will have to do this 22 | manually. 23 | 24 | To compile and install the filter: 25 | 26 | stack install 27 | 28 | or 29 | 30 | cabal install 31 | 32 | Make sure the filter is in your path (stack puts executables in 33 | `$HOME/.local/bin`). 34 | 35 | To use the filter with pandoc (currently pandoc 1.18 is required): 36 | 37 | pandoc math-samples.md --filter pandoc-tex2svg -s -t html5 -o math-samples.html 38 | 39 | The filter is rather slow, and it adds significantly to file 40 | size, but the resulting HTML renders quickly and does not depend 41 | on an internet connection or JavaScript. 42 | 43 | Thanks to Kolen Cheung for the suggestion. 44 | 45 | -------------------------------------------------------------------------------- /math-samples.md: -------------------------------------------------------------------------------- 1 | Inline math 2 | ----------- 3 | 4 | The area of a circle with radius $r$ is $\pi r^2$. 5 | The volume of a cube with radius $r$ is $\frac{4}{3} \pi r^3$. 6 | 7 | The Lorenz Equations 8 | -------------------- 9 | 10 | $$ 11 | \begin{aligned} \dot{x} & = \sigma(y-x) \\ \dot{y} & = \rho x - y 12 | - xz \\ \dot{z} & = -\beta z + xy \end{aligned} 13 | $$ 14 | 15 | 16 | The Cauchy-Schwarz Inequality 17 | ----------------------------- 18 | 19 | $$ 20 | \left( \sum_{k=1}^n a_k b_k \right)^{\!\!2} \leq 21 | \left( \sum_{k=1}^n a_k^2 \right) \left( \sum_{k=1}^n 22 | b_k^2 \right) 23 | $$ 24 | 25 | A Cross Product Formula 26 | ----------------------- 27 | 28 | $$ 29 | \mathbf{V}_1 \times \mathbf{V}_2 = \begin{vmatrix} 30 | \mathbf{i} & \mathbf{j} & \mathbf{k} \\ \frac{\partial 31 | X}{\partial u} & \frac{\partial Y}{\partial u} & 0 \\ 32 | \frac{\partial X}{\partial v} & \frac{\partial Y}{\partial v} & 33 | 0 \\ \end{vmatrix} 34 | $$ 35 | 36 | The probability of getting \(k\) heads when flipping \(n\) coins is: 37 | ------------------------------------------------------------------------ 38 | $$ 39 | P(E) = {n \choose k} p^k (1-p)^{ n-k} 40 | $$ 41 | 42 | An Identity of Ramanujan 43 | ------------------------ 44 | $$ 45 | \frac{1}{(\sqrt{\phi \sqrt{5}}-\phi) e^{\frac25 \pi}} = 46 | 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}} 47 | {1+\frac{e^{-8\pi}} {1+\ldots} } } } 48 | $$ 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright John MacFarlane (c) 2016 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following 12 | disclaimer in the documentation and/or other materials provided 13 | with the distribution. 14 | 15 | * Neither the name of Author name here nor the names of other 16 | contributors may be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /pandoc-tex2svg.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ScopedTypeVariables #-} 2 | 3 | module Main where 4 | import Text.Pandoc.JSON 5 | import Control.Monad (when) 6 | import System.Exit 7 | import System.Process 8 | import Data.IORef 9 | import qualified Data.Map as M 10 | import System.Directory (findExecutable) 11 | import System.IO (stderr, hPutStrLn) 12 | 13 | newtype Cache = Cache (M.Map (MathType, String) String) 14 | 15 | lookupCache :: (MathType, String) -> Cache -> Maybe String 16 | lookupCache s (Cache c) = M.lookup s c 17 | 18 | addToCache :: (MathType, String) -> String -> Cache -> Cache 19 | addToCache s v (Cache c) = Cache $ M.insert s v c 20 | 21 | main :: IO () 22 | main = do 23 | cache <- newIORef (Cache M.empty) 24 | toJSONFilter (tex2svg cache) 25 | 26 | tex2svg :: IORef Cache -> Inline -> IO Inline 27 | tex2svg cr (Math mt math) = do 28 | mbfp <- findExecutable "tex2svg" 29 | when (mbfp == Nothing) $ do 30 | hPutStrLn stderr $ "The tex2svg program was not found in the path.\n" ++ 31 | "Install MathJax-node (https://github.com/mathjax/MathJax-node)\n" ++ 32 | "and ensure that tex2svg is in your path." 33 | exitWith $ ExitFailure 1 34 | cache <- readIORef cr 35 | svg <- case lookupCache (mt, math) cache of 36 | Just s -> return s 37 | Nothing -> do 38 | svg' <- readProcess "tex2svg" 39 | (["--inline" | mt == InlineMath] ++ [math]) "" 40 | modifyIORef cr (addToCache (mt, math) svg') 41 | return svg' 42 | if null svg -- indicates an error -- tex2svg doesn't return error status 43 | then do 44 | hPutStrLn stderr $ "Could not convert: " ++ math 45 | return $ Math mt math 46 | else return $ RawInline (Format "html") $ 47 | "" ++ 49 | svg ++ "" 50 | tex2svg _ il = return il 51 | 52 | -------------------------------------------------------------------------------- /math-samples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 |

Inline math

15 |

The area of a circle with radius 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | is 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | . The volume of a cube with radius 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | is 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | .

66 |

The Lorenz Equations

67 |

68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 |

132 |

The Cauchy-Schwarz Inequality

133 |

134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 |

212 |

A Cross Product Formula

213 |

214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 |

325 |

The probability of getting (k) heads when flipping (n) coins is:

326 |

327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 |

374 |

An Identity of Ramanujan

375 |

376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 |

504 | 505 | 506 | --------------------------------------------------------------------------------