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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 658277fafd37674b7c9be8026a325a2cb907f89c
4
- data.tar.gz: a1f74856053841ef8fb0573d246b64a712544c49
3
+ metadata.gz: f8c86251a8065212ca19858c38857005a7871457
4
+ data.tar.gz: 9be314a2db597e039c54dd4c4365e649e345fce5
5
5
  SHA512:
6
- metadata.gz: a589bcc70801b68c35d4d3b16e2a07e7863a199e211a96ca50f171dac1ea623215ed034084f8efcd7845b827565275eb51d832bd6a8a00bcf8f17f90d6606fcb
7
- data.tar.gz: 3005a5072e9d47179a0946ce166626cf6db502f9c99fe1f74b87014b57b2776369c1d04427a7f85be903a3d309d7002ca8a7abdad50d3327f8373343d90d8dd8
6
+ metadata.gz: 0507164165fabbce70addd13598209794d45bbfe414870db3cda85e8766de0edeca1597f973170b55444979443bd941823a00979396b3c5c7e8d02398d88be5b
7
+ data.tar.gz: 89b09a7873d8ebbf440aa06a8673bc7ddc66dd7e42975a0d72d3adf963cfddc649d252eef73691b595e25f1aa6d94da9392c5011ff222e724b506342eb43d54d
@@ -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/)).
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 Andrew Geweke
1
+ Copyright (c) 2014-2015 Andrew Geweke
2
2
 
3
3
  MIT License
4
4
 
@@ -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(pathname)
34
- ::Fortitude::Widget.widget_class_from_file(pathname, :root_dirs => widget_trees.map(&:root))
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
@@ -24,7 +24,7 @@ module Parcels
24
24
  end
25
25
 
26
26
  def usable?
27
- widget_class_full_path
27
+ super && widget_class_full_path
28
28
  end
29
29
 
30
30
  private
@@ -26,7 +26,7 @@ module Parcels
26
26
  end
27
27
 
28
28
  def usable?
29
- true
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 ||= ::Fortitude::Widget.widget_class_from_file(widget_class_full_path, :root_dirs => [ widget_tree.root ])
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, :file, :line
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
- args = [ file ]
95
- if processor == ::Tilt::ScssTemplate && (::Parcels::Sprockets.requires_explicit_load_paths_for_css_template?)
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
@@ -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
- @_parcels_env_proxy ||= ::Parcels::Sprockets::StaticCompilerEnvProxy.new(@env)
109
+ ::Parcels::Sprockets::StaticCompilerEnvProxy.new(@env)
114
110
  end
115
111
  end
116
112
  end
117
113
  end
118
114
 
119
- begin
120
- require 'sass/rails/importer'
121
- rescue LoadError => le
122
- # oh, well
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
- parcels = context.environment.parcels
133
- expanded_locations_to_search = context.environment.paths + [ File.dirname(base) ]
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
- return find_relative_without_parcels(name, base, options.merge(:load_paths => expanded_locations_to_search))
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
 
@@ -1,3 +1,3 @@
1
1
  module Parcels
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -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
- all_parcels << parcel if parcel.usable? && parcel.included_in_any_set?(set_names)
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 ||= File.join(root, PARCELS_WORKAROUND_DIRECTORY_NAME)
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 == SYMLINK_TARGET
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(SYMLINK_TARGET, prefix)
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
@@ -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.1"
47
+ spec.add_development_dependency "fortitude", ">= 0.9.2"
48
48
  end
@@ -5,7 +5,7 @@ module ParcelsRailsHelpers
5
5
 
6
6
  def rails_server_additional_gemfile_lines
7
7
  [
8
- "gem 'fortitude', \">= 0.9.0\"",
8
+ "gem 'fortitude', \">= 0.9.2\"",
9
9
  "gem 'parcels', :path => '#{rails_server_project_root}'"
10
10
  ]
11
11
  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 @sprockets_env
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
- out.parcels.add_widget_tree!(File.join(this_example_root, 'views'))
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,5 @@
1
+ module Views::BasicRailsSpec::HelpersModule
2
+ def my_helper
3
+ text "this is my_helper!"
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class Views::BasicRailsSpec::HelpersModuleTest < Views::Widgets::Base
2
+ include Views::BasicRailsSpec::HelpersModule
3
+
4
+ css %{
5
+ p { color: green; }
6
+ }
7
+
8
+ def content
9
+ text "and it is "
10
+ my_helper
11
+ text " tada!"
12
+ end
13
+ 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/.parcels_sprockets_workaround/_parcels_alongside/my_widget.pcss' do
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.1
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: 2014-12-15 00:00:00.000000000 Z
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.1
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.1
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: