Module: CssDryer::Processor
- Included in:
- NcssHandler, Rack::CssDryer
- Defined in:
- lib/css_dryer/processor.rb
Defined Under Namespace
Classes: StateMachine, StyleHash
Constant Summary collapse
- VERSION =
'0.4.3'
Instance Method Summary collapse
-
#nested_css_to_structure(css) ⇒ Object
:nodoc:.
-
#process(nested_css, indent = 2) ⇒ Object
Converts a stylesheet with nested styles into a flattened, normal CSS stylesheet.
-
#structure_to_css(structure, indent = 2) ⇒ Object
:nodoc:.
Instance Method Details
#nested_css_to_structure(css) ⇒ Object
:nodoc:
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/css_dryer/processor.rb', line 61 def nested_css_to_structure(css) #:nodoc: # Implementation notes: # - the correct way to do this would be using a lexer and parser # - ironically there is a degree of repetition here document = [] selectors = [] media_block = false css.each_line do |line| depth = selectors.length case line.chomp! # Media block (multiline) opening - treat as plain text but start # watching for close of media block. # Assume media blocks are never themselves nested. # (This must precede the multiline selector condition.) when /^(\s*@media.*)[{]\s*$/ media_block = true document << line if depth == 0 # Media block inline # Assume media blocks are never themselves nested. when /^\s*@media.*[{].*[}]\s*$/ document << line if depth == 0 # Multiline selector opening when /^\s*([^{]*?)\s*[{]\s*$/ hsh = StyleHash[ $1 => [] ] hsh.multiline = true if depth == 0 document << hsh else prev_hsh = selectors.last prev_hsh.value << hsh end selectors << hsh # Neither opening nor closing - 'plain text' when /^[^{}]*$/ if depth == 0 document << line else hsh = selectors.last hsh.value << (depth == 1 ? line : line.strip) end # Multiline selector closing when /^([^{]*)[}]\s*$/ if media_block media_block = false if depth == 0 document << line else hsh = selectors.last hsh.value << line end else selectors.pop end # Inline selector when /^([^{]*?)\s*[{]([^}]*)[}]\s*$/ key = (depth == 0 ? $1 : $1.strip) hsh = StyleHash[ key => [ $2 ] ] if depth == 0 document << hsh else prev_hsh = selectors.last prev_hsh.value << hsh end end end document end |
#process(nested_css, indent = 2) ⇒ Object
Converts a stylesheet with nested styles into a flattened, normal CSS stylesheet. The original whitespace is preserved as much as possible.
For example, the following DRY stylesheet:
div {
font-family: Verdana;
#content {
background-color: green;
p { color: red; }
}
}
is converted into this CSS:
div {
font-family: Verdana;
}
div #content {
background-color: green;
}
div #content p { color: red; }
Note, though, that @media blocks are preserved. For example:
@media screen, projection {
div {font-size:100%;}
}
is left unchanged.
Styles may be nested to an arbitrary level.
55 56 57 58 59 |
# File 'lib/css_dryer/processor.rb', line 55 def process(nested_css, indent = 2) #:doc: # 'Normalise' comma separated selectors nested_css = factor_out_comma_separated_selectors(nested_css, indent) structure_to_css(nested_css_to_structure(nested_css), indent) end |
#structure_to_css(structure, indent = 2) ⇒ Object
:nodoc:
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/css_dryer/processor.rb', line 129 def structure_to_css(structure, indent = 2) #:nodoc: # Implementation note: the recursion and the formatting # ironically both feel repetitive; DRY them. indentation = ' ' * indent css = '' structure.each do |elem| # Top-level hash if elem.kind_of? StyleHash set_asides = [] key = elem.key if elem.has_non_style_hash_children css << "#{key} {" css << (elem.multiline ? "\n" : '') end elem.value.each do |v| # Nested hash, depth = 1 if v.kind_of? StyleHash # Set aside set_asides << set_aside(combo_key(key, v.key), v.value, v.multiline) else unless v.blank? css << (elem.multiline ? "#{v}" : v) css << (elem.multiline ? "\n" : '') end end end css << "}\n" if elem.has_non_style_hash_children # Now write out the styles that were nested in the above hash set_asides.flatten.each { |hsh| next unless hsh.has_non_style_hash_children css << "#{hsh.key} {" css << (hsh.multiline ? "\n" : '') hsh.value.each { |item| unless item.blank? css << (hsh.multiline ? "#{indentation}#{item}" : item) css << (hsh.multiline ? "\n" : '') end } css << "}\n" } set_asides.clear else css << "#{elem}\n" end end css end |