opal 0.8.0 → 0.8.1.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +10 -0
- data/docs/compiled_ruby.md +425 -0
- data/docs/compiler.md +50 -0
- data/docs/compiler_directives.md +40 -34
- data/docs/configuring_gems.md +148 -0
- data/docs/encoding.md +13 -0
- data/docs/faq.md +17 -0
- data/docs/getting_started.md +30 -0
- data/docs/jquery.md +264 -0
- data/docs/libraries.md +36 -0
- data/docs/promises.md +64 -0
- data/docs/rails.md +116 -0
- data/docs/rspec.md +98 -0
- data/docs/sinatra.md +79 -0
- data/docs/source_maps.md +49 -0
- data/docs/static_applications.md +63 -0
- data/docs/templates.md +150 -0
- data/docs/unsupported_features.md +27 -0
- data/docs/using_sprockets.md +72 -0
- data/lib/opal/sprockets/processor.rb +15 -9
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/variables.rb +1 -1
- data/spec/lib/spec_helper.rb +2 -0
- data/spec/lib/sprockets/processor_spec.rb +11 -0
- metadata +22 -6
- data/lib/opal/sprockets/cache_key_fix.rb +0 -17
@@ -0,0 +1,63 @@
|
|
1
|
+
# Static Building
|
2
|
+
|
3
|
+
`opal` makes it easy to build static opal applications. Opal uses internal load
|
4
|
+
paths to make it easy to handle resolving requirements during building. `opal`
|
5
|
+
forms the basis of rails support, so anything you can do there, you can do
|
6
|
+
standalone as well.
|
7
|
+
|
8
|
+
## Overview
|
9
|
+
|
10
|
+
First, install `opal` adding them to a `Gemfile`:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# Gemfile
|
14
|
+
gem "opal", "~> 0.7.0"
|
15
|
+
```
|
16
|
+
|
17
|
+
Next, we want to add our main app code. Keep all opal code inside `app/`
|
18
|
+
directory, and edit `app/application.rb`:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
# app/application.rb
|
22
|
+
require "opal"
|
23
|
+
|
24
|
+
puts "Wow, running opal!"
|
25
|
+
```
|
26
|
+
|
27
|
+
You will notice the `require "opal"` line which will automatically include the
|
28
|
+
opal runtime and corelib into our output, giving us access to the `puts()`
|
29
|
+
method.
|
30
|
+
|
31
|
+
To build this, we need the rake task to add our
|
32
|
+
`app/` directory to the load path, and then to build our target file
|
33
|
+
`application.rb` which will be found because it is inside our added load path.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# Rakefile
|
37
|
+
require 'opal'
|
38
|
+
|
39
|
+
desc "Build our app to build.js"
|
40
|
+
task :build do
|
41
|
+
Opal.append_path "app"
|
42
|
+
File.binwrite "build.js", Opal::Builder.build("application").to_s
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
Now, if you run `rake build` you will get the `build.js` output file with our
|
47
|
+
application compiled, with the opal runtime included as well.
|
48
|
+
|
49
|
+
To run the application, lets create a very simple html file:
|
50
|
+
|
51
|
+
```html
|
52
|
+
<!DOCTYPE html>
|
53
|
+
<html>
|
54
|
+
<head>
|
55
|
+
<script src="build.js"></script>
|
56
|
+
</head>
|
57
|
+
<body>
|
58
|
+
</body>
|
59
|
+
</html>
|
60
|
+
```
|
61
|
+
|
62
|
+
Now, open this html file and check the browsers console. You should see our
|
63
|
+
message printed in the console.
|
data/docs/templates.md
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
# Templates with Opal
|
2
|
+
|
3
|
+
Opal includes support for running erb templates on the client. Haml templates
|
4
|
+
can also be used via the `opal-haml` gem.
|
5
|
+
|
6
|
+
## Basic Templates
|
7
|
+
|
8
|
+
If you require `template.rb` from the stdlib, then all compiled templates will
|
9
|
+
be available on the `Template` object. Each compiled template will be an
|
10
|
+
instance of `Template`, which provides a basic standard rendering api to make
|
11
|
+
rendering a uniform method on the client.
|
12
|
+
|
13
|
+
For example, to access a template named `user`:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
require 'template'
|
17
|
+
|
18
|
+
template = Template['user']
|
19
|
+
context = User.new('Ford Prefect')
|
20
|
+
|
21
|
+
puts template.render(context)
|
22
|
+
# => "<div>...</div>"
|
23
|
+
```
|
24
|
+
|
25
|
+
`#render()` will run the template in the given context, and return the result
|
26
|
+
as a string. This is usually a html string, but it can be used for any dynamic
|
27
|
+
content.
|
28
|
+
|
29
|
+
### Registered Templates
|
30
|
+
|
31
|
+
You can get a quick list of all registered templates using `.paths`:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Template.paths
|
35
|
+
# => [#<Template: 'views/user'>, #<Template: 'login'>]
|
36
|
+
```
|
37
|
+
|
38
|
+
These names are the keys used to access a template:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
Template['login']
|
42
|
+
# => #<Template: 'login'>
|
43
|
+
```
|
44
|
+
|
45
|
+
## Haml templates
|
46
|
+
|
47
|
+
`opal-haml` allows `.haml` templates to be compiled, just like opal compiles
|
48
|
+
ruby code, ready to run on the client.
|
49
|
+
|
50
|
+
To get started, add to your Gemfile:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# Gemfile
|
54
|
+
gem 'opal'
|
55
|
+
gem 'opal-haml'
|
56
|
+
```
|
57
|
+
|
58
|
+
`opal-haml` simply registers the `.haml` template to be handled under sprockets.
|
59
|
+
This means, that you can simply `require()` a haml template in your code.
|
60
|
+
|
61
|
+
Lets say you have the following simple opal app:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
# app/application.rb
|
65
|
+
require 'opal'
|
66
|
+
|
67
|
+
class User < Struct.new(:name, :age)
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
We want to create an instance of the `User` class and render it using a haml
|
72
|
+
template. Lets first create that template as `app/views/user.haml`:
|
73
|
+
|
74
|
+
```haml
|
75
|
+
-# app/views/user.haml
|
76
|
+
.row
|
77
|
+
.col-md-6
|
78
|
+
= self.name
|
79
|
+
.col-md-6
|
80
|
+
= self.age
|
81
|
+
```
|
82
|
+
|
83
|
+
You are nearly ready to go. Lets create a user instance and render the template
|
84
|
+
in the context of that user:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
# app/application.rb
|
88
|
+
require 'opal'
|
89
|
+
require 'views/user'
|
90
|
+
|
91
|
+
class User < Struct.new(:name, :age)
|
92
|
+
end
|
93
|
+
|
94
|
+
ford = User.new('Ford Prefect', 42)
|
95
|
+
template = Template['views/user']
|
96
|
+
|
97
|
+
puts template.render(ford)
|
98
|
+
```
|
99
|
+
|
100
|
+
Note, when requiring haml templates you do not need to specify the `.haml`
|
101
|
+
extension. This code will print the rendered html to the console. If you
|
102
|
+
check it out, you should see it compiled into something like the following:
|
103
|
+
|
104
|
+
```html
|
105
|
+
<div class="row">
|
106
|
+
<div class="col-md-6">
|
107
|
+
Ford Prefect
|
108
|
+
</div>
|
109
|
+
<div class="col-md-6">
|
110
|
+
42
|
111
|
+
</div>
|
112
|
+
</div>
|
113
|
+
```
|
114
|
+
|
115
|
+
## ERB Templates
|
116
|
+
|
117
|
+
Support for `erb` templates is built in directly to the opal gem and stdlib.
|
118
|
+
There is one caveat though when working with sprockets - it must have the
|
119
|
+
`.opalerb` file extension, instead of `.erb`. This is because sprockets has a
|
120
|
+
built in handler for `.erb` files.
|
121
|
+
|
122
|
+
If we have the same user class as above, create an `app/views/user.opalerb`
|
123
|
+
file:
|
124
|
+
|
125
|
+
```erb
|
126
|
+
<!-- app/views/user.opalerb -->
|
127
|
+
<div class="row">
|
128
|
+
<div class="col-md-3"><%= self.name %></div>
|
129
|
+
</div>
|
130
|
+
```
|
131
|
+
|
132
|
+
Again, you must then require the template (without the `.opalerb` extension):
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
# app/application.rb
|
136
|
+
require 'opal'
|
137
|
+
require 'views/user'
|
138
|
+
```
|
139
|
+
|
140
|
+
And then you can access and render the template:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
# app/application.rb
|
144
|
+
|
145
|
+
template = Template['views/user']
|
146
|
+
user = User.new('Ford Prefect')
|
147
|
+
|
148
|
+
puts template.render(user)
|
149
|
+
# => "<div class="row">...</div>"
|
150
|
+
```
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Unsupported Features
|
2
|
+
|
3
|
+
Opal does not support some language/runtime features of ruby. These are documented here when possible, as well as the reasons why they are not supported.
|
4
|
+
|
5
|
+
#### Mutable Strings ####
|
6
|
+
|
7
|
+
For performance and ease of runtime features, all strings in Opal are immutable, i.e. `#<<`, `#gsub!`, etc. do not exist. Also, symbols are just strings. There is no class, runtime or feature difference between Symbols and Strings. Their syntaxes can be used interchangeably.
|
8
|
+
|
9
|
+
#### Encodings ####
|
10
|
+
|
11
|
+
Encodings only have a very small implementation inside Opal.
|
12
|
+
|
13
|
+
#### Threads ####
|
14
|
+
|
15
|
+
Javascript does not have a native `Thread` implementation, so they are not present inside Opal. There is a placeholder `Thread` class just to provide some small level of compatibility with libraries that expect it. It does not have any function.
|
16
|
+
|
17
|
+
#### Frozen Objects ####
|
18
|
+
|
19
|
+
Opal does not currently support frozen objects, but has placeholder methods to prevent other libraries breaking when expecting these methods. Opal could support frozen objects in the future once a similar implementation becomes available across Javascript runtimes.
|
20
|
+
|
21
|
+
#### `method_added` and `method_removed` hooks ####
|
22
|
+
|
23
|
+
These are not *currently* supported by Opal, but this is considered a bug and will be implemented soon.
|
24
|
+
|
25
|
+
#### Private, Public and Protected methods ####
|
26
|
+
|
27
|
+
All methods in Opal are defined as `public` to avoid additional runtime overhead. `Module#private` and `Module#protected` exist as just placeholder methods and are no-op methods.
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Opal & Sprockets
|
2
|
+
|
3
|
+
Opal comes with built-in sprockets support, and provides a simple `Opal::Server`
|
4
|
+
class to make it easy to get a rack server up and running for trying out opal.
|
5
|
+
This server will automatically recompile ruby sources when they change, meaning
|
6
|
+
you just need to refresh your page to autorun.
|
7
|
+
|
8
|
+
## Getting setup
|
9
|
+
|
10
|
+
Add `opal` to a `Gemfile`:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
#Gemfile
|
14
|
+
source 'https://rubygems.org'
|
15
|
+
|
16
|
+
gem 'opal', '>= 0.6.0'
|
17
|
+
```
|
18
|
+
|
19
|
+
And install with `bundle install`.
|
20
|
+
|
21
|
+
We need a directory to hold our opal code, so create `app/` and add a simple
|
22
|
+
demo script to `app/application.rb`:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
# app/application.rb
|
26
|
+
require 'opal'
|
27
|
+
|
28
|
+
puts "hello world"
|
29
|
+
```
|
30
|
+
|
31
|
+
Finally, we need a html page to run, so create `index.html`:
|
32
|
+
|
33
|
+
```html
|
34
|
+
<!DOCTYPE html>
|
35
|
+
<html>
|
36
|
+
<head>
|
37
|
+
<meta charset="utf-8">
|
38
|
+
<title>opal server example</title>
|
39
|
+
<script src="/assets/application.js"></script>
|
40
|
+
</head>
|
41
|
+
<body>
|
42
|
+
</body>
|
43
|
+
</html>
|
44
|
+
```
|
45
|
+
|
46
|
+
## Using Opal::Server
|
47
|
+
|
48
|
+
`Opal::Server` can be run like any rack app, so just add a `config.ru` file:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
# config.ru
|
52
|
+
require 'bundler'
|
53
|
+
Bundler.require
|
54
|
+
|
55
|
+
run Opal::Server.new { |s|
|
56
|
+
s.append_path 'app'
|
57
|
+
|
58
|
+
s.main = 'application'
|
59
|
+
|
60
|
+
s.index_path = 'index.html'
|
61
|
+
}
|
62
|
+
```
|
63
|
+
|
64
|
+
This rack app simply adds our `app/` directory to opal load path, and sets our
|
65
|
+
main file to `application`, which will be found inside `app/`.
|
66
|
+
|
67
|
+
## Running the app
|
68
|
+
|
69
|
+
Run `bundle exec rackup` and visit the page `http://localhost:9292` in any
|
70
|
+
browser. Observe the console to see the printed statement.
|
71
|
+
|
72
|
+
You can just change `app/application.rb` and refresh the page to see any changes.
|
@@ -19,6 +19,15 @@ module Opal
|
|
19
19
|
define_singleton_method("#{config_option}=") { |value| Opal::Config.config[config_option] = value }
|
20
20
|
end
|
21
21
|
|
22
|
+
@@cache_key = nil
|
23
|
+
def self.cache_key
|
24
|
+
@@cache_key ||= ['Opal', Opal::VERSION, Opal::Config.config].to_json.freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.reset_cache_key!
|
28
|
+
@@cache_key = nil
|
29
|
+
end
|
30
|
+
|
22
31
|
def evaluate(context, locals, &block)
|
23
32
|
return super unless context.is_a? ::Sprockets::Context
|
24
33
|
|
@@ -64,7 +73,7 @@ module Opal
|
|
64
73
|
|
65
74
|
def process_requires(requires, context)
|
66
75
|
requires.each do |required|
|
67
|
-
required = required.sub(sprockets_extnames_regexp, '')
|
76
|
+
required = required.to_s.sub(sprockets_extnames_regexp, '')
|
68
77
|
context.require_asset required unless stubbed_files.include? required
|
69
78
|
end
|
70
79
|
end
|
@@ -103,14 +112,11 @@ module Opal
|
|
103
112
|
|
104
113
|
absolute_paths.each do |path|
|
105
114
|
path = Pathname(path)
|
106
|
-
pathname = path.relative_path_from(dirname)
|
107
|
-
|
108
|
-
if name.to_s == file
|
109
|
-
|
110
|
-
|
111
|
-
context.depend_on(path.to_s)
|
112
|
-
else
|
113
|
-
context.require_asset(pathname)
|
115
|
+
pathname = path.relative_path_from(dirname).to_s
|
116
|
+
|
117
|
+
if name.to_s == file then next
|
118
|
+
elsif path.directory? then context.depend_on(path.to_s)
|
119
|
+
else context.require_asset(pathname)
|
114
120
|
end
|
115
121
|
end
|
116
122
|
end
|
data/lib/opal/version.rb
CHANGED
data/opal/corelib/variables.rb
CHANGED
data/spec/lib/spec_helper.rb
CHANGED
@@ -6,4 +6,6 @@ RSpec.configure do |config|
|
|
6
6
|
config.filter_run :focus
|
7
7
|
config.order = 'random'
|
8
8
|
config.before { Opal.instance_variable_set('@paths', nil) }
|
9
|
+
config.before { Opal::Config.reset! if defined? Opal::Config }
|
10
|
+
config.before { Opal::Processor.reset_cache_key! if defined? Opal::Processor }
|
9
11
|
end
|
@@ -64,4 +64,15 @@ describe Opal::Processor do
|
|
64
64
|
code.should match stubbed_file
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
68
|
+
describe '.cache_key' do
|
69
|
+
it 'can be reset' do
|
70
|
+
Opal::Config.arity_check_enabled = true
|
71
|
+
old_cache_key = described_class.cache_key
|
72
|
+
Opal::Config.arity_check_enabled = false
|
73
|
+
expect(described_class.cache_key).to eq(old_cache_key)
|
74
|
+
described_class.reset_cache_key!
|
75
|
+
expect(described_class.cache_key).not_to eq(old_cache_key)
|
76
|
+
end
|
77
|
+
end
|
67
78
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.1.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Beynon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sourcemap
|
@@ -225,7 +225,24 @@ files:
|
|
225
225
|
- bin/opal-mspec
|
226
226
|
- bin/opal-repl
|
227
227
|
- config.ru
|
228
|
+
- docs/compiled_ruby.md
|
229
|
+
- docs/compiler.md
|
228
230
|
- docs/compiler_directives.md
|
231
|
+
- docs/configuring_gems.md
|
232
|
+
- docs/encoding.md
|
233
|
+
- docs/faq.md
|
234
|
+
- docs/getting_started.md
|
235
|
+
- docs/jquery.md
|
236
|
+
- docs/libraries.md
|
237
|
+
- docs/promises.md
|
238
|
+
- docs/rails.md
|
239
|
+
- docs/rspec.md
|
240
|
+
- docs/sinatra.md
|
241
|
+
- docs/source_maps.md
|
242
|
+
- docs/static_applications.md
|
243
|
+
- docs/templates.md
|
244
|
+
- docs/unsupported_features.md
|
245
|
+
- docs/using_sprockets.md
|
229
246
|
- examples/rack/.gitignore
|
230
247
|
- examples/rack/Gemfile
|
231
248
|
- examples/rack/app/application.rb
|
@@ -299,7 +316,6 @@ files:
|
|
299
316
|
- lib/opal/regexp_anchors.rb
|
300
317
|
- lib/opal/source_map.rb
|
301
318
|
- lib/opal/sprockets.rb
|
302
|
-
- lib/opal/sprockets/cache_key_fix.rb
|
303
319
|
- lib/opal/sprockets/environment.rb
|
304
320
|
- lib/opal/sprockets/erb.rb
|
305
321
|
- lib/opal/sprockets/path_reader.rb
|
@@ -932,12 +948,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
932
948
|
version: '0'
|
933
949
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
934
950
|
requirements:
|
935
|
-
- - "
|
951
|
+
- - ">"
|
936
952
|
- !ruby/object:Gem::Version
|
937
|
-
version:
|
953
|
+
version: 1.3.1
|
938
954
|
requirements: []
|
939
955
|
rubyforge_project:
|
940
|
-
rubygems_version: 2.4.
|
956
|
+
rubygems_version: 2.4.5.1
|
941
957
|
signing_key:
|
942
958
|
specification_version: 4
|
943
959
|
summary: Ruby runtime and core library for javascript
|