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
108 lines (107 loc) • 4.09 kB
JavaScript
class f {
constructor(e) {
this.container = e;
}
getSelectedRoot(e, r = !1) {
const n = e.getRangeAt(0);
return !n.collapsed || this.hasContentInRange(n) ? this.getDeepestNodes(n, r) : r ? [] : this.handleCollapsedRange(e, n);
}
getDeepestNodes(e, r) {
const n = [], s = [];
if (!this.container.contains(e.commonAncestorContainer))
return [];
const o = document.createTreeWalker(
e.commonAncestorContainer,
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,
null
);
let t = o.currentNode = e.startContainer;
for (; t; ) {
if (t !== this.container && t.nodeType === Node.TEXT_NODE && t.textContent && t.textContent.trim().length > 0 && e.intersectsNode(t)) {
const i = t.parentElement;
i && this.isStyledTextNode(i) && !this.isTableNode(i) && !this.isBlockNode(i) ? s.includes(i) || s.push(i) : n.push(t);
}
if (t === e.endContainer) break;
t = o.nextNode();
}
if (!r)
for (const i of n) {
const l = this.createSpanIfNeeded(i, e);
l && !s.includes(l) && s.push(l);
}
return s;
}
handleCollapsedRange(e, r) {
var o;
const n = e.anchorNode;
if (!n || !this.container.contains(n)) return [];
let s = document.createElement("span");
return n.nodeType === Node.ELEMENT_NODE && n.tagName === "SPAN" ? s = n : (s.textContent = " ", (o = n.parentNode) == null || o.insertBefore(s, n.nextSibling)), r.setStart(s, 1), r.setEnd(s, 1), e.removeAllRanges(), e.addRange(r), [s];
}
hasContentInRange(e) {
return e.toString().trim().length > 0 || e.cloneContents().childNodes.length > 0;
}
createSpanIfNeeded(e, r) {
var i;
if (e.nodeType !== Node.TEXT_NODE || !e.textContent) return null;
const { textContent: n } = e, s = e === r.startContainer ? r.startOffset : 0, o = e === r.endContainer ? r.endOffset : n.length;
if (o === 0 || s === n.length || s === o) return null;
const t = document.createElement("span");
t.textContent = n.substring(s, o), this.replaceNodeWithSpan(e, t, s, o);
try {
const l = window.getSelection();
if (l) {
const a = document.createRange(), c = t.firstChild;
c && c.nodeType === Node.TEXT_NODE && (a.setStart(c, 0), a.setEnd(c, ((i = c.textContent) == null ? void 0 : i.length) || 0), l.removeAllRanges(), l.addRange(a));
}
} catch (l) {
console.error(l);
}
return t;
}
replaceNodeWithSpan(e, r, n, s) {
const { textContent: o } = e, t = e.parentNode;
if (!t || !o) return;
const i = document.createTextNode(o.substring(0, n)), l = document.createTextNode(o.substring(s));
t.insertBefore(i, e), t.insertBefore(r, e), t.insertBefore(l, e), t.removeChild(e);
}
isStyledTextNode(e) {
return e ? !e.classList.contains("html-editor") : !1;
}
isTableNode(e) {
return e ? !!(e.closest("table") || e.closest("tr") || e.closest("td") || e.closest("th")) : !1;
}
isBlockNode(e) {
return e ? e.classList.contains("block-content") : !1;
}
applyStyleToNode(e, r, n) {
e.nodeType === Node.ELEMENT_NODE && n(e, r);
}
removeStyleFromNode(e, r, n) {
var s;
if (e.nodeType === Node.ELEMENT_NODE) {
const o = e;
if (this.isStyledTextNode(o) && (n(o, r), !o.getAttribute("style") && o.classList.length === 0 && o.tagName === "SPAN")) {
const t = document.createDocumentFragment();
for (; o.firstChild; )
t.appendChild(o.firstChild);
const i = o.parentNode, l = t.firstChild, a = t.lastChild;
i == null || i.replaceChild(t, o);
try {
if (l && a && l.nodeType === Node.TEXT_NODE && a.nodeType === Node.TEXT_NODE) {
const c = window.getSelection();
if (c) {
const d = document.createRange();
d.setStart(l, 0), d.setEnd(a, ((s = a.textContent) == null ? void 0 : s.length) || 0), c.removeAllRanges(), c.addRange(d);
}
}
} catch (c) {
console.error(c);
}
}
}
}
}
export {
f as DomUtils
};