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
143 lines (142 loc) • 7.56 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 C = (h, t, e) => t in h ? L(h, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : h[t] = e;
var c = (h, t, e) => C(h, typeof t != "symbol" ? t + "" : t, e);
/* empty css */
/* empty css */
import { createToolbarButton as E } from "../ToolbarPlugin/utils.mjs";
import N from "../../icons/list-bullet.svg.mjs";
import B from "../../icons/list-numbered.svg.mjs";
import { createP as y } from "../../utils/helpers.mjs";
class b {
// private menu: ListsMenu;
constructor() {
c(this, "name", "lists");
c(this, "hotkeys", [
{ keys: "Ctrl+Shift+B", description: "Bulleted list", command: "lists-unordered", icon: "•" },
{ keys: "Ctrl+Shift+N", description: "Numbered list", command: "lists-ordered", icon: "1️⃣" }
]);
c(this, "editor", null);
c(this, "ulButton", null);
c(this, "olButton", null);
c(this, "handleKeydown", (t) => {
(t.metaKey || t.ctrlKey) && t.key === "Enter" && (t.preventDefault(), this.exitListAndInsertBreak());
});
}
initialize(t) {
this.editor = t, this.addToolbarButtons(), this.setupListHandling(), this.editor.on("lists-unordered", () => {
var e;
(e = this.editor) == null || e.ensureEditorFocus(), this.toggleList("unordered");
}), this.editor.on("lists-ordered", () => {
var e;
(e = this.editor) == null || e.ensureEditorFocus(), this.toggleList("ordered");
});
}
addToolbarButtons() {
var e, o, i, n;
const t = (e = this.editor) == null ? void 0 : e.getToolbar();
t && (this.ulButton = E({
icon: N,
title: (o = this.editor) == null ? void 0 : o.t("Bullet List"),
onClick: () => {
var s;
(s = this.editor) == null || s.ensureEditorFocus(), this.toggleList("unordered"), this.handleSelectionChange();
}
}), this.olButton = E({
icon: B,
title: (i = this.editor) == null ? void 0 : i.t("Numbered List"),
onClick: () => {
var s;
(s = this.editor) == null || s.ensureEditorFocus(), this.toggleList("ordered"), this.handleSelectionChange();
}
}), t.appendChild(this.ulButton), t.appendChild(this.olButton), (n = this.editor) == null || n.on("selectionchange", () => this.handleSelectionChange()));
}
handleSelectionChange() {
var n, s, r, d, a, l, m, g, u;
const t = (s = (n = this.editor) == null ? void 0 : n.getTextFormatter()) == null ? void 0 : s.getSelection();
if (!t || !t.rangeCount) return;
const o = t.getRangeAt(0).commonAncestorContainer, i = o.nodeType === Node.ELEMENT_NODE ? o.closest("ul, ol") : (r = o.parentElement) == null ? void 0 : r.closest("ul, ol");
i ? i.tagName === "UL" ? ((d = this.ulButton) == null || d.classList.add("active"), (a = this.olButton) == null || a.classList.remove("active")) : i.tagName === "OL" && ((l = this.olButton) == null || l.classList.add("active"), (m = this.ulButton) == null || m.classList.remove("active")) : ((g = this.ulButton) == null || g.classList.remove("active"), (u = this.olButton) == null || u.classList.remove("active"));
}
setupListHandling() {
this.editor && this.editor.getContainer().addEventListener("keydown", this.handleKeydown);
}
exitListAndInsertBreak() {
var i, n, s, r, d;
const t = (n = (i = this.editor) == null ? void 0 : i.getTextFormatter()) == null ? void 0 : n.getSelection();
if (!t || !t.rangeCount) return;
const e = t.getRangeAt(0), o = (s = e.commonAncestorContainer.parentElement) == null ? void 0 : s.closest("li");
if (o) {
const a = o.parentElement;
if (!a) return;
const l = y("my-4");
a.nextSibling ? (r = a.parentNode) == null || r.insertBefore(l, a.nextSibling) : (d = a.parentNode) == null || d.appendChild(l), e.selectNodeContents(l), e.collapse(!0), t.removeAllRanges(), t.addRange(e);
}
}
toggleList(t) {
var s, r;
if (!this.editor) return;
const e = (s = this.editor.getTextFormatter()) == null ? void 0 : s.getSelection();
if (!e || !e.rangeCount) return;
const o = e.getRangeAt(0), i = o.commonAncestorContainer, n = i.nodeType === Node.ELEMENT_NODE ? i.closest("ul, ol") : (r = i.parentElement) == null ? void 0 : r.closest("ul, ol");
n ? t === "ordered" && n.tagName === "OL" || t === "unordered" && n.tagName === "UL" ? this.unwrapList(n) : this.replaceList(n, t) : this.createNewList(o, t);
}
unwrapList(t) {
var s, r, d;
const e = Array.from(t.querySelectorAll("li")), o = document.createElement("div");
e.forEach((a, l) => {
o.appendChild(document.createTextNode(a.textContent || "")), l < e.length - 1 && o.appendChild(document.createElement("br"));
}), (s = t.parentNode) == null || s.replaceChild(o, t);
const i = document.createRange();
i.selectNodeContents(o);
const n = (d = (r = this.editor) == null ? void 0 : r.getTextFormatter()) == null ? void 0 : d.getSelection();
n == null || n.removeAllRanges(), n == null || n.addRange(i);
}
replaceList(t, e) {
var n;
const o = e === "ordered" ? "ol" : "ul", i = document.createElement(o);
Array.from(t.children).forEach((s) => {
const r = document.createElement("li");
r.innerHTML = s.innerHTML, i.appendChild(r);
}), (n = t.parentNode) == null || n.replaceChild(i, t), this.applyListStyles(i, e);
}
createNewList(t, e) {
var d, a;
const o = t.extractContents(), i = e === "ordered" ? "ol" : "ul", n = document.createElement(i);
if (Array.from(o.childNodes).forEach((l) => {
var m, g;
if (l.nodeType === Node.TEXT_NODE)
(((m = l.textContent) == null ? void 0 : m.split(`
`).filter((p) => p.trim() !== "")) || []).forEach((p) => {
const f = document.createElement("li");
f.textContent = p.trim(), n.appendChild(f);
});
else if (l.nodeName !== "BR") {
if (l.nodeType === Node.ELEMENT_NODE && ((g = l.textContent) == null ? void 0 : g.trim()) !== "") {
const u = document.createElement("li");
u.appendChild(l.cloneNode(!0)), n.appendChild(u);
}
}
}), n.children.length === 0) {
const l = document.createElement("li");
l.textContent = "List item", n.appendChild(l);
}
t.insertNode(n), this.applyListStyles(n, e);
const s = document.createRange();
s.selectNodeContents(n.lastElementChild || n);
const r = (a = (d = this.editor) == null ? void 0 : d.getTextFormatter()) == null ? void 0 : a.getSelection();
r == null || r.removeAllRanges(), r == null || r.addRange(s);
}
applyListStyles(t, e) {
e === "ordered" ? t.className = "list-decimal pl-8 my-4 space-y-2" : t.className = "list-disc pl-8 my-4 space-y-2", t.querySelectorAll("li").forEach((o) => {
o.className = "pl-2";
});
}
destroy() {
var t, e;
this.editor && this.editor.getContainer().removeEventListener("keydown", this.handleKeydown), this.ulButton && this.ulButton.parentElement && this.ulButton.parentElement.removeChild(this.ulButton), this.olButton && this.olButton.parentElement && this.olButton.parentElement.removeChild(this.olButton), (t = this.editor) == null || t.off("selectionchange"), (e = this.editor) == null || e.off("lists"), this.editor = null, this.ulButton = null, this.olButton = null;
}
}
export {
b as ListsPlugin
};