feat(17-02): richeditor field on TipTap with the untouched rule
- RichEditorField: Reka toolbar, link popover with the http/https/mailto/tel and relative URL policy, Edit HTML view, lossy note, skeleton while the lazily imported TipTap chunk loads, HTML view fallback when it fails - untouched values are submitted byte-identical; after an edit the value is the editor HTML (empty paragraph -> ""); a value from outside (the save's sanitized answer) reloads the editor - read-only renders through a client display allowlist, never as stored - TipTap 3.31.4 (core, pm, starter-kit) pinned exact after the package check - richeditor.* phrase keys (en, pl), smoke specs, forms docs
This commit is contained in:
@@ -446,6 +446,14 @@ The value travels as a string of HTML, or null. Anything else in a save body is
|
||||
|
||||
The editor's own toolbar keeps to the same allowlist, but the server is the gate: a value posted by any client goes through the policy. The type is supported in controller forms only; settings forms and relation forms refuse it at start-up, so no save path stores an unsanitized value.
|
||||
|
||||
In the admin SPA the field is a TipTap editor with a toolbar for bold, italic, underline, a level 3 heading, bullet and numbered lists, quotes, links, undo and redo. The editor code loads on first use, so forms without a rich text field never download it.
|
||||
|
||||
- **Untouched values stay as stored.** Until the administrator edits the text, the form sends the loaded string unchanged. Opening and saving a form never rewrites imported HTML, even markup the editor would format differently. After the first edit the value is the editor's HTML, and an editor holding only an empty paragraph sends an empty string.
|
||||
- **Edit HTML.** The toolbar's HTML view edits the source in a plain text area and sends the text as typed. Use it for markup the editor cannot show: when the stored HTML contains elements other than `p`, `br`, `strong`, `b`, `em`, `i`, `u`, `s`, `h3`, `ul`, `ol`, `li`, `blockquote`, `a`, `div` and `span`, a note above the text says so, and the HTML view changes it without losing it.
|
||||
- **Links** accept `http`, `https`, `mailto`, `tel` and relative URLs. Ctrl+K (Cmd+K) opens the link box.
|
||||
- **After a save** the notices appear under the field and the editor shows the sanitized value the server stored.
|
||||
- If the editor code cannot be loaded, the field falls back to the HTML view, so the record can still be edited and saved.
|
||||
|
||||
## What a save may write
|
||||
|
||||
The form's writable fields are bound to model columns at boot. A save passes only those fields that are also in the model's `Fillable` list, drops unknown keys, case variants and nested objects, and fills the model with `lagoon.Fill` (see [Models](../database/models.md)). Declared `mltext`, `mltextarea` and `mlmarkdown` locale maps are the exception: they are lifted first, as [Markdown and multilingual fields](#markdown-and-multilingual-fields). A [repeater](#repeater)'s list of rows is the other exception: it is decoded row by row before the projection. The model's validation rules (a `Rules` method returning `lagoon.Validate` rule strings) and the form's `required` flags are checked in the save's transaction, and a failure is a 422 with messages per field. A value that does not fit its column is also a 422 on that field. A controller implementing `pact.FormRules` supplies its own rule set per operation, which replaces the model's rules for admin saves.
|
||||
|
||||
Reference in New Issue
Block a user