Edytor rich text

View on GitHub

Edytor rich text

Opisy issues (i, w trybie tylko-do-odczytu/wyłączonym, treść overview katalogu integracji) są edytowane/renderowane przez Tiptap, skonfigurowany raz w EditableMarkdown.tsx i zapisywany jako zwykły tekst markdown na backendzie — nie ma żadnej osobnej kolumny na bogatą treść ani formatu dokumentu JSON, tylko kolumna TEXT trzymająca cokolwiek markdown zserializuje rozszerzenie tiptap-markdown Tiptapa.

Przewodniki, w kolejności, w jakiej faktycznie będziesz ich potrzebować

  1. Dodaj nowe rozszerzenie TiptapEdytor rich textDodaj nowe rozszerzenie TiptapPrzećwiczony przykład: dodanie podświetlania tekstu (@tiptap/extension-highlight) do edytora opisu issue — rozszerzenie dziś niezainstalowane, na wzór dokł… — przećwiczony przykład dodania podświetlania tekstu (@tiptap/extension-highlight, dziś niezainstalowanego) do listy rozszerzeń edytora.
  2. Dodaj upload obrazów przez wklejenie i przeciągnięcieEdytor rich textDodaj upload obrazów przez wklejenie i przeciągnięciePrzejście przez cały pipeline, dzięki któremu opis issue przyjmuje obraz wklejony przez Ctrl+V albo przeciągnięty na stronę — każda jego warstwa, w kolejno… — cały pipeline stojący za wklejeniem albo przeciągnięciem obrazu do opisu issue: tabela attachments, repozytorium, serwis i JSON-owy endpoint uploadu, sprawdzanie NSFW współdzielone z uploadem awatarów oraz obsługa wklejania/upuszczania w edytorze.
  3. Dodaj upload obrazów do kolejnej powierzchniEdytor rich textDodaj upload obrazów do kolejnej powierzchniJak pipeline uploadu z 02-add-image-paste-and-drop-uploads.md dociera do tych pól markdown w aplikacji, które nie są Tiptapem: Część A to komentarze do iss… — jak ten pipeline dociera do powierzchni będących zwykłymi textareami, a nie Tiptapem: komentarze do issue (pisanie, edycja, renderowanie i pułapka zakresów wzmianek) oraz treść szablonu typu issue — dwa kształty, jakie przyjmie każda kolejna powierzchnia.
  4. Dodaj wzmianki do powierzchni TiptapEdytor rich textDodaj wzmianki do powierzchni TiptapPrzećwiczony przykład: wzmianki @member i #issue w opisie issue, czyli w edytorze Tiptap za EditableMarkdown. Komentarze do issue miały już oba rodzaje (zo… — jak działają wzmianki @member i #issue w edytorze opisu opartym na Tiptapie: węzły wzmianek zapisywane do tych samych tokenów markdown co w komentarzach, most od wtyczki suggestion Tiptapa do współdzielonego menu MentionSuggestions oraz listener powiadamiający członków wymienionych w opisie.

Architektura w jednym akapicie

EditableMarkdown (resources/js/Components/Molecules/EditableMarkdown/EditableMarkdown.tsx) owija pojedyncze wywołanie useEditor() z @tiptap/react, zawsze zamontowane, ale przełączające editable: false/true przy kliknięciu zamiast warunkowo renderować osobny komponent odczytu/edycji — kliknięcie wyrenderowanej treści wywołuje startEditing() (ustawia editable: true, fokusuje na koniec), a utrata fokusu (onBlur) albo naciśnięcie Escape kończy edycję, wywołując onSave(markdown) tylko wtedy, gdy treść faktycznie się zmieniła (porównywane przez editor.storage.markdown.getMarkdown() z tiptap-markdown względem ostatnio zapisanego propa value). Lista rozszerzeń — StarterKit (bold/italic/listy/nagłówki/kod/itd., z link skonfigurowanym, żeby nie otwierał się przy kliknięciu podczas edycji), Markdown (sam serializer, html: false, więc wklejony/wpisany HTML nigdy nie przecieka do zapisanego markdownu), Placeholder, TaskList/TaskItem, TableKit i Image — to jedyne miejsce, które decyduje, jakie formatowanie jest możliwe; nic innego w aplikacji nie ma własnej, osobnej konfiguracji Tiptapa. Osobna ścieżka renderowania, react-markdown/remark-gfm (zobacz ../architecture/01-tech-stack-and-project-structure.mdArchitektura i technikalia projektuStack technologiczny i struktura projektuGłówny README.md ma sztandarową tabelę stacku (PHP/Laravel, Inertia, React/TypeScript/Vite, Tailwind, SQLite, Pest/Vitest). Ten przewodnik schodzi o poziom…), obsługuje markdown, który nigdy nie jest edytowalny (statyczne pole overview katalogu integracji) — nie sięgaj po Tiptapa do wyświetlania markdownu tylko do odczytu; to cięższe narzędzie do zadania, które react-markdown już wykonuje.

Wzmianki to drugi wyjątek, choć zostają w kolumnie TEXT: gdy przekazane są users/projectId, do listy dochodzą dwa dodatkowe węzły (@member, #issue), serializowane do tych samych tokenów @[Name](id) / #[Title](id:number), które zapisują komentarze — przewodnik 4.

Obrazy to jedyna rzecz, która nie mieszka w tej kolumnie TEXT. Wklejenie albo upuszczenie obrazu wysyła go do POST /projects/{project}/attachments (AttachmentController → AttachmentService → AttachmentRepository, prześwietlany przez NsfwDetectionService dokładnie tak jak awatar), a do markdownu trafia tylko zwrócony URL jako zwykłe ![alt](url). Załączniki należą do projektu, a nie do issue, komentarza czy szablonu, który je referuje — i to właśnie pozwala jednemu endpointowi obsłużyć każdą powierzchnię edycji w aplikacji. Opisy issues dostają obrazy za darmo dzięki węzłowi Image Tiptapa; komentarze — będące zwykłymi textareami, a nie Tiptapem — wykonują tę samą pracę ręcznie przez insertMarkdownImage i splitMarkdownImages z resources/js/utils/imagePaste.ts, co przechodzi krok po kroku przewodnik 3.