Class: Ass::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/ass/parser.rb

Constant Summary collapse

OPEN_BRACE =
" {\n"
CLOSING_BRACE =
"}\n"
AT =
/^ *@/
COMMENT =
/^ *\/\*(.*)(?:\*\/)?$/
ASS_COMMENT =
/&\/\//
BLANK =

TODO: Single n char as well, update test.ass

/^ *$/
WORD =
/([\w]+)/
HYPHENATED_WORD =
/([\w\-]+)/
MIXIN =
/^ *\+#{WORD}/
SELECTOR =

TODO: review CSS specification

/^([#\w\-\.,:\[\]\~\* ]+) *$/
EQUALS =
/ *= */
CONSTANT =
/:#{WORD}/
CONSTANT_VALUE =
/([#\w]+)/
CONSTANT_WITH_VALUE =
/^ *#{CONSTANT}#{EQUALS}#{CONSTANT_VALUE}/
PROPERTY =
/^ *#{HYPHENATED_WORD}/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ass = '') ⇒ Parser

Returns a new instance of Parser.



25
26
27
# File 'lib/ass/parser.rb', line 25

def initialize ass = ''
  @ass, @css, @constants = ass, '', {}
end

Instance Attribute Details

#assObject

Returns the value of attribute ass.



22
23
24
# File 'lib/ass/parser.rb', line 22

def ass
  @ass
end

#constantsObject

Returns the value of attribute constants.



22
23
24
# File 'lib/ass/parser.rb', line 22

def constants
  @constants
end

#cssObject Also known as: to_s

Returns the value of attribute css.



22
23
24
# File 'lib/ass/parser.rb', line 22

def css
  @css
end

Class Method Details

.parse(ass) ⇒ Object



103
104
105
# File 'lib/ass/parser.rb', line 103

def self.parse ass
  new(ass).parse!.css
end

.parse_file(file) ⇒ Object



107
108
109
# File 'lib/ass/parser.rb', line 107

def self.parse_file file
  new(File.read(file)).parse!.css
end

Instance Method Details

#format_property(line) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/ass/parser.rb', line 94

def format_property line
  line.gsub! PROPERTY, '  \1:'
  line.gsub! CONSTANT do |constant| 
    constant[0,1] = ''
    @constants[constant.to_sym] || 'undefined_constant'
  end
  line << ";\n"
end

#indents_in(string) ⇒ Object



90
91
92
# File 'lib/ass/parser.rb', line 90

def indents_in string
  string.match(/^( *)/).captures.first.length / 2 rescue 0
end

#nested_selector?(selector_a, selector_b) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/ass/parser.rb', line 86

def nested_selector? selector_a, selector_b
  indents_in(selector_a) > indents_in(selector_b)
end

#parse!Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/ass/parser.rb', line 29

def parse!
  mixins = Hash.new ''
  in_block, in_mixin = false, false
  last_selector = ''
  lines = @ass.split "\n"
  lines.each do |line|
    
    case line
    when COMMENT
      @css << "/* #{$1.strip} */\n"
    when MIXIN
      if in_block
        next if in_mixin
        @css << mixins[$1]
      else
        in_mixin, in_block = $1, true
      end
    when CONSTANT_WITH_VALUE
      @constants[$1.to_sym] = $2
    when BLANK
      if in_block
        in_block = false
        next if in_mixin
        @css << CLOSING_BRACE
      end
    when AT
      @css << line << "\n"
    else
      if not in_block and line.match SELECTOR 
        in_block = true
        if nested_selector?($1, last_selector)
          next if in_mixin
          selector = splice_selectors last_selector, $1.strip
          @css << selector << OPEN_BRACE
        else
          in_mixin = false
          selector = $1.strip
          @css << selector << OPEN_BRACE
        end
        last_selector = selector
      elsif line.match PROPERTY
        if mixin = in_mixin
          mixins[mixin] << format_property(line)
        else
          @css << format_property(line)
        end
      end
    end
  end
  self
end

#splice_selectors(selector_a, selector_b) ⇒ Object



81
82
83
84
# File 'lib/ass/parser.rb', line 81

def splice_selectors selector_a, selector_b
  selector_b[0,0] = ' ' unless selector_b[0,1] == ':'
  selector_a.strip.gsub(/([^,]+),/, "\\1#{selector_b},") << selector_b
end