import {DOMUtils, ContenteditableExtension} from 'nylas-exports'; export default class TemplateEditor extends ContenteditableExtension { static onContentChanged = ({editor})=> { // Run through and remove all code nodes that are invalid const codeNodes = editor.rootNode.querySelectorAll("code.var.empty"); for (let ii = 0; ii < codeNodes.length; ii++) { const codeNode = codeNodes[ii]; // remove any style that was added by contenteditable codeNode.removeAttribute("style"); // grab the text content and the indexable text content const codeNodeText = codeNode.textContent; const indexText = DOMUtils.getIndexedTextContent(codeNode).map(({text})=> text).join(""); // unwrap any code nodes that don't start/end with {{}}, and any with line breaks inside if ((!codeNodeText.startsWith("{{")) || (!codeNodeText.endsWith("}}")) || (indexText.indexOf("\n") > -1)) { editor.whilePreservingSelection(()=> { DOMUtils.unwrapNode(codeNode); }); } } // Attempt to sanitize extra nodes that may have been created by contenteditable on certain text editing // operations (insertion/deletion of line breaks, etc.). These are generally , but can also be // , , and possibly others. The extra nodes often grab CSS styles from neighboring elements // as inline style, including the yellow text from nodes that we insert. This is contenteditable // trying to be "smart" and preserve styles, which is very undesirable for the node styles. The // below code is a hack to prevent yellow text from appearing. const starNodes = editor.rootNode.querySelectorAll("*"); for (let ii = 0; ii < starNodes.length; ii++) { const node = starNodes[ii]; if ((!node.className) && (node.style.color === "#c79b11")) { editor.whilePreservingSelection(()=> { DOMUtils.unwrapNode(node); }); } } const fontNodes = editor.rootNode.querySelectorAll("font"); for (let ii = 0; ii < fontNodes.length; ii++) { const node = fontNodes[ii]; if (node.color === "#c79b11") { editor.whilePreservingSelection(()=> { DOMUtils.unwrapNode(node); }); } } // Find all {{}} and wrap them in code nodes if they aren't already // Regex finds any {{ }} that doesn't contain {, }, or \n // https://regex101.com/r/jF2oF4/1 for (const range of editor.regExpSelectorAll(/\{\{[^\n{}]*?\}\}/g)) { if (!DOMUtils.isWrapped(range, "CODE")) { // Preserve the selection based on text index within the range matched by the regex const selIndex = editor.getSelectionTextIndex(range); const codeNode = DOMUtils.wrap(range, "CODE"); codeNode.className = "var empty"; // Sets node contents to just its textContent, strips HTML codeNode.textContent = codeNode.textContent; if (selIndex != null) { editor.restoreSelectionByTextIndex(codeNode, selIndex.startIndex, selIndex.endIndex); } } } } }