Форумы 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

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

Первая | 1 | 2
15.05.2009 13:39:53 #
Iceweasel dima
Проголосовал.
11.06.2009 04:37:07 #
Mozilla Firefox Гость morozovsk
vlad, чтобы всё быстро работало в базе нужна хранить не бб-код, а хтмл, а при редактировании пользователем своего сообщения (что происходит в сотни раз реже чем просмотры этого сообщения), конвертировать его обратно из хтмл в бб-текст, тогда у вас будет самый быстрый форум на свете Well
11.06.2009 13:36:52 #
Iceweasel dima
Лучше всего хранить исходный BBCode вместе со сгенерированным HTML. Тогда все будет быстро и удобно.
 
А преобразовывать HTML в BBCode нехорошо, так как такое преобразование неоднозначно и пользователь вправе возмутиться, почему BBCode, который он сохранял, стал другим, для этого пользователя неудобным.
16.06.2009 06:35:29 #
Mozilla Firefox Vlad
К слову, у каждого способа есть свои преимущества и недостатки. Какой способ лучше решает исключительно разработчик в рамках своего проекта. Я же выбрал наиболее практичный, на мой взгляд, способ из известных мне на тот момент.
 
dima, вам спасибо за голос Well
16.06.2009 10:59:05 #
Iceweasel dima
Я же выбрал наиболее практичный, на мой взгляд, способ из известных мне на тот момент.

Имеется в виду способ хранения? Какой, если не секрет?
16.06.2009 12:08:22 #
Mozilla Firefox Vlad
dima
Имеется в виду способ хранения? Какой, если не секрет?
В базу заносится текст прямо из формы, т.е. каким его видит пользователь, а обрабатывается уже на выводе из базы. Правки, которые я вношу в код, сразу отражаются на всех постах. В случае же использования одного из способов, изложенных выше, придется либо вручную править посты, либо ждать, пока их отредактирует сам пользователь.
morozovsk, сомнительная "выгода" Well Пока ваш способ нигде не увидел.
16.06.2009 12:46:31 #
Iceweasel dima
Я тоже не стал особо заморачиваться. Храню в базе исходный BBCode. При выводе преобразую его в HTML и кеширую. В случае редактирования, кеш очищается.
17.06.2009 17:48:57 #
Mozilla Firefox Гость morozovsk
Vlad
morozovsk, сомнительная "выгода" Well Пока ваш способ нигде не увидел.
мой способ реализуется в системе ucoz, а на ней построено ну очень много сайтов
24.07.2019 02:21:38 #
Google Chrome Гость quarkgold
Интересоваться девочками неплохо -  https://prostitutkispb78.org...devyatkino/ - проститутки с Девяткино сделают процесс максимально простым
21.08.2019 06:38:47 #
Google Chrome Гость полд
ролд

Для того, чтобы вставить цитату со страницы, выделите
Perl

        do {
      i--;   
         data = EEPROM_READ(i);
//    EEPROM_WRITE(i,0xFF);
    if ( data != 0xFF ) { break; }
 
    } while ( i > 0 );
   
      return i;
     
 }
 
Первая | 1 | 2

Ответить:

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

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

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

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