Jul 28 - Update text-editor to allow image resize

This commit is contained in:
2026-07-28 14:55:12 -04:00
parent ea9458395d
commit 4bb345da39
7 changed files with 622 additions and 26 deletions
+41 -25
View File
@@ -142,6 +142,8 @@
{% block scripts %}
<script src="{{ url_for('static', filename='vendor/quill.min.js') }}"></script>
<script src="{{ url_for('static', filename='vendor/quill-table-better.js') }}"></script>
<script src="{{ asset_url('js/image-upload.js') }}"></script>
<script src="{{ asset_url('js/image-resize.js') }}"></script>
<script>
(function () {
if (typeof Quill === 'undefined') return; // textarea stays usable
@@ -156,7 +158,19 @@
Quill.register({ 'modules/table-better': QuillTableBetter }, true);
}
var csrf = document.querySelector('meta[name="csrf-token"]').content;
// Paste/drop image uploading. Quill's default uploader base64s the file
// into the body, which the sanitizer strips on save — this replaces it with
// a real upload to /admin/upload.
var uploads = window.JQCImageUpload
? window.JQCImageUpload.create({ url: '{{ url_for("admin.upload") }}', csrf: csrf })
: null;
var modules = { toolbar: toolbarEl };
if (uploads) {
modules.uploader = { mimetypes: uploads.mimetypes, handler: uploads.handler };
}
if (hasTables) {
modules.table = false; // disable Quill's basic table
modules['table-better'] = {
@@ -182,36 +196,38 @@
}
}
var csrf = document.querySelector('meta[name="csrf-token"]').content;
// --- Image button: upload the file, then embed the returned URL. This
// keeps the DB small (no base64) and the image is served as a static file.
quill.getModule('toolbar').addHandler('image', function () {
var input = document.createElement('input');
input.type = 'file';
input.accept = 'image/png,image/jpeg,image/gif,image/webp';
input.onchange = function () {
var file = input.files && input.files[0];
if (!file) return;
var fd = new FormData();
fd.append('file', file);
fetch('{{ url_for("admin.upload") }}', {
method: 'POST', headers: { 'X-CSRFToken': csrf }, body: fd
}).then(function (r) {
return r.json().then(function (j) { return { ok: r.ok, body: j }; });
}).then(function (res) {
if (!res.ok) { alert(res.body.error || 'Upload failed.'); return; }
// --- Image button: pick a file and upload it through the same path as a
// paste/drop, so the DB stays small (no base64) and the image is served as
// a static file.
if (uploads) {
quill.getModule('toolbar').addHandler('image', function () {
var input = document.createElement('input');
input.type = 'file';
input.accept = uploads.mimetypes.join(',');
input.onchange = function () {
var file = input.files && input.files[0];
if (!file) return;
var range = quill.getSelection(true);
quill.insertEmbed(range.index, 'image', res.body.url, 'user');
quill.setSelection(range.index + 1, 'silent');
}).catch(function () { alert('Upload failed.'); });
};
input.click();
});
uploads.insertFiles(quill, range ? range.index : quill.getLength(), [file]);
};
input.click();
});
// Pasted HTML can carry base64 images (Word, Google Docs); rehost those
// as they arrive, since the uploader module never sees them.
uploads.watch(quill);
}
// Table resize + cell alignment are handled by quill-table-better's own
// drag handles and floating cell menu — no extra toolbar wiring needed.
// --- Click an image to resize it (corner handles + S/M/L/Full presets).
// Guarded: if the script didn't load, the editor still works, images just
// stay at their natural size.
if (window.JQCImageResize) {
window.JQCImageResize.init(quill);
}
// Switch the UI from textarea to Quill only once it's ready.
document.body.classList.add('quill-on');