parcels 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/CHANGES.md +8 -0
- data/LICENSE.txt +1 -1
- data/lib/parcels/environment.rb +52 -2
- data/lib/parcels/fortitude/assets.rb +3 -0
- data/lib/parcels/fortitude_alongside_parcel.rb +1 -1
- data/lib/parcels/fortitude_parcel.rb +15 -2
- data/lib/parcels/fragments/css_fragment.rb +5 -8
- data/lib/parcels/sprockets.rb +26 -14
- data/lib/parcels/utils/path_utils.rb +5 -2
- data/lib/parcels/version.rb +1 -1
- data/lib/parcels/widget_tree.rb +42 -7
- data/parcels.gemspec +1 -1
- data/spec/helpers/parcels_rails_helpers.rb +1 -1
- data/spec/helpers/sprockets_helpers.rb +12 -2
- data/spec/lib/spec/expected/expected_asset.rb +6 -3
- data/spec/lib/spec/expected/expected_asset_set.rb +2 -2
- data/spec/rails/basic_rails_spec.rb +11 -0
- data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/helpers_module.rb +5 -0
- data/spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/helpers_module_test.rb +13 -0
- data/spec/system/ad_hoc_development_mode_spec.rb +80 -0
- data/spec/system/alongside_file_spec.rb +3 -1
- data/spec/system/class_from_file_spec.rb +60 -0
- data/spec/system/workaround_directories_spec.rb +81 -0
- metadata +16 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8c86251a8065212ca19858c38857005a7871457
|
4
|
+
data.tar.gz: 9be314a2db597e039c54dd4c4365e649e345fce5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0507164165fabbce70addd13598209794d45bbfe414870db3cda85e8766de0edeca1597f973170b55444979443bd941823a00979396b3c5c7e8d02398d88be5b
|
7
|
+
data.tar.gz: 89b09a7873d8ebbf440aa06a8673bc7ddc66dd7e42975a0d72d3adf963cfddc649d252eef73691b595e25f1aa6d94da9392c5011ff222e724b506342eb43d54d
|
data/CHANGES.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Parcels Releases
|
2
|
+
|
3
|
+
## 0.0.2, 21 January 2015
|
4
|
+
|
5
|
+
* Fixed an issue where having a `.rb` file in your `views` directory that didn't define a widget class, but rather a
|
6
|
+
module (presumably a "helper-like" module of view methods), would cause asset compilation to fail.
|
7
|
+
* Improved compatibility with non-Rails build environments (_e.g._, that used by
|
8
|
+
[Middleman](http://middlemanapp.com/)).
|
data/LICENSE.txt
CHANGED
data/lib/parcels/environment.rb
CHANGED
@@ -9,6 +9,8 @@ module Parcels
|
|
9
9
|
def initialize(sprockets_environment)
|
10
10
|
@sprockets_environment = sprockets_environment
|
11
11
|
@widget_trees = [ ]
|
12
|
+
@workaround_directories_for_widget_trees = { }
|
13
|
+
@workaround_directories_root = nil
|
12
14
|
|
13
15
|
register_engines!
|
14
16
|
end
|
@@ -30,8 +32,15 @@ module Parcels
|
|
30
32
|
widget_tree.add_workaround_directory_to_sprockets!(sprockets_environment)
|
31
33
|
end
|
32
34
|
|
33
|
-
def widget_class_from_file(
|
34
|
-
|
35
|
+
def widget_class_from_file(full_path)
|
36
|
+
widget_trees.each do |widget_tree|
|
37
|
+
if (removed = widget_tree.remove_workaround_directory_from(full_path))
|
38
|
+
full_path = removed
|
39
|
+
break
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
::Fortitude::Widget.widget_class_from_file(full_path, :root_dirs => widget_trees.map(&:widget_naming_root_dirs).flatten.uniq)
|
35
44
|
end
|
36
45
|
|
37
46
|
def create_and_add_all_workaround_directories!
|
@@ -41,12 +50,53 @@ module Parcels
|
|
41
50
|
end
|
42
51
|
|
43
52
|
def add_all_widgets_to!(sprockets_context, set_names)
|
53
|
+
if widget_trees.length == 0
|
54
|
+
raise %{Error: You have not defined any widget trees -- directories containing Fortitude widgets.
|
55
|
+
You must call #add_widget_tree! on the Parcels environment, which usually is accessible
|
56
|
+
as #parcels from your Sprockets environment.}
|
57
|
+
end
|
58
|
+
|
44
59
|
widget_trees.each { |wt| wt.add_all_widgets_to_sprockets_context!(sprockets_context, set_names) }
|
45
60
|
end
|
46
61
|
|
62
|
+
def workaround_directory_root_for_widget_tree(widget_tree)
|
63
|
+
@workaround_directories_for_widget_trees[widget_tree] ||= begin
|
64
|
+
if @workaround_directories_root
|
65
|
+
File.join(@workaround_directories_root, workaround_directory_name_for(widget_tree))
|
66
|
+
else
|
67
|
+
File.join(widget_tree.root, PARCELS_WORKAROUND_DIRECTORY_NAME)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def workaround_directories_root
|
73
|
+
@workaround_directories_root
|
74
|
+
end
|
75
|
+
|
76
|
+
def workaround_directories_root=(new_root)
|
77
|
+
new_root = File.expand_path(new_root)
|
78
|
+
|
79
|
+
if @workaround_directories_for_widget_trees.size > 0 && @workaround_directories_root != new_root
|
80
|
+
raise "You can't set the workaround directories root to:
|
81
|
+
#{new_root}
|
82
|
+
...it's already set to:
|
83
|
+
#{@workaround_directories_root}"
|
84
|
+
end
|
85
|
+
|
86
|
+
@workaround_directories_root = new_root
|
87
|
+
end
|
88
|
+
|
47
89
|
private
|
48
90
|
attr_reader :widget_trees
|
49
91
|
|
92
|
+
PARCELS_WORKAROUND_DIRECTORY_NAME = ".parcels_sprockets_workaround".freeze
|
93
|
+
|
94
|
+
def workaround_directory_name_for(widget_tree)
|
95
|
+
require 'digest/md5'
|
96
|
+
digest = Digest::MD5.hexdigest(widget_tree.root).strip
|
97
|
+
"#{PARCELS_WORKAROUND_DIRECTORY_NAME}_#{digest}"
|
98
|
+
end
|
99
|
+
|
50
100
|
def register_engines!
|
51
101
|
@engines_registered ||= begin
|
52
102
|
if ::Parcels.fortitude_available?
|
@@ -145,6 +145,9 @@ you may want to enable Parcels on any of its Fortitude superclasses, which are:
|
|
145
145
|
end
|
146
146
|
|
147
147
|
@_parcels_inline_css_fragments ||= [ ]
|
148
|
+
@_parcels_inline_css_fragments.delete_if do |fragment|
|
149
|
+
fragment.file == caller_file && fragment.line >= caller_line
|
150
|
+
end
|
148
151
|
@_parcels_inline_css_fragments += css_strings.map do |css_string|
|
149
152
|
::Parcels::Fragments::CssFragment.new(css_string, self, caller_file, caller_line, _parcels_css_options.merge(options))
|
150
153
|
end
|
@@ -26,7 +26,7 @@ module Parcels
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def usable?
|
29
|
-
|
29
|
+
!! widget_class
|
30
30
|
end
|
31
31
|
|
32
32
|
def included_in_any_set?(set_names)
|
@@ -96,7 +96,20 @@ module Parcels
|
|
96
96
|
end
|
97
97
|
|
98
98
|
def widget_class
|
99
|
-
@widget_class ||=
|
99
|
+
@widget_class ||= begin
|
100
|
+
if widget_class_full_path
|
101
|
+
begin
|
102
|
+
::Fortitude::Widget.widget_class_from_file(widget_class_full_path,
|
103
|
+
:root_dirs => widget_tree.widget_naming_root_dirs)
|
104
|
+
rescue ::Fortitude::Widget::Files::CannotDetermineWidgetClassNameError => cdwcne
|
105
|
+
raise unless cdwcne.resulting_objects.detect { |o| o.kind_of?(Module) }
|
106
|
+
:none
|
107
|
+
end
|
108
|
+
else
|
109
|
+
:none
|
110
|
+
end
|
111
|
+
end
|
112
|
+
@widget_class unless @widget_class == :none
|
100
113
|
end
|
101
114
|
end
|
102
115
|
end
|
@@ -8,6 +8,8 @@ module Parcels
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
attr_reader :file, :line
|
12
|
+
|
11
13
|
def initialize(css_string, source, file, line, options)
|
12
14
|
options.assert_valid_keys(:engines, :wrap, :prefix)
|
13
15
|
|
@@ -51,7 +53,7 @@ module Parcels
|
|
51
53
|
end
|
52
54
|
|
53
55
|
private
|
54
|
-
attr_reader :css_string, :source, :options
|
56
|
+
attr_reader :css_string, :source, :options
|
55
57
|
|
56
58
|
def header_comment
|
57
59
|
out = "/* From '#{file}'"
|
@@ -91,13 +93,8 @@ module Parcels
|
|
91
93
|
result = data
|
92
94
|
|
93
95
|
processors.each do |processor|
|
94
|
-
|
95
|
-
|
96
|
-
args = [ file, 1, { :load_paths => context.environment.paths } ]
|
97
|
-
end
|
98
|
-
|
99
|
-
template = processor.new(*args) { result }
|
100
|
-
result = template.render(context, {})
|
96
|
+
template = processor.new(file, 1, { :load_paths => context.environment.paths, :filename => file }) { result }
|
97
|
+
result = template.render(context, { :filename => file })
|
101
98
|
end
|
102
99
|
|
103
100
|
result
|
data/lib/parcels/sprockets.rb
CHANGED
@@ -9,10 +9,6 @@ module Parcels
|
|
9
9
|
@sprockets_version_components ||= ::Sprockets::VERSION.split(".").map { |x| x.to_i }
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.requires_explicit_load_paths_for_css_template?
|
13
|
-
sprockets_version_components[0] <= 2 && sprockets_version_components[1] < 11
|
14
|
-
end
|
15
|
-
|
16
12
|
def self.requires_fix_for_protected_methods_on_directive_processor?
|
17
13
|
RUBY_VERSION =~ /^2/ && sprockets_version_components[0] <= 2 && sprockets_version_components[1] < 11
|
18
14
|
end
|
@@ -95,7 +91,7 @@ if static_compiler_class
|
|
95
91
|
end
|
96
92
|
|
97
93
|
def each_logical_path(*args, &block)
|
98
|
-
@env.each_logical_path do |logical_path|
|
94
|
+
@env.each_logical_path(*args) do |logical_path|
|
99
95
|
unless ::Parcels.is_fortitude_logical_path?(logical_path)
|
100
96
|
block.call(logical_path)
|
101
97
|
end
|
@@ -110,27 +106,42 @@ if static_compiler_class
|
|
110
106
|
|
111
107
|
static_compiler_class.class_eval do
|
112
108
|
def env
|
113
|
-
|
109
|
+
::Parcels::Sprockets::StaticCompilerEnvProxy.new(@env)
|
114
110
|
end
|
115
111
|
end
|
116
112
|
end
|
117
113
|
end
|
118
114
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
115
|
+
[ 'sass/rails/importer', 'sprockets/sass/importer' ].each do |filename|
|
116
|
+
begin
|
117
|
+
require filename
|
118
|
+
rescue LoadError => le
|
119
|
+
# oh, well
|
120
|
+
end
|
123
121
|
end
|
124
122
|
|
125
|
-
[ '::Sprockets::SassImporter', '::Sass::Rails::Importer' ].each do |class_name|
|
123
|
+
[ '::Sprockets::SassImporter', '::Sass::Rails::Importer', '::Sprockets::Sass::Importer' ].each do |class_name|
|
126
124
|
klass = class_name.constantize rescue nil
|
127
125
|
|
128
126
|
if klass
|
129
127
|
klass.class_eval do
|
130
128
|
if defined?(klass::GLOB)
|
131
129
|
def find_relative_with_parcels(name, base, options)
|
132
|
-
|
133
|
-
|
130
|
+
sprockets_context = (options[:custom] || { })[:sprockets_context]
|
131
|
+
sprockets_context ||= context if respond_to?(:context)
|
132
|
+
unless sprockets_context
|
133
|
+
raise "Unable to find the Sprockets context here; it was neither in options, nor do we have it in the class"
|
134
|
+
end
|
135
|
+
|
136
|
+
parcels = sprockets_context.environment.parcels
|
137
|
+
expanded_locations_to_search = sprockets_context.environment.paths + [ File.dirname(base) ]
|
138
|
+
expanded_locations_to_search = expanded_locations_to_search.map do |location|
|
139
|
+
if location.kind_of?(::Pathname)
|
140
|
+
location
|
141
|
+
else
|
142
|
+
::Pathname.new(location.to_s)
|
143
|
+
end
|
144
|
+
end
|
134
145
|
|
135
146
|
if name =~ self.class.const_get(:GLOB) && parcels.is_underneath_root?(base)
|
136
147
|
paths_to_search = expanded_locations_to_search
|
@@ -143,7 +154,8 @@ end
|
|
143
154
|
end
|
144
155
|
end
|
145
156
|
|
146
|
-
|
157
|
+
load_paths = (options[:load_paths] || [ ]) + expanded_locations_to_search
|
158
|
+
return find_relative_without_parcels(name, base, options.merge(:load_paths => load_paths))
|
147
159
|
end
|
148
160
|
|
149
161
|
alias_method_chain :find_relative, :parcels
|
@@ -3,6 +3,11 @@ module Parcels
|
|
3
3
|
module PathUtils
|
4
4
|
class << self
|
5
5
|
def path_under(path, under_what)
|
6
|
+
maybe_path_under(path, under_what) ||
|
7
|
+
raise(Errno::ENOENT, %{Path #{path.inspect} is not underneath directory #{under_what.inspect}.})
|
8
|
+
end
|
9
|
+
|
10
|
+
def maybe_path_under(path, under_what)
|
6
11
|
path = path.to_s.strip
|
7
12
|
under_what = under_what.to_s.strip
|
8
13
|
|
@@ -10,8 +15,6 @@ module Parcels
|
|
10
15
|
path[under_what.length..under_what.length] == File::SEPARATOR
|
11
16
|
|
12
17
|
path[(under_what.length + 1)..-1]
|
13
|
-
else
|
14
|
-
raise Errno::ENOENT, %{Path #{path.inspect} is not underneath directory #{under_what.inspect}.}
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
data/lib/parcels/version.rb
CHANGED
data/lib/parcels/widget_tree.rb
CHANGED
@@ -4,6 +4,8 @@ require 'parcels/fortitude_inline_parcel'
|
|
4
4
|
require 'parcels/fortitude_alongside_parcel'
|
5
5
|
require 'parcels/dependency_parcel_list'
|
6
6
|
|
7
|
+
require 'pathname'
|
8
|
+
|
7
9
|
require 'find'
|
8
10
|
|
9
11
|
module Parcels
|
@@ -17,11 +19,14 @@ module Parcels
|
|
17
19
|
@sprockets_environments_added_to = { }
|
18
20
|
end
|
19
21
|
|
22
|
+
def widget_naming_root_dirs
|
23
|
+
@widget_naming_root_dirs ||= [ root, File.dirname(root) ]
|
24
|
+
end
|
25
|
+
|
20
26
|
def add_workaround_directory_to_sprockets!(sprockets_environment)
|
21
27
|
return if (! root_exists?)
|
22
28
|
|
23
29
|
@sprockets_environments_added_to[sprockets_environment] ||= begin
|
24
|
-
ensure_workaround_directory_is_set_up!
|
25
30
|
sprockets_environment.prepend_path(workaround_directory)
|
26
31
|
true
|
27
32
|
end
|
@@ -31,6 +36,26 @@ module Parcels
|
|
31
36
|
::Parcels::Utils::PathUtils.path_under(full_path, root)
|
32
37
|
end
|
33
38
|
|
39
|
+
def remove_workaround_directory_from(full_path)
|
40
|
+
if (path_under_workaround = ::Parcels::Utils::PathUtils.maybe_path_under(full_path, workaround_directory))
|
41
|
+
if (separator_index = path_under_workaround.index(File::SEPARATOR))
|
42
|
+
if (separator_index > 0 && separator_index < (path_under_workaround.length - 1))
|
43
|
+
link_name = path_under_workaround[0..(separator_index - 1)]
|
44
|
+
after_link = path_under_workaround[(separator_index + 1)..-1]
|
45
|
+
|
46
|
+
if File.symlink?(File.join(workaround_directory, link_name))
|
47
|
+
link_value = File.readlink(File.join(workaround_directory, link_name))
|
48
|
+
resolved_link = File.expand_path(File.join(workaround_directory, link_value))
|
49
|
+
final_path = File.join(resolved_link, after_link)
|
50
|
+
return final_path
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
|
34
59
|
def add_all_widgets_to_sprockets_context!(sprockets_context, set_names)
|
35
60
|
return unless root_exists?
|
36
61
|
sprockets_context.depend_on(root)
|
@@ -47,7 +72,13 @@ module Parcels
|
|
47
72
|
extension = File.extname(full_path).strip.downcase
|
48
73
|
if (klass = EXTENSION_TO_PARCEL_CLASS_MAP[extension])
|
49
74
|
parcel = klass.new(self, full_path)
|
50
|
-
|
75
|
+
if parcel.usable? && parcel.included_in_any_set?(set_names)
|
76
|
+
if all_parcels.length == 0
|
77
|
+
ensure_workaround_directory_is_set_up!
|
78
|
+
end
|
79
|
+
|
80
|
+
all_parcels << parcel
|
81
|
+
end
|
51
82
|
end
|
52
83
|
end
|
53
84
|
|
@@ -66,8 +97,6 @@ module Parcels
|
|
66
97
|
|
67
98
|
ALL_EXTENSIONS = EXTENSION_TO_PARCEL_CLASS_MAP.keys.dup.freeze
|
68
99
|
|
69
|
-
PARCELS_WORKAROUND_DIRECTORY_NAME = ".parcels_sprockets_workaround".freeze
|
70
|
-
|
71
100
|
PARCELS_LOGICAL_PATH_PREFIXES = EXTENSION_TO_PARCEL_CLASS_MAP.values.map { |k| k.logical_path_prefix }
|
72
101
|
|
73
102
|
def root_exists?
|
@@ -75,7 +104,7 @@ module Parcels
|
|
75
104
|
end
|
76
105
|
|
77
106
|
def workaround_directory
|
78
|
-
@workaround_directory ||=
|
107
|
+
@workaround_directory ||= parcels_environment.workaround_directory_root_for_widget_tree(self)
|
79
108
|
end
|
80
109
|
|
81
110
|
def ensure_workaround_directory_is_set_up!
|
@@ -127,7 +156,7 @@ However, this directory currently contains other file(s) that we weren't expecti
|
|
127
156
|
if File.symlink?(symlink)
|
128
157
|
contents = File.readlink(symlink)
|
129
158
|
|
130
|
-
if contents ==
|
159
|
+
if contents == symlink_target
|
131
160
|
# ok, great
|
132
161
|
else
|
133
162
|
File.delete(symlink)
|
@@ -151,8 +180,14 @@ and try again.}
|
|
151
180
|
|
152
181
|
def create_symlink!(prefix)
|
153
182
|
Dir.chdir(workaround_directory) do
|
154
|
-
FileUtils.ln_s(
|
183
|
+
FileUtils.ln_s(symlink_target, prefix)
|
155
184
|
end
|
156
185
|
end
|
186
|
+
|
187
|
+
def symlink_target
|
188
|
+
workaround_dir_path = Pathname.new(workaround_directory).realpath
|
189
|
+
root_path = Pathname.new(root).realpath
|
190
|
+
root_path.relative_path_from(workaround_dir_path).to_s
|
191
|
+
end
|
157
192
|
end
|
158
193
|
end
|
data/parcels.gemspec
CHANGED
@@ -44,5 +44,5 @@ Gem::Specification.new do |spec|
|
|
44
44
|
|
45
45
|
spec.add_development_dependency "oop_rails_server", "~> 0", ">= 0.0.5"
|
46
46
|
spec.add_development_dependency "css_parser"
|
47
|
-
spec.add_development_dependency "fortitude", ">= 0.9.
|
47
|
+
spec.add_development_dependency "fortitude", ">= 0.9.2"
|
48
48
|
end
|
@@ -3,9 +3,13 @@ module SprocketsHelpers
|
|
3
3
|
::Sprockets::Environment.new(*args)
|
4
4
|
end
|
5
5
|
|
6
|
+
def reset_sprockets_env!
|
7
|
+
per_example_data[:sprockets_env] = nil
|
8
|
+
end
|
9
|
+
|
6
10
|
def sprockets_env(*args, &block)
|
7
11
|
out = if args.length > 0 || block
|
8
|
-
raise "Duplicate creation of sprockets_env? #{args.inspect}" if
|
12
|
+
raise "Duplicate creation of sprockets_env? #{args.inspect}" if per_example_data[:sprockets_env]
|
9
13
|
args = [ this_example_root ] if args.length == 0
|
10
14
|
per_example_data[:sprockets_env] = new_sprockets_env(*args)
|
11
15
|
block.call(per_example_data[:sprockets_env]) if block
|
@@ -17,7 +21,13 @@ module SprocketsHelpers
|
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
20
|
-
|
24
|
+
default_widget_trees_to_add_to_sprockets.each do |widget_tree_root|
|
25
|
+
out.parcels.add_widget_tree!(widget_tree_root)
|
26
|
+
end
|
21
27
|
out
|
22
28
|
end
|
29
|
+
|
30
|
+
def default_widget_trees_to_add_to_sprockets
|
31
|
+
[ File.join(this_example_root, 'views') ]
|
32
|
+
end
|
23
33
|
end
|
@@ -5,11 +5,14 @@ require 'spec/expected/base_expected_asset'
|
|
5
5
|
module Spec
|
6
6
|
module Expected
|
7
7
|
class ExpectedAsset < BaseExpectedAsset
|
8
|
-
def initialize(root_directory, expected_subpath, &block)
|
8
|
+
def initialize(root_directory, expected_subpath, options = { }, &block)
|
9
9
|
super(root_directory, expected_subpath)
|
10
10
|
|
11
11
|
@expected_rules = { }
|
12
12
|
@allow_extra_rules = false
|
13
|
+
@options = options
|
14
|
+
|
15
|
+
options.assert_valid_keys(:sequencing)
|
13
16
|
|
14
17
|
instance_eval(&block) if block
|
15
18
|
end
|
@@ -52,7 +55,7 @@ module Spec
|
|
52
55
|
message << "\n\n #{remaining_asset}:\n #{remaining_asset.source}\n"
|
53
56
|
end
|
54
57
|
raise message
|
55
|
-
elsif matching_remaining_assets.length == 1
|
58
|
+
elsif matching_remaining_assets.length == 1 || options[:sequencing]
|
56
59
|
matching_remaining_asset = matching_remaining_assets.first
|
57
60
|
|
58
61
|
unless asset_matches?(matching_remaining_asset)
|
@@ -79,7 +82,7 @@ module Spec
|
|
79
82
|
end
|
80
83
|
|
81
84
|
private
|
82
|
-
attr_reader :expected_rules
|
85
|
+
attr_reader :expected_rules, :options
|
83
86
|
|
84
87
|
def extra_rules_allowed?
|
85
88
|
!! @allow_extra_rules
|
@@ -12,8 +12,8 @@ module Spec
|
|
12
12
|
instance_eval(&block) if block
|
13
13
|
end
|
14
14
|
|
15
|
-
def asset(subpath, &block)
|
16
|
-
expected_asset = Spec::Expected::ExpectedAsset.new(root_directory, subpath, &block)
|
15
|
+
def asset(subpath, options = { }, &block)
|
16
|
+
expected_asset = Spec::Expected::ExpectedAsset.new(root_directory, subpath, options, &block)
|
17
17
|
@expected_assets << expected_asset
|
18
18
|
end
|
19
19
|
|
@@ -99,4 +99,15 @@ describe "Parcels Rails basic support", :type => :rails do
|
|
99
99
|
allow_additional_assets!
|
100
100
|
end)
|
101
101
|
end
|
102
|
+
|
103
|
+
it "should allow putting a .rb file in views/ that is just a module (~ helpers)" do
|
104
|
+
compiled_rails_asset('application.css').should_match(rails_assets do
|
105
|
+
asset 'views/basic_rails_spec/helpers_module_test.rb' do
|
106
|
+
expect_wrapped_rule :p, 'color: green'
|
107
|
+
end
|
108
|
+
allow_additional_assets!
|
109
|
+
end)
|
110
|
+
|
111
|
+
expect_match("helpers_module_test", /and it is this is my_helper\! tada\!/)
|
112
|
+
end
|
102
113
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
describe "Parcels ad-hoc development mode support", :type => :system do
|
2
|
+
# Rails' development mode (which is really just ActiveSupport's class-unloading support) does the right thing:
|
3
|
+
# it actually completely unloads every class after each request cycle, removing the old class definition from memory
|
4
|
+
# (well, modulo GC, but you get the idea). This means that if you remove or change CSS definitions in a widget class,
|
5
|
+
# they will genuinely be gone/changed on the next iteration, and Parcels will behave correctly.
|
6
|
+
#
|
7
|
+
# Some programs, however -- Middleman is where I discovered this issue -- simply re-evaluate templates in development
|
8
|
+
# mode. For "normal" templates (e.g., ERb, HAML, whatever), this works just fine. But, with Parcels, this can be an
|
9
|
+
# issue: the widget class definition itself just gets re-processed, and, if you've removed CSS from the class or
|
10
|
+
# changed that CSS, the class will now have both the new *and* the old definitions around. This causes really
|
11
|
+
# frustrating chaos as your changes seem to sometimes, but not always, get picked up, depending on whether the new
|
12
|
+
# CSS actually overrides the old or depends on the old not being present (like removing a CSS selector, etc.).
|
13
|
+
#
|
14
|
+
# Unfortunately, due to the way Ruby classes work, there's no one "right way" around this issue: Ruby doesn't have
|
15
|
+
# any kind of callback saying "class X is getting defined", because re-opening classes means that there's really no
|
16
|
+
# objective way of deciding when that's true. Instead, we check for declarations of CSS on a widget class where the
|
17
|
+
# line number is equal to, or before, the line numbers of other CSS declarations, and remove those other declarations
|
18
|
+
# when this happens.
|
19
|
+
#
|
20
|
+
# This doesn't catch every single case -- if you simultaneously change CSS and add one or more lines above the .css
|
21
|
+
# call in a class, for example, it will be missed -- but it catches the vast majority of cases, and is uniformly an
|
22
|
+
# improvement to the system.
|
23
|
+
#
|
24
|
+
# This is a test to make sure that works.
|
25
|
+
context "with a widget class that gets changed" do
|
26
|
+
before :each do
|
27
|
+
files {
|
28
|
+
file 'assets/basic.css', %{
|
29
|
+
//= require_parcels
|
30
|
+
}
|
31
|
+
|
32
|
+
widget 'views/my_widget' do
|
33
|
+
css %{
|
34
|
+
p { color: red; }
|
35
|
+
}
|
36
|
+
css %{
|
37
|
+
span { color: green; }
|
38
|
+
}
|
39
|
+
end
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should handle the case where the CSS changes" do
|
44
|
+
compiled_sprockets_asset('basic').should_match(file_assets do
|
45
|
+
asset 'views/my_widget.rb', :sequencing => true do
|
46
|
+
expect_wrapped_rule :p, 'color: red'
|
47
|
+
end
|
48
|
+
|
49
|
+
asset 'views/my_widget.rb', :sequencing => true do
|
50
|
+
expect_wrapped_rule :span, 'color: green'
|
51
|
+
end
|
52
|
+
end)
|
53
|
+
|
54
|
+
widget_path = File.join(this_example_root, 'views', 'my_widget.rb')
|
55
|
+
expect(File.exist?(widget_path)).to be
|
56
|
+
|
57
|
+
File.open(widget_path, 'w') do |f|
|
58
|
+
f << <<-EOS
|
59
|
+
class Views::MyWidget < ::Spec::Fixtures::WidgetBase
|
60
|
+
css %{
|
61
|
+
p { color: yellow; }
|
62
|
+
}
|
63
|
+
end
|
64
|
+
EOS
|
65
|
+
end
|
66
|
+
|
67
|
+
old_sprockets_env = sprockets_env
|
68
|
+
reset_sprockets_env!
|
69
|
+
|
70
|
+
load(widget_path)
|
71
|
+
expect(sprockets_env.object_id).not_to eq(old_sprockets_env.object_id)
|
72
|
+
|
73
|
+
compiled_sprockets_asset('basic').should_match(file_assets do
|
74
|
+
asset 'views/my_widget.rb' do
|
75
|
+
expect_wrapped_rule :p, 'color: yellow'
|
76
|
+
end
|
77
|
+
end)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -161,10 +161,12 @@ describe "Parcels alongside files", :type => :system do
|
|
161
161
|
}
|
162
162
|
}
|
163
163
|
|
164
|
+
compiled_sprockets_asset('basic').source # to make sure workaround directories get added
|
165
|
+
|
164
166
|
ter = this_example_root
|
165
167
|
asset = compiled_sprockets_asset('one')
|
166
168
|
asset.should_match(file_assets do
|
167
|
-
asset 'views
|
169
|
+
asset 'views/my_widget.pcss' do
|
168
170
|
expect_rule ".parcels_class__views__my_widget p", 'color: red'
|
169
171
|
end
|
170
172
|
end)
|
@@ -0,0 +1,60 @@
|
|
1
|
+
describe "Parcels determining classes from files", :type => :system do
|
2
|
+
context "with a widget with a non-guessable class name, but at the right point in its path" do
|
3
|
+
before :each do
|
4
|
+
files {
|
5
|
+
file 'assets/basic.css', %{
|
6
|
+
//= require_parcels
|
7
|
+
}
|
8
|
+
|
9
|
+
file 'views/foo/bar/baz.rb', %{
|
10
|
+
path = [ "Vie", "oo", "Ba", "az" ]
|
11
|
+
path[0] = path[0] + "ws"
|
12
|
+
path[1] = "F" + path[1]
|
13
|
+
path[2] = path[2] + "r"
|
14
|
+
path[3] = "B" + path[3]
|
15
|
+
|
16
|
+
(0..2).each do |index|
|
17
|
+
module_name = path[0..index].join("::")
|
18
|
+
eval("module \#{module_name}; end")
|
19
|
+
end
|
20
|
+
|
21
|
+
class_name = path.join("::")
|
22
|
+
|
23
|
+
klass = Class.new(::Spec::Fixtures::WidgetBase) do
|
24
|
+
css 'p { color: red; }'
|
25
|
+
|
26
|
+
def content
|
27
|
+
p 'hello!'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
mod = eval(path[0..-2].join("::"))
|
32
|
+
mod.const_set(path[-1], klass)
|
33
|
+
}
|
34
|
+
|
35
|
+
# eval("class \#{class_name} < ::Spec::Fixtures::WidgetBase; css 'p { color: red; }'; def content; p 'hello!'; end; end")
|
36
|
+
|
37
|
+
file 'views/foo/bar/baz.pcss', %{
|
38
|
+
div { color: blue; }
|
39
|
+
}
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should be able to aggregate the CSS correctly still" do
|
44
|
+
compiled_sprockets_asset('basic').should_match(file_assets do
|
45
|
+
asset 'views/foo/bar/baz.rb' do
|
46
|
+
expect_wrapped_rule :p, 'color: red'
|
47
|
+
end
|
48
|
+
|
49
|
+
asset 'views/foo/bar/baz.pcss' do
|
50
|
+
expect_wrapped_rule :div, 'color: blue'
|
51
|
+
end
|
52
|
+
end)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should apply the correct autogenerated class to the widget" do
|
56
|
+
doc = render_file_asset('views/foo/bar/baz')
|
57
|
+
expect(classes_from(doc, 'p')).to eq([ expected_file_asset('views/foo/bar/baz.rb').parcels_wrapping_class ])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
describe "Parcels workaround directories", :type => :system do
|
2
|
+
context "with a simple widget" do
|
3
|
+
before :each do
|
4
|
+
files {
|
5
|
+
file 'assets/basic.css', %{
|
6
|
+
//= require_parcels
|
7
|
+
}
|
8
|
+
|
9
|
+
widget 'views/my_widget' do
|
10
|
+
css %{
|
11
|
+
p { color: red; }
|
12
|
+
}
|
13
|
+
end
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def all_workaround_directories_in(base_dir)
|
18
|
+
out = [ ]
|
19
|
+
Find.find(base_dir) do |file|
|
20
|
+
out << file if File.basename(file) =~ /^#{Regexp.escape(::Parcels::Environment::PARCELS_WORKAROUND_DIRECTORY_NAME)}/
|
21
|
+
end
|
22
|
+
out
|
23
|
+
end
|
24
|
+
|
25
|
+
def ensure_asset_compiles!
|
26
|
+
compiled_sprockets_asset('basic').should_match(file_assets do
|
27
|
+
asset 'views/my_widget.rb' do
|
28
|
+
expect_wrapped_rule :p, 'color: red'
|
29
|
+
end
|
30
|
+
end)
|
31
|
+
end
|
32
|
+
|
33
|
+
def default_widget_trees_to_add_to_sprockets
|
34
|
+
[ ]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should, by default, put workaround directories inside the widget-tree root" do
|
38
|
+
sprockets_env.parcels.add_widget_tree!(File.join(this_example_root, 'views'))
|
39
|
+
ensure_asset_compiles!
|
40
|
+
expect(all_workaround_directories_in(this_example_root)).to eq([
|
41
|
+
File.join(this_example_root, "views/#{::Parcels::Environment::PARCELS_WORKAROUND_DIRECTORY_NAME}")
|
42
|
+
])
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should put workaround directories elsewhere if you tell it to" do
|
46
|
+
require 'tmpdir'
|
47
|
+
test_dir = Dir.mktmpdir do |tempdir|
|
48
|
+
sprockets_env.parcels.workaround_directories_root = File.join(tempdir, 'foo', 'bar')
|
49
|
+
sprockets_env.parcels.add_widget_tree!(File.join(this_example_root, 'views'))
|
50
|
+
ensure_asset_compiles!
|
51
|
+
|
52
|
+
expect(all_workaround_directories_in(this_example_root)).to eq([ ])
|
53
|
+
expect(all_workaround_directories_in(tempdir).length).to eq(1)
|
54
|
+
expect(all_workaround_directories_in(tempdir)[0]).to match(
|
55
|
+
/^#{Regexp.escape(File.join(tempdir, 'foo', 'bar', ::Parcels::Environment::PARCELS_WORKAROUND_DIRECTORY_NAME))}_[0-9a-f]{32}$/
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should let you re-set the workaround directory location to the same thing as much as you want" do
|
61
|
+
require 'tmpdir'
|
62
|
+
test_dir = Dir.mktmpdir do |tempdir|
|
63
|
+
sprockets_env.parcels.workaround_directories_root = File.join(tempdir, 'foo', 'bar')
|
64
|
+
sprockets_env.parcels.add_widget_tree!(File.join(this_example_root, 'views'))
|
65
|
+
ensure_asset_compiles!
|
66
|
+
|
67
|
+
sprockets_env.parcels.workaround_directories_root = File.join(tempdir, 'foo', 'bar')
|
68
|
+
ensure_asset_compiles!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should give you an exception if you try to change the workaround directory location after it's been used" do
|
73
|
+
sprockets_env.parcels.add_widget_tree!(File.join(this_example_root, 'views'))
|
74
|
+
ensure_asset_compiles!
|
75
|
+
|
76
|
+
expect do
|
77
|
+
sprockets_env.parcels.workaround_directories_root = this_example_root
|
78
|
+
end.to raise_exception(/can't set/)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parcels
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Geweke
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -148,14 +148,14 @@ dependencies:
|
|
148
148
|
requirements:
|
149
149
|
- - ">="
|
150
150
|
- !ruby/object:Gem::Version
|
151
|
-
version: 0.9.
|
151
|
+
version: 0.9.2
|
152
152
|
type: :development
|
153
153
|
prerelease: false
|
154
154
|
version_requirements: !ruby/object:Gem::Requirement
|
155
155
|
requirements:
|
156
156
|
- - ">="
|
157
157
|
- !ruby/object:Gem::Version
|
158
|
-
version: 0.9.
|
158
|
+
version: 0.9.2
|
159
159
|
description: Allows you to package the CSS and Javascript for your view together with
|
160
160
|
that view, creating self-contained parcels of view code that seamlessly work together.
|
161
161
|
When used with Fortitude, automatically scopes your CSS, too. No more dueling CSS
|
@@ -169,6 +169,7 @@ files:
|
|
169
169
|
- ".gitignore"
|
170
170
|
- ".rspec-local"
|
171
171
|
- ".travis.yml"
|
172
|
+
- CHANGES.md
|
172
173
|
- Gemfile
|
173
174
|
- LICENSE.txt
|
174
175
|
- README.md
|
@@ -231,6 +232,8 @@ files:
|
|
231
232
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_and_inline_html.html.rb
|
232
233
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_erb.pcss
|
233
234
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_erb.rb
|
235
|
+
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/helpers_module.rb
|
236
|
+
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/helpers_module_test.rb
|
234
237
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/inline_erb.rb
|
235
238
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/multiple_engines.pcss
|
236
239
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/multiple_engines.rb
|
@@ -314,14 +317,17 @@ files:
|
|
314
317
|
- spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_one.rb
|
315
318
|
- spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_two.pcss
|
316
319
|
- spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_two.rb
|
320
|
+
- spec/system/ad_hoc_development_mode_spec.rb
|
317
321
|
- spec/system/alongside_file_spec.rb
|
318
322
|
- spec/system/autogenerated_class_application_spec.rb
|
319
323
|
- spec/system/basic_system_spec.rb
|
324
|
+
- spec/system/class_from_file_spec.rb
|
320
325
|
- spec/system/dependency_sorting_spec.rb
|
321
326
|
- spec/system/engines_spec.rb
|
322
327
|
- spec/system/prefix_spec.rb
|
323
328
|
- spec/system/sass_features_spec.rb
|
324
329
|
- spec/system/sets_spec.rb
|
330
|
+
- spec/system/workaround_directories_spec.rb
|
325
331
|
homepage: https://github.com/ageweke/parcels
|
326
332
|
licenses:
|
327
333
|
- MIT
|
@@ -384,6 +390,8 @@ test_files:
|
|
384
390
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_and_inline_html.html.rb
|
385
391
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_erb.pcss
|
386
392
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/alongside_erb.rb
|
393
|
+
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/helpers_module.rb
|
394
|
+
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/helpers_module_test.rb
|
387
395
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/inline_erb.rb
|
388
396
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/multiple_engines.pcss
|
389
397
|
- spec/rails/templates/basic_rails_spec/app/views/basic_rails_spec/multiple_engines.rb
|
@@ -467,11 +475,15 @@ test_files:
|
|
467
475
|
- spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_one.rb
|
468
476
|
- spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_two.pcss
|
469
477
|
- spec/rails/templates/sets_rails_spec/app/views/sets_rails_spec/normal_two.rb
|
478
|
+
- spec/system/ad_hoc_development_mode_spec.rb
|
470
479
|
- spec/system/alongside_file_spec.rb
|
471
480
|
- spec/system/autogenerated_class_application_spec.rb
|
472
481
|
- spec/system/basic_system_spec.rb
|
482
|
+
- spec/system/class_from_file_spec.rb
|
473
483
|
- spec/system/dependency_sorting_spec.rb
|
474
484
|
- spec/system/engines_spec.rb
|
475
485
|
- spec/system/prefix_spec.rb
|
476
486
|
- spec/system/sass_features_spec.rb
|
477
487
|
- spec/system/sets_spec.rb
|
488
|
+
- spec/system/workaround_directories_spec.rb
|
489
|
+
has_rdoc:
|