2021-02-12 22:18:48 +00:00
|
|
|
import { Editor } from 'editor/editor'
|
|
|
|
import {
|
|
|
|
safeGetSelection, safeGetRangeAt,
|
|
|
|
moveChildren,
|
|
|
|
blockNames, parentBlockNames,
|
|
|
|
} from 'editor/utils'
|
|
|
|
import { EditorNode, getType } from 'editor/types'
|
2021-02-12 15:57:23 +00:00
|
|
|
|
2021-02-12 22:18:48 +00:00
|
|
|
function makeParentBlock (tag: string, create: EditorNode["create"]): EditorNode {
|
2021-02-12 15:57:23 +00:00
|
|
|
return {
|
|
|
|
selector: tag,
|
2021-02-14 16:01:41 +00:00
|
|
|
allowedChildren: [...blockNames, 'multimedia'],
|
2021-02-12 15:57:23 +00:00
|
|
|
handleEmpty: 'remove',
|
2021-02-12 22:18:48 +00:00
|
|
|
create,
|
2021-02-12 15:57:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: añadir blockquote
|
|
|
|
// XXX: si agregás algo acá, probablemente le quieras hacer un botón
|
|
|
|
// en app/views/posts/attributes/_content.haml
|
2021-02-12 22:18:48 +00:00
|
|
|
export const parentBlocks: { [propName: string]: EditorNode } = {
|
2021-02-12 15:57:23 +00:00
|
|
|
left: makeParentBlock('div[data-align=left]', () => {
|
|
|
|
const el = document.createElement('div')
|
|
|
|
el.dataset.align = 'left'
|
|
|
|
return el
|
|
|
|
}),
|
|
|
|
center: makeParentBlock('div[data-align=center]', () => {
|
|
|
|
const el = document.createElement('div')
|
|
|
|
el.dataset.align = 'center'
|
|
|
|
return el
|
|
|
|
}),
|
|
|
|
right: makeParentBlock('div[data-align=right]', () => {
|
|
|
|
const el = document.createElement('div')
|
|
|
|
el.dataset.align = 'right'
|
|
|
|
return el
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
|
2021-02-12 22:18:48 +00:00
|
|
|
export function setupButtons (editor: Editor): void {
|
|
|
|
for (const [ name, type ] of Object.entries(parentBlocks)) {
|
|
|
|
const buttonEl = editor.toolbarEl.querySelector(
|
|
|
|
`[data-editor-button="parentBlock-${name}"]`
|
|
|
|
)
|
|
|
|
if (!buttonEl) continue
|
|
|
|
buttonEl.addEventListener("click", event => {
|
|
|
|
event.preventDefault()
|
|
|
|
|
|
|
|
const sel = safeGetSelection(editor)
|
|
|
|
if (!sel) return
|
|
|
|
const range = safeGetRangeAt(sel)
|
|
|
|
if (!range) return
|
|
|
|
|
|
|
|
// TODO: Esto solo mueve el bloque en el que está el final de la selección
|
|
|
|
// (anchorNode). quizás lo podemos hacer al revés (iterar desde contentEl
|
|
|
|
// para encontrar los bloques que están seleccionados y moverlos/cambiarles
|
|
|
|
// el parentBlock)
|
|
|
|
|
|
|
|
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('no')
|
|
|
|
|
2021-02-13 01:14:36 +00:00
|
|
|
const replacementEl = type.create(editor)
|
2021-02-12 22:18:48 +00:00
|
|
|
if (parentEl == editor.contentEl) {
|
|
|
|
// no está en un parentBlock
|
|
|
|
editor.contentEl.insertBefore(replacementEl, blockEl)
|
|
|
|
replacementEl.appendChild(blockEl)
|
|
|
|
} else {
|
|
|
|
// está en un parentBlock
|
|
|
|
moveChildren(parentEl, replacementEl, null)
|
|
|
|
editor.contentEl.replaceChild(replacementEl, parentEl)
|
|
|
|
}
|
|
|
|
sel.collapse(replacementEl)
|
|
|
|
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|