From 6467a265d3fd2c1b77d576d2cd5412c6f189ac0d Mon Sep 17 00:00:00 2001 From: f Date: Tue, 10 Aug 2021 18:36:55 -0300 Subject: [PATCH] Deprecar el editor --- app/javascript/editor/editor.ts | 313 -------------------------------- 1 file changed, 313 deletions(-) diff --git a/app/javascript/editor/editor.ts b/app/javascript/editor/editor.ts index 233cc3c0..c254a650 100644 --- a/app/javascript/editor/editor.ts +++ b/app/javascript/editor/editor.ts @@ -1,320 +1,7 @@ -import { storeContent, restoreContent, forgetContent } from "editor/storage"; -import { - isDirectChild, - moveChildren, - safeGetSelection, - safeGetRangeAt, - setAuxiliaryToolbar, - parentBlockNames, - clearSelected, -} from "editor/utils"; -import { types, getValidChildren, getType } from "editor/types"; -import { setupButtons as setupMarksButtons } from "editor/types/marks"; -import { setupButtons as setupBlocksButtons } from "editor/types/blocks"; -import { setupButtons as setupParentBlocksButtons } from "editor/types/parentBlocks"; -import { setupAuxiliaryToolbar as setupLinkAuxiliaryToolbar } from "editor/types/link"; -import { - setupAuxiliaryToolbar as setupMultimediaAuxiliaryToolbar, - setupButtons as setupMultimediaButtons, -} from "editor/types/multimedia"; -import { setupAuxiliaryToolbar as setupMarkAuxiliaryToolbar } from "editor/types/mark"; - /// @ts-ignore import SuttyEditor from "@suttyweb/editor"; import "@suttyweb/editor/dist/style.css"; -// Esta funcion corrije errores que pueden haber como: -// * que un nodo que no tiene 'text' permitido no tenga children (se les -// inserta un allowedChildren[0]) -// * TODO: que haya una imágen sin
o que no esté como bloque (se ponen -// después del bloque en el que están como bloque de por si) -// * convierte y en y -// Lo hace para que siga la estructura del documento y que no se borren por -// cleanContent luego. -function fixContent(editor: Editor, node: Element = editor.contentEl): void { - if (node.tagName === "SCRIPT" || node.tagName === "STYLE") { - node.parentElement?.removeChild(node); - return; - } - - if (node.tagName === "I") { - const el = document.createElement("em"); - moveChildren(node, el, null); - node.parentElement?.replaceChild(el, node); - node = el; - } - if (node.tagName === "B") { - const el = document.createElement("strong"); - moveChildren(node, el, null); - node.parentElement?.replaceChild(el, node); - node = el; - } - - if (node instanceof HTMLImageElement) { - node.dataset.multimediaInner = ""; - const figureEl = types.multimedia.create(editor); - - let targetEl = node.parentElement; - if (!targetEl) throw new Error("No encontré lx objetivo"); - while (true) { - const type = getType(targetEl); - if (!type) throw new Error("lx objetivo tiene tipo"); - if (type.type.allowedChildren.includes("multimedia")) break; - if (!targetEl.parentElement) throw new Error("No encontré lx objetivo"); - targetEl = targetEl.parentElement; - } - - let parentEl = [...targetEl.childNodes].find((el) => el.contains(node)); - if (!parentEl) throw new Error("no encontré lx pariente"); - targetEl.insertBefore(figureEl, parentEl); - - const innerEl = figureEl.querySelector("[data-multimedia-inner]"); - if (!innerEl) throw new Error("Raro."); - figureEl.replaceChild(node, innerEl); - - node = figureEl; - } - - const _type = getType(node); - if (!_type) return; - - const { typeName, type } = _type; - - if (type.allowedChildren !== "ignore-children") { - const sel = safeGetSelection(editor); - const range = sel && safeGetRangeAt(sel); - - if (getValidChildren(node, type).length == 0) { - if (typeof type.handleEmpty !== "string") { - const el = type.handleEmpty.create(editor); - // mover cosas que pueden haber - // por ejemplo: cuando convertís a un
    , queda texto fuera del li que - // creamos acá - moveChildren(node, el, null); - node.appendChild(el); - if (range?.intersectsNode(node)) sel?.collapse(el); - } - } - - for (const child of node.childNodes) { - if (!(child instanceof Element)) continue; - fixContent(editor, child); - } - } -} - -// Esta funcion hace que los elementos del editor sigan la estructura. -// TODO: nos falta borrar atributos (style, y básicamente cualquier otra cosa) -// Edge cases: -// * no borramos los
    por que se requieren para que los navegadores -// funcionen bien al escribir. no se deberían mostrar de todas maneras -function cleanContent(editor: Editor, node: Element = editor.contentEl): void { - const _type = getType(node); - if (!_type) { - node.parentElement?.removeChild(node); - return; - } - - const { type } = _type; - - if (type.allowedChildren !== "ignore-children") { - for (const child of node.childNodes) { - if ( - child.nodeType === Node.TEXT_NODE && - !type.allowedChildren.includes("text") - ) { - node.removeChild(child); - continue; - } - - if (!(child instanceof Element)) continue; - - const childType = getType(child); - if (childType?.typeName === "br") continue; - if (!childType || !type.allowedChildren.includes(childType.typeName)) { - // XXX: esto extrae las cosas de adentro para que no sea destructivo - moveChildren(child, node, child); - node.removeChild(child); - return; - } - - cleanContent(editor, child); - } - - // solo contar children válido para ese nodo - const validChildrenLength = getValidChildren(node, type).length; - - const sel = safeGetSelection(editor); - const range = sel && safeGetRangeAt(sel); - if ( - type.handleEmpty === "remove" && - validChildrenLength == 0 - //&& (!range || !range.intersectsNode(node)) - ) { - node.parentNode?.removeChild(node); - return; - } - } -} - -function routine(editor: Editor): void { - try { - fixContent(editor); - cleanContent(editor); - storeContent(editor); - - editor.htmlEl.value = editor.contentEl.innerHTML; - } catch (error) { - console.error("Hubo un problema corriendo la rutina", editor, error); - } -} - -export interface Editor { - editorEl: HTMLElement; - toolbarEl: HTMLElement; - toolbar: { - auxiliary: { - mark: { - parentEl: HTMLElement; - colorEl: HTMLInputElement; - textColorEl: HTMLInputElement; - }; - multimedia: { - parentEl: HTMLElement; - fileEl: HTMLInputElement; - uploadEl: HTMLButtonElement; - altEl: HTMLInputElement; - removeEl: HTMLButtonElement; - }; - link: { - parentEl: HTMLElement; - urlEl: HTMLInputElement; - }; - }; - }; - contentEl: HTMLElement; - wordAlertEl: HTMLElement; - htmlEl: HTMLTextAreaElement; -} - -function getSel(parentEl: HTMLElement, selector: string): T { - const el = parentEl.querySelector(selector); - if (!el) throw new Error(`No pude encontrar un componente \`${selector}\``); - return el; -} - -function setupEditor(editorEl: HTMLElement): void { - // XXX: ¡Esto afecta a todo el documento! ¿Quizás usar un iframe para el editor? - document.execCommand("defaultParagraphSeparator", false, "p"); - - const editor: Editor = { - editorEl, - toolbarEl: getSel(editorEl, ".editor-toolbar"), - toolbar: { - auxiliary: { - mark: { - parentEl: getSel(editorEl, "[data-editor-auxiliary=mark]"), - colorEl: getSel( - editorEl, - "[data-editor-auxiliary=mark] [name=mark-color]" - ), - textColorEl: getSel( - editorEl, - "[data-editor-auxiliary=mark] [name=mark-text-color]" - ), - }, - multimedia: { - parentEl: getSel(editorEl, "[data-editor-auxiliary=multimedia]"), - fileEl: getSel( - editorEl, - "[data-editor-auxiliary=multimedia] [name=multimedia-file]" - ), - uploadEl: getSel( - editorEl, - "[data-editor-auxiliary=multimedia] [name=multimedia-file-upload]" - ), - altEl: getSel( - editorEl, - "[data-editor-auxiliary=multimedia] [name=multimedia-alt]" - ), - removeEl: getSel( - editorEl, - "[data-editor-auxiliary=multimedia] [name=multimedia-remove]" - ), - }, - link: { - parentEl: getSel(editorEl, "[data-editor-auxiliary=link]"), - urlEl: getSel( - editorEl, - "[data-editor-auxiliary=link] [name=link-url]" - ), - }, - }, - }, - contentEl: getSel(editorEl, ".editor-content"), - wordAlertEl: getSel(editorEl, ".editor-aviso-word"), - htmlEl: getSel(editorEl, "textarea"), - }; - console.debug("iniciando editor", editor); - - // Recuperar el contenido si hay algo guardado, si tuviéramos un campo - // de última edición podríamos saber si el artículo fue editado - // después o la versión local es la última. - // - // TODO: Preguntar si se lo quiere recuperar. - restoreContent(editor); - - // Word alert - editor.contentEl.addEventListener("paste", () => { - editor.wordAlertEl.style.display = "block"; - }); - - // Setup routine listeners - const observer = new MutationObserver(() => routine(editor)); - observer.observe(editor.contentEl, { - childList: true, - attributes: true, - subtree: true, - characterData: true, - }); - - document.addEventListener("selectionchange", () => routine(editor)); - - // Capture onClick - editor.contentEl.addEventListener( - "click", - (event) => { - const target = event.target! as Element; - const type = getType(target); - if (!type || !type.type.onClick) { - setAuxiliaryToolbar(editor, null); - clearSelected(editor); - return true; - } - type.type.onClick(editor, target); - return false; - }, - true - ); - - // Clean seleted - const selectedEl = editor.contentEl.querySelector("[data-editor-selected]"); - if (selectedEl) delete (selectedEl as HTMLElement).dataset.editorSelected; - - // Setup botones - setupMarksButtons(editor); - setupBlocksButtons(editor); - setupParentBlocksButtons(editor); - setupMultimediaButtons(editor); - - setupLinkAuxiliaryToolbar(editor); - setupMultimediaAuxiliaryToolbar(editor); - setupMarkAuxiliaryToolbar(editor); - - // Finally... - routine(editor); -} - document.addEventListener("turbolinks:load", () => { const flash = document.querySelector(".js-flash");