Как в php конвертировать BB коды в HTML. Php BB коды Корректный bb login php

Если Вы создавали форум или создавали возможность комментирования на сайте, то, вполне вероятно, что Вы сталкивались с BB-кодами . На всякий случай, BB-коды - это набор тегов, похожих на HTML-теги , которые созданы для редактирования внешнего вида сообщения. Например, [b] , Google , http://сайт/img.jpg - это всё различные BB-коды . И вот задача программиста состоит в том, чтобы преобразовать BB-коды в HTML-код . Вот парсингом BB-кода и превращением его в HTML-код , мы и займёмся в этой статье.

Сразу привожу код этого скрипта, а точнее функции, которая принимает текст с BB-кодами , а возвращает уже HTML-код :

protected function replaceBBCode($text_post) {
$str_search = array(
"#\\\n#is",
"#\(.+?)\[\/b\]#is",
"#\(.+?)\[\/i\]#is",
"#\(.+?)\[\/u\]#is",
"#\(.+?)\[\/code\]#is",
"#\(.+?)\[\/quote\]#is",
"#\(.+?)\[\/url\]#is",
"#\(.+?)\[\/url\]#is",
"#\(.+?)\[\/img\]#is",
"#\(.+?)\[\/size\]#is",
"#\(.+?)\[\/color\]#is",
"#\(.+?)\[\/list\]#is",
"#\(.+?)\[\/listn\]#is",
"#\[\*\](.+?)\[\/\*\]#"
);
$str_replace = array(
"
",
"\\1",
"\\1",
"\\1",
"\\1",
"

Цитата
\\1
",
"\\2",
"\\1",
"",
"\\2",
"\\2",
"",
"",
""
);
return preg_replace($str_search, $str_replace, $text_post);
}
?>

Как видите, казалось бы сложная задача элементарно решается фактически одной функцией - preg_replace() . Поэтому, когда меня спрашивают, а нужны ли эти регулярные выражения, я всегда отвечаю: "Да! ". Если бы Вы решали эту задачу обычными строковыми функциями, то кода было бы намного больше, а результат был бы, скорее всего, хуже. Единственное, что в данной функции не делается - это проверка на корректность входных данных. Ведь пользователь может не закрыть тег (случайно удалил его, например) или, например, не соблюдать вложенность тегов, да много чего ещё. На практике, такими проверками никто не занимается, а в случае "кривого " сообщения, его правят вручную (обычно дефектность сразу видна).

У меня периодически появляется потребность в использовании «интерпретатора» BBCode в своих проектах (написанного на PHP), и постоянно нет времени искать какое-то более-менее удобоваримое решение, что в итоге выливается в использование или создание «костылей» для каждого конкретного случая.
Но вот, похоже, получилось найти то, что хотелось.

Моя претензия к подобным готовым решениям обычно в первую очередь заключается в неспособности этих библиотек правильно обрабатывать абзацы. Фактически они обычно вообще не используют абзацы (тэг P ), вместо этого в результате своей работы они просто вставляют тег
, заменяя обычные символы переноса строки. Я считаю такой метод эмулирования абзацев в 98 процентах, мягко говоря, не уместным. Но так как перенос строк по средствам
намного легче реализовать вместо «человеческих»

, так большинство и делает 🙁 Некоторые даже придумывают оправдания, что мол с br даже правильнее, отчасти, из-за подобной лени разработчиков различных готовых библиотек, другая часть людей думает, что тэг P является устаревшим (ведь даже во многих готовых продуктах и сайтах абзацы формируются путем использования
) 🙂

Приступим

Но, кажется, есть свет в конце туннеля. Это готовый класс для работы с BBCode , который, судя по всему, отлично справляется со своей задачей (ничего лучше пока не видел). Единственный минус в том, что документация, представленная на сайте , не на русском языке. Этот минус я и хочу побороть в этой статье, приведя пример использования класса с русскими комментариями.

Для начала нужно скачать библиотеку (на момент написания статьи версия библиотеки была 0.3.3). В скачанном архиве в папке src вы обнаружите два нужных нам файла: stringparser.class.php и stringparser_bbcode.class.php.

Для примера предположим, что у нас есть пустой файл «index.php» и рядом с ним мы создадим папку «/bbcode/», содержащую в себе два упомянутых выше файла.
Для примера минимальное содержимое файла «index.php» должно быть таким (запустив этот пример можно будет сразу увидеть, работает ли библиотека):

< ?php //Вставляем файл библиотеки require_once "bbcode/stringparser_bbcode.class.php"; //Создаем объект класса StringParser_BBCode $bbcode = new StringParser_BBCode (); //Добавляем объекту класса понятие о тэге [b] //(в итоге только этот тэг и будет //обрабатываться этим классом) $bbcode->addCode ("b", "simple_replace", null, array ("start_tag" => "", "end_tag" => ""), "inline", array ("block", "inline"), array ()); //Обрабатываем тестовую строку и выводим ее в браузер echo $bbcode->parse ("Тестовый текст, это слово должно быть [b]жирным"); ?>

Функция addCode

Наибольший интерес в этом коде может вызвать, пожалуй, функция addCode у объекта класса StringParser_BBCode, вот ее прототип и список описание параметров:

Void addCode (string $code, string $type, string $callback, string $params, string $content_type, array $allowed_in, array $not_allowed_in);

Эта функция добавляет понятие о тех или иных кодах (bb-кодах) для объекта класса, чтоб он мог потом обнаружить эти коды в тексте и соответствующим образом обработать их. Т.е. можно сказать, что изначально объект класса StringParser_BBCode вообще ничего не знает о стандартных bb-кодах и не способен обработать как-либо их. Поэтому этот объект нужно будет после каждой инициализации «обучать» всем разновидностям bb-кодов.

$code (в примере имеет значение ‘b’) Код, который нужно искать в тексте для обработки. Т.е. если указать код test , то потом в обрабатываемом тексте будет искаться тэг и обрабатываться в соответствии с указаниями в других параметрах рассматриваемой функции. $type (в примере имеет значение ‘simple_replace’) Указание того, как тэг должен обрабатываться (какого он типа). Есть различные предопределенные типы тэгов, которые будут описаны ниже. В нашем же примере указан тип ‘simple_replace’ который указывает на то, что тэг будет парным (открывающийся тэг [b] и закрывающийся ) и что эти тэги будут заменены на указанные ниже html тэги. $callback (в примере имеет значение null) Позволяет указать имя функции, которая должна будет вызваться при обработке найденного тэга в тексте. В случае с типом тэга ‘simple_replace’ такая функция не вызывается, и, соответственно, в этом параметре можно указать null. $params (в примере имеет значение array(‘start_tag’ => ‘‘, ‘end_tag’ => ‘ ‘)) В этом параметре в основном указывается, какой нужно вставлять html тэг взамен bb тэга. Наименование параметров напрямую зависит от того, какой тип тэга мы указали в параметре $type. $content_type (в примере имеет значение ‘inline’) Тип внутреннего содержимого тега. Может принимать значения: ‘inline’, ‘block’, ‘link’, ‘image’. Если я не ошибаюсь, можно прописывать и свои типы чтобы потом можно было указывать для этого содержимого свои индивидуальные фильтры (пример использования фильтров смотрите ниже). $allowed_in (в примере имеет значение array (‘block’, ‘inline’)) В этом параметре можно указать, внутри каких типов объектов может находиться создаваемый bb-код (его обработка будет просто игнорироваться в ином случае). В нашем примере мы указали, что элемент может находиться как внутри блочных элементов, так и внутри линейных. $not_allowed_in (в примере имеет значение array ()) Имеет назначение, противоположное по смыслу предыдущему параметру.

Виды обработки тэгов

Описание вариантов значения параметра $type в функции addCode.

‘simple_replace’ Описывает простой парный тэг. При использовании этого типа обработки тэга в параметре функции ‘params’ должны обязательно присутствовать две ячейки: $params[‘start_tag’] и $params[‘end_tag’]. ‘start_tag’ должен в себе содержать аналог открывающегося тэга в хтмл, а ‘end_tag’ – закрывающегося тэга соответственно. ‘simple_replace_single’ То же самое, что ‘simple_replace’, но используется только лишь для одинарных тэгов, которые, собственно говоря, не имеют содержимого (типа br, hr и т.п.). Требует наличия только параметра $params[‘start_tag’]. ‘callback_replace’ При этом типе вы перекладываете на себя обработку по найденным совпадениям (с помощью своей callback функции) для парного тэга. ‘callback_replace_single’ То же самое, что и ‘callback_replace’, но только для одинарных тэгов. ‘usecontent’ То же самое что и ‘callback_replace’, только в содержимом такого тэга другие тэги не будут обрабатываться, например, это удобно для тэга code. ‘usecontent?’ Этот тип может себя вести как ‘usecontent’ или же как ‘callback_replace’ в зависимости от ситуации. Актуальность того или иного варианта определяется за счет присутствия заранее предполагаемого атрибута в bb тэге. Если атрибут найден, то будет использоваться обработка ‘callback_replace’, в другом случае тэг будет обрабатываться как ‘usecontent’. Имя атрибута для поиска указывается через параметр $params[‘usecontent_param’]. Если указано имя default, то подразумевается значение атрибута, присвоенное непосредственно тэгу, например, , значением атрибута default будет текст «http://link». Этот прием часто используется, например, для тэга . Этот тэг может использоваться в двух формах: http://www.example.com/ и Текст ссылки, а так же [b]жирный текст. В первом случае будет использоваться тип ‘usecontent’, т.к. текст ссылки должен выводиться без какого-либо форматирования (и, собственно, сама ссылка будет некорректна, если в ней будут посторонние символы). В другом случае должен быть использован тип ‘callback_replace’, т.к. сама ссылка передается отдельным параметром, а текст, обрамленный в ссылку, вполне может содержать в себе какое-то форматирование.
Примечание: Можно указать несколько параметров для их поиска, для чего в $params[‘usecontent_param’] нужно передать не строку, а массив, содержащий строки. Например: $bbcode->addCode (…, array(‘usecontent_param’ => array (‘parameter1’, ‘parameter2’)), …);. ‘callback_replace?’ Является противоположным вариантом типа ‘usecontent?’. Если один из атрибутов, указанных в usecontent_param, встречается в тэге, он будет обработан как ‘usecontent’, в противном случае как ‘callback_replace’.

Пример кода из «боевых» условий

Вот пример файла index.php с более расширенной конфигурацией класса для обрабатывания большего числа тэгов, в нем же и можно понять, как работают callback функции и т.п.:

< ?php //Вставляем файл библиотеки require_once "bbcode/stringparser_bbcode.class.php"; //Приводит разнообразные переводы строк //разных операционных систем в единый формат (\n) function convertlinebreaks ($text) { return preg_replace ("/\015\012|\015|\012/", "\n", $text); } //Удалить все символы, кроме переводов строк function bbcode_stripcontents ($text) { return preg_replace ("/[^\n]/", "", $text); } //Функция для обработки ссылок function do_bbcode_url ($action, $attributes, $content, $params, $node_object) { if (!isset ($attributes["default"])) { $url = $content; $text = htmlspecialchars ($content); } else { $url = $attributes["default"]; $text = $content; } //Часть функции, которая занимается //только валидацией данных тэга if ($action == "validate") { if (substr ($url, 0, 5) == "data:" || substr ($url, 0, 5) == "file:" || substr ($url, 0, 11) == "javascript:" || substr ($url, 0, 4) == "jar:") { return false; } return true; } //Непосредственное преобразование тэга в //html вариант с возвращением результата return "".$text.""; } // Функция для вставки изображений function do_bbcode_img ($action, $attributes, $content, $params, $node_object) { //Часть функции, которая занимается //только валидацией данных тэга if ($action == "validate") { if (substr ($content, 0, 5) == "data:" || substr ($content, 0, 5) == "file:" || substr ($content, 0, 11) == "javascript:" || substr ($content, 0, 4) == "jar:") { return false; } return true; } //Непосредственное преобразование тэга в //html вариант с возвращением результата return ""; } //Создаем объект класса StringParser_BBCode $bbcode = new StringParser_BBCode(); //Добавляем фильтр (подробнее см. офф. документацию), //задействуя нашу функцию convertlinebreaks, которая будет //преобразовывать переводы строки в тексте к единому $bbcode->addFilter (STRINGPARSER_FILTER_PRE, "convertlinebreaks"); //Добавляем свои парсеры для разных типов объектов //(подробнее см. офф. документацию) //Мы указываем, через какую функцию должно пройти //содержимое этих тэгов, например, через функцию //htmlspecialchars для предотвращения XSS и т.д. $bbcode->addParser (array ("block", "inline", "link", "listitem"), "htmlspecialchars"); $bbcode->addParser (array ("block", "inline", "link", "listitem"), "nl2br"); $bbcode->addParser ("list", "bbcode_stripcontents"); //Добавляем bb-код , используемый в виде: //Текст заголовка первого уровня $bbcode->addCode ("h1", "simple_replace", null, array ("start_tag" => "

", "end_tag" => "

"), "block", array ("listitem", "block", "link"), array ()); //Добавляем bb-код , используемый в виде: //Текст заголовка второго уровня $bbcode->addCode ("h2", "simple_replace", null, array ("start_tag" => "

", "end_tag" => "

"), "block", array ("listitem", "block", "link"), array ()); //Добавляем bb-код , используемый в виде: //Текст заголовка третьего уровня $bbcode->addCode ("h3", "simple_replace", null, array ("start_tag" => "

", "end_tag" => "

"), "block", array ("listitem", "block", "link"), array ()); //Добавляем bb-код , используемый в виде: //Текст заголовка четвертого уровня $bbcode->addCode ("h4", "simple_replace", null, array ("start_tag" => "

", "end_tag" => "

"), "block", array ("listitem", "block", "link"), array ()); //Добавляем bb-код , используемый в виде: //Текст заголовка пятого уровня $bbcode->addCode ("h5", "simple_replace", null, array ("start_tag" => "
", "end_tag" => "
"), "block", array ("listitem", "block", "link"), array ()); //Добавляем bb-код , используемый в виде: //Текст заголовка шестого уровня $bbcode->addCode ("h6", "simple_replace", null, array ("start_tag" => "
", "end_tag" => "
"), "block", array ("listitem", "block", "link"), array ()); //Устанавливаем флаги для bb-кодов с h1 до h6, //указывая, что они являются блочными элементами, //что будет в дальнейшем благотворно влиять на умную //генерацию html кода. Такой элемент, к примеру, не сможет //находиться внутри других блочных элементов $bbcode->setCodeFlag("h1", "paragraph_type", BBCODE_PARAGRAPH_BLOCK_ELEMENT); $bbcode->setCodeFlag("h2", "paragraph_type", BBCODE_PARAGRAPH_BLOCK_ELEMENT); $bbcode->setCodeFlag("h3", "paragraph_type", BBCODE_PARAGRAPH_BLOCK_ELEMENT); $bbcode->setCodeFlag("h4", "paragraph_type", BBCODE_PARAGRAPH_BLOCK_ELEMENT); $bbcode->setCodeFlag("h5", "paragraph_type", BBCODE_PARAGRAPH_BLOCK_ELEMENT); $bbcode->setCodeFlag("h6", "paragraph_type", BBCODE_PARAGRAPH_BLOCK_ELEMENT); //Добавляем bb-код [b], используемый в виде: //[b]выделенный текст $bbcode->addCode ("b", "simple_replace", null, array ("start_tag" => "", "end_tag" => ""), "inline", array ("listitem", "block", "inline", "link"), array ()); //Добавляем bb-код [i], используемый в виде: //[i]наклонный текст $bbcode->addCode ("i", "simple_replace", null, array ("start_tag" => "", "end_tag" => ""), "inline", array ("listitem", "block", "inline", "link"), array ()); //Добавляем bb-код , используемый в виде: //http://www.needsite.domain и //Текст ссылки $bbcode->addCode ("url", "usecontent?", "do_bbcode_url", array ("usecontent_param" => "default"), "link", array ("listitem", "block", "inline"), array ("link")); //Добавляем bb-код , используемый в виде: //http://www.needsite.domain $bbcode->addCode ("link", "callback_replace_single", "do_bbcode_url", array (), "link", array ("listitem", "block", "inline"), array ("link")); //Добавляем bb-код , используемый в виде: //http://www.needsite.domain/img.jpg $bbcode->addCode ("img", "usecontent", "do_bbcode_img", array (), "image", array ("listitem", "block", "inline", "link"), array ()); //Добавляем bb-код (по смыслу то же самое, //что и ), используемый в виде: //http://www.needsite.domain/img.jpg $bbcode->addCode ("bild", "usecontent", "do_bbcode_img", array (), "image", array ("listitem", "block", "inline", "link"), array ()); //Создаем группу image из bb-кодов img и bild //для последующей возможности задания //неких правил для этих групп $bbcode->setOccurrenceType ("img", "image"); $bbcode->setOccurrenceType ("bild", "image"); //Указываем, что тэги из группы image //могут встречаться (обрабатываться) в тексте не более //двух раз. В нашем случае это нужно для того, //чтобы пользователь не мог вставить более двух //картинок в текст сообщения $bbcode->setMaxOccurrences ("image", 2); //Добавляем bb-код $bbcode->addCode ("list", "simple_replace", null, array ("start_tag" => "
    ", "end_tag" => "
"), "list", array ("block", "listitem"), array ()); //Добавляем bb-код [*], указывая, что этот тэг //может использоваться только внутри тэга //с типом list (этот тип мы присвоили выше тэгу ) $bbcode->addCode ("*", "simple_replace", null, array ("start_tag" => "
  • ", "end_tag" => "
  • "), "listitem", array ("list"), array ()); //Устанавливаем флаги для тэгов и [*] //Указываем, что для кода [*] закрывающийся тэг //не обязателен, таким образом, возможна будет //следующая конструкция: // //[*] Item //[*] Item // //Закрывающий тэг будет добавляться автоматически //в процессе формирования html кода $bbcode->setCodeFlag ("*", "closetag", BBCODE_CLOSETAG_OPTIONAL); //Как я понял, этот флаг обозначает, что тэг [*] //всегда может быть использован только //в начале новой строки $bbcode->setCodeFlag ("*", "paragraphs", true); // является блочным элементом $bbcode->setCodeFlag ("list", "paragraph_type", BBCODE_PARAGRAPH_BLOCK_ELEMENT); //Перед открывающимся тэгом //символ строки будет устранен $bbcode->setCodeFlag ("list", "opentag.before.newline", BBCODE_NEWLINE_DROP); //Перед закрывающимся тэгом //символ строки будет устранен $bbcode->setCodeFlag ("list", "closetag.before.newline", BBCODE_NEWLINE_DROP); //В итоге мы можем использовать списки в bb-коде, //используя вместе теги list и *: // //[*] Элемент списка //[*] Элемент списка //[*] и т.д. // //Активируем обработку параграфов $bbcode->setRootParagraphHandling (true); //Как я понял, таким образом указывается, //какими символами нужно заменять встреченный //перенос строки внутри абзаца //(по сути, как обрабатывать пустые абзацы). $bbcode->setParagraphHandlingParameters ("\n", ""); $res_text = "Тестовый текст [b]для проверки работы класса"; //На всякий случай удаляем все оставшиеся //символы переноса строки в виде "\r", //если такие остались в тексте $res_text = str_replace("\r", "", $res_text); //Вуаля! echo $bbcode->parse($res_text);

    Послесловие

    Я, конечно же, не сделал полный перевод документации, а только самый необходимый минимум, за более подробной документацией вы можете обратиться на официальный сайт (вообще, там описано куда больше различных возможностей).

    Эту библиотеку также не составляет труда внедрить в какой-либо php фреймворк, я, к примеру, с успехом проделывал это для cackePHP.

    Если вы тоже встречали подобные библиотеки (корректно работающие с абзацам! 🙂) , интересно было бы узнать о них.

    .
    Активное обсуждение вопросов, связанных с xBB можно найти на
    форумах PHP Club .

    XBB может быть использован в гостевых книгах, форумах, на досках объявлений и т.п. На сайте http://www.pc.uz поддержка BBCode в пользовательских комментариях реализована с помощью xBB. Данная документация целиком сверстана в BBCode и конвертирована в XHTML с помощью xBB.

    Парсер реализован несколько отлично от аналогов. Обычно такие парсеры реализуются с помощью регулярных выражений. Этот же использует метод конечных автоматов. Имеет следующий плюс: как бы ни была богата и продвинута коллекция тегов, поддерживаемая в данной реализации, скорость обработки текстов будет постоянной , так как осуществляется за фиксированное число проходов. Коллекцию поддерживаемых тегов можно увеличивать до бесконечности, а скрипт будет выполняться одинаково быстро. Скорость его работы зависит только от величины текста и от числа тегов, используемых в конкретном тексте, но не от числа всех возможных тегов и вариантов их написания. Скрипт не парсит текст многократно для каждого тега или варианта написания тега.

    XBB версии 0.29 поддерживает 134 тега, "автоматические ссылки", 100 смайлов. Коллекция тегов и смайлов легко расширяема.

    Теги имеют следующие особенности:

    1. Названия тегов и атрибутов не зависят от регистра. Например, [ font = Arial size = +1 ] , [ FONT = Arial SIZE = +1 ] и [ FoNt = Arial SiZe = +1 ] - равнозначно.
    2. Значения атрибутов могут быть закавычены "так" и "так", либо никак не закавычены. Следующие конструкции равнозначны: [ google = " BBCode " ] , [ google = " BBCode " ] , [ google = BBCode ] . Следующие конструкции НЕ равнозначны: [ google = " Поддержка BBCode " ] , [ google = Поддержка BBCode ] . Последний вариант будет интерпретирован скриптом как [ google = " Поддержка " bbcode = " " ] .
    3. Теги могут быть вложенными. Но те из них, которые создают элементы блочного типа (такие как [ h1 ] или [ table ] ), не могут быть вложены в строчные теги (такие как [ i ] или [ color ] ). Строчные элементы закрываются, если начинается блочный. Эти ограничения обусловлены требованиями W3C.
    4. Теги должны быть правильно вложены. Неправильный код " [ b ] [ i ] текст[ / b ] [ / i ] " будет интерпретирован скриптом как " [ b ] [ i ] текст[ / i ] [ / b ] ". Это ограничение также обусловлено требованием W3C.
    5. В данной реализации BBCode поддерживаются закрывающие теги вида [ / ] . Такой тег закрывает последний незакрытый тег. Например, [ b ] текст[ / b ] равнозначно [ b ] текст[ / ] . Тем не менее рекомендую пользоваться именно первой формой написания. Тогда, в случае нагромождения вложенных тегов, вам будет легче ориентроваться в коде. Кроме того, первая форма написания позволяет скрипту более корректно обрабатывать пользовательские ошибки.
    6. Поддерживается закрытие тега способом [тег /] . Например, конструкции [ url name = top ] [ / url ] и [ url name = top / ] равнозначны.
    7. В некоторых случаях можно не писать закрывающий тег. Например, тег [ tr ] (строка таблицы), будет автоматически закрыт, как только встретится очередной [ tr ] или закрывающий тег [ / table ] . Тег [ hr ] вообще не имеет закрывающего, интерпретируется скриптом как [ hr / ] . О поведении конкретных тегов смотрите их описания .
    8. При конвертации ББКода в HTML сохраняется форматирование пробелами. Т.е. все двойные пробелы переводятся в " " , все переводы строк заменяются на "
      "
      . Однако вокруг некоторых элементов (таких как [ h1 ] ) игнорируются 1-2 перевода строк, так как эти элементы сами по себе создают дополнительные отступы. Это сделано для того, чтобы по возможности приблизить визуальное представление HTML к исходному ББкоду.
    xBB поддерживает мнемонизацию специальных символов. Например, чтобы вывести на печать [b] без преобразования в HTML, можно ввести @l; b@r; . Поддерживаются мнемоники следующих спецсимволов:
    1. Открывающая квадратная скобка "[ " может быть мнемонизирована как "@l; " .
    2. Закрывающая квадратная скобка "] " может быть мнемонизирована как "@r; " .
    3. Двойная кавычка "" " может быть мнемонизирована как "@q; " .
    4. Одинарная кавычка "" " (апостроф) может быть мнемонизирована как "@a; " .
    5. Знак собачки "@ " может быть мнемонизирован как "@at; " .
    Поддержка "автоматических ссылок" означает, что строки вида "http://какойто_uri", "https://какойто_uri", "ftp://какойто_uri", "svn://какойто_uri" и т.п., а также "www.какойто_uri" и "ящик@домен" автоматически конвертируются в соответствующие гиперссылки. Этого не происходит для содержимого таких тегов как [ code ] , [ nobb ] и аналогичных. Автоматические ссылки могут быть отключены. Как это делается - смотрите раздел API .

    Теги, поддержка которых реализована в xBB по умолчанию, перечислены в разделе "Список тегов" .

    О том, как создать свой тег или переопределить существующий, читайте на странице "Как создать тег" .

    Благодарности

    Должен выразить глубокую признательность людям, помогавшим мне в работе над библиотекой, и людям, чьим трудом я воспользовался при создании библиотеки:
    • Большое спасибо разработчикам редактора TinyMCE из Moxiecode Systems AB . Я использовал их идеи для переделки тулбара в xBBEditor-е для xBB версии 0.29. А также заимствовал несколько кнопок.
    • Дмитрий Котеров (http://dklab.ru) - разработчик библиотеки JsHttpRequest, которую я использовал в xBBEditor-е для xBB версии 0.28.
    • Александр Пальчиков (ZigFreeD) - специально для xBB написал код JavaScript для редактирования BBCode в textarea. Этот код был использован в xBBEditor-е. Отдельное спасибо за активное тестирование и исправление найденных багов.

      79 комментариев

      Последние десять комментариев:

      Гость Александр
      Здравствуйте. не могу никак разобраться как добавить свой тег. Ткните пожалуйста пальцем, если не сложно, что и куда надо дописать, чтобы обрабатывался тег

      Принцип его работы такой:

      Нужно заменить на:

      • А на:


    >

    Php начинающим

    Иногда нам хочется добавить изюминку к нашим скриптам, сохранять в базе сообщения от пользователей не только в простом текстовом формате, но и давать им возможность форматировать свои сообщения как текст html. Здесь и нужны так называемые BB коды. То есть, это придуманные нами парные теги, которые при использовании нами будут преобразовываться в html теги.

    BB код Преобразование Описание
    [ b] что-то здесь [ /b] что-то здесь жирный текст
    [ i] что-то здесь [ /i] что-то здесь наклонный текст
    [ u] что-то здесь [ /u] что-то здесь подчеркнутый текст
    [ q] что-то здесь [ /q]

    что-то здесь
    выделенная цитата
    [ list ] что-то здесь[ /list]
    • что-то здесь
    не нумерованный список
    [ listn] что-то здесь [ /listn]
    1. что-то здесь
    нумерованный список
    (url)что-то здесь (/url) что-то здесь Url ссылка

    Ранее в разделе Php база , мы научились с Вами сохранять данные в таком формате, чтобы он не причинил вреда при выводе его из базы в html текст, теперь будем добавлять BB коды, а потом их преобразовывать в html. Пользователю, которого мы лишили html форматирования, теперь становится интереснее. Но, как обычно, в любом начинании есть проблемы.
    Одна из проблем в том, что пользователь может забыть закрыть тег, или, ещё хуже, какой-нибудь нехороший пользователь специально захочет Вам навредить. Так вот, как найти парные теги в сообщении полученном из формы, которое пользователь послал в Гостевую книгу или в Форум? Дело в том, что если у Вас простая Гостевая, это не требуется, но если есть BB коды, это становится актуально, ведь потом эти парные теги мы будем заменять на их html эквиваленты:

    К примеру:
    [ b] что-то здесь [ /b] , посланное пользователем, преобразуется в
    что-то здесь , в этих BB кодах

    Теперь представьте, что пользователь по ошибке или специально открыл только один тег
    [ b] что-то здесь, а закрыть тег не захотел, то получится:
    что-то здесь, а закрыть тег не захотел, то получится

    То есть, надо проверять парность тегов:
    - убирать в начале текста закрывающийся тег [ /b] ;
    - убирать в конце текста открывающийся тег [ b] ;
    - убирать пустые парные теги [ b] [ /b] ;
    - убирать повторяющиеся теги [ b] [ b] или [ /b] [ /b] ;

    Создадим такую функцию и посмотрим как она работает:

    # функция, которая убирает мусор в парных тегах
    function Teg ($on e ,$teg ,$to o ,$path ){
    $on = preg_quote ($on e ,"~");
    $to = preg_quote ($to o ,"~");
    $saerch1 = preg_quote ($on e ,"~") . $teg . preg_quote ($to o ,"~");
    $saerch2 = preg_quote ($on e ,"~") . "/" . $teg . preg_quote ($to o ,"~");
    $path = preg_replace ("~ +~"," ",$path );
    $path = trim ($path );
    $path = preg_replace ("~(".$saerch1 ." ?".$saerch1 .")+~", $on e .$teg .$to o , $path );
    $path = preg_replace ("~(".$saerch2 ." ?".$saerch2 .")+~", $on e ."/".$teg .$to o , $path );
    $path = preg_replace ("~ˆ( *".$saerch2 .")*~","",$path );
    $path = preg_replace ("~(".$saerch1 ." *)*$~","",$path );
    $_search = "~".$saerch1 ."(.+)".$saerch2 ."~U";
    $search = array ();
    if ( preg_match_all ($_search , $path , $array , PREG_PATTERN_ORDER)){
    while ( list (, $val ) = each ($array [ 0] )){
    $content = "~" . preg_quote ($val ,"~") . "~U";
    if (!empty ($search [ 0] )){ if ($content ==$search [ 0] ){ continue ;} }
    if (@array_search ($content ,$search )){ continue ; }
    $search = $content ;
    $pp = preg_replace ("~".$on ."[ /] ?".$teg .$to ."~","",$val );
    if (!preg_match ("~[ a-zA-Z0-9а-яА-Я_] ~",$pp )){ $pp = " "; }
    else { $pp = $on e .$teg .$to o .$pp .$on e ."/".$teg .$to o ; }
    $replace = $pp ;
    }
    $search = "~0~e";
    $replace = "0";
    $path = preg_replace ($search , $replace , $path );
    $path = preg_replace ("~ +~"," ",$path );
    $path = preg_replace ("~".$on ."([ /] ?)".$teg .$to ." ?".$on ."\\1".$teg .$to ."~s", $on e ."\\1".$teg .$to o , $path );
    }
    if (!preg_match ($_search , $path )){ $path = preg_replace ("~".$on ."[ /] ?".$teg .$to ."~", "", $path ); }
    return $path ;
    }

    # строка с плохими парными тегами
    $string = " [ /b] [ /b] [ /b] [ b] Проб[ b] у[ b] [ b] ем [ /b] Обм[ b] ан[ b] уть [ b] Програ [ /b] [ /b] [ /b] мму [ b] [ b] [ b] ";
    echo $string ."\n

    ";

    # применим функцию по сбору мусора
    # в ней четыре аргумента: первые три показывают
    # какой тег проверяем, а последний где проверяем
    $string = Teg ("[ ","b","] ",$string );
    echo $string ;


    В итоге работы программы получим:

    [ /b] [ /b] [ /b] [ b] Проб[ b] у[ b] [ b] ем [ /b] Обм[ b] ан[ b] уть [ b] Програ [ /b] [ /b] [ /b] мму [ b] [ b] [ b]

    [ b] Пробуем [ /b] Обм[ b] ануть Програ [ /b] мму

    То есть, в базу, при таком подходе мы запишем только парные теги. Вы скажете зачем всё это надо, но одно дело когда, например не закрылся тег [ b] , ещё пол беды (весь тест далее будет выделен жирным шрифтом), и совсем другое когда не закрылся [ q] , который мы будем преобразовывать в начало таблицы



    во первых: нахрена?
    во вторых: [ _/b] это не тег, это bb-код, и навредить он не может.

    в результате текст " [ _/b] 1[ _b] 2[ _b] 3[ _/b] 4[ _/b] " превратиться в " [ _/b] 1 2[ _b] 3 4[ _/b] " , т.е. нежелательные bb-коды будут частью текста (они не будут превращены в теги).








    (представляете, что будет на странице при выводе такого не закрытого тега).

    То есть, теперь подведем итог:
    Пользователь послал сообщение $message , которое мы будем записывать в базу, как убрать html дескрипторы из сообщения мы знаем (раздел Php база) , теперь оставим парные и уберем пустые теги BB кодов:

    // оставим парные и уберем пустые теги
    $message = Teg (" [ " ," b" ," ] " ,$message );
    $message = Teg (" [ " ," i" ," ] " ,$message );
    $message = Teg (" [ " ," u" ," ] " ,$message );
    $message = Teg (" [ " ," q" ," ] " ,$message );
    $message = Teg (" [ " ," list" ," ] " ,$message );
    $message = Teg (" [ " ," listn" ," ] " ,$message );
    $message = Teg (" (" ," url" ," )" ,$message );
    // записываем сообщение в базу
    $fp = fopen (" Base.dat" ," a" );
    fputs ($fp ," $message \n" );
    fclose ($fp );
    ?>

    При таком подходе, мы оставляем мало шансов злоумышленнику навредить нам, и даем дополнительные возможности добросовестному пользователю по использованию html разметки в своих сообщениях.

    cncvn
    полная хрень! можно сделать проще. нужно заменять bb-коды не по одному, а парами. ищем текст между парным bb-кодом и заменяем соответствующей комбинацией. а плохие bb-коды пускай так и остаются bb-кодами.
    Warning: preg_replace () [ function.preg-replace] : Compilation failed: nothing to repeat at offset 0 in D:\Program files\VertrigoServ\www\studline\function\teg.php on line 12
    sd dsdas bb fff

    если вести такую строку то будет
    sd dsdas bb fff

    1 тег не закрыт - ошибочка

    и ешё выдаёт Notice на 19 строке - Offset...

    если ввести коды

    [ _b] [ _s] [ _/s] [ _/b]

    то на самом деле генерится такое:

    Искала подобную статью по всему инету, а нашла как всегда у вас. Спасибо! %tashus%

    Ответ:

    Отличная статья как раз то, что было нужно, чтобы закончить делать сайт.

    Ответ:

    # декодирование биби-кодов
    function bbcode($sourse ){

    $bb = " #\[ b\] (.*?)\[ /b\] #si" ;
    $html = " \\1" ;
    $bb = " #\[ i\] (.*?)\[ /i\] #si" ;
    $html = " \\1" ;
    $bb = " #\[ u\] (.*?)\[ /u\] #si" ;
    $html = " \\1" ;
    $bb = " #\[ s\] (.*?)\[ /s\] #si" ;
    $html = " \\1" ;
    $bb = " #\[ li\] #si" ;
    $html = "

  • " ;
    $bb = " #\[ hr\] #si" ;
    $html = "
    " ;

    $sourse = preg_replace ($bb , $html , $sourse );
    return $sourse ;
    }

    давно не спал, удалил нужное))) вот рабочий пример

    Ответ: Да, неплохо, но у тебя нет проверки на наличие двойных тегов, да просто по ошибке кто - то введёт неправильно и что???

  • Не работает скрипт:(На седьмой строке все зацикливается.

    Ответ: Согласен, была ошибка, исправил

    Страница: 1
    Текущая страница: 1 Всего сообщений: 9