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<Token> 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<Token> tokens = getTokensFromFile(file);
List<Token> sortedTokens = getSortedTokens(tokens);
new File(rootPath + "newcss.txt").writeAsStringSync(reconstructCSS(sortedTokens));
});
}
int i = 0;
List<Token> getTokensFromFile(file){
String value = "";
while (i < 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] != "{" && 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<Token> getSortedTokens(tokens){
List<Token> sortedTokens = [];
try {
while (iSort < tokens.length){
if (tokens[iSort].identifier == "PROPERTY"){
List<Token> toSort = getAllPropertiesInSelector();
iSort--;
toSort.sort((current, next) => current.value.compareTo(next.value));
for (var elem in toSort){
sortedTokens.add(elem);
}
}
else {
sortedTokens.add(tokens[iSort]);
}
iSort++;
}
}
catch(ex) { }
return sortedTokens;
}
List<Token> getAllPropertiesInSelector(){
List<Token> properties = [];
try {
while (tokens[iSort].identifier == "PROPERTY"){
properties.add(tokens[iSort]);
iSort++;
}
}
catch(ex) { };
return properties;
}
String reconstructCSS(List<Token> 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;
}