import { Editor } from 'editor/editor' import { safeGetSelection, safeGetRangeAt, moveChildren } from 'editor/utils' import { EditorNode, getType } from 'editor/types' import { markNames } from 'editor/types/marks' import { parentBlockNames } from 'editor/types/parentBlocks' // TODO: implementar multimedia como otro tipo! ya que no puede tener children // debe ser tratado distinto que los bloques (quizás EditorBlockWithText y // EditorBlock o algo así) export interface EditorBlock extends EditorNode { } export const blockNames = ['paragraph', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'unordered_list', 'ordered_list'] function makeBlock (tag: string): EditorBlock { return { selector: tag, allowedChildren: [...markNames, 'text'], handleEmpty: 'do-nothing', create: () => { const el = document.createElement(tag) return el //moveChildren(el, newEl, null) //el.parentNode!.replaceChild(newEl, el) //// TODO: mantener la selección //const sel = window.getSelection() //sel && sel.collapse(newEl, 0) }, } } 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 sel = safeGetSelection(editor) if (!sel) return const range = safeGetRangeAt(sel) if (!range) return let blockEl = sel.anchorNode while (true) { if (!blockEl) throw new Error('WTF') if (!blockEl.parentElement) throw new Error('No pude encontrar contentEl!') let type = getType(blockEl.parentElement) if (!type) throw new Error('La selección está en algo que no es un type!') if (type.typeName === 'contentEl' || parentBlockNames.includes(type.typeName) ) break blockEl = blockEl.parentElement } if (!(blockEl instanceof Element)) throw new Error('La selección no está en un elemento!') const parentEl = blockEl.parentElement if (!parentEl) throw new Error('Inesperado') let replacementType = blockEl.matches(type.selector) ? blocks.paragraph : type const el = replacementType.create() moveChildren(blockEl, el, null) parentEl.replaceChild(el, blockEl) sel.collapse(el) return false }) } }