UNPKG

@patternslib/pat-tiptap

Version:
302 lines (258 loc) 12.2 kB
import dom from "@patternslib/patternslib/src/core/dom"; export function init_pre({ app }) { // pre-initialization step: // Search for available toolbar buttons. const tb = app.toolbar_el; const toolbar = {}; if (!tb) { return toolbar; } // paragraph formating toolbar.heading_level_1 = tb.querySelector(".button-heading-level-1"); toolbar.heading_level_2 = tb.querySelector(".button-heading-level-2"); toolbar.heading_level_3 = tb.querySelector(".button-heading-level-3"); toolbar.heading_level_4 = tb.querySelector(".button-heading-level-4"); toolbar.heading_level_5 = tb.querySelector(".button-heading-level-5"); toolbar.heading_level_6 = tb.querySelector(".button-heading-level-6"); toolbar.paragraph = tb.querySelector(".button-paragraph"); toolbar.blockquote = tb.querySelector(".button-blockquote"); toolbar.code_block = tb.querySelector(".button-code-block"); // character formating toolbar.bold = tb.querySelector(".button-bold"); toolbar.italic = tb.querySelector(".button-italic"); toolbar.strike = tb.querySelector(".button-strike"); toolbar.code = tb.querySelector(".button-code"); // lists toolbar.unordered_list = tb.querySelector(".button-unordered-list"); toolbar.ordered_list = tb.querySelector(".button-ordered-list"); // tables toolbar.table_create = tb.querySelector(".button-table-create"); toolbar.table_add_row_above = tb.querySelector(".button-table-add-row-above"); // prettier-ignore toolbar.table_add_row_below = tb.querySelector(".button-table-add-row-below"); // prettier-ignore toolbar.table_add_column_left = tb.querySelector(".button-table-add-column-left"); // prettier-ignore toolbar.table_add_column_right = tb.querySelector(".button-table-add-column-right"); // prettier-ignore toolbar.table_header_cell = tb.querySelector(".button-table-header-cell"); toolbar.table_header_row = tb.querySelector(".button-table-header-row"); toolbar.table_header_column = tb.querySelector(".button-table-header-column"); // prettier-ignore toolbar.table_merge_cells = tb.querySelector(".button-table-merge-cells"); toolbar.table_remove = tb.querySelector(".button-table-remove"); toolbar.table_remove_row = tb.querySelector(".button-table-remove-row"); toolbar.table_remove_column = tb.querySelector(".button-table-remove-column"); // prettier-ignore // other toolbar.horizontal_rule = tb.querySelector(".button-horizontal-rule"); // functionality toolbar.undo = tb.querySelector(".button-undo"); toolbar.redo = tb.querySelector(".button-redo"); // media/links toolbar.link = tb.querySelector(".button-link"); toolbar.image = tb.querySelector(".button-image"); toolbar.embed = tb.querySelector(".button-embed"); toolbar.source = tb.querySelector(".button-source"); return toolbar; } export async function init_extensions({ app }) { // Compile a list of TipTap extensions based on available toolbar buttons. // Btw, we need to import the toolbar extensions upfront for the editor to be initialized. // See: https://github.com/ueberdosis/tiptap/issues/1044 const extensions = []; if (Object.values(app.toolbar).length === 0) { return extensions; } let has_tables = false; const tb = app.toolbar; if ( tb.heading_level_1 || tb.heading_level_2 || tb.heading_level_3 || tb.heading_level_4 || tb.heading_level_5 || tb.heading_level_6 ) { extensions.push((await import("./extensions/heading")).factory()); } if (tb.blockquote) { extensions.push((await import("@tiptap/extension-blockquote")).Blockquote); } if (tb.code_block) { extensions.push((await import("@tiptap/extension-code-block")).CodeBlock); } if (tb.bold) { extensions.push((await import("@tiptap/extension-bold")).Bold); } if (tb.italic) { extensions.push((await import("@tiptap/extension-italic")).Italic); } if (tb.strike) { extensions.push((await import("@tiptap/extension-strike")).Strike); } if (tb.code) { extensions.push((await import("@tiptap/extension-code")).Code); } if (tb.unordered_list || tb.ordered_list) { extensions.push((await import("@tiptap/extension-list-item")).ListItem); } if (tb.unordered_list) { extensions.push((await import("@tiptap/extension-bullet-list")).BulletList); } if (tb.ordered_list) { extensions.push((await import("@tiptap/extension-ordered-list")).OrderedList); } if ( tb.table_create || tb.table_add_row_above || tb.table_add_row_below || tb.table_add_column_left || tb.table_add_column_right || tb.table_header_cell || tb.table_header_row || tb.table_header_column || tb.table_merge_cells || tb.table_remove || tb.table_remove_column || tb.table_remove_row ) { extensions.push( (await import("./extensions/table")).factory().configure({ resizable: false, }) ); extensions.push((await import("@tiptap/extension-table-cell")).default); extensions.push((await import("@tiptap/extension-table-header")).default); extensions.push((await import("@tiptap/extension-table-row")).default); // For the reason to include the next extension see the trailing-node extension code. extensions.push((await import("./extensions/fixed-paragraph")).factory()); extensions.push((await import("./extensions/trailing-node")).factory()); has_tables = true; } if (tb.horizontal_rule) { extensions.push( (await import("@tiptap/extension-horizontal-rule")).HorizontalRule ); } if (tb.link) { extensions.push( (await import("./extensions/link")).factory().configure({ HTMLAttributes: { target: null, rel: null }, // don't set these attributes. openOnClick: false, // don't open documents while editing. linkOnPaste: true, protocols: app.options.link["extra-protocols"], }) ); } if (tb.image) { extensions.push((await import("./extensions/image-inline")).factory()); extensions.push((await import("./extensions/image-figure")).factory()); } if (tb.embed) { extensions.push((await import("./extensions/embed")).factory()); } if (tb.image || tb.embed || has_tables) { extensions.push((await import("@tiptap/extension-dropcursor")).default); extensions.push((await import("./extensions/figure")).factory()); extensions.push((await import("./extensions/figcaption")).factory()); } return extensions; } export async function init_post({ app }) { if (Object.values(app.toolbar).length === 0) { return; } const connect_button = (btn, method, active_name, check_disabled, args = []) => { if (!btn) { return; } btn.addEventListener("click", () => { if (dom.get_data(app.toolbar_el, "tiptap-instance", null) !== app) { // If this pat-tiptap instance is not the one which was last // focused, just return and do nothing. // This might be due to one toolbar shared by multiple editors. return; } app.editor .chain() .focus() [method](...args) .run(); if (active_name || check_disabled) { app.editor.emit("selectionUpdate"); } // Dispatch a custom event for further customization app.editor.options.element.dispatchEvent(new Event(`pat-tiptap--${method}`)); }); if (active_name || check_disabled) { app.editor.on("selectionUpdate", () => { if (active_name) { app.editor.isActive(active_name, ...args) ? btn.classList.add("active") : btn.classList.remove("active"); } if (check_disabled) { btn.disabled = !app.editor.can()[method]; } }); } }; const tb = app.toolbar; connect_button(tb.heading_level_1, "toggleHeading", "heading", false, [{ level: 1 }]); // prettier-ignore connect_button(tb.heading_level_2, "toggleHeading", "heading", false, [{ level: 2 }]); // prettier-ignore connect_button(tb.heading_level_3, "toggleHeading", "heading", false, [{ level: 3 }]); // prettier-ignore connect_button(tb.heading_level_4, "toggleHeading", "heading", false, [{ level: 4 }]); // prettier-ignore connect_button(tb.heading_level_5, "toggleHeading", "heading", false, [{ level: 5 }]); // prettier-ignore connect_button(tb.heading_level_6, "toggleHeading", "heading", false, [{ level: 6 }]); // prettier-ignore connect_button(tb.paragraph, "setParagraph", "paragraph"); connect_button(tb.blockquote, "toggleBlockquote", "blockquote"); connect_button(tb.code_block, "toggleCodeBlock", "codeBlock"); connect_button(tb.bold, "toggleBold", "bold"); connect_button(tb.italic, "toggleItalic", "italic"); connect_button(tb.strike, "toggleStrike", "strike"); connect_button(tb.code, "toggleCode", "code"); connect_button(tb.unordered_list, "toggleBulletList", "bulletList"); connect_button(tb.ordered_list, "toggleOrderedList", "orderedList"); connect_button(tb.table_create, "insertTable", null, false, [{ rows: 3, cols: 3, withHeaderRow: true }]); // prettier-ignore connect_button(tb.table_add_row_above, "addRowBefore", null, true); connect_button(tb.table_add_row_below, "addRowAfter", null, true); connect_button(tb.table_add_column_left, "addColumnBefore", null, true); connect_button(tb.table_add_column_right, "addColumnAfter", null, true); connect_button(tb.table_header_cell, "toggleHeaderCell", null, true); connect_button(tb.table_header_row, "toggleHeaderRow", null, true); connect_button(tb.table_header_column, "toggleHeaderColumn", null, true); connect_button(tb.table_remove, "deleteTable", null, true); connect_button(tb.table_remove_row, "deleteRow", null, true); connect_button(tb.table_remove_column, "deleteColumn", null, true); connect_button(tb.horizontal_rule, "setHorizontalRule"); connect_button(tb.undo, "undo"); connect_button(tb.redo, "redo"); if (tb.table_merge_cells) { tb.table_merge_cells.addEventListener("click", () => { if (dom.get_data(app.toolbar_el, "tiptap-instance", null) !== app) { // If this pat-tiptap instance is not the one which was last // focused, just return and do nothing. // This might be due to one toolbar shared by multiple editors. return; } app.editor.chain().focus().mergeOrSplit().run(); app.editor.emit("selectionUpdate"); }); app.editor.on("selectionUpdate", () => { if (app.editor.can().mergeCells()) { tb.table_merge_cells.classList.add("active"); } if (app.editor.can().splitCell()) { tb.table_merge_cells.classList.remove("active"); } tb.table_merge_cells.disabled = !app.editor.can().mergeOrSplit(); }); } if (tb.link && app.options.link?.panel) { (await import("./extensions/link")).init({ app: app, button: tb.link }); } if (tb.image && app.options.image?.panel) { (await import("./extensions/image-figure")).init({ app: app, button: tb.image }); // prettier-ignore } if (tb.embed && app.options.embed?.panel) { (await import("./extensions/embed")).init({ app: app, button: tb.embed }); } if (tb.source && app.options.sourcePanel) { (await import("./extensions/source")).init({ app: app, button: tb.source }); } }