sproutcore 0.9.17 → 0.9.18

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.
Files changed (72) hide show
  1. data/History.txt +45 -2
  2. data/Manifest.txt +10 -0
  3. data/Rakefile +1 -1
  4. data/app_generators/sproutcore/templates/sc-config +8 -2
  5. data/bin/sc-server +4 -0
  6. data/clients/sc_docs/english.lproj/body.css +0 -20
  7. data/clients/sc_docs/english.lproj/body.rhtml +1 -3
  8. data/clients/sc_docs/english.lproj/strings.js +1 -1
  9. data/clients/sc_docs/french.lproj/strings.js +14 -0
  10. data/clients/sc_test_runner/english.lproj/body.css +0 -20
  11. data/clients/sc_test_runner/english.lproj/body.rhtml +1 -3
  12. data/config/hoe.rb +1 -1
  13. data/frameworks/sproutcore/HISTORY +56 -1
  14. data/frameworks/sproutcore/debug/trace.js +81 -0
  15. data/frameworks/sproutcore/debug/unittest.js +2 -1
  16. data/frameworks/sproutcore/english.lproj/buttons.css +5 -2
  17. data/frameworks/sproutcore/english.lproj/core.css +0 -16
  18. data/frameworks/sproutcore/english.lproj/images/sc-theme-sprite.png +0 -0
  19. data/frameworks/sproutcore/english.lproj/splitview.css +83 -0
  20. data/frameworks/sproutcore/english.lproj/theme.css +21 -5
  21. data/frameworks/sproutcore/foundation/object.js +23 -0
  22. data/frameworks/sproutcore/foundation/string.js +4 -3
  23. data/frameworks/sproutcore/lib/core_views.rb +43 -8
  24. data/frameworks/sproutcore/lib/form_views.rb +2 -2
  25. data/frameworks/sproutcore/lib/index.rhtml +1 -1
  26. data/frameworks/sproutcore/mixins/enumerable.js +4 -8
  27. data/frameworks/sproutcore/mixins/selection_support.js +1 -1
  28. data/frameworks/sproutcore/models/collection.js +14 -3
  29. data/frameworks/sproutcore/models/record.js +6 -5
  30. data/frameworks/sproutcore/models/store.js +3 -3
  31. data/frameworks/sproutcore/panes/picker.js +1 -0
  32. data/frameworks/sproutcore/server/rails_server.js +4 -7
  33. data/frameworks/sproutcore/server/server.js +58 -1
  34. data/frameworks/sproutcore/tests/controllers/object.rhtml +1 -1
  35. data/frameworks/sproutcore/tests/models/collection.rhtml +160 -0
  36. data/frameworks/sproutcore/tests/models/model.rhtml +15 -3
  37. data/frameworks/sproutcore/tests/views/collection/base.rhtml +120 -47
  38. data/frameworks/sproutcore/tests/views/collection/source_list_rendering.rhtml +232 -0
  39. data/frameworks/sproutcore/tests/views/view/frame.rhtml +2 -2
  40. data/frameworks/sproutcore/tests/views/view/innerFrame.rhtml +87 -85
  41. data/frameworks/sproutcore/tests/views/view/scrollFrame.rhtml +25 -26
  42. data/frameworks/sproutcore/views/collection/collection.js +5 -1
  43. data/frameworks/sproutcore/views/field/select_field.js +1 -1
  44. data/frameworks/sproutcore/views/radio_group.js +2 -2
  45. data/frameworks/sproutcore/views/split.js +191 -174
  46. data/frameworks/sproutcore/views/split_divider.js +71 -68
  47. data/frameworks/sproutcore/views/view.js +65 -25
  48. data/lib/sproutcore.rb +4 -1
  49. data/lib/sproutcore/build_tools/html_builder.rb +50 -46
  50. data/lib/sproutcore/build_tools/resource_builder.rb +17 -5
  51. data/lib/sproutcore/bundle_installer.rb +3 -1
  52. data/lib/sproutcore/bundle_manifest.rb +4 -3
  53. data/lib/sproutcore/cssmin.rb +195 -0
  54. data/lib/sproutcore/generator_helper.rb +15 -0
  55. data/lib/sproutcore/helpers/capture_helper.rb +2 -22
  56. data/lib/sproutcore/helpers/dom_id_helper.rb +14 -0
  57. data/lib/sproutcore/helpers/static_helper.rb +6 -2
  58. data/lib/sproutcore/helpers/text_helper.rb +1 -1
  59. data/lib/sproutcore/merb.rb +2 -2
  60. data/lib/sproutcore/renderers/erubis.rb +43 -0
  61. data/lib/sproutcore/renderers/haml.rb +28 -0
  62. data/lib/sproutcore/renderers/sass.rb +42 -0
  63. data/lib/sproutcore/version.rb +1 -1
  64. data/lib/sproutcore/view_helpers.rb +40 -46
  65. data/sc_generators/controller/controller_generator.rb +1 -1
  66. data/sc_generators/language/USAGE +5 -7
  67. data/sc_generators/language/language_generator.rb +1 -1
  68. data/sc_generators/language/templates/strings.js +5 -1
  69. data/sc_generators/model/model_generator.rb +1 -1
  70. data/sc_generators/test/test_generator.rb +1 -1
  71. data/sc_generators/view/view_generator.rb +1 -1
  72. metadata +12 -5
@@ -52,7 +52,13 @@ module SproutCore
52
52
 
53
53
  # Join the lines together. This is one last chance to do some prep of
54
54
  # the data (such as minifcation and comment stripping)
55
- def join(lines); lines.join; end
55
+ def join(lines)
56
+ if bundle.minify?
57
+ SproutCore::CSSPacker.new.compress(lines.join)
58
+ else
59
+ lines.join
60
+ end
61
+ end
56
62
 
57
63
  # Rewrites any inline content such as static urls. Subclasseses can
58
64
  # override this to rewrite any other inline content.
@@ -88,7 +94,7 @@ module SproutCore
88
94
  # check for requires. Only follow a require if the require is in
89
95
  # the list of filenames.
90
96
  required_file = _require_for(filename, line)
91
- unless required_file.nil? || !filenames.include?(required_file)
97
+ if required_file && filenames.include?(required_file)
92
98
  lines, required = _build_one(required_file, lines, required, link_only)
93
99
  end
94
100
 
@@ -102,6 +108,11 @@ module SproutCore
102
108
  lines << filename
103
109
 
104
110
  elsif file_lines.size > 0
111
+
112
+ if entry.ext == "sass"
113
+ file_lines = [ SproutCore::Renderers::Sass.compile(entry, file_lines.join()) ]
114
+ end
115
+
105
116
  lines << "/* Start ----------------------------------------------------- " << filename << "*/\n\n"
106
117
  lines += file_lines
107
118
  lines << "\n\n/* End ------------------------------------------------------- " << filename << "*/\n\n"
@@ -119,13 +130,14 @@ module SproutCore
119
130
 
120
131
  # check line for required() pattern. understands JS and CSS.
121
132
  def _require_for(filename,line)
122
- new_file = line.scan(/require\(['"](.*)['"]\)/)
133
+ new_file = line.scan(/require\s*\(\s*['"](.*)(\.(js|css|sass))?['"]\s*\)/)
123
134
  ret = (new_file.size > 0) ? new_file.first.first : nil
124
135
  ret.nil? ? nil : filename_for_require(ret)
125
136
  end
126
137
 
127
- def filename_for_require(ret); "#{ret}.css"; end
128
-
138
+ def filename_for_require(ret)
139
+ filenames.include?("#{ret}.css") ? "#{ret}.css" : "#{ret}.sass"
140
+ end
129
141
  end
130
142
 
131
143
  class JavaScriptResourceBuilder < ResourceBuilder
@@ -36,7 +36,9 @@ module SproutCore
36
36
  ### Install Only Options
37
37
 
38
38
  if can_install
39
- opts.on("-s", "--source=URL", "Specify a URL to install from. You can provide either a full URL or just the path on github to your project. The tool assumes that the url you provide plus '.git' can be used to clone the project.")
39
+ opts.on("-s", "--source=URL", "Specify a URL to install from. You can provide either a full URL or just the path on github to your project. The tool assumes that the url you provide plus '.git' can be used to clone the project.") do |opt_source|
40
+ options[:source] = opt_source
41
+ end
40
42
 
41
43
  opts.on("-f", "--[no-]force", "Normally SproutCore will not install a bundle if a directory already exists at the install location. If you include this option, it will forceably install bundles even if it has to delete an existing directory.") do |opt_force|
42
44
  options[:force] = !!opt_force
@@ -258,10 +258,10 @@ module SproutCore
258
258
  :html
259
259
  when /\.haml$/
260
260
  :html
261
- when /\.html.haml$/
262
- :html
263
261
  when /\.css$/
264
262
  :stylesheet
263
+ when /\.sass$/
264
+ :stylesheet
265
265
  when /\.js$/
266
266
  :javascript
267
267
  when /\.lproj\/.+/
@@ -326,6 +326,8 @@ module SproutCore
326
326
  ret.build_path = File.join(*[bundle.build_root, language.to_s, cache_link, ret.filename].compact)
327
327
  ret.url = [url_root, language.to_s, cache_link, ret.filename].compact.join('/')
328
328
  end
329
+ ret.build_path.sub!(/\.sass$/, '.css')
330
+ ret.url.sub!(/.sass$/, '.css')
329
331
 
330
332
  # Done.
331
333
  return ret
@@ -349,7 +351,6 @@ module SproutCore
349
351
  # ext:: the file extension
350
352
  # source_path:: absolute paths into source that will comprise this resource
351
353
  # url:: the url that should be used to reference this resource in the current mode.
352
- # build_url:: the url that will be used to referene this resource in production.
353
354
  # build_path:: absolute path to the compiled resource
354
355
  # type:: the top-level category
355
356
  # original_path:: save the original path used to build this entry
@@ -0,0 +1,195 @@
1
+ # module and class name have been modified
2
+ #
3
+ # == MIT License
4
+ # See http://code.google.com/p/rainpress/
5
+ #
6
+ # == About
7
+ #
8
+ # Rainpress is a compressor for CSS. It's written in ruby, but should not be
9
+ # limited to ruby projects.
10
+ #
11
+ # Rainpress does not apply common compression algorithms like gzip, it removes
12
+ # unnecessary characters and replaces some attributes with a shorter equivalent
13
+ # name.
14
+ #
15
+ # == Links
16
+ #
17
+ # * {Rainpress Website}[http://rainpress.xhochy.com/]
18
+ # * {SVN repository}[http://code.google.com/p/rainpress/source]
19
+ # * {Bugtracker}[https://bugs.launchpad.net/rainpress/]
20
+ # * {Wiki}[http://code.google.com/p/rainpress/w/list]
21
+ # * {Translations}[https://translations.launchpad.net/rainpress/]
22
+ # * {XhochY Weblog (for Announcements about Rainpress)}[http://xhochy.org/en/]
23
+ # * {Mailinglist}[http://groups.google.com/group/xy-oss-projects-discussion]
24
+ # * {Continous Integration Builds and Tests}[http://cruisecontrol-rb.xhochy.com/builds/rainpress]
25
+ # * {Freshmeat Record}[http://freshmeat.net/projects/rainpress]
26
+ module SproutCore
27
+
28
+ # == Information
29
+ #
30
+ # This is the main class of Rainpress, create an instance of it to compress
31
+ # your CSS-styles.
32
+ #
33
+ # == Simple Usage
34
+ #
35
+ # packer = SproutCore::CSSPacker.new
36
+ # compressed_style = packer.compress(style)
37
+ class CSSPacker
38
+
39
+ # Use always this functions if you want to compress your CSS-style
40
+ #
41
+ # <b>Options:</b>
42
+ #
43
+ # * <tt>:preserveComments</tt> - if set to true, comments will not be
44
+ # removed
45
+ # * <tt>:preserveNewline</tt> - if set to true, newlines will not be removed
46
+ # * <tt>:preserveSpaces</tt> - if set to true, spaces will not be removed
47
+ # * <tt>:preserveColors</tt> - if set to true, colors will not be modified
48
+ # * <tt>:skipMisc</tt> - if set to true, miscellaneous compression parts
49
+ # will be skipped
50
+ def compress(style, options = {})
51
+ # remove comments
52
+ style = remove_comments(style) unless options[:preserveComments]
53
+
54
+ # remove newlines
55
+ style = remove_newlines(style) unless options[:preserveNewlines]
56
+
57
+ # remove unneeded spaces
58
+ style = remove_spaces(style) unless options[:preserveSpaces]
59
+
60
+ # replace colours with shorter names
61
+ style = shorten_colors(style) unless options[:preserveColors]
62
+
63
+ # make all other things
64
+ style = do_misc(style) unless options[:skipMisc]
65
+
66
+ style
67
+ end
68
+
69
+ # Remove all comments out of the CSS-Document
70
+ def remove_comments(script)
71
+ input = script
72
+ script = ''
73
+
74
+ while input.length > 0 do
75
+ pos = input.index("/*");
76
+
77
+ # No more comments
78
+ if pos == nil
79
+ script += input
80
+ input = '';
81
+ else # Comment beginning at pos
82
+ script += input[0..(pos-1)] if pos > 0 # only append text if there is some
83
+ input = input[(pos+2)..-1]
84
+ # Comment ending at pos
85
+ pos = input.index("*/")
86
+ input = input[(pos+2)..-1]
87
+ end
88
+ end
89
+
90
+ # return
91
+ script
92
+ end
93
+
94
+ # Remove all newline characters
95
+ def remove_newlines(script)
96
+ script.gsub(/\n|\r/,'')
97
+ end
98
+
99
+ # 1. Turn mutiple spaces into a single
100
+ # 2. Remove spaces around ;:{},
101
+ # 3. Remove tabs
102
+ def remove_spaces(script)
103
+ script = script.gsub(/(\s(\s)+)/, ' ')
104
+ script = script.gsub(/\s*;\s*/,';')
105
+ script = script.gsub(/\s*:\s*/,':')
106
+ script = script.gsub(/\s*\{\s*/,'{')
107
+ script = script.gsub(/\s*\}\s*/,'}')
108
+ script = script.gsub(/\s*,\s*/,',')
109
+ script.gsub("\t",'');
110
+ end
111
+
112
+ # Replace color values with their shorter equivalent
113
+ #
114
+ # 1. Turn rgb(,,)-colors into #-values
115
+ # 2. Shorten #AABBCC down to #ABC
116
+ # 3. Replace names with their shorter hex-equivalent
117
+ # * white -> #fff
118
+ # * black -> #000
119
+ # 4. Replace #-values with their shorter name
120
+ # * #f00 -> red
121
+ def shorten_colors(style)
122
+ # rgb(50,101,152) to #326598
123
+ style = style.gsub(/rgb\s*\(\s*([0-9,\s]+)\s*\)/) do |match|
124
+ out = '#'
125
+ $1.split(',').each do |num|
126
+ if num.to_i < 16
127
+ out += '0'
128
+ end
129
+ out += num.to_i.to_s(16) # convert to hex
130
+ end
131
+ out
132
+ end
133
+ # #AABBCC to #ABC, keep if preceed by a '='
134
+ style = style.gsub(/([^\"'=\s])(\s*)#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/) do |match|
135
+ out = match
136
+ if ($3.downcase == $4.downcase) and ($5.downcase == $6.downcase) and ($7.downcase == $8.downcase)
137
+ out = $1 + '#' + $3.downcase + $5.downcase + $7.downcase
138
+ end
139
+ out
140
+ end
141
+ # shorten several names to numbers
142
+ style = style.gsub(/:[\s]*white[\s]*;/, ':#fff;')
143
+ style = style.gsub(/:[\s]*white[\s]*\}/, ':#fff}')
144
+ style = style.gsub(/:[\s]*black[\s]*;/, ':#000;')
145
+ style = style.gsub(/:[\s]*black[\s]*\}/, ':#000}')
146
+ # shotern several numbers to names
147
+ style = style.gsub(/:[\s]*#([fF]00|[fF]{2}0000);/, ':red;')
148
+ style = style.gsub(/:[\s]*#([fF]00|[fF]{2}0000)\}/, ':red}')
149
+
150
+ style
151
+ end
152
+
153
+ # Do miscellaneous compression methods on the style
154
+ def do_misc(script)
155
+ # Replace 0(pt,px,em,%) with 0 but only when preceded by : or a white-space
156
+ script = script.gsub(/([\s:]+)(0)(px|em|%|in|cm|mm|pc|pt|ex)/) do |match|
157
+ match.gsub(/(px|em|%|in|cm|mm|pc|pt|ex)/,'')
158
+ end
159
+ # Replace 0 0 0 0; with 0.
160
+ script = script.gsub(':0 0 0 0;', ':0;')
161
+ script = script.gsub(':0 0 0 0}', ':0}')
162
+ script = script.gsub(':0 0 0;', ':0;')
163
+ script = script.gsub(':0 0 0}', ':0}')
164
+ script = script.gsub(':0 0}', ':0}')
165
+ script = script.gsub(':0 0;', ':0;')
166
+ # Replace background-position:0; with background-position:0 0;
167
+ script = script.gsub('background-position:0;', 'background-position:0 0;');
168
+ # Replace 0.6 to .6, but only when preceded by : or a white-space
169
+ script = script.gsub(/[:\s]0+\.(\d+)/) do |match|
170
+ match.sub('0', '') # only first '0' !!
171
+ end
172
+ # Replace ;;;; with ;
173
+ script = script.gsub(/[;]+/, ';')
174
+ # Replace ;} with }
175
+ script = script.gsub(';}', '}')
176
+ # Replace background-color: with background:
177
+ script = script.gsub('background-color:', 'background:')
178
+ # Replace font-weight:normal; with 400, bold with 700
179
+ script = script.gsub(/font-weight[\s]*:[\s]*normal[\s]*;/,'font-weight:400;')
180
+ script = script.gsub(/font-weight[\s]*:[\s]*normal[\s]*\}/,'font-weight:400}')
181
+ script = script.gsub(/font[\s]*:[\s]*normal[\s;\}]*/) do |match|
182
+ match.sub('normal', '400')
183
+ end
184
+ script = script.gsub(/font-weight[\s]*:[\s]*bold[\s]*;/,'font-weight:700;')
185
+ script = script.gsub(/font-weight[\s]*:[\s]*bold[\s]*\}/,'font-weight:700}')
186
+ script = script.gsub(/font[\s]*:[\s]*bold[\s;\}]*/) do |match|
187
+ match.sub('bold', '700')
188
+ end
189
+
190
+ script
191
+ end
192
+
193
+ end
194
+
195
+ end
@@ -126,6 +126,21 @@ module SproutCore
126
126
  @args.first || default_base_class_name
127
127
  end
128
128
 
129
+ # Checks whether the proper file structure exists to generate files
130
+ def file_structure_exists?
131
+ has_path_and_filename? && target_directory_exists?
132
+ end
133
+
134
+ # Checks whether the target directory for a generated file exists
135
+ def target_directory_exists?
136
+ File.exists?("#{Dir.pwd}/clients/#{File.dirname(args[0])}")
137
+ end
138
+
139
+ # Checks that file generation was in the format client_name/file_name
140
+ def has_path_and_filename?
141
+ !(File.dirname(args[0]) == '.')
142
+ end
143
+
129
144
  ###################
130
145
  # Borrowed from Rails NamedBase
131
146
 
@@ -6,26 +6,7 @@ module SproutCore
6
6
 
7
7
  # Captures the resulting value of the block and returns it
8
8
  def capture(*args, &block)
9
- begin
10
- buffer = eval('_buf', block.binding)
11
- rescue
12
- buffer = nil
13
- end
14
-
15
- if buffer.nil?
16
- capture_haml(&block)
17
- else
18
- pos = buffer.length
19
- block.call(*args)
20
-
21
- # get emitted data
22
- data = buffer[pos..-1]
23
-
24
- # remove from buffer
25
- buffer[pos..-1] = ''
26
-
27
- data
28
- end
9
+ self.renderer ? self.renderer.capture(args, &block) : block.call(*args).to_s
29
10
  end
30
11
 
31
12
  # executes the passed block, placing the resulting content into a variable called
@@ -33,10 +14,9 @@ module SproutCore
33
14
  # variable or by calling yield(:area_name)
34
15
  #
35
16
  def content_for(name, &block)
36
- eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)"
17
+ eval "@content_for_#{name} = (@content_for_#{name} || '') + (capture(&block) || '')"
37
18
  end
38
19
 
39
20
  end
40
-
41
21
  end
42
22
  end
@@ -0,0 +1,14 @@
1
+ module SproutCore
2
+ module Helpers
3
+
4
+ module DomIdHelper
5
+ @@tick = 0
6
+
7
+ def dom_id!(type="id")
8
+ @@tick += 1
9
+ return "#{type}_#{(Time.now.to_i + @@tick)}"
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -32,7 +32,9 @@ module SproutCore
32
32
  urls = []
33
33
  all_bundles.each do |b|
34
34
  urls += b.sorted_stylesheet_entries(opts).map { |x| x.cacheable_url }
35
- urls += (b.stylesheet_libs || [])
35
+ end
36
+ all_bundles.each do |b|
37
+ urls += b.stylesheet_libs.reject { |lib| urls.include? lib } if b.stylesheet_libs
36
38
  end
37
39
 
38
40
  # Convert to HTML and return
@@ -73,7 +75,9 @@ module SproutCore
73
75
  urls = []
74
76
  all_bundles.each do |b|
75
77
  urls += b.sorted_javascript_entries(opts).map { |x| x.cacheable_url }
76
- urls += (b.javascript_libs || [])
78
+ end
79
+ all_bundles.each do |b|
80
+ urls += b.javascript_libs.reject { |lib| urls.include? lib } if b.javascript_libs
77
81
  end
78
82
 
79
83
  # Convert to HTML and return
@@ -26,7 +26,7 @@ module SproutCore
26
26
  # is equivalent to using:
27
27
  # <%= "hello" %>
28
28
  def concat(string, binding)
29
- eval('_buf', binding) << string
29
+ renderer.concat(string, binding)
30
30
  end
31
31
 
32
32
  # If +text+ is longer than +length+, +text+ will be truncated to the length of
@@ -15,8 +15,8 @@
15
15
 
16
16
  # Load Merb if it is available
17
17
  begin
18
- gem('merb-core', '>= 0.9.1', '< 0.9.5')
18
+ gem('merb-core', '>= 0.9.1')
19
19
  Dir.glob(File.join(File.dirname(__FILE__),'merb','**','*.rb')).each { |x| require(x) }
20
20
  rescue LoadError
21
- puts "WARNING: sproutcore/merb requires Merb 0.9.1 through 0.9.4. Earlier and later releases are not supported. Module was not loaded."
21
+ puts "WARNING: sproutcore/merb requires Merb 0.9.1 or later. Earlier releases are not supported. Module was not loaded."
22
22
  end
@@ -0,0 +1,43 @@
1
+ module Sproutcore
2
+ module Renderers
3
+
4
+ class Erubis
5
+ def initialize(html_context)
6
+ @html_context = html_context
7
+ end
8
+
9
+ def compile(input)
10
+ require 'erubis'
11
+ ::Erubis::Eruby.new.convert(input)
12
+ end
13
+
14
+ def concat(string, binding)
15
+ eval('_buf', binding) << string
16
+ end
17
+
18
+ def capture(*args, &block)
19
+ begin
20
+ buffer = eval('_buf', block.binding)
21
+ rescue
22
+ buffer = nil
23
+ end
24
+
25
+ if buffer.nil?
26
+ block.call(*args).to_s
27
+ else
28
+ pos = buffer.length
29
+ block.call(*args)
30
+
31
+ # get emitted data
32
+ data = buffer[pos..-1]
33
+
34
+ # remove from buffer
35
+ buffer[pos..-1] = ''
36
+
37
+ data
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end