Nettoyer le texte collé Microsoft Word en utilisant JavaScript

J'utilise un 'contenteditable' <div/> et j'active PASTE.

C'est incroyable la quantité de code de balisage qui est collée à partir d'une copie du presse-papiers de Microsoft Word. Je suis en train de lutter contre cela, et j'ai obtenu environ 1/2 chemin en utilisant la fonction stripTags() des Prototypes (qui ne semble malheureusement pas me permettre de garder quelques balises).

Cependant, même après cela, je me retrouve avec une quantité hallucinante de code de balisage inutile.

Donc ma question Est, y a-t-il une fonction (en utilisant JavaScript), ou approche que je peux utiliser qui va nettoyer la majorité de ce balisage inutile?

22
demandé sur Todd Main 2010-05-20 19:07:21

9 réponses

Voici la fonction que j'ai fini par écrire qui fait assez bien le travail (pour autant que je sache de toute façon).

Je suis certainement ouvert aux suggestions d'amélioration si quelqu'un en a. Grâce.

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;
}

J'espère que cela est utile à certains d'entre vous.

20
répondu OneNerd 2017-12-20 21:41:02

Vous pouvez soit utiliser le CKEditor complet qui nettoie sur la pâte, soit regarder la source.

3
répondu Todd Main 2010-05-20 15:21:05

J'utilise ceci:

$(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 est l'iframe modifiable, si vous utilisez un div modifiable, vous pouvez supprimer le .trouver ('corps') partie. Fondamentalement, il détecte un événement de collage, vérifie l'emplacement nettoie le nouveau texte, puis place le texte nettoyé là où il a été collé. (Cela semble déroutant... mais ce n'est pas vraiment aussi mauvais que cela puisse paraître.

Le setTimeout est nécessaire car vous ne pouvez pas saisir le texte tant qu'il n'est pas réellement collé dans l'élément, les événements de collage se déclenchent dès que le pâte commence.

3
répondu Daniel Sellers 2011-10-27 20:03:32

Que diriez-vous d'avoir un bouton "Coller en texte brut" qui affiche un <textarea>, permettant à l'utilisateur de coller le texte là-dedans? de cette façon, toutes les étiquettes seront supprimées pour vous. C'est ce que je fais avec mon CMS; j'ai renoncé à essayer de nettoyer le désordre de Word.

2
répondu Josh 2010-05-20 15:17:47

J'ai fait quelque chose comme ça il y a longtemps, où j'ai totalement nettoyé les choses dans un éditeur de texte enrichi et converti les balises de police en styles, brs en p, etc., pour le garder cohérent entre les navigateurs et empêcher certaines choses laides d'entrer via paste. J'ai pris ma fonction récursive et en ai arraché la majeure partie sauf pour la logique de base, cela pourrait être un bon point de départ ("result" est un objet qui accumule le résultat, qui prend probablement une deuxième passe pour convertir en une chaîne), si c'est quoi vous avez besoin de:

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]);
        }
    }
}
0
répondu rob 2010-05-20 18:16:23

Cela fonctionne très bien pour supprimer tous les commentaires du texte HTML, y compris ceux de 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;
}
0
répondu user759463 2014-11-07 16:11:37

Avait un problème similaire avec les sauts de ligne comptés comme des caractères et j'ai dû les supprimer.

$(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);
    }
  });
  
});
0
répondu ericmotil 2015-03-24 18:07:08

Pourriez-vous coller dans une zone de texte cachée, copier à partir de la même zone de texte et coller sur votre cible?

-1
répondu souLTower 2010-05-20 15:23:42

Je déteste le dire, mais j'ai finalement renoncé à faire de la merde de mot TinyMCE comme je le veux. Maintenant, je viens d'avoir un email envoyé à moi chaque fois que l'entrée d'un utilisateur contient certains HTML (recherchez <span lang="en-US"> par exemple) et je le corrige manuellement.

-4
répondu Amy B 2010-05-20 15:25:44