2 * DO NOT EDIT THIS FILE.
3 * See the following change record for more information,
4 * https://www.drupal.org/node/2815083
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);
15 var rule = new Drupal.FilterHTMLRule();
16 rule.restrictedTags.tags = ['*'];
17 rule.restrictedTags.forbidden.attributes = ['style', 'on*'];
25 Drupal.behaviors.filterFilterHtmlUpdating = {
26 $allowedHTMLFormItem: null,
28 $allowedHTMLDescription: null,
36 attach: function attach(context, settings) {
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);
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();
51 }).on('drupalEditorFeatureRemoved', function (e, feature) {
52 if (that.newFeatures.hasOwnProperty(feature.name)) {
53 delete that.newFeatures[feature.name];
54 that._updateAllowedTags();
58 that.$allowedHTMLFormItem.on('change.updateUserTags', function () {
59 that.userTags = _.difference(that._parseSetting(this.value), that.autoTags);
63 _updateAllowedTags: function _updateAllowedTags() {
64 this.autoTags = this._calculateAutoAllowedTags(this.userTags, this.newFeatures);
66 this.$allowedHTMLDescription.find('.editor-update-message').remove();
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));
73 this.$allowedHTMLFormItem.val(this._generateSetting(this.userTags));
76 _calculateAutoAllowedTags: function _calculateAutoAllowedTags(userAllowedTags, newFeatures) {
77 var editorRequiredTags = {};
79 Object.keys(newFeatures || {}).forEach(function (featureName) {
80 var feature = newFeatures[featureName];
81 var featureRule = void 0;
82 var filterRule = void 0;
85 for (var f = 0; f < feature.length; f++) {
86 featureRule = feature[f];
87 for (var t = 0; t < featureRule.required.tags.length; t++) {
88 tag = featureRule.required.tags[t];
89 if (!_.has(editorRequiredTags, tag)) {
90 filterRule = new Drupal.FilterHTMLRule();
91 filterRule.restrictedTags.tags = [tag];
93 filterRule.restrictedTags.allowed.attributes = featureRule.required.attributes.slice(0);
94 filterRule.restrictedTags.allowed.classes = featureRule.required.classes.slice(0);
95 editorRequiredTags[tag] = filterRule;
97 filterRule = editorRequiredTags[tag];
98 filterRule.restrictedTags.allowed.attributes = _.union(filterRule.restrictedTags.allowed.attributes, featureRule.required.attributes);
99 filterRule.restrictedTags.allowed.classes = _.union(filterRule.restrictedTags.allowed.classes, featureRule.required.classes);
105 var autoAllowedTags = {};
106 Object.keys(editorRequiredTags).forEach(function (tag) {
107 if (!_.has(userAllowedTags, tag)) {
108 autoAllowedTags[tag] = editorRequiredTags[tag];
110 var requiredAttributes = editorRequiredTags[tag].restrictedTags.allowed.attributes;
111 var allowedAttributes = userAllowedTags[tag].restrictedTags.allowed.attributes;
112 var needsAdditionalAttributes = requiredAttributes.length && _.difference(requiredAttributes, allowedAttributes).length;
113 var requiredClasses = editorRequiredTags[tag].restrictedTags.allowed.classes;
114 var allowedClasses = userAllowedTags[tag].restrictedTags.allowed.classes;
115 var needsAdditionalClasses = requiredClasses.length && _.difference(requiredClasses, allowedClasses).length;
116 if (needsAdditionalAttributes || needsAdditionalClasses) {
117 autoAllowedTags[tag] = userAllowedTags[tag].clone();
119 if (needsAdditionalAttributes) {
120 autoAllowedTags[tag].restrictedTags.allowed.attributes = _.union(allowedAttributes, requiredAttributes);
122 if (needsAdditionalClasses) {
123 autoAllowedTags[tag].restrictedTags.allowed.classes = _.union(allowedClasses, requiredClasses);
128 return autoAllowedTags;
130 _parseSetting: function _parseSetting(setting) {
134 var attributes = void 0;
135 var attribute = void 0;
136 var allowedTags = setting.match(/(<[^>]+>)/g);
137 var sandbox = document.createElement('div');
139 for (var t = 0; t < allowedTags.length; t++) {
140 sandbox.innerHTML = allowedTags[t];
141 node = sandbox.firstChild;
142 tag = node.tagName.toLowerCase();
144 rule = new Drupal.FilterHTMLRule();
146 rule.restrictedTags.tags = [tag];
148 attributes = node.attributes;
149 for (var i = 0; i < attributes.length; i++) {
150 attribute = attributes.item(i);
151 var attributeName = attribute.nodeName;
153 if (attributeName === 'class') {
154 var attributeValue = attribute.textContent;
155 rule.restrictedTags.allowed.classes = attributeValue.split(' ');
157 rule.restrictedTags.allowed.attributes.push(attributeName);
165 _generateSetting: function _generateSetting(tags) {
166 return _.reduce(tags, function (setting, rule, tag) {
167 if (setting.length) {
171 setting += '<' + tag;
172 if (rule.restrictedTags.allowed.attributes.length) {
173 setting += ' ' + rule.restrictedTags.allowed.attributes.join(' ');
176 if (rule.restrictedTags.allowed.classes.length) {
177 setting += ' class="' + rule.restrictedTags.allowed.classes.join(' ') + '"';
186 Drupal.theme.filterFilterHTMLUpdateMessage = function (tags) {
188 var tagList = Drupal.behaviors.filterFilterHtmlUpdating._generateSetting(tags);
189 html += '<p class="editor-update-message">';
190 html += Drupal.t('Based on the text editor configuration, these tags have automatically been added: <strong>@tag-list</strong>.', { '@tag-list': tagList });
194 })(jQuery, Drupal, _, document);