Module: Guard::CoffeeScript::Runner

Defined in:
lib/guard/coffeescript/runner.rb

Class Attribute Summary (collapse)

Class Method Summary (collapse)

Class Attribute Details

+ (Object) last_run_failed

Returns the value of attribute last_run_failed



8
9
10
# File 'lib/guard/coffeescript/runner.rb', line 8

def last_run_failed
  @last_run_failed
end

Class Method Details

+ (Array<String, String>) compile(filename, options) (private)

Compile the CoffeeScript and generate the source map.

Parameters:

  • filename (String)

    the CoffeeScript file n

  • options (Hash)

    the options for the execution

Options Hash (options):

  • :source_map (Boolean)

    generate the source map files

Returns:

  • (Array<String, String>)

    the JavaScript source and the source map



119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/guard/coffeescript/runner.rb', line 119

def compile(filename, options)
  file = File.read(filename)
  file_options = options_for_file(filename, options)

  if options[:source_map]
    file_options.merge! options_for_source_map(filename, options)
    result = ::CoffeeScript.compile(file, file_options)
    js, map = result['js'], result['v3SourceMap']
  else
    js  = ::CoffeeScript.compile(file, file_options)
  end

  [js, map]
end

+ (Array<Array<String>, Array<String>] the result for the compilation run) compile_files(files, watchers, options) (private)

Compiles all CoffeeScript files and writes the JavaScript files.

Parameters:

  • files (Array<String>)

    the files to compile

  • watchers (Array<Guard::Watcher>)

    the Guard watchers in the block

  • options (Hash)

    the options for the execution

Returns:

  • (Array<Array<String>, Array<String>] the result for the compilation run)

    Array, Array] the result for the compilation run



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
# File 'lib/guard/coffeescript/runner.rb', line 84

def compile_files(files, watchers, options)
  errors        = []
  changed_files = []
  directories   = detect_nested_directories(watchers, files, options)

  directories.each do |directory, scripts|
    scripts.each do |file|
      begin
        js, map = compile(file, options)
        changed_files << write_javascript_file(js, map, file, directory, options)

      rescue => e
        error_message = file + ': ' + e.message.to_s

        if options[:error_to_js]
          js_error_message = "throw \"#{ error_message }\";"
          changed_files << write_javascript_file(js_error_message, nil, file, directory, options)
        end

        errors << error_message
        Formatter.error(error_message)
      end
    end
  end

  [changed_files.flatten.compact, errors]
end

+ (Object) detect_nested_directories(watchers, files, options) (private)

Detects the output directory for each CoffeeScript file. Builds the product of all watchers and assigns to each directory the files to which it belongs to.

Parameters:

  • watchers (Array<Guard::Watcher>)

    the Guard watchers in the block

  • files (Array<String>)

    the CoffeeScript files

  • options (Hash)

    the options for the execution

Options Hash (options):

  • :output (String)

    the output directory

  • :shallow (Boolean)

    do not create nested directories



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/guard/coffeescript/runner.rb', line 227

def detect_nested_directories(watchers, files, options)
  return { options[:output] => files } if options[:shallow]

  directories = { }

  watchers.product(files).each do |watcher, file|
    if matches = file.match(watcher.pattern)
      target = matches[1] ? File.join(options[:output], File.dirname(matches[1])).gsub(/\/\.$/, '') : options[:output] || File.dirname(file)
      if directories[target]
        directories[target] << file
      else
        directories[target] = [file]
      end
    end
  end

  directories
end

+ (Object) javascript_file_name(file, directory) (private)

Calculates the output filename from the coffescript filename and the output directory

Parameters:

  • file (string)

    the CoffeeScript file name

  • directory (String)

    the output directory



213
214
215
# File 'lib/guard/coffeescript/runner.rb', line 213

def javascript_file_name(file, directory)
  File.join(directory, File.basename(file.gsub(/((?:js\.)?(?:coffee|coffee\.md|litcoffee))$/, 'js')))
end

+ (Object) notify_result(changed_files, errors, options = { }) (private)

Writes console and system notifications about the result of the compilation.

Parameters:

  • changed_files (Array<String>)

    the changed JavaScript files

  • errors (Array<String>)

    the error messages

  • options (Hash) (defaults to: { })

    the options for the execution

Options Hash (options):

  • :hide_success (Boolean)

    hide success message notification

  • :noop (Boolean)

    do not generate an output file



254
255
256
257
258
259
260
261
262
263
264
# File 'lib/guard/coffeescript/runner.rb', line 254

def notify_result(changed_files, errors, options = { })
  if !errors.empty?
    self.last_run_failed = true
    Formatter.notify(errors.join("\n"), :title => 'CoffeeScript results', :image => :failed, :priority => 2)
  elsif !options[:hide_success] || last_run_failed
    self.last_run_failed = false
    message = "Successfully #{ options[:noop] ? 'verified' : 'generated' } #{ changed_files.join(', ') }"
    Formatter.success(message)
    Formatter.notify(message, :title => 'CoffeeScript results')
  end
end

+ (Object) notify_start(files, options) (private)

Generates a start compilation notification.

Parameters:

  • files (Array<String>)

    the generated files

  • options (Hash)

    the options for the execution

Options Hash (options):

  • :noop (Boolean)

    do not generate an output file



72
73
74
75
# File 'lib/guard/coffeescript/runner.rb', line 72

def notify_start(files, options)
  message = options[:message] || (options[:noop] ? 'Verify ' : 'Compile ') + files.join(', ')
  Formatter.info(message, :reset => true)
end

+ (Hash) options_for_file(file, options) (private)

Gets the CoffeeScript compilation options.

Parameters:

  • file (String)

    the CoffeeScript file

  • options (Hash)

    the options for the execution of all files

Options Hash (options):

  • :bare (Boolean)

    do not wrap the output in a top level function

Returns:

  • (Hash)

    options for a particular file's execution



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/guard/coffeescript/runner.rb', line 141

def options_for_file(file, options)
  file_options = options.clone

  # if :bare was provided an array of filenames, check for file's inclusion
  if file_options[:bare].respond_to? :include?
    filename            = file[/([^\/]*)\.(?:coffee|coffee\.md|litcoffee)$/]
    file_options[:bare] = file_options[:bare].include?(filename)
  end

  if file[/\.(?:coffee\.md|litcoffee)$/]
    file_options[:literate] = true
  end

  file_options
end

+ (Object) options_for_source_map(filename, options) (private)

Gets the CoffeeScript source map options.

Parameters:

  • filename (String)

    the CoffeeScript filename

  • options (Hash)

    the options for the execution



162
163
164
165
166
167
168
169
170
171
172
# File 'lib/guard/coffeescript/runner.rb', line 162

def options_for_source_map(filename, options)
  # if :input was provided, make all filenames relative to that
  filename = Pathname.new(filename).relative_path_from(Pathname.new(options[:input])).to_s if options[:input]

  {
    :sourceMap => true,
    :generatedFile => filename.gsub(/((?:js\.)?(?:coffee|coffee\.md|litcoffee))$/, 'js'),
    :sourceFiles => [filename],
    :sourceRoot => options[:source_root] || options[:input] || '',
  }
end

+ (Object) remove(files, watchers, options = { })

The remove function deals with CoffeeScript file removal by locating the output javascript file and removing it.

Parameters:

  • files (Array<String>)

    the spec files or directories

  • watchers (Array<Guard::Watcher>)

    the Guard watchers in the block

  • options (Hash) (defaults to: { })

    the options for the removal

Options Hash (options):

  • :output (String)

    the output directory

  • :shallow (Boolean)

    do not create nested directories



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/guard/coffeescript/runner.rb', line 43

def remove(files, watchers, options = { })
  removed_files = []
  directories   = detect_nested_directories(watchers, files, options)

  directories.each do |directory, scripts|
    scripts.each do |file|
      javascript = javascript_file_name(file, directory)
      if File.exists?(javascript)
        FileUtils.remove_file(javascript)
        removed_files << javascript
      end
    end
  end

  if removed_files.length > 0
    message = "Removed #{ removed_files.join(', ') }"
    Formatter.success(message)
    Formatter.notify(message, :title => 'CoffeeScript results')
  end
end

+ (Array<Array<String>, Boolean>) run(files, watchers, options = { })

The CoffeeScript runner handles the CoffeeScript compilation, creates nested directories and the output file, writes the result to the console and triggers optional system notifications.

Parameters:

  • files (Array<String>)

    the spec files or directories

  • watchers (Array<Guard::Watcher>)

    the Guard watchers in the block

  • options (Hash) (defaults to: { })

    the options for the execution

Options Hash (options):

  • :input (String)

    the input directory

  • :output (String)

    the output directory

  • :bare (Boolean)

    do not wrap the output in a top level function

  • :shallow (Boolean)

    do not create nested directories

  • :hide_success (Boolean)

    hide success message notification

  • :noop (Boolean)

    do not generate an output file

  • :source_map (Boolean)

    generate the source map files

Returns:

  • (Array<Array<String>, Boolean>)

    the result for the compilation run



26
27
28
29
30
31
32
# File 'lib/guard/coffeescript/runner.rb', line 26

def run(files, watchers, options = { })
  notify_start(files, options)
  changed_files, errors = compile_files(files, watchers, options)
  notify_result(changed_files, errors, options)

  [changed_files, errors.empty?]
end

+ (String) write_javascript_file(js, map, file, directory, options) (private)

Analyzes the CoffeeScript compilation output and creates the nested directories and writes the output file.

Parameters:

  • js (String)

    the JavaScript content

  • map (String)

    the source map content

  • file (String)

    the CoffeeScript file name

  • directory (String)

    the output directory

  • options (Hash)

    the options for the execution

Options Hash (options):

  • :noop (Boolean)

    do not generate an output file

Returns:

  • (String)

    the JavaScript file name



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/guard/coffeescript/runner.rb', line 185

def write_javascript_file(js, map, file, directory, options)
  directory = Dir.pwd if !directory || directory.empty?
  filename = javascript_file_name(file, directory)

  return filename if options[:noop]

  if options[:source_map]
    map_name = filename + '.map'
    js += "\n/*\n//@ sourceMappingURL=#{File.basename(map_name)}\n*/\n"
  end

  FileUtils.mkdir_p(File.expand_path(directory)) if !File.directory?(directory)
  File.open(File.expand_path(filename), 'w') { |f| f.write(js) }

  if options[:source_map]
    File.open(File.expand_path(map_name), 'w') { |f| f.write(map) }
    [filename, map_name]
  else
    filename
  end
end