Giter Club home page Giter Club logo

latexmath's Introduction

latexmath

Gem Version Build Status Code Climate Pull Requests Commits since latest

Purpose

Ruby gem to translate LaTeX math into MathML. The MathML is supposed to be compliant with output of LaTeXML.

It also works in reverse by translating MathML into LaTeX code.

The LaTeX math syntax supports amsmath, array, split and pmatrix packages.

Note
Bolding, symbols like \backepsilon, equation alignment, are all supported.

Usage

require "latexmath"

latex = "$$f_i =  \sum_{j=1}^2 s_{ij} n_j \quad {\rm for} \quad i = 1,2$$"
mathml = Latexmath.parse(latex).to_mathml

latexmath's People

Contributors

ronaldtse avatar manzhikov avatar opoudjis avatar webdev778 avatar camobap avatar infinity0 avatar

Stargazers

 avatar Andrii Konchyn avatar expeehaa avatar  avatar

Watchers

 avatar Sebastian Skałacki avatar  avatar Anton Strogonoff avatar James Cloos avatar  avatar Alexander Dyuzhev avatar Frank Hofmann avatar Vasil Buraliev avatar  avatar KW Kwan avatar Manuel Fuenmayor avatar

latexmath's Issues

Array examples

\left( \begin{array}{c}
N_{xx}\\
N_{yy}\\
N_{xy}\\
M_{xx}\\
M_{yy}\\
M_{xy} \end{array} \right)
   \left(
\begin{array}{ccc}
s_{11}  & 0  & 0      \\
0  & s_{22}  & 0      \\
0  & 0  & s_{33}
\end{array}
\right)
\[  \left(
\begin{array}{cccccc}
d_{1111} & d_{1122} & d_{1133} & d_{1112} & d_{1123} & d_{1131} \\
         & d_{2222} & d_{2233} & d_{2212} & d_{2223} & d_{2231} \\
         &          & d_{3333} & d_{3312} & d_{3323} & d_{3331} \\
         &          &          & d_{1212} & d_{1223} & d_{1231} \\
         & \mbox{symmetric} & & & d_{2323} & d_{2331} \\
         &          &          &          &          & d_{3131}
\end{array}
\right) \]
   \left(
\begin{array}{cccccc}
{\displaystyle \frac{1}{E}} & -{\displaystyle \frac{\nu}{E}} & -{\displaystyle
\frac{\nu}{E}} & 0      & 0      & 0      \\[3mm]
            & {\displaystyle \frac{1}{E}}    & -{\displaystyle \frac{\nu}{E}} & 0

& 0      & 0      \\[3mm]
            &                & {\displaystyle \frac{1}{E}}    & 0      & 0      & 0

  \\[3mm]
            &                &        &  {\displaystyle \frac{1}{G}}   & 0      & 0

  \\[3mm]
            & \mbox{symmetric} &  &   & {\displaystyle \frac{1}{G}}    & 0

    \\[3mm]
            &                &        &        &        & {\displaystyle \frac{1}{G}}

\end{array}
\right)
J = \left( \begin{array}{cc}
  {\displaystyle \frac{\partial u}{\partial x}}   &
        {\displaystyle \frac{\partial v}{\partial x}}   \\[3mm]
    {\displaystyle \frac{\partial u}{\partial y}}    &
        {\displaystyle \frac{\partial v}{\partial y}}
       \end{array}  \right)
\begin{array}{cc}
\left(    \begin{array}{ccccccc}
        & & & & & & \\
        & +k & & & & -k  \\
        & & & & & & \\
        & & & & & & \\
        & & & & & & \\
        & -k & & & & +k
    \end{array}  \right)   &
         \begin{array}{cc}
                  & \\
                  \cdots & \mbox{degree of freedom 1, node 1} \\
                  & \\
                  & \\
                  & \\
                  \cdots & \mbox{degree of freedom 2, node 2}
         \end{array}      \\
                     & \\
        \begin{array}{cccccc}
           \vdots & & & & & \vdots
     \end{array}  & \\
     \begin{array}{cccc}
& \mbox{degree of}  & \mbox{degree of}  & \\
& \mbox{freedom 1,} & \mbox{freedom 2,} & \\
& \mbox{node 1} & \mbox{node 2}  &
    \end{array}    &
\end{array}
\[  \left(
\begin{array}{cccccc}
d_{1111} & d_{1122} & d_{1133} & d_{1112} & d_{1123} & d_{1131} \\
         & d_{2222} & d_{2233} & d_{2212} & d_{2223} & d_{2231} \\
         &          & d_{3333} & d_{3312} & d_{3323} & d_{3331} \\
         &          &          & d_{1212} & d_{1223} & d_{1231} \\
         & \mbox{symmetric} & & & d_{2323} & d_{2331} \\
         &          &          &          &          & d_{3131}
\end{array}
\right) \]
D' =
\left( \begin{array}{cc}
      h \, D_m    &        h \, p \, D_m  \\[2mm]
      h \, p \, D_m  &  {\displaystyle (\frac{1}{12} h^3 + h \, p^2) \, D_m  }
\end{array} \right)
\left( \begin{array}{c}
      V_x  \\
      V_y  \end{array} \right)  =
          h_s \: D_s \: \left( \begin{array}{c}
                    \varepsilon_{xz}   \\
                    \varepsilon_{yz}    \end{array} \right)
\varepsilon =
      \left( \begin{array}{c}
      {\displaystyle  \frac{\partial w}{\partial x} +
                      \frac{\partial u}{\partial z} }  \\[2mm]
      {\displaystyle  \frac{\partial w}{\partial y} +
                      \frac{\partial v}{\partial z} }
                                     \end{array} \right)
c =
   \left( \begin{array}{cc}
 {\displaystyle - \frac{\partial^2 w}{\partial x^2} } &
          {\displaystyle - \frac{\partial^2 w}{\partial x \partial y} } \\[2mm]
 {\displaystyle - \frac{\partial^2 w}{\partial x \partial y} } &
          {\displaystyle - \frac{\partial^2 w}{\partial y^2} }

                                     \end{array} \right)
\begin{array}{ccc}
 x' = x/L, & u' = u/(L/T), & \rho' = \rho/(M/L^3), \\
 y' = y/L, & v' = v/(L/T), & p' = p/(M/(L T^2)), \\
 z' = z/L, \quad & w' = w/(L/T), \quad & \mu' = \mu/(M/(L T)),
\end{array}

Split examples

\begin{split}
C_L &= {L \over {1\over2} \rho_\textrm{ref} q_\textrm{ref}^2 S} \\ \\
C_D &= {D \over {1\over2} \rho_\textrm{ref} q_\textrm{ref}^2 S} \\ \\
\vec{C}_M &= {\vec{M} \over {1\over2} \rho_\textrm{ref} q_\textrm{ref}^2 c_\textrm{ref} S_\textrm{ref}},
\end{split}
\begin{split}
 p''_{ijk} &\equiv p_{ijk} / (\rho_\textrm{ref} c_\textrm{ref}^2)[.02in] \\ \\
 \displaystyle &{}= {p_{ijk} \over M/(L T^2)} {M/L^3 \over \rho_\textrm{ref}} \left[ L/T \over c_\textrm{ref} \right]^2 \\ \\
 \displaystyle &{}= p'_{ijk} / (\rho'_\textrm{ref} (c'_\textrm{ref})^2)
\end{split}

does not render \sqrt{..}^{..} correctly

latexmath gets confused by the combination of \sqrt and ^. With \sqrt{a}^{b} instead the output looks like \sqrt(^) a b:

<mrow><msqrt><mi>^</mi></msqrt><mrow><mi>&#x00061;</mi></mrow><mrow><mi>&#x00062;</mi></mrow></mrow>

It should instead be:

  <msup>
    <msqrt>
      <mi>a</mi>
    </msqrt>
    <mi>b</mi>
  </msup>

Implement latexmath gem that converts LaTeX math to MathML

This work is to port LaTeXMathML.js [1] to Ruby, with the following functionality:

  1. The Ruby code should be able to translate LaTeX math into MathML.
  2. The Ruby code should also be able to work in reverse, by translating MathML into LaTeX code.
  3. The LaTeX math syntax should also accept syntax from the LaTeX amsmath package. (bolding, symbols like \backepsilon, equation alignment)

You should:
a. Check Ruby parsing libraries like oedipus_lex, rsec, parslet, treetop on creating parsing rules for LaTeX (and math) environments
b. Check how the asciimath [2] gem is implemented.

Example correctness should follow the output of latexmlmath with amsmath and amssymb enabled. This command is part of LaTeXML. You can find installation instructions at https://dlmf.nist.gov/LaTeXML/ .

The way to run latexmlmath is like this:

cat equation.tex | latexmlmath --strict --preload=amsmath -- -

e.g.

$ echo "\varepsilon = \frac{1}{2} ( J + J^t )"  | latexmlmath --strict --preload=amsmath -- -
<?xml version="1.0" encoding="UTF-8"?>
<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="\varepsilon=\frac{1}{2}(J+J^{t})" display="block">
  <mrow>
    <mi>ε</mi>
    <mo>=</mo>
    <mrow>
      <mfrac>
        <mn>1</mn>
        <mn>2</mn>
      </mfrac>
      <mo>⁢</mo>
      <mrow>
        <mo stretchy="false">(</mo>
        <mrow>
          <mi>J</mi>
          <mo>+</mo>
          <msup>
            <mi>J</mi>
            <mi>t</mi>
          </msup>
        </mrow>
        <mo stretchy="false">)</mo>
      </mrow>
    </mrow>
  </mrow>
</math>

(It is necessary to use cat and pipe because there are multiline equations, and symbols in LaTeX can conflict with your shell)

We want to use latexmlmath in RSpec to ensure the parsed/converted output is always correct.

The basic structure of latexmath and its specs are created -- steps:

  1. Add all the samples to the specs
  2. Parse and ensure all the MathML of specs are generated correctly.

[1] LaTeXMathML.js: http://math.etsu.edu/LaTeXMathML/LaTeXMathML.js
[2] Asciimath gem: https://github.com/asciidoctor/asciimath/

Vector marco (`\vec{...}`) disables rendering of math symbols

When vector macro (\vec{...}) is applied to math symbols, the rendering of the symbol gets disabled:

latexmath:[\vec{\lambda}], latexmath:[\vec{\theta}], latexmath:[\vec{\delta}], latexmath:[\vec{\xi}],
latexmath:[\vec{\pi}], latexmath:[\vec{\sigma}] latexmath:[\vec{\gamma}], latexmath:[\vec{\psi}], latexmath:[\vec{\omega}]

renders:
issue5

Fix specs due to Snap latexml package

Error: Unable to process command '::add-path::/snap/bin' successfully.
7
Error: The `add-path` command is disabled. Please upgrade to using Environment Files or opt into unsecure command execution by setting the `ACTIONS_ALLOW_UNSECURE_COMMANDS` environment variable to `true`. For more information see: https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/

Ping @CAMOBAP

Originally posted by @ronaldtse in #38 (comment)

Pmatrix examples

\begin{pmatrix}
\hat{e}_{\xi} \\ \hat{e}_{\eta} \\ \hat{e}_{\zeta}
\end{pmatrix}
= {\bf T} 
\begin{pmatrix}
\hat{e}_x \\ \hat{e}_y \\ \hat{e}_z
\end{pmatrix},

Multi-line examples

V = \frac{1}{2} \: {\bf u}^t \:
            \int_{surface} \: \int_{thickness} \: B^t \: D \: B \: dt \: ds
               \; {\bf u}
s_{ij} =  \sum_{k=1}^2 \sum_{l=1}^2 d_{ijkl} e_{kl} \;
 {\rm for} \; i = 1,2 \; {\rm and} \; j = 1,2
\Delta \sigma_{ij} =  \sum_{k=1}^3 \sum_{l=1}^3 d_{ijkl} (\Delta \varepsilon_{kl} -
 \alpha_{kl}\Delta T - \beta_{kl}\Delta M)  \;
 {\rm for} \; i = 1,3 \; {\rm and} \; j = 1,3
c_l = {L' \over {1\over2} \rho_\textrm{ref} q_\textrm{ref}^2 c_\textrm{ref}} \qquad
c_d = {D' \over {1\over2} \rho_\textrm{ref} q_\textrm{ref}^2 c_\textrm{ref}} \qquad
\vec{c}_m = {\vec{M}' \over {1\over2} \rho_\textrm{ref} q_\textrm{ref}^2 c_\textrm{ref}^2},
-\overline{u'_i u'_j} = \nu_{t} \left(
                  \frac{\partial u_i }{\partial x_j } +
                  \frac{\partial u_j }{\partial x_i }
                  \right)
S_i =  \sum_{j=1}^{6} D_{ij} (E_{j} - E_{j}^{T} - E_{j}^{M})  \;
 {\rm for} \; i = 1,6
m =    {\bf M}^{t}  \:
          \left( \begin{array}{c} n_y \\ n_z \end{array} \right)

Multiple math symbols are not supported

Symbols like \Theta, \Lambda, etc., are not being supported:

latexmath:[\Lambda], latexmath:[\Theta], latexmath:[\Delta], latexmath:[\Xi], latexmath:[\Pi], latexmath:[\Sigma]
latexmath:[\Gamma], latexmath:[\Psi], latexmath:[\Omega]

latexmath:[\lambda], latexmath:[\theta], latexmath:[\delta], latexmath:[\xi], latexmath:[\pi], latexmath:[\sigma]
latexmath:[\gamma], latexmath:[\psi], latexmath:[\omega]

renders
issue1

Same happens with math calligraphy:

latexmath:[\cal{A}], latexmath:[\cal{B}], latexmath:[\cal{C}], latexmath:[\cal{D}],
latexmath:[\cal{E}], latexmath:[\cal{F}], latexmath:[\cal{G}], latexmath:[\cal{H}]

renders
issue2-2

Simple parsing samples

\varepsilon = \frac{1}{2} ( J + J^t )
$$f_i =  \sum_{j=1}^2 s_{ij} n_j \quad {\rm for} \quad i = 1,2$$
G = {\displaystyle \frac{E}{2(1 + \nu)}}
\bf{x^\prime} = \bf{\xi}
\bf{z^\prime} = \langle \bf{\xi} \times \bf{\eta} \rangle
\bf{z} = \langle \bf{x} \times \bf{d} \rangle
\bf{y} \cdot \bf{d} > tolerance \, |\bf{y}| \, |\bf{d}|
Q =  \sum_{i=1}^n \: s_i \: j_i \: w_i \: q_i
\Delta\sigma_{ij} = \sum_{k=1}^3 \sum_{l=1}^3  d_{ijkl} \: \Delta\varepsilon_{kl}
 \varepsilon_{ij} =  \alpha_{ij} \: ( T \:  -  \: T_o )
 \Delta D_{ij} =  \sum_{k=1}^2 \sum_{l=1}^2  d_{ijkl} \: \Delta c_{kl}
\varepsilon = B \: {\bf u}
\vec{M} = M_\xi \hat{e}_{\xi} + M_\eta \hat{e}_{\eta} + M_\zeta \hat{e}_{\zeta} = \int (\vec{r} - \vec{r}_0) \times \vec{f} \,dA.
- \overline{u' v'} = \nu_t \left( \frac{\partial u}{\partial y} + \frac{\partial v}{\partial x} \right),
\frac{\Delta \theta}{\Delta L} = \frac{T }{J \: G}
\sum_{i=1}^n \left( a_i \cdot x_i \right)  = b
\left[ \frac{\partial}{\partial t} + (u \pm c) \frac{\partial}{\partial x} \right] \left( u \pm {2\over{\gamma - 1}} c \right) = 0.

Horizonal spacing commands are not supported

Currently, commands like quad and qquad are not supported by latexmath:

[latexmath%unnumbered]
++++
f_i =  \sum_{j=1}^2 s_{ij} n_j \quad {\rm for} \quad i = 1,2
++++

renders
issue4

Also not supported:

  • negative space: \!
  • boldface text: \textbf

Double bar `\bar{\bar{...}}` malformed rendering

There are circumstances where double bar markup (\bar{\bar{...}}) shows a malformed rendering:

Latexmath 1: latexmath:[\bar{\bar{\tau}}_{i,j}]

Latexmath 2: latexmath:[\bar{\bar{\tau}}]

Stem: stem:[bar bar tau_{i,j}]

renders

issue3

Apparently, the problem arises when there is a subscript present.

Spec failures in Opal version

Only two failures in Opal:

Failures:

  1) Latexmath::Aggregator array #5
     Failure/Error: expect(Latexmath::Aggregator.new(tokens).aggregate).to eq(param[2])
     
       expected: ["\\array", "cc", [[["\\left", "(", ["\\array", "ccccccc", [[nil, nil, nil, nil, nil, nil, nil], [nil...x{freedom 1,}", "\\mbox{freedom 2,}", nil], [nil, "\\mbox{node 1}", "\\mbox{node 2}", nil]]], nil]]]
            got: ["\\array", "cc", [[["\\left", "(", ["\\array", "ccccccc", [[{"$$id"=>4}, {"$$id"=>4}, {"$$id"=>4}, {...2,}", {"$$id"=>4}], [{"$$id"=>4}, "\\mbox{node 1}", "\\mbox{node 2}", {"$$id"=>4}]]], {"$$id"=>4}]]]
     
       (compared using ==)
     
       Diff:
       
       
       
       
       
       @@ -4,28 +4,70 @@
            "(",
            ["\\array",
             "ccccccc",
       -     [[nil, nil, nil, nil, nil, nil, nil],
       -      [nil, ["+", "k"], nil, nil, nil, ["-", "k"]],
       -      [nil, nil, nil, nil, nil, nil, nil],
       -      [nil, nil, nil, nil, nil, nil, nil],
       -      [nil, nil, nil, nil, nil, nil, nil],
       -      [nil, ["-", "k"], nil, nil, nil, ["+", "k"]]]],
       +     [[{"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4}],
       +      [{"$$id"=>4},
       +       ["+", "k"],
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       ["-", "k"]],
       +      [{"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4}],
       +      [{"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4}],
       +      [{"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4}],
       +      [{"$$id"=>4},
       +       ["-", "k"],
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       {"$$id"=>4},
       +       ["+", "k"]]]],
            "\\right",
            ")"],
           ["\\array",
            "cc",
       -    [[nil, nil],
       +    [[{"$$id"=>4}, {"$$id"=>4}],
             ["\\cdots", "\\mbox{degree of freedom 1, node 1}"],
       -     [nil, nil],
       -     [nil, nil],
       -     [nil, nil],
       +     [{"$$id"=>4}, {"$$id"=>4}],
       +     [{"$$id"=>4}, {"$$id"=>4}],
       +     [{"$$id"=>4}, {"$$id"=>4}],
             ["\\cdots", "\\mbox{degree of freedom 2, node 2}"]]]],
       -  [nil, nil],
       -  [["\\array", "cccccc", ["\\vdots", nil, nil, nil, nil, "\\vdots"]], nil],
       +  [{"$$id"=>4}, {"$$id"=>4}],
          [["\\array",
       +    "cccccc",
       +    ["\\vdots",
       +     {"$$id"=>4},
       +     {"$$id"=>4},
       +     {"$$id"=>4},
       +     {"$$id"=>4},
       +     "\\vdots"]],
       +   {"$$id"=>4}],
       +  [["\\array",
            "cccc",
       -    [[nil, "\\mbox{degree of}", "\\mbox{degree of}", nil],
       -     [nil, "\\mbox{freedom 1,}", "\\mbox{freedom 2,}", nil],
       -     [nil, "\\mbox{node 1}", "\\mbox{node 2}", nil]]],
       -   nil]]]
       +    [[{"$$id"=>4}, "\\mbox{degree of}", "\\mbox{degree of}", {"$$id"=>4}],
       +     [{"$$id"=>4}, "\\mbox{freedom 1,}", "\\mbox{freedom 2,}", {"$$id"=>4}],
       +     [{"$$id"=>4}, "\\mbox{node 1}", "\\mbox{node 2}", {"$$id"=>4}]]],
       +   {"$$id"=>4}]]]
       
     # ./spec/aggregator_spec.rb:435:in `block (3 levels) in <top (required)>'

  2) Latexmath::Converter issue #75 - 2 rows
     Failure/Error: def convert; $context.eval("Opal.Latexmath.Converter.$new(#{Latexmath.fixnils(@data.to_json)}).$convert()"); end
     
     ExecJS::ProgramError:
       value=: undefined method `value=' for #<Ox::Element:0x58>
     # constructor.$method_missing ((execjs):3907:56)
     # constructor.method_missing_stub ((execjs):1310:35)
     # Opal.send ((execjs):1671:19)
     # constructor.$tag= ((execjs):28185:9)
     # Opal.send ((execjs):1671:19)
     # $$17 ((execjs):26342:13)
     # constructor.$each ((execjs):17272:11)
     # Opal.send ((execjs):1671:19)
     # constructor.$convert_command ((execjs):26329:9)
     # constructor.$classify_subgroup ((execjs):26046:18)
     # ./spec/spec_helper.rb:40:in `convert'
     # ./spec/converter_spec.rb:1944:in `block (3 levels) in <top (required)>'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.