filter.filter_html.admin.js 7.6 KB

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