UNPKG

@curvenote/schema

Version:

Schema and markdown parser for @curvenote/editor

127 lines 5.63 kB
import { cleanWhitespaceChars } from '../clean'; import { indent } from '../indent'; export function createLatexStatement(opts, f) { return (state, node, p, i) => { const options = typeof opts === 'string' ? { command: opts } : opts(state, node); if (options == null) { f(state, node, p, i); state.closeBlock(node); return; } const { command, commandOpts, bracketOpts, inline, before, after } = options; if (before) state.out += `\n${state.delim}${before}`; const optsInCommand = commandOpts ? `{${commandOpts}}` : ''; const optsInBrackets = bracketOpts ? `[${bracketOpts}]` : ''; state.write(inline ? `\\${command}{\n` : `\\begin{${command}}${optsInCommand}${optsInBrackets}\n`); const dedent = indent(state); f(state, node, p, i); dedent(); state.out += inline ? `\n${state.delim}}` : `\n${state.delim}\\end{${command}}`; if (after) state.out += `\n${state.delim}${after}`; state.closeBlock(node); }; } export const blankTex = (state, node) => { state.write(`{\\bf \`${node.type.name}' not supported in \\LaTeX}`); }; export const blankTexLines = (state, node) => { state.ensureNewLine(); state.write(`{\\bf \`${node.type.name}' not supported in \\LaTeX}`); state.ensureNewLine(); }; // Funky placeholders (unlikely to be written ...?!) const BACKSLASH_SPACE = '💥🎯BACKSLASHSPACE🎯💥'; const BACKSLASH = '💥🎯BACKSLASH🎯💥'; const TILDE = '💥🎯TILDE🎯💥'; const textOnlyReplacements = { // Not allowed characters // Latex escaped characters are: \ & % $ # _ { } ~ ^ '&': '\\&', '%': '\\%', $: '\\$', '#': '\\#', _: '\\_', '{': '\\{', '}': '\\}', '^': '\\^', // quotes '’': "'", '‘': '`', '”': "''", '“': '``', // guillemots '»': '>>', '«': '<<', '…': '\\dots', '–': '--', '—': '---', '©': '\\textcopyright', '®': '\\textregistered', '™': '\\texttrademark', '<': '\\textless', '>': '\\textgreater', }; const arrows = { '↔': '\\leftrightarrow', '⇔': '\\Leftrightarrow', '→': '\\rightarrow', '⇒': '\\Rightarrow', '←': '\\leftarrow', '⇐': '\\Leftarrow', }; const symbols = { '−': '-', '-': '-', '﹣': '-', '-': '-', '+': '+', // Full-width Plus }; const textReplacements = Object.assign(Object.assign(Object.assign({}, textOnlyReplacements), arrows), symbols); const mathReplacements = Object.assign(Object.assign(Object.assign({}, arrows), symbols), { '½': '\\frac{1}{2}', '⅓': '\\frac{1}{3}', '⅔': '\\frac{2}{3}', '¼': '\\frac{1}{4}', '⅕': '\\frac{1}{5}', '⅖': '\\frac{2}{5}', '⅗': '\\frac{3}{5}', '⅘': '\\frac{4}{5}', '⅙': '\\frac{1}{6}', '⅚': '\\frac{5}{6}', '⅐': '\\frac{1}{7}', '⅛': '\\frac{1}{8}', '⅜': '\\frac{3}{8}', '⅝': '\\frac{5}{8}', '⅞': '\\frac{7}{8}', '⅑': '\\frac{1}{9}', '⅒': '\\frac{1}{10}', '±': '\\pm', Α: 'A', α: '\\alpha', Β: 'B', β: '\\beta', ß: '\\beta', Γ: '\\Gamma', γ: '\\gamma', Δ: '\\Delta', '∆': '\\Delta', δ: '\\delta', Ε: 'E', ε: '\\epsilon', Ζ: 'Z', ζ: '\\zeta', Η: 'H', η: '\\eta', Θ: '\\Theta', θ: '\\theta', ϑ: '\\vartheta', Ι: 'I', ι: '\\iota', Κ: 'K', κ: '\\kappa', Λ: '\\Lambda', λ: '\\lambda', Μ: 'M', μ: '\\mu', Ν: 'N', ν: '\\nu', Ξ: '\\Xi', ξ: '\\xi', Ο: 'O', ο: 'o', Π: '\\Pi', π: '\\pi', Ρ: 'P', ρ: '\\rho', Σ: '\\Sigma', σ: '\\sigma', Τ: 'T', τ: '\\tau', Υ: '\\Upsilon', υ: '\\upsilon', Φ: '\\Phi', ϕ: '\\phi', φ: '\\varphi', Χ: 'X', χ: '\\chi', Ψ: '\\Psi', ψ: '\\psi', Ω: '\\Omega', ω: '\\omega', '∂': '\\partial', '∞': '\\infty', '≈': '\\approx', '≠': '\\neq', '•': '\\cdot' }); export function stringToLatexText(text) { const escaped = (text !== null && text !== void 0 ? text : '') .replace(/\\ /g, BACKSLASH_SPACE) .replace(/\\/g, BACKSLASH) .replace(/~/g, TILDE); const replacedArray = Array(...escaped).map((char) => { if (textReplacements[char]) return { kind: 'text', text: textReplacements[char] }; if (mathReplacements[char]) return { kind: 'math', text: mathReplacements[char] }; return { kind: 'text', text: char }; }); const replaced = replacedArray .reduce((arr, next) => { // Join any strings of math or text together (avoids $\delta$$\mu$ --> $\delta\mu$) const prev = arr.slice(-1)[0]; if ((prev === null || prev === void 0 ? void 0 : prev.kind) === next.kind) prev.text += next.text; else arr.push(next); return arr; }, []) .reduce((s, next) => { if (next.kind === 'math') return `${s}$${next.text}$`; return s + next.text; }, ''); const final = replaced .replace(new RegExp(BACKSLASH_SPACE, 'g'), '{\\textbackslash}~') .replace(new RegExp(BACKSLASH, 'g'), '{\\textbackslash}') .replace(new RegExp(TILDE, 'g'), '{\\textasciitilde}'); return cleanWhitespaceChars(final, '~'); } export function stringToLatexMath(text) { const replaced = Array(...(text !== null && text !== void 0 ? text : '')).reduce((s, char) => { if (mathReplacements[char]) { const space = s.slice(-1) === ' ' ? '' : ' '; return `${s}${space}${mathReplacements[char]}`; } return s + char; }, ''); const final = replaced.trim(); return cleanWhitespaceChars(final); } //# sourceMappingURL=utils.js.map