Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically separate stylesheet into sub-stylesheets?

Tags:

css

Say you have a massive stylesheet with a full site worth of selectors, each loaded with properties in it (positioning, sizing, fonts, colors, etc... all together) and you want to separate them into different, appropriate files (e.g. fonts.css, colors.css, layout.css, etc..)..

Are there any known (automated) methods for completing such a task?

Example:

#myid {
display:block;
width:100px;
height:100px;
border:1px solid #f00;
background-color:#f00;
font-size:.75em;
color:#000;
}

Would be converted to the following 3 files:

layout.css:

#myid {
    display:block;
    width:100px;
    height:100px;
}

color.css:

#myid {
    border:1px solid #f00;
    background-color:#f00;
    color:#000;
}

fonts.css:

#myid {
    font-size:.75em;
}

My example probably doesn't utilize the best conventions for doing this, but a way to automate the separation of the properties into different files would be very convenient in framework creation, I imagine.

like image 740
tester Avatar asked Nov 12 '09 06:11

tester


4 Answers

Here's how I would do it:

  1. Copy your big stylesheet to the 3 files.
  2. Open each one and remove the styles you don't need.

For step 2, you can save a lot of time by using search/replace in an editor like Notepad++. For example in layout.css, you could do a regex search for ^.*background:.+$ and replace with nothing. (Then at the end remove all blank lines.)

In theory you should be able to reduce this to only a couple of regexes per file, but Notepad++ doesn't seem to like the pipe character, or parentheses for that matter. ^.*background(-color|-image)?:.+$ ought to work, but it doesn't.

This isn't programmatic, but TBH by the time you'd written your own code to do what you're asking you could have typed the stylesheets out from scratch.

like image 74
DisgruntledGoat Avatar answered Nov 08 '22 19:11

DisgruntledGoat


Roll your own. Valid CSS should not be terribly difficult to parse.

  • Split the entire file by }
  • In each of those, what comes before the { is the selector
  • Split what comes after { by ; to get each individual rule for each selector
  • Evaluate each rule and build your files accordingly

Semi-pseudo VB.NET code...

 Dim CssFile as String = System.IO.File.ReadAllText("MyFile.css")
 Dim CssRules as String() = CssFile.Split("}")

 For Each Rule as String in CssRules
     Dim Selector as String = Rule.Substring(0, Rule.IndexOf("{")).Trim();
     Dim Styles as String() = Rule.Substring(Rule.IndexOf("{") + 1).Trim().Split(";");

     For Each Style as String in Styles
         If Style.StartsWith("font") Then 
              ' Build your files... yada, yada, yada
         End If
     Next
 Next
like image 29
Josh Stodola Avatar answered Nov 08 '22 19:11

Josh Stodola


Do you have a command line grep? Do you care about comments in the output? Can you do a first pass to clean up the formatting? For example in your editor of choice ensure that {,}, and ; are followed by a new-line. Then these might get you close:

grep -i '[{]\|[}]\|background\|border\|color' source.css > color.css
grep -i '[{]\|[}]\|font\|letter\|line-height' source.css > font.css
grep -v 'background\|border\|color\|font\|letter\|line-height' source.css > layout.css

You'll have to make adjustments if you don't want any of the following tags in the layout.css: outline-*, text-*, white-space, word-spacing. That is if your css uses them. I'd also take a quick look to see what tags you are actually using. For example,

grep -v '[{]\|[}]' test2.css | sed -e 's/:.*$//g' | sort -u
like image 7
Brett Pontarelli Avatar answered Nov 08 '22 20:11

Brett Pontarelli


This should get you started:

#!/usr/bin/env python
import cssutils

PATH_TO_CSS_FILE = 'old_huge_css_file.css'

LAYOUT = ('display', 'width', 'height', 'margin', 'padding',
          'position', 'top', 'left', 'bottom', 'right')
COLOR = ('color', 'background', 'border', 'background-color')
FONTS = ('font', 'font-size')

def strip_styles(infile_path, outfile_path, properties_to_keep):
    stylesheet = cssutils.parseFile(infile_path)

    for rule in stylesheet:
        if not rule.type == rule.STYLE_RULE:
            continue

        [ rule.style.removeProperty(p) for p in rule.style.keys() 
            if not p in properties_to_keep ]

    f = open(outfile_path, 'w')
    f.write(stylesheet.cssText)
    f.close()

segments = (
    ('layout.css', LAYOUT),
    ('color.css', COLOR),
    ('fonts.css', FONTS),
)

for segment in segments:
    strip_styles(PATH_TO_CSS_FILE, *segment)

You'll need CssUtils

And obviously I havn't filled in the tuples at the beginning with every possible css property. I'll leave that as an exercise to the reader

note: It will leave all the comments in the stylesheet even though many of them will not pertain to the separated styles.

Also, all styles not enumerated in the LAYOUT, COLOR, and FONTS variables at the top will be filtered out.

You can easily modify the strip_styles function to filter out the styles in those three variables to make a 4th stylesheet that contains all the misc. properties if you like

like image 5
Jiaaro Avatar answered Nov 08 '22 21:11

Jiaaro