<s> import data <EOL> from tools import SortedDict <EOL> class CSSOptimizer ( object ) : <EOL> def __init__ ( self , parser ) : <EOL> self . parser = parser <EOL> self . _optimized_css = SortedDict <EOL> def optimize ( self , raw_css ) : <EOL> if self . parser . getSetting ( '<STR_LIT>' ) : <EOL> return raw_css <EOL> self . _optimized_css = raw_css <EOL> if self . parser . getSetting ( '<STR_LIT>' ) == <NUM_LIT:2> : <EOL> self . __merge_selectors ( ) <EOL> for media , css in self . _optimized_css . iteritems ( ) : <EOL> for selector , cssdata in css . iteritems ( ) : <EOL> if self . parser . getSetting ( '<STR_LIT>' ) >= <NUM_LIT:1> : <EOL> cssdata = self . __merge_4value_shorthands ( cssdata ) <EOL> if self . parser . getSetting ( '<STR_LIT>' ) >= <NUM_LIT:2> : <EOL> cssdata = self . __merge_bg ( cssdata ) <EOL> for item , value in cssdata . iteritems ( ) : <EOL> value = self . __compress_numbers ( item , value ) <EOL> value = self . __compress_important ( value ) <EOL> if item in data . color_values and self . parser . getSetting ( '<STR_LIT>' ) : <EOL> old = value [ : ] <EOL> value = self . __compress_color ( value ) <EOL> if old != value : <EOL> self . parser . log ( '<STR_LIT>' + selector + '<STR_LIT>' + item + '<STR_LIT>' + old + '<STR_LIT>' + value , '<STR_LIT>' ) <EOL> if item == '<STR_LIT>' and self . parser . getSetting ( '<STR_LIT>' ) : <EOL> if value == '<STR_LIT>' : <EOL> value = '<STR_LIT>' <EOL> self . parser . log ( '<STR_LIT>' + selector + '<STR_LIT>' , '<STR_LIT>' ) <EOL> elif value == '<STR_LIT>' : <EOL> value = '<STR_LIT>' <EOL> self . parser . log ( '<STR_LIT>' + selector + '<STR_LIT>' , '<STR_LIT>' ) <EOL> self . _optimized_css [ media ] [ selector ] [ item ] = value <EOL> return self . _optimized_css <EOL> def __merge_bg ( self , cssdata ) : <EOL> """<STR_LIT>""" <EOL> img = <NUM_LIT:1> <EOL> clr = <NUM_LIT:1> <EOL> bg_img_list = [ ] <EOL> if cssdata . has_key ( '<STR_LIT>' ) : <EOL> img = len ( cssdata [ '<STR_LIT>' ] . split ( '<STR_LIT:U+002C>' ) ) <EOL> bg_img_list = self . parser . gvw_important ( cssdata [ '<STR_LIT>' ] ) . split ( '<STR_LIT:U+002C>' ) <EOL> elif cssdata . has_key ( '<STR_LIT>' ) : <EOL> clr = len ( cssdata [ '<STR_LIT>' ] . split ( '<STR_LIT:U+002C>' ) ) <EOL> number_of_values = max ( img , clr , <NUM_LIT:1> ) <EOL> new_bg_value = '<STR_LIT>' <EOL> important = '<STR_LIT>' <EOL> for i in xrange ( number_of_values ) : <EOL> for bg_property , default_value in data . background_prop_default . iteritems ( ) : <EOL> if not cssdata . has_key ( bg_property ) : <EOL> continue <EOL> cur_value = cssdata [ bg_property ] <EOL> if ( len ( bg_img_list ) > i and bg_img_list [ i ] == '<STR_LIT:none>' ) and bg_property in frozenset ( [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) : <EOL> continue <EOL> if self . parser . is_important ( cur_value ) : <EOL> important = '<STR_LIT>' <EOL> cur_value = self . parser . gvw_important ( cur_value ) <EOL> if cur_value == default_value : <EOL> continue <EOL> temp = cur_value . split ( '<STR_LIT:U+002C>' ) <EOL> if len ( temp ) > i : <EOL> if bg_property == '<STR_LIT>' : <EOL> new_bg_value += '<STR_LIT:(>' + temp [ i ] + '<STR_LIT>' <EOL> else : <EOL> new_bg_value += temp [ i ] + '<STR_LIT:U+0020>' <EOL> new_bg_value = new_bg_value . strip ( ) <EOL> if i != ( number_of_values - <NUM_LIT:1> ) : <EOL> new_bg_value += '<STR_LIT:U+002C>' <EOL> for bg_property , default_value in data . background_prop_default . iteritems ( ) : <EOL> try : <EOL> del cssdata [ bg_property ] <EOL> except : <EOL> pass <EOL> if new_bg_value != '<STR_LIT>' : <EOL> cssdata [ '<STR_LIT>' ] = new_bg_value + important <EOL> return cssdata <EOL> def __merge_4value_shorthands ( self , cssdata ) : <EOL> """<STR_LIT>""" <EOL> for key , value in data . shorthands . iteritems ( ) : <EOL> important = '<STR_LIT>' <EOL> if value != <NUM_LIT:0> and cssdata . has_key ( value [ <NUM_LIT:0> ] ) and cssdata . has_key ( value [ <NUM_LIT:1> ] ) and cssdata . has_key ( value [ <NUM_LIT:2> ] ) and cssdata . has_key ( value [ <NUM_LIT:3> ] ) : <EOL> cssdata [ key ] = '<STR_LIT>' <EOL> for i in xrange ( <NUM_LIT:4> ) : <EOL> val = cssdata [ value [ i ] ] <EOL> if self . parser . is_important ( val ) : <EOL> important = '<STR_LIT>' <EOL> cssdata [ key ] += self . parser . gvw_important ( val ) + '<STR_LIT:U+0020>' <EOL> else : <EOL> cssdata [ key ] += val + '<STR_LIT:U+0020>' <EOL> del cssdata [ value [ i ] ] <EOL> if cssdata . has_key ( key ) : <EOL> cssdata [ key ] = self . __shorthand ( cssdata [ key ] + important . strip ( ) ) <EOL> return cssdata <EOL> def __merge_selectors ( self ) : <EOL> """<STR_LIT>""" <EOL> raw_css = self . _optimized_css . copy ( ) <EOL> delete = [ ] <EOL> add = SortedDict ( ) <EOL> for media , css in raw_css . iteritems ( ) : <EOL> for selector_one , value_one in css . iteritems ( ) : <EOL> newsel = selector_one <EOL> for selector_two , value_two in css . iteritems ( ) : <EOL> if selector_one == selector_two : <EOL> continue <EOL> if value_one == value_two : <EOL> newsel += '<STR_LIT:U+002CU+0020>' + selector_two <EOL> delete . append ( ( media , selector_two ) ) <EOL> if not add . has_key ( media ) : <EOL> add [ media ] = SortedDict ( ) <EOL> add [ media ] [ newsel ] = value_one <EOL> delete . append ( ( media , selector_one ) ) <EOL> for item in delete : <EOL> try : <EOL> del self . _optimized_css [ item [ <NUM_LIT:0> ] ] [ item [ <NUM_LIT:1> ] ] <EOL> except : <EOL> continue <EOL> for media , css in add . iteritems ( ) : <EOL> self . _optimized_css [ media ] . update ( css ) <EOL> def __shorthand ( self , value ) : <EOL> """<STR_LIT>""" <EOL> important = '<STR_LIT>' ; <EOL> if self . parser . is_important ( value ) : <EOL> value_list = self . parser . gvw_important ( value ) <EOL> important = '<STR_LIT>' <EOL> else : <EOL> value_list = value <EOL> ret = value <EOL> value_list = value_list . split ( '<STR_LIT:U+0020>' ) <EOL> if len ( value_list ) == <NUM_LIT:4> : <EOL> if value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:1> ] and value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:2> ] and value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:3> ] : <EOL> ret = value_list [ <NUM_LIT:0> ] + important <EOL> elif value_list [ <NUM_LIT:1> ] == value_list [ <NUM_LIT:3> ] and value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:2> ] : <EOL> ret = value_list [ <NUM_LIT:0> ] + '<STR_LIT:U+0020>' + value_list [ <NUM_LIT:1> ] + important <EOL> elif value_list [ <NUM_LIT:1> ] == value_list [ <NUM_LIT:3> ] : <EOL> ret = value_list [ <NUM_LIT:0> ] + '<STR_LIT:U+0020>' + value_list [ <NUM_LIT:1> ] + '<STR_LIT:U+0020>' + value_list [ <NUM_LIT:2> ] + important <EOL> elif len ( value_list ) == <NUM_LIT:3> : <EOL> if value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:1> ] and value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:2> ] : <EOL> ret = value_list [ <NUM_LIT:0> ] + important <EOL> elif value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:2> ] : <EOL> return value_list [ <NUM_LIT:0> ] + '<STR_LIT:U+0020>' + value_list [ <NUM_LIT:1> ] + important <EOL> elif len ( value_list ) == <NUM_LIT:2> : <EOL> if value_list [ <NUM_LIT:0> ] == value_list [ <NUM_LIT:1> ] : <EOL> ret = value_list [ <NUM_LIT:0> ] + important <EOL> if ret != value : <EOL> self . parser . log ( '<STR_LIT>' + value + '<STR_LIT>' + ret + '<STR_LIT:">' , '<STR_LIT>' ) <EOL> return ret <EOL> def __compress_important ( self , value ) : <EOL> """<STR_LIT>""" <EOL> if self . parser . is_important ( value ) : <EOL> value = self . parser . gvw_important ( value ) + '<STR_LIT>' <EOL> return value <EOL> def __compress_numbers ( self , prop , value ) : <EOL> """<STR_LIT>""" <EOL> value = value . split ( '<STR_LIT:/>' ) <EOL> for l in xrange ( len ( value ) ) : <EOL> if not ( len ( value [ l ] ) > <NUM_LIT:0> and ( value [ l ] [ <NUM_LIT:0> ] . isdigit ( ) or value [ l ] [ <NUM_LIT:0> ] in ( '<STR_LIT:+>' , '<STR_LIT:->' ) ) ) : <EOL> continue <EOL> if prop in data . color_values : <EOL> value [ l ] = '<STR_LIT:#>' + value [ l ] <EOL> is_floatable = False <EOL> try : <EOL> float ( value [ l ] ) <EOL> is_floatable = True <EOL> except : <EOL> pass <EOL> if is_floatable and float ( value [ l ] ) == <NUM_LIT:0> : <EOL> value [ l ] = '<STR_LIT:0>' <EOL> elif value [ l ] [ <NUM_LIT:0> ] != '<STR_LIT:#>' : <EOL> unit_found = False <EOL> for unit in data . units : <EOL> pos = value [ l ] . lower ( ) . find ( unit ) <EOL> if pos != - <NUM_LIT:1> and prop not in data . shorthands : <EOL> value [ l ] = self . __remove_leading_zeros ( float ( value [ l ] [ : pos ] ) ) + unit <EOL> unit_found = True <EOL> break ; <EOL> if not unit_found and prop in data . unit_values and prop not in data . shorthands : <EOL> value [ l ] = self . __remove_leading_zeros ( float ( value [ l ] ) ) + '<STR_LIT>' <EOL> elif not unit_found and prop not in data . shorthands : <EOL> value [ l ] = self . __remove_leading_zeros ( float ( value [ l ] ) ) <EOL> if len ( value ) > <NUM_LIT:1> : <EOL> return '<STR_LIT:/>' . join ( value ) <EOL> return value [ <NUM_LIT:0> ] <EOL> def __remove_leading_zeros ( self , float_val ) : <EOL> """<STR_LIT>""" <EOL> if abs ( float_val ) < <NUM_LIT:1> : <EOL> if float_val < <NUM_LIT:0> : <EOL> float_val = '<STR_LIT:->' . str ( float_val ) [ <NUM_LIT:2> : ] <EOL> else : <EOL> float_val = str ( float_val ) [ <NUM_LIT:1> : ] <EOL> return str ( float_val ) <EOL> def __compress_color ( self , color ) : <EOL> """<STR_LIT>""" <EOL> if color [ : <NUM_LIT:4> ] . lower ( ) == '<STR_LIT>' : <EOL> color_tmp = color [ <NUM_LIT:4> : ( len ( color ) - <NUM_LIT:5> ) ] <EOL> color_tmp = color_tmp . split ( '<STR_LIT:U+002C>' ) <EOL> for c in color_tmp : <EOL> c = c . strip ( ) <EOL> if c [ : - <NUM_LIT:1> ] == '<STR_LIT:%>' : <EOL> c = round ( ( <NUM_LIT:255> * color_tmp [ i ] ) / <NUM_LIT:100> ) <EOL> if color_tmp [ i ] > <NUM_LIT:255> : <EOL> color_tmp [ i ] = <NUM_LIT:255> <EOL> color = '<STR_LIT:#>' <EOL> for i in xrange ( <NUM_LIT:3> ) : <EOL> if color_tmp [ i ] < <NUM_LIT:16> : <EOL> color += '<STR_LIT:0>' + str ( hex ( color_tmp [ i ] ) ) . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> else : <EOL> color += str ( hex ( color_tmp [ i ] ) ) . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> if data . replace_colors . has_key ( color . lower ( ) ) : <EOL> color = data . replace_colors [ color . lower ( ) ] <EOL> if len ( color ) == <NUM_LIT:7> : <EOL> color_temp = color . lower ( ) <EOL> if color_temp [ <NUM_LIT:0> ] == '<STR_LIT:#>' and color_temp [ <NUM_LIT:1> ] == color_temp [ <NUM_LIT:2> ] and color_temp [ <NUM_LIT:3> ] == color_temp [ <NUM_LIT:4> ] and color_temp [ <NUM_LIT:5> ] == color_temp [ <NUM_LIT:6> ] : <EOL> color = '<STR_LIT:#>' + color [ <NUM_LIT:1> ] + color [ <NUM_LIT:3> ] + color [ <NUM_LIT:5> ] <EOL> if data . optimize_colors . has_key ( color . lower ( ) ) : <EOL> color = data . optimize_colors [ color . lower ( ) ] <EOL> return color </s>
