Toon posts:

[PHP/regex] HTML code highlighten

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik wil een (HTML) code highlighter bouwen, denk hierbij aan iets als de PHP functie highlight_string. Deze functie is imho zwaar achterhaald. Ik wil graag zelf iets dergelijks maken, maar dan dus uitgebreider (denk hierbij aan kleuren in kunnen stellen met CSS, geldige XHTML code ipv de zwaar achterhaalde < font > tags, etc).

Om bij het begin te beginnen, ik heb nu een regular expression
PHP:
1
$pattern = "/(<\/?)([A-z][A-z0-9])*( *[A-z]+(=\".*\")?)* *\/?>/";

waarmee ik tags uit een stuk HTML code kan halen.
Nu komt echter het tricky punt: ik wil < span > tags om de HTML tags heenzetten, die ik dus vervolgens een kleurtje kan geven. Als ik echter dit doe:
PHP:
1
2
3
$pattern = "/(<\/?)([A-z][A-z0-9])*( *[A-z]+(=\".*\")?)* *\/?>/";
$replace = "<span>$0</span>";
$new = preg_replace($pattern, $replace, $code);

Heb ik een probleem, de span tags staan nu in dezelfde string als de HTML code, terwijl ik wil dat de HTML code op mijn scherm verschijnt, en de toegevoegde tags niet 8)7

Ik kan natuurlijk werken met htmlspecialchars(), en die zal ik ook wel nodig hebben, maar hoe kan ik ervoor zorgen dat ik toch met deze regular expression kan werken? Om je special chars al in je pattern string te gebruiken zuigt namelijk nogal

Bij voorbaat dank :)

  • Ericston
  • Registratie: Maart 2001
  • Laatst online: 05-08 18:36
Zo?
PHP:
1
2
3
$pattern = '/(<)(\/?)([A-z0-9].*?)>/';
$replace = '<span class="$3">&lt;$2$3&gt;</span>';
$new = preg_replace($pattern, $replace, $code);
Dan kan je dit doen.
code:
1
2
3
4
5
6
7
8
<style type="text/css">
<!--
span.html { color:red }
span.head { color:green }
span.title { color:purple }
span.body { color:yellow }
-->
</style>

Pwetty colours.

Verwijderd

Topicstarter
Ericston schreef op 22 oktober 2002 @ 22:33:
PHP:
1
2
3
$pattern = '/(<)(\/?)([A-z0-9].*?)(>)/';
$replace = '<span>&lt;$2$3&gt;</span>';
$new = preg_replace($pattern, $replace, $code);
dat is inderdaad een oplossing ja, maar het komt in feite neer op wat ik zei: het zuigt ;)
Als ik nog een paar van die expressions heb, en die komen er, moet ik overal de originele karakters weer gaan vervangen door entities, en ik moet zeggen dat ik mijn tijd beter kan besteden ;)
Op deze manier die expressions schrijven kost gewoon meer denkwerk.

Dus nogmaals mijn vraag: hoe zou ik dit kunnen doen zonder entities te hoeven vervangen in mijn pattern dan wel replacement string?

Ericston, uiteraard bedankt voor je reply :)

edit:
Ik zie je edit nu, dat is wel een handige toevoeging moet ik zeggen B)

  • Ericston
  • Registratie: Maart 2001
  • Laatst online: 05-08 18:36
Verwijderd schreef op 22 oktober 2002 @ 22:46:
[...]
Dus nogmaals mijn vraag: hoe zou ik dit kunnen doen zonder entities te hoeven vervangen in mijn pattern dan wel replacement string?
[...]
Ben bang van niet.(*) Je zal uiteindelijk toch die <'s en >'s moeten replacen met < en >. Als je dat niet in of voor je regexen doet gaat het helemaal niet lukken.

Je kan natuurlijk net voor de output een regex hebben die alle html tekentjes filtert als ze tussen span tags staan (eventueel met een speciaal id attribute op jouw spans om ze te onderscheiden van spans uit de te highlighten code).

(*) Uiteraard denk ik er niet hard genoeg over na. ;)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

highlighten kun je beter niet met een replace doen, maar door te matchen. Je krijgt dan een array van elementen terug die je kunt doorlopen, en dan kun je overal je tags omheen zetten en de elementen zelf escapen mbv htmlspecialchars ()

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

Op verzoek van FoOL even een korte beschrijving van wat .oisyn mogelijk bedoelt :D

Werkwijze:
  1. Loop de string door dmv van een while loop, totdat de te highliten string "" is of de strlen() ervan 0 is
  2. Match elke iteratie van de loop het begin van de string met een aantal regexen die speciale tekens, of speciale tekenreeksen voorstellen. Het begin van de string match je met de '^' anchor
  3. Wanneer er een match is, snij het begin van de highlighten string af, met substr(), ter lengte van de match
  4. Highlight deze substring, en voeg hem toe aan een "output" string
  5. Wanneer er geen match wordt gemaakt, zou het begin van de string gematched moeten worden "totaan" het gedeelte wat wel weer gematched wordt op een speciaal karakter of tekenreeks, en dit gedeelte moet dan als default voor de huidige context worden gehilite.
  6. Geef eventueel in de loop aan (wanneer een bepaalde match is geweest, bijvoorbeeld '<?') in wat voor context je je bevindt, zodat je wel de juiste highlighting op de juiste characters kunt doen. Dit kun je het best op een stack doen, zodat, wanneer een bepaalde context weer afgelopen is, je terugvalt in de oude context.
  7. Verder zou je kunnen bepalen welke contexten wel en niet in elkaar voor mogen komen, of, beter gezegd, contexten die in bepaalde contexten voorkomen hoeven niet gehilite te worden.
Ik zie vast honderd dingen over het hoofd, maar ik heb ff geen tijd 't uit te werken...

En natuurlijk is het aan .oisyn om dit verhaal af te branden :D

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz


  • Banpei
  • Registratie: Juli 2001
  • Laatst online: 28-08 10:35
Aanrader: de preg_match_callback gebruiken zodat je voor verschillende doeleinden verschillende functies kan gebruiken.

  • Defspace
  • Registratie: Mei 2000
  • Laatst online: 27-08 11:17

Defspace

Administrator

Bedoel je zoiets ?

PHP:
1
2
3
4
$pattern = '/(<)(\/?)([A-z0-9].*?)>/';
$dummyrep = '<$2$3>';
$dummy = htmlspecialchars(preg_replace($pattern, $dummyrep, $code));
$new = "<span>$dummy</span>";

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

drm schreef op 24 oktober 2002 @ 14:22:
Op verzoek van FoOL even een korte beschrijving van wat .oisyn mogelijk bedoelt :D

Werkwijze:

[.. een lijst met stappen wat ik echt totaal niet bedoelde ..]

En natuurlijk is het aan .oisyn om dit verhaal af te branden :D


consider it done ;)

Wat ik bedoel is, matchen met preg_match_all (). Die geeft een 2-dimensionale array terug met alle gematchte elementen erin
voorbeeld: je wilt alle x'en highlighten in een bepaalde string.
De string is xxxyyyyyxxyyyxxxyyyyyxxyyy
Je matcht op "(x+)(y+)"

PHP:
1
2
3
$pattern = ("/(x+)(y+)/";
$string = "xxxyyyyyxxyyyxxxyyyyyxxyyy";
preg_match_all ($pattern, $string, $matches, PREG_SET_ORDER);


$matches is nu een 2-dimensionale array, waarin alle matches staan.
$matches[0] is de eerste match, $matches[1] is de 2e match, enz.

in $matches[x][0] staat de hele substring die gematcht is, en daarna komen de afzondenlijke elementen (dus in $matches[x][1] staat wat gematched is door "(x+)" en in $matches[x][2] staat wat gematched is door "(y+)")

bovenstaand voorbeeld levert de volgende array op:
code:
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
    [0] => Array
        (
            [0] => xxxyyyyy
            [1] => xxx
            [2] => yyyyy
        )

    [1] => Array
        (
            [0] => xxyyy
            [1] => xx
            [2] => yyy
        )

    [2] => Array
        (
            [0] => xxxyyyyy
            [1] => xxx
            [2] => yyyyy
        )

    [3] => Array
        (
            [0] => xxyyy
            [1] => xx
            [2] => yyy
        )


dus je loopt alle matches door, en je highlight alle x delen, en je plakt de y-delen eraan vast:

PHP:
1
2
3
4
5
6
$html = "":
foreach ($matches as $match)
{
    $html .= "<span>" . htmlspecialchars ($match[1]) . "</span>";
    $html .= htmlspecialchars ($match[2]);
}



Maar op de manier van banpei kun je het natuurlijk ook doen :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MisterData
  • Registratie: September 2001
  • Laatst online: 26-08 21:52
Ik heb een stackbased parser gemaakt voor templates, en dat zou je ook perfect kunnen ombouwen naar een highlighter natuurlijk :) Kijk maar eens op http://geemz.dyndns.org/cms/include/tpltest.php en let vooral op de boom die eronder verschijnt als je wat bbcode probeert in te voeren :)

  • packman
  • Registratie: November 2000
  • Laatst online: 17-12-2024
MisterData schreef op 24 oktober 2002 @ 19:29:
Ik heb een stackbased parser gemaakt voor templates, en dat zou je ook perfect kunnen ombouwen naar een highlighter natuurlijk :) Kijk maar eens op http://geemz.dyndns.org/cms/include/tpltest.php en let vooral op de boom die eronder verschijnt als je wat bbcode probeert in te voeren :)
Ik heb ook net zoiets geschreven, maar dan wel recursief (komt uiteindelijk op hetzelfde neer) - maar dan met "pluginnable" tag-renderers - je kan per "tag" een functie toewijzen om hem te renderen, en deze zal dan de text tussen de tags behandelen. Elke tag kan ook een parameter accepten (in de vorm van [tag=parameter]text in tag[/tag]) Code wordt wel eens vrijgegeven eens ze een beetje opgecleand is, en ik de auto-codefixing eindelijk implementeer ;) Ik ben hieraan begonnen omdat ik regex in code niet echt proper vind - en ook niet echt flexibel.. Op commandline of in editor regex gebruiken - ok - maar in code - bah... :p

En met zo'n parser als dit kan je idd mooi highlighten :)

I heard if you play the XP CD backwards, you get a satanic message. Thats nothing compared to what happens if you play it forward, then it installs Windows XP born2oc.be - Facts Of Life


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

MisterData schreef op 24 oktober 2002 @ 19:29:
Ik heb een stackbased parser gemaakt voor templates, en dat zou je ook perfect kunnen ombouwen naar een highlighter natuurlijk :) Kijk maar eens op http://geemz.dyndns.org/cms/include/tpltest.php en let vooral op de boom die eronder verschijnt als je wat bbcode probeert in te voeren :)
highlighten doe je over het algemeen met lexical analysers, niet met parsers, aangezien het niet nuttig is om een syntaxtree op te bouwen, en dus ook te controleren op syntax errors. Dit moet imho ook goed gehighlight worden:
text <i> italic <b> bolditalic </i> bold </i>

technisch gezien is dit misschien niet juiste (x)html, maar het zou wel fijn zijn als het goed highlight. Dat geldt ook voor niet-afgesloten tags en dergelijke.

Ik heb voor React een php module gemaakt die de code tussen codetags moet gaan highlighten. Er is tot nu toe alleen nog support voor C, C++ en Java, maar het is relatief simpel om andere talen toe te voegen. Deze highlighters zijn eigenlijk gewoon lexical analysers, die de keywords en identifiers eruit vissen en die een ander kleurtje geven (gemaakt met flex, dat c-code genereert). (Deze module zit ingebouwd in de volgende versie, 1.7, waar GoT binnenkort op over gaat). Parsers waren hier niet de juiste keuze geweest, aangezien het niet de bedoeling is dat de parser het niet meer snapt omdat degene die een code-tag plaatst verkeerde code gebruikt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

ik meende dat dat kon met de PHP plugin

;)

edit:
PHP:
1
2
3
4
5
<?php
$HTML = new html_highlight();
$string = $HTML->highlight ($string);
echo $string;
?>


zoiets was het..

[ Voor 0% gewijzigd door drm op 25-10-2002 08:55 ]


Verwijderd

Afbeeldingslocatie: http://images.tweakers.net/forum/templates/got/images/icons/edit.gif :? ;)

[ Voor 0% gewijzigd door drm op 25-10-2002 08:55 ]


  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06-2025

drm

f0pc0dert

.oisyn schreef op 25 oktober 2002 @ 03:43:highlighten doe je over het algemeen met lexical analysers, niet met parsers, aangezien het niet nuttig is om een syntaxtree op te bouwen, en dus ook te controleren op syntax errors. Dit moet imho ook goed gehighlight worden:
text <i> italic <b> bolditalic </i> bold </i>
Overigens zou het niet gek zijn als een highlighter nesting errors e.d. wel een ander kleurtje geeft. (#f00 ofzo ;))

Dus dan is misschien niet zo gek om toch op een stack bij te houden of 't allemaal wel juiste code is :?

[ Voor 0% gewijzigd door drm op 25-10-2002 08:58 . Reden: HTML |:( ]

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz

Pagina: 1