on-codemerge
Version:
A WYSIWYG editor for on-codemerge is a user-friendly interface that allows users to edit and view their code in real time, exactly as it will appear in the final product
177 lines (176 loc) • 7.04 kB
JavaScript
/*! on-codemerge v1.3.1 @author Pavel Kuzmin @license MIT @homepage https://s00d.github.io/on-codemerge/ @repository git+https://github.com/s00d/on-codemerge.git Copyright (c) 2026 Pavel Kuzmin - Built on 2026-07-02T13:39:17.947Z */
var o = Object.defineProperty;
var h = (s, e, t) => e in s ? o(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
var i = (s, e, t) => h(s, typeof e != "symbol" ? e + "" : e, t);
import { PopupManager as p } from "../../../core/ui/PopupManager.mjs";
import { MathRenderer as l } from "../services/MathRenderer.mjs";
import { createContainer as a, createLabel as d, createTextarea as c } from "../../../utils/helpers.mjs";
import { MathToolbar as u } from "./MathToolbar.mjs";
class b {
constructor(e) {
i(this, "editor");
i(this, "mathToolbar");
i(this, "popup");
i(this, "renderer");
i(this, "onInsert", null);
i(this, "editingMath", null);
i(this, "expressionInput", null);
i(this, "previewContainer", null);
i(this, "expression", "");
i(this, "handleInsertSymbol", (e) => {
if (!this.expressionInput) return;
const t = this.expressionInput.selectionStart, n = this.expressionInput.value;
this.expressionInput.value = n.slice(0, t) + e + n.slice(t), this.expressionInput.focus(), this.expressionInput.setSelectionRange(t + e.length, t + e.length), this.handleInputChange(this.expressionInput.value);
});
this.editor = e, this.renderer = new l(), this.mathToolbar = new u(this.handleInsertSymbol), this.popup = new p(e, {
title: e.t("Insert Math"),
className: "math-menu",
closeOnClickOutside: !0,
buttons: [
{
label: e.t("Cancel"),
variant: "secondary",
onClick: () => this.popup.hide()
},
{
label: e.t("Insert"),
variant: "primary",
onClick: () => this.handleSubmit()
}
],
items: this.createPopupItems()
});
}
createPopupItems() {
return [
{
type: "custom",
id: "math-editor-container",
content: () => this.createMathEditorContainer()
},
{
type: "custom",
id: "formula-help-section",
content: () => this.createFormulaHelpSection()
},
{
type: "custom",
id: "preview-math-container",
content: () => this.createPreviewContainer()
}
];
}
createFormulaHelpSection() {
const e = a("formula-help-section mt-4"), t = document.createElement("div");
t.className = "flex items-center justify-between cursor-pointer", t.innerHTML = `
<span class="text-lg font-semibold m-0 text-gray-800">How to Write Formulas</span>
<span class="arrow">▼</span>
`;
const n = a("formula-help-content hidden mt-2");
return n.innerHTML = `
<p class="text-gray-600">
Use LaTeX syntax to write mathematical expressions. Below are some examples:
</p>
<div class="mt-4 space-y-2">
<div>
<strong>Example 1:</strong> Quadratic formula
<pre class="bg-gray-100 p-2 rounded-md">x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}</pre>
</div>
<div>
<strong>Example 2:</strong> Integral
<pre class="bg-gray-100 p-2 rounded-md">\\int_{a}^{b} x^2 \\, dx</pre>
</div>
<div>
<strong>Example 3:</strong> Matrix
<pre class="bg-gray-100 p-2 rounded-md">
\\begin{bmatrix}
1 & 2 \\\\
3 & 4
\\end{bmatrix}
</pre>
</div>
<div>
<strong>Example 4:</strong> Greek letters
<pre class="bg-gray-100 p-2 rounded-md">\\alpha, \\beta, \\gamma</pre>
</div>
</div>
<p class="mt-4 text-gray-600">
For more information, refer to the <a href="https://en.wikibooks.org/wiki/LaTeX/Mathematics" target="_blank" class="text-blue-500 hover:underline">LaTeX documentation</a>.
</p>
`, t.addEventListener("click", () => {
n.classList.toggle("hidden");
const r = t.querySelector(".arrow");
r && (r.textContent = n.classList.contains("hidden") ? "▼" : "▲");
}), e.appendChild(t), e.appendChild(n), e;
}
createMathEditorContainer() {
const e = a("math-editor-container mb-6");
e.appendChild(this.mathToolbar.getElement());
const t = d("Math Expression (LaTeX)", "math-expression");
return this.expressionInput = c(
"Enter your math expression here...",
"",
(n) => this.handleInputChange(n)
), this.expressionInput.id = "math-editor-container mb-6", this.expressionInput.className = "math-input w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500", e.appendChild(t), e.appendChild(this.expressionInput), e;
}
handleInputChange(e) {
this.expression = e, this.updatePreview(e);
}
createPreviewContainer() {
return this.previewContainer = a(
"preview-math-container h-64 bg-gray-50 rounded-lg flex items-center justify-center"
), this.previewContainer.innerHTML = '<div class="text-gray-400">Math preview will appear here</div>', this.previewContainer;
}
async updatePreview(e) {
var r;
const t = (r = this.popup.getElement()) == null ? void 0 : r.querySelector(".preview-math-container");
if (!t) return;
const n = await this.renderer.renderMath(e, {
width: 400,
height: 100
});
t.innerHTML = "", t.appendChild(n);
}
async handleSubmit() {
var t;
const e = this.expression;
if (e) {
if ((t = this.editor) == null || t.ensureEditorFocus(), this.editingMath) {
this.editingMath.setAttribute("data-math-expression", e);
const n = await this.renderer.renderMath(e, {
width: this.editingMath.clientWidth || 800,
height: this.editingMath.clientHeight || 200
});
this.editingMath.innerHTML = "", this.editingMath.appendChild(n);
} else {
const n = a("math-container");
n.style.width = "100%", n.style.height = "200px", n.setAttribute("data-math-expression", e);
const r = await this.renderer.renderMath(e, {
width: n.clientWidth || 800,
height: n.clientHeight || 200
});
n.appendChild(r), this.onInsert && this.onInsert(n);
}
this.popup.hide();
}
}
show(e) {
this.editingMath = null, this.onInsert = e, this.popup.show();
}
edit(e) {
this.editingMath = e;
const t = e.getAttribute("data-math-expression");
t && (this.expression = t, this.updatePreview(t)), this.popup.show();
}
async redrawMath(e, t, n) {
const r = await this.renderer.renderMath(t, n);
e.innerHTML = "", e.appendChild(r);
}
destroy() {
var e, t;
this.popup.destroy(), this.mathToolbar.destroy(), (e = this.expressionInput) == null || e.remove(), (t = this.previewContainer) == null || t.remove(), this.editor = null, this.popup = null, this.renderer = null, this.onInsert = null, this.editingMath = null;
}
}
export {
b as MathMenu
};