Skip to content

Extender el editor

This content is not available in your language yet.

TierQuéCuándo se registraCómo
1 — UIBubble menu, dropdowns, botonesRuntimegetEditorInstance()
2 — SchemaImágenes, tablas, embeds, mentions con búsquedaAl crear el editorfeatures / customExtensions
3 — PresetEmpaquetar un conjunto de featuresAl crear el editorNuevo preset en presets.ts

Puedes manipular el editor en runtime obteniendo la instancia de Tiptap:

const el = document.querySelector('co-rich-text-editor');
const editor = await el.getEditorInstance();
// Ejecutar comandos
editor.chain().focus().toggleBold().run();
editor.chain().focus().toggleHeading({ level: 2 }).run();
editor.chain().focus().setColor('#02A270').run();
<template>
<div v-if="showBubble" :style="bubbleStyle" class="my-bubble">
<button @click="toggleBold">B</button>
<button @click="toggleItalic">I</button>
</div>
<CoRichTextEditor ref="editorRef" preset="task" @co-ready="onReady" />
</template>
<script setup>
import { ref } from 'vue';
import { CoRichTextEditor } from '@prolibu-suite/cobalt-vue';
const editorRef = ref();
const editor = ref(null);
const showBubble = ref(false);
const bubbleStyle = ref({});
async function onReady() {
editor.value = await editorRef.value.getEditorInstance();
editor.value.on('selectionUpdate', updateBubble);
}
function updateBubble() {
const { from, to } = editor.value.state.selection;
if (from === to) { showBubble.value = false; return; }
const coords = editor.value.view.coordsAtPos(from);
bubbleStyle.value = { position: 'fixed', top: `${coords.top - 40}px`, left: `${coords.left}px` };
showBubble.value = true;
}
function toggleBold() { editor.value.chain().focus().toggleBold().run(); }
function toggleItalic() { editor.value.chain().focus().toggleItalic().run(); }
</script>
<!-- Activar variables y menciones en preset task -->
<co-rich-text-editor
preset="task"
features='{"variables": true, "mentions": true}'
></co-rich-text-editor>

Ruta B: customExtensions (extensiones propias)

Sección titulada «Ruta B: customExtensions (extensiones propias)»
import { Table } from '@tiptap/extension-table';
import { TableRow } from '@tiptap/extension-table-row';
import { TableHeader } from '@tiptap/extension-table-header';
import { TableCell } from '@tiptap/extension-table-cell';
const editor = document.querySelector('co-rich-text-editor');
editor.customExtensions = [
Table.configure({ resizable: true }),
TableRow,
TableHeader,
TableCell,
];

VariableNode — nodo atómico <span data-variable="contact.firstName">:

// Insertar variable programáticamente
const editor = await el.getEditorInstance();
editor.chain().focus().insertVariable('contact.firstName', 'Nombre').run();

MentionNode — nodo atómico <span data-mention-id data-mention-label>:

editor.chain().focus().insertMention('user-123', 'Juan Pérez').run();

Activadas por preset="document" o features='{"image": true}'. Tres modos de inserción:

  1. Botón de toolbar — abre un formulario inline (popover) para insertar por URL
  2. Paste — pegar imagen del portapapeles
  3. Drop — drag & drop de archivo

Para subir a CDN en lugar de usar base64:

const editor = document.querySelector('co-rich-text-editor');
editor.imageUpload = async (file) => {
const formData = new FormData();
formData.append('file', file);
const res = await fetch('/api/upload', { method: 'POST', body: formData });
const { url } = await res.json();
return url;
};
  1. Agregar el nombre al tipo RichTextPreset en types.ts
  2. Configurar STARTERKIT_CONFIG, PRESET_TOOLBAR, PRESET_MAXLENGTH y extras en presets.ts
  3. Agregar whitelist de sanitización en sanitizer.tsSANITIZE_CONFIGS
  4. Replicar whitelist en co-rich-text-viewer.tsxALLOWED_TAGS
  5. Agregar tests en presets.test.ts y sanitizer.test.ts
  1. Registrar la extensión en getExtensions (preset o customExtensions)
  2. Permitir sus tags/attrs en sanitizer.ts Y en el viewer
  3. Estilizar en co-rich-text-editor.css (.co-rte-content .ProseMirror …) y co-rich-text-viewer.css
  4. (Opcional) Agregar botón en toolbar-config.ts + handler en co-rich-text-toolbar.tsx
  5. Ejecutar cadena de rebuild + tests