773f35a9d8405442fdeb2ccb2eb6e9486d9b4e2a
[yaffs-website] / web / core / modules / filter / filter.filter_html.admin.js
1 /**
2 * DO NOT EDIT THIS FILE.
3 * See the following change record for more information,
4 * https://www.drupal.org/node/2815083
5 * @preserve
6 **/
7
8 (function ($, Drupal, _, document) {
9   if (Drupal.filterConfiguration) {
10     Drupal.filterConfiguration.liveSettingParsers.filter_html = {
11       getRules: function getRules() {
12         var currentValue = $('#edit-filters-filter-html-settings-allowed-html').val();
13         var rules = Drupal.behaviors.filterFilterHtmlUpdating._parseSetting(currentValue);
14
15         var rule = new Drupal.FilterHTMLRule();
16         rule.restrictedTags.tags = ['*'];
17         rule.restrictedTags.forbidden.attributes = ['style', 'on*'];
18         rules.push(rule);
19
20         return rules;
21       }
22     };
23   }
24
25   Drupal.behaviors.filterFilterHtmlUpdating = {
26     $allowedHTMLFormItem: null,
27
28     $allowedHTMLDescription: null,
29
30     userTags: {},
31
32     autoTags: null,
33
34     newFeatures: {},
35
36     attach: function attach(context, settings) {
37       var that = this;
38       $(context).find('[name="filters[filter_html][settings][allowed_html]"]').once('filter-filter_html-updating').each(function () {
39         that.$allowedHTMLFormItem = $(this);
40         that.$allowedHTMLDescription = that.$allowedHTMLFormItem.closest('.js-form-item').find('.description');
41         that.userTags = that._parseSetting(this.value);
42
43         $(document).on('drupalEditorFeatureAdded', function (e, feature) {
44           that.newFeatures[feature.name] = feature.rules;
45           that._updateAllowedTags();
46         }).on('drupalEditorFeatureModified', function (e, feature) {
47           if (that.newFeatures.hasOwnProperty(feature.name)) {
48             that.newFeatures[feature.name] = feature.rules;
49             that._updateAllowedTags();
50           }
51         }).on('drupalEditorFeatureRemoved', function (e, feature) {
52           if (that.newFeatures.hasOwnProperty(feature.name)) {
53             delete that.newFeatures[feature.name];
54             that._updateAllowedTags();
55           }
56         });
57
58         that.$allowedHTMLFormItem.on('change.updateUserTags', function () {
59           that.userTags = _.difference(that._parseSetting(this.value), that.autoTags);
60         });
61       });
62     },
63     _updateAllowedTags: function _updateAllowedTags() {
64       this.autoTags = this._calculateAutoAllowedTags(this.userTags, this.newFeatures);
65
66       this.$allowedHTMLDescription.find('.editor-update-message').remove();
67
68       if (!_.isEmpty(this.autoTags)) {
69         this.$allowedHTMLDescription.append(Drupal.theme('filterFilterHTMLUpdateMessage', this.autoTags));
70         var userTagsWithoutOverrides = _.omit(this.userTags, _.keys(this.autoTags));
71         this.$allowedHTMLFormItem.val(this._generateSetting(userTagsWithoutOverrides) + ' ' + this._generateSetting(this.autoTags));
72       } else {
73           this.$allowedHTMLFormItem.val(this._generateSetting(this.userTags));
74         }
75     },
76     _calculateAutoAllowedTags: function _calculateAutoAllowedTags(userAllowedTags, newFeatures) {
77       var featureName = void 0;
78       var feature = void 0;
79       var featureRule = void 0;
80       var filterRule = void 0;
81       var tag = void 0;
82       var editorRequiredTags = {};
83
84       for (featureName in newFeatures) {
85         if (newFeatures.hasOwnProperty(featureName)) {
86           feature = newFeatures[featureName];
87           for (var f = 0; f < feature.length; f++) {
88             featureRule = feature[f];
89             for (var t = 0; t < featureRule.required.tags.length; t++) {
90               tag = featureRule.required.tags[t];
91               if (!_.has(editorRequiredTags, tag)) {
92                 filterRule = new Drupal.FilterHTMLRule();
93                 filterRule.restrictedTags.tags = [tag];
94
95                 filterRule.restrictedTags.allowed.attributes = featureRule.required.attributes.slice(0);
96                 filterRule.restrictedTags.allowed.classes = featureRule.required.classes.slice(0);
97                 editorRequiredTags[tag] = filterRule;
98               } else {
99                   filterRule = editorRequiredTags[tag];
100                   filterRule.restrictedTags.allowed.attributes = _.union(filterRule.restrictedTags.allowed.attributes, featureRule.required.attributes);
101                   filterRule.restrictedTags.allowed.classes = _.union(filterRule.restrictedTags.allowed.classes, featureRule.required.classes);
102                 }
103             }
104           }
105         }
106       }
107
108       var autoAllowedTags = {};
109       for (tag in editorRequiredTags) {
110         if (!_.has(userAllowedTags, tag)) {
111           autoAllowedTags[tag] = editorRequiredTags[tag];
112         } else {
113             var requiredAttributes = editorRequiredTags[tag].restrictedTags.allowed.attributes;
114             var allowedAttributes = userAllowedTags[tag].restrictedTags.allowed.attributes;
115             var needsAdditionalAttributes = requiredAttributes.length && _.difference(requiredAttributes, allowedAttributes).length;
116             var requiredClasses = editorRequiredTags[tag].restrictedTags.allowed.classes;
117             var allowedClasses = userAllowedTags[tag].restrictedTags.allowed.classes;
118             var needsAdditionalClasses = requiredClasses.length && _.difference(requiredClasses, allowedClasses).length;
119             if (needsAdditionalAttributes || needsAdditionalClasses) {
120               autoAllowedTags[tag] = userAllowedTags[tag].clone();
121             }
122             if (needsAdditionalAttributes) {
123               autoAllowedTags[tag].restrictedTags.allowed.attributes = _.union(allowedAttributes, requiredAttributes);
124             }
125             if (needsAdditionalClasses) {
126               autoAllowedTags[tag].restrictedTags.allowed.classes = _.union(allowedClasses, requiredClasses);
127             }
128           }
129       }
130
131       return autoAllowedTags;
132     },
133     _parseSetting: function _parseSetting(setting) {
134       var node = void 0;
135       var tag = void 0;
136       var rule = void 0;
137       var attributes = void 0;
138       var attribute = void 0;
139       var allowedTags = setting.match(/(<[^>]+>)/g);
140       var sandbox = document.createElement('div');
141       var rules = {};
142       for (var t = 0; t < allowedTags.length; t++) {
143         sandbox.innerHTML = allowedTags[t];
144         node = sandbox.firstChild;
145         tag = node.tagName.toLowerCase();
146
147         rule = new Drupal.FilterHTMLRule();
148
149         rule.restrictedTags.tags = [tag];
150
151         attributes = node.attributes;
152         for (var i = 0; i < attributes.length; i++) {
153           attribute = attributes.item(i);
154           var attributeName = attribute.nodeName;
155
156           if (attributeName === 'class') {
157             var attributeValue = attribute.textContent;
158             rule.restrictedTags.allowed.classes = attributeValue.split(' ');
159           } else {
160             rule.restrictedTags.allowed.attributes.push(attributeName);
161           }
162         }
163
164         rules[tag] = rule;
165       }
166       return rules;
167     },
168     _generateSetting: function _generateSetting(tags) {
169       return _.reduce(tags, function (setting, rule, tag) {
170         if (setting.length) {
171           setting += ' ';
172         }
173
174         setting += '<' + tag;
175         if (rule.restrictedTags.allowed.attributes.length) {
176           setting += ' ' + rule.restrictedTags.allowed.attributes.join(' ');
177         }
178
179         if (rule.restrictedTags.allowed.classes.length) {
180           setting += ' class="' + rule.restrictedTags.allowed.classes.join(' ') + '"';
181         }
182
183         setting += '>';
184         return setting;
185       }, '');
186     }
187   };
188
189   Drupal.theme.filterFilterHTMLUpdateMessage = function (tags) {
190     var html = '';
191     var tagList = Drupal.behaviors.filterFilterHtmlUpdating._generateSetting(tags);
192     html += '<p class="editor-update-message">';
193     html += Drupal.t('Based on the text editor configuration, these tags have automatically been added: <strong>@tag-list</strong>.', { '@tag-list': tagList });
194     html += '</p>';
195     return html;
196   };
197 })(jQuery, Drupal, _, document);