opal-sprockets 0.4.5.1.0.3.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,5 @@
1
1
  module Opal
2
2
  module Sprockets
3
- BASE_VERSION = '0.4.5'
4
- OPAL_VERSION = '1.0.0'
5
- SPROCKETS_VERSION = '3.7'
6
-
7
- # Just keep the first two segments of dependencies' versions
8
- v = -> v { v.split('.')[0..1].compact.join('.') }
9
-
10
- VERSION = "#{BASE_VERSION}.#{v[OPAL_VERSION]}.#{v[SPROCKETS_VERSION]}"
3
+ VERSION = '1.0.0'
11
4
  end
12
5
  end
@@ -1,25 +1,39 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/opal/sprockets/version', __FILE__)
3
-
4
- Gem::Specification.new do |s|
5
- s.name = 'opal-sprockets'
6
- s.version = Opal::Sprockets::VERSION
7
- s.authors = ['Elia Schito', 'Adam Beynon']
8
- s.email = 'elia@schito.me'
9
- s.homepage = 'https://github.com/opal/opal-sprockets#readme'
10
- s.summary = 'Sprockets support for Opal.'
11
- s.description = 'Sprockets support for Opal.'
12
-
13
- s.files = `git ls-files`.split("\n")
14
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
- s.require_paths = ['lib']
16
-
17
- s.add_dependency 'sprockets', "~> #{Opal::Sprockets::SPROCKETS_VERSION}"
18
- s.add_dependency 'opal', "~> #{Opal::Sprockets::OPAL_VERSION}"
19
- s.add_dependency 'tilt', '>= 1.4'
20
-
21
- s.add_development_dependency 'rake'
22
- s.add_development_dependency 'rspec'
23
- s.add_development_dependency 'rack-test'
24
- s.add_development_dependency 'sourcemap'
1
+ require_relative 'lib/opal/sprockets/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'opal-sprockets'
5
+ spec.version = Opal::Sprockets::VERSION
6
+ spec.authors = ['Elia Schito', 'Adam Beynon']
7
+ spec.email = 'elia@schito.me'
8
+
9
+ spec.summary = 'Sprockets support for Opal.'
10
+ spec.homepage = 'https://github.com/opal/opal-sprockets#readme'
11
+ spec.license = 'MIT'
12
+
13
+ spec.metadata['homepage_uri'] = spec.homepage
14
+ spec.metadata['source_code_uri'] = 'https://github.com/opal/opal-sprockets'
15
+ spec.metadata['changelog_uri'] = 'https://github.com/opal/opal-sprockets/blob/master/CHANGELOG.md'
16
+
17
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5', '< 3.1')
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
22
+
23
+ spec.files = files.grep_v(%r{^(test|spec|features)/})
24
+ spec.test_files = files.grep(%r{^(test|spec|features)/})
25
+ spec.bindir = "exe"
26
+ spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_dependency 'sprockets', "~> 4.0"
30
+ spec.add_dependency 'opal', [">= 1.0", "< 1.2"]
31
+ spec.add_dependency 'tilt', '>= 1.4'
32
+
33
+ spec.add_development_dependency 'rake'
34
+ spec.add_development_dependency 'rspec'
35
+ spec.add_development_dependency 'rack-test'
36
+ spec.add_development_dependency 'sourcemap'
37
+ spec.add_development_dependency 'ejs'
38
+ spec.add_development_dependency 'pry'
25
39
  end
@@ -1,5 +1,5 @@
1
1
  #= require no_requires
2
- //= require jst_file
2
+ #= require ./jst_file
3
3
  #= require_tree ./required_tree_test
4
4
  require 'file_with_directives'
5
5
  require <%= "base64".inspect %>
File without changes
data/spec/spec_helper.rb CHANGED
@@ -1,2 +1,9 @@
1
1
  require 'bundler'
2
2
  Bundler.require
3
+
4
+ RSpec.configure do |config|
5
+ config.before do
6
+ Opal::Config.reset!
7
+ Opal::Sprockets::Processor.reset_cache_key!
8
+ end
9
+ end
@@ -1,38 +1,28 @@
1
1
  require 'spec_helper'
2
2
  require 'opal/sprockets/erb'
3
3
 
4
- describe Opal::ERB::Processor do
4
+ describe Opal::Sprockets::ERB do
5
5
  let(:pathname) { Pathname("/Code/app/mylib/opal/foo.#{ext}") }
6
- let(:environment) { double(Sprockets::Environment,
7
- cache: nil,
8
- :[] => nil,
9
- resolve: pathname.expand_path.to_s,
10
- engines: double(keys: %w[.rb .js .erb .opal]),
11
- ) }
12
- let(:sprockets_context) { double(Sprockets::Context,
13
- logical_path: "foo.#{ext}",
14
- environment: environment,
15
- pathname: pathname,
6
+ let(:data) { %{<% print("") %><a href="<%= url %>"><%= name %></a>} }
7
+ let(:input) { {
8
+ environment: Opal::Sprockets::Environment.new.tap {|e| e.append_path "/Code/app/mylib/opal"},
9
+ data: data,
16
10
  filename: pathname.to_s,
17
- root_path: '/Code/app/mylib',
18
- is_a?: true,
19
- ) }
20
- let(:required_assets) { [] }
21
- let(:template) { described_class.new { |t| %Q{<% print("") %><a href="<%= url %>"><%= name %></a>} } }
22
- before { allow(sprockets_context).to receive(:require_asset) {|asset| required_assets << asset } }
23
-
11
+ load_path: "/Code/app/mylib/opal",
12
+ metadata: {},
13
+ cache: Sprockets::Cache.new
14
+ } }
24
15
  let(:ext) { 'opalerb' }
25
16
 
26
- it "is registered for '.opalerb' files" do
27
- expect(Tilt["test.#{ext}"]).to eq(described_class)
28
- end
29
-
30
17
  it 'renders the template' do
31
- expect(template.render(sprockets_context)).to include('"<a href=\""')
18
+ result = described_class.call(input)
19
+
20
+ expect(result[:data]).to include('"<a href=\""')
32
21
  end
33
22
 
34
23
  it 'implicitly requires "erb"' do
35
- template.render(sprockets_context)
36
- expect(required_assets).to eq(['erb'])
24
+ result = described_class.call(input)
25
+
26
+ expect(result[:required].first).to include("stdlib/erb.rb")
37
27
  end
38
28
  end
@@ -1,79 +1,75 @@
1
1
  require 'spec_helper'
2
2
  require 'opal/sprockets/processor'
3
3
 
4
- describe Opal::Processor do
4
+ describe Opal::Sprockets::Processor do
5
5
  let(:pathname) { Pathname("/Code/app/mylib/opal/foo.#{ext}") }
6
- let(:environment) { double(Sprockets::Environment,
7
- cache: nil,
8
- :[] => nil,
9
- resolve: pathname.expand_path.to_s,
10
- engines: double(keys: %w[.rb .js .opal]),
11
- ) }
12
- let(:sprockets_context) { double(Sprockets::Context,
13
- logical_path: "foo.#{ext}",
14
- environment: environment,
15
- pathname: pathname,
6
+ let(:data) { "foo" }
7
+ let(:input) { {
8
+ environment: Opal::Sprockets::Environment.new.tap {|e| e.append_path "/Code/app/mylib/opal"},
9
+ data: data,
16
10
  filename: pathname.to_s,
17
- root_path: '/Code/app/mylib',
18
- is_a?: true,
19
- ) }
11
+ load_path: "/Code/app/mylib/opal",
12
+ metadata: {},
13
+ cache: Sprockets::Cache.new
14
+ } }
15
+
16
+ before do
17
+ allow(Sprockets::SourceMapUtils).to receive(:format_source_map)
18
+ allow(Sprockets::SourceMapUtils).to receive(:combine_source_maps)
19
+ end
20
20
 
21
21
  %w[.rb .opal].each do |ext|
22
- let(:ext) { ext }
22
+ describe %{with extension "#{ext}"} do
23
+ let(:ext) { ext }
23
24
 
24
- describe %Q{with extension "#{ext}"} do
25
25
  it "is registered for '#{ext}' files" do
26
- expect(Sprockets.engines[ext]).to eq(described_class)
26
+ mime_type = Sprockets.mime_types.find { |_,v| v[:extensions].include? ".rb" }.first
27
+ transformers = Sprockets.transformers[mime_type]
28
+ transformer = transformers["application/javascript"]
29
+ expect(transformer.processors).to include(described_class)
27
30
  end
28
31
 
29
- it "compiles and evaluates the template on #render" do
30
- template = described_class.new { |t| "puts 'Hello, World!'\n" }
31
- expect(template.render(sprockets_context)).to include('"Hello, World!"')
32
+ it "compiles the code" do
33
+ result = described_class.call(input.merge data: "puts 'Hello, World!'\n")
34
+
35
+ expect(result[:data]).to include('"Hello, World!"')
32
36
  end
33
- end
34
- end
35
37
 
36
- describe '.stubbed_files' do
37
- around do |e|
38
- config.stubbed_files.clear
39
- e.run
40
- config.stubbed_files.clear
41
- end
38
+ describe '.stubbed_files' do
39
+ it 'requires non-stubbed files' do
40
+ result = described_class.call(input.merge(data: 'require "set"'))
42
41
 
43
- let(:stubbed_file) { 'foo' }
44
- let(:template) { described_class.new { |t| "require #{stubbed_file.inspect}" } }
45
- let(:config) { Opal::Config }
42
+ expect(result[:required].first).to include("stdlib/set.rb")
43
+ end
46
44
 
47
- it 'usually require files' do
48
- expect(sprockets_context).to receive(:require_asset).with(stubbed_file)
49
- template.render(sprockets_context)
50
- end
45
+ it 'skips require of stubbed file' do
46
+ Opal::Config.stubbed_files << 'set'
47
+ result = described_class.call(input.merge(data: "require 'set'"))
51
48
 
52
- it 'skips require of stubbed file' do
53
- config.stubbed_files << stubbed_file.to_s
54
- expect(sprockets_context).not_to receive(:require_asset).with(stubbed_file)
55
- template.render(sprockets_context)
56
- end
49
+ expect(result[:required]).not_to include("set.rb")
50
+ end
57
51
 
58
- it 'marks a stubbed file as loaded' do
59
- config.stubbed_files << stubbed_file.to_s
60
- asset = double(dependencies: [], pathname: Pathname('bar'), logical_path: 'bar')
61
- allow(environment).to receive(:[]).with('bar.js') { asset }
62
- allow(environment).to receive(:engines) { {'.rb' => described_class, '.opal' => described_class} }
52
+ it 'marks a stubbed file as loaded' do
53
+ Opal::Config.stubbed_files << 'set'
54
+ result = described_class.call(input.merge(data: "require 'set'"))
63
55
 
64
- code = ::Opal::Sprockets.load_asset('bar')
65
- expect(code).to match(stubbed_file)
66
- end
67
- end
56
+ expect(result[:data]).not_to include(::Opal::Sprockets.load_asset('set'))
57
+ end
58
+ end
68
59
 
69
- describe '.cache_key' do
70
- it 'can be reset' do
71
- Opal::Config.arity_check_enabled = true
72
- old_cache_key = described_class.cache_key
73
- Opal::Config.arity_check_enabled = false
74
- expect(described_class.cache_key).to eq(old_cache_key)
75
- described_class.reset_cache_key!
76
- expect(described_class.cache_key).not_to eq(old_cache_key)
60
+ describe '.cache_key' do
61
+ it 'can be reset' do
62
+ old_cache_key = described_class.cache_key
63
+ Opal::Config.arity_check_enabled = !Opal::Config.arity_check_enabled
64
+ stale_cache_key = described_class.cache_key
65
+
66
+ described_class.reset_cache_key!
67
+ reset_cache_key = described_class.cache_key
68
+
69
+ expect(stale_cache_key).to eq(old_cache_key)
70
+ expect(reset_cache_key).not_to eq(old_cache_key)
71
+ end
72
+ end
77
73
  end
78
74
  end
79
75
  end
@@ -20,60 +20,130 @@ describe Opal::Sprockets::Server do
20
20
  end
21
21
 
22
22
  it 'serves assets with complex sprockets requires' do
23
- asset = app.sprockets['complex_sprockets']
23
+ asset = app.sprockets['complex_sprockets', accept: "application/javascript"]
24
24
  expect(asset).to be_truthy
25
25
 
26
- assets = asset.to_a.map do |sub_asset|
27
- sub_asset.logical_path.gsub(/\.self\.js$/, '.js')
26
+ assets = asset.metadata[:included].map do |sub_asset|
27
+ URI.parse(sub_asset).path.split(%r'/fixtures/|/stdlib/').last
28
28
  end
29
29
 
30
30
  %w[
31
- base64.js
32
- no_requires.js
33
- jst_file.js
34
- required_tree_test/required_file1.js
35
- required_tree_test/required_file2.js
31
+ base64.rb
32
+ no_requires.rb
33
+ jst_file.jst.ejs
34
+ required_tree_test/required_file1.rb
35
+ required_tree_test/required_file2.rb
36
36
  file_with_directives.js
37
37
  ].each do |logical_path|
38
38
  expect(assets).to include(logical_path)
39
39
  end
40
40
  end
41
41
 
42
+ it 'recompiles the asset when its dependencies change' do
43
+ does_include = proc do |it, what, what_not=[], what_else=nil, what_else_not=nil|
44
+ expect(it).to include what_else if what_else
45
+ expect(it).not_to include what_else_not if what_else_not
46
+ what.each { |i| expect(it).to include %{modules["required_tree_test/required_file#{i}"]} }
47
+ what_not.each { |i| expect(it).not_to include %{modules["required_tree_test/required_file#{i}"]} }
48
+ end
49
+
50
+ ["default", "debug"].each do |pipeline|
51
+ asset = app.sprockets['require_tree_test', pipeline: pipeline, accept: "application/javascript"]
52
+ expect(asset).to be_truthy
53
+ does_include.(asset.to_s, [1,2], [3], nil, "UNIQUESTRING")
54
+ get "/assets/require_tree_test.#{pipeline}.js"
55
+ does_include.(last_response.body, [1,2], [3], nil, "UNIQUESTRING")
56
+
57
+ sleep 1 # Make sure to modify mtime
58
+
59
+ File.write(__dir__+"/../fixtures/required_tree_test/required_file2.rb", "p 'UNIQUESTRING1'")
60
+
61
+ asset = app.sprockets['require_tree_test', pipeline: pipeline, accept: "application/javascript"]
62
+ expect(asset).to be_truthy
63
+ does_include.(asset.to_s, [1,2], [3], "UNIQUESTRING1")
64
+ get "/assets/require_tree_test.#{pipeline}.js"
65
+ does_include.(last_response.body, [1,2], [3], "UNIQUESTRING1")
66
+
67
+ sleep 1 # Make sure to modify mtime
68
+
69
+ File.write(__dir__+"/../fixtures/required_tree_test/required_file2.rb", "p 'UNIQUESTRING2'")
70
+
71
+ asset = app.sprockets['require_tree_test', pipeline: pipeline, accept: "application/javascript"]
72
+ expect(asset).to be_truthy
73
+ does_include.(asset.to_s, [1,2], [3], "UNIQUESTRING2")
74
+ get "/assets/require_tree_test.#{pipeline}.js"
75
+ does_include.(last_response.body, [1,2], [3], "UNIQUESTRING2")
76
+
77
+ sleep 1 # Make sure to modify mtime
78
+
79
+ File.write(__dir__+"/../fixtures/required_tree_test/required_file2.rb", "p 'UNIQUESTRING3'")
80
+ File.write(__dir__+"/../fixtures/required_tree_test/required_file3.rb", "p 3")
81
+
82
+ asset = app.sprockets['require_tree_test', pipeline: pipeline, accept: "application/javascript"]
83
+ expect(asset).to be_truthy
84
+ does_include.(asset.to_s, [1,2,3], [], "UNIQUESTRING3")
85
+ get "/assets/require_tree_test.#{pipeline}.js"
86
+ does_include.(last_response.body, [1,2], [], "UNIQUESTRING3") # fails with 3 - it doesn't get new files
87
+
88
+ sleep 1 # Make sure to modify mtime
89
+ ensure
90
+ File.write(__dir__+"/../fixtures/required_tree_test/required_file2.rb", "p 2\n")
91
+ File.unlink(__dir__+"/../fixtures/required_tree_test/required_file3.rb") rescue nil
92
+ end
93
+ end
94
+
42
95
  describe 'source maps' do
43
- RSpec::Matchers.define :include_inline_source_map do
96
+ RSpec::Matchers.define :include_source_map do
44
97
  match do |actual_response|
45
98
  actual_response.ok? &&
46
- actual_response.body.lines.last.start_with?('//# sourceMappingURL=data:application/json;base64,')
99
+ actual_response.body.lines.last.start_with?('//# sourceMappingURL=')
47
100
  end
48
101
  end
49
102
 
50
- def extract_inline_map(response)
103
+ def extract_map(path, response)
51
104
  last_line = response.body.lines.last
52
- b64_encoded = last_line.split('//# sourceMappingURL=data:application/json;base64,', 2)[1]
53
- json_string = Base64.decode64(b64_encoded)
105
+ if last_line.start_with? "//# sourceMappingURL=data:application/json;base64,"
106
+ b64_encoded = last_line.split('//# sourceMappingURL=data:application/json;base64,', 2)[1]
107
+ json_string = Base64.decode64(b64_encoded)
108
+ else
109
+ map_file = last_line.split('//# sourceMappingURL=', 2)[1].chomp
110
+ map_file = relative_path(path, map_file)
111
+ map_file = get map_file
112
+ json_string = map_file.body
113
+ end
54
114
  JSON.parse(json_string, symbolize_names: true)
55
115
  end
56
116
 
117
+ def relative_path(path, file)
118
+ URI.join("http://example.com/", path, file).path
119
+ end
120
+
57
121
  it 'serves map for a top level file' do
58
- get '/assets/opal_file.js'
59
- expect(last_response).to include_inline_source_map
122
+ path = '/assets/opal_file.debug.js'
123
+ get path
124
+ expect(last_response).to include_source_map
60
125
 
61
- map = extract_inline_map(last_response)
126
+ map = extract_map(path, last_response)
62
127
 
63
- expect(map[:sources]).to eq(['opal_file.rb']).or eq(['opal_file'])
64
- expect(map[:sourcesContent]).to eq(["require 'opal'\nputs 'hi from opal!'\n"])
128
+ expect(map[:file]).to eq('opal_file.rb')
129
+ expect(map[:sections].last[:map][:sources]).to eq(['opal_file.source.rb'])
130
+
131
+ expect(get(relative_path(path, map[:sections].last[:map][:sources][0])).body.chomp)
132
+ .to eq("require 'opal'\nputs 'hi from opal!'")
65
133
  end
66
134
 
67
135
  it 'serves map for a subfolder file' do
68
- get '/assets/source_map/subfolder/other_file.self.js'
69
- expect(last_response).to include_inline_source_map
136
+ path = '/assets/source_map/subfolder/other_file.debug.js'
137
+ get path
138
+ expect(last_response).to include_source_map
139
+
140
+ map = extract_map(path, last_response)
70
141
 
71
- map = extract_inline_map(last_response)
142
+ expect(map[:file]).to eq('source_map/subfolder/other_file.rb')
143
+ expect(map[:sections].first[:map][:sources]).to eq(['other_file.source.rb'])
72
144
 
73
- expect(map[:sources])
74
- .to eq(['source_map/subfolder/other_file.rb'])
75
- .or eq(['source_map/subfolder/other_file'])
76
- expect(map[:sourcesContent]).to eq(["puts 'other!'\n"])
145
+ expect(get(relative_path(path, map[:sections][0][:map][:sources][0])).body.chomp)
146
+ .to eq("puts 'other!'")
77
147
  end
78
148
  end
79
149
  end
@@ -8,20 +8,20 @@ describe Opal::Sprockets do
8
8
  describe '.load_asset' do
9
9
  it 'loads the main asset' do
10
10
  code = described_class.load_asset('console')
11
- expect(code).to include('Opal.load("console");')
11
+ expect(code).to include('Opal.require("console");')
12
12
  end
13
13
 
14
14
  it 'marks as loaded stubs and all non-opal assets' do
15
15
  allow(Opal::Config).to receive(:stubbed_files) { %w[foo bar] }
16
16
 
17
17
  code = described_class.load_asset('baz')
18
- expect(code).to include('Opal.loaded(["foo","bar"].concat(OpalLoaded || []));')
19
- expect(code).to include('Opal.load("baz");')
18
+ expect(code).to include(%{Opal.loaded(["foo","bar"].concat(typeof(OpalLoaded) === "undefined" ? [] : OpalLoaded));})
19
+ expect(code).to include('Opal.require("baz");')
20
20
  end
21
21
 
22
22
  it 'tries to load an asset if it is registered as opal module' do
23
23
  code = described_class.load_asset('foo')
24
- expect(code).to include('Opal.load("foo");')
24
+ expect(code).to include('Opal.require("foo");')
25
25
  end
26
26
 
27
27
  it 'warns the user that passing an env is not needed, only once' do
@@ -35,16 +35,16 @@ describe Opal::Sprockets do
35
35
 
36
36
  it 'accepts multiple names' do
37
37
  code = described_class.load_asset('foo', 'bar')
38
- expect(code).to include('Opal.load("foo");')
39
- expect(code).to include('Opal.load("bar");')
38
+ expect(code).to include('Opal.require("foo");')
39
+ expect(code).to include('Opal.require("bar");')
40
40
  end
41
41
 
42
42
  it 'detects deprecated env with multiple names' do
43
43
  code = described_class.load_asset('foo', 'bar', env)
44
44
  expect(code).to eq([
45
- 'Opal.loaded(OpalLoaded || []);',
46
- 'Opal.load("foo");',
47
- 'Opal.load("bar");',
45
+ 'Opal.loaded(typeof(OpalLoaded) === "undefined" ? [] : OpalLoaded);',
46
+ 'Opal.require("foo");',
47
+ 'Opal.require("bar");',
48
48
  ].join("\n"))
49
49
  end
50
50
  end