search

Home  >  Q&A  >  body text

Simplify input of mathematical symbols to make it easier for you on the Internet

Is there a solution for a React library that allows users to easily enter mathematical symbols and have them converted to LaTeX on the backend? I mean, like a user-friendly editor, maybe with clickable buttons? These elements are then converted to LaTeX on the backend.

P粉057869348P粉057869348426 days ago586

reply all(1)I'll reply

  • P粉637866931

    P粉6378669312023-09-15 11:44:19

    You can try using MathJax. Version 3 is the latest version and is very powerful.

    According to this question, it is the best JavaScript LaTeX renderer.

    In the example below, you can render existing content to LaTeX, or add elements dynamically.

    const expressions = [
      '\frac{a}{b}',
      '\(V = {4 \over 3} \pi^3 \)'
    ];
    
    document.querySelectorAll('.expression').forEach(el => {
      el.replaceWith(MathJax.tex2chtml(el.textContent));
    });
    
    expressions.forEach(expression => {
      document.body.append(MathJax.tex2chtml(expression));
    });
    html, body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    body {
      display: flex;
      justify-content: space-around;
      align-items: center;
    }
    
    body > * {
      border: thin solid grey;
      padding: 1rem;
    }
    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
    <div class="expression">(\int_{a}^{b} x^2 \,dx)</div>

    Parse infix expressions into LaTeX

    If you want to interpret the expression and convert it to LaTeX, you can try the following:

    const form = document.forms['latex-add'];
    const container = document.querySelector('#expression-list');
    const expressions = ['\frac{a}{b}', '\frac{{(25 \cdot 5)}}{6}'];
    
    const main = () => {
      form.elements.expression.value = '(25*5)/b';
      form.addEventListener('submit', handleAdd);
      renderExpressions();
    };
    
    const handleAdd = (e) => {
      e.preventDefault();
      const expression = e.target.elements.expression.value.trim();
      const tex = texFromExpression(expression);
      console.log(tex);
      expressions.push(tex);
      renderExpressions();
      e.target.reset();
    };
    
    const renderExpressions = () => {
      container.innerHTML = '';
      expressions.forEach(expression => {
        const wrapper = document.createElement('div');
        wrapper.classList.add('expression');
        const tex = document.createElement('div');
        tex.classList.add('tex');
        tex.textContent = expression;
        wrapper.append(tex);
        wrapper.append(MathJax.tex2chtml(expression));
        container.append(wrapper);
      });
    };
    
    // Credit: https://stackoverflow.com/a/57449164/1762224
    const texFromExpression = (str) => {
      let pos = -1, ch;
    
      const nextChar = () => {
        ch = (++pos < str.length) ? str.charAt(pos) : -1;
      };
    
      const eat = (charToEat) => {
        while (ch == ' ') nextChar();
        if (ch == charToEat) {
          nextChar();
          return true;
        }
        return false;
      };
    
      const parse = () => {
        nextChar();
        const x = parseExpression();
        if (pos < str.length) throw new Error(`Unexpected: ${ch}`)
        return x;
      };
    
      const parseExpression = () => {
        let x = parseTerm();
        while (true) {
          if (eat('+')) x = `${x} + ${parseTerm()}` // addition
          else if (eat('-')) x = `${x} - ${parseTerm()}` // subtraction
          else return x;
        }
      };
    
      const parseTerm = () => {
        var x = parseFactor();
        while (true) {
          if (eat('*')) x = `${x} \cdot ${parseTerm()}`; // multiplication
          else if (eat('/')) x = `\frac{${x}}{${parseTerm()}}`; // division
          else return x;
        }
      };
    
      const parseFactor = () => {
        if (eat('+')) return parseFactor(); // unary plus
        if (eat('-')) return `-${parseFactor()}`; // unary minus
        let x;
        const startPos = pos;
        if (eat('(')) { // parentheses
          x = `{(${parseExpression()})}`
          eat(')');
        } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
          while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
          x = str.substring(startPos, pos);
        } else if (ch >= 'a' && ch <= 'z') { // variables
          while (ch >= 'a' && ch <= 'z') nextChar();
          x = str.substring(startPos, pos);
          if (x.length > 1) {
            x = `\${x} {${parseFactor()}}`;
          }
        } else {
          throw new Error(`Unexpected: ${ch}`);
        }
        if (eat('^')) x = `${x} ^ {${parseFactor()}}` // superscript
        if (eat('_')) x = `${x}_{${parseFactor()}}`;
        return x;
      }
      return parse();
    }
    
    main();
    #expression-list {
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      gap: 0.5rem;
    }
    
    .expression {
      padding: 0.5rem;
      border: thin solid grey;
    }
    
    .tex {
      font-family: monospace;
      font-size: smaller;
    }
    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
    <form name="latex-add" autocomplete="off">
      <label for="expression">Expression:</label>
      <input type="text" id="expression" name="expression"
             value="" placeholder="Expression..." />
      <button type="submit">Add</button>
    </form>
    <hr />
    <div id="expression-list"></div>

    reply
    0
  • Cancelreply