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
161 lines (160 loc) • 6.63 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 p = Object.defineProperty;
var f = (m, t, e) => t in m ? p(m, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : m[t] = e;
var a = (m, t, e) => f(m, typeof t != "symbol" ? t + "" : t, e);
/* empty css */
/* empty css */
import { TimerMenu as T } from "./components/TimerMenu.mjs";
import { TimerManager as g } from "./services/TimerManager.mjs";
import { createToolbarButton as w } from "../ToolbarPlugin/utils.mjs";
import b from "../../icons/timer.svg.mjs";
import { TimerContextMenu as y } from "./components/TimerContextMenu.mjs";
import { createLineBreak as E } from "../../utils/helpers.mjs";
class A {
constructor() {
a(this, "name", "timer");
a(this, "hotkeys", [{ keys: "Ctrl+Alt+D", description: "Insert timer", command: "timer", icon: "⏱️" }]);
a(this, "editor", null);
a(this, "menu", null);
a(this, "manager");
a(this, "toolbarButton", null);
a(this, "contextMenu", null);
}
initialize(t) {
this.editor = t, this.manager = new g(t), this.menu = new T(this.manager, t), this.contextMenu = new y(this.manager, t), this.addToolbarButton(), this.setupEventListeners(), this.startTimerUpdates(), t.on("timer", () => this.showTimerMenu());
}
addToolbarButton() {
var e;
if (!this.editor) return;
const t = (e = this.editor) == null ? void 0 : e.getToolbar();
t && (this.toolbarButton = w({
icon: b,
title: this.editor.t("Timer"),
onClick: () => this.showTimerMenu()
}), t.appendChild(this.toolbarButton));
}
setupEventListeners() {
this.editor && (this.editor.getContainer().addEventListener("click", (t) => this.handleTimerClick(t)), this.editor.getContainer().addEventListener("contextmenu", (t) => this.handleContextMenu(t)));
}
handleTimerClick(t) {
var n;
const i = t.target.closest(".timer-widget");
if (!i) return;
const r = i.getAttribute("data-timer-id");
if (!r) return;
const o = this.manager.getTimer(r);
o && ((n = this.menu) == null || n.showEditTimerForm(o));
}
handleContextMenu(t) {
var n;
const i = t.target.closest(".timer-widget");
if (!i) return;
t.preventDefault();
const r = i.getAttribute("data-timer-id");
if (!r) return;
const o = this.manager.getTimer(r);
o && ((n = this.contextMenu) == null || n.show(t, o, (s) => {
this.handleContextMenuAction(s, o);
}));
}
handleContextMenuAction(t, e) {
var i, r, o, n, s;
switch (t) {
case "edit-timer":
(i = this.menu) == null || i.showEditTimerForm(e);
break;
case "copy-timer":
try {
this.manager.copyTimer(e.id), (o = this.editor) == null || o.showSuccessNotification(
((r = this.editor) == null ? void 0 : r.t("Timer copied successfully")) || "Timer copied successfully"
), this.refreshTimers();
} catch {
(s = this.editor) == null || s.showErrorNotification(
((n = this.editor) == null ? void 0 : n.t("Failed to copy timer")) || "Failed to copy timer"
);
}
break;
case "export-timer":
this.showExportDialog(e);
break;
case "import-timer":
this.showImportDialog();
break;
case "delete-timer":
this.manager.deleteTimer(e.id), this.refreshTimers();
break;
}
}
showTimerMenu() {
var e;
if (!this.editor) return;
const t = this.editor.saveCursorPosition();
(e = this.menu) == null || e.show((i) => {
this.editor && (t && this.editor.restoreCursorPosition(t), this.insertTimer(i));
});
}
insertTimer(t) {
if (!this.editor) return;
const e = this.manager.generateTimerHTML(t);
this.editor.insertContent(e), this.editor.insertContent(E());
}
refreshTimers() {
var e;
const t = (e = this.editor) == null ? void 0 : e.getContainer().querySelectorAll(".timer-widget");
t == null || t.forEach((i) => {
const r = i.getAttribute("data-timer-id");
if (!r) return;
const o = this.manager.getTimer(r);
if (!o) return;
const n = this.manager.generateTimerHTML(o), s = document.createElement("div");
s.innerHTML = n;
const c = s.firstElementChild, h = s.querySelector("script");
if (c && i.parentNode) {
const d = i.parentNode.querySelector(`script[data-timer-id="${r}"]`);
d && d.remove(), i.parentNode && i.parentNode.replaceChild(c, i), h && i.parentNode && (h.setAttribute("data-timer-id", r), i.parentNode.appendChild(h));
}
});
}
startTimerUpdates() {
setInterval(() => {
this.refreshTimers();
}, 1e3);
}
showExportDialog(t) {
var e;
try {
const i = JSON.stringify(t, null, 2), r = new Blob([i], { type: "application/json" }), o = URL.createObjectURL(r), n = document.createElement("a");
n.href = o, n.download = `timer-${t.id}.json`, n.click(), URL.revokeObjectURL(o);
} catch {
(e = this.editor) == null || e.showErrorNotification(this.editor.t("Export failed") || "Export failed");
}
}
showImportDialog() {
const t = document.createElement("input");
t.type = "file", t.accept = ".json", t.onchange = (e) => {
var r;
const i = (r = e.target.files) == null ? void 0 : r[0];
if (i) {
const o = new FileReader();
o.onload = (n) => {
var s, c, h, d, l;
try {
const u = JSON.parse((s = n.target) == null ? void 0 : s.result);
this.manager.importTimer(u), (h = this.editor) == null || h.showSuccessNotification(
((c = this.editor) == null ? void 0 : c.t("Timer imported successfully")) || "Timer imported successfully"
), this.refreshTimers();
} catch {
(l = this.editor) == null || l.showErrorNotification(((d = this.editor) == null ? void 0 : d.t("Import failed")) || "Import failed");
}
}, o.readAsText(i);
}
}, t.click();
}
destroy() {
var t;
this.toolbarButton && this.toolbarButton.parentElement && this.toolbarButton.parentElement.removeChild(this.toolbarButton), this.menu && (this.menu.destroy(), this.menu = null), this.contextMenu && (this.contextMenu.destroy(), this.contextMenu = null), (t = this.editor) == null || t.off("timer"), this.editor = null, this.manager = null, this.toolbarButton = null;
}
}
export {
A as TimerPlugin
};