]> BookStack Code Mirror - bookstack/commitdiff
Started initial tasklist attempt, failed implementation
authorDan Brown <redacted>
Sat, 19 Mar 2022 16:04:33 +0000 (16:04 +0000)
committerDan Brown <redacted>
Sat, 19 Mar 2022 16:04:33 +0000 (16:04 +0000)
resources/js/wysiwyg/config.js
resources/js/wysiwyg/plugins-tasklist.js [new file with mode: 0644]
resources/sass/_text.scss

index 965b14d083699d6c5bb1ce6adb1b38c3eeee4ea2..fab6a38862fb717f78b291920e423528f10b853a 100644 (file)
@@ -10,6 +10,7 @@ import {getPlugin as getCustomhrPlugin} from "./plugins-customhr";
 import {getPlugin as getImagemanagerPlugin} from "./plugins-imagemanager";
 import {getPlugin as getAboutPlugin} from "./plugins-about";
 import {getPlugin as getDetailsPlugin} from "./plugins-details";
+import {getPlugin as getTasklistPlugin} from "./plugins-tasklist";
 
 const style_formats = [
     {title: "Large Header", format: "h2", preview: 'color: blue;'},
@@ -81,6 +82,7 @@ function gatherPlugins(options) {
         "imagemanager",
         "about",
         "details",
+        "tasklist",
         options.textDirection === 'rtl' ? 'directionality' : '',
     ];
 
@@ -89,6 +91,7 @@ function gatherPlugins(options) {
     window.tinymce.PluginManager.add('imagemanager', getImagemanagerPlugin(options));
     window.tinymce.PluginManager.add('about', getAboutPlugin(options));
     window.tinymce.PluginManager.add('details', getDetailsPlugin(options));
+    window.tinymce.PluginManager.add('tasklist', getTasklistPlugin(options));
 
     if (options.drawioUrl) {
         window.tinymce.PluginManager.add('drawio', getDrawioPlugin(options));
@@ -204,7 +207,7 @@ export function build(options) {
         statusbar: false,
         menubar: false,
         paste_data_images: false,
-        extended_valid_elements: 'pre[*],svg[*],div[drawio-diagram],details[*],summary[*],div[*]',
+        extended_valid_elements: 'pre[*],svg[*],div[drawio-diagram],details[*],summary[*],div[*],li[class]',
         automatic_uploads: false,
         custom_elements: 'doc-root,code-block',
         valid_children: [
diff --git a/resources/js/wysiwyg/plugins-tasklist.js b/resources/js/wysiwyg/plugins-tasklist.js
new file mode 100644 (file)
index 0000000..07f9344
--- /dev/null
@@ -0,0 +1,123 @@
+/**
+ * @param {Editor} editor
+ */
+function defineTaskListCustomElement(editor) {
+    const doc = editor.getDoc();
+    const win = doc.defaultView;
+
+    class TaskListElement extends win.HTMLElement {
+        constructor() {
+            super();
+            // this.attachShadow({mode: 'open'});
+            //
+            // const input = doc.createElement('input');
+            // input.setAttribute('type', 'checkbox');
+            // input.setAttribute('disabled', 'disabled');
+            //
+            // if (this.hasAttribute('selected')) {
+            //     input.setAttribute('selected', 'selected');
+            // }
+            //
+            // this.shadowRoot.append(input);
+            // this.shadowRoot.close();
+        }
+    }
+
+    win.customElements.define('task-list-item', TaskListElement);
+}
+
+/**
+ * @param {Editor} editor
+ * @param {String} url
+ */
+function register(editor, url) {
+
+    // editor.on('NewBlock', ({ newBlock}) => {
+    //     ensureElementHasCheckbox(newBlock);
+    // });
+
+    editor.on('PreInit', () => {
+
+        defineTaskListCustomElement(editor);
+
+        editor.parser.addNodeFilter('li', function(elms) {
+            for (const elem of elms) {
+                if (elem.attributes.map.class === 'task-list-item') {
+                    replaceTaskListNode(elem);
+                }
+            }
+        });
+
+        // editor.serializer.addNodeFilter('li', function(elms) {
+        //     for (const elem of elms) {
+        //         if (elem.attributes.map.class === 'task-list-item') {
+        //             ensureNodeHasCheckbox(elem);
+        //         }
+        //     }
+        // });
+
+    });
+
+}
+
+/**
+ * @param {AstNode} node
+ */
+function replaceTaskListNode(node) {
+
+    const taskListItem = new tinymce.html.Node.create('task-list-item', {
+    });
+
+    for (const child of node.children()) {
+        if (node.name !== 'input') {
+            taskListItem.append(child);
+        }
+    }
+
+    node.replace(taskListItem);
+}
+
+// /**
+//  * @param {Element} elem
+//  */
+// function ensureElementHasCheckbox(elem) {
+//     const hasCheckbox = elem.querySelector(':scope > input[type="checkbox"]') !== null;
+//     if (hasCheckbox) {
+//         return;
+//     }
+//
+//     const input = elem.ownerDocument.createElement('input');
+//     input.setAttribute('type', 'checkbox');
+//     input.setAttribute('disabled', 'disabled');
+//     elem.prepend(input);
+// }
+
+/**
+ * @param {AstNode} elem
+ */
+function ensureNodeHasCheckbox(elem) {
+    // Stop if there's already an input
+    if (elem.firstChild && elem.firstChild.name === 'input') {
+        return;
+    }
+
+    const input = new tinymce.html.Node.create('input', {
+        type: 'checkbox',
+        disabled: 'disabled',
+    });
+
+    if (elem.firstChild) {
+        elem.insert(input, elem.firstChild, true);
+    } else {
+        elem.append(input);
+    }
+}
+
+
+/**
+ * @param {WysiwygConfigOptions} options
+ * @return {register}
+ */
+export function getPlugin(options) {
+    return register;
+}
\ No newline at end of file
index cbe3cd4be02b25158f261a293c9015274f25c8a6..884808bb44daac5a9585c13302aab568a8ecf3b3 100644 (file)
@@ -310,6 +310,7 @@ li > ol, li > ul {
 }
 
 li.checkbox-item, li.task-list-item {
+  display: list-item;
   list-style: none;
   margin-left: -($-m * 1.2);
   input[type="checkbox"] {