Transform poor CSS into a more beatiful form in Dart I have this script that opens a file containing (possibly) bad CSS, lexes the content of it and creates a new file with the same code in a more pleasant way to look at. It formats it and sorts the properties alphabetically.

I would love to hear some very critical feedback on coding style, best practises and how I can make it cleaner.

Some concerns I have right now are the global variables (like i and iSort), the hard coded file path and the use of while loops.

I am trying to make it as easy as possible for others to read, but to me it seems as if passing around file[i] and other variables makes it more cluttered than it should be.

The exception handling seems unnecessary, but without it, the index overflows at some point and the program execution just stops. Is there a way I can avoid it in this case?

import 'dart:io';
import "dart:core";

class Token {
  String identifier;
  String value;
  Token(this.identifier, this.value);
}

List&lt;Token&gt; tokens = [];

void main() {
  String rootPath = "C:/Users/User/Desktop/Datein/AlphaCSS/bin/";
  String originalFilePath = "samplecss.css";

  new File(rootPath + originalFilePath).readAsString().then((String file) {
    List&lt;Token&gt; tokens = getTokensFromFile(file);
    List&lt;Token&gt; sortedTokens = getSortedTokens(tokens);
    new File(rootPath + "newcss.txt").writeAsStringSync(reconstructCSS(sortedTokens));
  });
}

int i = 0;

List&lt;Token&gt; getTokensFromFile(file){
  String value = "";
  while (i &lt; file.length-1){
    value = "";
    if (isValidStart(file[i])){
      value = getTokenContent(file);
      addTokenBasedOnType(file[i], value);
    }
    else if (isEndOfSelector(file[i])){
      addTokenBasedOnType(file[i], "");
    }
    i++;
  }
  return tokens;
}

bool isValidStart(String char){
  RegExp regex = new RegExp(r"[a-zA-Z0-9#.]");
  return (regex.hasMatch(char)) ? true : false;
}

bool isEndOfSelector(String char){
  return (char == "}") ? true : false;
}

String getTokenContent(String file){
  String content = "";
  while (file[i] != "{" &amp;&amp; file[i] != ";"){
    content += file[i];
    i++;
  }
  return content;
}

void addTokenBasedOnType(String char, String value){
  if (char == "{"){
    tokens.add(new Token("SELECTOR", value));
  }
  else if (char == "}"){
    tokens.add(new Token("END", ""));
  }
  else {
    tokens.add(new Token("PROPERTY", value));
  }
}

int iSort = 0;

List&lt;Token&gt; getSortedTokens(tokens){

  List&lt;Token&gt; sortedTokens = [];
  try {
    while (iSort &lt; tokens.length){
      if (tokens[iSort].identifier == "PROPERTY"){
        List&lt;Token&gt; toSort = getAllPropertiesInSelector();
        iSort--;
        toSort.sort((current, next) =&gt; current.value.compareTo(next.value));
        for (var elem in toSort){
          sortedTokens.add(elem);
        }
      }
      else {
        sortedTokens.add(tokens[iSort]);
      }
      iSort++;
    }
  }
  catch(ex) { }
  return sortedTokens;
}

List&lt;Token&gt; getAllPropertiesInSelector(){
  List&lt;Token&gt; properties = [];
  try {
    while (tokens[iSort].identifier == "PROPERTY"){
      properties.add(tokens[iSort]);
      iSort++;
    }
  }
  catch(ex) { };
  return properties;
}

String reconstructCSS(List&lt;Token&gt; sortedTokens) {
  String finalString = "";

  for (var elem in sortedTokens){
    if (elem.identifier == "SELECTOR"){
      finalString += "${elem.value}{\n";
    }
    else if (elem.identifier == "END"){
      finalString += "}\n\n";
    }
    else if (elem.identifier == "PROPERTY"){
      finalString += "  ${elem.value};\n";
    }
  }
  return finalString;
}
Sorting the properties alphabetically does not yield "the same code". Properties that appear later in a rule override properties that occur earlier in the same rule. Mozilla Developer Network gives an example of a tricky edge case:


  
  A value which is not specified is set to its initial value. That sounds anecdotal, but it really means that it overrides previously set values. Therefore:

background-color: red;
background: url(images/bg.gif) no-repeat top right;

  
  will not set the color of the background to red but to background-color's default, transparent, as the second rule has precedence.
  


If you reverse the properties in that example, you would get a different result.