2010-03-06 3 views
3

Я уже давно бил головой об этом reg ex и надеюсь, что кто-то может помочь. В основном у меня есть поле WYSIWYG, где пользователь может печатать форматированный текст. Но, конечно, они будут копировать и вставлять форму word/web/etc. Таким образом, у меня есть функция JS, которая захватывает входные данные при вставке. У меня есть функция, которая будет лишать ВСЕ форматирования текста, который хорош, но я бы хотел, чтобы он оставлял теги, такие как p и br, поэтому это не просто большой беспорядок.Как удалить все теги html в javascript с исключениями?

Любые рядовые ниндзя? Вот что я до сих пор, и это работает. Просто нужно разрешить теги.

o.node.innerHTML=o.node.innerHTML.replace(/(<([^>]+)>)/ig,""); 
+1

http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – waiwai933

ответ

9

В браузере уже есть отлично разбирающееся дерево HTML в o.node. Сериализация содержимого документа в HTML (с использованием innerHTML), пытаясь взломать его с помощью регулярного выражения (которое не может корректно разобрать HTML), затем повторная обработка результатов обратно в содержимое документа путем установки innerHTML ... просто немного извращена ,

Вместо этого проверьте узлы элементов и атрибутов, которые у вас уже есть внутри o.node, удаляя те, которые вы не хотите, например.:

filterNodes(o.node, {p: [], br: [], a: ['href']}); 

Определяется как:

// Remove elements and attributes that do not meet a whitelist lookup of lowercase element 
// name to list of lowercase attribute names. 
// 
function filterNodes(element, allow) { 
    // Recurse into child elements 
    // 
    Array.fromList(element.childNodes).forEach(function(child) { 
     if (child.nodeType===1) { 
      filterNodes(child, allow); 

      var tag= child.tagName.toLowerCase(); 
      if (tag in allow) { 

       // Remove unwanted attributes 
       // 
       Array.fromList(child.attributes).forEach(function(attr) { 
        if (allow[tag].indexOf(attr.name.toLowerCase())===-1) 
         child.removeAttributeNode(attr); 
       }); 

      } else { 

       // Replace unwanted elements with their contents 
       // 
       while (child.firstChild) 
        element.insertBefore(child.firstChild, child); 
       element.removeChild(child); 
      } 
     } 
    }); 
} 

// ECMAScript Fifth Edition (and JavaScript 1.6) array methods used by `filterNodes`. 
// Because not all browsers have these natively yet, bodge in support if missing. 
// 
if (!('indexOf' in Array.prototype)) { 
    Array.prototype.indexOf= function(find, ix /*opt*/) { 
     for (var i= ix || 0, n= this.length; i<n; i++) 
      if (i in this && this[i]===find) 
       return i; 
     return -1; 
    }; 
} 
if (!('forEach' in Array.prototype)) { 
    Array.prototype.forEach= function(action, that /*opt*/) { 
     for (var i= 0, n= this.length; i<n; i++) 
      if (i in this) 
       action.call(that, this[i], i, this); 
    }; 
} 

// Utility function used by filterNodes. This is really just `Array.prototype.slice()` 
// except that the ECMAScript standard doesn't guarantee we're allowed to call that on 
// a host object like a DOM NodeList, boo. 
// 
Array.fromList= function(list) { 
    var array= new Array(list.length); 
    for (var i= 0, n= list.length; i<n; i++) 
     array[i]= list[i]; 
    return array; 
}; 
+0

Отличная функция! и умный метод. Работает как шарм. Единственное, что осталось (иногда). . Я думаю, потому что они не узлы. Любой способ избавиться от этого? Если еще не замечательно! –

+0

Это узлы комментариев. Вы можете избавиться от них, если хотите с помощью '... else if (child.nodeType === 8) {element.removeChild (child); } '(' 8' 'COMMENT_NODE', как' 1' является 'ELEMENT_NODE' (хотя IE не дает вам постоянных имен, поэтому вам нужно использовать номера). – bobince

+0

Безопасен ли код выше XSS (см. [Вопрос ] (http://stackoverflow.com/questions/18370188/securely-strip-html-tags-in-javascript-with-whitelist)) –

3

Во-первых, я не уверен, что регулярное выражение является правильным инструментом для этого. Пользователь может ввести недопустимый HTML (забудьте > или поместите > внутри атрибутов), и тогда будет вызываться регулярное выражение. Я не знаю, однако, если бы парсер был бы намного лучше/более пуленепробиваемым.

Во-вторых, у вас есть несколько ненужных круглых скобок в вашем регулярном выражении.

В-третьих, вы можете использовать предпросмотр, чтобы исключить определенные теги:

o.node.innerHTML=o.node.innerHTML.replace(/<(?!\s*\/?(br|p)\b)[^>]+>/ig,""); 

Объяснение:

< матч угол открывающая скобка

(?!\s*\/?(br|p)\b) утверждают, что это не возможно, чтобы соответствовать ноль или более пробельных символов , ноль или один /, любой из br или p, за которым следует граница слова. Граница слова важна, в противном случае вы можете вызвать lookahead на теги, например <pre> или <param ...>.

[^>]+ матч один или несколько символы, которые не являются ни одного угла закрытия скобки

> матча закрывающих угловых скобок.

Обратите внимание, что вы можете столкнуться с проблемой, если скобка закрывающего угла происходит где-то внутри тега.

Так что это будет соответствовать (и полосы)

<pre> <a href="dot.com"> </a> </pre>

и оставить

<p> <p> </br> <br /> <br> т.д.

в одиночку.

+0

Хм просто попробовал и все еще раздеты все ... не reg ex, что бы вы предложили? Я не хотел находить и заменять каждый тип тега. –

+0

Извините, я сначала неправильно понял ваше сообщение ('b' вместо' br'). Можете ли вы попробовать еще раз? –

+0

Работает идеально для меня! Благодаря! :) – podeig