22.01.2012, 19:31
|
|
Модератор
|
|
Регистрация: 27.04.2010
Сообщений: 3,417
|
|
Сообщение от Gozar
|
на скорости правда это не отразилось, может мало циклов,
|
Да и не должно было - тут же происходит каждый раз два переприсвоения в цикле) А в твоём варианте - только одно)
|
|
23.01.2012, 13:34
|
что-то знаю
|
|
Регистрация: 24.05.2009
Сообщений: 5,176
|
|
да, что-то более лучшего ничего не выходит, только так:
var text = 'test [b]blah [i]tata[/i] blah[/b] param [quote="test"]lal[alala[/quote] qweqweqwe [u]ter[u]tet[/u]er[/u] hjf [u]sdhg[/u] end';
var re = /(\[\s*([a-z]+)\s*(?:=?\s*([^\]]+))?\])([^\[]+)(\[\/\2\])/i,
next = true, step = 1;
while( next ) {
next = false;
text = text.replace( re, function( all, tagattr, tag, attr, content, close ) {
next = true;
alert( [tagattr, tag, attr, content, close] );
return '<' + tag + '>' + content + '</' + tag + '>';
});
if ( !next && step++ == 1 ) {
next = true;
re = /(\[\s*([a-z]+)\s*(?:=?\s*([^\]]+))?\])(.*?)(\[\/\2\])/i;
}
}
alert( text );
|
|
05.01.2016, 01:37
|
без статуса
|
|
Регистрация: 25.05.2012
Сообщений: 8,219
|
|
var text = 'test [b]blah\n\ [i]tata[/i] blah[/b] param [quote="test"]d[quote="test2"]lalsd[li]fnsdf[alalsdfsda[/quote] qweqweqwe [u]ter[u]t[/quote]et[/u]er[/u] hjf [u]sdhg[/u] end';
var chang = '¬'; //Строка замены для "["
var re = /(\[([a-z]+)(?:="?([^\]]+?))?"?\])([^\[]*)(\[\/\2\])/gi,
next = true, step = 1;
while( next ) {
next = false;
if(step==1)text = text.replace( re, function( all, tagattr, tag, attr, content, close ) {
next = true;
//alert( [step,tagattr, tag, attr, content, close] );
return '<' + tag + '>' + content + '</' + tag + '>';
});
if ( !next) {step = 2;
text = text.replace(/^([\s\S]*?)(\[\/([a-z]+)\])([\s\S]*)$/i, function(str,strST,tagEnd, tag, strEnd) {
next = true;
var end = strST.length,
st = strST.lastIndexOf('['+tag);
if(st<0) return strST + chang+'/'+ tag + ']' + strEnd;
var find = text.substring(st,end),
rega = '^\\['+tag+'(?:="?([^\\[\\]]+?))?"?\\]([\\s\\S]*)$';
var found = find.replace(RegExp(rega,'i'), function(str,attr,content) {return '<'+tag+'>'+ content.replace(/\[/g, chang) + '</'+tag+'>'});
return text.substr(0,st) + (found!=find ? found : chang + find.slice(1)+ tagEnd) + strEnd;
})
}
}
text = text.replace(RegExp(chang,'g'),'['); //возвращаем скобку;
alert( text );
Чуть ускорил, сделав первый проход глобальным поиском (/gi),
На Втором проверка неполных вложенных тегов (Исключаем ситуации типа [div][li][/div][/li]; подменяем у них символ \[)
===================
В принципе вторая часть работает и самостоятельно, но совместно с первой, получаем приличное ускорение на тегах без квадратных скобок внутри
Последний раз редактировалось Deff, 09.01.2016 в 07:25.
|
|
05.01.2016, 21:11
|
|
Модератор
|
|
Регистрация: 27.04.2010
Сообщений: 3,417
|
|
Deff, ты его четыре года писал?
|
|
05.01.2016, 21:29
|
Профессор
|
|
Регистрация: 12.04.2010
Сообщений: 557
|
|
Понимаю что тема старая
но раз уж всплыла, то вот мой вариант. Здесь в упрощенном виде, только самые простые теги, чтобы нагляднее была идея. А идея вот в чем: когда натыкаемся на открывающий тег, кладем его в стек. Если встретили закрывающий, то проверяем его соответствие верхушке стека, если не соответствует, оставляем бб-код, иначе ставим закрывающий и убираем со стека. В конце, если что-то осталось на стеке, добиваем "закрывашками".
var parseBB = function(str) {
if (!str) { return str; }
var rx = /\[(\/?)(b|i|u|s)\s*\]/gi;
var stack = [];
str = str.replace(rx, function(m, close, tag) {
tag = tag.toLowerCase();
if (close) {
if (!stack.length || (stack[stack.length - 1] !== tag)) {
return m;
}
stack.pop();
} else {
stack.push(tag);
}
return "<" + close + tag + ">";
});
if (stack.length) {
str = str + stack.reverse().map(function(tag) {
return "</" + tag + ">";
}).join("");
}
return str;
};
|
|
07.01.2016, 01:43
|
без статуса
|
|
Регистрация: 25.05.2012
Сообщений: 8,219
|
|
trikadin,
Нет, у мну 4 дня назад встала тема быстрого предпросмотра сообщений в топике(точнее мгновенного, по мере ввода), поискал в инете, наткнулся на эту тему, остальные Варианты были хуже
Последний раз редактировалось Deff, 07.01.2016 в 02:35.
|
|
07.01.2016, 01:46
|
без статуса
|
|
Регистрация: 25.05.2012
Сообщений: 8,219
|
|
Сообщение от Яростный Меч
|
иначе ставим закрывающий и убираем со стека. В конце, если что-то осталось на стеке, добиваем "закрывашками".
|
У мну лучше, 1. Решена проблема пересекающихся(или неполных) тегов
2. Задача по топику была делать не рекурсией(кушает много памяти при длинных строках с много тегами), а простым повтором через while
3. Нун вначале искать первый тег закрытия от начала строки и двигаться вверх до его "открывашки", только тогда не будет пересекающихся тегов(или конфликтов), если вдобавок на всём пути, пройденного до найденной "открывашки", убиваем(подменяем, с возвратом в конце распарса) все открывающиеся скобки "[" , ибо внутри не может быть валидных вложенных ВВ-тегов по определению.
Если "открывашка" не найдена, убиваем открывающуюся скобку "[" у найденного первоначального тега-"закрывашки" .
Крутим цикл пока не будут найдены все('ближайшие от начала') "закрывашки" ...
Последний раз редактировалось Deff, 07.01.2016 в 02:44.
|
|
07.01.2016, 03:01
|
без статуса
|
|
Регистрация: 25.05.2012
Сообщений: 8,219
|
|
Яростный Меч,
Тест: (тег [quote="test2"] - валидный - пропущен, по идее валидный и первый, но тут можно оспорить, ты сделал валидными теги [u]
var parseBB = function(str) {
if (!str) { return str; }
var rx = /\[(\/?)(b|i|u|s)\s*\]/gi;
var stack = [];
str = str.replace(rx, function(m, close, tag) {
tag = tag.toLowerCase();
if (close) {
if (!stack.length || (stack[stack.length - 1] !== tag)) {
return m;
}
stack.pop();
} else {
stack.push(tag);
}
return "<" + close + tag + ">";
});
if (stack.length) {
str = str + stack.reverse().map(function(tag) {
return "</" + tag + ">";
}).join("");
}
return str;
};
var text = 'test [b]blah\n\ [i]tata[/i] blah[/b] param [quote="test"]d[quote="test2"]lalsd[li]fnsdf[alalsdfsda[/quote] qweqweqwe [u]ter[u]t[/quote]et[/u]er[/u] hjf [u]sdhg[/u] end';
alert(parseBB(text));
//Убрал атрибуты, сменил quote на s //Да, тут терпимо, но: у [/s] - концовка осталась (ошибки в закрывашках критичны - цитата - тег <div> убила бы страницу)
var text2 = 'test [b]blah\n\ [i]tata[/i] blah[/b] param [s]d[s]lalsd[li]fnsdf[alalsdfsda[/s] qweqweqwe [u]ter[u]t[/s]et[/u]er[/u] hjf [u]sdhg[/u] end';
alert(parseBB(text2))
Вдобавок у меня, при парсе на лету, когда юзер не закончил строку, желателен максимальный распарс тегов
//Тут ксать у мну и таблицы еще есть, пока не додумал как парсить исключения-ошибки отсутствия некоторых тегов)
Последний раз редактировалось Deff, 07.01.2016 в 04:23.
|
|
07.01.2016, 03:23
|
Профессор
|
|
Регистрация: 12.04.2010
Сообщений: 557
|
|
Сообщение от Deff
|
1. Решена проблема пересекающихся(или неполных) тегов
|
У меня тоже решена, правда, на скорую руку примитивным способом, но тут можно допилить работу со стеком, и сделать по нормальному, не меняя общий подход. Не получится только игнорировать открывающий тег, для которого нет закрывашки, т.к. нет заглядывания вперед.
Сообщение от Deff
|
2. Задача по топику была делать не рекурсией(кушает много памяти при длинных строках с много тегами), а простым повтором через while
|
В моём случае всё делается за один replace. Т.е. по затратам памяти имеем только исходную строку и результат.
----
На форумах бывает тег оформления исходного кода, в котором теги [b] и т.п. вообще не заменяются. Твой способ сумеет такое поддержать? Мой - запросто, если при нахождении такого тега включать специальный режим "незамены".
|
|
07.01.2016, 03:41
|
без статуса
|
|
Регистрация: 25.05.2012
Сообщений: 8,219
|
|
Яростный Меч,
Ну идея была такая: вкладывать в тег перепарсенной "открывашки" атрибут data-исходник в котором прописывать исходный код полного bb-teга в еncode, ибо парсятся все (а у меня есть и таблицы) если какой то тег в табле отсутствует, то нун возвращать теги в BB-код, что при JQ делается парой строк
На самом деле будут возвращаться все(до распарса в HTML), не прописанные в объекте перепарса (это на этапе самого распарса, не стал усложнять код незначимыми подробностями) Ибо у меня много кодов трансформируемых в несколько тегов и вставкой атрибутов
Вот эта функция будет браться из объекта с описанными функциями распарса по тегам
var found = find.replace(RegExp(rega,'i'), function(str,attr,content) {return '<'+tag+'>'+ content.replace(/\[/g, chang) + '</'+tag+'>'});
Последний раз редактировалось Deff, 07.01.2016 в 04:01.
|
|
|
|