Jul 28 - Update text-editor to allow image resize
This commit is contained in:
@@ -119,11 +119,52 @@ shows only `is_published` topics (sections with no published topics are hidden).
|
||||
shows the editor). If Quill fails to load, the textarea stays usable and a save
|
||||
never wipes the body. The submit handler keeps the body when it contains an
|
||||
`img`/`table` even though `getText()` is empty for embed-only content.
|
||||
- **Paste / drop upload:** `static/js/image-upload.js` (ours). Quill 2's built-in
|
||||
`uploader` module base64s a pasted/dropped file into the body — which
|
||||
`sanitize_html()` then strips on save (bleach blocks `data:` on img src), so
|
||||
the image looked fine in the editor and vanished on save. We override
|
||||
`modules.uploader` (`{mimetypes, handler}`) so paste AND drag-drop both POST to
|
||||
`/admin/upload` and embed the returned `/static/uploads/...` path. The toolbar
|
||||
image button now goes through the same `insertFiles()`, so all three routes
|
||||
behave identically.
|
||||
- Quill's uploader only sees pasted *files*. HTML pasted from Word/Docs carries
|
||||
base64 `<img>` markup through the clipboard instead, so `watch(quill)` sweeps
|
||||
`img[src^="data:image/"]` after a user edit and rehosts each one (delete +
|
||||
re-insert the embed, preserving any `width`). Re-entrancy is guarded by a
|
||||
`busy` flag — our own edits fire `text-change` too. A failed rehost tags the
|
||||
node `data-upload-failed` so it isn't retried forever, and says plainly that
|
||||
the image won't be saved (we don't silently delete admin content).
|
||||
- Feedback is a non-blocking `.jqc-toast` (an `alert()` mid-paste interrupts
|
||||
typing). Client-side checks mirror the server: MIME allowlist + 8 MB cap.
|
||||
- Remote `http(s)` images pasted from a web page are NOT rehosted — bleach
|
||||
allows those URLs, so they render, but they hotlink the original server.
|
||||
- **Images:** the custom `#editor-toolbar` has a `ql-image` button. Images upload
|
||||
via `POST /admin/upload` (`login_required`, CSRF via `X-CSRFToken` header):
|
||||
extension allowlist + magic-byte sniff (`_sniff_image`, SVG excluded), 8 MB cap,
|
||||
saved as a random `uuid4().hex.<ext>` under `static/uploads/`, returns `{url}`;
|
||||
the handler `insertEmbed`s it (no base64 → DB stays small).
|
||||
- **Image resize:** `static/js/image-resize.js` — ours, not vendored (Quill 2 has
|
||||
no resize UI and the third-party modules target Quill 1). Click an image in the
|
||||
editor → fixed-positioned frame with 4 corner handles, S/M/L/Full presets
|
||||
(25/50/75/100 % of the containing block, so it also works inside a table cell)
|
||||
and a Reset. Loaded after Quill in `topic_form.html` and initialised behind a
|
||||
`window.JQCImageResize` guard, so a failed load just means no resize UI.
|
||||
- **Size is the `width` ATTRIBUTE, never inline `style`** — `style` is not on
|
||||
the sanitizer's img allowlist, `width` is, so the size survives the save.
|
||||
`height` is removed on every change; the public CSS (`.prose img{max-width:
|
||||
100%;height:auto}`) keeps the aspect ratio and still shrinks on a phone.
|
||||
- **Commit via `quill.formatText(i, 1, {width: v}, 'user')` — pass a formats
|
||||
OBJECT, not `(name, value)`.** Quill's argument overload reads a `null`
|
||||
`value` as the `source` argument, so the `(name, value)` form silently
|
||||
no-ops when clearing the width (this is exactly what broke Reset). The width
|
||||
round-trips through `clipboard.convert` on load because Quill's Image blot
|
||||
lists `width` in its `formats()`.
|
||||
- A drag writes the attribute directly for live preview and commits once on
|
||||
release → one undo step per drag, not dozens. The preset bar calls
|
||||
`preventDefault()` on mousedown so it never steals the caret (otherwise
|
||||
Ctrl+Z after a resize stops reaching Quill), and it flips above the image /
|
||||
clamps to the viewport — the frame is `position:fixed`, so a bar left below
|
||||
the fold could not be scrolled to.
|
||||
- **Tables:** `quill-table-better` 1.2.3 vendored (`static/vendor/quill-table-better.js`
|
||||
+ `.css`, UMD → reads global `Quill`, exposes `QuillTableBetter`; self-contained,
|
||||
no CDN/CSP issues). Registered as `modules/table-better`; Quill 2's basic
|
||||
|
||||
Reference in New Issue
Block a user