Piszemy parser BBCode
BBCode jest to język formatowania wiadomości internetowych, pojawiający się często na forach dyskusyjnych. Głównym założeniem tego skryptu jest ułatwienie osobie nieznającej składni HTML odpowiedniego zmodyfikowania wypowiedzi na jej potrzeby.
Jak dodać obsługę znaczników BBCode do własnej strony, forum czy też systemu komentarzy? Zajmiemy się dziś rozwiązaniem tego problemu przy pomocy wyrażeń regularnych w języku PHP.
BBCode, wyrażenia regularne
Wyrażenia regularne służą do zaawansowanego dopasowania szukanej w tekście frazy. Tym razem zaprzęgniemy je do zamiany tagów BBCode, na odpowiedni kod HTML w celu uzyskania pożądanego formatowania.
Znaczników BBCode może być kilka lub kilkadziesiąt
w zależności od implementacji jaką będzie nam dane spotkać, my skupimy się na tych podstawowych jak pogrubienie, pochylenie, podkreślenie tekstu, zmianę koloru, rozmiaru oraz tworzenie hiperłączy. Pozostałe, czy nawet swoje własne łatwo dodać bazując na tych podstawowych.
Funkcja służącą do dopasowania wyrażenie regularnego do treści jest preg_match, z kolei do zamiany treści preg_replace. Nie chcę tutaj skupiać się na tym jak wyglądają/działają wyrażenia regularne, gdyż z pewnością zajęło by to więcej czasu niż napisanie całego parsera BBCode, omówię zatem tylko ogólnie co dane wyrażenie rogi.
Pogrubienie tekstu
Zacznijmy zatem od pogrubienia tych treści które zostały opatrzone tagami [b]…[/b]:
$text = preg_replace ( '|\[b\](.*?)\[/b\]|i', '<span style="font-weight: bold;">\1</span>', $text );
Zastosowane wyrażenie regularne:
|\[b\](.*?)\[/b\]|i
…ma za zadanie odszukać wszystkie wystąpienia ciągu [b](dowolny tekst)[/b] i zamienić go na odpowiednie znaczniki HTML (zaopatrzone w styl dodający pogrubienie czcionki). Końcowy przełącznik „i”, sprawa że wielkość liter jest ignorowana, zatem nie ma znaczenia czy użyte taki BBCode będą wpisane z małej czy też dużej litery.
Zmiana koloru i rozmiaru
Jak można się domyślić, podobnie wyglądać będzie kod dla pozostałych formatowań. Przejdźmy teraz do znaczników z dodatkowym parametrem, takim jak zmiana koloru ([color=red]…[/color]) oraz rozmiaru tekstu ([size=16]…[/size]):
$text = preg_replace ( '|\[color=([a-z]+)\](.*?)\[/color\]|i', '<span style="color: \1;">\2</span>', $text ); $text = preg_replace ( '|\[size=([0-9]+)\](.*?)\[/size\]|i', '<span style="font-size: \1px;">\2</span>', $text );
Tym razem wyrażenia regularne wyłuskują 2 parametry jakimi jest rozmiar/kolor tekstu oraz właściwy fragment który należy odpowiednio sformatować.
Hiperłącza
I jedyne co pozostało to hiperłącza ([url=moja_strona.pl]…[/url]):
$text = preg_replace ( '|\[url=(http://)?(.+?)\](.*?)\[/url\]|i', '<a href="http://\2">\3</a>', $text );
Dodatkowo, powyższy fragment kodu, sprawdza czy adres został podany z czy też bez przedrostka http://, i przy jego braku dodaje go. Zapewnia to większą uniwersalność działania.
Gotowe rozwiązanie
Zbierzmy zatem wszystko w ładną całość w postaci funkcji:
function bbcode($text)
{
$patterns = array
(
'|\[b\](.*?)\[/b\]|i',
'|\[i\](.*?)\[/i\]|i',
'|\[u\](.*?)\[/u\]|i',
'|\[color=([a-z]+)\](.*?)\[/color\]|i',
'|\[size=([0-9]+)\](.*?)\[/size\]|i',
'|\[url=(http://)?(.+?)\](.*?)\[/url\]|i'
);
$replacements = array
(
'<span style="font-weight: bold;">\1</span>',
'<span style="font-style: italic;">\1</span>',
'<span style="text-decoration: underline;">\1</span>',
'<span style="color: \1;">\2</span>',
'<span style="font-size: \1px;">\2</span>',
'<a href="http://\2">\3</a>'
);
$text = str_replace("\n", '<br>', trim($text));
$text = preg_replace($patterns, $replacements, $text);
return $text;
}
Najwyższy czas na sprawdzenie jak spisuje się skonstruowana przez nas funkcja. Weźmy przykładowy tekst i przepośćmy go przez funkcję bbcode():
Lorem [b]ipsum dolor[/b] sit amet enim. [i]Etiam ullamcorper[/i]. Suspendisse a pellentesque dui, non felis. Maecenas malesuada elit lectus felis, [u]malesuada[/u] ultricies. Curabitur et ligula. Ut molestie a, ultricies porta urna. Vestibulum [color=green]commodo volutpat,[/color] a, convallis ac, laoreet enim. [size=30]P[/size]hasellus fermentum in, dolor. Pellentesque [url=bbproject.net]facilisis[/url]. Nulla imperdiet sit amet magna. Vestibulum [size=20][b][color=red]dapibus[/color][/b][/size], mauris nec [b][i][u]malesuada[/u][/i][/b] fames ac turpis velit, [size=24][url=http://www.bbproject.net]rhoncus[/url][/size] eu, luctus et interdum adipiscing wisi.
…i sprawdźmy jej wynik:
Lorem ipsum dolor sit amet enim. Etiam ullamcorper. Suspendisse a pellentesque dui, non felis.
Maecenas malesuada elit lectus felis, malesuada ultricies.
Curabitur et ligula. Ut molestie a, ultricies porta urna.
Vestibulum commodo volutpat, a, convallis ac, laoreet enim. Phasellus fermentum in, dolor.
Pellentesque facilisis. Nulla imperdiet sit amet magna.
Vestibulum dapibus, mauris nec malesuada fames ac turpis velit,
rhoncus eu, luctus et interdum adipiscing wisi.
Podsumowanie
Tym sposobem zakończyliśmy ten krótki przewodnik po BBCode i ich wykorzystaniu przy pomocy wyrażeń regularnych w PHP. Osobiście zachęcam do zgłębienia wiedzy na temat samych wyrażeń regularnych, gdyż jest to potężne narzędzie jeśli wiemy jak się nim posługiwać, a możliwości jego wykorzystania nie kończą się na PHP, gdyż wiele nowoczesnych języków również je obsługuje (czy też nawet niektóre środowiska IDE do wyszukiwania treści).
po grzyba w kolorze mogą być cyferki, jeżeli nie uwzględniłeś krzyżyka? kolory w html-u i niektórych implementacjach bbcode można zapisywać jako „#rrggbb”, ale ten parser sobie z tym nie poradzi.
Masz rację, poprawiłem. BBCode z założenia ma służyć do formatowania tekstu dla ludzi którzy nie znają HTML’a, także podawanie w hexach to jakaś pomyłka, aczkolwiek bardzo łatwo dodać taką możliwość, tak jak inne których brakuje w artykule – to tylko naprowadzenie na właściwy tor, aniżeli całkowite rozwiązanie.
Jasne, podawanie w heksach jest „złe”. Oczywiście. Na 100%.
Ale ja jednak optowałbym za heksami – a przy oknie edycji można zrobić skrypt wyświetlający różne kolorki, i od razu w zaznaczonym miejscu dodający odpowiednie tagi; bo takich kolorów zdefiniowanych przez standardy html nie ma wiele i część z nich jest brzydka.
Jeszcze nie jestem pewny, czy kolory i inne takie nie powinny być case-insensitive; jednak co do tego przypadku bardzo prawdopodobne jest że się mylę.
Ciekawy artykuł jednak użycie wyrażeń regularnych w taki sposób jak Ty to przedstawiłeś to chybiony pomysł. Po pierwsze będzie to bardzo niewydajne, szczególnie przy dużych partiach tekstu. Po drugie nie zabezpiecza Cię to przed błędnych BBCode(np. plątanie znaczników – „[b] cos tutaj [u] tutaj [/b] i tutaj[/u]”
Przykład mojej klasy: http://srodek.info/examples/handycode/
Do pobrania z http://srodek.info/files/
Pozdrawiam serdecznie