Kilka słów o handyCode.
HandyCode to rozbudowany parser BBcode, którego głównymi zaletami są szybkość oraz fakt iż generuje on w pełni semantyczny kod html. Przejrzysta budowa sprawia, iż w łatwy sposób możemy dodawać własne znaczniki, zarządzać ich parametrami czy np. blokować parsowanie znaczników-dzieci. Dzięki drzewiastej strukturze bez problemu możemy określić rodziców oraz w zależności od nich wygenerować odpowiedni kod.
Standardowo klasa wyposażona jest w sporą listę znaczników:
- b - pogrubienie
- u - podkreślenie
- i - pochylenie
- color - zmiana koloru
- size - zmiana rozmiaru
- quote - cytat
- img - wklejenie obrazka
- position - zmiana pozycji
- url - umieszczenie odnośnika
- list - tworzenie listy
- li - utworzenie elementu listy(działa tylko wewnątrz [list][/list]
handyCode nie krzyżuje znaczników oraz nie parsuje znaczników niezamkniętych. Dodatkowo zatrzymuje przetwarzanie rodziców.
Aby wyświetlić kod BBcode należy go skomentować za pomocą backslasha "\".
1
[u] \[b\]pogrubienie\[/b\] [/u]
Parametry
Kolejną ciekawą rzeczą są parametry które możemy bezproblemowo wykorzystywać we własnych znacznikach. Standardowo w każdym znaczniku osłygiwanych jest pięć podstawowych parametrów: id, class, position, color oraz size. Dodatkowo znacznik może posiadać parametr główny(bez nazwy np. [url=parametrglowny]link[/url]) oraz parametry specjalne które są konwertowane bezpośrednio przez funkcję znacznika. Wartości parametrów możemy otoczyć cudzysłowem.
1
[u=parametrglowny] [b class="jedenZparametrowGlobalnych" mojwlasny="parametrSpecjalny"]pogrubienie[/b] [/u]
Rainbow - aby świat był kolorowy
Dzięki współpracy z oddzielną klasą Rainbow, która koloruje kody źródłowe różnych języków możliwe jest użycie znaczników
- handycode - umieszczenie kodu BBcode
- code - umieszczenie kodu(wersja mieszana(kod php, html, css i JavaScript) lub po prostu kod języka którego kolorowania Rainbow nie wspiera np. c#)
- php
- css
- html
- sql
- js - JavaScript
Podczas użycia trybu code(lub użycia innego trybu w niepoprawny sposób(wtedy klasa sama zmieni tryb na code)) klasa oprócz kolorowania kodu html i php odnajduje elementy css i JavaScript ukryte pomiędzy znacznikami <style></style>, <script></script> lub w parametrach style="", onmouseover="" etc.
Przykład wygenerowanego kodu:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<head>
<style type="text/css">
tag #obiekt {color:red;}
tag.klasa {font-family:'Arial', 'Tahoma', sans}
.innaklasa {background:#345;}
</style>
<title>handyCode - live demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript">
for(var i=0; i<string.length;i++)
{
alert(i + ' glupi kod dla przykladu ;) ' + string.value);
}
</script>
</head>
<body>
<p id="p1"><span class="gfx"></span><span style="color:red;">Pokaż Polskiej społeczności PHP na co Cię stać!</span></p>
<p id="p2"><span class="gfx"></span><span onclick="alert(\"AAAAA\")">Wykaż się swoją wyobraźnią...</span></p>
<p id="p3"><span class="gfx"></span><span>Przedstaw nam Swoja prace!</span></p>
<?php
$zmienna = '';
?>
</body>
Oczywiście klasa reaguje w przypadku złego kodu html. Upomina odpowiednim ostylowaniem o małych literach, cudzysłowach etc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<DIV CLASS=top>
<DIV CLASS=logo>
<IMG SRC="img/logo.gif" WIDTH=530 HEIGHT=100>
</DIV>
</DIV>
<DIV CLASS=btntop>
<A CLASS=btntop HREF="tutorial.html" TARGET="_top"> Tutorial </A>
<A CLASS=btntop HREF="tools.html" TARGET="_top"> Tools & Languages </A>
<A CLASS=btntop HREF="examples.html" TARGET="_top"> Examples </A>
<A CLASS=btntop HREF="books.html" TARGET="_top"> Books & Reference </A>
</DIV>
Tworzenie obiektu klasy
Przejdźmy do konkretów. Użycie klasy jest banalnie proste.
1
2
3
4
5
6
7
8
9
include('libs/handycode.class.php');
$sCode = ( isset($_POST['code']) ) ? $_POST['code'] : '';
$obj = new handyCode();
echo $obj -> parse( $sCode, null, 0, 1 );
Składnia funkcji parse:
parse( string code, [,string id [, bool cache [, bool rainbow]]])
- code - przekazujemy zmienną która zawiera nasz kod BB
- id - przekazujemy identyfikator cachu(ważne aby dla każdego kodu był inny)
- cache - 0 - nie twórz pamięci cache, 1 - stwórz pamięć cache
- rainbow - 0/1 - nie uaktywniaj/uaktywnij klasę Rainbow
Co zrobić gdy chcemy zadeklarować własną listę znaczników? Możliwości są dwie - przekazać odpowiednie parametry do konstruktora klasy lub stworzyć własną klasę która rozszerzy handyCode
Przekazanie parametrów do konstruktora
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
include('libs/handycode.class.php');
$tags='b|u|i|color|url';
$parametrs = Array('id', 'class', 'color');
$block = null;
$obj = new handyCode( $tags, $parametrs, $block);
Rozszerzenie klasy handyCode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
include('libs/handycode.class.php');
class BBchat extends handyCode
{
public function __construct()
{
$this -> blockChild = null;
$this -> AllowedParametrs = Array('id', 'class', 'color', 'size');
$this -> AllowedTags = 'b|u|i|color|url';
}
}
$obj = new BBchat();
Własne znaczniki
Dzięki użyciu drugiej metody możliwe jest w bardzo prosty sposób rozszerzenie listy znaczników. Dodajmy znacznik [manual].
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
include('libs/handycode.class.php');
class BBchat extends handyCode
{
protected function tag_manual( $data, $mainParam = null, $addParams = null, $styles = null, $specialParams = null )
{
if($mainParam)
{
return '<a href="http://pl.php.net/manual/pl/function.'.str_replace('_','-',$mainParam).'.php" '.$addParams.'>'.$data.'()</a>';
}
else
{
$data = str_replace('()','',$data);
return '<a href="http://pl.php.net/manual/pl/function.'.str_replace('_','-',$data).'.php" '.$addParams.'>'.$data.'()</a>';
}
}
public function __construct()
{
$this -> blockChild = null;
$this -> AllowedParametrs = Array('id', 'class', 'color', 'size');
$this -> AllowedTags = 'b|u|i|color|url|manual';
}
}
$obj = new BBchat();
Ważne jest aby metoda przetwarzająca dany znacznik miała nazwę tag_NazwaZnacznika i nie była metodą prywatną. W przeciwnym wypadu nie zostanie ona odnaleziona.
Składnia funkcji znacznika:
tag_NazwaZnacznika( string data, [,string mainParam [, string addParams [, string styles[ , array specialParams ]]]])
- data - Wnętrze znacznika, czyli to co znajduje się pomiędzy jego otwarciem a zamknięciem
- mainParam - parametr główny deklarowany za pomocą konstrukcji [NazwaZnacznika="mainParam"]...[/NazwaZnacznika]
- addParams - parametry dodatkowe takie jak id lub class. Deklarujemy je za pomocą konstrukcji [NazwaZnacznika id="mojobiekt" class="mojaklasa"]...[/NazwaZnacznika]
- styles - czasami znaczniki globalne generują kod css np. parametr color="#de2222" generuje kod color:#de2222;. Podobnie dzieje się z parametrem size oraz position. Aby nie powielać parametru style="" w znaczniku html po prostu jest przekazywana lista styli css.
- specialParams - niekiedy musimy dla wybranego znacznika użyć dodatkowych parametrów np. dla [quote] mogą to być: login="login" aby określić autora cytatu i date="data" aby przekazać datę cytatu. Dlatego też wszystkie parametry które nie są globalnie aktywne są przekazywane do poszczególnych funkcji w postaci tablicy $specialParams. Jeśli teraz chcemy dowiedzieć się czegoś na temat parametru "login" po prostu odwołujemy się do zmiennej $specialParams['login']
Relacje rodzic - dziecko
Klasa handyCode udostępnia dwa rodzaje operacji działających na zasadzie dziedziczności. Po pierwsze rodzic może zabronić dzieciom parsowania się. Po drugie dziecko może w zależności od posiadanego rodzica zwracać różne wartości.
W poniższym przykładzie dodałem dwa nowe znaczniki - [s] oraz [dziecko]. Pierwszy przekreśla swoją zawartość dodatkowo blokując wszystkie swoje dzieci aby się nie parsowały. Drugi, czyli dziecko pobiera informacje z tablicy $this -> parents na temat swoich przodków i wyświetla odpowiednie komunikaty.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class BBchat extends handyCode
{
protected function tag_s( $data, $mainParam = null, $addParams = null, $styles = null, $specialParams = null )
{
return '<span style="text-decoration: line-through; '.$styles.'"'.$addParams.'>'.$data.'</span>';
}
protected function tag_dziecko( $data, $mainParam = null, $addParams = null, $styles = null, $specialParams = null )
{
$rodzic = end($this -> parents);
$dziadek = prev($this -> parents);
if($rodzic)
return 'Moim rodzicem jest <b style="color:red">'.$rodzic.'</b>'.(($dziadek) ? ' a dziadkiem'.
' <b style="color:red">'.$dziadek.'</b>' : '').' a ja krzyczę : <i style="color:red">'.$data.'</i>';
else
return 'Czy ja jestem sierotą? :( ('.$data.')';
}
public function __construct()
{
$this -> blockChild = Array('s' => 1);
$this -> AllowedParametrs = Array('id', 'class', 'color', 'size');
$this -> AllowedTags = 's|dziecko|b|u|i|color|size|url|list|li';
}
}
Dla przykładowego wejścia:
1
2
3
4
5
[s] [b]znacznik ktory mnie otacza nie zostanie przeparsowany[/b] [/s]
[i] [b] [dziecko]Aaa[/dziecko] [/b][/i]
[u] [dziecko]Aaaaa[/dziecko] [/u]
[dziecko]Aaaaaaa[/dziecko]
Parser zwróci:
[b]znacznik ktory mnie otacza nie zostanie przeparsowany[/b]
Moim rodzicem jest b a dziadkiem i a ja krzyczę : Aaa
Moim rodzicem jest u a ja krzyczę : Aaaaa
Czy ja jestem sierotą? :( (Aaaaaaa)
Autor
Michał "SHiP" Środek
kadu: 4152790
devBlog: http://srodek.info
Licencja
Klasa jest w pełni darmowa i może być dowolnie modyfikowana i rozprowadzana. Jedynym warunkiem jest umieszczenie informacji o autorze klasy.
Biblioteka jest darmowa dlatego autor nie ponosi żadnej odpowiedzialności za jakiekolwiek skutki spowodowane złym użytkowaniem(szczególnie wersji pochodnych) oraz nie udziela żadnej gwarancji/pomocy technicznej itp.