5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-07-07 10:45:45 +00:00
panel/app/javascript/editor/types/marks.ts

97 lines
2.5 KiB
TypeScript
Raw Normal View History

import { Editor } from 'editor/editor'
import { EditorNode } from 'editor/types'
import {
safeGetSelection, safeGetRangeAt,
moveChildren,
markNames,
} from 'editor/utils'
2021-02-13 01:14:36 +00:00
import { link } from 'editor/types/link'
import { mark } from 'editor/types/mark'
function makeMark (name: string, tag: string): EditorNode {
return {
selector: tag,
allowedChildren: [...markNames.filter(n => n !== name), 'text'],
handleEmpty: 'remove',
create: () => document.createElement(tag),
}
}
// XXX: si agregás algo acá, agregalo a markNames
export const marks: { [propName: string]: EditorNode } = {
bold: makeMark('bold', 'strong'),
italic: makeMark('italic', 'em'),
deleted: makeMark('deleted', 'del'),
underline: makeMark('underline', 'u'),
sub: makeMark('sub', 'sub'),
super: makeMark('super', 'sup'),
mark,
2021-02-13 01:14:36 +00:00
link,
2021-03-26 15:31:36 +00:00
small: makeMark('small', 'small'),
}
function recursiveFilterSelection (
node: Element,
selection: Selection,
selector: string,
): Element[] {
let output: Element[] = []
for (const child of [...node.children]) {
if (child.matches(selector)
&& selection.containsNode(child)
) output.push(child)
output = [...output, ...recursiveFilterSelection(child, selection, selector)]
}
return output
}
export function setupButtons (editor: Editor): void {
for (const [ name, type ] of Object.entries(marks)) {
const buttonEl = editor.toolbarEl.querySelector(`[data-editor-button="mark-${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 parentEl = range.commonAncestorContainer
while (!(parentEl instanceof Element)) {
if (!parentEl.parentElement) return
parentEl = parentEl.parentElement
}
const existingMarks = recursiveFilterSelection(
parentEl,
sel,
type.selector,
)
console.debug('marks encontradas:', existingMarks)
if (existingMarks.length > 0) {
const mark = existingMarks[0]
if (!mark.parentElement)
throw new Error(':/')
moveChildren(mark, mark.parentElement, mark)
mark.parentElement.removeChild(mark)
} else {
if (range.commonAncestorContainer === editor.contentEl)
// TODO: mostrar error
return console.error("No puedo marcar cosas a través de distintos bloques!")
2021-02-13 01:14:36 +00:00
const tagEl = type.create(editor)
type.onClick && type.onClick(editor, tagEl)
tagEl.appendChild(range.extractContents())
range.insertNode(tagEl)
range.selectNode(tagEl)
}
return false
})
}
}