Rich text reports display-only link resolution as an edit: setContent(x, false) doesn't suppress the update in Tiptap 3

Abierto Apto para principiantes
#231 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
78/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
javascript, react
Área
frontend, testing

Línea de trabajo

Empieza en packages/editor-ui/src/components/settings/inputs/RichTextInput.jsx e inspecciona las cuatro llamadas a setContent alrededor de las líneas 477, 487, 500 y 516, junto con el controlador onUpdate. Actualiza las llamadas para suprimir las actualizaciones emitidas y añade una prueba del componente para un enlace cuyo slug de destino haya cambiado. El objetivo se cumple cuando no se llama a onChange durante la resolución de visualización y el formulario permanece limpio; ejecuta la prueba pertinente del componente y las pruebas existentes de stableLink.test.jsx.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug editor

A rich-text field is meant to resolve its internal links for display without counting that as an edit. It counts it anyway: the field calls onChange, so opening a widget can mark the page as changed when nothing was edited.

What happens

RichTextInput keeps internal links pointing at current slugs for display. The comment above its sync effect says this is display-only:

setContent with emitUpdate=false means this is display-only — it does NOT fire onUpdate/onChange, so the field isn't dirtied and the stored value is untouched until a real edit.

But the call passes a bare false:

editor.commands.setContent(displayValue, false);

(packages/editor-ui/src/components/settings/inputs/RichTextInput.jsx ~477; the same call at ~487, ~500 and ~516.)

In Tiptap 3 the second argument is an options object (setContent(content, { emitUpdate, parseOptions, errorOnInvalidContent })), and emitUpdate defaults to true. Destructuring false finds no emitUpdate, so the default applies and the update is emitted. The editor's onUpdate (~449) then calls onChange(editor.getHTML()).

So whenever resolveForDisplay(value) differs from what the editor holds (for example, a link to a page whose slug has changed since the link was saved), the resolved HTML is reported as a change to the field. Expected: the page stays clean, and the stored value keeps its original href until a real edit.

The other three calls (switching back from source mode, source blur, collapsing the expanded editor) call onChange themselves right after, so for them the extra update is harmless but redundant.

Fix

Pass the options object in all four places:

editor.commands.setContent(displayValue, { emitUpdate: false });

Then add a test that mounts the field with a link whose target slug has changed and checks that onChange isn't called and the form isn't dirty. The current link tests (stableLink.test.jsx) use a headless editor, so they don't cover the component.

How it was found

Code review during the dependency upgrades, checked against Tiptap's setContent signature (the same in 3.18 and 3.32). Not yet reproduced in the editor UI.

Lenguaje dominante
JavaScript
Estrellas
162
Forks
6
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

  • Incluye un Dockerfile o un archivo de Docker Compose
  • Sin plantilla de pull request
  • Sin guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de tsiger/widgetizer

Todos los issues de tsiger/widgetizer

Issues similares

Más issues de JavaScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.