Pregunta

Tengo una cadena (en parte HTML) donde quiero sustituir la cadena en :-) :wink: BBCode. Pero esta sustitución no debería ocurrir dentro de <pre>, pero en ninguna otra etiqueta (o incluso no dentro de una etiqueta).

Por ejemplo, quiero reemplazar

:-)<pre>:-)</pre><blockquote>:-)</blockquote>

a:

:wink:<pre>:-)</pre><blockquote>:wink:</blockquote>

Ya probé con la siguiente expresión regular, pero no funciona (nada es reemplazado):

var s = ':-)<pre>:-)</pre><blockquote>:-)</blockquote>';
var regex = /:\-\)(?!(^<pre>).*<\/pre>)/g;
var r = s.replace(regex, ':wink:');

Por favor alguien puede ayudarme? : -)

¿Fue útil?

Solución

Esto debería hacerlo: -

var src = ":-)<pre>:-)</pre><blockquote>:-)</blockquote>"

var result = src.replace(/(<pre>(?:[^<](?!\/pre))*<\/pre>)|(\:\-\))/gi, fnCallback)

function fnCallback(s)
{
    if (s == ":-)") return ":wink:"
    return s;
}

alert(result);

Funciona porque cualquier elemento pre conseguirá recogido por la primera opción en la expresión regular y una vez consumido significa que cualquier :-) contenida no puede ser igualada ya que el procesador se habrá movido más allá de ella.

Otros consejos

Se podría evitar expresiones regulares infernales por completo si se utiliza una biblioteca adecuada tal como jQuery, por ejemplo:.

var excludeThese = ['pre'];

// loop over all elements on page, replacing :-) with :wink: for anything
// that is *not* a tag name in the excludeThese array

$('* not:(' + excludeThese.join(',') + ')').each(function() {
    $(this).html($(this).html().replace(/:\-\)/,':wink:'));
});

Sólo pensé que valdría la pena ofrecer una solución DOM:

por ejemplo.

var div = document.createElement('div');
div.innerHTML = ":-)<pre>:-)</pre><blockquote>:-)</blockquote>";

replace(div, /:-\)/g, ":wink:", function(){

    // Custom filter function.
    // Returns false for <pre> elements.

    return this.nodeName.toLowerCase() !== 'pre';

});

div.innerHTML; // <== here's your new string!

Y aquí está la función replace:

function replace(element, regex, replacement, filter) {

    var cur = element.firstChild;

    if (cur) do {

        if ( !filter || filter.call(cur) ) {

            if ( cur.nodeType == 1 ) {
                replace( cur, regex, replacement );
            } else {
                cur.data = cur.data.replace( regex, replacement );
            }

        }

    } while ( cur = cur.nextSibling );

}

tratar con var = regex /: -) (?! (^) * ) / g;

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top