Skip to content

Commit ca989e7

Browse files
committed
fix(pat-tinymce): Add a fallback for Plone 5 images without data-picturevariant attributes.
Responsive picture variants were introduced in Plone 6. Content from Plone 5 where no `data-picturevariant` was available lost had no scale selected in the image dialog. This PR fixes that by falling back to the `data-scale` attribute. This allows old images in the TinyMCE‌ image edit dialog to have their scale preselected. The precondition for this is that the old scales are configured as picture variants.
1 parent db84db6 commit ca989e7

3 files changed

Lines changed: 61 additions & 11 deletions

File tree

src/pat/tinymce/js/links.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -899,10 +899,10 @@ export default Base.extend({
899899
self.linkTypes[self.linkType].load(self.imgElm);
900900

901901
// set scale selection in link modal:
902-
var pictureVariant = self.dom.getAttrib(
903-
self.imgElm,
904-
"data-picturevariant",
905-
);
902+
var pictureVariant =
903+
self.dom.getAttrib(self.imgElm, "data-picturevariant") ||
904+
// fallback for backwards compatibility
905+
self.dom.getAttrib(self.imgElm, "data-scale");
906906
self.$scale.val(pictureVariant);
907907

908908
// var selectedImageUid = self.dom.getAttrib(

src/pat/tinymce/tinymce--implementation.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@ const log = logger.getLogger("tinymce--implementation");
1010
let LinkModal = null;
1111

1212
export default class TinyMCE {
13+
14+
linkModal;
15+
imageModal;
16+
1317
constructor(el, options) {
1418
this.el = el;
1519
this.$el = $(el);
1620
this.options = options;
1721
}
1822
addLinkClicked() {
1923
var self = this;
20-
if (self.linkModal === null) {
24+
if (! self.linkModal) {
2125
var $el = $("<div/>").insertAfter(self.$el);
2226
var linkTypes = ["internal", "upload", "external", "email", "anchor"];
2327
if (!self.options.upload) {
@@ -38,7 +42,7 @@ export default class TinyMCE {
3842
}
3943
addImageClicked() {
4044
var self = this;
41-
if (self.imageModal === null) {
45+
if (! self.imageModal) {
4246
var linkTypes = ["image", "uploadImage", "externalImage"];
4347
if (!self.options.upload) {
4448
linkTypes.splice(1, 1);
@@ -221,7 +225,6 @@ export default class TinyMCE {
221225
LinkModal = (await import("./js/links")).default;
222226

223227
var self = this;
224-
self.linkModal = self.imageModal = self.uploadModal = self.pasteModal = null;
225228
// tiny needs an id in order to initialize. Creat it if not set.
226229
var id = utils.setId(self.$el);
227230

src/pat/tinymce/tinymce.test.js

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@ import $ from "jquery";
44
import sinon from "sinon";
55
import registry from "@patternslib/patternslib/src/core/registry";
66
import utils from "@patternslib/patternslib/src/core/utils";
7+
import events from "@patternslib/patternslib/src/core/events";
78

89
$.fx.off = true;
910

1011
var createTinymce = async function (options) {
11-
return await registry.patterns.tinymce.init(
12-
$('<textarea class="pat-tinymce"></textarea>').appendTo("body"),
13-
options || {},
14-
);
12+
document.body.innerHTML = `
13+
<textarea class="pat-tinymce"></textarea>
14+
`;
15+
const textarea = document.querySelector("textarea");
16+
const instance = new TinyMCE(textarea, options || {});
17+
await events.await_pattern_init(instance);
18+
19+
return instance;
1520
};
1621

1722
const registry_scan = async () => {
@@ -249,6 +254,48 @@ describe("TinyMCE", function () {
249254
);
250255
});
251256

257+
it.skip("When parsing images from old Plone installations without picture-variants, TinyMCE‌'s image dialog falls back to data-scale", async function () {
258+
// TinyMCE contents without a picture variant but a data-scale, as it
259+
// was used in Plone 5.
260+
const pat_instance = await createTinymce(
261+
{
262+
prependToScalePart: "/@@images/image/",
263+
imageScales: '[{"title": "Preview", "value": "preview"}]',
264+
pictureVariants: {
265+
"preview": {
266+
"title": "Preview",
267+
"sourceset": [
268+
{
269+
"scale": "preview",
270+
"media": ""
271+
}
272+
]
273+
},
274+
},
275+
}
276+
);
277+
278+
// Await the TinyMCE initialization.
279+
await utils.timeout(0);
280+
const tiny = pat_instance.instance.tiny;
281+
282+
tiny.setContent(`
283+
<img
284+
src="resolveuid/foobar/@@images/image/preview"
285+
data-scale="preview"
286+
alt="This is an alt"
287+
title="This is a title"
288+
data-caption="This is a caption"
289+
/>
290+
`);
291+
292+
// Select the image before opening the image dialog.
293+
const img = tiny.dom.getRoot().getElementsByTagName("img")[0];
294+
tiny.selection.select(img);
295+
296+
pat_instance.instance.addImageClicked();
297+
});
298+
252299
it("test inline tinyMCE", async function () {
253300
document.body.innerHTML = `
254301
<textarea class="pat-tinymce" data-pat-tinymce='{"inline": true}'></textarea>

0 commit comments

Comments
 (0)