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 featureName = void 0;
79 var featureRule = void 0;
80 var filterRule = void 0;
82 var editorRequiredTags = {};
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];
95 filterRule.restrictedTags.allowed.attributes = featureRule.required.attributes.slice(0);
96 filterRule.restrictedTags.allowed.classes = featureRule.required.classes.slice(0);
97 editorRequiredTags[tag] = filterRule;
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);
108 var autoAllowedTags = {};
109 for (tag in editorRequiredTags) {
110 if (!_.has(userAllowedTags, tag)) {
111 autoAllowedTags[tag] = editorRequiredTags[tag];
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();
122 if (needsAdditionalAttributes) {
123 autoAllowedTags[tag].restrictedTags.allowed.attributes = _.union(allowedAttributes, requiredAttributes);
125 if (needsAdditionalClasses) {
126 autoAllowedTags[tag].restrictedTags.allowed.classes = _.union(allowedClasses, requiredClasses);
131 return autoAllowedTags;
133 _parseSetting: function _parseSetting(setting) {
137 var attributes = void 0;
138 var attribute = void 0;
139 var allowedTags = setting.match(/(<[^>]+>)/g);
140 var sandbox = document.createElement('div');
142 for (var t = 0; t < allowedTags.length; t++) {
143 sandbox.innerHTML = allowedTags[t];
144 node = sandbox.firstChild;
145 tag = node.tagName.toLowerCase();
147 rule = new Drupal.FilterHTMLRule();
149 rule.restrictedTags.tags = [tag];
151 attributes = node.attributes;
152 for (var i = 0; i < attributes.length; i++) {
153 attribute = attributes.item(i);
154 var attributeName = attribute.nodeName;
156 if (attributeName === 'class') {
157 var attributeValue = attribute.textContent;
158 rule.restrictedTags.allowed.classes = attributeValue.split(' ');
160 rule.restrictedTags.allowed.attributes.push(attributeName);
168 _generateSetting: function _generateSetting(tags) {
169 return _.reduce(tags, function (setting, rule, tag) {
170 if (setting.length) {
174 setting += '<' + tag;
175 if (rule.restrictedTags.allowed.attributes.length) {
176 setting += ' ' + rule.restrictedTags.allowed.attributes.join(' ');
179 if (rule.restrictedTags.allowed.classes.length) {
180 setting += ' class="' + rule.restrictedTags.allowed.classes.join(' ') + '"';
189 Drupal.theme.filterFilterHTMLUpdateMessage = function (tags) {
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 });
197 })(jQuery, Drupal, _, document);