From 735dc7893e6a9196f76f77645be867083960ccbd Mon Sep 17 00:00:00 2001
From: webchick <drupal@webchick.net>
Date: Tue, 3 Nov 2015 13:02:21 -0800
Subject: [PATCH] Issue #2585173 by Wim Leers, Jelle_S, DuaelFr, nod_, Reinmar,
 attiks: [regression] "Allowed HTML tags" setting corrupted upon accessing
 Text Format configuration UI

---
 .../ckeditor/js/plugins/drupalimage/plugin.js | 68 +++++++++++--------
 .../js/plugins/drupalimagecaption/plugin.js   | 11 +--
 .../ckeditor/js/plugins/drupallink/plugin.js  | 29 ++++----
 3 files changed, 61 insertions(+), 47 deletions(-)

diff --git a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
index c481264473cf..51550188df28 100644
--- a/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
+++ b/core/modules/ckeditor/js/plugins/drupalimage/plugin.js
@@ -29,41 +29,51 @@
           return;
         }
 
-        // Override requiredContent & allowedContent.
+        // First, convert requiredContent & allowedContent from the string
+        // format that image2 uses for both to formats that are better suited
+        // for extending, so that both this basic drupalimage plugin and Drupal
+        // modules can easily extend it.
+        // @see http://docs.ckeditor.com/#!/api/CKEDITOR.filter.allowedContentRules
+        // Mapped from image2's allowedContent. Unlike image2, we don't allow
+        // <figure>, <figcaption>, <div> or <p>  in our downcast, so we omit
+        // those. For the <img> tag, we list all attributes it lists, but omit
+        // the classes, because the listed classes are for alignment, and for
+        // alignment we use the data-align attribute.
+        widgetDefinition.allowedContent = {
+          img: {
+            attributes: {
+              '!src': true,
+              '!alt': true,
+              'width': true,
+              'height': true
+            },
+            classes: {},
+            styles: {}
+          }
+        };
+        // Mapped from image2's requiredContent: "img[src,alt]". This does not
+        // use the object format unlike above, but a CKEDITOR.style instance,
+        // because requiredContent does not support the object format.
+        // @see https://www.drupal.org/node/2585173#comment-10456981
         widgetDefinition.requiredContent = new CKEDITOR.style({
           element: 'img',
           styles: {},
           attributes: {
-            'alt': '',
-            'src': '',
-            'width': '',
-            'height': '',
-            'data-entity-type': '',
-            'data-entity-uuid': ''
+            src: '',
+            alt: ''
           }
         });
-        var allowedContentDefinition = {
-          element: 'img',
-          styles: {},
-          attributes: {
-            '!data-entity-type': '',
-            '!data-entity-uuid': ''
-          }
-        };
-        var imgAttributes = widgetDefinition.allowedContent.img.attributes.split(/\s*,\s*/);
-        for (var i = 0; i < imgAttributes.length; i++) {
-          allowedContentDefinition.attributes[imgAttributes[i]] = '';
-        }
-        if (widgetDefinition.allowedContent.img.classes) {
-          allowedContentDefinition.attributes['class'] = widgetDefinition.allowedContent.img.classes.split(/\s*,\s*/).join(' ');
-        }
-        if (widgetDefinition.allowedContent.img.styles) {
-          var imgStyles = widgetDefinition.allowedContent.img.styles.split(/\s*,\s*/);
-          for (var j = 0; j < imgStyles.length; j++) {
-            allowedContentDefinition.styles[imgStyles[j]] = '';
-          }
-        }
-        widgetDefinition.allowedContent = new CKEDITOR.style(allowedContentDefinition);
+
+        // Extend requiredContent & allowedContent.
+        // CKEDITOR.style is an immutable object: we cannot modify its
+        // definition to extend requiredContent. Hence we get the definition,
+        // modify it, and pass it to a new CKEDITOR.style instance.
+        var requiredContent = widgetDefinition.requiredContent.getDefinition();
+        requiredContent.attributes['data-entity-type'] = '';
+        requiredContent.attributes['data-entity-uuid'] = '';
+        widgetDefinition.requiredContent = new CKEDITOR.style(requiredContent);
+        widgetDefinition.allowedContent.img.attributes['!data-entity-type'] = true;
+        widgetDefinition.allowedContent.img.attributes['!data-entity-uuid'] = true;
 
         // Override downcast(): since we only accept <img> in our upcast method,
         // the element is already correct. We only need to update the element's
diff --git a/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js b/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js
index 9fba103c308b..44e89dffd890 100644
--- a/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js
+++ b/core/modules/ckeditor/js/plugins/drupalimagecaption/plugin.js
@@ -50,15 +50,16 @@
           }
         }, true);
 
-        // Override requiredContent & allowedContent.
+        // Extend requiredContent & allowedContent.
+        // CKEDITOR.style is an immutable object: we cannot modify its
+        // definition to extend requiredContent. Hence we get the definition,
+        // modify it, and pass it to a new CKEDITOR.style instance.
         var requiredContent = widgetDefinition.requiredContent.getDefinition();
         requiredContent.attributes['data-align'] = '';
         requiredContent.attributes['data-caption'] = '';
         widgetDefinition.requiredContent = new CKEDITOR.style(requiredContent);
-        var allowedContent = widgetDefinition.allowedContent.getDefinition();
-        allowedContent.attributes['!data-align'] = '';
-        allowedContent.attributes['!data-caption'] = '';
-        widgetDefinition.allowedContent = new CKEDITOR.style(allowedContent);
+        widgetDefinition.allowedContent.img.attributes['!data-align'] = true;
+        widgetDefinition.allowedContent.img.attributes['!data-caption'] = true;
 
         // Override allowedContent setting for the 'caption' nested editable.
         // This must match what caption_filter enforces.
diff --git a/core/modules/ckeditor/js/plugins/drupallink/plugin.js b/core/modules/ckeditor/js/plugins/drupallink/plugin.js
index 2cc9bc10069f..2707a947f34c 100644
--- a/core/modules/ckeditor/js/plugins/drupallink/plugin.js
+++ b/core/modules/ckeditor/js/plugins/drupallink/plugin.js
@@ -13,14 +13,16 @@
     init: function (editor) {
       // Add the commands for link and unlink.
       editor.addCommand('drupallink', {
-        allowedContent: new CKEDITOR.style({
-          element: 'a',
-          styles: {},
-          attributes: {
-            '!href': '',
-            'target': ''
+        allowedContent: {
+          a: {
+            attributes: {
+              '!href': true,
+              'target': true
+            },
+            classes: {},
+            styles: {}
           }
-        }),
+        },
         requiredContent: new CKEDITOR.style({
           element: 'a',
           styles: {},
@@ -147,13 +149,14 @@
       editor.addCommand('drupalunlink', {
         contextSensitive: 1,
         startDisabled: 1,
-        allowedContent: new CKEDITOR.style({
-          element: 'a',
-          attributes: {
-            '!href': '',
-            'target': ''
+        allowedContent: {
+          a: {
+            attributes: {
+              '!href': true,
+              'target': true
+            }
           }
-        }),
+        },
         requiredContent: new CKEDITOR.style({
           element: 'a',
           attributes: {
-- 
GitLab