2

For a little context, we have recently made the decision to disable page builder and move towards a component-driven content entry approach utilising widgets. We have a "Generic Text" widget, which consists of a custom WYSIWYG parameter.

Whilst testing this widget, we came across a rather odd (and probably quite specific) problem, which is that if a quotation mark is present in the text, and then the word type is present anywhere in the preceding text, the widget fails to insert or save and completely disappears from the editor.

Steps to reproduce

Ensure Page Builder is disabled, and you're using the standard TinyMCE editor.

  1. Create, or edit an existing, page
  2. Click insert widget button/icon
  3. Choose CMS Page Link Enter " type into 'Anchor Custom Text'
  4. Insert the widget

You should find that the widget modal retracts, and you're left with:

  • If you created a new page, a blank editor
  • If you edited a page, the inserted widget won't be present

The same happens when trying to save a widget which existing content:

  1. Insert a new widget (without " type and save it), or edit an existing widget
  2. Edit the content of a text field so that " type is now included
  3. Save the widget

Raised on Magento 2 GitHub

The issue has been raised on the Magento 2 GitHub (#38711), and has been verified and replicated on a fresh 2.4-develop Luma theme environment.

If anyone is able to contribute towards this, or suggest a temporary fix until Magento applies a patch, that would be greatly appreciated.

2 Answers 2

3
+100

I tracked it down with firefox debugger (& chrome when I wanted to quickly test my custom JS) to here :
lib/web/mage/adminhtml/wysiwyg/tiny_mce/plugins/magentowidget/editor_plugin.js
where both encodeWidgets() & decodeWidgets() functions call :
lib/web/mage/adminhtml/wysiwyg/tiny_mce/tinymce5Adapter.js::parseAttributesString() which seems to fail replacing the quote (HTML Entity) to an escaped quote :

    attributes = attributes.replace(/"/g, '"');

So, I tried

    attributes = attributes.replace(/"/g, '\\"');
//and tried this :
    attributes = attributes.replace(/"/g, '\\\"');

But it doesn't seem to fix (Maybe I have cache prob) I will EDIT this answer when I get more.

Using Magento CE version 2.4.7

EDIT what worked for me :
So I tried to do it before and after the regex replacement, and I used what is being used in Page Builder for the same action :
module-page-builder/view/adminhtml/web/js/utils/editor.js::parseAttributesString() :

        /**
         * @param {Object} attributes
         * @return {Object}
         */
        parseAttributesString: function (attributes) {
            var result = {};

            // Decode " entity, as regex below does not support encoded quote
            attributes = attributes.replace(/"/g, '\\\"');

            attributes.replace(/(\w+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g, function (match, key, value) {
                result[key] = value ? value.replace(/"/g, "\\\"") : value;
                return "";
            });

            return result;
        },

And maybe we have to go from a fresh CMS page edit to see it working.

3
  • 1
    Hi Medmek, thanks for the answer. You're definitely in the right place here! Just quickly tested myself by simply commenting out that line. Doing that fixes the problem with saving the widget when " type is present. The secondary problem though is that, if you click the "Show / Hide Editor" button, the quotes are not encoded. So, pressing the "Show / Hide Editor" button a second time will remove the widget. I'm also not aware of the adverse effects undoing the encoding on the quotation mark might have on the attributes.gsub( immediately after. Commented May 20 at 14:21
  • 1
    If this helps, in my case I ran php bin/magento s:d:c after making the change. As well as some additional commands in the form of an alias to clear caches/static content: alias quickflush="rm -rf pub/static var/view_preprocessed/ var/cache/ var/page_cache/ generated/" Commented May 20 at 14:27
  • 1
    Another observation - uncommenting the line you've referred to in your answer also fixes the saving issue for plain text fields within core Magento widgets (e.g. CMS Page Link). I'm not sure why the tinymce5Adapter.js would also be involved with saving a plain text field, but it seems it is.. Commented May 20 at 14:31
0

Inside this core file,

vendor/magento/module-cms/Model/Wysiwyg/Gallery/DefaultConfigProvider.php

You can add the setup function to escape special characters in the getConfig() method. Here's how you can modify the method:

Replace the public function getConfig( with the code below and check.

If this works then create a temporary patch until the issue gets resolved.

Code:

public function getConfig(\Magento\Framework\DataObject $config) : \Magento\Framework\DataObject
{
    $pluginData = (array) $config->getData('plugins');
    $imageData = [
        [
            'name' => 'image',
        ]
    ];

    $fileBrowserUrlParams = [];

    if (is_string($this->currentTreePath)) {
        $fileBrowserUrlParams = [
            'current_tree_path' => $this->imagesHelper->idEncode($this->currentTreePath),
        ];
    }

    $configData = [
        'add_images' => true,
        'files_browser_window_url' => $this->backendUrl->getUrl(
            $this->openDialogUrl->get(),
            $fileBrowserUrlParams
        ),
        'files_browser_window_width' => $this->windowSize['width'],
        'files_browser_window_height' => $this->windowSize['height'],
        'plugins' => array_merge($pluginData, $imageData),
        'tinymce4' => [
            'toolbar' => 'formatselect | bold italic underline | alignleft aligncenter alignright | bullist numlist | link table charmap',
            'plugins' => 'advlist autolink lists link charmap media noneditable table contextmenu paste code help table',
            'setup' => "function (editor) {
                editor.on('BeforeSetContent', function (e) {
                    e.content = e.content.replace(/\"/g, '\\\"').replace(/'/g, '\\\'');
                });
            }"
        ]
    ];

    return $config->addData($configData);
}
2
  • Hi Jigar, thanks for taking the time to put an answer together. Unfortunately, the file in which your suggested fix is placed doesn't appear to run when a widget is saved, only when a TinyMCE instance is loaded. It's upon saving a widget with the custom WYSIWYG parameter where quotations aren't escaped and ultimately conflict with the word "type" in any preceding text. Would you have any idea about targeting the widget save action and forcing quotations to be escaped there before the {{widget type="xxx" content="xxx"}} code is generated? Commented May 20 at 9:57
  • Sorry. Just to clarify my previous comment, the issue is present when any text field in a widget is saved with a quotation mark followed by the word "type" anywhere in the text. Not just when you have a custom WYSIWYG parameter, so it's not necessarily related to the TinyMCE editor. It's related to the widget not escaping quotation marks when saved. Commented May 20 at 10:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.