opal 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +40 -9
  3. data/CHANGELOG.md +349 -0
  4. data/Gemfile +7 -8
  5. data/README.md +25 -3
  6. data/Rakefile +4 -2
  7. data/bin/opal +1 -1
  8. data/examples/rack/Gemfile +3 -0
  9. data/examples/rack/app/application.rb +13 -0
  10. data/examples/rack/app/user.rb +21 -0
  11. data/examples/rack/config.ru +7 -0
  12. data/examples/rack/index.html.erb +10 -0
  13. data/examples/sinatra/Gemfile +4 -0
  14. data/examples/sinatra/app/application.rb +7 -0
  15. data/examples/sinatra/config.ru +21 -0
  16. data/lib/mspec/opal/rake_task.rb +29 -8
  17. data/lib/mspec/opal/runner.rb +5 -4
  18. data/lib/opal.rb +1 -0
  19. data/lib/opal/builder.rb +0 -28
  20. data/lib/opal/cli.rb +0 -14
  21. data/lib/opal/compiler.rb +12 -11
  22. data/lib/opal/fragment.rb +8 -1
  23. data/lib/opal/nodes/array.rb +1 -1
  24. data/lib/opal/nodes/base.rb +4 -0
  25. data/lib/opal/nodes/call.rb +6 -2
  26. data/lib/opal/nodes/call_special.rb +1 -1
  27. data/lib/opal/nodes/class.rb +2 -2
  28. data/lib/opal/nodes/constants.rb +3 -1
  29. data/lib/opal/nodes/helpers.rb +23 -14
  30. data/lib/opal/nodes/if.rb +16 -9
  31. data/lib/opal/nodes/literal.rb +37 -5
  32. data/lib/opal/nodes/logic.rb +7 -1
  33. data/lib/opal/nodes/module.rb +2 -2
  34. data/lib/opal/nodes/scope.rb +13 -2
  35. data/lib/opal/nodes/top.rb +9 -0
  36. data/lib/opal/nodes/variables.rb +5 -2
  37. data/lib/opal/parser.rb +306 -71
  38. data/lib/opal/parser/grammar.rb +2667 -2775
  39. data/lib/opal/parser/grammar.y +177 -233
  40. data/lib/opal/parser/lexer.rb +511 -427
  41. data/lib/opal/parser/sexp.rb +15 -3
  42. data/lib/opal/source_map.rb +8 -4
  43. data/lib/opal/sprockets.rb +4 -0
  44. data/lib/opal/sprockets/cache_key_fix.rb +17 -0
  45. data/lib/opal/sprockets/environment.rb +21 -0
  46. data/lib/opal/sprockets/erb.rb +30 -0
  47. data/lib/opal/sprockets/processor.rb +127 -0
  48. data/lib/opal/sprockets/server.rb +166 -0
  49. data/lib/opal/util.rb +29 -0
  50. data/lib/opal/version.rb +1 -1
  51. data/opal.gemspec +1 -1
  52. data/opal/corelib/array.rb +106 -187
  53. data/opal/corelib/array/inheritance.rb +113 -0
  54. data/opal/corelib/basic_object.rb +6 -2
  55. data/opal/corelib/boolean.rb +4 -0
  56. data/opal/corelib/class.rb +2 -0
  57. data/opal/corelib/complex.rb +3 -0
  58. data/opal/corelib/enumerable.rb +75 -8
  59. data/opal/corelib/enumerator.rb +2 -0
  60. data/opal/corelib/error.rb +23 -23
  61. data/opal/corelib/hash.rb +5 -5
  62. data/opal/corelib/helpers.rb +51 -16
  63. data/opal/corelib/io.rb +7 -24
  64. data/opal/corelib/kernel.rb +23 -11
  65. data/opal/corelib/module.rb +44 -47
  66. data/opal/corelib/nil_class.rb +4 -0
  67. data/opal/corelib/numeric.rb +101 -15
  68. data/opal/corelib/range.rb +2 -0
  69. data/opal/corelib/rational.rb +3 -0
  70. data/opal/corelib/regexp.rb +36 -17
  71. data/opal/corelib/runtime.js +22 -7
  72. data/opal/corelib/string.rb +213 -110
  73. data/opal/corelib/string/inheritance.rb +78 -0
  74. data/opal/corelib/struct.rb +8 -0
  75. data/opal/corelib/time.rb +54 -42
  76. data/opal/corelib/variables.rb +24 -0
  77. data/opal/opal.rb +5 -27
  78. data/spec/cli/compiler_spec.rb +136 -0
  79. data/spec/cli/dependency_resolver_spec.rb +40 -0
  80. data/spec/cli/lexer_spec.rb +110 -0
  81. data/spec/cli/parser/alias_spec.rb +26 -0
  82. data/spec/cli/parser/and_spec.rb +13 -0
  83. data/spec/cli/parser/attrasgn_spec.rb +28 -0
  84. data/spec/cli/parser/begin_spec.rb +42 -0
  85. data/spec/cli/parser/block_spec.rb +12 -0
  86. data/spec/cli/parser/break_spec.rb +17 -0
  87. data/spec/cli/parser/call_spec.rb +139 -0
  88. data/spec/cli/parser/class_spec.rb +35 -0
  89. data/spec/cli/parser/comments_spec.rb +11 -0
  90. data/spec/cli/parser/def_spec.rb +61 -0
  91. data/spec/cli/parser/if_spec.rb +26 -0
  92. data/spec/cli/parser/iter_spec.rb +59 -0
  93. data/spec/cli/parser/lambda_spec.rb +64 -0
  94. data/spec/cli/parser/literal_spec.rb +113 -0
  95. data/spec/cli/parser/masgn_spec.rb +37 -0
  96. data/spec/cli/parser/module_spec.rb +27 -0
  97. data/spec/cli/parser/not_spec.rb +27 -0
  98. data/spec/cli/parser/op_asgn1_spec.rb +23 -0
  99. data/spec/cli/parser/op_asgn2_spec.rb +23 -0
  100. data/spec/cli/parser/or_spec.rb +13 -0
  101. data/spec/cli/parser/return_spec.rb +17 -0
  102. data/spec/cli/parser/sclass_spec.rb +21 -0
  103. data/spec/cli/parser/string_spec.rb +269 -0
  104. data/spec/cli/parser/super_spec.rb +20 -0
  105. data/spec/cli/parser/undef_spec.rb +15 -0
  106. data/spec/cli/parser/unless_spec.rb +13 -0
  107. data/spec/cli/parser/variables_spec.rb +92 -0
  108. data/spec/cli/parser/while_spec.rb +15 -0
  109. data/spec/cli/parser/yield_spec.rb +20 -0
  110. data/spec/cli/spec_helper.rb +31 -11
  111. data/spec/opal/core/array/set_range_to_array_spec.rb +7 -0
  112. data/spec/opal/core/date_spec.rb +122 -0
  113. data/spec/opal/core/language/predefined_spec.rb +1 -1
  114. data/spec/opal/core/runtime/operator_call_spec.rb +13 -0
  115. data/spec/opal/core/runtime/truthy_spec.rb +23 -0
  116. data/spec/opal/filters/bugs/array.rb +96 -87
  117. data/spec/opal/filters/bugs/basic_object.rb +9 -0
  118. data/spec/opal/filters/bugs/class.rb +16 -0
  119. data/spec/opal/filters/bugs/enumerable.rb +54 -0
  120. data/spec/opal/filters/bugs/language.rb +37 -3
  121. data/spec/opal/filters/bugs/math.rb +93 -0
  122. data/spec/opal/filters/bugs/nil.rb +7 -0
  123. data/spec/opal/filters/bugs/numeric.rb +19 -0
  124. data/spec/opal/filters/bugs/opal.rb +12 -0
  125. data/spec/opal/filters/bugs/regexp.rb +0 -2
  126. data/spec/opal/filters/bugs/string.rb +317 -19
  127. data/spec/opal/filters/bugs/struct.rb +29 -0
  128. data/spec/opal/filters/bugs/time.rb +130 -9
  129. data/spec/opal/filters/unsupported/encoding.rb +52 -4
  130. data/spec/opal/filters/unsupported/enumerator.rb +0 -3
  131. data/spec/opal/filters/unsupported/integer_size.rb +7 -0
  132. data/spec/opal/filters/unsupported/method_added.rb +10 -0
  133. data/spec/opal/filters/unsupported/mutable_strings.rb +299 -1
  134. data/spec/opal/filters/unsupported/private_constants.rb +30 -0
  135. data/spec/opal/filters/unsupported/private_methods.rb +16 -0
  136. data/spec/opal/filters/unsupported/random.rb +4 -0
  137. data/spec/opal/filters/unsupported/tainted.rb +53 -0
  138. data/spec/opal/filters/unsupported/trusted.rb +5 -0
  139. data/spec/opal/rubyspecs +167 -234
  140. data/spec/opal/spec_helper.rb +3 -0
  141. data/spec/opal/stdlib/promise/error_spec.rb +15 -0
  142. data/spec/opal/stdlib/promise/rescue_spec.rb +35 -0
  143. data/spec/opal/stdlib/promise/then_spec.rb +54 -0
  144. data/spec/opal/stdlib/promise/trace_spec.rb +35 -0
  145. data/spec/opal/stdlib/promise/value_spec.rb +15 -0
  146. data/spec/opal/stdlib/promise/when_spec.rb +34 -0
  147. data/stdlib/base64.rb +152 -0
  148. data/stdlib/date.rb +82 -49
  149. data/{opal/corelib → stdlib}/encoding.rb +3 -1
  150. data/stdlib/erb.rb +0 -1
  151. data/stdlib/json.rb +10 -26
  152. data/stdlib/math.rb +370 -0
  153. data/stdlib/native.rb +40 -33
  154. data/stdlib/opal-parser.rb +7 -4
  155. data/stdlib/promise.rb +292 -0
  156. data/stdlib/strscan.rb +1 -1
  157. data/stdlib/template.rb +1 -3
  158. data/stdlib/time.rb +9 -0
  159. metadata +143 -204
  160. data/doc/compiler.md +0 -42
  161. data/doc/compiler_options.md +0 -5
  162. data/doc/examples/node_http_server.rb +0 -49
  163. data/doc/external_libraries.md +0 -9
  164. data/doc/generated_javascript.md +0 -272
  165. data/doc/home.md +0 -17
  166. data/doc/method_missing.md +0 -58
  167. data/doc/static_applications.md +0 -60
  168. data/doc/using_ruby_from_javascript.md +0 -18
  169. data/doc/using_sprockets.md +0 -65
  170. data/spec/opal/core/numeric/abs_spec.rb +0 -12
  171. data/spec/opal/core/numeric/downto_spec.rb +0 -19
  172. data/spec/opal/core/numeric/equal_value_spec.rb +0 -9
  173. data/spec/opal/core/numeric/even_spec.rb +0 -21
  174. data/spec/opal/core/numeric/magnitude_spec.rb +0 -12
  175. data/spec/opal/core/numeric/odd_spec.rb +0 -21
  176. data/spec/opal/core/string/chop_spec.rb +0 -10
  177. data/spec/opal/core/string/chr_spec.rb +0 -13
  178. data/spec/opal/core/string/clone_spec.rb +0 -8
  179. data/spec/opal/core/string/comparison_spec.rb +0 -13
  180. data/spec/opal/core/string/dup_spec.rb +0 -8
  181. data/spec/opal/core/string/element_reference_spec.rb +0 -96
  182. data/spec/opal/core/string/fixtures/classes.rb +0 -49
  183. data/spec/opal/core/string/format_spec.rb +0 -9
  184. data/spec/opal/core/string/freeze_spec.rb +0 -15
  185. data/spec/opal/core/string/gsub_spec.rb +0 -31
  186. data/spec/opal/core/string/lines_spec.rb +0 -9
  187. data/spec/opal/core/string/ljust_spec.rb +0 -32
  188. data/spec/opal/core/string/lstrip_spec.rb +0 -7
  189. data/spec/opal/core/string/match_spec.rb +0 -49
  190. data/spec/opal/core/string/next_spec.rb +0 -10
  191. data/spec/opal/core/string/ord_spec.rb +0 -9
  192. data/spec/opal/core/string/partition_spec.rb +0 -10
  193. data/spec/opal/core/string/rindex_spec.rb +0 -50
  194. data/spec/opal/core/string/rjust_spec.rb +0 -32
  195. data/spec/opal/core/string/rstrip_spec.rb +0 -7
  196. data/spec/opal/core/string/scan_spec.rb +0 -66
  197. data/spec/opal/core/string/slice_spec.rb +0 -74
  198. data/spec/opal/core/string/split_spec.rb +0 -5
  199. data/spec/opal/core/string/strip_spec.rb +0 -6
  200. data/spec/opal/core/string/sub_spec.rb +0 -38
  201. data/spec/opal/core/string/succ_spec.rb +0 -10
  202. data/spec/opal/core/string/sum_spec.rb +0 -5
  203. data/spec/opal/core/string/to_f_spec.rb +0 -14
  204. data/spec/opal/core/string/to_i_spec.rb +0 -25
  205. data/spec/opal/core/string/tr_s_spec.rb +0 -31
  206. data/spec/opal/core/string/tr_spec.rb +0 -31
  207. data/spec/opal/filters/bugs/parser.rb +0 -10
  208. data/spec/opal/filters/unsupported/immutable_strings.rb +0 -24
  209. data/spec/opal/filters/unsupported/string_subclasses.rb +0 -8
  210. data/spec/opal/parser/alias_spec.rb +0 -26
  211. data/spec/opal/parser/and_spec.rb +0 -13
  212. data/spec/opal/parser/array_spec.rb +0 -22
  213. data/spec/opal/parser/attrasgn_spec.rb +0 -28
  214. data/spec/opal/parser/begin_spec.rb +0 -42
  215. data/spec/opal/parser/block_spec.rb +0 -12
  216. data/spec/opal/parser/break_spec.rb +0 -17
  217. data/spec/opal/parser/call_spec.rb +0 -131
  218. data/spec/opal/parser/class_spec.rb +0 -35
  219. data/spec/opal/parser/const_spec.rb +0 -13
  220. data/spec/opal/parser/cvar_spec.rb +0 -11
  221. data/spec/opal/parser/def_spec.rb +0 -61
  222. data/spec/opal/parser/false_spec.rb +0 -17
  223. data/spec/opal/parser/file_spec.rb +0 -7
  224. data/spec/opal/parser/gvar_spec.rb +0 -13
  225. data/spec/opal/parser/hash_spec.rb +0 -17
  226. data/spec/opal/parser/heredoc_spec.rb +0 -30
  227. data/spec/opal/parser/iasgn_spec.rb +0 -9
  228. data/spec/opal/parser/if_spec.rb +0 -26
  229. data/spec/opal/parser/int_spec.rb +0 -13
  230. data/spec/opal/parser/iter_spec.rb +0 -59
  231. data/spec/opal/parser/ivar_spec.rb +0 -9
  232. data/spec/opal/parser/lambda_spec.rb +0 -64
  233. data/spec/opal/parser/lasgn_spec.rb +0 -8
  234. data/spec/opal/parser/line_spec.rb +0 -8
  235. data/spec/opal/parser/lvar_spec.rb +0 -38
  236. data/spec/opal/parser/masgn_spec.rb +0 -37
  237. data/spec/opal/parser/module_spec.rb +0 -27
  238. data/spec/opal/parser/nil_spec.rb +0 -17
  239. data/spec/opal/parser/not_spec.rb +0 -27
  240. data/spec/opal/parser/nth_ref_spec.rb +0 -13
  241. data/spec/opal/parser/op_asgn1_spec.rb +0 -23
  242. data/spec/opal/parser/op_asgn2_spec.rb +0 -23
  243. data/spec/opal/parser/or_spec.rb +0 -13
  244. data/spec/opal/parser/parse_spec.rb +0 -66
  245. data/spec/opal/parser/regexp_spec.rb +0 -16
  246. data/spec/opal/parser/return_spec.rb +0 -17
  247. data/spec/opal/parser/sclass_spec.rb +0 -21
  248. data/spec/opal/parser/self_spec.rb +0 -17
  249. data/spec/opal/parser/str_spec.rb +0 -107
  250. data/spec/opal/parser/string_spec.rb +0 -8
  251. data/spec/opal/parser/super_spec.rb +0 -20
  252. data/spec/opal/parser/true_spec.rb +0 -17
  253. data/spec/opal/parser/undef_spec.rb +0 -15
  254. data/spec/opal/parser/unless_spec.rb +0 -13
  255. data/spec/opal/parser/while_spec.rb +0 -15
  256. data/spec/opal/parser/xstr_spec.rb +0 -116
  257. data/spec/opal/parser/yield_spec.rb +0 -20
@@ -1,10 +1,10 @@
1
1
  module Opal
2
2
  class Sexp
3
3
 
4
- attr_accessor :line
5
- attr_accessor :end_line
6
4
  attr_reader :array
7
5
 
6
+ attr_accessor :source
7
+
8
8
  def initialize(args)
9
9
  @array = args
10
10
  end
@@ -53,8 +53,20 @@ module Opal
53
53
 
54
54
  alias eql? ==
55
55
 
56
+ def line
57
+ @source && @source[0]
58
+ end
59
+
60
+ def column
61
+ @source && @source[1]
62
+ end
63
+
56
64
  def inspect
57
- "(#{@array.map { |e| e.inspect }.join ' '})"
65
+ "(#{@array.map { |e| e.inspect }.join ', '})"
66
+ end
67
+
68
+ def pretty_inspect
69
+ "(#{line ? "#{line} " : ''}#{@array.map { |e| e.inspect }.join ', '})"
58
70
  end
59
71
 
60
72
  alias to_s inspect
@@ -21,15 +21,19 @@ module Opal
21
21
  :generated_line => line,
22
22
  :generated_col => column,
23
23
  :source_line => source_line,
24
- :source_col => 0,
24
+ :source_col => fragment.column,
25
25
  :source => file
26
26
  )
27
27
  end
28
28
 
29
-
30
29
  new_lines = fragment.code.count "\n"
31
30
  line += new_lines
32
- column = 0
31
+
32
+ if new_lines > 0
33
+ column = fragment.code.size - (fragment.code.rindex("\n") + 1)
34
+ else
35
+ column += fragment.code.size
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -43,7 +47,7 @@ module Opal
43
47
  end
44
48
 
45
49
  def magic_comment map_path
46
- "\n//@ sourceMappingURL=file://#{map_path}"
50
+ "\n//# sourceMappingURL=file://#{map_path}"
47
51
  end
48
52
  end
49
53
  end
@@ -0,0 +1,4 @@
1
+ require 'opal/sprockets/environment'
2
+ require 'opal/sprockets/processor'
3
+ require 'opal/sprockets/erb'
4
+ require 'opal/sprockets/server'
@@ -0,0 +1,17 @@
1
+ require 'sprockets'
2
+ require 'sprockets/base'
3
+
4
+ module Sprockets
5
+ class Base
6
+ def cache_key_for(path, options)
7
+ "#{path}:#{options[:bundle] ? '1' : '0'}"
8
+ processors = attributes_for(path).processors
9
+ processors_key = processors.map do |p|
10
+ version = p.respond_to?(:version) ? p.version : '0'
11
+ "#{p.name}-#{version}"
12
+ end.join(':')
13
+
14
+ "#{path}:#{options[:bundle] ? '1' : '0'}:#{processors_key}"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'sprockets'
2
+
3
+ module Opal
4
+ # Environment is a subclass of Sprockets::Environment which already has our opal
5
+ # load paths loaded. This makes it easy for stand-alone rack apps, or test runners
6
+ # that have opal load paths ready to use. You can also add an existing gem's lib
7
+ # directory to our load path to use real gems inside your opal environment.
8
+ #
9
+ # If you are running rails, then you just need opal-rails instead, which will
10
+ # do this for you.
11
+ class Environment < ::Sprockets::Environment
12
+ def initialize *args
13
+ super
14
+ Opal.paths.each { |p| append_path p }
15
+ end
16
+
17
+ def use_gem gem_name
18
+ append_path File.join(Gem::Specification.find_by_name(gem_name).gem_dir, 'lib')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ require 'opal'
2
+ require 'opal/compiler'
3
+ require 'sprockets'
4
+
5
+ module Opal
6
+ module ERB
7
+ class Processor < Tilt::Template
8
+ self.default_mime_type = 'application/javascript'
9
+
10
+ def self.engine_initialized?
11
+ true
12
+ end
13
+
14
+ def initialize_engine
15
+ require_template_library 'opal'
16
+ end
17
+
18
+ def prepare
19
+ end
20
+
21
+ def evaluate(context, locals, &block)
22
+ context.require_asset 'erb'
23
+ Opal::ERB.compile data, context.logical_path.sub(/^templates\//, '')
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ Tilt.register 'opalerb', Opal::ERB::Processor
30
+ Sprockets.register_engine '.opalerb', Opal::ERB::Processor
@@ -0,0 +1,127 @@
1
+ require 'set'
2
+ require 'sprockets'
3
+ require 'opal/version'
4
+
5
+ $OPAL_SOURCE_MAPS = {}
6
+
7
+ module Opal
8
+ # Proccess using Sprockets
9
+ #
10
+ # Opal.process('opal-jquery') # => String
11
+ def self.process asset
12
+ Environment.new[asset].to_s
13
+ end
14
+
15
+ # The Processor class is used to make ruby files (with rb or opal extensions)
16
+ # available to any sprockets based server. Processor will then get passed any
17
+ # ruby source file to build. There are some options you can override globally
18
+ # which effect how certain ruby features are handled:
19
+ #
20
+ # * method_missing_enabled [true by default]
21
+ # * optimized_operators_enabled [true by default]
22
+ # * arity_check_enabled [false by default]
23
+ # * const_missing_enabled [true by default]
24
+ # * dynamic_require_severity [true by default]
25
+ # * source_map_enabled [true by default]
26
+ # * irb_enabled [false by default]
27
+ #
28
+ class Processor < Tilt::Template
29
+ self.default_mime_type = 'application/javascript'
30
+
31
+ def self.engine_initialized?
32
+ true
33
+ end
34
+
35
+ def self.version
36
+ ::Opal::VERSION
37
+ end
38
+
39
+ class << self
40
+ attr_accessor :method_missing_enabled
41
+ attr_accessor :arity_check_enabled
42
+ attr_accessor :const_missing_enabled
43
+ attr_accessor :dynamic_require_severity
44
+ attr_accessor :source_map_enabled
45
+ attr_accessor :irb_enabled
46
+ end
47
+
48
+ self.method_missing_enabled = true
49
+ self.arity_check_enabled = false
50
+ self.const_missing_enabled = true
51
+ self.dynamic_require_severity = :error # :error, :warning or :ignore
52
+ self.source_map_enabled = true
53
+ self.irb_enabled = false
54
+
55
+ def self.stub_file(name)
56
+ stubbed_files << name.to_s
57
+ end
58
+
59
+ def self.stubbed_files
60
+ @stubbed_files ||= Set.new
61
+ end
62
+
63
+ def initialize_engine
64
+ require_template_library 'opal'
65
+ end
66
+
67
+ def prepare
68
+ end
69
+
70
+ def evaluate(context, locals, &block)
71
+ options = {
72
+ :method_missing => self.class.method_missing_enabled,
73
+ :arity_check => self.class.arity_check_enabled,
74
+ :const_missing => self.class.const_missing_enabled,
75
+ :dynamic_require_severity => self.class.dynamic_require_severity,
76
+ :irb => self.class.irb_enabled,
77
+ :file => context.logical_path,
78
+ }
79
+
80
+ compiler = Opal::Compiler.new
81
+ result = compiler.compile data, options
82
+
83
+ compiler.requires.each do |r|
84
+ next if stubbed_file? r
85
+ path = find_opal_require context.environment, r
86
+ context.require_asset path
87
+ end
88
+
89
+ if self.class.source_map_enabled
90
+ $OPAL_SOURCE_MAPS[context.pathname] = compiler.source_map(source_file_url(context)).to_s
91
+ "#{result}\n//# sourceMappingURL=#{source_map_url(context)}\n"
92
+ else
93
+ result
94
+ end
95
+ end
96
+
97
+ def source_map_url(context)
98
+ "#{prefix}/#{context.logical_path}.js.map"
99
+ end
100
+
101
+ def source_file_url(context)
102
+ "#{prefix}/#{context.logical_path.to_s}"
103
+ end
104
+
105
+ def prefix
106
+ "/__opal_source_maps__"
107
+ end
108
+
109
+ def stubbed_file?(name)
110
+ self.class.stubbed_files.include? name
111
+ end
112
+
113
+ def find_opal_require(environment, r)
114
+ path = environment.paths.find do |p|
115
+ File.exist?(File.join(p, "#{r}.rb"))
116
+ end
117
+
118
+ path ? File.join(path, "#{r}.rb") : r
119
+ end
120
+ end
121
+ end
122
+
123
+ Tilt.register 'rb', Opal::Processor
124
+ Sprockets.register_engine '.rb', Opal::Processor
125
+
126
+ Tilt.register 'opal', Opal::Processor
127
+ Sprockets.register_engine '.opal', Opal::Processor
@@ -0,0 +1,166 @@
1
+ require 'rack/file'
2
+ require 'rack/urlmap'
3
+ require 'rack/builder'
4
+ require 'rack/directory'
5
+ require 'rack/showexceptions'
6
+ require 'opal/source_map'
7
+ require 'opal/sprockets/environment'
8
+ require 'erb'
9
+
10
+ module Opal
11
+
12
+ class SourceMapServer
13
+ def initialize sprockets
14
+ @sprockets = sprockets
15
+ end
16
+
17
+ attr_reader :sprockets
18
+
19
+ attr_writer :prefix
20
+
21
+ def prefix
22
+ @prefix ||= '/__opal_source_maps__'
23
+ end
24
+
25
+ def inspect
26
+ "#<#{self.class}:#{object_id}>"
27
+ end
28
+
29
+ def call(env)
30
+ path_info = env['PATH_INFO']
31
+
32
+ if path_info =~ /\.js\.map$/
33
+ path = env['PATH_INFO'].gsub(/^\/|\.js\.map$/, '')
34
+ asset = sprockets[path]
35
+ return [404, {}, []] if asset.nil?
36
+
37
+ return [200, {"Content-Type" => "text/json"}, [$OPAL_SOURCE_MAPS[asset.pathname].to_s]]
38
+ else
39
+ return [200, {"Content-Type" => "text/text"}, [File.read(sprockets.resolve(path_info))]]
40
+ end
41
+ end
42
+ end
43
+
44
+ class Server
45
+
46
+ attr_accessor :debug, :use_index, :index_path, :main, :public_root, :public_urls, :sprockets
47
+
48
+ def initialize debug_or_options = {}
49
+ unless Hash === debug_or_options
50
+ warn "passing a boolean to control debug is deprecated.\n"+
51
+ "Please pass an Hash instead: Server.new(debug: true)"
52
+ options = {:debug => debug_or_options}
53
+ else
54
+ options = debug_or_options
55
+ end
56
+
57
+ @use_index = true
58
+ @public_root = nil
59
+ @public_urls = ['/']
60
+ @sprockets = Environment.new
61
+ @debug = options.fetch(:debug, true)
62
+
63
+ yield self if block_given?
64
+ create_app
65
+ end
66
+
67
+ def public_dir=(dir)
68
+ @public_root = dir
69
+ @public_urls = ["/"]
70
+ end
71
+
72
+ def source_map=(enabled)
73
+ Opal::Processor.source_map_enabled = enabled
74
+ end
75
+
76
+ def source_map_enabled
77
+ Opal::Processor.source_map_enabled
78
+ end
79
+
80
+ def append_path path
81
+ @sprockets.append_path path
82
+ end
83
+
84
+ def use_gem gem_name
85
+ @sprockets.use_gem gem_name
86
+ end
87
+
88
+ def create_app
89
+ server, sprockets = self, @sprockets
90
+
91
+ @app = Rack::Builder.app do
92
+ not_found = lambda { |env| [404, {}, []] }
93
+
94
+ use Rack::Deflater
95
+ use Rack::ShowExceptions
96
+ map('/assets') { run sprockets }
97
+ map(server.source_maps.prefix) { run server.source_maps } if server.source_map_enabled
98
+ use Index, server if server.use_index
99
+ run Rack::Static.new(not_found, :root => server.public_root, :urls => server.public_urls)
100
+ end
101
+ end
102
+
103
+ def source_maps
104
+ @source_maps ||= SourceMapServer.new(@sprockets)
105
+ end
106
+
107
+ def call(env)
108
+ @app.call env
109
+ end
110
+
111
+ class Index
112
+
113
+ def initialize(app, server)
114
+ @app = app
115
+ @server = server
116
+ @index_path = server.index_path
117
+ end
118
+
119
+ def call(env)
120
+ if %w[/ /index.html].include? env['PATH_INFO']
121
+ [200, { 'Content-Type' => 'text/html' }, [html]]
122
+ else
123
+ @app.call env
124
+ end
125
+ end
126
+
127
+ # Returns the html content for the root path. Supports ERB
128
+ def html
129
+ if @index_path
130
+ raise "index does not exist: #{@index_path}" unless File.exist?(@index_path)
131
+ Tilt.new(@index_path).render(self)
132
+ else
133
+ ::ERB.new(SOURCE).result binding
134
+ end
135
+ end
136
+
137
+ def javascript_include_tag source
138
+ if @server.debug
139
+ assets = @server.sprockets[source].to_a
140
+
141
+ raise "Cannot find asset: #{source}" if assets.empty?
142
+
143
+ scripts = assets.map do |a|
144
+ %Q{<script src="/assets/#{ a.logical_path }?body=1"></script>}
145
+ end
146
+
147
+ scripts.join "\n"
148
+ else
149
+ "<script src=\"/assets/#{source}.js\"></script>"
150
+ end
151
+ end
152
+
153
+ SOURCE = <<-HTML
154
+ <!DOCTYPE html>
155
+ <html>
156
+ <head>
157
+ <title>Opal Server</title>
158
+ </head>
159
+ <body>
160
+ <%= javascript_include_tag @server.main %>
161
+ </body>
162
+ </html>
163
+ HTML
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,29 @@
1
+ module Opal
2
+ module Util
3
+ extend self
4
+
5
+ # Used for uglifying source to minify
6
+ def uglify(str)
7
+ IO.popen('uglifyjs 2> /dev/null', 'r+') do |i|
8
+ i.puts str
9
+ i.close_write
10
+ return i.read
11
+ end
12
+ rescue Errno::ENOENT, Errno::EPIPE
13
+ $stderr.puts '"uglifyjs" command not found (install with: "npm install -g uglify-js")'
14
+ nil
15
+ end
16
+
17
+ # Gzip code to check file size
18
+ def gzip(str)
19
+ IO.popen('gzip -f 2> /dev/null', 'r+') do |i|
20
+ i.puts str
21
+ i.close_write
22
+ return i.read
23
+ end
24
+ rescue Errno::ENOENT, Errno::EPIPE
25
+ $stderr.puts '"gzip" command not found, it is required to produce the .gz version'
26
+ nil
27
+ end
28
+ end
29
+ end