sproutcore 1.6.0.1-java → 1.7.1.beta-java
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.
- data/CHANGELOG +21 -0
- data/Gemfile +5 -0
- data/Rakefile +26 -13
- data/VERSION.yml +2 -2
- data/lib/Buildfile +43 -4
- data/lib/buildtasks/build.rake +10 -0
- data/lib/buildtasks/helpers/file_rule.rb +22 -0
- data/lib/buildtasks/helpers/file_rule_list.rb +137 -0
- data/lib/buildtasks/manifest.rake +133 -122
- data/lib/frameworks/sproutcore/CHANGELOG.md +69 -2
- data/lib/frameworks/sproutcore/apps/tests/english.lproj/strings.js +1 -0
- data/lib/frameworks/sproutcore/frameworks/bootstrap/system/browser.js +28 -22
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/array.js +9 -5
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controllers/controller.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/controls/button.js +18 -13
- data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/bind.js +5 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/ext/handlebars/collection.js +2 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/action_support.js +80 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/mixins/template_helpers/text_field_support.js +84 -116
- data/lib/frameworks/sproutcore/frameworks/core_foundation/panes/pane.js +8 -5
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/event.js +157 -157
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/platform.js +5 -3
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/root_responder.js +6 -6
- data/lib/frameworks/sproutcore/frameworks/core_foundation/system/sparse_array.js +10 -7
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/mixins/action_support.js +106 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/collection.js +18 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/template/handlebars.js +71 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/attribute_bindings_test.js +38 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/class_name_bindings_test.js +47 -0
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutChildViews.js +18 -18
- data/lib/frameworks/sproutcore/frameworks/core_foundation/tests/views/view/layoutStyle.js +42 -10
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view.js +158 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/keyboard.js +26 -1
- data/lib/frameworks/sproutcore/frameworks/core_foundation/views/view/layout_style.js +14 -8
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record.js +15 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +108 -108
- data/lib/frameworks/sproutcore/frameworks/datastore/system/query.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/record/error_methods.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/models/single_attribute.js +26 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/query/builders.js +7 -0
- data/lib/frameworks/sproutcore/frameworks/datastore/tests/system/record_array/error_methods.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/system/datetime.js +4 -1
- data/lib/frameworks/sproutcore/frameworks/datetime/frameworks/core/tests/system/datetime.js +6 -0
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/menu.js +26 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/panes/picker.js +97 -96
- data/lib/frameworks/sproutcore/frameworks/desktop/system/drag.js +4 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/tests/panes/menu/ui.js +17 -4
- data/lib/frameworks/sproutcore/frameworks/desktop/views/collection.js +7 -7
- data/lib/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +7 -5
- data/lib/frameworks/sproutcore/frameworks/desktop/views/scroll.js +12 -3
- data/lib/frameworks/sproutcore/frameworks/desktop/views/web.js +23 -14
- data/lib/frameworks/sproutcore/frameworks/experimental/Buildfile +5 -1
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/render_delegates/menu_scroller.js +28 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/tests/menu/scroll.js +235 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroll.js +363 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/menu/views/menu/scroller.js +250 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/desktop_scroller.js +92 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/native_scroll.js +25 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/scroll.js +33 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/render_delegates/touch_scroller.js +76 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/integration.js +50 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/methods.js +143 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/tests/scroll/ui.js +258 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroll.js +1164 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/core_scroller.js +332 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroll.js +236 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/desktop/scroller.js +347 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroll.js +15 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/scroller.js +10 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroll.js +804 -0
- data/lib/frameworks/sproutcore/frameworks/experimental/frameworks/scroll_view/views/touch/scroller.js +133 -0
- data/lib/frameworks/sproutcore/frameworks/foundation/resources/text_field.css +3 -3
- data/lib/frameworks/sproutcore/frameworks/foundation/validators/number.js +3 -1
- data/lib/frameworks/sproutcore/frameworks/foundation/views/text_field.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/media/views/audio.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/media/views/controls.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/media/views/media_slider.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/media/views/mini_controls.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/media/views/simple_controls.js +2 -4
- data/lib/frameworks/sproutcore/frameworks/media/views/video.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/routing/system/routes.js +29 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/core.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/debug/test_suites/array/replace.js +1 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/private/property_chain.js +2 -1
- data/lib/frameworks/sproutcore/frameworks/runtime/system/binding.js +3 -3
- data/lib/frameworks/sproutcore/frameworks/runtime/system/index_set.js +2 -2
- data/lib/frameworks/sproutcore/frameworks/runtime/system/object.js +1 -1
- data/lib/frameworks/sproutcore/themes/ace/resources/collection/normal/list_item.css +2 -2
- data/lib/frameworks/sproutcore/themes/legacy_theme/english.lproj/segmented.css +1 -1
- data/lib/gen/app/templates/apps/@target_name@/Buildfile +3 -5
- data/lib/gen/app/templates/apps/@target_name@/resources/_theme.css +18 -0
- data/lib/gen/project/templates/@filename@/Buildfile +2 -2
- data/lib/sproutcore.rb +30 -5
- data/lib/sproutcore/builders.rb +1 -0
- data/lib/sproutcore/builders/chance_file.rb +9 -16
- data/lib/sproutcore/builders/html.rb +2 -1
- data/lib/sproutcore/builders/minify.rb +4 -35
- data/lib/sproutcore/builders/module.rb +38 -1
- data/lib/sproutcore/builders/split.rb +63 -0
- data/lib/sproutcore/builders/strings.rb +7 -1
- data/lib/sproutcore/helpers.rb +1 -1
- data/lib/sproutcore/helpers/css_split.rb +190 -0
- data/lib/sproutcore/helpers/entry_sorter.rb +2 -0
- data/lib/sproutcore/helpers/minifier.rb +40 -16
- data/lib/sproutcore/helpers/static_helper.rb +35 -17
- data/lib/sproutcore/models/manifest.rb +26 -0
- data/lib/sproutcore/models/target.rb +12 -1
- data/lib/sproutcore/rack.rb +1 -0
- data/lib/sproutcore/rack/proxy.rb +244 -225
- data/lib/sproutcore/rack/restrict_ip.rb +67 -0
- data/lib/sproutcore/rack/service.rb +8 -2
- data/lib/sproutcore/tools.rb +102 -46
- data/lib/sproutcore/tools/build.rb +91 -43
- data/lib/sproutcore/tools/gen.rb +2 -3
- data/lib/sproutcore/tools/manifest.rb +22 -16
- data/lib/sproutcore/tools/server.rb +21 -0
- data/spec/buildtasks/helpers/accept_list +22 -0
- data/spec/buildtasks/helpers/accept_list.rb +128 -0
- data/spec/buildtasks/helpers/list.json +11 -0
- data/spec/buildtasks/manifest/prepare_build_tasks/chance_2x_spec.rb +1 -39
- data/spec/buildtasks/manifest/prepare_build_tasks/chance_spec.rb +0 -38
- data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +4 -4
- data/spec/buildtasks/manifest/prepare_build_tasks/module_spec.rb +2 -2
- data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_indirect_spec.rb +7 -16
- data/spec/buildtasks/manifest/prepare_build_tasks/packed_2x_spec.rb +7 -17
- data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +11 -6
- data/spec/fixtures/builder_tests/Buildfile +2 -1
- data/spec/fixtures/builder_tests/apps/module_test/modules/required_module/core.js +0 -0
- data/spec/lib/builders/module_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/sproutcore.gemspec +4 -9
- data/vendor/chance/lib/chance.rb +25 -6
- data/vendor/chance/lib/chance/factory.rb +45 -0
- data/vendor/chance/lib/chance/instance.rb +173 -28
- data/vendor/chance/lib/chance/instance/data_url.rb +0 -29
- data/vendor/chance/lib/chance/instance/slicing.rb +57 -4
- data/vendor/chance/lib/chance/instance/spriting.rb +112 -21
- data/vendor/chance/lib/chance/parser.rb +80 -52
- data/vendor/sproutcore/SCCompiler.jar +0 -0
- data/vendor/sproutcore/lib/args4j-2.0.12.jar +0 -0
- data/vendor/sproutcore/lib/yuicompressor-2.4.2.jar +0 -0
- metadata +84 -25
@@ -111,7 +111,13 @@ describe "manifest:prepare_build_tasks:packed" do
|
|
111
111
|
|
112
112
|
before do
|
113
113
|
run_task
|
114
|
-
|
114
|
+
|
115
|
+
# for 1x (but not 2x) there should be an intermediary entry for a transform
|
116
|
+
# (split_css) that... splits the CSS. See its documentation.
|
117
|
+
#
|
118
|
+
# we are looking for the stylesheet-packed.css that is set on its source entry.
|
119
|
+
@entry = entry_for('stylesheet-packed.css')[:source_entry]
|
120
|
+
|
115
121
|
@entry_2x = entry_for('stylesheet@2x-packed.css')
|
116
122
|
end
|
117
123
|
|
@@ -125,11 +131,6 @@ describe "manifest:prepare_build_tasks:packed" do
|
|
125
131
|
@entry.source_entries.each do |entry|
|
126
132
|
entry.filename.should == 'stylesheet.css'
|
127
133
|
end
|
128
|
-
|
129
|
-
@entry_2x.source_entries.size.should > 0
|
130
|
-
@entry_2x.source_entries.each do |entry|
|
131
|
-
entry.filename.should == 'stylesheet@2x.css'
|
132
|
-
end
|
133
134
|
end
|
134
135
|
|
135
136
|
it "should include ordered_entries ordered by required target order" do
|
@@ -145,17 +146,6 @@ describe "manifest:prepare_build_tasks:packed" do
|
|
145
146
|
@entry.ordered_entries.each do |entry|
|
146
147
|
entry.target.should == targets.shift
|
147
148
|
end
|
148
|
-
|
149
|
-
targets = @target.expand_required_targets(:theme => true) + [@target]
|
150
|
-
variation = @entry.manifest.variation
|
151
|
-
targets.reject! do |t|
|
152
|
-
t.manifest_for(variation).build!.entry_for('stylesheet@2x.css').nil?
|
153
|
-
end
|
154
|
-
|
155
|
-
@entry_2x.ordered_entries.each do |entry|
|
156
|
-
entry.target.should == targets.shift
|
157
|
-
end
|
158
|
-
|
159
149
|
end
|
160
150
|
|
161
151
|
it "should include the actual targets this packed version covers in the targets property (even those w no stylesheet.css)" do
|
@@ -40,8 +40,8 @@ describe "manifest:prepare_build_tasks:packed" do
|
|
40
40
|
@manifest.entry_for('javascript-packed.js').should_not be_nil
|
41
41
|
@manifest.entry_for('stylesheet-packed.css').should_not be_nil
|
42
42
|
|
43
|
-
#
|
44
|
-
@manifest.entry_for('stylesheet@2x-packed.css').
|
43
|
+
# there must always be a 2x-packed entry
|
44
|
+
@manifest.entry_for('stylesheet@2x-packed.css').should_not be_nil
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should remove non-packed JS entries from apps" do
|
@@ -132,16 +132,21 @@ describe "manifest:prepare_build_tasks:packed" do
|
|
132
132
|
|
133
133
|
run_task
|
134
134
|
|
135
|
-
|
135
|
+
# for 1x (but not 2x) there should be an intermediary entry for a transform
|
136
|
+
# (split_css) that... splits the CSS. See its documentation.
|
137
|
+
#
|
138
|
+
# we are looking for the stylesheet-packed.css that is set on its source entry.
|
139
|
+
@entry = entry_for('stylesheet-packed.css')[:source_entry]
|
140
|
+
|
136
141
|
@entry_2x = entry_for('stylesheet@2x-packed.css')
|
137
142
|
end
|
138
143
|
|
139
144
|
it "should generate a stylesheet-packed.css entry" do
|
140
145
|
@entry.should_not be_nil
|
141
146
|
|
142
|
-
# should be
|
143
|
-
#
|
144
|
-
@entry_2x.
|
147
|
+
# There should always be a 2x packed entry, because default JS
|
148
|
+
# looks for 2x when running in 2x mode, and has no fallback.
|
149
|
+
@entry_2x.should_not be_nil
|
145
150
|
end
|
146
151
|
|
147
152
|
it "should include stylesheet.css entries from all required targets" do
|
@@ -19,4 +19,5 @@ config '/module_test/deferred_module',
|
|
19
19
|
config :module_test,
|
20
20
|
:deferred_modules => [:deferred_module],
|
21
21
|
:prefetched_modules => [:required_target],
|
22
|
-
:inlined_modules => [:inlined_module]
|
22
|
+
:inlined_modules => [:inlined_module],
|
23
|
+
:required => [:required_module]
|
File without changes
|
@@ -45,7 +45,7 @@ describe 'SC::Builder::ModuleInfo' do
|
|
45
45
|
req = @target.required_targets
|
46
46
|
|
47
47
|
req.size.should == 1
|
48
|
-
req.first.target_name.should == :'/module_test/
|
48
|
+
req.first.target_name.should == :'/module_test/required_module'
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should require one deferred module" do
|
data/spec/spec_helper.rb
CHANGED
data/sproutcore.gemspec
CHANGED
@@ -3,7 +3,6 @@ require "sproutcore/version"
|
|
3
3
|
|
4
4
|
os = Gem::Platform.local.os
|
5
5
|
is_jruby = (os == "java")
|
6
|
-
is_mingw = (os == "mingw32")
|
7
6
|
|
8
7
|
Gem::Specification.new do |s|
|
9
8
|
s.name = 'sproutcore'
|
@@ -14,17 +13,17 @@ Gem::Specification.new do |s|
|
|
14
13
|
s.summary = "SproutCore is a platform for building native look-and-feel applications on the web"
|
15
14
|
|
16
15
|
s.platform = 'java' if is_jruby
|
17
|
-
s.platform = 'x86-mingw32' if is_mingw
|
18
16
|
|
19
17
|
s.add_dependency 'rack', '~> 1.2'
|
20
18
|
s.add_dependency 'json_pure', "~> 1.4.6"
|
21
19
|
s.add_dependency 'extlib', "~> 0.9.15"
|
22
20
|
s.add_dependency 'erubis', "~> 2.6"
|
23
21
|
s.add_dependency 'thor', '~> 0.14.3'
|
24
|
-
s.add_dependency '
|
25
|
-
|
26
|
-
s.add_dependency 'compass', '~> 0.11.1'
|
22
|
+
s.add_dependency 'sass', '~> 3.1.3'
|
23
|
+
s.add_dependency 'haml', '~> 3.1.2'
|
27
24
|
|
25
|
+
s.add_dependency 'compass', '~> 0.11.3'
|
26
|
+
s.add_dependency 'chunky_png', '~> 1.2.0'
|
28
27
|
s.add_dependency 'em-http-request', '~> 1.0.0.beta'
|
29
28
|
|
30
29
|
if is_jruby
|
@@ -33,10 +32,6 @@ Gem::Specification.new do |s|
|
|
33
32
|
s.add_dependency 'thin', '~> 1.2.11'
|
34
33
|
end
|
35
34
|
|
36
|
-
if is_mingw
|
37
|
-
s.add_dependency 'eventmachine', '~> 1.0.0.beta'
|
38
|
-
end
|
39
|
-
|
40
35
|
s.add_development_dependency 'gemcutter', "~> 0.6.0"
|
41
36
|
s.add_development_dependency 'rspec', "~> 2.5.0"
|
42
37
|
s.add_development_dependency 'rake'
|
data/vendor/chance/lib/chance.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "chance/instance"
|
2
|
+
require "chance/factory"
|
2
3
|
|
3
4
|
require 'sass'
|
4
5
|
|
@@ -19,8 +20,10 @@ module Chance
|
|
19
20
|
|
20
21
|
@files = {}
|
21
22
|
|
23
|
+
@clear_files_immediately = false
|
24
|
+
|
22
25
|
class << self
|
23
|
-
attr_accessor :files, :_current_instance
|
26
|
+
attr_accessor :files, :_current_instance, :clear_files_immediately
|
24
27
|
|
25
28
|
def add_file(path, content=nil)
|
26
29
|
mtime = 0
|
@@ -29,9 +32,7 @@ module Chance
|
|
29
32
|
end
|
30
33
|
|
31
34
|
if @files[path]
|
32
|
-
|
33
|
-
update_file(path, content) if mtime > @files[path][:mtime]
|
34
|
-
return
|
35
|
+
return update_file_if_needed(path, content)
|
35
36
|
end
|
36
37
|
|
37
38
|
file = {
|
@@ -67,6 +68,21 @@ module Chance
|
|
67
68
|
puts "Updated " + path if Chance::CONFIG[:verbose]
|
68
69
|
end
|
69
70
|
|
71
|
+
# if the path is a valid filesystem path and the mtime has changed, this invalidates
|
72
|
+
# the file. Returns the mtime if the file was updated.
|
73
|
+
def update_file_if_needed(path, content=nil)
|
74
|
+
if @files[path]
|
75
|
+
mtime = File.mtime(path).to_f
|
76
|
+
if mtime > @files[path][:mtime]
|
77
|
+
update_file(path, content)
|
78
|
+
end
|
79
|
+
|
80
|
+
return mtime
|
81
|
+
else
|
82
|
+
return false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
70
86
|
def remove_file(path)
|
71
87
|
if not @files.has_key? path
|
72
88
|
puts "Could not remove " + path + " because it is not in system."
|
@@ -144,10 +160,13 @@ module Chance
|
|
144
160
|
content = file[:content]
|
145
161
|
|
146
162
|
requires = []
|
147
|
-
content = content.gsub(/
|
148
|
-
requires.push $
|
163
|
+
content = content.gsub(/(sc_)?require\(['"]?(.*?)['"]?\);?/) {|match|
|
164
|
+
requires.push $2
|
149
165
|
""
|
150
166
|
}
|
167
|
+
|
168
|
+
# sc_resource will already be handled by the build tool. We just need to ignore it.
|
169
|
+
content.gsub!(/sc_resource\(['"]?(.*?)['"]?\);?/, '')
|
151
170
|
|
152
171
|
file[:requires] = requires
|
153
172
|
file[:content] = content
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# The Chance factory.
|
3
|
+
# All methods require two parts: a key and a hash of options. The hash will be used in
|
4
|
+
# the case of a cache missed.
|
5
|
+
#
|
6
|
+
module Chance
|
7
|
+
module ChanceFactory
|
8
|
+
|
9
|
+
@instances = {}
|
10
|
+
@file_hashes = {}
|
11
|
+
class << self
|
12
|
+
def clear_instances
|
13
|
+
@file_hashes = {}
|
14
|
+
@instances = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def instance_for_key(key, opts)
|
18
|
+
if not @instances.include? key
|
19
|
+
@instances[key] = Chance::Instance.new(opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
return @instances[key]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Call with a hash mapping instance paths to absolute paths. This will compare with
|
26
|
+
# the last
|
27
|
+
def update_instance(key, opts, files)
|
28
|
+
instance = instance_for_key(key, opts)
|
29
|
+
last_hash = @file_hashes[key] || {}
|
30
|
+
|
31
|
+
# If they are not equal, we might as well throw everything. The biggest cost is from
|
32
|
+
# Chance re-running, and it will have to anyway.
|
33
|
+
if not last_hash.eql? files
|
34
|
+
instance.unmap_all
|
35
|
+
files.each {|path, identifier|
|
36
|
+
instance.map_file path, identifier
|
37
|
+
}
|
38
|
+
|
39
|
+
@file_hashes[key] = files
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -10,6 +10,8 @@ require 'chance/instance/spriting'
|
|
10
10
|
require 'chance/instance/data_url'
|
11
11
|
require 'chance/instance/javascript'
|
12
12
|
|
13
|
+
require 'digest/md5'
|
14
|
+
|
13
15
|
|
14
16
|
Compass.discover_extensions!
|
15
17
|
Compass.configure_sass_plugin!
|
@@ -21,7 +23,9 @@ module Chance
|
|
21
23
|
attr_reader :path
|
22
24
|
def initialize(path)
|
23
25
|
@path = path
|
26
|
+
super(message)
|
24
27
|
end
|
28
|
+
|
25
29
|
def message
|
26
30
|
"File not mapped in Chance instance: #{path}"
|
27
31
|
end
|
@@ -48,18 +52,25 @@ module Chance
|
|
48
52
|
"chance@2x.css" => { :method => :css, :x2 => true },
|
49
53
|
"chance-sprited.css" => { :method => :css, :sprited => true },
|
50
54
|
"chance-sprited@2x.css" => { :method => :css, :sprited => true, :x2 => true },
|
51
|
-
"chance.js" => { :method => :javascript },
|
52
|
-
"chance-mhtml.txt" => { :method => :mhtml },
|
53
55
|
|
54
56
|
# For Testing Purposes...
|
55
57
|
"chance-test.css" => { :method => :chance_test }
|
56
58
|
}
|
57
59
|
|
60
|
+
@@uid = 0
|
61
|
+
|
58
62
|
@@generation = 0
|
59
63
|
|
60
64
|
def initialize(options = {})
|
61
65
|
@options = options
|
62
66
|
@options[:theme] = "" if @options[:theme].nil?
|
67
|
+
@options[:pad_sprites_for_debugging] = true if @options[:pad_sprites_for_debugging].nil?
|
68
|
+
@options[:optimize_sprites] = true if @options[:optimize_sprites].nil?
|
69
|
+
|
70
|
+
@@uid += 1
|
71
|
+
@uid = @@uid
|
72
|
+
|
73
|
+
@options[:instance_id] = @uid if @options[:instance_id].nil?
|
63
74
|
|
64
75
|
if @options[:theme].length > 0 and @options[:theme][0] != "."
|
65
76
|
@options[:theme] = "." + @options[:theme].to_s
|
@@ -68,6 +79,10 @@ module Chance
|
|
68
79
|
# The mapped files are a map from file names in the Chance Instance to
|
69
80
|
# their identifiers in Chance itself.
|
70
81
|
@mapped_files = { }
|
82
|
+
|
83
|
+
# The file mtimes are a collection of mtimes for all the files we have. Each time we
|
84
|
+
# read a file we record the mtime, and then we compare on check_all_files
|
85
|
+
@file_mtimes = { }
|
71
86
|
|
72
87
|
# The @files set is a set cached generated output files, used by the output_for
|
73
88
|
# method.
|
@@ -80,6 +95,10 @@ module Chance
|
|
80
95
|
|
81
96
|
# Tracks whether _render has been called.
|
82
97
|
@has_rendered = false
|
98
|
+
|
99
|
+
# A generation number for the current render. This allows the slicing and spriting
|
100
|
+
# to be invalidated smartly.
|
101
|
+
@render_cycle = 0
|
83
102
|
end
|
84
103
|
|
85
104
|
# maps a path relative to the instance to a file identifier
|
@@ -90,6 +109,11 @@ module Chance
|
|
90
109
|
# The identifier would be a name of a file that you added to
|
91
110
|
# Chance using add_file.
|
92
111
|
def map_file(path, identifier)
|
112
|
+
if @mapped_files[path] == identifier
|
113
|
+
# Don't do anything if there is nothing to do.
|
114
|
+
return
|
115
|
+
end
|
116
|
+
|
93
117
|
path = path.to_s
|
94
118
|
file = Chance.has_file(identifier)
|
95
119
|
|
@@ -104,12 +128,35 @@ module Chance
|
|
104
128
|
# unmaps a path from its identifier. In short, removes a file
|
105
129
|
# from this Chance instance. The file will remain in Chance's "virtual filesystem".
|
106
130
|
def unmap_file(path)
|
131
|
+
if not @mapped_files.include?(path)
|
132
|
+
# Don't do anything if there is nothing to do
|
133
|
+
return
|
134
|
+
end
|
135
|
+
|
107
136
|
path = path.to_s
|
108
137
|
@mapped_files.delete path
|
109
138
|
|
110
139
|
# Invalidate our render because things have changed.
|
111
140
|
clean
|
112
141
|
end
|
142
|
+
|
143
|
+
# unmaps all files
|
144
|
+
def unmap_all
|
145
|
+
@mapped_files = {}
|
146
|
+
end
|
147
|
+
|
148
|
+
# checks all files to see if they have changed
|
149
|
+
def check_all_files
|
150
|
+
needs_clean = false
|
151
|
+
@mapped_files.each {|p, f|
|
152
|
+
mtime = Chance.update_file_if_needed(f)
|
153
|
+
if @file_mtimes[p].nil? or mtime > @file_mtimes[p]
|
154
|
+
needs_clean = true
|
155
|
+
end
|
156
|
+
}
|
157
|
+
|
158
|
+
clean if needs_clean
|
159
|
+
end
|
113
160
|
|
114
161
|
# Using a path relative to this instance, gets an actual Chance file
|
115
162
|
# hash, with any necessary preprocessing already performed. For instance,
|
@@ -178,6 +225,9 @@ module Chance
|
|
178
225
|
def _render
|
179
226
|
return if @has_rendered
|
180
227
|
|
228
|
+
# Update the render cycle to invalidate sprites, slices, etc.
|
229
|
+
@render_cycle = @render_cycle + 1
|
230
|
+
|
181
231
|
@files = {}
|
182
232
|
begin
|
183
233
|
# SCSS code executing needs to know what the current instance of Chance is,
|
@@ -188,13 +238,25 @@ module Chance
|
|
188
238
|
# The output of this process is a "virtual" file that imports all of the
|
189
239
|
# SCSS files used by this Chance instance. This also sets up the @slices hash.
|
190
240
|
import_css = _preprocess
|
241
|
+
|
242
|
+
# Because we encapsulate with instance_id, we should not have collisions even IF another chance
|
243
|
+
# instance were running at the same time (which it couldn't; if it were, there'd be MANY other issues)
|
244
|
+
image_css_path = File.join('./tmp/chance/image_css', @options[:instance_id].to_s, '_image_css.scss')
|
245
|
+
FileUtils.mkdir_p(File.dirname(image_css_path))
|
246
|
+
|
247
|
+
file = File.new(image_css_path, "w")
|
248
|
+
file.write(_css_for_slices)
|
249
|
+
file.close
|
250
|
+
|
251
|
+
image_css_path = File.join('./tmp/chance/image_css', @options[:instance_id].to_s, 'image_css')
|
252
|
+
|
191
253
|
|
192
254
|
# STEP 2: Preparing input CSS
|
193
255
|
# The main CSS file we pass to the Sass Engine will have placeholder CSS for the
|
194
256
|
# slices (the details will be postprocessed out).
|
195
257
|
# After that, all of the individual files (using the import CSS generated
|
196
258
|
# in Step 1)
|
197
|
-
css =
|
259
|
+
css = "@import \"#{image_css_path}\";\n" + import_css
|
198
260
|
|
199
261
|
# Step 3: Apply Sass Engine
|
200
262
|
engine = Sass::Engine.new(css, Compass.sass_engine_options.merge({
|
@@ -218,17 +280,24 @@ module Chance
|
|
218
280
|
# slicing operation has not yet taken place. The postprocessing portion
|
219
281
|
# receives sliced versions.
|
220
282
|
def _css_for_slices
|
221
|
-
|
283
|
+
|
284
|
+
output = []
|
222
285
|
slices = @slices
|
223
286
|
|
224
287
|
slices.each do |name, slice|
|
225
|
-
#
|
226
|
-
output
|
227
|
-
|
228
|
-
|
288
|
+
# Write out comments specifying all the files the slice is used from
|
289
|
+
output << "/* Slice #{name}, used in: \n"
|
290
|
+
slice[:used_by].each {|used_by|
|
291
|
+
output << "\t#{used_by[:path]}\n"
|
292
|
+
}
|
293
|
+
output << "*/"
|
294
|
+
|
295
|
+
output << "." + slice[:css_name] + " { "
|
296
|
+
output << "_sc_chance: \"#{name}\";"
|
297
|
+
output << "} \n"
|
229
298
|
end
|
230
299
|
|
231
|
-
return output
|
300
|
+
return output.join ""
|
232
301
|
|
233
302
|
end
|
234
303
|
|
@@ -241,16 +310,63 @@ module Chance
|
|
241
310
|
# :sprited => whether to use spriting instead of data uris.
|
242
311
|
def _postprocess_css(opts)
|
243
312
|
if opts[:sprited]
|
244
|
-
postprocess_css_sprited(opts)
|
313
|
+
ret = postprocess_css_sprited(opts)
|
245
314
|
else
|
246
|
-
postprocess_css_dataurl(opts)
|
315
|
+
ret = postprocess_css_dataurl(opts)
|
247
316
|
end
|
317
|
+
|
318
|
+
ret = _strip_slice_class_names(ret)
|
319
|
+
end
|
320
|
+
|
321
|
+
#
|
322
|
+
# Strips dummy slice class names that were added by Chance so that SCSS could do its magic,
|
323
|
+
# but which are no longer needed.
|
324
|
+
#
|
325
|
+
def _strip_slice_class_names(css)
|
326
|
+
css.gsub! /\.__chance_slice[^{]*?,/, ""
|
327
|
+
css
|
248
328
|
end
|
249
329
|
|
250
330
|
|
251
331
|
#
|
252
332
|
# COMBINING CSS
|
253
333
|
#
|
334
|
+
|
335
|
+
# Determines the "Chance Header" to add at the beginning of the file. The
|
336
|
+
# Chance Header can set, for instance, the $theme variable.
|
337
|
+
#
|
338
|
+
# The Chance Header is loaded from the nearest _theme.css file in this folder
|
339
|
+
# or a containing folder (the file list specifically ignores such files; they are
|
340
|
+
# only used for this purpose)
|
341
|
+
#
|
342
|
+
# For backwards-compatibility, the fallback if no _theme.css file is present
|
343
|
+
# is to return code setting $theme to the now-deprecated @options[:theme]
|
344
|
+
# passed to Chance
|
345
|
+
def chance_header_for_file(file)
|
346
|
+
# 'file' is the name of a file, so we actually need to start at dirname(file)
|
347
|
+
dir = File.dirname(file)
|
348
|
+
|
349
|
+
# This should not be slow, as this is just a hash lookup
|
350
|
+
while dir.length > 0 and not dir == "."
|
351
|
+
header_file = @mapped_files[File.join(dir, "_theme.css")]
|
352
|
+
if not header_file.nil?
|
353
|
+
return Chance.get_file(header_file)
|
354
|
+
end
|
355
|
+
|
356
|
+
dir = File.dirname(dir)
|
357
|
+
end
|
358
|
+
|
359
|
+
# Make sure to look globally
|
360
|
+
header_file = @mapped_files["_theme.css"]
|
361
|
+
return Chance.get_file(header_file) if not header_file.nil?
|
362
|
+
|
363
|
+
{
|
364
|
+
# Never changes (without a restart, at least)
|
365
|
+
:mtime => 0,
|
366
|
+
:content => "$theme: '" + @options[:theme] + "';\n"
|
367
|
+
}
|
368
|
+
end
|
369
|
+
|
254
370
|
#
|
255
371
|
# _include_file is the recursive method in the depth-first-search
|
256
372
|
# that creates the ordered list of files.
|
@@ -262,6 +378,9 @@ module Chance
|
|
262
378
|
#
|
263
379
|
def _include_file(file)
|
264
380
|
return if not file =~ /\.css$/
|
381
|
+
|
382
|
+
# skip _theme.css files
|
383
|
+
return if file =~ /_theme\.css$/
|
265
384
|
|
266
385
|
file = Chance.get_file(file)
|
267
386
|
|
@@ -271,7 +390,13 @@ module Chance
|
|
271
390
|
requires = file[:requires]
|
272
391
|
file[:included] = @@generation
|
273
392
|
|
274
|
-
|
393
|
+
if not requires.nil?
|
394
|
+
requires.each {|r|
|
395
|
+
# Add the .css extension if needed. it is optional for sc_require
|
396
|
+
r = r + ".css" if not r =~ /\.css$/
|
397
|
+
_include_file(@mapped_files[r])
|
398
|
+
}
|
399
|
+
end
|
275
400
|
|
276
401
|
|
277
402
|
|
@@ -289,35 +414,55 @@ module Chance
|
|
289
414
|
@@generation = @@generation + 1
|
290
415
|
files = @mapped_files.values
|
291
416
|
@file_list = []
|
292
|
-
|
293
|
-
|
417
|
+
|
418
|
+
# We have to sort alphabetically first...
|
419
|
+
tmp_file_list = []
|
420
|
+
@mapped_files.each {|p, f| tmp_file_list.push([p, f]) }
|
421
|
+
tmp_file_list.sort_by! {|a| a[0] }
|
422
|
+
|
423
|
+
tmp_file_list.each {|paths|
|
424
|
+
p, f = paths
|
425
|
+
|
426
|
+
# Save the mtime for caching
|
427
|
+
mtime = Chance.update_file_if_needed(f)
|
428
|
+
@file_mtimes[p] = mtime
|
429
|
+
|
430
|
+
_include_file(f)
|
431
|
+
}
|
294
432
|
|
295
433
|
relative_paths = @mapped_files.invert
|
296
434
|
|
297
435
|
@file_list.map {|file|
|
298
|
-
#
|
299
|
-
#
|
300
|
-
#
|
301
|
-
|
436
|
+
# NOTE: WE MUST CALL CHANCE PARSER NOW, because it generates our slicses.
|
437
|
+
# We can't be picky and just call it if something has changed. Thankfully,
|
438
|
+
# parser is fast. Unlike SCSS.
|
439
|
+
header_file = chance_header_for_file(relative_paths[file[:path]])
|
440
|
+
|
302
441
|
content = "@_chance_file " + relative_paths[file[:path]] + ";\n"
|
303
|
-
content +=
|
442
|
+
content += header_file[:content]
|
304
443
|
content += file[:content]
|
305
444
|
|
306
445
|
parser = Chance::Parser.new(content, @options)
|
307
446
|
parser.parse
|
308
447
|
file[:parsed_css] = parser.css
|
448
|
+
|
449
|
+
# We used to use an md5 hash here, but this hides the original file name
|
450
|
+
# from SCSS, which makes the file name + line number comments useless.
|
451
|
+
#
|
452
|
+
# Instead, we sanitize the path.
|
453
|
+
path_safe = file[:path].gsub(/[^a-zA-Z0-9\-_\\\/]/, '-')
|
309
454
|
|
310
|
-
|
311
|
-
# i.e. colons in drive names on Windows
|
312
|
-
# Also removing leading slashes
|
313
|
-
cleaned_path = file[:path].gsub(/[^\w\/_-]+/,'_').sub(/^\//,'')
|
314
|
-
tmp_path = "./tmp/chance/#{cleaned_path}.scss"
|
455
|
+
tmp_path = "./tmp/chance/#{path_safe}.scss"
|
315
456
|
|
316
457
|
FileUtils.mkdir_p(File.dirname(tmp_path))
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
458
|
+
|
459
|
+
if (not file[:mtime] or not file[:wtime] or file[:wtime] < file[:mtime] or
|
460
|
+
not header_file[:mtime] or file[:wtime] < header_file[:mtime])
|
461
|
+
f = File.new(tmp_path, "w")
|
462
|
+
f.write(parser.css)
|
463
|
+
f.close
|
464
|
+
file[:wtime] = Time.now.to_f
|
465
|
+
end
|
321
466
|
|
322
467
|
css = "@import \"" + tmp_path + "\";"
|
323
468
|
|