sproutcore 0.9.17 → 0.9.18

Sign up to get free protection for your applications and to get access to all the features.
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