Форумы xBB

Форумы xBB > Вебразработка

Альтернативный обработчик BB-Code

Автор: Гость Vlad. Последнее редактирование: 2009-04-12 04:09:59

PHP
/*
Теги BB-Code
 
Способы замены:
both - заменяет один из параметров другим в случае, если тот не указан (например, [url]http://example.com[/url] равносильно [url="http://example.com"]http://example.com[/url]).
simple - единственный принимаемый параметр, это тело тега. Остальные игнорируются.
strictly - все параметры остаются как есть.
 
Имя тега всегда в нижнем регистре!
*/

define('CHECKING_URL', '^(https?|ftp)://[^\s"\']+$');
 
$config['bb-tags']=array(
        'url' => array(
                'type' => 'tag',
                'replace-method' => 'both',
                'format' => '<a href="%s">%s</a>',
                'secure-check' => CHECKING_URL
        ),
        'a' => array(
                'type' => 'alias',
                'model' => 'url'
        ),
        'link' => array(
                'type' => 'alias',
                'model' => 'url'
        ),
        'b' => array(
                'type' => 'tag',
                'replace-method' => 'simple',
                'format' => "<b>%2\$s</b>",
                'secure-check' => ''
        ),
        'strong' => array(
                'type' => 'alias',
                'model' => 'b'
        ),
        'bold' => array(
                'type' => 'alias',
                'model' => 'b'
        ),
        'i' => array(
                'type' => 'tag',
                'replace-method' => 'simple',
                'format' => "<i>%2\$s</i>",
                'secure-check' => ''
        ),
        'italic' => array(
                'type' => 'alias',
                'model' => 'i'
        ),
        'quote' => array(
                'type' => 'tag',
                'replace-method' => 'strictly',
                'format' => "<blockquote>%s писал(а):<br><i>%s</i></blockquote>",
                'secure-check' => '[-\wа-я ]*'
        ),
        'color' => array(
                'type' => 'tag',
                'name' => 'color',
                'replace-method' => 'strictly',
                'format' => "<font style=\"color:%s\">%s</font>",
                'secure-check' => '[-\#0-9a-z]{3,15}'
        ),
        'img' => array(
                'type' => 'tag',
                'replace-method' => 'both',
                'format' => '<img src="%s">',
                'secure-check' => CHECKING_URL
        ),
        'image' => array(
                'type' => 'alias',
                'model' => 'img'
        ),
        'align' => array(
                'type' => 'tag',
                'replace-method' => 'strictly',
                'format' => "<div align=\"%s\">%s</div>",
                'secure-check' => '(center|left|right|justify)'
        ),
        'center' => array(
                'type' => 'tag',
                'replace-method' => 'simple',
                'format' => "<div align=\"center\">%2\$s</div>",
                'secure-check' => ''
        ),
        'left' => array(
                'type' => 'tag',
                'replace-method' => 'simple',
                'format' => "<div align=\"left\">%2\$s</div>",
                'secure-check' => ''
        ),
        'right' => array(
                'type' => 'tag',
                'replace-method' => 'simple',
                'format' => "<div align=\"right\">%2\$s</div>",
                'secure-check' => ''
        ),
        'justify' => array(
                'type' => 'tag',
                'replace-method' => 'simple',
                'format' => "<div align=\"justify\">%2\$s</div>",
                'secure-check' => ''
        ),
);
 

class protect
{
static $bbspecialchars=array(
        '[' => '@lsqrt@;',
        ']' => '@rsqrt@;'
);
static $bbspch_decode=array(
        '@lsqrt@;' => '[',
        '@rsqrt@;' => ']'
);
 
 private function _parsebbc($three)
 {
 global $config;
        if (preg_match('#\[(\w+)(\s*=[^\[\]]+)?\](.*)\[/(\\1)?\]#mi', $three, $arg, PREG_OFFSET_CAPTURE))
        {
                list(, $tag, $argument, $body, $closer)=$arg;
                $tag=strtolower($tag[0]);
                $closer[0]=strtolower($closer[0]);
                $len=(function_exists('mb_strlen')) ? mb_strlen($arg[0][0], 'cp1251') : strlen($arg[0][0]);
                        if ($tag=='nobb')
                                return protect::_parsebbc(substr_replace($three, strtr($body[0], protect::$bbspecialchars), $arg[0][1], $len));
                        if (isset($config['bb-tags'][$tag]))
                        {
                                $curtag=($config['bb-tags'][$tag]['type']=='alias') ? $config['bb-tags'][$config['bb-tags'][$tag]['model']] : $config['bb-tags'][$tag];
                                $arg2=trim(html_entity_decode($argument[0])," \t\v\n\0\r'\"=");
                                switch ($curtag['replace-method'])
                                {
                                        case 'both':
                                        if (empty($arg2)) $arg2=html_entity_decode($body[0]);
                                        elseif (empty($body[0])) $body[0]=htmlspecialchars($arg2);
                                        case 'strictly':
                                        if (preg_match('#'.$curtag['secure-check'].'#i', $arg2))
                                                return protect::_parsebbc(substr_replace($three, sprintf($curtag['format'], $arg2, $body[0]), $arg[0][1], $len));
                                        break;
                                        case 'simple':
                                        if (preg_match('#'.$curtag['secure-check'].'#i', $body[0]))
                                                return protect::_parsebbc(substr_replace($three, sprintf($curtag['format'], $arg2, $body[0]), $arg[0][1], $len));
                                }
                        }
                $context=protect::$bbspecialchars['['] . $tag . $argument[0] . protect::$bbspecialchars[']'] . $body[0] . protect::$bbspecialchars['['] . '/' . $closer[0] . protect::$bbspecialchars[']'];
                return protect::_parsebbc(substr_replace($three, $context, $arg[0][1], $len));
        }
        return strtr($three, protect::$bbspch_decode);
 }
 function filter($text,$enablebb=false)
 {
 $text=nl2br($text);
 $text=preg_replace('#\s(https?|ftp)://[^\s\"]+#i', '<a href="$0">$0</a>', $text); // Quick links / Быстрые ссылки
 if ($enablebb) return protect::_parsebbc($text);
 return $text;
 }
 

Этот код не претендует на титул xBB, т.к. он гораздо менее функционален и рассчитан на пряморуких программистов-лентяев. Упор делается на скорость и лаконичность кода. Пряморукому кодеру не составит труда добавить поддержку смайлов и других своих фич.
 
P.S. Иногда неадекватно себя ведет автозакрытие тега, например когда два тега находятся рядом:
[b]dolor[/] [i]sit[/]
Наверное это подразумевает такой вывод:
dolor sit
но парсер так не считает, и выводит по своему:
dolor[_/] [_i]sit

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

12.04.2009 04:22:23 #
Opera Гость Vlad
Ах да, самое главное:
function protect::filter(string text, [bool обрабатывать_теги_или_нет])
12.04.2009 12:19:31 #
Iceweasel dima
Добавил в новости.
12.04.2009 19:17:37 #
Opera Гость Vlad
Не буду зафлуживать топик бесконечными попытками, лучше выложу в виде архива:
bbcode.inc.zip
 
P.S. Сотрите пожалуйста верхние посты.
13.04.2009 00:36:43 #
Iceweasel dima
Стер. Ограничение на длину коммента = 2000B.
 
Чтобы иметь возможность редактировать комменты, надо зарегистрироваться.
13.04.2009 16:52:43 #
Opera Гость Vlad
dima
Ограничение на длину коммента = 2000B.
Дмитрий, обрезать комменты - плохая практика. Правильнее и вежливее по отношению к пользователю было бы сообщение об ошибке, мол, так и так, вы превысили дупустимую длину в N байт.
 
Думаю, если мой парсер будет интересен, выложу на sourceforge.
25.04.2009 18:38:34 #
Opera Гость Vlad
Теперь сама библитотека + маленький пример доступны здесь: BBLib Project.
Спасибо всем тем, кто находит мою библиотеку сколь-нибудь полезной. Not precisely
27.04.2009 13:00:27 #
Iceweasel dima
Здорово. Well
14.05.2009 16:16:42 #
Opera Vlad
BBLib

Голосуйте Well
14.05.2009 18:49:56 #
Iceweasel dima
Не думаю, что такой специализированной вещи, как BBCode, что-то светит на подобных конкурсах. Возможно ли где нибудь увидеть текущие результаты голосований?
14.05.2009 22:47:56 #
Opera Vlad
dima
Возможно ли где нибудь увидеть текущие результаты голосований?
Похоже, что нет.
dima
Не думаю, что такой специализированной вещи, как BBCode, что-то светит на подобных конкурсах.
И я на победу сильно не рассчитываю Well Участие мое в конкурсе чисто символическое, ради собственного интереса.

Ответить:

Представиться как     Антибот:
   

Просьба не постить мусор. Пользуйтесь кнопкой предварительного просмотра на панели инструментов редактора.

Введите логин: и пароль: (

© 2007-2017, Дмитрий Скоробогатов.
Разрешается воспроизводить, распространять и/или изменять материалы сайта
в соответствии с условиями GNU Free Documentation License,
версии 1.2 или любой более поздней версии, опубликованной FSF,
если только иное не указано в самих материалах.