editor: desrepetir código
esto me huele a que podría introducir bugs pero espero que no.
This commit is contained in:
parent
3b9237d870
commit
b11346074a
4 changed files with 71 additions and 88 deletions
|
@ -3,7 +3,7 @@ import { marks } from 'editor/types/marks'
|
|||
import { blocks, li, EditorBlock } from 'editor/types/blocks'
|
||||
import { parentBlocks } from 'editor/types/parentBlocks'
|
||||
import { multimedia } from 'editor/types/multimedia'
|
||||
import { blockNames, parentBlockNames } from 'editor/utils'
|
||||
import { blockNames, parentBlockNames, safeGetRangeAt, safeGetSelection } from 'editor/utils'
|
||||
|
||||
export interface EditorNode {
|
||||
selector: string,
|
||||
|
@ -56,6 +56,54 @@ export function getType (node: Element): { typeName: string, type: EditorNode }
|
|||
return null
|
||||
}
|
||||
|
||||
// encuentra el primer pariente que pueda tener al type, y retorna un array
|
||||
// donde
|
||||
// array[0] = elemento que matchea el type
|
||||
// array[array.len - 1] = primer elemento seleccionado
|
||||
export function getValidParentInSelection (args: {
|
||||
editor: Editor,
|
||||
type: string,
|
||||
}): Element[] {
|
||||
const sel = safeGetSelection(args.editor)
|
||||
if (!sel) throw new Error('No se donde insertar esto')
|
||||
const range = safeGetRangeAt(sel)
|
||||
if (!range) throw new Error('No se donde insertar esto')
|
||||
|
||||
let list: Element[] = []
|
||||
|
||||
if (!sel.anchorNode) {
|
||||
throw new Error('No se donde insertar esto')
|
||||
} else if (sel.anchorNode instanceof Element) {
|
||||
list = [sel.anchorNode]
|
||||
} else if (sel.anchorNode.parentElement) {
|
||||
list = [sel.anchorNode.parentElement]
|
||||
} else {
|
||||
throw new Error('No se donde insertar esto')
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const el = list[0]
|
||||
if (!args.editor.contentEl.contains(el)
|
||||
&& el != args.editor.contentEl)
|
||||
throw new Error('No se donde insertar esto')
|
||||
const type = getType(el)
|
||||
|
||||
if (type) {
|
||||
//if (type.typeName === 'contentEl') break
|
||||
//if (parentBlockNames.includes(type.typeName)) break
|
||||
if ((type.type.allowedChildren instanceof Array)
|
||||
&& type.type.allowedChildren.includes(args.type)) break
|
||||
}
|
||||
if (el.parentElement) {
|
||||
list = [el.parentElement, ...list]
|
||||
} else {
|
||||
throw new Error('No se donde insertar esto')
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
export function getValidChildren (node: Element, type: EditorNode): Node[] {
|
||||
if (type.allowedChildren === 'ignore-children')
|
||||
throw new Error('se llamó a getValidChildren con un type que no lo permite!')
|
||||
|
|
|
@ -2,9 +2,9 @@ import { Editor } from 'editor/editor'
|
|||
import {
|
||||
safeGetSelection, safeGetRangeAt,
|
||||
moveChildren,
|
||||
markNames, parentBlockNames,
|
||||
markNames, blockNames, parentBlockNames,
|
||||
} from 'editor/utils'
|
||||
import { EditorNode, getType } from 'editor/types'
|
||||
import { EditorNode, getType, getValidParentInSelection } from 'editor/types'
|
||||
|
||||
export interface EditorBlock extends EditorNode {
|
||||
}
|
||||
|
@ -49,40 +49,22 @@ export function setupButtons (editor: Editor): void {
|
|||
buttonEl.addEventListener("click", event => {
|
||||
event.preventDefault()
|
||||
|
||||
const sel = safeGetSelection(editor)
|
||||
if (!sel) return
|
||||
const range = safeGetRangeAt(sel)
|
||||
if (!range) return
|
||||
const list = getValidParentInSelection({ editor, type: name })
|
||||
|
||||
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
|
||||
// No borrar cosas como multimedia
|
||||
if (blockNames.indexOf(getType(list[1])!.typeName) === -1) {
|
||||
return
|
||||
}
|
||||
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)
|
||||
let replacementType = list[1].matches(type.selector)
|
||||
? blocks.paragraph
|
||||
: type
|
||||
|
||||
const el = replacementType.create(editor)
|
||||
replacementType.onClick && replacementType.onClick(editor, el)
|
||||
moveChildren(blockEl, el, null)
|
||||
parentEl.replaceChild(el, blockEl)
|
||||
sel.collapse(el)
|
||||
moveChildren(list[1], el, null)
|
||||
list[0].replaceChild(el, list[1])
|
||||
window.getSelection()?.collapse(el)
|
||||
|
||||
return false
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Editor } from 'editor/editor'
|
||||
import { EditorNode, getType } from 'editor/types'
|
||||
import { EditorNode, getValidParentInSelection } from 'editor/types'
|
||||
import {
|
||||
safeGetSelection, safeGetRangeAt,
|
||||
markNames, parentBlockNames,
|
||||
|
@ -192,34 +192,11 @@ export function setupButtons (editor: Editor): void {
|
|||
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')
|
||||
const list = getValidParentInSelection({ editor, type: 'multimedia' })
|
||||
|
||||
const el = multimedia.create(editor)
|
||||
multimedia.onClick!(editor, el)
|
||||
parentEl.insertBefore(el, blockEl.nextElementSibling)
|
||||
list[0].insertBefore(el, list[1].nextElementSibling)
|
||||
select(editor, el)
|
||||
|
||||
return false
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
moveChildren,
|
||||
blockNames, parentBlockNames,
|
||||
} from 'editor/utils'
|
||||
import { EditorNode, getType } from 'editor/types'
|
||||
import { EditorNode, getType, getValidParentInSelection } from 'editor/types'
|
||||
|
||||
function makeParentBlock (tag: string, create: EditorNode["create"]): EditorNode {
|
||||
return {
|
||||
|
@ -45,48 +45,24 @@ export function setupButtons (editor: Editor): void {
|
|||
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')
|
||||
const list = getValidParentInSelection({ editor, type: name })
|
||||
|
||||
const replacementEl = type.create(editor)
|
||||
if (parentEl == editor.contentEl) {
|
||||
if (list[0] == editor.contentEl) {
|
||||
// no está en un parentBlock
|
||||
editor.contentEl.insertBefore(replacementEl, blockEl)
|
||||
replacementEl.appendChild(blockEl)
|
||||
editor.contentEl.insertBefore(replacementEl, list[1])
|
||||
replacementEl.appendChild(list[1])
|
||||
} else {
|
||||
// está en un parentBlock
|
||||
moveChildren(parentEl, replacementEl, null)
|
||||
editor.contentEl.replaceChild(replacementEl, parentEl)
|
||||
moveChildren(list[0], replacementEl, null)
|
||||
editor.contentEl.replaceChild(replacementEl, list[0])
|
||||
}
|
||||
sel.collapse(replacementEl)
|
||||
window.getSelection()?.collapse(replacementEl)
|
||||
|
||||
return false
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue