sutty/app/javascript/editor/types/blocks.ts

77 lines
2 KiB
TypeScript

import { Editor } from "editor/editor";
import {
safeGetSelection,
safeGetRangeAt,
moveChildren,
markNames,
blockNames,
parentBlockNames,
} from "editor/utils";
import { EditorNode, getType, getValidParentInSelection } from "editor/types";
export interface EditorBlock extends EditorNode {}
function makeBlock(tag: string): EditorBlock {
return {
selector: tag,
allowedChildren: [...markNames, "text"],
handleEmpty: "do-nothing",
create: () => document.createElement(tag),
};
}
export const li: EditorBlock = makeBlock("li");
// XXX: si agregás algo acá, agregalo a blockNames
// (y probablemente le quieras hacer un botón en app/views/posts/attributes/_content.haml)
export const blocks: { [propName: string]: EditorBlock } = {
paragraph: makeBlock("p"),
h1: makeBlock("h1"),
h2: makeBlock("h2"),
h3: makeBlock("h3"),
h4: makeBlock("h4"),
h5: makeBlock("h5"),
h6: makeBlock("h6"),
unordered_list: {
...makeBlock("ul"),
allowedChildren: ["li"],
handleEmpty: li,
},
ordered_list: {
...makeBlock("ol"),
allowedChildren: ["li"],
handleEmpty: li,
},
};
export function setupButtons(editor: Editor): void {
for (const [name, type] of Object.entries(blocks)) {
const buttonEl = editor.toolbarEl.querySelector(
`[data-editor-button="block-${name}"]`
);
if (!buttonEl) continue;
buttonEl.addEventListener("click", (event) => {
event.preventDefault();
const list = getValidParentInSelection({ editor, type: name });
// No borrar cosas como multimedia
if (blockNames.indexOf(getType(list[1])!.typeName) === -1) {
return;
}
let replacementType = list[1].matches(type.selector)
? blocks.paragraph
: type;
const el = replacementType.create(editor);
replacementType.onClick && replacementType.onClick(editor, el);
moveChildren(list[1], el, null);
list[0].replaceChild(el, list[1]);
window.getSelection()?.collapse(el);
return false;
});
}
}