github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/pubnot/trumbowyg/plugins/cleanpaste/trumbowyg.cleanpaste.js (about)

     1  /* ===========================================================
     2   * trumbowyg.cleanpaste.js v1.0
     3   * Font Clean paste plugin for Trumbowyg
     4   * http://alex-d.github.com/Trumbowyg
     5   * ===========================================================
     6   * Author : Eric Radin
     7   */
     8  
     9  /**
    10   * This plugin will perform a "cleaning" on any paste, in particular
    11   * it will clean pasted content of microsoft word document tags and classes.
    12   */
    13  (function ($) {
    14      'use strict';
    15  
    16      function reverse(sentString) {
    17          var theString = '';
    18          for (var i = sentString.length - 1; i >= 0; i -= 1) {
    19              theString += sentString.charAt(i);
    20          }
    21          return theString;
    22      }
    23  
    24      function checkValidTags(snippet) {
    25          var theString = snippet;
    26  
    27          // Replace uppercase element names with lowercase
    28          theString = theString.replace(/<[^> ]*/g, function (match) {
    29              return match.toLowerCase();
    30          });
    31  
    32          // Replace uppercase attribute names with lowercase
    33          theString = theString.replace(/<[^>]*>/g, function (match) {
    34              match = match.replace(/ [^=]+=/g, function (match2) {
    35                  return match2.toLowerCase();
    36              });
    37              return match;
    38          });
    39  
    40          // Put quotes around unquoted attributes
    41          theString = theString.replace(/<[^>]*>/g, function (match) {
    42              match = match.replace(/( [^=]+=)([^"][^ >]*)/g, '$1\"$2\"');
    43              return match;
    44          });
    45  
    46          return theString;
    47      }
    48  
    49      function cleanIt(htmlBefore, htmlAfter) {
    50          var matchedHead = '';
    51          var matchedTail = '';
    52          var afterStart;
    53          var afterFinish;
    54          var newSnippet;
    55  
    56          // we need to extract the inserted block
    57          for (afterStart = 0; htmlAfter.charAt(afterStart) === htmlBefore.charAt(afterStart); afterStart += 1) {
    58              matchedHead += htmlAfter.charAt(afterStart);
    59          }
    60  
    61          // If afterStart is inside a HTML tag, move to opening brace of tag
    62          for (var i = afterStart; i >= 0; i -= 1) {
    63              if (htmlBefore.charAt(i) === '<') {
    64                  afterStart = i;
    65                  matchedHead = htmlBefore.substring(0, afterStart);
    66                  break;
    67              } else if (htmlBefore.charAt(i) === '>') {
    68                  break;
    69              }
    70          }
    71  
    72          // now reverse string and work from the end in
    73          htmlAfter = reverse(htmlAfter);
    74          htmlBefore = reverse(htmlBefore);
    75  
    76          // Find end of both strings that matches
    77          for (afterFinish = 0; htmlAfter.charAt(afterFinish) === htmlBefore.charAt(afterFinish); afterFinish += 1) {
    78              matchedTail += htmlAfter.charAt(afterFinish);
    79          }
    80  
    81          // If afterFinish is inside a HTML tag, move to closing brace of tag
    82          for (var j = afterFinish; j >= 0; j -= 1) {
    83              if (htmlBefore.charAt(j) === '>') {
    84                  afterFinish = j;
    85                  matchedTail = htmlBefore.substring(0, afterFinish);
    86                  break;
    87              } else if (htmlBefore.charAt(j) === '<') {
    88                  break;
    89              }
    90          }
    91  
    92          matchedTail = reverse(matchedTail);
    93  
    94          // If there's no difference in pasted content
    95          if (afterStart === (htmlAfter.length - afterFinish)) {
    96              return false;
    97          }
    98  
    99          htmlAfter = reverse(htmlAfter);
   100          newSnippet = htmlAfter.substring(afterStart, htmlAfter.length - afterFinish);
   101  
   102          // first make sure all tags and attributes are made valid
   103          newSnippet = checkValidTags(newSnippet);
   104  
   105          // Replace opening bold tags with strong
   106          newSnippet = newSnippet.replace(/<b(\s+|>)/g, '<strong$1');
   107          // Replace closing bold tags with closing strong
   108          newSnippet = newSnippet.replace(/<\/b(\s+|>)/g, '</strong$1');
   109  
   110          // Replace italic tags with em
   111          newSnippet = newSnippet.replace(/<i(\s+|>)/g, '<em$1');
   112          // Replace closing italic tags with closing em
   113          newSnippet = newSnippet.replace(/<\/i(\s+|>)/g, '</em$1');
   114  
   115          // strip out comments -cgCraft
   116          newSnippet = newSnippet.replace(/<!(?:--[\s\S]*?--\s*)?>\s*/g, '');
   117  
   118          // strip out &nbsp; -cgCraft
   119          newSnippet = newSnippet.replace(/&nbsp;/gi, ' ');
   120          // strip out extra spaces -cgCraft
   121          newSnippet = newSnippet.replace(/ <\//gi, '</');
   122  
   123          while (newSnippet.indexOf('  ') !== -1) {
   124              var anArray = newSnippet.split('  ');
   125              newSnippet = anArray.join(' ');
   126          }
   127  
   128          // strip &nbsp; -cgCraft
   129          newSnippet = newSnippet.replace(/^\s*|\s*$/g, '');
   130  
   131          // Strip out unaccepted attributes
   132          newSnippet = newSnippet.replace(/<[^>]*>/g, function (match) {
   133              match = match.replace(/ ([^=]+)="[^"]*"/g, function (match2, attributeName) {
   134                  if (['alt', 'href', 'src', 'title'].indexOf(attributeName) !== -1) {
   135                      return match2;
   136                  }
   137                  return '';
   138              });
   139              return match;
   140          });
   141  
   142          // Final cleanout for MS Word crud
   143          newSnippet = newSnippet.replace(/<\?xml[^>]*>/g, '');
   144          newSnippet = newSnippet.replace(/<[^ >]+:[^>]*>/g, '');
   145          newSnippet = newSnippet.replace(/<\/[^ >]+:[^>]*>/g, '');
   146  
   147          // remove unwanted tags
   148          newSnippet = newSnippet.replace(/<(div|span|style|meta|link){1}.*?>/gi, '');
   149  
   150          htmlAfter = matchedHead + newSnippet + matchedTail;
   151          return htmlAfter;
   152      }
   153  
   154      // clean editor
   155      // this will clean the inserted contents
   156      // it does a compare, before and after paste to determine the
   157      // pasted contents
   158      $.extend(true, $.trumbowyg, {
   159          plugins: {
   160              cleanPaste: {
   161                  init: function (trumbowyg) {
   162                      trumbowyg.pasteHandlers.push(function () {
   163                          try {
   164                              var contentBefore = trumbowyg.$ed.html();
   165                              setTimeout(function () {
   166                                  var contentAfter = trumbowyg.$ed.html();
   167                                  contentAfter = cleanIt(contentBefore, contentAfter);
   168                                  trumbowyg.$ed.html(contentAfter);
   169                              }, 0);
   170                          } catch (c) {
   171                          }
   172                      });
   173                  }
   174              }
   175          }
   176      });
   177  })(jQuery);
   178  
   179