Sorting CSS styles and classes in your files with a Python script
When editing CSS files, it’s quite common that the length of the file gets so big that it’s hard to find the classes in it. Some IDEs like Eclipse help you to show a sorted outline of the CSS file, but it will not sort the file for you as you want to.
I’ve barely seen any larger projects with nicely structured CSS files, which is partially because neither the editors nor the tools are perfect for CSS editing.
To highlight one of the many problems with CSS, let’s see a simple snippet:
#mystyle li{
color:green;
}
input
{
background-color: red;
}
#mystyle
{
/*should not use . and # with the
same name!*/
}
b{
font-size: 1.2em;
}
.mystyle{
font-weight: bold;
}
It’s a bit mixed up here and there, not well formatted, the DOM level CSS styles are mixed with the ID and class definitions, the names are not in sorted order. It’s pretty hard to read.
How about we sort and pretty print it a bit:
b {
font-size: 1.2em;
}
input {
background-color: red;
}
.mystyle {
font-weight: bold;
}
#mystyle {
/*should not use . and # with the
same name!*/
}
#mystyle li {
color:green;
}
Looking at the second output, it’s much easier to see what’s going on. It’s fairly obvious now that B and INPUT are the only DOM elements that are overridden and we have some issues around the ‘mystyle’ naming. Moreover, it’s easy to see that any LI within ‘mystyle’ will be green.
To sort a CSS file styles like the above, I’ve created a simple Python script (70 lines) that reads the original CSS and outputs the sorted version to the STDOUT. It does not handle special cases like one line CSS styles and commented out styles, but to be honest I don’t really create those so I don’t need to handle them either.
import re import argparse class CSSClass: def __init__(self, name, body): self.name = name self.body = body pass @staticmethod def parseFile(filename): f = open(filename) name = '' body = [] prev = '' cssarr = [] for lineOrig in f: line = lineOrig.strip() slineopen = line.split('{') slineclose = line.split('}') if len(slineopen) > 1: body = [''] sline0 = slineopen[0].strip() if sline0 == '': name = prev # // { in new line else: name = sline0 # // { in line with name elif len(slineclose) == 2: css = CSSClass(name, body) cssarr.append(css) body = [] name = '' else: body.append(line) prev = line return cssarr @staticmethod def csscomparator(cssx, cssy): x = cssx.name y = cssy.name xsw = False ysw = False if re.match('^[.#]', x): x = x[1:] xsw = True if re.match('^[.#]', y): y = y[1:] ysw = True if xsw == ysw: # both class or top level return cmp(x, y) return 1 if xsw else -1 # // if X is class, it's larger def __str__(self): return '%s {\t%s\n}\n' % (self.name,'\n\t'.join( self.body )) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Sort the style names in your CSS file') parser.add_argument('input', metavar='style.css', help='input CSS to be sorted. Output is STDOUT') args = parser.parse_args() cssarr = CSSClass.parseFile(args.input) cssarr.sort(CSSClass.csscomparator) for css in cssarr: print css pass
To run it, simply do:
$python cssSorter.py styles.css > sortedstyles.css
Comments
Post a Comment