30

我正在使用“contenteditable”<div/>并启用 PASTE。

令人惊讶的是,从 Microsoft Word 的剪贴板副本中粘贴的标记代码数量之多。我正在与这个作斗争,并且使用 Prototypes 的stripTags()功能已经获得了大约 1/2 的方式(不幸的是,这似乎无法让我保留一些标签)。

然而,即使在那之后,我最终还是得到了大量不需要的标记代码。

所以我的问题是,是否有一些函数(使用 JavaScript)或我可以使用的方法来清理大部分不需要的标记?

4

10 回答 10

24

这是我最终编写的函数,它做得相当好(据我所知)。

如果有人有任何改进建议,我当然愿意接受。谢谢。

function cleanWordPaste( in_word_text ) {
 var tmp = document.createElement("DIV");
 tmp.innerHTML = in_word_text;
 var newString = tmp.textContent||tmp.innerText;
 // this next piece converts line breaks into break tags
 // and removes the seemingly endless crap code
 newString  = newString.replace(/\n\n/g, "<br />").replace(/.*<!--.*-->/g,"");
 // this next piece removes any break tags (up to 10) at beginning
 for ( i=0; i<10; i++ ) {
  if ( newString.substr(0,6)=="<br />" ) { 
   newString = newString.replace("<br />", ""); 
  }
 }
 return newString;
}

希望这对你们中的一些人有所帮助。

于 2010-05-20T18:16:06.680 回答
3

我正在使用这个:

$(body_doc).find('body').bind('paste',function(e){
                var rte = $(this);
                _activeRTEData = $(rte).html();
                beginLen = $.trim($(rte).html()).length; 

                setTimeout(function(){
                    var text = $(rte).html();
                    var newLen = $.trim(text).length;

                    //identify the first char that changed to determine caret location
                    caret = 0;

                    for(i=0;i < newLen; i++){
                        if(_activeRTEData[i] != text[i]){
                            caret = i-1;
                            break;  
                        }
                    }

                    var origText = text.slice(0,caret);
                    var newText = text.slice(caret, newLen - beginLen + caret + 4);
                    var tailText = text.slice(newLen - beginLen + caret + 4, newLen);

                    var newText = newText.replace(/(.*(?:endif-->))|([ ]?<[^>]*>[ ]?)|(&nbsp;)|([^}]*})/g,'');

                    newText = newText.replace(/[·]/g,'');

                    $(rte).html(origText + newText + tailText);
                    $(rte).contents().last().focus();
                },100);
            });

body_doc 是可编辑的 iframe,如果您使用的是可编辑的 div,则可以删除 .find('body') 部分。基本上,它会检测粘贴事件,检查位置是否清理了新文本,然后将清理后的文本放回粘贴的位置。(听起来令人困惑......但它并不像听起来那么糟糕。

需要 setTimeout 是因为在将文本实际粘贴到元素中之前无法抓取文本,粘贴事件会在粘贴开始后立即触发。

于 2011-10-27T20:03:32.403 回答
3

您可以使用完整的CKEditor来清除粘贴,或者查看源代码

于 2010-05-20T15:21:05.880 回答
2

有一个显示 的“粘贴为纯文本”按钮<textarea>,允许用户将文本粘贴到那里怎么样?这样,所有标签都会为您剥离。这就是我对 CMS 所做的;我放弃了尝试清理 Word 的烂摊子。

于 2010-05-20T15:17:47.337 回答
0

我很久以前做过类似的事情,我在富文本编辑器中完全清理了这些东西,并将字体标签转换为样式,将 brs 转换为 p 等,以保持浏览器之间的一致性,并防止某些丑陋的东西通过粘贴进入。我使用了我的递归函数并删除了除核心逻辑之外的大部分内容,这可能是一个很好的起点(“结果”是一个累积结果的对象,它可能需要第二次传递才能转换为字符串),如果这就是你需要的:

var cleanDom = function(result, n) {
var nn = n.nodeName;
if(nn=="#text") {
    var text = n.nodeValue;

    }
else {
    if(nn=="A" && n.href)
        ...;
    else if(nn=="IMG" & n.src) {
        ....
        }
    else if(nn=="DIV") {
        if(n.className=="indent")
            ...
        }
    else if(nn=="FONT") {
        }       
    else if(nn=="BR") {
        }

    if(!UNSUPPORTED_ELEMENTS[nn]) {
        if(n.childNodes.length > 0)
            for(var i=0; i<n.childNodes.length; i++) 
                cleanDom(result, n.childNodes[i]);
        }
    }
}
于 2010-05-20T18:16:23.090 回答
0

有一个类似的问题,换行符被视为字符,我不得不删除它们。

$(document).ready(function(){

  $(".section-overview textarea").bind({
    paste : function(){
    setTimeout(function(){
      //textarea
      var text = $(".section-overview textarea").val();
      // look for any "\n" occurences and replace them
      var newString = text.replace(/\n/g, '');
      // print new string
      $(".section-overview textarea").val(newString);
    },100);
    }
  });
  
});

于 2015-03-24T18:07:08.623 回答
0

这非常适合从 HTML 文本中删除任何注释,包括 Word 中的注释:

function CleanWordPastedHTML(sTextHTML) {
  var sStartComment = "<!--", sEndComment = "-->";
  while (true) {
    var iStart = sTextHTML.indexOf(sStartComment);
    if (iStart == -1) break;
    var iEnd = sTextHTML.indexOf(sEndComment, iStart);
    if (iEnd == -1) break;
    sTextHTML = sTextHTML.substring(0, iStart) + sTextHTML.substring(iEnd + sEndComment.length);
  }
  return sTextHTML;
}
于 2014-11-07T16:11:37.423 回答
0

你可以用正则表达式

  1. 删除头部标签

  2. 删除脚本标签

  3. 删除样式标签

    let clipboardData = event.clipboardData || window.clipboardData;
    let pastedText = clipboardData.getData('text/html');
    pastedText = pastedText.replace(/\<head[^>]*\>([^]*)\<\/head/g, '');
    pastedText = pastedText.replace(/\<script[^>]*\>([^]*)\<\/script/g, '');
    pastedText = pastedText.replace(/\<style[^>]*\>([^]*)\<\/style/g, '');
    // pastedText = pastedText.replace(/<(?!(\/\s*)?(b|i|u)[>,\s])([^>])*>/g, '');
    

这里的示例:https ://stackblitz.com/edit/angular-u9vprc

于 2021-08-01T08:16:56.640 回答
-1

你能粘贴到一个隐藏的文本区域,从同一个文本区域复制,然后粘贴到你的目标吗?

于 2010-05-20T15:23:42.067 回答
-4

讨厌这么说,但我最终放弃了让 TinyMCE 以我想要的方式处理 Word 废话。现在,每当用户的输入包含某些 HTML(<span lang="en-US">例如查找)时,我都会收到一封电子邮件,我会手动更正它。

于 2010-05-20T15:25:44.467 回答