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粉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>
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>