2013-05-19 10 views
5

ho questa riga di codice che sto usando per preparare alcuni file CSS:stringa di sostituirlo con l'eccezione su alcune corde

TheMinifiedCSS = TheMinifiedCSS.Replace("white", "#FFF"); 

Il problema è che in CSS, ho questa dichiarazione:

.SomeClass{white-space:pre-wrap;} 

Come modificare l'istruzione .Replace per sostituire white con #FFF ma lasciare white-space da solo?

Grazie.

Nota, so che posso aggiungere TheMinifiedCSS = TheMinifiedCSS.Replace("#FFF-space", "white-space"); ma sto cercando qualcosa di più pulito.

+2

Se si sta facendo questo per rendere il file CSS più piccolo allora andrei fino a suggerire che è una perdita di tempo. Faresti molto meglio semplicemente assicurandoti che il file sia memorizzato nella cache e lasciandolo lì a meno che tu non stia ottenendo enormi quantità di utenti che lo guardano. – Chris

risposta

6

La gente continua cercando di scrivere le regole per le cose che appaiono prima o dopo "white", quando penso a quello che si desidera è che "white" è proprio token e non fa parte di un selettore.

Regex.Replace(TheMinifiedCSS, @"(?<![-_a-zA-Z0-9#.])white(?![-_a-zA-Z0-9])", @"#FFF"); 

Una regola più completo sarebbe implementare l'intera regola per i token identificatore nel CSS, ma penso che questo copre tutte le parole chiave.

Ecco un banco di prova un po 'più complicato di quanto sia stato scritto finora:

.white> TD { color: white;box-shadow: 0px 0px 3px white, inset 0px 0px 5px black; white-space:pre-wrap; } 
BODY { background: url('test.png'),white; } 

ancora più difficile, e non gestita dal mio esempio, sono i nomi dei file.

BODY 
{ 
    background-color:white; 
    background-image:url('almost white, but not really.png'); 
} 

Per farlo, probabilmente è necessario un parser completo CSS.

+0

Beh, grazie mille per la tua risposta !! Molto pensato! – frenchie

1

È possibile utilizzare un'espressione regolare per questo. Penso che questo sia il modo migliore per te. Ecco il link dove è possibile ottenere informazioni più dettagliate:

http://msdn.microsoft.com/en-us/library/xwewhkd1.aspx

io non sono veramente forte con i modelli di costruzione per le espressioni regolari, ma si può provare questo campione

static void Main(string[] args) 
{ 
    var inputText = @"white-space: 0; color: white; 
        box-shadow: 10px 20px 30px white, inset 0px 0px 5px black;"; 

    inputText = ChangeColor(inputText, "white", "#FFF"); 
} 

private static string ChangeColor(string css, string oldColor, string newColor) 
{ 
    // Rule 1 
    var pattern1 = string.Format(@"(color)(\s*):(\s*){0}(\s*)", oldColor); 
    var replacement = string.Format("$1 : {0}", newColor); 

    var rgx = new Regex(pattern1); 
    css = rgx.Replace(css, replacement); 

    // Rule 2 
    var pattern2 = string.Format(@"([\d]*)px(\s*)([\d]*)px(\s*)([\d]*)px(\s*){0}", oldColor); 
    var replacement2 = string.Format("$1px $3px $5px {0}", newColor); 

    rgx = new Regex(pattern2); 
    css = rgx.Replace(css, replacement2); 

    return css; 
} 
+0

C'è anche questo caso: box-shadow: 0px 0px 3px bianco, inserto 0px 0px 5px nero; – frenchie

+0

Ho modificato il codice e anche in questo caso – user2399170

0

Un semplice trucco sarebbe essere sostituire solo quando è preceduto da un :

TheMinifiedCSS = TheMinifiedCSS.Replace(": white", ":#FFF"); 

questo modo sarà sostituire solo css valori an d non proprietà.

A mio parere, tuttavia, il modo migliore è utilizzare espressioni regolari o utilizzare un parser CSS e ricostruire completamente il documento.

BTW: Se stai facendo questo per scopi di apprendimento va bene, tuttavia se vuoi usarlo a fini di produzione, ti consiglio caldamente di usare un componente esistente che faccia già tutto questo.

+0

E se non c'è spazio dopo ':', o c'è un carattere di tabulazione, o ... 'String.Replace' non è molto bravo in questo. –

+0

Esattamente, questo perché è un hack e l'OP dovrebbe usare espressioni regolari o un parser CSS – Kenneth

+0

Cosa succede con box-shadow: 0px 0px 3px bianco, inserto 0px 0px 5px nero; – frenchie

0

Semplice ... dovrebbe funzionare per la maggior parte degli scopi:

TheMinifedCSS = Regex.Replace(TheMinifiedCSS, @":(.*)white(.*);", @":$1#FFF$2;") 

In pratica controlla se è dopo i due punti, poi prende tutti i caratteri fino bianco, sostituisce e poi si fa tutti i caratteri dopo e poi un punto e virgola. Successivamente, inserisce il css attorno al nuovo bit che sostituisce white (#FFF) e quindi un punto e virgola.

0

Questo sarebbe modo più efficace per trovare la stringa white & sostituirla con #FFF

TheMinifedCSS = 
Regex.Replace(TheMinifiedCSS, @"(:(.*)(white)(.*);|:[ ]*(white)[ ]*})", @"#FFF"); 

Gestisce spazio in mezzo come: {color: white}{color:white} entrambi sono validi.

È possibile controllare questo link per ulteriori riferimenti: http://regexr.com?34tqv

1

Regex può rendere le cose molto più complicate. Ecco una soluzione che funziona. Ha anche la soluzione per commenti e stringhe.

static void Main(string[] args) 
    { 
     string test = ".white> TD { color: white;box-shadow: 0px 0px 3px white, inset 0px 0px 5px black; white-space:pre-wrap; background-image='white black \" white \"'}"; 
     Console.WriteLine("Before: " + test); 
     test = replaceInCSS(test, "white", "green"); 
     Console.WriteLine("After: " + test); 
     Console.ReadLine(); 
    } 

    static string replaceInCSS(string text, string replace, string replacement) 
    { 
     char[] forceBefore = new char[]{ '\n', '\t', ';', '{', ' ', ':', ','}; 
     char[] forceAfter = new char[] { ';', '}', ' ', ','}; 

     int index = text.IndexOf(replace, 0); 
     while (index != -1) 
     { 
      if (!indexWithinStringOrComment(text, index)) 
      { 
       int afterPos = index + replace.Length; 
       bool beforeOk = false, afterOk = false; 

       if (index > 0 && forceBefore.Contains<char>(text[index - 1])) 
        beforeOk = true; 
       if (afterPos < text.Length - 1 && forceAfter.Contains<char>(text[afterPos])) 
        afterOk = true; 

       if ((index == 0 || beforeOk) && 
        (afterPos == text.Length - 1 || afterOk)) 
       { 
        text = text.Remove(index, replace.Length); 
        text = text.Insert(index, replacement); 
       } 
      } 

      index = text.IndexOf(replace, index + 1); 
     } 

     return text; 
    } 

    static bool indexWithinStringOrComment(string text, int index) 
    { 
     bool insideStrSimple = false; 
     bool insideStrDouble = false; 
     bool insideStrComment = false; 
     for (int i = 0; i < index; ++i) 
     { 
      string subStr = text.Substring(i, 2); 

      if (text[i] == '\'' && !insideStrDouble && !insideStrComment) 
       insideStrSimple = !insideStrSimple; 
      else if (text[i] == '"' && !insideStrSimple && !insideStrComment) 
       insideStrDouble = !insideStrDouble; 
      else if (text.Substring(i, 2) == "/*" && !insideStrDouble && !insideStrSimple) 
       insideStrComment = true; 
      else if (text.Substring(i, 2) == "*/" && insideStrComment) 
       insideStrComment = false; 
     } 

     return insideStrDouble || insideStrSimple || insideStrComment; 
    } 

uscita:

Before: .white> TD { color: white;box-shadow: 0px 0px 3px white, inset 0px 0px 5px black; white-space:pre-wrap; background-image='white black \" white \"'} 
After: .white> TD { color: green;box-shadow: 0px 0px 3px green, inset 0px 0px 5px black; white-space:pre-wrap; background-image='white black \" white \"'} 

Edit: Ci andiamo. Anche il problema delle stringhe interne viene risolto. Questo dovrebbe funzionare per sostituire qualsiasi proprietà CSS. Modifica di nuovo: aggiunta correzione per i commenti.

+0

E cosa ottieni come risultato? Il ".white> TD" NON dovrebbe essere cambiato –

+0

Ah ok, dammi 5min. – Flipbed

+0

Fatto. Ho impiegato 24 minuti però :( – Flipbed

Problemi correlati