[PHP] Spaties verwijderen behalve die tussen : en ;

Pagina: 1
Acties:
  • 315 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Ik ben bezig met een script voor syntax highlighting voor CSS. Het highlight eigenlijk niet alleen de code, maar het haalt ook de originele whitespace weg en zet er overnieuw tabs en newlines tussen, zodat het uiterlijk van de code consistent is. Nu is het zo dat alle whitespace wordt verwijderd, voordat de rest wordt geparsed. Het probleem is dat niet alleen spaties zoals bij "body {color:red ; }" verwijderd worden ("body:color:red;"), maar "span{margin:20px 30px 20px 40px;}" wordt bijvoorbeeld "span{margin:20px30px20px40px;}". Dat is naast onleesbaar ook invalid code.

Ik zou hiervoor dus een regexp willen maken die alle spaties verwijdert, behalve die tussen : en ;. Ik heb al flink gezocht naar documentatie hiervoor, maar ik heb nog geen goede uitleg gevonden. Zelfs php.net kon het me niet duidelijk maken. Ik hoop dat iemand hier me een duwtje in de goede richting kan geven :)

Acties:
  • 0 Henk 'm!

  • remcotolsma
  • Registratie: December 2005
  • Laatst online: 08-09 11:11
Documentatie over Regular Expression binnen PHP is hier te vinden:
http://nl2.php.net/manual/nl/ref.regex.php
http://nl2.php.net/manual/nl/ref.pcre.php

Verder is er genoeg te vinden over reguliere expressies:
http://www.regular-expressions.info/

Hier is zelfs een hele database met kant en klare reguliere expressies:
http://regexlib.com/

Verder zijn er denk ik genoeg scripts die iets vergelijkbaars doen:
http://iceyboard.no-ip.org/showcode/code/css_compressor.php
http://csstidy.sourceforge.net/download.php

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Je kunt controleren of de spatie niet wordt voorgegaan door een dubbele punt, en niet wordt gevolgt door een puntkomma. Zoek eens op "Assertions" in de manual

Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
remcotolsma schreef op zaterdag 28 april 2007 @ 11:30:
Documentatie over Regular Expression binnen PHP is hier te vinden:
http://nl2.php.net/manual/nl/ref.regex.php
http://nl2.php.net/manual/nl/ref.pcre.php

Verder is er genoeg te vinden over reguliere expressies:
http://www.regular-expressions.info/
Ik heb aangegeven flink gezocht te hebben, maar ik kon niks vinden wat mij duidelijk kon maken hoe dit werkte.
Hier is zelfs een hele database met kant en klare reguliere expressies:
http://regexlib.com/

Verder zijn er denk ik genoeg scripts die iets vergelijkbaars doen:
http://iceyboard.no-ip.org/showcode/code/css_compressor.php
http://csstidy.sourceforge.net/download.php
Dank voor de links, maar ik wil het graag zelf kunnen :P Ik ben (nog steeds) hobbyist en het is voor mij gewoon een uitdaging die dingen te maken. Ik had al bedacht dat er vast al scripts zouden zijn, maar ik wilde het gewoon vanaf scratch maken :)
frickY schreef op zaterdag 28 april 2007 @ 11:30:
Je kunt controleren of de spatie niet wordt voorgegaan door een dubbele punt, en niet wordt gevolgt door een puntkomma. Zoek eens op "Assertions" in de manual
Ga ik eens lezen. Danku :)

Acties:
  • 0 Henk 'm!

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 07-09 11:44

Bergen

Spellingscontroleur

Ik raad aan het boek O'Reilly - Mastering Regular Expressions te downloaden kopen.

Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
Mei schreef op zaterdag 28 april 2007 @ 10:31:
Ik zou hiervoor dus een regexp willen maken die alle spaties verwijdert, behalve die tussen : en ;.
Dat geldt niet altijd, de ; is een seperator en kan dus weggelaten worden bij de laatste property.

Dit is geldige CSS:
Cascading Stylesheet:
1
2
3
4
5
#element {
  text-align: center;
  margin: 3px 5px
}
div { color:blue }

:)

Acties:
  • 0 Henk 'm!

  • Bolukan
  • Registratie: Oktober 2002
  • Laatst online: 23-08 23:43
Als eindteken dus } of ; accepteren.
:)

Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Hmm. Iemand tips over hoe ik dit ga aanpakken?

Acties:
  • 0 Henk 'm!

  • sjhgvr
  • Registratie: Januari 2004
  • Laatst online: 04-08 14:27
Mei schreef op zaterdag 28 april 2007 @ 15:09:
Hmm. Iemand tips over hoe ik dit ga aanpakken?
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$blaat = explode(" ", $code);
$hold = 0;
$out = '';
foreach ($blaat as $piece) {
    if ($hold) {
        if (strpos($piece, ";")) {
            $out .= $piece;
            $hold = 0;
        } else
            $out .= $piece . ' ';
    } else if (strpos($piece, ":")) {
        $out .= $piece . ' ';
        $hold = 1;
    } else {
        $out .= $piece;
        $hold = 0;
    }   
}

*untested

oisd.nl


Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Hmm, ik denk inderdaad dat stacking (zo heet dat toch?:P) de oplossing is, maar jouw scriptje gaat niet werken als bij de invoer ergens een ; wordt weggelaten. Ik ga eens met die code bezig. Denk dat ik al weet hoe ik dat ga aanpakken.

Acties:
  • 0 Henk 'm!

  • remcotolsma
  • Registratie: December 2005
  • Laatst online: 08-09 11:11
Het is toch niet zo moeilijk om daar een reguliere expressie voor te bedenken? Als je de je de spaties om de volgende characters: '{', ':', ';', '}' weghaalt ben je er toch?

PHP:
1
$css = trim(preg_replace("/\s*({|:|;|})\s*/", '$1', $css));

Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
remcotolsma schreef op zaterdag 28 april 2007 @ 16:33:
Het is toch niet zo moeilijk om daar een reguliere expressie voor te bedenken?
Niet iedereen is een die-hard developer ;)
Als je de je de spaties om de volgende characters: '{', ':', ';', '}' weghaalt ben je er toch?

PHP:
1
$css = trim(preg_replace("/\s*({|:|;|})\s*/", '$1', $css));
Nee, want ik heb nooit beweerd dat het alleen om die spaties gaat. Ik heb gezegd dat álle qhitespace weg moest, behalve die om waardes te scheiden, zoals in mijn voorbeeld.

Acties:
  • 0 Henk 'm!

  • DukeBox
  • Registratie: April 2000
  • Laatst online: 17:51

DukeBox

loves wheat smoothies

Waarom eigenlijk ? Misschien brengt dat meer duidelijkheid in je probleem.
Meestal kun je met explode, trim en implode een heel eind komen als het alleen om shitespace gaat.

[ Voor 10% gewijzigd door DukeBox op 28-04-2007 16:47 ]

Duct tape can't fix stupid, but it can muffle the sound.


Acties:
  • 0 Henk 'm!

  • remcotolsma
  • Registratie: December 2005
  • Laatst online: 08-09 11:11
Mei schreef op zaterdag 28 april 2007 @ 16:37:
Niet iedereen is een die-hard developer ;)
Dat ben ik ook niet, maar ik kan het wel ;) :P.

Maar een CSS bestand is toch volgens bepaalde regels opgebouwd. Volgens mij kunnen in een CSS bestand niet veel andere spaties staan. Misschien in een commentaar blok? Die kun je eventueel er ook nog wel uit filteren.

PHP:
1
2
3
4
5
$css = trim($css);
// strip comments
$css = preg_replace('/\/\*(.*?)\*\//si', '', $css);
// strip white-space
$css = preg_replace("/\s*({|:|;|,|})\s*/", '$1', $css);

Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
DukeBox schreef op zaterdag 28 april 2007 @ 16:46:
Waarom eigenlijk ? Misschien brengt dat meer duidelijkheid in je probleem.
Meestal kun je met explode, trim en implode een heel eind komen als het alleen om shitespace gaat.
remcotolsma schreef op zaterdag 28 april 2007 @ 16:51:
Maar een CSS bestand is toch volgens bepaalde regels opgebouwd. Volgens mij kunnen in een CSS bestand niet veel andere spaties staan. Misschien in een commentaar blok? Die kun je eventueel er ook nog wel uit filteren.
Ik wil zorgen dat tussen de ingevoerde code een consistente manier van tabs en newlines gebruiken komt, zodat er een goed overzicht is. Alle standaard whitespace gaat er daarom uit en daarna worden er tegelijk met het hightlighten de noodzakelijke newlines en tabs weer toegevoegd. De spaties tussen waardes bij bijvoorbeeld de margin-eigenschap. Daar kan je vier waardes krijgen en zonder spaties ertussen werkt het niet.

Een CSS bestand is inderdaad volgens bepaalde regels opgebouwd, maar zoals net al duidelijk werd is een ; ter afsluiting van een eigenschap dus niet verplicht. Dan heb je gelijk weer wat minder houvast om te kijken waar een eigenschap afgelopen is. De syntax van CSS is gewoon niet so super streng. Wel simpel, maar niet streng. Je mag bijvoorbeeld overal tussendoor spaties, tabs en newlines neerkwakken zonder dat je problemen krijgt of de boel invalid is.

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Ik zou het zelf denk ik regel voor regel doen;
Alle opmaak verwijderen
Eerste regel lezen
Newline en tab geven na {
Spatie geven na :
Newline en tab geven na ;
2 newlines geven na }

Of je dan een overzichtelijk stylesheet overhoud is een tweede, maar alles is dan wel gelijk ingesprongen.

Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
frickY schreef op zaterdag 28 april 2007 @ 18:09:
Ik zou het zelf denk ik regel voor regel doen;
Alle opmaak verwijderen
Eerste regel lezen
Newline en tab geven na {
Spatie geven na :
Newline en tab geven na ;
2 newlines geven na }

Of je dan een overzichtelijk stylesheet overhoud is een tweede, maar alles is dan wel gelijk ingesprongen.
Daar gaat het niet om. Alle newlines en tabs worden nu perfect doorgevoerd, het gaat alleen nog om de eventuele spaties tussen de values. Het probleem is hoe ik dit zo foolproof mogelijk maak, aangezien het niet verplicht is aan te geven wanneer je eigenschap afgelopen is. Zoeken naar de volgende element definitie is ook moeilijk, want als je met geneste elementen werkt, dan heb je een aantal woorden met spaties ertussen. Het script van DaPi is leuk, maar die houdt ook rekening met puntkomma's om eigenschappen af te sluiten.

Dit is trouwens de code die ik nu heb:
PHP:
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
<?php
//Strip HTML tags
$text=strip_tags($text);

//Strip redundant spaces
$text=preg_replace('/ {2,}/',' ',$text);

//Strip newlines, tabs and incorrect comments
$text=preg_replace('/\/\/(.+)|\r\n|\t|\n|(?<=:) |(?=;) /','',$text);
        
//Comments
$text=preg_replace('/\/\*(.+?)\*\//',"\n\n<span class=\"bb-css-comment\">/*\\1*/</span>\n",$text);
    
//@imports
$text=preg_replace('/@import(.+?);/',"\n\n<span class=\"bb-css-atimport\">@import</span>\\1;\n",$text);
    
//Element definitions
$text=preg_replace('/([a-z1-6.#-_]+){(.+?)}/i',"\n<span class=\"bb-css-element\">\\1</span> {\\2\n}",$text);
    
//Properties and their values
$text=preg_replace('/([a-z-]+):(.+?);/si',"\n\t<span class=\"bb-css-property\">\\1</span>:<span class=\"bb-css-value\">\\2</span>;",$text);
    
//Syntax characters
$text=preg_replace('/([{}:;]|(?<!"|<\/span)>)/','<span class="bb-css-syntax-characters">\\1</span>',$text);
?>

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 18:26

crisp

Devver

Pixelated

remcotolsma schreef op zaterdag 28 april 2007 @ 16:51:
[...]

Dat ben ik ook niet, maar ik kan het wel ;) :P.

Maar een CSS bestand is toch volgens bepaalde regels opgebouwd. Volgens mij kunnen in een CSS bestand niet veel andere spaties staan. Misschien in een commentaar blok? Die kun je eventueel er ook nog wel uit filteren.
Cascading Stylesheet:
1
2
3
#foo:before {
    content: "Content met allemaal spaties"
}

;)

Je kan dit soort dingen beter tokenizen: tokenization of CSS

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Ja hallo, hoeveel bier heb jij op? :P Ik wil een simpele syntax highlighter maken, geen validator :P

Huidige code:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    //Strip HTML tags
    $text=strip_tags($text);

    //Strip redundant spaces
    $text=preg_replace('/ {2,}/',' ',$text);

    //Strip newlines, tabs and incorrect comments
    $text=preg_replace('/\/\/(.+)|\r\n|\t|\n|(?<=:) |(?=;) /','',$text);
        
    //Comments
    $text=preg_replace('/\/\*(.+?)\*\//',"\n\n<span class=\"bb-css-comment\">/*\\1*/</span>\n",$text);
    
    //@imports
    $text=preg_replace('/@import(.+?);/',"\n\n<span class=\"bb-css-atimport\">@import</span>\\1;\n",$text);
    
    //Properties and their values
    $text=preg_replace('/([a-z-]+):(.+?);/si',"\n\t<span class=\"bb-css-property\">\\1</span>:<span class=\"bb-css-value\">\\2</span>;",$text);
    $text=preg_replace('/([a-z-]+):(.+?)}/si',"\n\t<span class=\"bb-css-property\">\\1</span>:<span class=\"bb-css-value\">\\2</span>}",$text);
    
    //Element definitions
    $text=preg_replace('/([a-z1-6.,#-_* ]+){(.+?)}/si',"\n<span class=\"bb-css-element\">\\1</span> {\\2\n}",$text);
    
    //Syntax characters
    $text=preg_replace('/([{}:;]|(?<!"|<\/span)>)/','<span class="bb-css-syntax-characters">\\1</span>',$text);


Momenteel heb ik alleen nog problemen bij commentaar van meerdere regels. De whitespace wordt er tussenuit gehaald en het commentaar komt dan op één lange regel te staan.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 18:26

crisp

Devver

Pixelated

Mei schreef op zondag 29 april 2007 @ 00:49:
[...]


Ja hallo, hoeveel bier heb jij op? :P Ik wil een simpele syntax highlighter maken, geen validator :P
Ik geef alleen maar aan dat enkel reguliere expressies daarvoor onvoldoende soelaas bieden, je zal op z'n minst een soort van state-machine moeten bouwen, hoe wil je anders onderscheid kunnen maken in deze constructie:
Cascading Stylesheet:
1
table { display: table; }

:?

de GoT highlighter is in fact een lexer met verschillende states ;)

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Nou, ik ga niet alle code classificeren, maar kijk maar naar de regexps in mijn code. Er wordt wel degelijk gekeken naar de opbouw en aan de hand daarvan wordt op de goede plek een span met class ingevoegd.

Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Laatst online: 18:26

crisp

Devver

Pixelated

Wat jij wilt hoor, ik geef alleen maar aan dat deze manier van werken sub-optimaal is en er genoeg edge-cases te vinden zijn waarbij je highlighting niet werkt zoals je wilt (zie mijn content: voorbeeld, in feite kan je daar van alles in zetten).

Als wat je nu hebt goed genoeg voor je is, fine with me ;)

Intentionally left blank


Acties:
  • 0 Henk 'm!

  • Mei
  • Registratie: Juni 2005
  • Laatst online: 17-10-2024
Op die manier ja... Misschien dat ik het ooit nog eens doe, maar ik moet dan eerst eens goed gaat uivinden hoe ik het ga doen, want mijn kennis daarvan is nul komma nul.
Pagina: 1