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
156 lines (155 loc) • 5.98 kB
JavaScript
var h = Object.defineProperty;
var u = (d, t, e) => t in d ? h(d, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : d[t] = e;
var a = (d, t, e) => u(d, typeof t != "symbol" ? t + "" : t, e);
/* empty css */
/* empty css */
import { CommentManager as p } from "./services/CommentManager.mjs";
import { CommentMenu as f } from "./components/CommentMenu.mjs";
import { ErrorModal as C } from "./components/ErrorModal.mjs";
import { createToolbarButton as g } from "../ToolbarPlugin/utils.mjs";
import M from "../../icons/comment.svg.mjs";
import v from "../../icons/comment-marker.svg.mjs";
import { createContainer as k, createSpan as c } from "../../utils/helpers.mjs";
class I {
constructor() {
a(this, "name", "comments");
a(this, "hotkeys", [{ keys: "Ctrl+Alt+M", description: "Insert comment", command: "comment", icon: "💬" }]);
a(this, "editor", null);
a(this, "manager");
a(this, "menu", null);
a(this, "errorModal", null);
a(this, "tooltip");
this.manager = new p(), this.tooltip = this.createTooltip(), document.body.appendChild(this.tooltip);
}
initialize(t) {
this.errorModal = new C(t), this.menu = new f(t), this.editor = t, this.addToolbarButton(), this.setupEventListeners(), this.editor.on("comment", () => {
this.addComment();
});
}
createTooltip() {
const t = k("comment-tooltip");
return t.style.display = "none", t;
}
addToolbarButton() {
var o;
const t = document.querySelector(".editor-toolbar");
if (!t) return;
const e = g({
icon: M,
title: (o = this.editor) == null ? void 0 : o.t("Insert Comment"),
onClick: () => this.addComment()
});
t.appendChild(e);
}
setupEventListeners() {
if (!this.editor) return;
const t = this.editor.getContainer();
this.handleMouseOver = this.handleMouseOver.bind(this), this.handleMouseOut = this.handleMouseOut.bind(this), this.handleClick = this.handleClick.bind(this), t.addEventListener("mouseover", this.handleMouseOver), t.addEventListener("mouseout", this.handleMouseOut), t.addEventListener("click", this.handleClick);
}
handleMouseOver(t) {
const e = t.target.closest(".comment-marker");
if (e instanceof HTMLElement) {
const o = e.getAttribute("data-comment-id");
o && this.showTooltip(e, o);
}
}
handleMouseOut(t) {
t.target.closest(".comment-marker") && this.hideTooltip();
}
handleClick(t) {
const e = t.target.closest(".comment-marker");
if (e instanceof HTMLElement) {
const o = e.getAttribute("data-comment-id");
o && this.editComment(o);
}
}
showTooltip(t, e) {
const o = this.manager.getComment(e);
if (!o) return;
this.tooltip.textContent = o.content, this.tooltip.style.display = "block";
const n = t.getBoundingClientRect();
this.tooltip.style.left = `${n.left + n.width / 2}px`, this.tooltip.style.top = `${n.bottom + 8}px`;
}
hideTooltip() {
this.tooltip.style.display = "none";
}
addComment() {
var o, n, s, m;
if (!this.editor) {
(o = this.errorModal) == null || o.show("Editor not initialized");
return;
}
const t = window.getSelection();
if (!t || !t.rangeCount) {
(n = this.errorModal) == null || n.show(this.editor.t("Please select some text to comment on"));
return;
}
const e = t.getRangeAt(0);
if (e.collapsed) {
(s = this.errorModal) == null || s.show(this.editor.t("Please select some text to comment on"));
return;
}
(m = this.menu) == null || m.show((r, i) => {
if (i === "save") {
const l = this.manager.createComment(r);
this.insertCommentMarker(l.id, e);
}
});
}
editComment(t) {
var o;
const e = this.manager.getComment(t);
e && ((o = this.menu) == null || o.show(
(n, s) => {
var m;
if (s === "save")
this.manager.updateComment(t, n);
else if (s === "delete") {
this.manager.deleteComment(t);
const r = (m = this.editor) == null ? void 0 : m.getContainer().querySelector(`[data-comment-id="${t}"]`);
if (r) {
const i = r.previousElementSibling;
if (i != null && i.classList.contains("commented-text")) {
const l = i.parentNode;
if (l) {
for (; i.firstChild; )
l.insertBefore(i.firstChild, i);
i.remove(), r.remove();
}
}
}
}
},
e.content,
!0
));
}
insertCommentMarker(t, e) {
var o, n;
try {
const s = e.cloneContents(), m = c("commented-text");
m.appendChild(s);
const r = c("comment-marker");
r.setAttribute("data-comment-id", t), r.innerHTML = v;
const i = document.createDocumentFragment();
i.appendChild(m), i.appendChild(r), e.deleteContents(), e.insertNode(i), e.setStartAfter(r), e.setEndAfter(r);
const l = window.getSelection();
l && (l.removeAllRanges(), l.addRange(e));
} catch (s) {
console.error("Failed to insert comment:", s), (n = this.errorModal) == null || n.show(
((o = this.editor) == null ? void 0 : o.t("Failed to insert comment. Please try selecting a simpler text range.")) ?? ""
);
}
}
destroy() {
var t, e, o;
if (this.editor) {
const n = this.editor.getContainer();
n.removeEventListener("mouseover", this.handleMouseOver), n.removeEventListener("mouseout", this.handleMouseOut), n.removeEventListener("click", this.handleClick);
}
this.tooltip && this.tooltip.parentElement && this.tooltip.parentElement.removeChild(this.tooltip), (t = this.menu) == null || t.destroy(), (e = this.errorModal) == null || e.destroy(), (o = this.editor) == null || o.off("comment"), this.editor = null, this.menu = null, this.errorModal = null, this.tooltip = null, this.manager = null;
}
}
export {
I as CommentsPlugin
};