import { App, Editor, Modal, Notice, Plugin, Setting, sanitizeHTMLToDom } from 'obsidian'; import { replacements, combiningmarks, subsuperscripts } from './data.ts'; export default class LaTeXtoUnicode extends Plugin { async onload() { this.addCommand({ id: "latex-to-unicode", name: "LaTeX to Unicode", editorCallback: (editor: Editor) => { const onSubmit = (res: string) => { const pos = editor.getCursor(); editor.replaceRange(`${res}`, pos); editor.setCursor(pos); }; new LaTeXToUnicodeModal(this.app, onSubmit).open(); }, }); } } export class LaTeXToUnicodeModal extends Modal { res: string; onSubmit: (res: string) => void; constructor( app: App, onSubmit: (res: string) => void ) { super(app); this.onSubmit = onSubmit; } onOpen() { const { contentEl } = this; contentEl.createEl("h1", { text: "LaTeX to Unicode" }); const elContainer = contentEl.createEl('table'); elContainer.className = 'latexInputTable'; const first = elContainer.createEl('tr'); first.createEl('td', {text: 'LaTeX command'}); const elInput = first.createEl('td').createEl('input', {type: 'text'}); elInput.id = 'userInput'; elInput.addEventListener("input", (e) => { this.res = replace(e.target.value); document.getElementById('resDisp').value = this.res; }); const second = elContainer.createEl('tr'); second.createEl('td', {text: 'Result'}); const elRes = second.createEl('td').createEl('input', {type: 'text'}); elRes.id = 'resDisp'; elRes.readOnly = true; new Setting(contentEl).addButton((btn) => btn .setButtonText("Insert") .setCta() .onClick(() => { this.onSubmit(this.res); }) ); } onClose() { let { contentEl } = this; contentEl.empty(); } } // From: https://github.com/svenkreiss/unicodeit/blob/master/ts_src/replace.ts export function replace(f: string): string { // escape combining marks with a space after the backslash for (const ic in combiningmarks) { const c = combiningmarks[ic]; let i = -1; while ( (i = f.indexOf(c[0], i+1)) > -1 && f.indexOf("}", i+1) > i ) { f = f.slice(0, i+1) + ' ' + f.slice(i+1); } } // console.log(replacements); for (const ir in replacements) { const r = replacements[ir]; // dirty way of a replaceAll(): f = f.split(r[0]).join(r[1]); if (r[0].slice(-2) == '{}') { f = f.split('\\ '+r[0].slice(1)).join(r[1]); } } // expand groups of subscripts: _{01234} let isub = -1; while ( (isub = f.indexOf("_{", isub+1)) > -1 && f.indexOf("}", isub+1) > isub ) { f = f.slice(0, isub) + '_' + f[isub+2] + '_{' + f.slice(isub+3); f = f.replace('_{}', ''); } // expand groups of superscripts: ^{01234} let isup = -1; while ( (isup = f.indexOf("^{", isup+1)) > -1 && f.indexOf("}", isup+1) > isup ) { f = f.slice(0, isup) + '^' + f[isup+2] + '^{' + f.slice(isup+3); f = f.replace('^{}', ''); } // now replace subsuperscripts for (const ir in subsuperscripts) { const r = subsuperscripts[ir]; // dirty way of a replaceAll(): f = f.split(r[0]).join(r[1]); } // combining marks (unicode char modifies previous char) for (const ic in combiningmarks) { const c = combiningmarks[ic]; let i = -1; while ( (i = f.indexOf('\\ '+c[0].slice(1)+'{', i+1)) > -1 && f.indexOf("}", i+1) > i ) { const newString = f[i+c[0].length+2] + c[1]; f = f.slice(0,i)+newString+f.slice(i+1+c[0].length+3); } } return f; }