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
150 lines (149 loc) • 4.49 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 l = Object.defineProperty;
var f = (a, t, s) => t in a ? l(a, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : a[t] = s;
var i = (a, t, s) => f(a, typeof t != "symbol" ? t + "" : t, s);
class y {
constructor() {
i(this, "shortcuts", /* @__PURE__ */ new Map());
i(this, "isMac");
i(this, "stats", {
totalShortcuts: 0,
mostUsed: [],
recentlyUsed: [],
conflicts: []
});
this.isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0;
}
register(t, s, e, r, o, c) {
const u = {
id: t,
keys: s.split("+").map((n) => n.trim().toLowerCase()),
keysMac: c ? c.split("+").map((n) => n.trim().toLowerCase()) : void 0,
callback: e,
description: r,
category: o,
usageCount: 0,
lastUsed: 0
}, h = this.checkConflicts(u);
h.length > 0 && (console.warn(`Shortcut conflicts for ${t}:`, h), this.stats.conflicts.push(...h)), this.shortcuts.set(t, u), this.stats.totalShortcuts = this.shortcuts.size, this.updateStats();
}
handleKeyDown(t) {
const s = [];
(this.isMac ? t.metaKey : t.ctrlKey) && s.push("ctrl"), t.shiftKey && s.push("shift"), t.altKey && s.push("alt");
const e = this.normalizeKey(t.key);
e && !["Control", "Shift", "Alt", "Meta"].includes(t.key) && s.push(e);
for (const r of this.shortcuts.values()) {
const o = this.isMac && r.keysMac ? r.keysMac : r.keys;
if (this.matchesShortcut(s, o))
return t.preventDefault(), this.executeShortcut(r), !0;
}
return !1;
}
executeShortcut(t) {
try {
t.callback(), t.usageCount++, t.lastUsed = Date.now(), this.updateStats();
} catch (s) {
console.error(`Error executing shortcut ${t.id}:`, s);
}
}
normalizeKey(t) {
return {
Enter: "enter",
Backspace: "backspace",
Delete: "delete",
Escape: "escape",
Tab: "tab",
Space: "space",
ArrowUp: "arrowup",
ArrowDown: "arrowdown",
ArrowLeft: "arrowleft",
ArrowRight: "arrowright",
Home: "home",
End: "end",
PageUp: "pageup",
PageDown: "pagedown",
Insert: "insert",
F1: "f1",
F2: "f2",
F3: "f3",
F4: "f4",
F5: "f5",
F6: "f6",
F7: "f7",
F8: "f8",
F9: "f9",
F10: "f10",
F11: "f11",
F12: "f12"
}[t] || t.toLowerCase();
}
matchesShortcut(t, s) {
if (t.length !== s.length) return !1;
const e = [...t].sort();
return [...s].sort().every((o, c) => e[c] === o);
}
checkConflicts(t) {
const s = [], e = this.isMac && t.keysMac ? t.keysMac : t.keys;
for (const [r, o] of this.shortcuts) {
if (r === t.id) continue;
const c = this.isMac && o.keysMac ? o.keysMac : o.keys;
this.matchesShortcut(e, c) && s.push(`${r} (${o.description})`);
}
return s;
}
updateStats() {
const t = Array.from(this.shortcuts.values());
this.stats.mostUsed = t.sort((s, e) => e.usageCount - s.usageCount).slice(0, 5), this.stats.recentlyUsed = t.filter((s) => s.lastUsed > 0).sort((s, e) => e.lastUsed - s.lastUsed).slice(0, 5);
}
getShortcuts() {
return Array.from(this.shortcuts.values());
}
getShortcutsByCategory() {
const t = {};
for (const s of this.shortcuts.values())
t[s.category] || (t[s.category] = []), t[s.category].push(s);
return t;
}
getStats() {
return { ...this.stats };
}
getPlatform() {
return this.isMac ? "mac" : "windows";
}
formatShortcut(t) {
const s = {
ctrl: this.isMac ? "⌘" : "Ctrl",
shift: "⇧",
alt: this.isMac ? "⌥" : "Alt",
enter: "↵",
backspace: "⌫",
delete: "⌦",
escape: "⎋",
tab: "⇥",
space: "␣",
arrowup: "↑",
arrowdown: "↓",
arrowleft: "←",
arrowright: "→",
home: "⇱",
end: "⇲",
pageup: "⇞",
pagedown: "⇟"
};
return t.map((e) => s[e] || e.toUpperCase()).join(" ");
}
unregister(t) {
return this.shortcuts.delete(t);
}
clear() {
this.shortcuts.clear(), this.stats = {
totalShortcuts: 0,
mostUsed: [],
recentlyUsed: [],
conflicts: []
};
}
}
export {
y as ShortcutManager
};