Chciałbym zaprezentować w tym wpisie krótką i prostą funkcję, która bywa bardzo użyteczna i jest wykorzystywana praktycznie w każdym moim projekcie.
Zgodnie z zasadami typografi, spójnik czy jedno-znakowy wyraz nie powinien być nigdy na końcu linii, lecz musi zostać przeniesiony do nowego wiersza/nowej linii.
Problem niby jest błahy i niezbyt istotny, jednak niektórzy są bardzo przewrażliwieni na punkcie poprawnej gramatyki, zwłaszcza w ojczystym języku. Poniżej zaprezentowana funkcja powinna rozwiązywać ten problem.
Kod źródłowy i opis działania
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | /** * Upiększacz tekstu * zadaniem funkcji jest poprawienie tekstu na zgodny z zasadami języka polskiego * * @param string $text tekst do poprawy * @param string $encoding użyte kodowanie, domyślnie UTF-8 * @return string poprawiony tekst * * @authors Kamil Brenk <kontakt@kamilbrenk.pl>, Michal Wachowski * @license GPL * @link http://blog.kamilbrenk.pl/gramatyka-w-php-czesc-1/ */ function repairText($text, $encoding = 'UTF-8') { // poczatek tekstu jest poczatkiem zdania $uc_first = true; // --- ustalamy znacznik kropki wykorzystywany przy adresach email i WWW $dotItem = '#dot#'; $dashItem = '#dash#'; // konwertuj znaki specjalne do encji HTML $text = htmlspecialchars($text, ENT_NOQUOTES); // wywal podwójne i niepotrzebne spacje // wywal nadmiar wykrzykników, pytajników, przecinków, dwukropków, średników $text = preg_replace('/([?]){0,}([!]){0,}([,:;]){0,}([ ]){1,}/', '$1$2$3$4', $text); // --- zamieniamy kropki i myslniki na ustalone znaczniki w adresach e-mail, by reszta skryptu nie poprawila ich jako konce zdania itp. $text = preg_replace('/([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text); // --- zamieniamy kropki i myslniki na ustalone znaczniki w WWW, by reszta skryptu nie poprawila ich jako konce zdania itp. $text = preg_replace('/([A-Z0-9._%-]+\.[A-Z0-9.-]+\.[A-Z]{2,4}[A-Z0-9._%-\/?&=]*)/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text); // popraw zapis kropki i przecinka na prawidłowy w zdaniu // np. "wyraz. Wyraz", "wyraz, wyraz" // --- zmienilem zapis by rozróżniał wielokropek // --- pozbyłem się niepotrzebnych nawiasów () i {} // dodana poprawa: wykrzyknik, pytajnik, dwukropek, średnik $text = preg_replace('/(\pL+)[ ]*([.]{1,3}|[,;:]{1}|[!?]{1,2})[ ]*(\pL?)/', '$1$2 $3', $text); // popraw zapis myślnika na prawidłowy w zdaniu // np. "miasto - Bydgoszcz, państwo - Polska" // --- dodałem obsługę myślnika, wcześniej był tylko minus // --- jak wyżej - pozbyłem się niepotrzebnych nawiasów () i {} $text = preg_replace('/(\pL+)[ ]*-|–[ ]*(\pL?)/', '$1 - $2', $text); // stwórz z tekstu tablicę - każdy wyraz jako nowy rekord $text = explode(' ', trim($text)); // przejdź przez tablicę wyrazów i popraw tekst foreach ($text as &$val) { // jeśli zaczynasz nowe zdanie - pisz wielką literą if ($uc_first) { // nowe zdanie rozpocznij wielką literą // --- dodałem parametr $encoding $val[0] = mb_strtoupper($val[0], $encoding); // koniec pierwszego wyrazu zdania $uc_first = false; } // jeśli wyraz zawiera kropkę - kończy zdanie // oznacz, że zaczyna się nowe zdanie // --- dodałem parametr $encoding // zdanie rozpoczynaj także po pytajniku i wykrzykniku if ( mb_strpos($val, '.', 0, $encoding) !== false || mb_strpos($val, '!', 0, $encoding) !== false || mb_strpos($val, '?', 0, $encoding) !== false ) { $uc_first = true; } // jeśli długość wyrazu równa sie 1 - dodaj za nim twardą spację // jeśli wyraz jest kropką lub przecinkiem - pomiń // --- dodałem parametr encoding if (mb_strlen($val, $encoding) === 1) { $val = $val . ' '; } // niecodzienny przypadek, można pominąć // np. "wynik wynosi 2." // --- dodałem obsługę encoding if ( (mb_strlen($val, $encoding) === 2) && (($val[1] === ',') || ($val[1] === '.') || ($val[1] === '!')) ) { $val = $val . ' '; } } // ponownie połącz tekst $text = implode(' ', $text); // wywal normalne spacje po "twardych" spacjach // --- odmieniamy znaczniki kropki i myslnika w adresach e-mail i WWW na kropki i myslniki // zamień ?! na !? $text = str_replace( array(' ', '?!', $dotItem, $dashItem), array(' ', '!?', '.', '-'), $text); // zwróć poprawiony tekst // --- kasujemy spacje z poczatku i konca tekstu, tak dla pewnosci // usuwamy twarde spacje z końca tekstu - niepotrzebne return trim($text, ' '); } |
Krótko opiszę zadania, które wykonuje powyższa funkcja.
- wywala niepotrzebne spacje – dopuszczalne są tylko pojedyncze spacje
- poprawa zapisu kropki i przecinku na prawidłowy, np. „wyraz. Wyraz”, „wyraz, wyraz”
- poprawa zapisu znaku myślnika, np. „miasto – Bydgoszcz, państwo – Polska”
- rozpoczynanie zdania wielką literą
- dodanie „twardych” spacji do jednoznakowych wyrazów i spójników
- dodanie „twardych” spacji do dwuznakowych wyrazów, jeśli jeden ze znaków jest przecinkiem, myślnikiem lub kropką
- usunięcie zbędnych spacji przed i za tekstem
- zamiana błędnego zapisu ?! na !?
- redukcja zbędnych wykrzykników, pytajników i innych znaków interpunkcyjnych oraz poprawa zapisu tych znaków,
- (czekam na kolejne propozycje)
Wykorzystanie
Do tak przygotowanej funkcji wystarczy przekazać tekst, który ma zostać poprawiony. Sam z niej korzystam najczęściej przy zapisie danych wysyłanych przez użytkowników: komentarzy, artykułów i innych, jak i danych wysyłanych przez siebie w panelu administracyjnym.
Gramatyka w PHP – pokaż przykład
Podsumowanie
Funkcja nie jest zbyt optymalna i wydajna, jednak używana z rozsądkiem może okazać się całkiem przydatna. Teraz tylko wystarczy testować i wytykać błędy – zapewne takowe się znajdą. Czekam również na kolejne propozycje rozbudowy funkcji :)
O, coś co każdy może wykorzystać.
Co stanie się w sytuacji gdy ktoś wprowadzi tekst bez odstępów po przecinkach/kropkach?
(Już pomijam sens układania pojedynczych liter na początku tekstu, gdy zdania zaczynane są z małej litery)
Moja wizja funkcji:
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
$string = htmlspecialchars($string, ENT_NOQUOTES);
$sArr = preg_split('#[,. ]#s', $string, NULL, PREG_SPLIT_OFFSET_CAPTURE);
$ucFirst = true;
foreach($sArr as &$elem) {
$pos = $elem[1] + strlen($elem[0]);
$item = $string[$pos];
if($ucFirst) {
$ucFirst = false;
$elem[0] = mb_substr(mb_strtoupper($elem[0], $encoding), 0, 1, $encoding).mb_substr($elem[0], 1, mb_strlen($elem[0], $encoding), $encoding);
}
if(strlen($elem[0]) == 1) {
$elem[0] = $elem[0].' ';
}
if($item == '.') {
$ucFirst = true;
$elem[0] = $elem[0].$item;
}
if($item == ',') {
$elem[0] = $elem[0].$item;
}
$elem = $elem[0];
}
$string = implode(' ', $sArr);
$string = str_replace(array(' ', ' ,', ' .'), array(' ', ',', '.'), $string);
return $string;
}
Robi to co twoja propozycja + pierwsze słowo w zdaniu, z dużej litery, kropki i przecinki ‚przykleja’ do wcześniejszego wyrazu.
(pewnie code nie działa?)
Dziękuję Michale za uwagę, Twoja funkcja faktycznie ma kolejne, lepsze poprawianie tekstu. Choć nie do końca mi działa, tzn.
Input:
” zadaniem tego narzędzia jest upiększenie tekstu, tak by był zgodny z zasadami języka polskiego. obecnie jedyną obsługiwaną funkcją jest przeniesienie jedno-znakowego wyrazu (i, o, a) do następnego wiersza. ”
output:
” Zadaniem tego narzędzia jest upiększenie tekstu, tak by był zgodny z zasadami języka polskiego. obecnie jedyną obsługiwaną funkcją jest przeniesienie jedno-znakowego wyrazu (i, o , a) do następnego wiersza. ”
Twoja funkcja tworzy podwójne spacje za kropkami i przecinkami, przez co pierwsza litera nowego zdania nie zawsze jest pisana wielką literą („obecnie”).
Gdy tylko znajdę chwilę czasu postaram się ulepszyć funkcję, tzn.
– zaaplikować proponowane przez Ciebie zmiany,
– usuwać podwójne spacje z tekstu,
– pozostawić poprzednią funkcjonalność.
Sam blog też potrzebuje kilku poprawek i usprawnień (code w komentarzach i inne), ale to wkrótce.
Tymczasem dziękuję za komentarz :)
To co wklejałem – powstało, niejako na szybko – zainspirowane Twoim rozwiązaniem.
Osobiście nigdy nie porządkuję cudzych tekstów – pisząc niechlujnie, wystawia sam sobie wizytówkę.
Wracając do funkcji – prócz wymienionego przez Ciebie błędów, zauważyłem jeszcze jeden – jeśli w tekście jest adres – zostanie on potraktowany jak ‚połączone zdanie’… to też trzeba by poprawić.
Pisząc te funkcję – naszła mnie myśl, że prócz PHP’owej wersji – ciekawym rozwiązaniem była by wersja JS’owa.
Ok, naniosłem kilka proponowanych poprawek, rozszerzając swój przykład powyżej. Nie jest zbyt optymalnie i ładnie, trochę rozbudowana funkcja wyszła, ale trudno :)
Co do JavaScript, ok – nie byłoby ciężko przepisać. Jednak przy jakim zdarzeniu tekst miałby być poprawiany? Myślę, ze byłoby to trochę denerwujące i mylące dla użytkownika, gdyby co chwile odświeżało mu pole tekstowe, nanosząc poprawki..
Użytkownik mógłby jakimś buttonem po napisaniu ‚upiększyć’ treść, ale to takie gdybanie – praktyka uczy, że i tak nikt tego nie będzie używał :D
Wprowadzilem kilka dalszych poprawek i zagmatwań tj.:
– dodałem do mb_* parametr $encoding
– wywaliłem zbędną drugą tablicę
– dodałem wyrażenia które podmieniają kropki i myślniki w adresach WWW i e-mail – przez co nie są one ‚poprawiane’
– i kilka pomniejszych, estetycznych (na moje oko) poprawek w tym co już istnieje
Większość rzeczy pokomentowałem, moje komentarze zaczynają się od // —
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// poczatek tekstu jest poczatkiem zdania
$uc_first = true;
// --- ustalamy znacznik kropki wykorzystywany przy adresach email i WWW
$dotItem = '#dot#';
$dashItem = '#dash#';
// konwertuj znaki specjalne do encji HTML
$text = htmlspecialchars($text, ENT_NOQUOTES);
// wywal podwójne i niepotrzebne spacje
$text = preg_replace('/\s+/', ' ', $text);
// --- zamieniamy kropki i myslniki na ustalone znaczniki w adresach e-mail, by reszta skryptu nie poprawila ich jako konce zdania itp.
$text = preg_replace('/([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text);
// --- zamieniamy kropki i myslniki na ustalone znaczniki w WWW, by reszta skryptu nie poprawila ich jako konce zdania itp.
$text = preg_replace('/([A-Z0-9._%-]+\.[A-Z0-9.-]+\.[A-Z]{2,4}[A-Z0-9._%-\/?&=]+)/ie', 'str_replace(array(".", "-"), array($dotItem, $dashItem), "$1")', $text);
// popraw zapis kropki i przecinka na prawidłowy w zdaniu
// np. "wyraz. Wyraz", "wyraz, wyraz"
// --- zmienilem zapis by rozróżniał wielokropek
// --- pozbyłem się niepotrzebnych nawiasów () i {}
$text = preg_replace('/(\pL+)[ ]*([.]{1,3}|[,]{1})[ ]*(\pL?)/', '$1$2 $3', $text);
// popraw zapis myślnika na prawidłowy w zdaniu
// np. "miasto - Bydgoszcz, państwo - Polska"
// --- dodałem obsługę myślnika, wcześniej był tylko minus
// --- jak wyżej - pozbyłem się niepotrzebnych nawiasów () i {}
$text = preg_replace('/(\pL+)[ ]*-|–[ ]*(\pL?)/', '$1 - $2', $text);
// stwórz z tekstu tablicę - każdy wyraz jako nowy rekord
$text = explode(' ', trim($text));
// przejdź przez tablicę wyrazów i popraw tekst
foreach ($text as &$val) {
// jeśli zaczynasz nowe zdanie - pisz wielką literą
if ($uc_first) {
// nowe zdanie rozpocznij wielką literą
// --- dodałem parametr $encoding
$val[0] = mb_strtoupper($val[0], $encoding);
// koniec pierwszego wyrazu zdania
$uc_first = false;
}
// jeśli wyraz zawiera kropkę - kończy zdanie
// oznacz, że zaczyna się nowe zdanie
// --- dodałem parametr $encoding
if (mb_strpos($val, '.', 0, $encoding) !== false) {
$uc_first = true;
}
// jeśli długość wyrazu równa sie 1 - dodaj za nim twardą spację
// jeśli wyraz jest kropką lub przecinkiem - pomiń
// --- usunąłem nawiasy, nie są potrzebne gdy są and'y
// --- dodałem parametr encoding
if (mb_strlen($val, $encoding) === 1 && $val !== '.' && $val !== ',' && $val !== '-') {
$val = $val . ' ';
}
// niecodzienny przypadek, można pominąć
// np. "wynik wynosi 2."
// --- dodałem obsługę encoding
if ( (mb_strlen($val, $encoding) === 2) && (($val[1] === ',') || ($val[1] === '.')) ) {
$val = $val . ' ';
}
}
// ponownie połącz tekst
$text = implode(' ', $text);
// wywal normalne spacje po "twardych" spacjach
$text = str_replace(' ', ' ', $text);
// --- odmieniamy znaczniki kropki i myslnika w adresach e-mail i WWW na kropki i myslniki
$text = str_replace(array($dotItem, $dashItem), array('.', '-'), $text);
// zwróć poprawiony tekst
// --- kasujemy spacje z poczatku i konca tekstu, tak dla pewnosci
return trim($text);
}
Więcej się chyba nie da z tego wyciągnąć, kolejnym krokiem co by było? Sprawdzanie pisowni ? :)
Dziękuję Michale za pomoc, sam bym sobie nie poradził z wszystkimi powyższymi poprawkami :)
Od siebie wprowadziłem kolejne dobre usprawnienia i poprawki, lecz sama funkcja niewiele się zmieniła. Choć funkcja jest stosunkowo kompletna, można by ją nadal rozwijać, m.in. wprowadzić prawidłową obsługę cudzysłów, nawiasów. Same poprawki mogą też czasami wprowadzać zamęt, m. in. w skrótach i akronimach (np. „m. in.”, „dr.” i inne).
Powyższa funkcja może pomóc, ale może też trochę zaszkodzić :) Najlepiej chyba dać obok pola tekstowego przycisk typu „Popraw błędy i interpunkcję”, pokazać użytkownikowi proponowane zmiany – no i dać wybór zatwierdzenia lub odrzucenia poprawek :)
A proszę, proszę.
(Po dr nie stawiamy kropki :D)
Hmm, …. zamiast całych tych super fajnych skryptów można użyć funkcji: ucwords() lub ucfirst().
ucwords
Powoduje zwiększenie KAŻDEGO wyrazu w zdaniu na zaczynającego się wielką literą.
ucfirst
Powoduje zamianę TYLKO pierwszego wyrazu zdania na pisaną wielką literą.
Nie takie były założenia skryptu :-)
„zamiana błędnego zapisu ?! na !?”
Oba zapisy są poprawne.
http://so.pwn.pl/zasady.php?id=629840
Kamil, skrót „m.in.” zapisujemy bez spacji pomiędzy, a „dr” w mianowniku bez kropki (w pozostałych przypadkach z kropką).
Hehe, dziękuję za uwagę Lolzer ;)
Domyślałem się, że za daleko popłynąłem z funkcjonalnością. Początkowym założeniem było dodawanie twardych spacji w miejscach, które to wymagają – co jest bardzo fajną i przydatną funkcjonalnością (stosowaną w praktyce w kilku innych serwisach, co bardzo się sprawdza i czego brakuje mi w WordPressie).
Niestety w ramach bloga chciałem dopisywać kolejne „bajery” i powstał mały potworek, który dodatkowo nie jest zgodny z gramatyką i psuje prawidłowe zdania :D
Ja natomiast próbuję napisać coś, co usuwałoby niepotrzebne znaki np:
……………….. -> … (wiele kropek to pojedynczego wielokropka)
.. – > . (2 kropki do jednej)
??????????????? -> ? (redukcja)
!!!!!!!!!!!!!!!!!!!!!!!!!!! – ! (redukcja)
?!?!?!?!?! -> ?! (redukcja)
!?!?!?!?!?!?! -> !? (redukcja)
!!!!!!!!!!!!??!!!!!!!!!???!!!!!!!! -> !? (redukcja)
!!!!!!!!!!!!!……….?????????? -> !? (usunięcie kropek za znakami interpunkcyjnymi; redukcja znaków)
.! -> ! ale …! -> …! i ………! -> …! (przy wielokropku zostawiało bez zmian)
.. .. . -> … (likwidacja spacji między kolidującymi znakami; redukcja)
!… -> ! (usunięcie kropek/wielokropka za niektórymi znakami)
„Pytanie?”. -> „Pytanie?” (usunięcie kropki za cudzysłowem, jeśli cytowane jest pytanie. To samo z wykrzyknikiem).
„Zdanie.”. – > „Zdanie”. (usunięcie kropki w cudzysłowie, jeśli jest już jedna poza).
(Wtrącenie.) -> (Wtrącenie). (przeniesienie ostatniej kropki poza nawias).
„Zdanie.” -> „Zdanie”. (przeniesienie ostatniej kropki poza cudzysłów).
Zdanie . -> Zdanie. (usunięcie spacji przed kropką, przecinkiem, średnikiem, pytajnikiem i wykrzyknikiem).
I spacja zawsze po kropce i przecinku. Po wielokropku też, jeśli nie poprzedza znaku zapytania lub wykrzyknika.
No i wstawianie twardych spacji w oczywistych przypadkach. Przyznaję, trochę mnie przerosło i mam wrażenie, że wyszedł mi mało optymalny kod, ponieważ zabieg musi być kilka razy powtórzony w pętli, gdyż przy redukcji niektórych niepotrzebnych znaków pojawia się kolizja innych, którą ponownie trzeba poddać redukcji.
O linki i URL-e się nie boje, ponieważ są zakazane na mojej stronie.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function cleanThatShitUp($text){
$text = preg_replace('#\.{1,}\)#i', ').' ,$text); //ostatnia kropka poza nawias
$text = preg_replace('#\.{1,}"#i', '".' ,$text); //ostatnia kropka poza cudzysłów
$text = preg_replace('/\s+/', ' ', $text);
$text = preg_replace('# ([\.,\?!;])#i', '\\1' ,$text); //usuwanie spacji przed niektórymi znakami
$text = preg_replace('#([\?!;"\',])\\1{1,}#i','\\1',$text); //redukcja powtarzających się znaków
$text = preg_replace('#(\.){3,}#i','..',$text); //tutaj wyjątkowo nieeleganckie rozwiązanie - ograniczenie maksymalnej liczby kropek do 2
$text = preg_replace('#(\.\.)#i','...',$text); //...po czym następuje zamiana 2 kopek na wielokropek
$text = preg_replace('#([\?!,;])\.*#i','\\1',$text); //usuwanie kropek po znakach interpunkcyjnych
$text = preg_replace('#(\?!|!\?)*(\?|!)?#i','\\1',$text); //redukcja naprzemiennie postawionych "?" i "!"
$text = preg_replace('#([\?!,;\.])([^\p{P}\s])#i','\\1 \\2',$text); //postawienie spacji po znaku interpunkcyjnym, jeśli nie jest poprzedzony białym znakiem lub innym znakiem interpunkcyjnym
return $text;
}
echo cleanThatShitUp("WTF ??????????????!!!!!!!!!!!!!!.... lol1.....lol2 lol3.lol4 lol5..lol6 ....?!?!?!?!?!?!?........... lol7.. . ?? "lololol8." '' lol9 .. lol10................????????!!!!!!!!?!?!?!?!?!lol11 . lol12!?!?!?!");
//efektem będzie:
//WTF?! lol1... lol2 lol3. lol4 lol5... lol6...?! lol7... "lololol8". ' lol9... lol10...?! lol11. lol12!?
?>
Napisałem coś takiego bez użycia pętli. Może nie jest idealne, ale chyba radzi sobie z najbardziej hardcorowymi przypadkami. Tak myślę…
Tak poprawiony tekst można później przepuścić przez Twoją funkcję z drobnymi zmianami.
Do forum się to jednak nie nadaje – tnie bbcode i linki.
Pozdrawiam
Wykorzystałem kod Kamila i swój, trochę zmodyfikowałem (w kodzie, który podał wcześniej są błędy!) i nie tnie żadnych linków. No i funkcji bbcode należy użyć po tej funkcji, nie przed.
Prawda Lolzer, WordPress tnie mi zamienia mi niektóre znaki i robi ogólny syf. W wolnym czasie napiszę wtyczkę, która by coś z tym robiła. Niemniej jednak dziękuję za uwagę, to dobra motywacja :-)
Lolzer. jeśli powyższy skrypt zamieni Ci link
z http://www.costam
na
Www. Costam
to żebyś użył bbcode nawet dwa ni po tej funkcji to nie zmieni to faktu, że link w bbode i tak nie będzie działał.
Pozdrawiam
@lolkowski, wybacz, jednak myślałem, że ksywka lolkowski i lolzer należy do tej samej osoby :P później postaram się pomóc, na razie sesja egzaminacyjna i brak czasu.. :)
@lolkowski, napisałem, że nie tnie linków.
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
$uc_first = true;
$dotItem = '#dot#';
$dashItem = '#dash#';
$questionItem = '#quest#';
$comaItem = '#coma#';
$text = preg_replace('/([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/ie', 'str_replace(array(".", "-", "?", ","), array($dotItem, $dashItem, $questionItem, $comaItem), "$1$2 ")', $text);
$text = preg_replace('#(http[s]?://)([A-Za-z0-9_%\-\.:@]*)([A-Za-z0-9\-]+)\.([A-Za-z0-9\._%\-/\?&=:]*)([^\?!\.,;\s])#ie', 'str_replace(array(".", "-", "?", ","), array($dotItem, $dashItem, $questionItem, $comaItem), "$1$2$3.$4$5 ")', $text);
$text = preg_replace('#\.{1,}\)#i', ').' ,$text);
$text = preg_replace('#\.{1,}"#i', '".' ,$text);
$text = preg_replace('/\s+/', ' ', $text);
$text = preg_replace('# ([\.,\?!;])#i', '\\1' ,$text);
$text = preg_replace('#([\?!;"\', ])\\1{1,}#i','\\1',$text);
$text = preg_replace('#(\.){3,}#i','..',$text);
$text = preg_replace('#(\.\.)#i','...',$text);
$text = preg_replace('#([\?!,;])\.*#i','\\1',$text);
$text = preg_replace('#([^\.])(\.)([\?!,;])#i','\\1\\3',$text);
$text = preg_replace('#(\?!|!\?){1,}(\?|!)?#i','\\1',$text);
$text = preg_replace('/\s+/', ' ', $text);
$text = preg_replace('#([\?!,;\.])([^\p{P}\s])#i','\\1 \\2',$text);
$text = htmlspecialchars($text, ENT_NOQUOTES);
$text = explode(' ', trim($text));
foreach ($text as &$val) {
if ($uc_first) {
if(!ereg('(http[s]?://)([^ ])+', $val) && !ereg('([\p{P}])', $val[0]) && !ereg('([A-Za-z0-9\-_\.])@([A-Za-z0-9\-_\.)\.([A-Za-z]){2,4}', $val)){
$val[0] = mb_strtoupper($val[0]);
if($uc_first = true){
$uc_first = false;
}
}
if(ereg('(http[s]?://)([^ ]){1,}', $val) || ereg('([A-Za-z0-9\-_\.])@([A-Za-z0-9\-_\.)\.([A-Za-z]){2,4}' , $val)){
if(ereg('([\.,\?!; ])', substr($val, -1, 1))){
$i = -1;
while(ereg('([\.,\?!; ])', substr($val, $i, 1))){
$i--;
}
$i++;
$val = substr($val, 0, $i)." ".substr($val, $i, $i*(-1));
}
}
}
if (
mb_strpos($val, '.', 0, $encoding) !== false ||
mb_strpos($val, '!', 0, $encoding) !== false ||
mb_strpos($val, '?', 0, $encoding) !== false
) {
$uc_first = true;
}
if (mb_strlen($val, $encoding) === 1) {
$val = $val . ' ';
}
if ( (mb_strlen($val, $encoding) === 2) && (($val[1] === ',') || ($val[1] === '.') || ($val[1] === '!')) ) {
$val = $val . ' ';
}
}
$text = implode(' ', $text);
$text = str_replace(
array(' ', $dotItem, $dashItem, $questionItem, $comaItem),
array(' ', '.', '-', '?', ','),
$text);
return $text;
}
Komentarze usunąłem tylko w tym kodzie – u mnie na stronie zostały, ponieważ zachowałem w nich te części kodu, których użył Kamil, a mi były niepotrzebne.
Kod brzydki, ale działa. :P
Dobry tekst, przyda mi się to. Pozdrawiam autora.
„Zgodnie z zasadami gramatyki, spójnik czy jednoznakowy wyraz nie powinien być nigdy na końcu linii, lecz musi zostać przeniesiony do nowego akapitu.”
Zamieniłbym na:
„Zgodnie z zasadami typografi, spójnik czy jedno-znakowy wyraz nie powinien być nigdy na końcu linii, lecz musi zostać przeniesiony do nowego wiersza/nowej linii.”
W paru miejscach rzeczywiście przydałaby się taka funkcja, chociaż chyba lepiej po stronie klienta.
Prezentowane na tej stronie kody źródłowe można kopiować i dowolnie modyfikować?
@Wojciech Brzeziński: tak, można wykorzystywać do woli / modyfikować wg własnego uznania :) fajnie jednak wiedzieć, że ktoś/gdzieś użył mojego kodu, sama satysfakcja z tego wynikająca jest wystarczającym motywem :)
Po stronie klienta ma taką zaletę, że w przypadku popełnienia błędu w algorytmie późniejsze korekty będą łatwiejsze (możliwe) do wykonania. W przypadku przerzucenia na serwer (tak jak jest teraz) nie trzeba poprawek nanosić każdorazowo i u każdego z osobna (co może widocznie pogorszyć wydajność/płynność działania strony); można by kombinować z jakąś hybrydą, ale żeby zachować zalety obu rozwiązań najłatwiej byłoby trzymać teksty użytkowników w dwóch kolumnach (oryginalny tekst; poprawiony tekst).
Witaj. Ogólnie bardzo ciekawa no i co najważniejsze praktyczna i przydatna funkcja. Myślę jednak że warto by było dodać opcję formatowania/nieformatowania znaczników (np:
), obecnie całość stringu zawierającego jakieś znaczniki sypie się. Często dane na stronie zawierają różnego rodzaju znaczniki, i w tym momencie funkcja nie może być ze zrozumiałych względów zastosowana, a przydałaby się. Dobrym pomysłem byłoby też po dodaniu wspomnianej opcji sprawdzanie i ewentualnie domykanie błędnych znaczników (niestety jak wiadomo zdarza się to niekiedy przy ręcznym pisaniu). Pozdrawiam :-)