sproutcore 0.9.20 → 0.9.21
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +12 -0
- data/Manifest.txt +3 -1
- data/bin/sc-build +41 -4
- data/config/hoe.rb +1 -1
- data/lib/sproutcore/build_tools/html_builder.rb +29 -6
- data/lib/sproutcore/build_tools/resource_builder.rb +35 -16
- data/lib/sproutcore/build_tools/test_template.rhtml +12 -0
- data/lib/sproutcore/bundle.rb +77 -28
- data/lib/sproutcore/bundle_manifest.rb +121 -47
- data/lib/sproutcore/helpers/static_helper.rb +4 -0
- data/lib/sproutcore/library.rb +23 -0
- data/lib/sproutcore/merb/bundle_controller.rb +4 -0
- data/lib/sproutcore/version.rb +1 -1
- data/lib/sproutcore/view_helpers.rb +1 -1
- data/yui_compressor/yuicompressor-2.4.2.jar +0 -0
- metadata +7 -5
data/History.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== 0.9.21
|
2
|
+
|
3
|
+
* Disabled platform name in URLs. We will be using a different approach in the next version of the build tools, so this will avoid incompatible URLs from being published. You can still technically build with platforms, but that should be avoided.
|
4
|
+
|
5
|
+
* Added support for using build numbers in URL strings instead of query string parameters. This will make caches flush more reliably.
|
6
|
+
|
7
|
+
* Added support for building multiple platforms. This is to be used with mobile platforms.
|
8
|
+
|
9
|
+
* Unit tests can now be simple .js files. These files will be inserted into an html template automatically.
|
10
|
+
|
11
|
+
== 0.9.20
|
12
|
+
|
1
13
|
== 0.9.19
|
2
14
|
|
3
15
|
* back out relative-path change which breaks dev mode [Erich Ocean]
|
data/Manifest.txt
CHANGED
@@ -339,6 +339,7 @@ jsdoc/test/variable_redefine.js
|
|
339
339
|
jsdoc/test.js
|
340
340
|
lib/sproutcore/build_tools/html_builder.rb
|
341
341
|
lib/sproutcore/build_tools/resource_builder.rb
|
342
|
+
lib/sproutcore/build_tools/test_template.rhtml
|
342
343
|
lib/sproutcore/build_tools.rb
|
343
344
|
lib/sproutcore/bundle.rb
|
344
345
|
lib/sproutcore/bundle_installer.rb
|
@@ -410,4 +411,5 @@ spec/sproutcore_spec.rb
|
|
410
411
|
tasks/deployment.rake
|
411
412
|
tasks/environment.rake
|
412
413
|
tasks/rspec.rake
|
413
|
-
tasks/website.rake
|
414
|
+
tasks/website.rake
|
415
|
+
yui_compressor/yuicompressor-2.4.2.jar
|
data/bin/sc-build
CHANGED
@@ -47,6 +47,11 @@ languages = nil
|
|
47
47
|
clean = false
|
48
48
|
docs = false
|
49
49
|
build_all = false
|
50
|
+
build_numbers = nil
|
51
|
+
platforms = nil
|
52
|
+
symlink = false
|
53
|
+
|
54
|
+
$0 = "sc-build #{ARGV * ' '}"
|
50
55
|
|
51
56
|
opts = OptionParser.new do |opts|
|
52
57
|
opts.version = SproutCore::VERSION::STRING
|
@@ -76,7 +81,22 @@ opts = OptionParser.new do |opts|
|
|
76
81
|
opts.on("-v", "--[no-]verbose", "If set, extra debug output will be displayed during the build") do |opt_verbose|
|
77
82
|
verbose = !!opt_verbose
|
78
83
|
end
|
79
|
-
|
84
|
+
|
85
|
+
opts.on("-p", "--platform=PLATFORM", "A comma separated list of the platforms you want to build. If you do not pass this option, the build tool will build all platforms found in the target bundle.") do |opt_platform|
|
86
|
+
platforms = opt_platform.split(',').map { |x| x.to_sym }
|
87
|
+
end
|
88
|
+
|
89
|
+
opts.on("-b", "--build=BUILD_NUMBERS", "build numbers. Name build number for taret or list of build numbers if needed") do |opt_build|
|
90
|
+
build_numbers = {}
|
91
|
+
opt_build = opt_build.split(',').map { |x| x.split(':') }.each do |x|
|
92
|
+
if x.size == 1
|
93
|
+
build_numbers[bundle_name.to_sym] = x[0].to_sym
|
94
|
+
elsif x.size > 1
|
95
|
+
build_numbers[x[0].to_sym] = x[1].to_sym
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
80
100
|
opts.on("-L", "--languages=LANGUAGE", "Pass a comma separated list of the specific languages you want to build. If you do not pass this option, the build tool will build all languages required by the bundles to function") do |opt_lang|
|
81
101
|
languages = opt_lang.split(',').map { |x| x.to_sym }
|
82
102
|
end
|
@@ -93,6 +113,10 @@ opts = OptionParser.new do |opts|
|
|
93
113
|
build_all = !!opt_all
|
94
114
|
end
|
95
115
|
|
116
|
+
opts.on('-a', '--[no-]symlink', "Use symlinks where possible to reduce build size. Only use this option if you are both building and deploying on machines that support symlinks") do |opt_symlink|
|
117
|
+
symlink = !!opt_symlink
|
118
|
+
end
|
119
|
+
|
96
120
|
end
|
97
121
|
opts.parse!
|
98
122
|
|
@@ -105,7 +129,7 @@ SC.logger.level = (verbose) ? Logger::DEBUG : Logger::INFO
|
|
105
129
|
SC.logger.progname = $0
|
106
130
|
|
107
131
|
# Load Library
|
108
|
-
library = SC.library_for(library_root, :public_root => build_root, :build_mode => build_mode)
|
132
|
+
library = SC.library_for(library_root, :public_root => build_root, :build_mode => build_mode, :build_numbers => build_numbers)
|
109
133
|
|
110
134
|
if library.nil?
|
111
135
|
SC.logger.fatal("No SproutCore library could be found. Make sure you are inside of your project directory (the one with an sc-config file in it).")
|
@@ -116,13 +140,14 @@ end
|
|
116
140
|
## FIND BUNDLES TO BUILD
|
117
141
|
##
|
118
142
|
|
119
|
-
|
143
|
+
target_bundle = [] # save for platform detection, does not include required...
|
120
144
|
|
121
145
|
# Find the bundles to build.
|
122
146
|
if bundle_name
|
123
147
|
# Get bundle
|
124
148
|
bundle = library.bundle_for(bundle_name.to_sym)
|
125
149
|
not_found(bundle) if bundle.nil?
|
150
|
+
target_bundles = [bundle]
|
126
151
|
|
127
152
|
# If dependencies are required, get those bundles as well
|
128
153
|
if include_dependencies
|
@@ -137,6 +162,7 @@ if bundle_name
|
|
137
162
|
else
|
138
163
|
bundles = (build_all) ? library.bundles : library.default_bundles_for_build
|
139
164
|
SC.logger.info("Building ALL bundles:\n #{bundles.map { |x| x.bundle_name } * ', '}...")
|
165
|
+
target_bundles = bundles
|
140
166
|
end
|
141
167
|
|
142
168
|
############################################################
|
@@ -151,7 +177,16 @@ languages ||= library.environment_for(nil)[:build_languages]
|
|
151
177
|
languages = nil unless languages.nil? || languages.size > 0
|
152
178
|
languages ||= bundles.map { |b| b.installed_languages }.flatten.uniq
|
153
179
|
|
180
|
+
# Detect required platforms to build
|
181
|
+
# Unless platforms are specified on the command line, we build any platforms
|
182
|
+
# specified in the build_platforms config or text languages in the target
|
183
|
+
# bundles.
|
184
|
+
platforms ||= library.environment_for(nil)[:build_platforms]
|
185
|
+
platforms = nil unless platforms.nil? || platforms.size > 0
|
186
|
+
platforms ||= target_bundles.map { |b| b.installed_platforms }.flatten.uniq
|
187
|
+
|
154
188
|
SC.logger.info("Building Languages: #{languages.join(', ')}")
|
189
|
+
SC.logger.info("Building Platforms: #{platforms.join(', ')}")
|
155
190
|
|
156
191
|
SC.logger.info('')
|
157
192
|
bundles.each do |bundle|
|
@@ -162,7 +197,9 @@ bundles.each do |bundle|
|
|
162
197
|
FileUtils.rm_rf(bundle.build_root)
|
163
198
|
end
|
164
199
|
|
165
|
-
bundle.
|
200
|
+
SC.logger.info("~ Build Number: #{bundle.build_number}")
|
201
|
+
$0 = "sc-build: building #{bundle.bundle_name}"
|
202
|
+
platforms.each { |p| bundle.build(p, *languages) }
|
166
203
|
|
167
204
|
if docs
|
168
205
|
SC.logger.debug('~ Building docs')
|
data/config/hoe.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'sproutcore/version'
|
2
2
|
|
3
3
|
AUTHOR = "Charles Jolley, Erich Ocean" # can also be an array of Authors
|
4
|
-
EMAIL = 'charles@sproutit.com
|
4
|
+
EMAIL = 'charles@sproutit.com'
|
5
5
|
DESCRIPTION = "SproutCore - JavaScript Application Framework + Build Tools"
|
6
6
|
GEM_NAME = 'sproutcore' # what ppl will type to install your gem
|
7
7
|
RUBYFORGE_PROJECT = 'sproutcore' # The unix name for your project
|
@@ -19,11 +19,12 @@ module SproutCore
|
|
19
19
|
include SproutCore::Helpers::DomIdHelper
|
20
20
|
include SproutCore::ViewHelpers
|
21
21
|
|
22
|
-
attr_reader :entry, :bundle, :entries, :filename, :language, :library, :renderer
|
22
|
+
attr_reader :entry, :bundle, :entries, :filename, :language, :library, :renderer, :unit_test, :platform
|
23
23
|
|
24
24
|
def initialize(entry, bundle, deep=true)
|
25
25
|
@entry = nil
|
26
26
|
@language = entry.language
|
27
|
+
@platform = entry.platform
|
27
28
|
@bundle = bundle
|
28
29
|
@library = bundle.library
|
29
30
|
|
@@ -94,12 +95,31 @@ module SproutCore
|
|
94
95
|
|
95
96
|
def _render(file_path)
|
96
97
|
SC.logger.debug("~ Rendering #{file_path}")
|
97
|
-
|
98
|
+
|
99
|
+
# if this is a JS file, read the JS into a unit_test variable then
|
100
|
+
# output a special unit_test.rhtml file.
|
101
|
+
if file_path =~ /\.js$/
|
102
|
+
@unit_test = File.read(file_path)
|
103
|
+
|
104
|
+
unit_test_template = File.join(File.dirname(__FILE__), 'test_template.rhtml')
|
105
|
+
input = File.read(unit_test_template)
|
106
|
+
|
107
|
+
# Otherwise, just read in the source file
|
108
|
+
else
|
109
|
+
input = File.read(file_path)
|
110
|
+
end
|
111
|
+
|
98
112
|
@renderer = case file_path
|
99
|
-
|
113
|
+
|
114
|
+
# rhtml & .html.erb get processed through Erubis.
|
115
|
+
# JS files passed in for unit tests are also erubis.
|
116
|
+
when /\.js$/, /\.rhtml$/, /\.html.erb$/
|
100
117
|
Sproutcore::Renderers::Erubis.new(self)
|
118
|
+
|
119
|
+
# haml is processed through HAML
|
101
120
|
when /\.haml$/
|
102
121
|
Sproutcore::Renderers::Haml.new(self)
|
122
|
+
|
103
123
|
end
|
104
124
|
_render_compiled_template( @renderer.compile(input) )
|
105
125
|
end
|
@@ -132,9 +152,12 @@ module SproutCore
|
|
132
152
|
|
133
153
|
end
|
134
154
|
|
135
|
-
# Building a test is
|
136
|
-
# all the other html templates
|
137
|
-
|
155
|
+
# Building a test is almost like building a single page except that we
|
156
|
+
# do not include all the other html templates. Also, if the test is a
|
157
|
+
# JS file instead, we need to generate the HTML template.
|
158
|
+
def self.build_test(entry, bundle)
|
159
|
+
build_html(entry, bundle, false)
|
160
|
+
end
|
138
161
|
|
139
162
|
end
|
140
163
|
end
|
@@ -10,20 +10,23 @@ module SproutCore
|
|
10
10
|
# The ResourceBuilder knows how
|
11
11
|
class ResourceBuilder
|
12
12
|
|
13
|
-
attr_reader :bundle, :language, :filenames
|
13
|
+
attr_reader :bundle, :language, :platform, :filenames
|
14
14
|
|
15
15
|
# Utility method you can call to get the items sorted by load order
|
16
|
-
def self.sort_entries_by_load_order(entries, language, bundle)
|
16
|
+
def self.sort_entries_by_load_order(entries, language, bundle, platform)
|
17
17
|
filenames = entries.map { |e| e.filename }
|
18
18
|
hashed = {}
|
19
19
|
entries.each { |e| hashed[e.filename] = e }
|
20
20
|
|
21
|
-
sorted = self.new(filenames, language, bundle).required
|
21
|
+
sorted = self.new(filenames, language, bundle, platform).required
|
22
22
|
sorted.map { |filename| hashed[filename] }
|
23
23
|
end
|
24
24
|
|
25
|
-
def initialize(filenames, language, bundle)
|
26
|
-
@bundle = bundle
|
25
|
+
def initialize(filenames, language, bundle, platform)
|
26
|
+
@bundle = bundle
|
27
|
+
@language = language
|
28
|
+
@platform = platform
|
29
|
+
@filenames = filenames
|
27
30
|
end
|
28
31
|
|
29
32
|
# Simply returns the filenames in the order that they were required
|
@@ -81,7 +84,7 @@ module SproutCore
|
|
81
84
|
return [lines, required] if required.include?(filename)
|
82
85
|
required << filename
|
83
86
|
|
84
|
-
entry = bundle.entry_for(filename, :hidden => :include, :language => language)
|
87
|
+
entry = bundle.entry_for(filename, :hidden => :include, :language => language, :platform => platform)
|
85
88
|
if entry.nil?
|
86
89
|
puts "WARNING: Could not find require file: #{filename}"
|
87
90
|
return [lines, required]
|
@@ -144,7 +147,6 @@ module SproutCore
|
|
144
147
|
|
145
148
|
# Final processing of file. Remove comments & minify
|
146
149
|
def join(lines)
|
147
|
-
|
148
150
|
if bundle.minify?
|
149
151
|
# first suck out any comments that should be retained
|
150
152
|
comments = []
|
@@ -152,20 +154,25 @@ module SproutCore
|
|
152
154
|
lines.each do | line |
|
153
155
|
is_mark = (line =~ /@license/)
|
154
156
|
unless include_line
|
155
|
-
|
157
|
+
if is_mark
|
158
|
+
include_line = true
|
159
|
+
line= "/*!\n"
|
160
|
+
end
|
156
161
|
is_mark = false
|
157
162
|
end
|
158
|
-
|
159
|
-
|
160
|
-
|
163
|
+
if include_line && is_mark
|
164
|
+
include_line = false
|
165
|
+
comments << "*/\n"
|
166
|
+
elsif include_line
|
167
|
+
comments << line
|
168
|
+
end
|
161
169
|
end
|
162
|
-
|
163
170
|
# now minify and prepend any static
|
164
171
|
comments.push "\n" unless comments.empty?
|
165
|
-
comments.push
|
172
|
+
comments.push (lines * '')
|
166
173
|
lines = comments
|
167
174
|
end
|
168
|
-
|
175
|
+
|
169
176
|
lines.join
|
170
177
|
end
|
171
178
|
|
@@ -197,7 +204,7 @@ module SproutCore
|
|
197
204
|
|
198
205
|
def self.build_stylesheet(entry, bundle)
|
199
206
|
filenames = entry.composite? ? entry.composite_filenames : [entry.filename]
|
200
|
-
builder = ResourceBuilder.new(filenames, entry.language, bundle)
|
207
|
+
builder = ResourceBuilder.new(filenames, entry.language, bundle, entry.platform)
|
201
208
|
if output = builder.build
|
202
209
|
FileUtils.mkdir_p(File.dirname(entry.build_path))
|
203
210
|
f = File.open(entry.build_path, 'w')
|
@@ -208,12 +215,24 @@ module SproutCore
|
|
208
215
|
|
209
216
|
def self.build_javascript(entry, bundle)
|
210
217
|
filenames = entry.composite? ? entry.composite_filenames : [entry.filename]
|
211
|
-
builder = JavaScriptResourceBuilder.new(filenames, entry.language, bundle)
|
218
|
+
builder = JavaScriptResourceBuilder.new(filenames, entry.language, bundle, entry.platform)
|
212
219
|
if output = builder.build
|
213
220
|
FileUtils.mkdir_p(File.dirname(entry.build_path))
|
214
221
|
f = File.open(entry.build_path, 'w')
|
215
222
|
f.write(output)
|
216
223
|
f.close
|
224
|
+
if bundle.minify?
|
225
|
+
yui_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'yui_compressor'))
|
226
|
+
jar_path = File.join(yui_root, 'yuicompressor-2.4.2.jar')
|
227
|
+
filecompress = "java -jar " + jar_path + " --charset utf-8 " + entry.build_path + " -o " +entry.build_path
|
228
|
+
puts 'Compressing with YUI .... '+ entry.build_path
|
229
|
+
puts `#{filecompress}`
|
230
|
+
if $?.exitstatus != 0
|
231
|
+
SC.logger.fatal("!!!!YUI compressor failed, please check that your js code is valid and doesn't contain reserved statements like debugger;")
|
232
|
+
SC.logger.fatal("!!!!Failed compressing ... "+ entry.build_path)
|
233
|
+
exit(1)
|
234
|
+
end
|
235
|
+
end
|
217
236
|
end
|
218
237
|
end
|
219
238
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% # ========================================================================
|
2
|
+
# Generic Unit Test Template
|
3
|
+
# This template is used when you include a .js file in your unit tests.
|
4
|
+
# ========================================================================
|
5
|
+
%>
|
6
|
+
<% content_for('final') do %>
|
7
|
+
|
8
|
+
<script>
|
9
|
+
<%= unit_test %>
|
10
|
+
</script>
|
11
|
+
|
12
|
+
<% end %>
|
data/lib/sproutcore/bundle.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'sproutcore/build_tools'
|
2
|
+
require 'digest/md5'
|
2
3
|
|
3
4
|
module SproutCore
|
4
5
|
|
@@ -74,6 +75,10 @@ module SproutCore
|
|
74
75
|
# MD5 digests instead of timestamps. This will ensure uniqueness when
|
75
76
|
# building on multiple machines.
|
76
77
|
#
|
78
|
+
# build_number:: The build number. Defaults to timestamp
|
79
|
+
#
|
80
|
+
# prefered_platform:: preferred default platform. Default :desktop
|
81
|
+
#
|
77
82
|
class Bundle
|
78
83
|
|
79
84
|
LONG_LANGUAGE_MAP = { :english => :en, :french => :fr, :german => :de, :japanese => :ja, :spanish => :es, :italian => :it }
|
@@ -94,6 +99,8 @@ module SproutCore
|
|
94
99
|
attr_reader :build_mode, :layout
|
95
100
|
attr_reader :make_resources_relative
|
96
101
|
attr_reader :use_digest_tokens
|
102
|
+
|
103
|
+
attr_reader :preferred_platform
|
97
104
|
|
98
105
|
def library_root
|
99
106
|
@library_root ||= library.nil? ? nil : library.root_path
|
@@ -131,6 +138,16 @@ module SproutCore
|
|
131
138
|
@autobuild.nil? ? true : @autobuild
|
132
139
|
end
|
133
140
|
|
141
|
+
# ==== Returns
|
142
|
+
# The build number for the bundle. If you supply a build number, that
|
143
|
+
# will be used. If not, then the build number will always be
|
144
|
+
# 'development' in development mode and a number computed by MD5 hash
|
145
|
+
# of the entire bundle contents in production mode.
|
146
|
+
def build_number
|
147
|
+
return 'development' if build_mode == :development
|
148
|
+
return @build_number ||= SC.library.compute_build_number(self)
|
149
|
+
end
|
150
|
+
|
134
151
|
# ==== Returns
|
135
152
|
# The computed path to the layout rhtml.
|
136
153
|
def layout_path
|
@@ -236,6 +253,9 @@ module SproutCore
|
|
236
253
|
|
237
254
|
@use_digest_tokens = opts[:use_digest_tokens] || (@build_mode == :production)
|
238
255
|
|
256
|
+
@preferred_platform = opts[:preferred_platform] || :desktop
|
257
|
+
@build_number = opts[:build_number]
|
258
|
+
|
239
259
|
reload!
|
240
260
|
end
|
241
261
|
|
@@ -247,16 +267,18 @@ module SproutCore
|
|
247
267
|
# The array of stylesheet entries sorted in load order.
|
248
268
|
def sorted_stylesheet_entries(opts = {})
|
249
269
|
opts[:language] ||= preferred_language
|
270
|
+
opts[:platform] ||= preferred_platform
|
250
271
|
entries = entries_for(:stylesheet, opts)
|
251
|
-
BuildTools::ResourceBuilder.sort_entries_by_load_order(entries, opts[:language], self)
|
272
|
+
BuildTools::ResourceBuilder.sort_entries_by_load_order(entries, opts[:language], self, opts[:platform])
|
252
273
|
end
|
253
274
|
|
254
275
|
# ==== Returns
|
255
276
|
# The array of javascript entries sorted in load order.
|
256
277
|
def sorted_javascript_entries(opts = {})
|
257
278
|
opts[:language] ||= preferred_language
|
279
|
+
opts[:platform] ||= preferred_platform
|
258
280
|
entries = entries_for(:javascript, opts)
|
259
|
-
BuildTools::JavaScriptResourceBuilder.sort_entries_by_load_order(entries, opts[:language], self)
|
281
|
+
BuildTools::JavaScriptResourceBuilder.sort_entries_by_load_order(entries, opts[:language], self, opts[:platform])
|
260
282
|
end
|
261
283
|
|
262
284
|
# This method returns the manifest entries for resources of the specified
|
@@ -268,14 +290,16 @@ module SproutCore
|
|
268
290
|
#
|
269
291
|
# ==== Options
|
270
292
|
# language:: The language to use. Defaults to preferred language.
|
293
|
+
# platform:: The platform to use. Defaults to preferred platform.
|
271
294
|
# hidden:: Can be :none|:include|:only
|
272
295
|
#
|
273
296
|
def entries_for(resource_type, opts={})
|
274
297
|
with_hidden = opts[:hidden] || :none
|
275
298
|
|
276
299
|
language = opts[:language] || preferred_language
|
300
|
+
platform = opts[:platform] || preferred_platform
|
277
301
|
mode = (opts[:build_mode] || build_mode).to_sym
|
278
|
-
manifest = manifest_for(language, mode)
|
302
|
+
manifest = manifest_for(language, mode, platform)
|
279
303
|
|
280
304
|
ret = manifest.entries_for(resource_type)
|
281
305
|
|
@@ -295,14 +319,16 @@ module SproutCore
|
|
295
319
|
#
|
296
320
|
# ==== Options
|
297
321
|
# language:: The language to use. Defaults to preferred language
|
322
|
+
# platform:: The platform to use. Defaults to preferred platform.
|
298
323
|
# hidden:: Can be :none|:include|:only
|
299
324
|
#
|
300
325
|
def entry_for(resource_name, opts={})
|
301
326
|
with_hidden = opts[:hidden] || :none
|
302
327
|
|
303
328
|
language = opts[:language] || preferred_language
|
329
|
+
platform = opts[:platform] || preferred_platform
|
304
330
|
mode = (opts[:build_mode] || build_mode).to_sym
|
305
|
-
manifest = manifest_for(language, mode)
|
331
|
+
manifest = manifest_for(language, mode, platform)
|
306
332
|
|
307
333
|
ret = manifest.entry_for(resource_name)
|
308
334
|
|
@@ -316,9 +342,9 @@ module SproutCore
|
|
316
342
|
end
|
317
343
|
|
318
344
|
# Returns the entry for the specified URL. This will extract the language
|
319
|
-
# from the URL and try to get the entry from both the
|
320
|
-
# current build mode and in the production build mode (if
|
321
|
-
# provided)
|
345
|
+
# and platform from the URL and try to get the entry from both the
|
346
|
+
# manifest in the current build mode and in the production build mode (if
|
347
|
+
# one is provided)
|
322
348
|
#
|
323
349
|
# ==== Params
|
324
350
|
# url<String>:: The url
|
@@ -327,15 +353,21 @@ module SproutCore
|
|
327
353
|
# hidden:: Use :include,:none,:only to control hidden options
|
328
354
|
# language:: Explicitly include the language. Leave this out to
|
329
355
|
# autodetect from URL.
|
356
|
+
# platform:: Explicitly include the platform. Leave this out to
|
357
|
+
# autodetect from URL.
|
330
358
|
#
|
331
359
|
def entry_for_url(url, opts={})
|
360
|
+
|
332
361
|
# get the language
|
333
362
|
opts[:language] ||= url.match(/^#{url_root}\/([^\/]+)\//).to_a[1] || url.match(/^#{index_root}\/([^\/]+)\//).to_a[1] || preferred_language
|
334
363
|
|
364
|
+
opts[:platform] ||= url.match(/^#{url_root}\/([^\/]+)\/([^\/]+)\//).to_a[2] || url.match(/^#{index_root}\/([^\/]+)\/([^\/]+)\//).to_a[2] || preferred_platform
|
365
|
+
|
335
366
|
# use the current build mode
|
336
367
|
opts[:build_mode] = build_mode
|
337
368
|
entries(opts).each do |entry|
|
338
369
|
return entry if entry.url == url
|
370
|
+
return entry if entry.current_url == url
|
339
371
|
end
|
340
372
|
|
341
373
|
# try production is necessary...
|
@@ -343,6 +375,7 @@ module SproutCore
|
|
343
375
|
opts[:build_mode] = :production
|
344
376
|
entries(opts).each do |entry|
|
345
377
|
return entry if entry.url == url
|
378
|
+
return entry if entry.current_url == url
|
346
379
|
end
|
347
380
|
end
|
348
381
|
|
@@ -351,20 +384,24 @@ module SproutCore
|
|
351
384
|
|
352
385
|
# Helper method. This will normalize a URL into one that can map directly
|
353
386
|
# to an entry in the bundle. If the URL is of a format that cannot be
|
354
|
-
# converted, returns
|
387
|
+
# converted, returns the url. In particular, this will look for all the
|
388
|
+
# different ways you can request an index.html file and convert it to a
|
389
|
+
# canonical form
|
355
390
|
#
|
356
391
|
# ==== Params
|
357
392
|
# url<String>:: The URL
|
358
393
|
#
|
359
394
|
def normalize_url(url)
|
360
395
|
|
361
|
-
#
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
url
|
396
|
+
# Parse the URL
|
397
|
+
matched = url.match(/^#{index_root}(\/([^\/\.]+))?(\/([^\/\.]+))?(\/|(\/index\.html))?$/)
|
398
|
+
unless matched.nil?
|
399
|
+
matched_language = matched[2] || preferred_language
|
400
|
+
matched_platform = matched[4] || preferred_platform
|
401
|
+
matched_build_number = matched[6] || 'current'
|
402
|
+
url = [index_root,
|
403
|
+
matched_language, matched_build_number,
|
404
|
+
'index.html'] * '/'
|
368
405
|
end
|
369
406
|
|
370
407
|
return url
|
@@ -374,14 +411,16 @@ module SproutCore
|
|
374
411
|
#
|
375
412
|
# ==== Options
|
376
413
|
# language:: The language to use. Defaults to preferred language
|
414
|
+
# platform:: The platform to use. Defaults to preferred platform
|
377
415
|
# hidden:: Can be :none|:include|:only
|
378
416
|
#
|
379
417
|
def entries(opts ={})
|
380
418
|
with_hidden = opts[:hidden] || :none
|
381
419
|
|
382
420
|
language = opts[:language] || preferred_language
|
421
|
+
platform = opts[:platform] || preferred_platform
|
383
422
|
mode = (opts[:build_mode] || build_mode).to_sym
|
384
|
-
manifest = manifest_for(language, mode)
|
423
|
+
manifest = manifest_for(language, mode, platform)
|
385
424
|
|
386
425
|
ret = manifest.entries
|
387
426
|
|
@@ -500,17 +539,17 @@ module SproutCore
|
|
500
539
|
@seen << entry unless @seen.nil?
|
501
540
|
end
|
502
541
|
|
503
|
-
# This will perform a
|
504
|
-
def build_language(language)
|
505
|
-
SC.logger.info("~ Language: #{language}")
|
506
|
-
build_entries(entries(:language => language))
|
542
|
+
# This will perform a build for a single language
|
543
|
+
def build_language(language, platform=nil)
|
544
|
+
SC.logger.info("~ Language/Platform: #{[language,platform].compact.join('/') }")
|
545
|
+
build_entries(entries(:language => language, :platform => platform))
|
507
546
|
SC.logger.debug("~ Done.\n")
|
508
547
|
end
|
509
548
|
|
510
549
|
# This will perform a complete build for all languages that have a
|
511
550
|
# matching lproj. You can also pass in an array of languages you would
|
512
551
|
# like to build
|
513
|
-
def build(*languages)
|
552
|
+
def build(platform, *languages)
|
514
553
|
|
515
554
|
# Get the installed languages (and the preferred language, just in case)
|
516
555
|
languages = languages.flatten
|
@@ -521,7 +560,7 @@ module SproutCore
|
|
521
560
|
SC.logger.debug("~ Source Root: #{source_root}")
|
522
561
|
SC.logger.debug("~ Build Root: #{build_root}")
|
523
562
|
|
524
|
-
languages.uniq.each { |lang| build_language(lang) }
|
563
|
+
languages.uniq.each { |lang| build_language(lang, platform) }
|
525
564
|
|
526
565
|
# After build is complete, try to copy the index.html file of the
|
527
566
|
# preferred language to the build_root
|
@@ -679,18 +718,28 @@ module SproutCore
|
|
679
718
|
|
680
719
|
# Returns the bundle manifest for the specified language and build mode.
|
681
720
|
# The manifest will be created if it does not yet exist.
|
682
|
-
def manifest_for(language, build_mode)
|
683
|
-
manifest_key = [build_mode.to_s, language.to_s].join(':').to_sym
|
684
|
-
@manifests[manifest_key] ||= BundleManifest.new(self, language.to_sym, build_mode.to_sym)
|
721
|
+
def manifest_for(language, build_mode, platform)
|
722
|
+
manifest_key = [build_mode.to_s, language.to_s, platform.to_s].join(':').to_sym
|
723
|
+
@manifests[manifest_key] ||= BundleManifest.new(self, language.to_sym, build_mode.to_sym, platform.to_sym)
|
685
724
|
end
|
686
725
|
|
726
|
+
# ==== Returns
|
727
|
+
# Platforms installed in the source directory
|
728
|
+
#
|
729
|
+
def installed_platforms
|
730
|
+
ret = Dir.glob(File.join(source_root, '*.platform')).map do |x|
|
731
|
+
x.match(/([^\/]+)\.platform$/).to_a[1]
|
732
|
+
end
|
733
|
+
ret << preferred_platform
|
734
|
+
ret.compact.map { |x| x.to_sym }.uniq
|
735
|
+
end
|
736
|
+
|
687
737
|
# ==== Returns
|
688
738
|
# Languages installed in the source directory
|
689
739
|
#
|
690
740
|
def installed_languages
|
691
|
-
ret = Dir.glob(File.join(source_root,'*.lproj')).
|
692
|
-
|
693
|
-
end
|
741
|
+
ret = Dir.glob(File.join(source_root,'*.lproj')) + Dir.glob(File.join(source_root, '*.platform', '*.lproj'))
|
742
|
+
ret.map! { |x| x.match(/([^\/]+)\.lproj$/).to_a[1] }
|
694
743
|
ret << preferred_language
|
695
744
|
ret.compact.map { |x| LONG_LANGUAGE_MAP[x.to_sym] || x.to_sym }.uniq
|
696
745
|
end
|
@@ -6,21 +6,30 @@ module SproutCore
|
|
6
6
|
# A Bundle Manifest describes all of the resources in a bundle, including
|
7
7
|
# mapping their source paths, destination paths, and urls.
|
8
8
|
#
|
9
|
-
# A Bundle will create a manifest for every language
|
10
|
-
# If you invoke reload! on the bundle, it will dispose of
|
11
|
-
# rebuild them.
|
9
|
+
# A Bundle will create a manifest for every language and platform you
|
10
|
+
# request from it. If you invoke reload! on the bundle, it will dispose of
|
11
|
+
# its manifests and rebuild them.
|
12
12
|
#
|
13
13
|
class BundleManifest
|
14
14
|
|
15
|
-
CACHED_TYPES
|
15
|
+
CACHED_TYPES = [:javascript, :stylesheet, :fixture, :test]
|
16
16
|
SYMLINKED_TYPES = [:resource]
|
17
|
+
|
18
|
+
PLATFORM_MATCH = /^([^\/]+)\.platform\//
|
19
|
+
LPROJ_MATCH = /^([^\/]+\.platform\/)?([^\/]+\.lproj)\//
|
20
|
+
|
21
|
+
NORMALIZED_TYPE_EXTENSIONS = {
|
22
|
+
:stylesheet => { :sass => :css },
|
23
|
+
:test => { '[^\/\.]+' => :html }
|
24
|
+
}
|
17
25
|
|
18
|
-
attr_reader :bundle, :language, :build_mode
|
26
|
+
attr_reader :bundle, :language, :build_mode, :platform
|
19
27
|
|
20
|
-
def initialize(bundle, language, build_mode)
|
28
|
+
def initialize(bundle, language, build_mode, platform)
|
21
29
|
@bundle = bundle
|
22
30
|
@language = language
|
23
31
|
@build_mode = build_mode
|
32
|
+
@platform = platform
|
24
33
|
@entries_by_type = {} # entries by type
|
25
34
|
@entries_by_filename = {} # entries by files
|
26
35
|
build!
|
@@ -168,7 +177,8 @@ module SproutCore
|
|
168
177
|
end
|
169
178
|
|
170
179
|
# Build a catalog of entries for this manifest. This will simply filter
|
171
|
-
# out the files that don't actually belong in the current language
|
180
|
+
# out the files that don't actually belong in the current language or
|
181
|
+
# platform
|
172
182
|
def catalog_entries
|
173
183
|
|
174
184
|
# Entries arranged by resource filename
|
@@ -180,8 +190,9 @@ module SproutCore
|
|
180
190
|
default_lproj = bundle.lproj_for(bundle.preferred_language)
|
181
191
|
target_lproj = bundle.lproj_for(language)
|
182
192
|
|
183
|
-
# Any files living in the two lproj dirs will be shunted off into these
|
184
|
-
# and processed later to make sure we process them in the right
|
193
|
+
# Any files living in the two lproj dirs will be shunted off into these
|
194
|
+
# arrays and processed later to make sure we process them in the right
|
195
|
+
# order
|
185
196
|
default_lproj_files = []
|
186
197
|
target_lproj_files = []
|
187
198
|
|
@@ -192,33 +203,46 @@ module SproutCore
|
|
192
203
|
# Get source type. Skip any without a useful type
|
193
204
|
next if (src_type = type_of(src_path)) == :skip
|
194
205
|
|
206
|
+
# Get target platform (if there is one). Skip is not target platform
|
207
|
+
if current_platform = src_path.match(PLATFORM_MATCH).to_a[1]
|
208
|
+
next if current_platform.to_sym != platform
|
209
|
+
end
|
210
|
+
|
195
211
|
# Get current lproj (if there is one). Skip if not default or current
|
196
|
-
if current_lproj = src_path.match(
|
212
|
+
if current_lproj = src_path.match(LPROJ_MATCH).to_a[2]
|
197
213
|
next if (current_lproj != default_lproj) && (current_lproj != target_lproj)
|
198
214
|
end
|
199
215
|
|
200
|
-
# OK, pass all of our validations. Go ahead and build an entry for
|
201
|
-
# Add entry to list of entries for appropriate lproj if
|
216
|
+
# OK, pass all of our validations. Go ahead and build an entry for
|
217
|
+
# this. Add entry to list of entries for appropriate lproj if
|
218
|
+
# localized.
|
219
|
+
#
|
220
|
+
# Note that entries are namespaced by platform. This way non-platform
|
221
|
+
# specific entries will not be overwritten by platfor-specific entries
|
222
|
+
# of the same name.
|
223
|
+
#
|
202
224
|
entry = build_entry_for(src_path, src_type)
|
225
|
+
entry_key = [current_platform||'', entry.filename].join(':')
|
203
226
|
case current_lproj
|
204
227
|
when default_lproj
|
205
|
-
default_lproj_entries[
|
228
|
+
default_lproj_entries[entry_key] = entry
|
206
229
|
when target_lproj
|
207
|
-
target_lproj_entries[
|
230
|
+
target_lproj_entries[entry_key] = entry
|
208
231
|
else
|
209
232
|
|
210
233
|
# Be sure to mark any
|
211
|
-
entries[
|
234
|
+
entries[entry_key] = entry
|
212
235
|
end
|
213
236
|
end
|
214
237
|
Dir.chdir(old_wd) # restore wd
|
215
238
|
|
216
|
-
# Now,
|
217
|
-
# in both places.
|
239
|
+
# Now, merge in default and target lproj entries. This will overwrite
|
240
|
+
# entries that exist in both places.
|
218
241
|
entries.merge!(default_lproj_entries)
|
219
242
|
entries.merge!(target_lproj_entries)
|
220
243
|
|
221
|
-
# Finally, entries will need to be grouped by type to allow further
|
244
|
+
# Finally, entries will need to be grouped by type to allow further
|
245
|
+
# processing.
|
222
246
|
ret = {}
|
223
247
|
entries.values.each { |entry| (ret[entry.type] ||= []) << entry }
|
224
248
|
return ret
|
@@ -246,11 +270,11 @@ module SproutCore
|
|
246
270
|
def type_of(src_path)
|
247
271
|
return :skip if File.directory?(src_path)
|
248
272
|
case src_path
|
249
|
-
when /^tests\/.+/
|
273
|
+
when /^([^\/\.]+\.platform\/)?tests\/.+/
|
250
274
|
:test
|
251
|
-
when /^fixtures\/.+\.js$/
|
275
|
+
when /^([^\/\.]+\.platform\/)?fixtures\/.+\.js$/
|
252
276
|
:fixture
|
253
|
-
when /^debug\/.+\.js$/
|
277
|
+
when /^([^\/\.]+\.platform\/)?debug\/.+\.js$/
|
254
278
|
:debug
|
255
279
|
when /\.rhtml$/
|
256
280
|
:html
|
@@ -275,6 +299,16 @@ module SproutCore
|
|
275
299
|
# source_root) This should assume we are in going to simply build each
|
276
300
|
# resource into the build root without combining files, but not using our
|
277
301
|
# _src symlink magic.
|
302
|
+
#
|
303
|
+
# +Params+
|
304
|
+
#
|
305
|
+
# src_path:: the source path, relative to the bunlde.source_root
|
306
|
+
# src_type:: the detected source type (from type_of())
|
307
|
+
# composite:: Array of entries that should be combined to form this or nil
|
308
|
+
# hide_composite:: Makes composit entries hidden if !composite.nil?
|
309
|
+
#
|
310
|
+
# +Returns: Entry
|
311
|
+
#
|
278
312
|
def build_entry_for(src_path, src_type, composite=nil, hide_composite = true)
|
279
313
|
ret = ManifestEntry.new
|
280
314
|
ret.ext = File.extname(src_path)[1..-1] || '' # easy stuff
|
@@ -282,17 +316,20 @@ module SproutCore
|
|
282
316
|
ret.original_path = src_path
|
283
317
|
ret.hidden = false
|
284
318
|
ret.language = language
|
319
|
+
ret.platform = platform
|
285
320
|
ret.use_digest_tokens = bundle.use_digest_tokens
|
286
321
|
|
287
|
-
# the filename is the src_path less any lproj in the front
|
288
|
-
ret.filename = src_path.gsub(
|
322
|
+
# the filename is the src_path less any lproj or platform in the front
|
323
|
+
ret.filename = src_path.gsub(LPROJ_MATCH,'')
|
289
324
|
|
290
325
|
# the source path is just the combine source root + the path
|
291
|
-
|
326
|
+
# Composite entries do not have a source path b/c they are generated
|
327
|
+
# dynamically.
|
328
|
+
ret.source_path = composite.nil? ? File.join(bundle.source_root, src_path) : nil
|
292
329
|
|
293
330
|
# set the composite property. The passed in array should contain other
|
294
331
|
# entries if hide_composite is true, then hide the composite items as
|
295
|
-
# well
|
332
|
+
# well.
|
296
333
|
unless composite.nil?
|
297
334
|
composite.each { |x| x.hidden = true } if hide_composite
|
298
335
|
|
@@ -303,45 +340,77 @@ module SproutCore
|
|
303
340
|
ret.composite = composite.dup
|
304
341
|
end
|
305
342
|
|
306
|
-
#
|
307
|
-
|
308
|
-
#
|
309
|
-
#
|
343
|
+
# PREPARE BUILD_PATH and URL
|
344
|
+
|
345
|
+
# The main index.html file is served from the index_Root. All other
|
346
|
+
# resourced are served from the URL root.
|
310
347
|
url_root = (src_path == 'index.html') ? bundle.index_root : bundle.url_root
|
311
|
-
cache_link = nil
|
312
|
-
use_source_directly =false
|
313
348
|
|
314
|
-
#
|
315
|
-
#
|
349
|
+
# Setup special cases. Certain types of files are processed and then
|
350
|
+
# cached in development mode (i.e. JS + CSS). Other resources are
|
351
|
+
# simply served up directly without any processing or building. See
|
352
|
+
# constants for types.
|
353
|
+
cache_link = nil; use_source_directly =false
|
316
354
|
if (self.build_mode == :development) #&& composite.nil?
|
317
355
|
cache_link = '_cache' if CACHED_TYPES.include?(src_type)
|
318
356
|
use_source_directly = true if SYMLINKED_TYPES.include?(src_type)
|
319
357
|
end
|
320
358
|
|
359
|
+
# If this resource should be served directly, setup both the build_path
|
360
|
+
# and URL to point to a special URL that maps directly to the resource.
|
361
|
+
# This is only useful in development mode
|
321
362
|
ret.use_source_directly = use_source_directly
|
322
363
|
if use_source_directly
|
323
|
-
|
324
|
-
ret.
|
364
|
+
path_parts = [bundle.build_root, language.to_s, '_src', src_path]
|
365
|
+
ret.build_path = File.join(*(path_parts.compact))
|
366
|
+
path_parts[0] = url_root
|
367
|
+
ret.url = path_parts.compact.join('/')
|
368
|
+
|
369
|
+
# If the resource is not served directly, then calculate the actual
|
370
|
+
# build path and URL for production mode. The build path is the
|
371
|
+
# build root + language + platform + (cache_link || build_number) +
|
372
|
+
# filename
|
373
|
+
#
|
374
|
+
# The URL is the url_root + current_language + current_platform + (cache_link)
|
325
375
|
else
|
326
|
-
|
327
|
-
|
376
|
+
path_parts = [bundle.build_root, language.to_s,
|
377
|
+
(cache_link || bundle.build_number.to_s), ret.filename]
|
378
|
+
ret.build_path = File.join(*path_parts.compact)
|
379
|
+
|
380
|
+
path_parts[0] = url_root
|
381
|
+
ret.url = path_parts.compact.join('/')
|
382
|
+
|
383
|
+
path_parts[2] = 'current' # create path to "current" build
|
384
|
+
ret.current_url = path_parts.compact.join('/')
|
385
|
+
|
386
|
+
end
|
387
|
+
|
388
|
+
# Convert the input source type an output type.
|
389
|
+
if sub_type = NORMALIZED_TYPE_EXTENSIONS[ret.type]
|
390
|
+
sub_type.each do | matcher, ext |
|
391
|
+
matcher = /\.#{matcher.to_s}$/; ext = ".#{ext.to_s}"
|
392
|
+
ret.build_path.sub!(matcher, ext)
|
393
|
+
ret.url.sub!(matcher, ext)
|
394
|
+
end
|
328
395
|
end
|
329
|
-
ret.build_path.sub!(/\.sass$/, '.css')
|
330
|
-
ret.url.sub!(/.sass$/, '.css')
|
331
396
|
|
332
397
|
# Done.
|
333
398
|
return ret
|
334
399
|
end
|
335
400
|
|
336
|
-
# Lookup the timestamp on the source path and interpolate that into the
|
337
|
-
#
|
401
|
+
# Lookup the timestamp on the source path and interpolate that into the
|
402
|
+
# filename URL and build path. This should only be called on entries
|
403
|
+
# that are to be cached (in development mode)
|
338
404
|
def setup_timestamp_token(entry)
|
339
405
|
timestamp = bundle.use_digest_tokens ? entry.digest : entry.timestamp
|
406
|
+
|
407
|
+
# add timestamp or digest to URL
|
340
408
|
extname = File.extname(entry.url)
|
341
|
-
entry.url
|
409
|
+
entry.url.gsub!(/#{extname}$/,"-#{timestamp}#{extname}")
|
342
410
|
|
411
|
+
# add timestamp or digest to build path
|
343
412
|
extname = File.extname(entry.build_path)
|
344
|
-
entry.build_path
|
413
|
+
entry.build_path.gsub!(/#{extname}$/,"-#{timestamp}#{extname}")
|
345
414
|
end
|
346
415
|
end
|
347
416
|
|
@@ -350,7 +419,8 @@ module SproutCore
|
|
350
419
|
# filename:: path relative to the built language (e.g. sproutcore/en) less file extension
|
351
420
|
# ext:: the file extension
|
352
421
|
# source_path:: absolute paths into source that will comprise this resource
|
353
|
-
# url:: the url that should be used to reference this resource in the current mode.
|
422
|
+
# url:: the url that should be used to reference this resource in the current build mode.
|
423
|
+
# current_url:: the url that can be used to reference this resource, substituting "current" for a build number
|
354
424
|
# build_path:: absolute path to the compiled resource
|
355
425
|
# type:: the top-level category
|
356
426
|
# original_path:: save the original path used to build this entry
|
@@ -359,8 +429,9 @@ module SproutCore
|
|
359
429
|
# language:: the language in use when this entry was created
|
360
430
|
# composite:: If set, this will contain the filenames of other resources that should be combined to form this resource.
|
361
431
|
# bundle:: the owner bundle for this entry
|
432
|
+
# platform:: the target platform for the entry, if any
|
362
433
|
#
|
363
|
-
class ManifestEntry < Struct.new(:filename, :ext, :source_path, :url, :build_path, :type, :original_path, :hidden, :use_source_directly, :language, :use_digest_tokens)
|
434
|
+
class ManifestEntry < Struct.new(:filename, :ext, :source_path, :url, :build_path, :type, :original_path, :hidden, :use_source_directly, :language, :use_digest_tokens, :platform, :current_url)
|
364
435
|
def to_hash
|
365
436
|
ret = {}
|
366
437
|
self.members.zip(self.values).each { |p| ret[p[0]] = p[1] }
|
@@ -431,8 +502,9 @@ module SproutCore
|
|
431
502
|
|
432
503
|
# Returns a URL that takes into account caching requirements.
|
433
504
|
def cacheable_url
|
434
|
-
|
435
|
-
|
505
|
+
url
|
506
|
+
#token = (use_digest_tokens) ? digest : timestamp
|
507
|
+
#[url, token].compact.join('?')
|
436
508
|
end
|
437
509
|
|
438
510
|
# :stopdoc:
|
@@ -492,6 +564,8 @@ module SproutCore
|
|
492
564
|
"xpm" => "image/x-xpixmap",
|
493
565
|
"xwd" => "image/x-xwindowdump",
|
494
566
|
"zip" => "application/zip",
|
567
|
+
"js" => "text/javascript",
|
568
|
+
"json" => "text/json"
|
495
569
|
}
|
496
570
|
# :startdoc:
|
497
571
|
|
@@ -18,6 +18,7 @@ module SproutCore
|
|
18
18
|
def stylesheets_for_client(bundle_name = nil, opts = {})
|
19
19
|
|
20
20
|
opts[:language] ||= language
|
21
|
+
opts[:platform] ||= platform
|
21
22
|
|
22
23
|
# Set the import method to use the standard <link> tag, if not set
|
23
24
|
include_method = opts[:include_method] ||= :link
|
@@ -64,6 +65,7 @@ module SproutCore
|
|
64
65
|
def javascripts_for_client(bundle_name = nil, opts = {})
|
65
66
|
|
66
67
|
opts[:language] ||= language
|
68
|
+
opts[:platform] ||= platform
|
67
69
|
|
68
70
|
# Get bundle
|
69
71
|
cur_bundle = bundle_name.nil? ? bundle : library.bundle_for(bundle_name)
|
@@ -94,6 +96,7 @@ module SproutCore
|
|
94
96
|
# Returns the URL for the named resource
|
95
97
|
def static_url(resource_name, opts = {})
|
96
98
|
opts[:language] ||= language
|
99
|
+
opts[:platform] ||= platform
|
97
100
|
entry = bundle.find_resource_entry(resource_name, opts)
|
98
101
|
entry.nil? ? '' : entry.cacheable_url
|
99
102
|
end
|
@@ -102,6 +105,7 @@ module SproutCore
|
|
102
105
|
def loc(string, opts = {})
|
103
106
|
string = string.nil? ? '' : string.to_s
|
104
107
|
opts[:language] ||= language
|
108
|
+
opts[:platform] ||= platform
|
105
109
|
bundle.strings_hash(opts)[string] || string
|
106
110
|
end
|
107
111
|
|
data/lib/sproutcore/library.rb
CHANGED
@@ -348,6 +348,21 @@ module SproutCore
|
|
348
348
|
self.bundle_installer.remove(bundle_name, opts)
|
349
349
|
end
|
350
350
|
|
351
|
+
# Computes a build number for the bundle by generating a SHA1 hash. The
|
352
|
+
# return value is cached to speed up future requests.
|
353
|
+
def compute_build_number(bundle)
|
354
|
+
@cached_build_numbers ||= {}
|
355
|
+
src = bundle.source_root
|
356
|
+
ret = @cached_build_numbers[src]
|
357
|
+
return ret unless ret.nil?
|
358
|
+
|
359
|
+
digests = Dir.glob(File.join(src, '**', '*.*')).map do |path|
|
360
|
+
(File.exists?(path) && !File.directory?(path)) ? Digest::SHA1.hexdigest(File.read(path)) : '0000'
|
361
|
+
end
|
362
|
+
ret = @cached_build_numbers[src] = Digest::SHA1.hexdigest(digests.join)
|
363
|
+
return ret
|
364
|
+
end
|
365
|
+
|
351
366
|
protected
|
352
367
|
|
353
368
|
# Load the library at the specified path. Loads the sc-config.rb if it
|
@@ -379,6 +394,14 @@ module SproutCore
|
|
379
394
|
end
|
380
395
|
|
381
396
|
# Override any all options with load_opts
|
397
|
+
if build_numbers = @load_opts[:build_numbers]
|
398
|
+
@load_opts.delete(:build_numbers)
|
399
|
+
build_numbers.each do | bundle_name, build_number |
|
400
|
+
env = @environment[bundle_name.to_sym] ||= {}
|
401
|
+
env[:build_number] = build_number
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
382
405
|
(@environment[:all] ||= {}).merge!(@load_opts)
|
383
406
|
|
384
407
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'sproutcore/jsdoc'
|
2
2
|
require 'net/http'
|
3
3
|
require 'uri'
|
4
|
+
require 'rack/utils'
|
4
5
|
|
5
6
|
module SproutCore
|
6
7
|
|
@@ -69,8 +70,11 @@ module SproutCore
|
|
69
70
|
|
70
71
|
# Check for a few special urls for built-in services and route them off
|
71
72
|
case url
|
73
|
+
|
74
|
+
# Returns the JSON file that contains the current list of tests.
|
72
75
|
when "#{current_bundle.url_root}/-tests/index.js"
|
73
76
|
ret = handle_test(url)
|
77
|
+
|
74
78
|
when "#{current_bundle.index_root}/-docs/index.html"
|
75
79
|
ret = (request.method == :post) ? handle_doc(url) : handle_resource(url)
|
76
80
|
|
data/lib/sproutcore/version.rb
CHANGED
@@ -62,7 +62,7 @@ module SproutCore
|
|
62
62
|
%{#{key} = #{opts[:class] || 'SC.View'}.extend({\n #{ opts[:properties] }\n});}
|
63
63
|
end
|
64
64
|
ret << %{#{prefix}.page = SC.Page.create({\n#{ outlets * ",\n\n" }\n}); }
|
65
|
-
bundle ? SproutCore::BuildTools::JavaScriptResourceBuilder.new(nil, nil, bundle).join(ret) : ret*"\n"
|
65
|
+
bundle ? SproutCore::BuildTools::JavaScriptResourceBuilder.new(nil, nil, bundle, nil).join(ret) : ret*"\n"
|
66
66
|
end
|
67
67
|
|
68
68
|
def self.render_css
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sproutcore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Jolley, Erich Ocean
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-01-08 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -60,11 +60,11 @@ dependencies:
|
|
60
60
|
requirements:
|
61
61
|
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 1.
|
63
|
+
version: 1.8.0
|
64
64
|
version:
|
65
65
|
description: SproutCore - JavaScript Application Framework + Build Tools
|
66
66
|
email:
|
67
|
-
- charles@sproutit.com
|
67
|
+
- charles@sproutit.com
|
68
68
|
executables:
|
69
69
|
- sc-build
|
70
70
|
- sc-gen
|
@@ -426,6 +426,7 @@ files:
|
|
426
426
|
- jsdoc/test.js
|
427
427
|
- lib/sproutcore/build_tools/html_builder.rb
|
428
428
|
- lib/sproutcore/build_tools/resource_builder.rb
|
429
|
+
- lib/sproutcore/build_tools/test_template.rhtml
|
429
430
|
- lib/sproutcore/build_tools.rb
|
430
431
|
- lib/sproutcore/bundle.rb
|
431
432
|
- lib/sproutcore/bundle_installer.rb
|
@@ -498,6 +499,7 @@ files:
|
|
498
499
|
- tasks/environment.rake
|
499
500
|
- tasks/rspec.rake
|
500
501
|
- tasks/website.rake
|
502
|
+
- yui_compressor/yuicompressor-2.4.2.jar
|
501
503
|
has_rdoc: true
|
502
504
|
homepage: http://sproutcore.rubyforge.org
|
503
505
|
post_install_message:
|
@@ -521,7 +523,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
521
523
|
requirements: []
|
522
524
|
|
523
525
|
rubyforge_project: sproutcore
|
524
|
-
rubygems_version: 1.
|
526
|
+
rubygems_version: 1.3.1
|
525
527
|
signing_key:
|
526
528
|
specification_version: 2
|
527
529
|
summary: SproutCore - JavaScript Application Framework + Build Tools
|