5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-11-15 05:21:42 +00:00

Merge branch 'void/editor' into rails

This commit is contained in:
f 2021-03-23 11:43:49 -03:00
commit 365146ed59
8 changed files with 59 additions and 35 deletions

View file

@ -1,5 +1,5 @@
import { storeContent, restoreContent, forgetContent } from 'editor/storage' import { storeContent, restoreContent, forgetContent } from 'editor/storage'
import { isDirectChild, moveChildren, safeGetSelection, safeGetRangeAt, setAuxiliaryToolbar } from 'editor/utils' import { isDirectChild, moveChildren, safeGetSelection, safeGetRangeAt, setAuxiliaryToolbar, parentBlockNames, clearSelected } from 'editor/utils'
import { types, getValidChildren, getType } from 'editor/types' import { types, getValidChildren, getType } from 'editor/types'
import { setupButtons as setupMarksButtons } from 'editor/types/marks' import { setupButtons as setupMarksButtons } from 'editor/types/marks'
import { setupButtons as setupBlocksButtons } from 'editor/types/blocks' import { setupButtons as setupBlocksButtons } from 'editor/types/blocks'
@ -252,8 +252,7 @@ function setupEditor (editorEl: HTMLElement): void {
const type = getType(target) const type = getType(target)
if (!type || !type.type.onClick) { if (!type || !type.type.onClick) {
setAuxiliaryToolbar(editor, null) setAuxiliaryToolbar(editor, null)
const selectedEl = editor.contentEl.querySelector('[data-editor-selected]') clearSelected(editor)
if (selectedEl) delete (selectedEl as HTMLElement).dataset.editorSelected
return true return true
} }
type.type.onClick(editor, target) type.type.onClick(editor, target)
@ -282,7 +281,7 @@ document.addEventListener("turbolinks:load", () => {
const flash = document.querySelector<HTMLElement>('.js-flash') const flash = document.querySelector<HTMLElement>('.js-flash')
if (flash) { if (flash) {
const keys = JSON.parse(flash.dataset.keys || '') const keys = JSON.parse(flash.dataset.keys || '[]')
switch (flash.dataset.target) { switch (flash.dataset.target) {
case 'editor': case 'editor':

View file

@ -20,6 +20,10 @@ export interface EditorNode {
// ej: ul: { handleNothing: li } // ej: ul: { handleNothing: li }
handleEmpty: 'do-nothing' | 'remove' | EditorBlock, handleEmpty: 'do-nothing' | 'remove' | EditorBlock,
// esta función puede ser llamada para cosas que no necesariamente sea la
// creación del nodo con el botón; por ejemplo, al intentar recuperar
// el formato. esto es importante por que, por ejemplo, no deberíamos
// cambiar la selección acá.
create: (editor: Editor) => HTMLElement, create: (editor: Editor) => HTMLElement,
onClick?: (editor: Editor, target: Element) => void, onClick?: (editor: Editor, target: Element) => void,

View file

@ -79,6 +79,7 @@ export function setupButtons (editor: Editor): void {
: type : type
const el = replacementType.create(editor) const el = replacementType.create(editor)
replacementType.onClick && replacementType.onClick(editor, el)
moveChildren(blockEl, el, null) moveChildren(blockEl, el, null)
parentEl.replaceChild(el, blockEl) parentEl.replaceChild(el, blockEl)
sel.collapse(el) sel.collapse(el)

View file

@ -1,6 +1,13 @@
import { Editor } from 'editor/editor' import { Editor } from 'editor/editor'
import { EditorNode } from 'editor/types' import { EditorNode } from 'editor/types'
import { markNames, setAuxiliaryToolbar } from 'editor/utils' import { markNames, setAuxiliaryToolbar, clearSelected } from 'editor/utils'
function select (editor: Editor, el: HTMLAnchorElement): void {
clearSelected(editor)
el.dataset.editorSelected = ''
editor.toolbar.auxiliary.link.urlEl.value = el.href
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.link.parentEl)
}
export const link: EditorNode = { export const link: EditorNode = {
selector: 'a', selector: 'a',
@ -10,9 +17,7 @@ export const link: EditorNode = {
onClick (editor, el) { onClick (editor, el) {
if (!(el instanceof HTMLAnchorElement)) if (!(el instanceof HTMLAnchorElement))
throw new Error('oh no') throw new Error('oh no')
el.dataset.editorSelected = '' select(editor, el)
editor.toolbar.auxiliary.link.urlEl.value = el.href
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.link.parentEl)
}, },
} }

View file

@ -1,6 +1,6 @@
import { Editor } from 'editor/editor' import { Editor } from 'editor/editor'
import { EditorNode } from 'editor/types' import { EditorNode } from 'editor/types'
import { markNames, setAuxiliaryToolbar } from 'editor/utils' import { markNames, setAuxiliaryToolbar, clearSelected } from 'editor/utils'
const hex = (x: string) => ("0" + parseInt(x).toString(16)).slice(-2) const hex = (x: string) => ("0" + parseInt(x).toString(16)).slice(-2)
// https://stackoverflow.com/a/3627747 // https://stackoverflow.com/a/3627747
@ -11,6 +11,16 @@ function rgbToHex (rgb: string): string {
return "#" + hex(matches[1]) + hex(matches[2]) + hex(matches[3]) return "#" + hex(matches[1]) + hex(matches[2]) + hex(matches[3])
} }
function select (editor: Editor, el: HTMLElement): void {
clearSelected(editor)
el.dataset.editorSelected = ''
editor.toolbar.auxiliary.mark.colorEl.value
= el.style.backgroundColor
? rgbToHex(el.style.backgroundColor)
: '#f206f9'
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.mark.parentEl)
}
export const mark: EditorNode = { export const mark: EditorNode = {
selector: 'mark', selector: 'mark',
allowedChildren: [...markNames.filter(n => n !== 'mark'), 'text'], allowedChildren: [...markNames.filter(n => n !== 'mark'), 'text'],
@ -19,12 +29,7 @@ export const mark: EditorNode = {
onClick (editor, el) { onClick (editor, el) {
if (!(el instanceof HTMLElement)) if (!(el instanceof HTMLElement))
throw new Error('oh no') throw new Error('oh no')
el.dataset.editorSelected = '' select(editor, el)
editor.toolbar.auxiliary.mark.colorEl.value
= el.style.backgroundColor
? rgbToHex(el.style.backgroundColor)
: '#f206f9'
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.mark.parentEl)
}, },
} }

View file

@ -4,7 +4,6 @@ import {
safeGetSelection, safeGetRangeAt, safeGetSelection, safeGetRangeAt,
moveChildren, moveChildren,
markNames, markNames,
setAuxiliaryToolbar,
} from 'editor/utils' } from 'editor/utils'
import { link } from 'editor/types/link' import { link } from 'editor/types/link'
import { mark } from 'editor/types/mark' import { mark } from 'editor/types/mark'
@ -82,6 +81,7 @@ export function setupButtons (editor: Editor): void {
return console.error("No puedo marcar cosas a través de distintos bloques!") return console.error("No puedo marcar cosas a través de distintos bloques!")
const tagEl = type.create(editor) const tagEl = type.create(editor)
type.onClick && type.onClick(editor, tagEl)
tagEl.appendChild(range.extractContents()) tagEl.appendChild(range.extractContents())

View file

@ -3,7 +3,7 @@ import { EditorNode, getType } from 'editor/types'
import { import {
safeGetSelection, safeGetRangeAt, safeGetSelection, safeGetRangeAt,
markNames, parentBlockNames, markNames, parentBlockNames,
setAuxiliaryToolbar, setAuxiliaryToolbar, clearSelected,
} from 'editor/utils' } from 'editor/utils'
// TODO: tener ActiveStorage como import así no hacemos hacks // TODO: tener ActiveStorage como import así no hacemos hacks
@ -59,6 +59,18 @@ function setAlt (multimediaInnerEl: HTMLElement, value: string): void {
} }
} }
function select (editor: Editor, el: HTMLElement): void {
clearSelected(editor)
el.dataset.editorSelected = ''
const innerEl = el.querySelector<HTMLElement>('[data-multimedia-inner]')
if (!innerEl) throw new Error('No hay multimedia válida')
if (innerEl.tagName !== 'P')
editor.toolbar.auxiliary.multimedia.altEl.value = getAlt(innerEl) || ''
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.multimedia.parentEl)
}
export const multimedia: EditorNode = { export const multimedia: EditorNode = {
selector: 'figure[data-multimedia]', selector: 'figure[data-multimedia]',
allowedChildren: 'ignore-children', allowedChildren: 'ignore-children',
@ -85,14 +97,7 @@ export const multimedia: EditorNode = {
onClick (editor, el) { onClick (editor, el) {
if (!(el instanceof HTMLElement)) if (!(el instanceof HTMLElement))
throw new Error('oh no') throw new Error('oh no')
el.dataset.editorSelected = '' select(editor, el)
const innerEl = el.querySelector<HTMLElement>('[data-multimedia-inner]')
if (!innerEl) throw new Error('No hay multimedia válida')
if (innerEl.tagName !== 'P')
editor.toolbar.auxiliary.multimedia.altEl.value = getAlt(innerEl) || ''
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.multimedia.parentEl)
}, },
} }
function createElementWithFile (url: string, type: string): HTMLElement { function createElementWithFile (url: string, type: string): HTMLElement {
@ -213,6 +218,7 @@ export function setupButtons (editor: Editor): void {
if (!parentEl) throw new Error('Inesperado') if (!parentEl) throw new Error('Inesperado')
const el = multimedia.create(editor) const el = multimedia.create(editor)
multimedia.onClick!(editor, el)
parentEl.insertBefore(el, blockEl.nextElementSibling) parentEl.insertBefore(el, blockEl.nextElementSibling)
return false return false

View file

@ -71,3 +71,7 @@ export function setAuxiliaryToolbar (editor: Editor, bar: HTMLElement | null): v
} }
if (bar) bar.dataset.editorAuxiliaryActive = 'active' if (bar) bar.dataset.editorAuxiliaryActive = 'active'
} }
export function clearSelected (editor: Editor): void {
const selectedEl = editor.contentEl.querySelector('[data-editor-selected]')
if (selectedEl) delete (selectedEl as HTMLElement).dataset.editorSelected
}