jQuery: Как мне сопоставить текст с шаблоном RegEx и обернуть результаты в тег привязки? - PullRequest
2 голосов
/ 25 сентября 2010

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

В качестве примера здесь приведен твит, где я хотел бы@Bundlehunt чтобы стать <a href="http://twitter.com/bundlehunt">@Bundlehunt</a>, а http://bundlehunt.com должно стать <a href="http://bundlehunt.com">http://bundlehunt.com</a>.

Образец твита:

joined @BundleHunt for a chance to win the 2010 Mega Bundle! 
http://bundlehunt.com * Only 10 Days Left!

Звучит достаточно просто, я подумал, поэтому я использовал превосходный http://www.gskinner.com/RegExr/ инструмент, чтобы найти следующий шаблон 2 RegEx, который соответствует этим вещам в моих твитах:

@twittername = /@(\w.+?)(?=\s)/gi
@links = /http:\/\/(.*)\.([a-zA-Z\.]){2,3}/gi

Теперь вернувшись в свой документ jQuery, я пытаюсь просмотреть текст и сопоставить RegEx, но там язаблудиться ...

Как мне на самом деле идти о сопоставлении простого текста, обтекании тегов привязки и вставке сопоставленного текста в соответствующий тег привязки?

Спасибо за чтение,

Jannis

Ответы [ 2 ]

1 голос
/ 25 сентября 2010

Проще всего использовать replace метод String Object:

var TWITTER_NAME =  /@(\w.+?)(?=\s)/gi , LINK = /http:\/\/(.*)\.([a-zA-Z\.]){2,3}/gi ;

var string = "joined @BundleHunt for a chance to win the 2010 Mega Bundle! \n http://bundlehunt.com * Only 10 Days Left!"

    string.replace(
        TWITTER_NAME,
        function(str,c1,c2) { 
            return "<a href=\"http://www.twitter.com/" + c1.toLowerCase() + ">" + str + "</a>" ;
        }
    ) ; 
    string.replace(LINK,"<a href=\"$&\">$&</a>") ;

См. Здесь документацию: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace.


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

1 голос
/ 25 сентября 2010

Если бы вы использовали метод jQuery .html () для ненадежного ввода, ваше веб-приложение было бы уязвимо для атаки межсайтового скриптинга (XSS), которую можно было бы использовать, отправив вредоносный твит. Лучший способ избежать этой проблемы безопасности - добавлять каждую часть твита по отдельности, используя правильные функции jQuery, которые используют функции DOM веб-браузера для HTML-строк.

  1. Сначала объедините два регулярных выражения в одно, используя чередование регулярных выражений (символ |). Для целей моего примера кода регулярное выражение имени пользователя в Твиттере равно /@\w+/gi, а регулярное выражение URL-адреса равно /(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi. Эти регулярные выражения не совпадают с теми, что были в исходном вопросе; оригинальное регулярное выражение URL, похоже, не работает правильно, и нам не нужно использовать группы захвата. Таким образом, объединенное регулярное выражение равно /@\w+|(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi.

  2. При каждом совпадении регулярного выражения надежно добавляйте текст, предшествующий совпадению, в контейнер. Для этого в jQuery создайте пустой элемент span и используйте метод .text () для вставки текста внутрь. Использование $ ('text here') оставит широко открытую дыру в XSS. Что если содержимое твита составляет <script>alert(document.cookie)</script>?

  3. Проверьте первый символ совпадения, чтобы определить, как он должен быть отформатирован. Имена пользователей Twitter начинаются с "@", но URL-адреса не могут.

  4. Отформатируйте совпадение и добавьте его в контейнер. Опять же, не передавайте ненадежный ввод функции $ или jQuery; используйте метод .attr () для добавления таких атрибутов, как href и метод .text () для добавления текста ссылки.

  5. После того, как все совпадения были обработаны, добавьте последнюю часть текста в виде простого текста, которая не была добавлена ​​в шаге 3 или 4.

Пример кода (также на http://jsfiddle.net/6X6xD/3/):

var tweet = 'joined @BundleHunt for a chance to win the 2010 Mega Bundle! http://bundlehunt.com * Only 10 Days Left! URL containing an at sign: http://www.last.fm/event/1196311+Live+@+Public+Assembly. This should not work: <scr'+'ipt>alert(document.cookie)</scr'+'ipt>';

var combinedRegex = /@\w+|(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi,
    container = $('#tweet-container');

var result, prevLastIndex = 0;
combinedRegex.lastIndex = 0;
while((result = combinedRegex.exec(tweet))) {
    // Append the text coming before the matched entity
    container.append($('<span/>').text(tweet.slice(prevLastIndex, result.index)));
    if(result[0].slice(0, 1) == "@") {
        // Twitter username was matched
        container.append($('<a/>')
            // .slice(1) cuts off the first character (i.e. "@")
            .attr('href', 'http://twitter.com/' + encodeURIComponent(result[0].slice(1)))
            .text(result[0])
        );
    } else {
        // URL was matched
        container.append($('<a/>')
            .attr('href', result[0])
            .text(result[0])
        );
    }
    // prevLastIndex will point to the next plain text character to be added
    prevLastIndex = combinedRegex.lastIndex;
}
// Append last plain text part of tweet
container.append($('<span/>').text(tweet.slice(prevLastIndex)));

Примечание. Старые версии этого ответа рекомендовали использовать метод .html (). Поскольку это серьезная проблема безопасности, как уже упоминалось выше, я использовал кнопку редактирования, чтобы опубликовать свой новый ответ, удалив старый из вида.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...