Class: Flay

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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.load_pluginsObject



5
6
7
# File 'lib/flay_js.rb', line 5

def self.load_plugins
  %w(js erb haml)
end

.options_js(o, options) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/flay_js.rb', line 9

def self.options_js o, options
  o.separator nil
  o.separator "flay-js options:"
  o.separator nil
  o.on("-e", "--exclude PATH", String,
          "Path to file with regular expressions for files to be skipped",
          "  use '-e default' to skip jquery, jquery-ui, *.min.js and versioned file names") do |p|
      p = File.dirname(__FILE__) + "/../data/flay_js_exclude" if p == 'default'
      rexps = File.readlines(p).
          map(&:strip).
          reject(&:empty?).
          map{ |s| Regexp.new s }
      options[:exclude] = Regexp.union(rexps) unless rexps.empty?
  end
  o.on("-j", "--javascript",
       "Run flay in javascript mode",
       "  (in addition to *.js process javascript fragments in *.erb and *.haml ") do
    @@plugins = %w(js haml erb)
    alias_method :null_erb, :process_erb
    alias_method :process_erb, :do_erb
    alias_method :sexp_to_erb, :sexp_to_js
    alias_method :null_haml, :process_haml if respond_to? :process_haml
    alias_method :process_haml, :do_haml
    alias_method :sexp_to_haml, :sexp_to_js
  end
end

Instance Method Details

#do_erb(file) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/flay_js.rb', line 66

def do_erb(file)
  return nil if option[:exclude] && option[:exclude] =~ file
  return process_js(file) if file =~ /\.js\./
  erb = File.read file
  return nil if erb !~ /<\s*script/i

  blocks = js_erb_blocks(erb, file)
  return nil if blocks.empty?

  sexp = s(:block, *blocks)
  sexp.line 1
end

#do_haml(file) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/flay_js.rb', line 36

def do_haml(file)
  return nil if option[:exclude] && option[:exclude] =~ file
  haml = File.read file
  return nil if haml !~ /$\s*:javascript/

  blocks = js_haml_blocks(haml, file)
  return nil if blocks.empty?
  sexp = s(:block, *blocks)
  sexp.line 1
end

#fixed(sexp, offset = 0) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/flay_js.rb', line 114

def fixed(sexp, offset = 0)
  sexp.line ||= 0
  sexp.line += offset
  file = sexp.file
  sexp.deep_each do |s|
    s.line ||= 0
    s.line += offset
    file ||= s.file
  end
  sexp.file = file
  sexp.deep_each do |s|
    s.file = file
  end
  sexp
end

#js_erb_blocks(erb, file) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/flay_js.rb', line 79

def js_erb_blocks(erb, file)
  lines = erb.lines.to_a
  blocks = []
  offset = 0
  while lines && (off = lines.find_index{ |s| s =~ /<\s*script/i })
    str = lines.join
    str =~ /(<\s*script[^>]*>[\n\s]*)(.*?)(<\s*\/\s*script\s*>[\n\s]*)/im
    off = off + $1.count("\n")
    blocks << js_sexp($2, file, offset + off)
    offset += ($2 + $3).count("\n") + off + 1
    lines = lines[offset .. -1]
  end
  blocks
end

#js_haml_blocks(haml, file) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/flay_js.rb', line 47

def js_haml_blocks(haml, file)
  lines = haml.lines.to_a
  blocks = []
  off = 0
  while lines && (off = lines.find_index{ |s| s =~ /^(\s*):javascript\s*$/})
    indent = $1.size
    offset = off + 1
    js = ''
    while (line = lines[offset]) &&
      ( (line =~/^(\s*)[^\s]/ && $1.size > indent) || line.strip.empty? )
      js << line
      offset += 1
    end
    blocks << js_sexp(js, file, off + 1)
    lines = lines[offset..-1]
  end
  blocks
end

#js_sexp(js, file, offset) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/flay_js.rb', line 100

def js_sexp(js, file, offset)
  js = unerb(js) if file =~ /\.erb$/
  js = uninterpolate(js) if file =~ /\.haml$/

  asx = RKelly::Parser.new.parse(js, file)
  puts js if asx.nil? && option[:verbose]
  raise "JS syntax error in #{file}" unless asx
  if option[:diff]
    @asx ||= Hash.new{|h,k| h[k] = []}
    @asx[file] << asx
  end
  fixed(asx.to_real_sexp, offset)
end

#process_js(file) ⇒ Object



94
95
96
97
98
# File 'lib/flay_js.rb', line 94

def process_js(file)
  return nil if option[:exclude] && option[:exclude] =~ file
  js = File.read file
  js_sexp(js, file, 0)
end

#sexp_to_js(sexp) ⇒ Object



149
150
151
152
153
154
155
156
# File 'lib/flay_js.rb', line 149

def sexp_to_js(sexp)
  @asx[sexp.file].each do |asx|
    asx.each do |sa|
      return sa.to_ecma if sa.to_real_sexp == sexp
    end
  end
  'Conversion to javascript failed'
end

#unerb(js) ⇒ Object



130
131
132
133
134
# File 'lib/flay_js.rb', line 130

def unerb(js)
  js.gsub(/(<%=.*?%>)/) do |erb|
    erb.gsub(/[^\w]+/,'_')
  end
end

#uninterpolate(js) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/flay_js.rb', line 136

def uninterpolate(js)
  # WOW!!!!!
  js.gsub(/(\#{[^{}]*})/) do |str|
    str.gsub(/[^\w]+/,'_')
  end.gsub(/(\#{.*})/) do |str|
    str.gsub(/[^#]({[^{}]*})/) do |sub|
      sub.gsub(/[^\w]+/,'_')
    end.gsub(/(\#?{[^{}]*})/) do |sub|
      sub.gsub(/[^\w]+/,'_')
    end
  end
end