import { QuillHtmlLogger } from './logger';
import "./styles.css";
import Quill from "quill";
import { QuillHtmlEditButtonOptions } from "./options";
import { OutputHTMLParser } from "./html-parser";
import { FormatHTMLStringIndentation } from "./html-formatter";
function $create(elName: string) {
return document.createElement(elName);
}
function $setAttr(el: HTMLElement, key: string, value: string) {
return el.setAttribute(key, value);
}
const Logger = new QuillHtmlLogger();
class htmlEditButton {
constructor(quill: Quill, optionsInput: QuillHtmlEditButtonOptions) {
const options = optionsInput || {} as QuillHtmlEditButtonOptions;
const debug = !!(options && options.debug);
Logger.setDebug(debug);
Logger.log("logging enabled");
// Add button to all quill toolbar instances
const toolbarModule = quill.getModule("toolbar");
if (!toolbarModule) {
throw new Error(
'quill.htmlEditButton requires the "toolbar" module to be included too'
);
}
this.registerDivModule();
let toolbarEl = toolbarModule.container;
const buttonContainer = $create("span");
$setAttr(buttonContainer, "class", "ql-formats");
const button = $create("button") as HTMLButtonElement;
button.innerHTML = options.buttonHTML || "<>";
button.title = options.buttonTitle || "Show HTML source";
button.type = "button";
const onSave = (html: string) => {
quill.clipboard.dangerouslyPasteHTML(html);
};
button.onclick = function (e) {
e.preventDefault();
launchPopupEditor(quill, options, onSave);
};
buttonContainer.appendChild(button);
toolbarEl.appendChild(buttonContainer);
}
registerDivModule() {
// To allow divs to be inserted into html editor
// obtained from issue: https://github.com/quilljs/quill/issues/2040
const Block = Quill.import("blots/block");
class Div extends Block {}
Div.tagName = "div";
Div.blotName = "div";
Div.allowedChildren = Block.allowedChildren;
Div.allowedChildren.push(Block);
Quill.register(Div);
}
}
function launchPopupEditor(
quill: Quill & any,
options: QuillHtmlEditButtonOptions,
saveCallback: (html: string) => void
) {
const htmlFromEditor = quill.container.querySelector(".ql-editor").innerHTML;
const popupContainer = $create("div");
const overlayContainer = $create("div");
const msg =
options.msg ||
'Edit HTML here, when you click "OK" the quill editor\'s contents will be replaced';
const cancelText = options.cancelText || "Cancel";
const okText = options.okText || "Ok";
const closeOnClickOverlay = options.closeOnClickOverlay !== false;
$setAttr(overlayContainer, "class", "ql-html-overlayContainer");
$setAttr(popupContainer, "class", "ql-html-popupContainer");
const popupTitle = $create("span");
$setAttr(popupTitle, "class", "ql-html-popupTitle");
popupTitle.innerText = msg;
const textContainer = $create("div");
textContainer.appendChild(popupTitle);
$setAttr(textContainer, "class", "ql-html-textContainer");
const codeBlock = $create("pre");
$setAttr(codeBlock, "data-language", "xml");
codeBlock.innerText = FormatHTMLStringIndentation(htmlFromEditor, Logger);
const htmlEditor = $create("div");
$setAttr(htmlEditor, "class", "ql-html-textArea");
const buttonCancel = $create("button");
buttonCancel.innerHTML = cancelText;
$setAttr(buttonCancel, "class", "ql-html-buttonCancel");
const buttonOk = $create("button");
buttonOk.innerHTML = okText;
$setAttr(buttonOk, "class", "ql-html-buttonOk");
const buttonGroup = $create("div");
$setAttr(buttonGroup, "class", "ql-html-buttonGroup");
const prependSelector = document.querySelector(options.prependSelector);
buttonGroup.appendChild(buttonCancel);
buttonGroup.appendChild(buttonOk);
htmlEditor.appendChild(codeBlock);
textContainer.appendChild(htmlEditor);
textContainer.appendChild(buttonGroup);
popupContainer.appendChild(textContainer);
overlayContainer.appendChild(popupContainer);
if (prependSelector) {
prependSelector.prepend(overlayContainer);
} else {
document.body.appendChild(overlayContainer);
}
const modules = options && options.editorModules;
const hasModules = !!modules && !!Object.keys(modules).length;
const modulesSafe = hasModules ? modules : {};
// console.time('new Quill')
const editor = new Quill(htmlEditor, {
modules: {
syntax: options.syntax,
...modulesSafe,
},
});
// console.timeEnd('new Quill')
buttonCancel.onclick = function () {
if (prependSelector) {
prependSelector.removeChild(overlayContainer);
} else {
document.body.removeChild(overlayContainer);
}
};
if (closeOnClickOverlay) {
overlayContainer.onclick = buttonCancel.onclick;
}
popupContainer.onclick = function (e) {
e.preventDefault();
e.stopPropagation();
};
buttonOk.onclick = function () {
const container = (editor as any).container as HTMLElement;
const qlElement = container.querySelector(".ql-editor") as HTMLDivElement;
const htmlInputFromPopup = qlElement.innerText;
const htmlOutputFormatted = OutputHTMLParser(htmlInputFromPopup);
Logger.log('OutputHTMLParser', { htmlInputFromPopup, htmlOutputFormatted })
saveCallback(htmlOutputFormatted);
if (prependSelector) {
prependSelector.removeChild(overlayContainer);
} else {
document.body.removeChild(overlayContainer);
}
};
}
(window as any)["htmlEditButton"] = htmlEditButton;
export default htmlEditButton;
export { htmlEditButton };