sproutit-sproutcore 1.0.20090721145281 → 1.0.20090721145282
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/Buildfile +4 -3
- data/VERSION.yml +2 -2
- data/buildtasks/entry.rake +3 -0
- data/buildtasks/manifest.rake +35 -9
- data/buildtasks/target.rake +25 -6
- data/frameworks/sproutcore/Buildfile +10 -0
- data/frameworks/sproutcore/frameworks/datastore/data_sources/data_source.js +41 -20
- data/frameworks/sproutcore/frameworks/datastore/data_sources/fixtures.js +14 -43
- data/frameworks/sproutcore/frameworks/datastore/models/record.js +11 -0
- data/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +6 -3
- data/frameworks/sproutcore/frameworks/datastore/system/nested_store.js +5 -1
- data/frameworks/sproutcore/frameworks/datastore/system/query.js +10 -7
- data/frameworks/sproutcore/frameworks/datastore/system/record_array.js +19 -20
- data/frameworks/sproutcore/frameworks/datastore/system/store.js +126 -93
- data/frameworks/sproutcore/frameworks/datastore/tests/data_sources/fixtures.js +9 -3
- data/frameworks/sproutcore/frameworks/datastore/tests/models/many_attribute.js +6 -1
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/core_methods.js +28 -3
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/destroy.js +13 -5
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/storeDidChangeProperties.js +46 -23
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record/writeAttribute.js +29 -5
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +13 -4
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/chain.js +109 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChanges.js +69 -15
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/commitChangesFromNestedStore.js +20 -1
- data/frameworks/sproutcore/frameworks/datastore/tests/system/nested_store/dataHashDidChange.js +4 -1
- data/frameworks/sproutcore/frameworks/datastore/tests/system/query/find_all.js +56 -6
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/commitRecord.js +9 -2
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/core_methods.js +45 -2
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/recordDidChange.js +0 -1
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/retrieveRecord.js +53 -6
- data/frameworks/sproutcore/frameworks/datastore/tests/system/store/writeDataHash.js +0 -5
- data/frameworks/sproutcore/frameworks/desktop/panes/menu.js +47 -27
- data/frameworks/sproutcore/frameworks/desktop/system/drag.js +5 -4
- data/frameworks/sproutcore/frameworks/desktop/tests/views/collection/mouse.js +23 -12
- data/frameworks/sproutcore/frameworks/desktop/tests/views/list/render.js +92 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/methods.js +104 -53
- data/frameworks/sproutcore/frameworks/desktop/tests/views/select_field/ui.js +2 -0
- data/frameworks/sproutcore/frameworks/desktop/views/button.js +4 -3
- data/frameworks/sproutcore/frameworks/desktop/views/collection.js +6 -2
- data/frameworks/sproutcore/frameworks/desktop/views/list.js +9 -0
- data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +2 -2
- data/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +3 -3
- data/frameworks/sproutcore/frameworks/desktop/views/popup_button.js +9 -1
- data/frameworks/sproutcore/frameworks/desktop/views/select_field.js +80 -102
- data/frameworks/sproutcore/frameworks/foundation/controllers/array.js +0 -1
- data/frameworks/sproutcore/frameworks/foundation/english.lproj/text_field.css +5 -1
- data/frameworks/sproutcore/frameworks/foundation/panes/pane.js +8 -1
- data/frameworks/sproutcore/frameworks/foundation/private/tree_item_observer.js +0 -1
- data/frameworks/sproutcore/frameworks/foundation/system/datetime.js +31 -3
- data/frameworks/sproutcore/frameworks/foundation/system/event.js +0 -4
- data/frameworks/sproutcore/frameworks/foundation/system/render_context.js +3 -7
- data/frameworks/sproutcore/frameworks/foundation/system/request.js +3 -4
- data/frameworks/sproutcore/frameworks/foundation/system/user_defaults.js +78 -17
- data/frameworks/sproutcore/frameworks/foundation/system/utils.js +9 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/controllers/array/single_case.js +2 -2
- data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_selector.js +2 -2
- data/frameworks/sproutcore/frameworks/foundation/tests/system/datetime.js +5 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/request.js +2 -2
- data/frameworks/sproutcore/frameworks/foundation/tests/system/user_defaults.js +1 -4
- data/frameworks/sproutcore/frameworks/foundation/tests/validators/validator.js +20 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +13 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/text_field/ui.js +132 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/isVisibleInWindow.js +6 -3
- data/frameworks/sproutcore/frameworks/foundation/validators/validator.js +8 -5
- data/frameworks/sproutcore/frameworks/foundation/views/image.js +18 -5
- data/frameworks/sproutcore/frameworks/foundation/views/text_field.js +292 -21
- data/frameworks/sproutcore/frameworks/foundation/views/view.js +13 -14
- data/frameworks/sproutcore/frameworks/mini/license.js +28 -0
- data/frameworks/sproutcore/frameworks/runtime/core.js +35 -0
- data/frameworks/sproutcore/frameworks/runtime/mixins/enumerable.js +1 -1
- data/frameworks/sproutcore/frameworks/runtime/system/sparse_array.js +79 -5
- data/frameworks/sproutcore/frameworks/runtime/tests/mixins/enumerable.js +6 -6
- data/frameworks/sproutcore/frameworks/runtime/tests/system/sparse_array.js +53 -0
- data/frameworks/sproutcore/frameworks/testing/system/plan.js +4 -0
- data/frameworks/sproutcore/frameworks/testing/system/runner.js +1 -1
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/radio.css +4 -0
- data/gen/design/Buildfile +23 -0
- data/gen/design/README +1 -0
- data/gen/design/USAGE +10 -0
- data/gen/design/templates/english.lproj/@filename@.js +16 -0
- data/gen/page/Buildfile +36 -0
- data/gen/page/README +1 -0
- data/gen/page/USAGE +15 -0
- data/gen/page/templates/pages/@target_name@/Buildfile +16 -0
- data/gen/page/templates/pages/@target_name@/core.js +22 -0
- data/gen/page/templates/pages/@target_name@/english.lproj/body.css +1 -0
- data/gen/page/templates/pages/@target_name@/english.lproj/body.rhtml +7 -0
- data/gen/page/templates/pages/@target_name@/english.lproj/strings.js +15 -0
- data/gen/view/README +1 -1
- data/gen/view/USAGE +5 -5
- data/lib/sproutcore/builders/base.rb +13 -2
- data/lib/sproutcore/builders/html.rb +28 -1
- data/lib/sproutcore/builders/minify.rb +84 -18
- data/lib/sproutcore/builders/test.rb +2 -1
- data/lib/sproutcore/helpers/entry_sorter.rb +16 -1
- data/lib/sproutcore/helpers/static_helper.rb +32 -4
- data/lib/sproutcore/helpers/tag_helper.rb +65 -0
- data/lib/sproutcore/models/manifest.rb +40 -6
- data/lib/sproutcore/models/target.rb +12 -3
- data/lib/sproutcore/rack/builder.rb +56 -4
- data/lib/sproutcore/tools/manifest.rb +1 -0
- data/lib/sproutcore/tools/server.rb +1 -0
- data/lib/sproutcore/tools.rb +21 -1
- data/lib/sproutcore.rb +13 -0
- metadata +16 -1
@@ -130,7 +130,14 @@ module SC
|
|
130
130
|
# self
|
131
131
|
#
|
132
132
|
def compile(render_engine, input_path, content_for_key = nil)
|
133
|
-
|
133
|
+
|
134
|
+
if content_for_key.nil?
|
135
|
+
if @in_partial
|
136
|
+
content_for_key = :_partial_
|
137
|
+
else
|
138
|
+
content_for_key = self.default_content_for_key
|
139
|
+
end
|
140
|
+
end
|
134
141
|
|
135
142
|
if !File.exist?(input_path)
|
136
143
|
raise "html_builder could compile file at #{input_path} because the file could not be found"
|
@@ -140,6 +147,7 @@ module SC
|
|
140
147
|
@renderer = render_engine # save for capture...
|
141
148
|
|
142
149
|
input = File.read(input_path)
|
150
|
+
|
143
151
|
content_for content_for_key do
|
144
152
|
_render_compiled_template( render_engine.compile(input) )
|
145
153
|
end
|
@@ -150,6 +158,25 @@ module SC
|
|
150
158
|
|
151
159
|
private
|
152
160
|
|
161
|
+
# Renders an entry as a partial. This will insert the results inline
|
162
|
+
# instead of into a content div.
|
163
|
+
def render_partial(entry)
|
164
|
+
|
165
|
+
# save off
|
166
|
+
old_partial = @content_for__partial_
|
167
|
+
old_in_partial = @in_partial
|
168
|
+
|
169
|
+
@content_for__partial_ = ''
|
170
|
+
@in_partial = true
|
171
|
+
render_entry(entry)
|
172
|
+
ret = @content_for__partial_
|
173
|
+
@content_for__partial_ = old_partial
|
174
|
+
@in_partial = old_in_partial
|
175
|
+
|
176
|
+
return ret
|
177
|
+
|
178
|
+
end
|
179
|
+
|
153
180
|
# Renders a single entry. The entry will be staged and then its
|
154
181
|
# render task will be executed.
|
155
182
|
def render_entry(entry)
|
@@ -33,35 +33,101 @@ module SC
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def build_css(dst_path)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
yui_root = File.expand_path(File.join(LIBPATH, '..', 'vendor', 'yui-compressor'))
|
37
|
+
jar_path = File.join(yui_root, 'yuicompressor-2.4.2.jar')
|
38
|
+
FileUtils.mkdir_p(File.dirname(dst_path)) # make sure loc exists...
|
39
|
+
filecompress = "java -jar " + jar_path + " --charset utf-8 --line-break 0 --nomunge --preserve-semi --disable-optimizations " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
|
40
|
+
SC.logger.info 'Compressing CSS with YUI .... '+ dst_path
|
41
|
+
SC.logger.debug `#{filecompress}`
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
if $?.exitstatus != 0
|
44
|
+
_report_error(output, entry.filename, entry.source_path)
|
45
|
+
SC.logger.fatal("!!!!YUI compressor failed, please check that your css code is valid.")
|
46
|
+
SC.logger.fatal("!!!!Failed compressing CSS... "+ dst_path)
|
47
|
+
end
|
48
|
+
end
|
48
49
|
|
49
50
|
# Minify some javascript by invoking the YUI compressor.
|
50
51
|
def build_javascript(dst_path)
|
51
52
|
yui_root = File.expand_path(File.join(LIBPATH, '..', 'vendor', 'yui-compressor'))
|
52
53
|
jar_path = File.join(yui_root, 'yuicompressor-2.4.2.jar')
|
53
54
|
FileUtils.mkdir_p(File.dirname(dst_path)) # make sure loc exists...
|
54
|
-
filecompress = "java -jar " + jar_path + " --charset utf-8 --line-break 80 " + entry.source_path + " -o " + dst_path
|
55
|
-
SC.logger.info 'Compressing with YUI
|
56
|
-
|
57
|
-
|
55
|
+
filecompress = "java -jar " + jar_path + " --charset utf-8 --line-break 80 " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
|
56
|
+
SC.logger.info 'Compressing with YUI: '+ dst_path + "..."
|
57
|
+
|
58
|
+
output = `#{filecompress}` # It'd be nice to just read STDERR, but
|
59
|
+
# I can't find a reasonable, commonly-
|
60
|
+
# installed, works-on-all-OSes solution.
|
58
61
|
if $?.exitstatus != 0
|
59
|
-
|
62
|
+
_report_error(output, entry.filename, entry.source_path)
|
63
|
+
SC.logger.fatal("!!!!YUI compressor failed, please check that your js code is valid")
|
60
64
|
SC.logger.fatal("!!!!Failed compressing ... "+ dst_path)
|
61
65
|
end
|
62
66
|
|
63
67
|
end
|
64
|
-
|
65
|
-
end
|
66
68
|
|
69
|
+
|
70
|
+
def _report_error(output, input_filename, input_filepath)
|
71
|
+
# The output might have some clues to what exactly was wrong, and it'll
|
72
|
+
# be convenient for users if we include the subset. So we'll read the
|
73
|
+
# line numbers from any output lines that start with "[ERROR]" those
|
74
|
+
# lines, too.
|
75
|
+
if output
|
76
|
+
parsed_a_line = false
|
77
|
+
output.each_line { |output_line|
|
78
|
+
output_line = output_line.chomp
|
79
|
+
if (output_line =~ /^\[ERROR\] (\d+):(\d+):.*/) != nil
|
80
|
+
line_number = $1
|
81
|
+
position = $2
|
82
|
+
parsed_a_line = true
|
83
|
+
if ( position && position.to_i > 0 )
|
84
|
+
# Read just that line and output it.
|
85
|
+
# (sed -n '3{;p;q;}' would probably be faster, but not
|
86
|
+
# universally available)
|
87
|
+
line_number = line_number.to_i
|
88
|
+
line_counter = 1
|
89
|
+
begin
|
90
|
+
file = File.new(input_filepath, "r")
|
91
|
+
outputted_line = false
|
92
|
+
previous_line = nil
|
93
|
+
while (file_line = file.gets)
|
94
|
+
|
95
|
+
if ( line_counter == line_number )
|
96
|
+
message = "YUI compressor error: #{output_line} on line #{line_number} of #{input_filename}:\n"
|
97
|
+
if !previous_line.nil?
|
98
|
+
message += " [#{line_number - 1}] #{previous_line}"
|
99
|
+
end
|
100
|
+
message += " --> [#{line_number}] #{file_line}"
|
101
|
+
|
102
|
+
SC.logger.error message
|
103
|
+
outputted_line = true
|
104
|
+
break
|
105
|
+
else
|
106
|
+
previous_line = file_line
|
107
|
+
end
|
108
|
+
line_counter += 1
|
109
|
+
end
|
110
|
+
file.close
|
111
|
+
rescue => err
|
112
|
+
SC.logger.error "Could not read the actual line from the file: #{err}"
|
113
|
+
end
|
114
|
+
|
115
|
+
if !outputted_line
|
116
|
+
SC.logger.error "YUI compressor error: #{output_line}, but couldn't read that line in the input file"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
}
|
121
|
+
|
122
|
+
# If we didn't handle at least one line of output specially, then
|
123
|
+
# just output it all.
|
124
|
+
if !parsed_a_line
|
125
|
+
SC.logger.error output
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
end
|
132
|
+
|
67
133
|
end
|
@@ -48,7 +48,8 @@ module SC
|
|
48
48
|
# conflict with any others.
|
49
49
|
def render_jstest(entry)
|
50
50
|
lines = readlines(entry.staging_path)
|
51
|
-
|
51
|
+
pathname = entry.staging_path.gsub(/^.+\/staging\//,'').gsub(/"/, '\"')
|
52
|
+
lines.unshift %[<script type="text/javascript">\nif (typeof SC !== "undefined") {\n SC.mode = "TEST_MODE";\n SC.filename = "#{pathname}"; \n}\n(function() {\n]
|
52
53
|
lines.push %[\n})();\n</script>\n]
|
53
54
|
@content_for_final = (@content_for_final || '') + lines.join("")
|
54
55
|
end
|
@@ -29,7 +29,22 @@ module SC
|
|
29
29
|
def sort(entries)
|
30
30
|
# first sort entries by filename - ignoring case
|
31
31
|
entries = entries.sort do |a,b|
|
32
|
-
|
32
|
+
a = (a.filename || '').to_s.downcase
|
33
|
+
b = (b.filename || '').to_s.downcase
|
34
|
+
|
35
|
+
# lproj/foo_page.js and main.js are loaded last
|
36
|
+
a_kind = (a =~ /lproj\/.+_page\.js$/) ? 1 : -1
|
37
|
+
a_kind = 2 if a =~ /main.js$/
|
38
|
+
|
39
|
+
b_kind = (b =~ /lproj\/.+_page\.js$/) ? 1 : -1
|
40
|
+
b_kind = 2 if b =~ /main.js$/
|
41
|
+
|
42
|
+
if a_kind != b_kind
|
43
|
+
a_kind <=> b_kind
|
44
|
+
else
|
45
|
+
a <=> b
|
46
|
+
end
|
47
|
+
|
33
48
|
end
|
34
49
|
all_entries = entries.dup # needed for sort...
|
35
50
|
|
@@ -94,7 +94,7 @@ module SC
|
|
94
94
|
|
95
95
|
# include either the entry URL or URL of ordered entries
|
96
96
|
# depending on setup
|
97
|
-
if combine_javascript
|
97
|
+
if cur_target.config.combine_javascript
|
98
98
|
urls << cur_entry.cacheable_url
|
99
99
|
else
|
100
100
|
urls += cur_entry.ordered_entries.map { |e| e.cacheable_url }
|
@@ -115,9 +115,27 @@ module SC
|
|
115
115
|
urls.join("\n")
|
116
116
|
end
|
117
117
|
|
118
|
+
# Attempts to render the named entry as a partial
|
119
|
+
#
|
120
|
+
# === Options
|
121
|
+
# language:: the language to use. defaults to current
|
122
|
+
#
|
123
|
+
def partial(resource_name, opts = {})
|
124
|
+
resource_name = resource_name.to_s
|
125
|
+
m = self.manifest
|
126
|
+
if opts[:language]
|
127
|
+
m = target.manifest_for(:language => opts[:language]).build!
|
128
|
+
end
|
129
|
+
|
130
|
+
entry = m.find_entry(resource_name, :hidden => true, :entry_type => :html)
|
131
|
+
return entry.nil? ? '' : render_partial(entry)
|
132
|
+
end
|
133
|
+
|
118
134
|
# Returns the URL for the named resource
|
119
135
|
def sc_static(resource_name, opts = {})
|
120
136
|
|
137
|
+
resource_name = resource_name.to_s
|
138
|
+
|
121
139
|
# determine which manifest to search. if a language is explicitly
|
122
140
|
# specified, lookup manifest for that language. otherwise use
|
123
141
|
# current manifest.
|
@@ -127,10 +145,19 @@ module SC
|
|
127
145
|
end
|
128
146
|
|
129
147
|
entry = m.find_entry(resource_name)
|
130
|
-
|
148
|
+
return '' if entry.nil?
|
149
|
+
return entry.friendly_url if opts[:friendly] && entry.friendly_url
|
150
|
+
return entry.cacheable_url
|
131
151
|
end
|
132
152
|
alias_method :static_url, :sc_static
|
133
153
|
|
154
|
+
# Returns the URL of the named target's index.html, if it has one
|
155
|
+
def sc_target(resource_name, opts = {})
|
156
|
+
opts[:friendly] = true
|
157
|
+
resource_name = "#{resource_name}:index.html"
|
158
|
+
sc_static(resource_name, opts)
|
159
|
+
end
|
160
|
+
|
134
161
|
# Allows you to specify HTML resource this html template should be
|
135
162
|
# merged into. Optionally also specify the layout file to use when
|
136
163
|
# building this resource.
|
@@ -168,8 +195,9 @@ module SC
|
|
168
195
|
return ret
|
169
196
|
end
|
170
197
|
|
171
|
-
def title
|
172
|
-
|
198
|
+
def title(cur_target=nil)
|
199
|
+
cur_target = self.target if cur_target.nil?
|
200
|
+
cur_target.config.title || cur_target.target_name.to_s.sub(/^\//,'').gsub(/[-_\/]/,' ').split(' ').map { |x| x.capitalize }.join(' ')
|
173
201
|
end
|
174
202
|
|
175
203
|
private
|
@@ -84,6 +84,71 @@ module SC
|
|
84
84
|
fix_double_escape(html_escape(html.to_s))
|
85
85
|
end
|
86
86
|
|
87
|
+
# Simple link_to can wrap a passed string with a link to a specified
|
88
|
+
# target or static asset. If you pass a block then the block will be
|
89
|
+
# invoked and its resulting content linked. You can also pass
|
90
|
+
# :popup, :title, :id, :class, and :style
|
91
|
+
def link_to(content, opts=nil, &block)
|
92
|
+
if block_given?
|
93
|
+
concat(link_to(capture(&block), content), block.binding);
|
94
|
+
return ''
|
95
|
+
end
|
96
|
+
|
97
|
+
if !content.instance_of?(String) && opts.nil?
|
98
|
+
opts = content
|
99
|
+
content = nil
|
100
|
+
end
|
101
|
+
|
102
|
+
opts = { :href => opts } if opts.instance_of? String
|
103
|
+
opts = HashStruct.new(opts)
|
104
|
+
html_attrs = HashStruct.new
|
105
|
+
is_target = false
|
106
|
+
|
107
|
+
if opts.href
|
108
|
+
html_attrs.href = opts.href
|
109
|
+
elsif opts.target
|
110
|
+
|
111
|
+
is_target = (target.target_name.to_sym == "/#{opts.target.to_s}".to_sym)
|
112
|
+
|
113
|
+
# supply title if needed
|
114
|
+
if content.nil?
|
115
|
+
cur_target = is_target ? target : target.target_for(opts.target)
|
116
|
+
content = title(cur_target) if cur_target
|
117
|
+
content = opts.target if content.nil?
|
118
|
+
end
|
119
|
+
|
120
|
+
# if current==false, then don't link if current target matches
|
121
|
+
if !opts.current.nil? && (opts.current==false) && is_target
|
122
|
+
return %(<span class="anchor current">#{content}</span>)
|
123
|
+
end
|
124
|
+
|
125
|
+
html_attrs.href = sc_target(opts.target, :language => opts.language)
|
126
|
+
elsif opts.static
|
127
|
+
html_attrs.href = sc_static(opts.static, :language => opts.language)
|
128
|
+
end
|
129
|
+
|
130
|
+
if opts.popup
|
131
|
+
popup = opts.popup
|
132
|
+
html_attrs.target = popup.instance_of?(String) ? popup : '_blank'
|
133
|
+
end
|
134
|
+
|
135
|
+
%w[title id class style].each do |key|
|
136
|
+
html_attrs[key] = opts[key] if opts[key]
|
137
|
+
end
|
138
|
+
|
139
|
+
# add "current" class name
|
140
|
+
if is_target
|
141
|
+
html_attrs[:class] = [html_attrs[:class], 'current'].compact.join(' ')
|
142
|
+
end
|
143
|
+
|
144
|
+
ret = ["<a "]
|
145
|
+
html_attrs.each { |k,v| ret << [k,'=','"',v,'" '].join('') }
|
146
|
+
ret << '>'
|
147
|
+
ret << content
|
148
|
+
ret << '</a>'
|
149
|
+
return ret.join('')
|
150
|
+
end
|
151
|
+
|
87
152
|
private
|
88
153
|
def content_tag_string(name, content, options)
|
89
154
|
tag_options = options ? tag_options(options) : ""
|
@@ -88,6 +88,8 @@ module SC
|
|
88
88
|
return self
|
89
89
|
end
|
90
90
|
|
91
|
+
def built?; @is_built; end
|
92
|
+
|
91
93
|
# Resets the manifest entries. this is called before a build is
|
92
94
|
# performed. This will reset only the entries, none of the other props.
|
93
95
|
#
|
@@ -213,6 +215,10 @@ module SC
|
|
213
215
|
end
|
214
216
|
opts.staging_path ||= unique_staging_path(staging_path)
|
215
217
|
|
218
|
+
# generate a unique cache path from the staging page. just sub the
|
219
|
+
# staging root for the cache root
|
220
|
+
opts.cache_path ||= unique_cache_path(entry.cache_path)
|
221
|
+
|
216
222
|
# copy other useful entries
|
217
223
|
opts.source_entry = entry
|
218
224
|
opts.source_entries = [entry]
|
@@ -289,11 +295,28 @@ module SC
|
|
289
295
|
#
|
290
296
|
def find_entry(fragment, opts = {}, seen=nil)
|
291
297
|
|
298
|
+
entry_extname = entry_rootname = ret = target_name = nil
|
299
|
+
|
300
|
+
# optionally you can specify an explicit target name
|
301
|
+
split_index = fragment.index(':') # find first index
|
302
|
+
unless split_index.nil?
|
303
|
+
target_name = '/' + fragment[0..(split_index-1)] if split_index>0
|
304
|
+
fragment = fragment[(split_index+1)..-1] # remove colon
|
305
|
+
end
|
306
|
+
|
307
|
+
# find the current manifest
|
308
|
+
if target_name
|
309
|
+
cur_target = self.target.target_for(target_name) || self.target
|
310
|
+
cur_manifest = cur_target.manifest_for(self.variation).build!
|
311
|
+
else
|
312
|
+
cur_manifest = self
|
313
|
+
end
|
314
|
+
|
292
315
|
extname = File.extname(fragment)
|
293
316
|
rootname = fragment.sub(/#{extname}$/, '')
|
294
|
-
entry_extname = entry_rootname = nil
|
295
317
|
|
296
|
-
|
318
|
+
# look on our own target only if target is named
|
319
|
+
ret = cur_manifest.entries(:hidden => opts[:hidden]).reject do |entry|
|
297
320
|
if entry.has_options?(opts)
|
298
321
|
entry_extname = File.extname(entry.filename)
|
299
322
|
entry_rootname = entry.filename.sub(/#{entry_extname}$/,'')
|
@@ -301,16 +324,17 @@ module SC
|
|
301
324
|
else
|
302
325
|
ext_match = false
|
303
326
|
end
|
327
|
+
|
304
328
|
!(ext_match && (/#{rootname}$/ =~ entry_rootname))
|
305
329
|
end
|
306
|
-
|
330
|
+
|
307
331
|
ret = ret.first
|
308
|
-
|
332
|
+
|
309
333
|
# if no match was found, search the same manifests in required targets
|
310
334
|
if ret.nil?
|
311
335
|
seen = Set.new if seen.nil?
|
312
|
-
seen <<
|
313
|
-
|
336
|
+
seen << cur_manifest.target
|
337
|
+
cur_manifest.target.expand_required_targets.each do |t|
|
314
338
|
next if seen.include?(t) # avoid recursion
|
315
339
|
|
316
340
|
manifest = t.manifest_for(self.variation).build!
|
@@ -330,6 +354,16 @@ module SC
|
|
330
354
|
end
|
331
355
|
return path
|
332
356
|
end
|
357
|
+
|
358
|
+
# Finds a unique cache path starting with the root proposed staging
|
359
|
+
# path.
|
360
|
+
def unique_cache_path(path)
|
361
|
+
paths = entries(:hidden => true).map { |e| e.cache_path }
|
362
|
+
while paths.include?(path)
|
363
|
+
path = path.sub(/(__\$[0-9]+)?(\.\w+)?$/,"__$#{next_staging_uuid}\\2")
|
364
|
+
end
|
365
|
+
return path
|
366
|
+
end
|
333
367
|
|
334
368
|
protected
|
335
369
|
|
@@ -241,7 +241,10 @@ module SC
|
|
241
241
|
# === Returns
|
242
242
|
# A build number string
|
243
243
|
#
|
244
|
-
def compute_build_number(seen=nil)
|
244
|
+
def compute_build_number(seen=nil, opts = {})
|
245
|
+
|
246
|
+
# reset cache if forced to recompute
|
247
|
+
build_number = nil if opts[:force]
|
245
248
|
|
246
249
|
# Look for a global build_numbers hash and try that
|
247
250
|
if (build_numbers = config.build_numbers)
|
@@ -272,10 +275,16 @@ module SC
|
|
272
275
|
# causing infinite loops. Normally this should not be necessary, but
|
273
276
|
# we put this here to gaurd against misconfigured projects
|
274
277
|
seen ||= []
|
275
|
-
|
278
|
+
|
279
|
+
_targets = required_targets(:theme => true).sort do |a,b|
|
280
|
+
(a.target_name||'').to_s <=> (b.target_name||'').to_s
|
281
|
+
end
|
282
|
+
|
283
|
+
_targets.each do |ct|
|
276
284
|
next if seen.include?(ct)
|
285
|
+
ct.prepare!
|
277
286
|
seen << ct
|
278
|
-
digests <<
|
287
|
+
digests << ct.compute_build_number(seen, :force => true)
|
279
288
|
end
|
280
289
|
|
281
290
|
# Finally digest the complete string - tada! build number
|
@@ -171,18 +171,70 @@ module SC
|
|
171
171
|
# Reloads the project if reloading is enabled. At maximum this will
|
172
172
|
# reload the project every 5 seconds.
|
173
173
|
def reload_project!
|
174
|
+
|
175
|
+
monitor_project!
|
176
|
+
|
174
177
|
# don't reload if no project or is disabled
|
175
178
|
return if @project.nil? || !@project.config.reload_project
|
176
179
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
if reload_delay > 5
|
180
|
+
if @project_did_change
|
181
|
+
@project_did_change = false
|
181
182
|
SC.logger.info "Rebuilding project manifest"
|
182
183
|
@project.reload!
|
183
184
|
end
|
184
185
|
end
|
186
|
+
|
187
|
+
def monitor_project!
|
188
|
+
if !@should_monitor
|
189
|
+
@should_monitor = true
|
190
|
+
@project_root = @project.project_root
|
191
|
+
|
192
|
+
# collect initial info on project
|
193
|
+
files = Dir.glob(@project_root / '**' / '*')
|
194
|
+
# follow 1-level of symlinks
|
195
|
+
files += Dir.glob(@project_root / '**' / '*' / '**' / '*')
|
196
|
+
tmp_path = /^#{Regexp.escape(@project_root / 'tmp')}/
|
197
|
+
files.reject! { |f| f =~ tmp_path }
|
198
|
+
files.reject! { |f| File.directory?(f) }
|
199
|
+
|
200
|
+
@project_file_count = files.size
|
201
|
+
@project_mtime = files.map { |x| File.mtime(x).to_i }.max
|
202
|
+
|
203
|
+
Thread.new do
|
204
|
+
while @should_monitor
|
205
|
+
|
206
|
+
# only need to start scanning again 2 seconds after the last
|
207
|
+
# request was serviced.
|
208
|
+
reload_delay = (Time.now - @last_reload_time)
|
209
|
+
if reload_delay > 2
|
210
|
+
files = Dir.glob(@project_root / '**' / '*')
|
211
|
+
# follow 1-level of symlinks
|
212
|
+
files += Dir.glob(@project_root / '**' / '*' / '**' / '*')
|
213
|
+
tmp_path = /^#{Regexp.escape(@project_root / 'tmp')}/
|
214
|
+
files.reject! { |f| f =~ tmp_path }
|
215
|
+
files.reject! { |f| File.directory?(f) }
|
216
|
+
|
217
|
+
cur_file_count = files.size
|
218
|
+
cur_mtime = files.map { |x| File.mtime(x).to_i }.max
|
219
|
+
|
220
|
+
if (@project_file_count != cur_file_count) || (@project_mtime != cur_mtime)
|
221
|
+
SC.logger.info "Detected project change. Will rebuild manifest"
|
222
|
+
@project_did_change = true
|
223
|
+
@project_file_count = cur_file_count
|
224
|
+
@project_mtime = cur_mtime
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
sleep(5)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
185
233
|
|
234
|
+
def stop_monitor!
|
235
|
+
@should_monitor = false
|
236
|
+
end
|
237
|
+
|
186
238
|
def target_for(url)
|
187
239
|
|
188
240
|
# get targets
|
data/lib/sproutcore/tools.rb
CHANGED
@@ -253,15 +253,35 @@ module SC
|
|
253
253
|
if (languages = options.languages).nil?
|
254
254
|
languages = targets.map { |t| t.installed_languages }
|
255
255
|
else
|
256
|
-
languages = languages.split('
|
256
|
+
languages = languages.split(',').map { |l| l.to_sym }
|
257
257
|
end
|
258
258
|
languages.flatten.uniq.compact
|
259
259
|
end
|
260
260
|
|
261
|
+
# Discovers build numbers requested for the build and sets them in the
|
262
|
+
# in the env if needed.
|
263
|
+
def find_build_numbers(*targets)
|
264
|
+
if options['build-numbers']
|
265
|
+
numbers = {}
|
266
|
+
options['build-numbers'].split(',').each do |pair|
|
267
|
+
pair = pair.split(':')
|
268
|
+
if pair.length < 2
|
269
|
+
fatal! "Could not parse build numbers! #{options['build-numbers']}"
|
270
|
+
end
|
271
|
+
numbers["/#{pair[0]}"] = pair[1]
|
272
|
+
end
|
273
|
+
SC.env.build_numbers = numbers
|
274
|
+
SC.logger.info "Using build numbers: #{numbers.map { |k,v| "#{k}: #{v}" }.join(',')}"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
261
278
|
# Core method to process command line options and then build a manifest.
|
262
279
|
# Shared by sc-manifest, sc-build and sc-docs commands.
|
263
280
|
def build_manifests(*targets)
|
264
281
|
|
282
|
+
# setup build numbers
|
283
|
+
find_build_numbers(*targets)
|
284
|
+
|
265
285
|
requires_project! # get project
|
266
286
|
targets = find_targets(*targets) # get targets
|
267
287
|
languages = find_languages(*targets) # get languages
|
data/lib/sproutcore.rb
CHANGED
@@ -125,6 +125,19 @@ module SproutCore
|
|
125
125
|
def self.project; @project; end
|
126
126
|
def self.project=(project); @project = project; end
|
127
127
|
|
128
|
+
# Attempts to load a project for the current working directory or from the
|
129
|
+
# passed directory location. Returns nil if no project could be detected.
|
130
|
+
# This is just a shorthand for creating a Project object. It is useful
|
131
|
+
# when using the build tools as a Ruby library
|
132
|
+
def self.load_project(path = nil, opts = {})
|
133
|
+
path = File.expand_path(path.nil? ? Dir.pwd : path)
|
134
|
+
if FalseClass === opts[:discover]
|
135
|
+
SC::Project.load path, :parent => SC.builtin_project
|
136
|
+
else # attempt to autodiscover unless disabled
|
137
|
+
SC::Project.load_nearest_project path, :parent => SC.builtin_project
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
128
141
|
end # module SC
|
129
142
|
|
130
143
|
SC = SproutCore # alias
|