barista 0.6.1 → 0.7.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- data/DESCRIPTION +7 -0
- data/Gemfile +6 -4
- data/Gemfile.lock +23 -12
- data/Rakefile +3 -11
- data/barista.gemspec +53 -50
- data/lib/barista.rb +129 -106
- data/lib/barista/compiler.rb +131 -33
- data/lib/barista/extensions.rb +92 -0
- data/lib/barista/filter.rb +13 -3
- data/lib/barista/framework.rb +48 -13
- data/lib/barista/haml_filter.rb +42 -0
- data/lib/barista/helpers.rb +61 -0
- data/lib/barista/integration.rb +28 -0
- data/lib/barista/integration/rails2.rb +16 -0
- data/lib/barista/integration/rails3.rb +26 -0
- data/lib/barista/integration/sinatra.rb +23 -0
- data/lib/barista/server.rb +110 -0
- data/lib/barista/version.rb +3 -3
- data/lib/generators/barista/install/templates/initializer.rb +0 -13
- metadata +61 -65
- data/.gitignore +0 -21
- data/app/controllers/barista_controller.rb +0 -25
- data/config/routes.rb +0 -3
- data/lib/barista/compilers.rb +0 -9
- data/lib/barista/compilers/base.rb +0 -39
- data/lib/barista/compilers/native.rb +0 -55
- data/lib/barista/compilers/node.rb +0 -59
- data/lib/coffee-script/coffee-script-0.9.4.js +0 -469
data/lib/barista/compiler.rb
CHANGED
@@ -3,53 +3,151 @@ require 'digest/sha2'
|
|
3
3
|
module Barista
|
4
4
|
class Compiler
|
5
5
|
|
6
|
+
# TODO: Deprecate.
|
6
7
|
class << self
|
7
|
-
attr_accessor :bin_path, :js_path
|
8
|
-
end
|
9
|
-
self.bin_path ||= "coffee"
|
10
|
-
self.js_path ||= File.expand_path('../coffee-script/coffee-script-0.9.4.js', File.dirname(__FILE__))
|
11
8
|
|
12
|
-
|
13
|
-
|
9
|
+
def js_path
|
10
|
+
CoffeeScript::Source.path
|
11
|
+
end
|
12
|
+
|
13
|
+
def js_path=(value)
|
14
|
+
CoffeeScript::Source.path = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def bin_path
|
18
|
+
CoffeeScript::Engines::Node.binary
|
19
|
+
end
|
20
|
+
|
21
|
+
def bin_path=(path)
|
22
|
+
CoffeeScript::Engines::Node.binary = path
|
23
|
+
end
|
24
|
+
|
25
|
+
def available?
|
26
|
+
CoffeeScript.engine.present? && CoffeeScript.engine.supported?
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_availability!(silence = false)
|
30
|
+
available = available?
|
31
|
+
if !available && Barista.exception_on_error? && !silence
|
32
|
+
raise CompilerUnavailableError, "No method of compiling cofffescript is currently available. Please install therubyracer or node."
|
33
|
+
end
|
34
|
+
available
|
35
|
+
end
|
36
|
+
|
37
|
+
def compile(content, options = {})
|
38
|
+
self.new(content, options).to_js
|
39
|
+
end
|
40
|
+
|
41
|
+
def autocompile_file(file, force = false, silence_error = false)
|
42
|
+
# Ensure we have a coffeescript compiler available.
|
43
|
+
if !check_availability!(silence_error)
|
44
|
+
Barista.debug "The coffeescript compiler at '#{Compiler.bin_path}' is currently unavailable."
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
# Expand the path from the framework.
|
48
|
+
origin_path, framework = Framework.full_path_for(file)
|
49
|
+
return if origin_path.nil?
|
50
|
+
destination_path = framework.output_path_for(file)
|
51
|
+
return File.read(destination_path) unless dirty?(origin_path, destination_path) || force
|
52
|
+
Barista.debug "Compiling #{file} from framework '#{framework.name}'"
|
53
|
+
compiler = new(origin_path, :silence_error => silence_error, :output_path => destination_path)
|
54
|
+
content = compiler.to_js
|
55
|
+
compiler.save
|
56
|
+
content
|
57
|
+
end
|
58
|
+
|
59
|
+
def compile_as(file, type)
|
60
|
+
origin_path, framework = Framework.full_path_for(file)
|
61
|
+
return if origin_path.nil?
|
62
|
+
if type == :coffeescript
|
63
|
+
return File.read(origin_path), File.mtime(origin_path)
|
64
|
+
else
|
65
|
+
return autocompile_file(file), Time.now
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def dirty?(from, to)
|
70
|
+
File.exist?(from) && (!File.exist?(to) || File.mtime(to) < File.mtime(from))
|
71
|
+
end
|
72
|
+
|
73
|
+
def setup_default_error_logger
|
74
|
+
Barista.on_compilation_error do |where, message|
|
75
|
+
if Barista.verbose?
|
76
|
+
Barista.debug "There was an error compiling coffeescript from #{where}:"
|
77
|
+
message.each_line { |line| Barista.debug line.rstrip }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
14
82
|
end
|
15
83
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
self.compiler_klass = nil
|
84
|
+
def initialize(context, options = {})
|
85
|
+
@compiled = false
|
86
|
+
@options = options
|
87
|
+
setup_compiler_context context
|
21
88
|
end
|
22
|
-
|
23
|
-
def
|
24
|
-
|
89
|
+
|
90
|
+
def compile!
|
91
|
+
location = @options.fetch(:origin, 'inline')
|
92
|
+
@compiled_content = compile(@context, location)
|
93
|
+
@compiled_content = preamble(location) + @compiled_content if Barista.add_preamble?
|
94
|
+
@compiled = true
|
25
95
|
end
|
26
|
-
|
27
|
-
def
|
28
|
-
|
96
|
+
|
97
|
+
def to_js
|
98
|
+
compile! unless defined?(@compiled) && @compiled
|
99
|
+
@compiled_content
|
29
100
|
end
|
30
101
|
|
31
|
-
def
|
32
|
-
|
102
|
+
def compile(script, where = 'inline')
|
103
|
+
Barista.invoke_hook :before_compilation, where
|
104
|
+
out = CoffeeScript.compile script, :bare => Barista.bare?
|
105
|
+
Barista.invoke_hook :compiled, where
|
106
|
+
out
|
107
|
+
rescue CoffeeScript::Error => e
|
108
|
+
Barista.invoke_hook :compilation_failed, where, e.message
|
109
|
+
if Barista.exception_on_error? && !@options[:silence]
|
110
|
+
raise CompilationError, "CoffeeScript encountered an error compiling #{where}: #{e.message}"
|
111
|
+
end
|
112
|
+
compilation_error_for where, e.message
|
33
113
|
end
|
34
114
|
|
35
|
-
def
|
36
|
-
|
115
|
+
def save(path = @options[:output_path])
|
116
|
+
return false unless path.is_a?(String) && !to_js.nil?
|
117
|
+
FileUtils.mkdir_p File.dirname(path)
|
118
|
+
File.open(path, "w+") { |f| f.write @compiled_content }
|
119
|
+
true
|
120
|
+
rescue Errno::EACCES
|
121
|
+
false
|
37
122
|
end
|
38
123
|
|
39
|
-
|
40
|
-
available?.tap do |available|
|
41
|
-
if !available && Barista.exception_on_error? && !silence
|
42
|
-
raise CompilerUnavailableError, "A coffee script compiler is currently unavailable. Please install therubyracer or coffee-script via node"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
124
|
+
protected
|
46
125
|
|
47
|
-
def
|
48
|
-
|
126
|
+
def preamble(location)
|
127
|
+
"/* DO NOT MODIFY. This file was compiled #{Time.now.httpdate} from\n * #{location.strip}\n */\n\n"
|
49
128
|
end
|
50
|
-
|
51
|
-
def
|
52
|
-
|
129
|
+
|
130
|
+
def compilation_error_for(location, message)
|
131
|
+
details = "Compilation of '#{location}' failed:\n#{message}"
|
132
|
+
Barista.verbose? ? "alert(#{details.to_json});" : nil
|
53
133
|
end
|
134
|
+
|
135
|
+
def setup_compiler_context(context)
|
136
|
+
if context.respond_to?(:read)
|
137
|
+
@context = context.read
|
138
|
+
@type = :string
|
139
|
+
default_path = context.respond_to?(:path) ? context.path : 'inline'
|
140
|
+
@options[:origin] ||= default_path
|
141
|
+
elsif !context.include?("\n") && File.exist?(context)
|
142
|
+
@context = File.read(context)
|
143
|
+
@type = :file
|
144
|
+
@options[:origin] ||= context
|
145
|
+
else
|
146
|
+
@context = context.to_s
|
147
|
+
@type = :string
|
148
|
+
@options[:origin] ||= 'inline'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
54
152
|
end
|
55
153
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Barista
|
2
|
+
module Extensions
|
3
|
+
|
4
|
+
def self.included(parent)
|
5
|
+
parent.class_eval do
|
6
|
+
extend ClassMethods
|
7
|
+
include InstanceMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def has_boolean_options(*names)
|
14
|
+
source = []
|
15
|
+
names.each do |name|
|
16
|
+
source << <<-EOM
|
17
|
+
|
18
|
+
def #{name}!
|
19
|
+
@#{name} = true
|
20
|
+
end
|
21
|
+
|
22
|
+
def #{name}?
|
23
|
+
defined?(@#{name}) ? @#{name} : default_for_#{name}
|
24
|
+
end
|
25
|
+
|
26
|
+
def #{name}=(value)
|
27
|
+
@#{name} = !!value
|
28
|
+
end
|
29
|
+
|
30
|
+
def default_for_#{name}
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
EOM
|
35
|
+
end
|
36
|
+
class_eval source.join("\n"), __FILE__, __LINE__
|
37
|
+
end
|
38
|
+
|
39
|
+
def has_hook_method(options)
|
40
|
+
source = []
|
41
|
+
options.each_pair do |name, event|
|
42
|
+
source << <<-EOM
|
43
|
+
def #{name}(&blk)
|
44
|
+
on_hook #{event.to_sym.inspect}, &blk
|
45
|
+
end
|
46
|
+
EOM
|
47
|
+
end
|
48
|
+
class_eval source.join("\n"), __FILE__, __LINE__
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_delegate_methods(delegate, *args)
|
52
|
+
source = []
|
53
|
+
args.each do |method|
|
54
|
+
source << <<-EOM
|
55
|
+
|
56
|
+
def #{method}(*args, &blk)
|
57
|
+
#{delegate}.send(:#{method}, *args, &blk)
|
58
|
+
end
|
59
|
+
|
60
|
+
EOM
|
61
|
+
end
|
62
|
+
class_eval source.join("\n"), __FILE__, __LINE__
|
63
|
+
end
|
64
|
+
|
65
|
+
def has_deprecated_methods(*args)
|
66
|
+
source = []
|
67
|
+
args.each do |method|
|
68
|
+
source << <<-EOM
|
69
|
+
|
70
|
+
def #{method}(*args, &blk)
|
71
|
+
Barista.deprecate!(self, :#{method})
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
EOM
|
76
|
+
end
|
77
|
+
class_eval source.join("\n"), __FILE__, __LINE__
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
module InstanceMethods
|
83
|
+
|
84
|
+
def deprecate!(object, method, other = nil)
|
85
|
+
klass_prefix = (object.is_a?(Class) || object.is_a?(Module)) ? "#{object.name}." : "#{object.class.name}#"
|
86
|
+
warn "#{klass_prefix}#{method} is deprecated and will be removed in 1.0. #{other}".strip
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
data/lib/barista/filter.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
module Barista
|
2
2
|
class Filter
|
3
3
|
|
4
|
-
def
|
5
|
-
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
dup._call(env)
|
10
|
+
end
|
11
|
+
|
12
|
+
def _call(env)
|
13
|
+
Barista.debug 'Compiling all scripts for barista'
|
6
14
|
Barista.compile_all!
|
15
|
+
# Now, actually call the app.
|
16
|
+
@app.call env
|
7
17
|
end
|
8
18
|
|
9
19
|
end
|
10
|
-
end
|
20
|
+
end
|
data/lib/barista/framework.rb
CHANGED
@@ -10,9 +10,9 @@ module Barista
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.all(include_default = false)
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
(@all ||= []).dup.tap do |all|
|
14
|
+
all.unshift default_framework if include_default
|
15
|
+
end
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.exposed_coffeescripts
|
@@ -20,6 +20,10 @@ module Barista
|
|
20
20
|
collection + fw.exposed_coffeescripts
|
21
21
|
end.uniq.sort_by { |f| f.length }
|
22
22
|
end
|
23
|
+
|
24
|
+
def self.coffeescript_glob_paths
|
25
|
+
all(true).map { |fw| fw.coffeescript_glob_path }
|
26
|
+
end
|
23
27
|
|
24
28
|
def self.full_path_for(script)
|
25
29
|
script = script.to_s.gsub(/\.js$/, '.coffee').gsub(/^\/+/, '')
|
@@ -31,7 +35,7 @@ module Barista
|
|
31
35
|
end
|
32
36
|
|
33
37
|
def self.register(name, root)
|
34
|
-
(@all ||= []) << self.new(name, root)
|
38
|
+
(@all ||= []) << self.new(:name => name, :root => root)
|
35
39
|
end
|
36
40
|
|
37
41
|
def self.[](name)
|
@@ -41,19 +45,34 @@ module Barista
|
|
41
45
|
|
42
46
|
attr_reader :name, :framework_root, :output_prefix
|
43
47
|
|
44
|
-
def initialize(
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
def initialize(options, root = nil, output_prefix = nil)
|
49
|
+
unless options.is_a?(Hash)
|
50
|
+
Barista.deprecate! self, "initialize(name, root = nil, output_prefix = nil)", "Please use the option syntax instead."
|
51
|
+
options = {
|
52
|
+
:name => options,
|
53
|
+
:root => root,
|
54
|
+
:output_prefix => output_prefix
|
55
|
+
}
|
56
|
+
end
|
57
|
+
# actually setup the framework.
|
58
|
+
check_options! options, :name, :root
|
59
|
+
@name = options[:name].to_s
|
60
|
+
@output_prefix = options[:output_prefix]
|
61
|
+
@framework_root = File.expand_path(options[:root].to_s)
|
62
|
+
@output_root = options[:output_root] && Pathname(options[:output_root])
|
48
63
|
end
|
49
64
|
|
50
65
|
def coffeescripts
|
51
|
-
Dir[
|
66
|
+
Dir[coffeescript_glob_path]
|
67
|
+
end
|
68
|
+
|
69
|
+
def coffeescript_glob_path
|
70
|
+
@coffeescript_glob_path ||= File.join(@framework_root, "**", "*.coffee")
|
52
71
|
end
|
53
72
|
|
54
73
|
def short_name(script)
|
55
74
|
short_name = remove_prefix script, @framework_root
|
56
|
-
File.join
|
75
|
+
File.join(*[@output_prefix, short_name].compact)
|
57
76
|
end
|
58
77
|
|
59
78
|
def exposed_coffeescripts
|
@@ -61,8 +80,8 @@ module Barista
|
|
61
80
|
end
|
62
81
|
|
63
82
|
def output_prefix=(value)
|
64
|
-
value = value.to_s.gsub
|
65
|
-
@output_prefix = value.
|
83
|
+
value = value.to_s.gsub(/(^\/|\/$)/, '').strip
|
84
|
+
@output_prefix = value.empty? ? nil : value
|
66
85
|
end
|
67
86
|
|
68
87
|
def full_path_for(name)
|
@@ -70,10 +89,26 @@ module Barista
|
|
70
89
|
File.exist?(full_path) ? full_path : nil
|
71
90
|
end
|
72
91
|
|
92
|
+
def output_root
|
93
|
+
@output_root || Barista.output_root
|
94
|
+
end
|
95
|
+
|
96
|
+
def output_path_for(file, format = 'js')
|
97
|
+
# Strip the leading slashes
|
98
|
+
file = file.to_s.gsub(/^\/+/, '')
|
99
|
+
output_root.join(file).to_s.gsub(/\.[^\.]+$/, ".#{format}")
|
100
|
+
end
|
101
|
+
|
73
102
|
protected
|
74
103
|
|
75
104
|
def remove_prefix(path, prefix)
|
76
|
-
path.to_s.gsub
|
105
|
+
path.to_s.gsub(/^#{Regexp.escape(prefix.to_s)}\/?/, '')
|
106
|
+
end
|
107
|
+
|
108
|
+
def check_options!(options, *keys)
|
109
|
+
keys.each do |option|
|
110
|
+
raise ArgumentError, "#{option.inspect} is a required options." if options[option].nil?
|
111
|
+
end
|
77
112
|
end
|
78
113
|
|
79
114
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Barista
|
2
|
+
module HamlFilter
|
3
|
+
module CoffeeScript
|
4
|
+
|
5
|
+
def render_with_options(text, options)
|
6
|
+
type = render_type
|
7
|
+
case type
|
8
|
+
when :coffeescript
|
9
|
+
content_type = 'text/coffeescript'
|
10
|
+
cdata_wrapper = '#%s'
|
11
|
+
inner = text
|
12
|
+
when :javascript
|
13
|
+
content_type = 'text/javascript'
|
14
|
+
cdata_wrapper = '//%s'
|
15
|
+
inner = Barista::Compiler.compile(text)
|
16
|
+
end
|
17
|
+
output = []
|
18
|
+
output << "<script type=#{options[:attr_wrapper]}#{content_type(type)}#{options[:attr_wrapper]}>"
|
19
|
+
output << " #{cdata_wrapper % '<![CDATA['}"
|
20
|
+
output << " #{inner}".rstrip.gsub("\n", "\n ")
|
21
|
+
output << " #{cdata_wrapper % ']]>'}"
|
22
|
+
output << "</script>"
|
23
|
+
output.join("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
def render_type
|
27
|
+
Barista.embedded_interpreter? ? :coffeescript : :javascript
|
28
|
+
end
|
29
|
+
|
30
|
+
def content_type(render_type)
|
31
|
+
Barista::Server::CONTENT_TYPE_MAPPING[render_type]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.setup
|
37
|
+
if defined?(Haml)
|
38
|
+
CoffeeScript.module_eval { include Haml::Filters::Base }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|