@curvenote/schema
Version:
Schema and markdown parser for @curvenote/editor
127 lines • 5.63 kB
JavaScript
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