sproutcore 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (270) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +269 -0
  4. data/README.txt +67 -0
  5. data/Rakefile +4 -0
  6. data/app_generators/sproutcore/USAGE +5 -0
  7. data/app_generators/sproutcore/sproutcore_generator.rb +66 -0
  8. data/app_generators/sproutcore/templates/README +77 -0
  9. data/app_generators/sproutcore/templates/environment.yml +4 -0
  10. data/bin/sc-build +145 -0
  11. data/bin/sc-gen +24 -0
  12. data/bin/sc-server +63 -0
  13. data/bin/sproutcore +21 -0
  14. data/clients/sc_docs/controllers/docs.js +118 -0
  15. data/clients/sc_docs/core.js +19 -0
  16. data/clients/sc_docs/english.lproj/body.css +159 -0
  17. data/clients/sc_docs/english.lproj/body.rhtml +33 -0
  18. data/clients/sc_docs/english.lproj/controls.css +0 -0
  19. data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
  20. data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
  21. data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
  22. data/clients/sc_docs/english.lproj/images/indicator.gif +0 -0
  23. data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
  24. data/clients/sc_docs/english.lproj/no_docs.rhtml +7 -0
  25. data/clients/sc_docs/english.lproj/strings.js +14 -0
  26. data/clients/sc_docs/english.lproj/warning.rhtml +6 -0
  27. data/clients/sc_docs/fixtures/doc.js +11 -0
  28. data/clients/sc_docs/main.js +21 -0
  29. data/clients/sc_docs/models/doc.js +9 -0
  30. data/clients/sc_docs/tests/controllers/docs.rhtml +21 -0
  31. data/clients/sc_docs/tests/models/doc.rhtml +21 -0
  32. data/clients/sc_docs/tests/views/doc_frame.rhtml +21 -0
  33. data/clients/sc_docs/tests/views/doc_label_view.rhtml +21 -0
  34. data/clients/sc_docs/views/doc_frame.js +33 -0
  35. data/clients/sc_docs/views/doc_label.js +20 -0
  36. data/clients/sc_test_runner/controllers/runner.js +175 -0
  37. data/clients/sc_test_runner/core.js +19 -0
  38. data/clients/sc_test_runner/english.lproj/body.css +151 -0
  39. data/clients/sc_test_runner/english.lproj/body.rhtml +35 -0
  40. data/clients/sc_test_runner/english.lproj/controls.css +0 -0
  41. data/clients/sc_test_runner/english.lproj/icons/small/next.png +0 -0
  42. data/clients/sc_test_runner/english.lproj/icons/small/reset.png +0 -0
  43. data/clients/sc_test_runner/english.lproj/images/gradients.png +0 -0
  44. data/clients/sc_test_runner/english.lproj/images/indicator.gif +0 -0
  45. data/clients/sc_test_runner/english.lproj/images/toolbar.png +0 -0
  46. data/clients/sc_test_runner/english.lproj/no_tests.rhtml +6 -0
  47. data/clients/sc_test_runner/english.lproj/strings.js +14 -0
  48. data/clients/sc_test_runner/english.lproj/warning.rhtml +6 -0
  49. data/clients/sc_test_runner/fixtures/test.js +12 -0
  50. data/clients/sc_test_runner/main.js +26 -0
  51. data/clients/sc_test_runner/models/test.js +11 -0
  52. data/clients/sc_test_runner/views/runner_frame.js +72 -0
  53. data/clients/sc_test_runner/views/test_label.js +20 -0
  54. data/config/hoe.rb +70 -0
  55. data/config/requirements.rb +17 -0
  56. data/environment.yml +9 -0
  57. data/frameworks/prototype/prototype.js +4186 -0
  58. data/frameworks/sproutcore/Core.js +378 -0
  59. data/frameworks/sproutcore/README +3 -0
  60. data/frameworks/sproutcore/controllers/array.js +236 -0
  61. data/frameworks/sproutcore/controllers/collection.js +305 -0
  62. data/frameworks/sproutcore/controllers/controller.js +323 -0
  63. data/frameworks/sproutcore/controllers/object.js +372 -0
  64. data/frameworks/sproutcore/drag/drag.js +549 -0
  65. data/frameworks/sproutcore/drag/drag_data_source.js +32 -0
  66. data/frameworks/sproutcore/drag/drag_source.js +64 -0
  67. data/frameworks/sproutcore/drag/drop_target.js +153 -0
  68. data/frameworks/sproutcore/english.lproj/blank.gif +0 -0
  69. data/frameworks/sproutcore/english.lproj/buttons.css +589 -0
  70. data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
  71. data/frameworks/sproutcore/english.lproj/inline_text_editor.css +21 -0
  72. data/frameworks/sproutcore/english.lproj/menu.css +121 -0
  73. data/frameworks/sproutcore/english.lproj/panels/background-fat.jpg +0 -0
  74. data/frameworks/sproutcore/english.lproj/panels/background-thin.jpg +0 -0
  75. data/frameworks/sproutcore/english.lproj/panels/bottom-edge.png +0 -0
  76. data/frameworks/sproutcore/english.lproj/panels/bottom-left-corner.png +0 -0
  77. data/frameworks/sproutcore/english.lproj/panels/bottom-right-corner.png +0 -0
  78. data/frameworks/sproutcore/english.lproj/panels/left-edge.png +0 -0
  79. data/frameworks/sproutcore/english.lproj/panels/overlay.png +0 -0
  80. data/frameworks/sproutcore/english.lproj/panels/right-edge.png +0 -0
  81. data/frameworks/sproutcore/english.lproj/panels/top-edge.png +0 -0
  82. data/frameworks/sproutcore/english.lproj/panels/top-left-corner.png +0 -0
  83. data/frameworks/sproutcore/english.lproj/panels/top-right-corner.png +0 -0
  84. data/frameworks/sproutcore/english.lproj/panes.css +155 -0
  85. data/frameworks/sproutcore/english.lproj/picker.css +22 -0
  86. data/frameworks/sproutcore/english.lproj/strings.js +15 -0
  87. data/frameworks/sproutcore/english.lproj/tab.css +23 -0
  88. data/frameworks/sproutcore/english.lproj/tests.css +67 -0
  89. data/frameworks/sproutcore/english.lproj/theme.css +77 -0
  90. data/frameworks/sproutcore/foundation/animator.js +670 -0
  91. data/frameworks/sproutcore/foundation/application.js +199 -0
  92. data/frameworks/sproutcore/foundation/array.js +348 -0
  93. data/frameworks/sproutcore/foundation/benchmark.js +211 -0
  94. data/frameworks/sproutcore/foundation/binding.js +384 -0
  95. data/frameworks/sproutcore/foundation/date.js +357 -0
  96. data/frameworks/sproutcore/foundation/error.js +39 -0
  97. data/frameworks/sproutcore/foundation/input_manager.js +153 -0
  98. data/frameworks/sproutcore/foundation/json.js +296 -0
  99. data/frameworks/sproutcore/foundation/mock.js +42 -0
  100. data/frameworks/sproutcore/foundation/node_descriptor.js +56 -0
  101. data/frameworks/sproutcore/foundation/object.js +777 -0
  102. data/frameworks/sproutcore/foundation/observable.js +451 -0
  103. data/frameworks/sproutcore/foundation/page.js +63 -0
  104. data/frameworks/sproutcore/foundation/path_module.js +413 -0
  105. data/frameworks/sproutcore/foundation/responder.js +310 -0
  106. data/frameworks/sproutcore/foundation/routes.js +371 -0
  107. data/frameworks/sproutcore/foundation/run_loop.js +21 -0
  108. data/frameworks/sproutcore/foundation/server.js +491 -0
  109. data/frameworks/sproutcore/foundation/set.js +96 -0
  110. data/frameworks/sproutcore/foundation/string.js +149 -0
  111. data/frameworks/sproutcore/foundation/undo_manager.js +186 -0
  112. data/frameworks/sproutcore/foundation/unittest.js +622 -0
  113. data/frameworks/sproutcore/foundation/utils.js +61 -0
  114. data/frameworks/sproutcore/globals/panels.js +182 -0
  115. data/frameworks/sproutcore/globals/popups.js +60 -0
  116. data/frameworks/sproutcore/globals/window.js +381 -0
  117. data/frameworks/sproutcore/lib/index.rhtml +66 -0
  118. data/frameworks/sproutcore/models/collection.js +395 -0
  119. data/frameworks/sproutcore/models/record.js +622 -0
  120. data/frameworks/sproutcore/models/store.js +295 -0
  121. data/frameworks/sproutcore/panes/dialog.js +16 -0
  122. data/frameworks/sproutcore/panes/manager.js +164 -0
  123. data/frameworks/sproutcore/panes/menu.js +45 -0
  124. data/frameworks/sproutcore/panes/overlay.js +231 -0
  125. data/frameworks/sproutcore/panes/pane.js +90 -0
  126. data/frameworks/sproutcore/panes/panel.js +19 -0
  127. data/frameworks/sproutcore/panes/picker.js +45 -0
  128. data/frameworks/sproutcore/tests/controllers/array.rhtml +86 -0
  129. data/frameworks/sproutcore/tests/controllers/controller.rhtml +273 -0
  130. data/frameworks/sproutcore/tests/controllers/object.rhtml +327 -0
  131. data/frameworks/sproutcore/tests/foundation/application.rhtml +125 -0
  132. data/frameworks/sproutcore/tests/foundation/array.rhtml +221 -0
  133. data/frameworks/sproutcore/tests/foundation/object.rhtml +69 -0
  134. data/frameworks/sproutcore/tests/globals/window.rhtml +45 -0
  135. data/frameworks/sproutcore/tests/panes/pane.rhtml +88 -0
  136. data/frameworks/sproutcore/tests/views/collection.rhtml +137 -0
  137. data/frameworks/sproutcore/tests/views/popup_button.rhtml +115 -0
  138. data/frameworks/sproutcore/tests/views/text_field.rhtml +37 -0
  139. data/frameworks/sproutcore/validators/credit_card.js +92 -0
  140. data/frameworks/sproutcore/validators/date.js +36 -0
  141. data/frameworks/sproutcore/validators/email.js +29 -0
  142. data/frameworks/sproutcore/validators/not_empty.js +24 -0
  143. data/frameworks/sproutcore/validators/number.js +55 -0
  144. data/frameworks/sproutcore/validators/password.js +78 -0
  145. data/frameworks/sproutcore/validators/validator.js +304 -0
  146. data/frameworks/sproutcore/views/button.js +425 -0
  147. data/frameworks/sproutcore/views/checkbox_field.js +30 -0
  148. data/frameworks/sproutcore/views/collection.js +1521 -0
  149. data/frameworks/sproutcore/views/container.js +62 -0
  150. data/frameworks/sproutcore/views/error_explanation.js +45 -0
  151. data/frameworks/sproutcore/views/field.js +214 -0
  152. data/frameworks/sproutcore/views/filter_button.js +29 -0
  153. data/frameworks/sproutcore/views/form.js +591 -0
  154. data/frameworks/sproutcore/views/image.js +141 -0
  155. data/frameworks/sproutcore/views/inline_text_editor.js +96 -0
  156. data/frameworks/sproutcore/views/label.js +176 -0
  157. data/frameworks/sproutcore/views/menu_item.js +90 -0
  158. data/frameworks/sproutcore/views/pagination.js +54 -0
  159. data/frameworks/sproutcore/views/popup_button.js +86 -0
  160. data/frameworks/sproutcore/views/popup_menu.js +137 -0
  161. data/frameworks/sproutcore/views/progress.js +100 -0
  162. data/frameworks/sproutcore/views/radio_field.js +107 -0
  163. data/frameworks/sproutcore/views/radio_group.js +48 -0
  164. data/frameworks/sproutcore/views/segmented.js +80 -0
  165. data/frameworks/sproutcore/views/select_field.js +272 -0
  166. data/frameworks/sproutcore/views/spinner.js +11 -0
  167. data/frameworks/sproutcore/views/tab.js +126 -0
  168. data/frameworks/sproutcore/views/text_field.js +179 -0
  169. data/frameworks/sproutcore/views/textarea_field.js +14 -0
  170. data/frameworks/sproutcore/views/toolbar.js +29 -0
  171. data/frameworks/sproutcore/views/view.js +1389 -0
  172. data/frameworks/sproutcore/views/workspace.js +170 -0
  173. data/generators/client/README +3 -0
  174. data/generators/client/USAGE +12 -0
  175. data/generators/client/client_generator.rb +53 -0
  176. data/generators/client/templates/core.js +19 -0
  177. data/generators/client/templates/english.lproj/body.css +0 -0
  178. data/generators/client/templates/english.lproj/body.rhtml +3 -0
  179. data/generators/client/templates/english.lproj/controls.css +0 -0
  180. data/generators/client/templates/english.lproj/strings.js +14 -0
  181. data/generators/client/templates/main.js +37 -0
  182. data/generators/controller/USAGE +16 -0
  183. data/generators/controller/controller_generator.rb +51 -0
  184. data/generators/controller/templates/controller.js +21 -0
  185. data/generators/controller/templates/test.rhtml +21 -0
  186. data/generators/framework/README +7 -0
  187. data/generators/framework/USAGE +12 -0
  188. data/generators/framework/framework_generator.rb +53 -0
  189. data/generators/framework/templates/core.js +20 -0
  190. data/generators/framework/templates/english.lproj/body.css +0 -0
  191. data/generators/framework/templates/english.lproj/body.rhtml +3 -0
  192. data/generators/framework/templates/english.lproj/controls.css +0 -0
  193. data/generators/framework/templates/english.lproj/strings.js +14 -0
  194. data/generators/language/USAGE +16 -0
  195. data/generators/language/language_generator.rb +47 -0
  196. data/generators/language/templates/strings.js +10 -0
  197. data/generators/model/USAGE +24 -0
  198. data/generators/model/model_generator.rb +55 -0
  199. data/generators/model/templates/fixture.js +11 -0
  200. data/generators/model/templates/model.js +20 -0
  201. data/generators/model/templates/test.rhtml +21 -0
  202. data/generators/test/USAGE +16 -0
  203. data/generators/test/templates/test.rhtml +21 -0
  204. data/generators/test/test_generator.rb +47 -0
  205. data/generators/view/USAGE +16 -0
  206. data/generators/view/templates/test.rhtml +21 -0
  207. data/generators/view/templates/view.js +20 -0
  208. data/generators/view/view_generator.rb +51 -0
  209. data/jsdoc/README.txt +119 -0
  210. data/jsdoc/app/DocFile.js +137 -0
  211. data/jsdoc/app/DocTag.js +110 -0
  212. data/jsdoc/app/Doclet.js +63 -0
  213. data/jsdoc/app/Dumper.js +143 -0
  214. data/jsdoc/app/JsDoc.js +103 -0
  215. data/jsdoc/app/JsHilite.js +45 -0
  216. data/jsdoc/app/JsIO.js +163 -0
  217. data/jsdoc/app/JsParse.js +385 -0
  218. data/jsdoc/app/JsPlate.js +130 -0
  219. data/jsdoc/app/JsTestrun.js +129 -0
  220. data/jsdoc/app/JsToke.js +564 -0
  221. data/jsdoc/app/Symbol.js +298 -0
  222. data/jsdoc/app/Transformer.js +14 -0
  223. data/jsdoc/app/Util.js +97 -0
  224. data/jsdoc/app/js.jar +0 -0
  225. data/jsdoc/app/run.js +144 -0
  226. data/jsdoc/plugins/min.js +316 -0
  227. data/jsdoc/plugins/strip.js +20 -0
  228. data/jsdoc/templates/sproutcore/class.tmpl +438 -0
  229. data/jsdoc/templates/sproutcore/default.css +241 -0
  230. data/jsdoc/templates/sproutcore/index.html +13 -0
  231. data/jsdoc/templates/sproutcore/index.tmpl +21 -0
  232. data/jsdoc/templates/sproutcore/prototype.js +4186 -0
  233. data/jsdoc/templates/sproutcore/publish.js +236 -0
  234. data/jsdoc/templates/sproutcore/splash.html +7 -0
  235. data/lib/sproutcore/build_tools/html_builder.rb +88 -0
  236. data/lib/sproutcore/build_tools/resource_builder.rb +194 -0
  237. data/lib/sproutcore/build_tools.rb +44 -0
  238. data/lib/sproutcore/bundle.rb +517 -0
  239. data/lib/sproutcore/bundle_manifest.rb +397 -0
  240. data/lib/sproutcore/generator_helper.rb +170 -0
  241. data/lib/sproutcore/helpers/capture_helper.rb +42 -0
  242. data/lib/sproutcore/helpers/static_helper.rb +80 -0
  243. data/lib/sproutcore/helpers/tag_helper.rb +110 -0
  244. data/lib/sproutcore/helpers/text_helper.rb +336 -0
  245. data/lib/sproutcore/helpers.rb +3 -0
  246. data/lib/sproutcore/jsdoc.rb +40 -0
  247. data/lib/sproutcore/jsmin.rb +247 -0
  248. data/lib/sproutcore/library.rb +258 -0
  249. data/lib/sproutcore/merb/bundle_controller.rb +179 -0
  250. data/lib/sproutcore/merb/router.rb +43 -0
  251. data/lib/sproutcore/merb.rb +27 -0
  252. data/lib/sproutcore/version.rb +9 -0
  253. data/lib/sproutcore/view_helpers/button_views.rb +302 -0
  254. data/lib/sproutcore/view_helpers/core_views.rb +284 -0
  255. data/lib/sproutcore/view_helpers/form_views.rb +258 -0
  256. data/lib/sproutcore/view_helpers/menu_views.rb +94 -0
  257. data/lib/sproutcore/view_helpers.rb +628 -0
  258. data/lib/sproutcore.rb +30 -0
  259. data/script/destroy +14 -0
  260. data/script/generate +14 -0
  261. data/script/txt2html +74 -0
  262. data/setup.rb +1585 -0
  263. data/spec/spec.opts +1 -0
  264. data/spec/spec_helper.rb +7 -0
  265. data/spec/sproutcore_spec.rb +11 -0
  266. data/tasks/deployment.rake +34 -0
  267. data/tasks/environment.rake +7 -0
  268. data/tasks/rspec.rake +21 -0
  269. data/tasks/website.rake +17 -0
  270. metadata +365 -0
@@ -0,0 +1,397 @@
1
+ require 'yaml'
2
+
3
+ module SproutCore
4
+
5
+ # A Bundle Manifest describes all of the resources in a bundle, including mapping their
6
+ # source paths, destination paths, and urls.
7
+ #
8
+ # A Bundle will create a manifest for every language you request from it. If you invoke
9
+ # reload! on the bundle, it will dispose of its manifests and rebuild them.
10
+ #
11
+ class BundleManifest
12
+
13
+ CACHED_TYPES = [:javascript, :stylesheet, :fixture, :test]
14
+ SYMLINKED_TYPES = [:resource]
15
+
16
+ attr_reader :bundle, :language
17
+
18
+ def initialize(bundle, language)
19
+ @bundle = bundle
20
+ @language = language
21
+ @entries_by_type = {} # entries by type
22
+ @entries_by_filename = {} # entries by files
23
+ build!
24
+ end
25
+
26
+ # ==== Returns
27
+ # All entries as an array
28
+ #
29
+ def entries; @entries_by_filename.values; end
30
+
31
+ # ==== Returns
32
+ # All of the entries matching the specified type
33
+ #
34
+ def entries_for(resource_type)
35
+ @entries_by_type[resource_type] || []
36
+ end
37
+
38
+ # ==== Returns
39
+ # Entry for the resource with the specified name
40
+ #
41
+ def entry_for(resource_name)
42
+ @entries_by_filename[resource_name] || nil
43
+ end
44
+
45
+ def to_a; @entries_by_filename.values.map { |x| x.to_hash }; end
46
+ def to_hash; @entries_by_type; end
47
+ def to_s; @entries_by_filename.to_yaml; end
48
+
49
+ protected
50
+
51
+ # Builds a manifest for the bundle and the specified language
52
+ def build!
53
+
54
+ # STEP 1: Catalog all of the files in the project, including the target language
55
+ # and the default language. This will filter out resources not used in this language.
56
+ entries = catalog_entries
57
+
58
+ # STEP 2: Combine the HTML file paths into a single entry, unless this is a framework
59
+ if (working = entries[:html]) && working.size > 0
60
+ if bundle.can_have_html?
61
+ working << build_entry_for('index.html', :html, working)
62
+ else
63
+ working.each { |x| x.hidden = true }
64
+ end
65
+ end
66
+
67
+ # STEP 3: If in development build mode:
68
+ if bundle.build_mode == :development
69
+
70
+ # a. Merge fixture types into JS types & tests
71
+ unless entries[:fixture].nil?
72
+ entries[:javascript] = (entries[:javascript] || []) + entries[:fixture]
73
+ end
74
+
75
+ # b. Rewrite all of the JS & CSS file paths and URLs to point to cached versions
76
+ # (Cached versions are written to _cache/filename-ctime.ext)
77
+ (entries[:javascript] ||= []).each do | entry |
78
+ setup_timestamp_token(entry)
79
+ end
80
+
81
+ (entries[:stylesheet] ||= []).each do | entry |
82
+ setup_timestamp_token(entry)
83
+ end
84
+
85
+ # c. Rewrite the URLs for all other resources to go through the _src symlink
86
+ ##-----> Already done build_entry_for()
87
+
88
+
89
+ # STEP 4: If in production mode, remove extra assets that should never be built
90
+ else
91
+
92
+ # c. Remove the entries for anything that is not JS, CSS, HTML or Resource
93
+ entries.delete(:fixture)
94
+ entries.delete(:test)
95
+ end
96
+
97
+ # STEP 5: Add entry for javascript.js & stylesheet.js. If in production mode, set
98
+ # these to visible and hide the composite. If in dev mode, do the opposite.
99
+
100
+ hide_composite = (bundle.build_mode != :development)
101
+
102
+ # a. Combine the JS file paths into a single entry for the javascript.js
103
+ if (working = entries[:javascript]) && working.size>0
104
+ entry = build_entry_for('javascript.js', :javascript, working, hide_composite)
105
+ entry.hidden = true unless hide_composite
106
+ working << entry
107
+ end
108
+
109
+ # b. Combine the CSS file paths into a single entry for the stylesheet.css
110
+ if (working = entries[:stylesheet]) && working.size>0
111
+ entry = build_entry_for('stylesheet.css', :stylesheet, working, hide_composite)
112
+ entry.hidden = true unless hide_composite
113
+ working << entry
114
+ end
115
+
116
+ # Save entries into hashes
117
+ @entries_by_type = entries
118
+ @entries_by_filenames = {}
119
+ entries.values.flatten.each { |entry| @entries_by_filename[entry.filename] = entry }
120
+ end
121
+
122
+ # Build a catalog of entries for this manifest. This will simply filter out the files
123
+ # that don't actually belong in the current language
124
+ def catalog_entries
125
+
126
+ # Entries arranged by resource filename
127
+ entries = {}
128
+ default_lproj_entries = {}
129
+ target_lproj_entries = {}
130
+
131
+ # Get the name of the lproj dirs for the default and current languages
132
+ default_lproj = bundle.lproj_for(bundle.preferred_language)
133
+ target_lproj = bundle.lproj_for(language)
134
+
135
+ # Any files living in the two lproj dirs will be shunted off into these arrays
136
+ # and processed later to make sure we process them in the right order
137
+ default_lproj_files = []
138
+ target_lproj_files = []
139
+
140
+ # Now, glob all the files and sort through them
141
+ old_wd = Dir.getwd; Dir.chdir(bundle.source_root)
142
+ Dir.glob(File.join('**','*')).each do | src_path |
143
+
144
+ # Get source type. Skip any without a useful type
145
+ next if (src_type = type_of(src_path)) == :skip
146
+
147
+ # Get current lproj (if there is one). Skip if not default or current
148
+ if current_lproj = src_path.match(/^([^\/]+\.lproj)\//).to_a[1]
149
+ next if (current_lproj != default_lproj) && (current_lproj != target_lproj)
150
+ end
151
+
152
+ # OK, pass all of our validations. Go ahead and build an entry for this
153
+ # Add entry to list of entries for appropriate lproj if localized
154
+ entry = build_entry_for(src_path, src_type)
155
+ case current_lproj
156
+ when default_lproj
157
+ default_lproj_entries[entry.filename] = entry
158
+ when target_lproj
159
+ target_lproj_entries[entry.filename] = entry
160
+ else
161
+ entries[entry.filename] = entry
162
+ end
163
+ end
164
+ Dir.chdir(old_wd) # restore wd
165
+
166
+ # Now, new in default and target lproj entries. This will overwrite entries that exist
167
+ # in both places.
168
+ entries.merge!(default_lproj_entries)
169
+ entries.merge!(target_lproj_entries)
170
+
171
+ # Finally, entries will need to be grouped by type to allow further processing.
172
+ ret = {}
173
+ entries.values.each { |entry| (ret[entry.type] ||= []) << entry }
174
+ return ret
175
+ end
176
+
177
+ # Determines the type for this manifest entry. Should be one of:
178
+ #
179
+ # stylesheet:: a CSS file
180
+ # javascript:: a JavaScript file
181
+ # html:: an HTML file
182
+ #
183
+ # test:: a test file (inside of /tests)
184
+ # fixture:: a fixture file (inside of /fixtures)
185
+ #
186
+ # resource:: any other file inside an lproj dir
187
+ # skip:: any other file outside of an lproj dir directories
188
+ #
189
+ # If you need to handle additional types of resources in the future, this is the place to
190
+ # put it.
191
+ #
192
+ # ==== Params
193
+ #
194
+ # src_path:: The source path, relative to source_root.
195
+ #
196
+ def type_of(src_path)
197
+ return :skip if File.directory?(src_path)
198
+ case src_path
199
+ when /^tests\/.+/
200
+ :test
201
+ when /^fixtures\/.+/
202
+ :fixture
203
+ when /.html$/
204
+ :html
205
+ when /.rhtml$/
206
+ :html
207
+ when /.html.erb$/
208
+ :html
209
+ when /.css$/
210
+ :stylesheet
211
+ when /.js$/
212
+ :javascript
213
+ when /\.lproj\/.+/
214
+ :resource
215
+ else
216
+ :skip
217
+ end
218
+ end
219
+
220
+ # Build an entry for the resource at the named src_path (relative to the source_root)
221
+ # This should assume we are in going to simply build each resource into the build root
222
+ # without combining files, but not using our _src symlink magic.
223
+ def build_entry_for(src_path, src_type, composite=nil, hide_composite = true)
224
+ ret = ManifestEntry.new
225
+ ret.ext = File.extname(src_path)[1..-1] || '' # easy stuff
226
+ ret.type = src_type
227
+ ret.original_path = src_path
228
+ ret.hidden = false
229
+ ret.language = language
230
+
231
+ # the filename is the src_path less any lproj in the front
232
+ ret.filename = src_path.gsub(/^[^\/]+.lproj\//,'')
233
+
234
+ # the source path is just the combine source root + the path
235
+ ret.source_path = (composite.nil?) ? File.join(bundle.source_root, src_path) : nil
236
+
237
+ # set the composite property. The passed in array should contain other entries
238
+ # if hide_composite is true, then hide the composite items as well
239
+ unless composite.nil? || composite.size == 0
240
+ composite.each { |x| x.hidden = true } if hide_composite
241
+ ret.composite = composite.map { |x| x.filename }
242
+ end
243
+
244
+ # The build path is the build_root + the filename
245
+ # The URL is the url root + the language code + filename
246
+ # also add in _cache or _sym in certain cases. This is just more efficient than doing
247
+ # it later.
248
+ url_root = (src_path == 'index.html') ? bundle.index_root : bundle.url_root
249
+ cache_link = nil
250
+ use_symlink =false
251
+
252
+ # Note: you can only access real resources via the cache. If the entry is a composite
253
+ # then do not go through cache.
254
+ if (bundle.build_mode == :development) && composite.nil?
255
+ cache_link = '_cache' if CACHED_TYPES.include?(src_type)
256
+ use_symlink = true if SYMLINKED_TYPES.include?(src_type)
257
+ end
258
+
259
+ ret.use_symlink = use_symlink
260
+ if use_symlink
261
+ ret.build_path = File.join(bundle.build_root, '_src', src_path)
262
+ ret.url = [url_root, '_src', src_path].join('/')
263
+ else
264
+ ret.build_path = File.join(*[bundle.build_root, language.to_s, cache_link, ret.filename].compact)
265
+ ret.url = [url_root, language.to_s, cache_link, ret.filename].compact.join('/')
266
+ end
267
+
268
+ # Done.
269
+ return ret
270
+ end
271
+
272
+ # Lookup the timestamp on the source path and interpolate that into the filename URL.
273
+ # also insert the _cache element.
274
+ def setup_timestamp_token(entry)
275
+ timestamp = entry.timestamp
276
+ extname = File.extname(entry.url)
277
+ entry.url = entry.url.gsub(/#{extname}$/,"-#{timestamp}#{extname}") # add timestamp
278
+
279
+ extname = File.extname(entry.build_path)
280
+ entry.build_path = entry.build_path.gsub(/#{extname}$/,"-#{timestamp}#{extname}") # add timestamp
281
+
282
+ puts "\n\n*setup_timestamp_token(#{entry.url} - #{entry.timestamp})" if /docs-/ =~ entry.url
283
+ end
284
+ end
285
+
286
+ # describes a single entry in the Manifest:
287
+ #
288
+ # filename:: path relative to the built language (e.g. sproutcore/en) less file extension
289
+ # ext:: the file extension
290
+ # source_path:: absolute paths into source that will comprise this resource
291
+ # url:: the url that should be used to reference this resource
292
+ # build_path:: absolute path to the compiled resource
293
+ # type:: the top-level category
294
+ # original_path:: save the original path used to build this entry
295
+ # hidden:: if true, this entry is needed internally, but otherwise should not be used
296
+ # use_symlink:: if true, then this entry should be handled via the build symlink
297
+ # language:: the language in use when this entry was created
298
+ # composite:: If set, this will contain the filenames of other resources that should be
299
+ # combined to form this resource.
300
+ #
301
+ class ManifestEntry < Struct.new(:filename, :ext, :source_path, :url, :build_path, :type, :original_path, :hidden, :use_symlink, :language, :composite)
302
+ def to_hash
303
+ ret = {}
304
+ self.members.zip(self.values).each { |p| ret[p[0]] = p[1] }
305
+ ret.symbolize_keys
306
+ end
307
+
308
+ def hidden?; !!hidden; end
309
+ def use_symlink?; !!use_symlink; end
310
+ def composite?; !!composite; end
311
+
312
+ # Returns true if this entry can be cached even in development mode. Composite resources
313
+ # and tests need to be regenerated whenever you get this.
314
+ def cacheable?
315
+ !composite? && (type != :test)
316
+ end
317
+
318
+ # Returns the mtime of the source_path. If this entry is a composite or if the source
319
+ # file does not exist, returns nil
320
+ def source_path_mtime
321
+ (composite? || !File.exists?(source_path)) ? nil : File.mtime(source_path)
322
+ end
323
+
324
+ # Returns a timestamp based on the source_path_mtime. If source_path_mtime is nil, always
325
+ # returns a new timestamp
326
+ def timestamp
327
+ (source_path_mtime || Time.now).to_i.to_s
328
+ end
329
+
330
+ # Returns the content type for this entry. Based on a set of MIME_TYPES borrowed from Rack
331
+ def content_type
332
+ MIME_TYPES[File.extname(build_path)[1..-1]] || 'text/plain'
333
+ end
334
+
335
+ # :stopdoc:
336
+ # From WEBrick.
337
+ MIME_TYPES = {
338
+ "ai" => "application/postscript",
339
+ "asc" => "text/plain",
340
+ "avi" => "video/x-msvideo",
341
+ "bin" => "application/octet-stream",
342
+ "bmp" => "image/bmp",
343
+ "class" => "application/octet-stream",
344
+ "cer" => "application/pkix-cert",
345
+ "crl" => "application/pkix-crl",
346
+ "crt" => "application/x-x509-ca-cert",
347
+ #"crl" => "application/x-pkcs7-crl",
348
+ "css" => "text/css",
349
+ "dms" => "application/octet-stream",
350
+ "doc" => "application/msword",
351
+ "dvi" => "application/x-dvi",
352
+ "eps" => "application/postscript",
353
+ "etx" => "text/x-setext",
354
+ "exe" => "application/octet-stream",
355
+ "gif" => "image/gif",
356
+ "htm" => "text/html",
357
+ "html" => "text/html",
358
+ "rhtml" => "text/html",
359
+ "jpe" => "image/jpeg",
360
+ "jpeg" => "image/jpeg",
361
+ "jpg" => "image/jpeg",
362
+ "lha" => "application/octet-stream",
363
+ "lzh" => "application/octet-stream",
364
+ "mov" => "video/quicktime",
365
+ "mpe" => "video/mpeg",
366
+ "mpeg" => "video/mpeg",
367
+ "mpg" => "video/mpeg",
368
+ "pbm" => "image/x-portable-bitmap",
369
+ "pdf" => "application/pdf",
370
+ "pgm" => "image/x-portable-graymap",
371
+ "png" => "image/png",
372
+ "pnm" => "image/x-portable-anymap",
373
+ "ppm" => "image/x-portable-pixmap",
374
+ "ppt" => "application/vnd.ms-powerpoint",
375
+ "ps" => "application/postscript",
376
+ "qt" => "video/quicktime",
377
+ "ras" => "image/x-cmu-raster",
378
+ "rb" => "text/plain",
379
+ "rd" => "text/plain",
380
+ "rtf" => "application/rtf",
381
+ "sgm" => "text/sgml",
382
+ "sgml" => "text/sgml",
383
+ "tif" => "image/tiff",
384
+ "tiff" => "image/tiff",
385
+ "txt" => "text/plain",
386
+ "xbm" => "image/x-xbitmap",
387
+ "xls" => "application/vnd.ms-excel",
388
+ "xml" => "text/xml",
389
+ "xpm" => "image/x-xpixmap",
390
+ "xwd" => "image/x-xwindowdump",
391
+ "zip" => "application/zip",
392
+ }
393
+ # :startdoc:
394
+
395
+ end
396
+
397
+ end
@@ -0,0 +1,170 @@
1
+
2
+ module SproutCore
3
+
4
+ # You can use these methods basically copy the contents of your templates
5
+ # directory into a target location.
6
+ module GeneratorHelper
7
+
8
+ def apply_template(m, root_dir)
9
+ m.directory root_dir
10
+
11
+ template_directories.each do |d|
12
+ m.directory File.join(root_dir,d)
13
+ end
14
+
15
+ template_files.each do |f|
16
+ f_out = File.join(root_dir,f)
17
+ if f =~ /\.rhtml$/
18
+ m.file f, f_out
19
+ else
20
+ m.template f, f_out
21
+ end
22
+ end
23
+ end
24
+
25
+ def template_directories
26
+ template_files(true)
27
+ end
28
+
29
+ def template_files(directories=false, cur_dir=nil,cur_base=nil)
30
+ if cur_dir.nil?
31
+ cur_dir = File.join(spec.path,'templates')
32
+ cur_base = ''
33
+ end
34
+
35
+ ret = []
36
+ Dir.foreach(cur_dir) do |x|
37
+ next if (x == '.' || x == '..' || x == '.svn')
38
+ base = cur_base + x
39
+ dir = File.join(cur_dir,x)
40
+
41
+ if File.directory?(dir)
42
+ ret << (cur_base + x) if directories
43
+ ret += template_files(directories, dir, base + "/")
44
+ else
45
+ ret << (cur_base + x) if !directories
46
+ end
47
+ end
48
+
49
+ return ret
50
+ end
51
+
52
+ def build_client_directories(m, path)
53
+ parts = File.dirname(path).split('/')
54
+ cpath = []
55
+ parts.each do |p|
56
+ cpath << p
57
+ m.directory File.join(cpath)
58
+ end
59
+ end
60
+
61
+ # Convert the Ruby version of the class name to a JavaScript version.
62
+ def client_class_name
63
+ class_name.gsub('::','.')
64
+ end
65
+
66
+ def client_namespace
67
+ parts = client_class_name.split('.')
68
+ parts.pop
69
+ return parts * '.'
70
+ end
71
+
72
+ def controller_class_name
73
+ ret = client_class_name
74
+ ret += 'Controller' unless ret =~ /Controller$/
75
+ ret
76
+ end
77
+
78
+ def controller_instance_name
79
+ ret = controller_class_name.split('.')
80
+ ret[ret.size-1] = ret.last.underscore.camelize(:lower)
81
+ return ret * "."
82
+ end
83
+
84
+ def view_class_name
85
+ ret = client_class_name
86
+ ret += 'View' unless ret =~ /View$/
87
+ ret
88
+ end
89
+
90
+ # This will convert the file_name provided by Rails to one suitable for
91
+ # the client. i.e. calendar/event => calendar/sub_dir/event
92
+ def client_file_path(sub_dir, ext=nil, to_strip = nil, fp = nil)
93
+ parts = (fp.nil? ? file_path : fp).split('/')
94
+
95
+ # Determine the root dir. Search clients then frameworks.
96
+ loc = @client_location
97
+
98
+ # check for clients
99
+ if loc.nil?
100
+ client_path = File.join(destination_root, "clients")
101
+ app_name = parts.first
102
+ loc = "clients" if File.exists?(client_path) && Dir.new(client_path).include?(app_name)
103
+ end
104
+
105
+ # check for frameworks
106
+ if loc.nil?
107
+ client_path = File.join(destination_root, "frameworks")
108
+ app_name = parts.first
109
+ loc = "frameworks" if File.exists?(client_path) && Dir.new(client_path).include?(app_name)
110
+ end
111
+
112
+ loc = "clients" if loc.nil? # fallback
113
+
114
+ path = parts.insert(parts.size-1,sub_dir).unshift(loc) * '/'
115
+
116
+ # We want to stop the final part of the name for controllers and views.
117
+ if to_strip && (path =~ /_#{to_strip}$/)
118
+ path = path.slice(0,path.size - (to_strip.size + 1))
119
+ end
120
+
121
+ [path,ext].compact * '.'
122
+ end
123
+
124
+ # Returns the base class name, which is the first argument or a default.
125
+ def base_class_name(default_base_class_name = 'SC.Object')
126
+ @args.first || default_base_class_name
127
+ end
128
+
129
+ ###################
130
+ # Borrowed from Rails NamedBase
131
+
132
+ attr_reader :name, :class_name, :singular_name, :plural_name
133
+ attr_reader :class_path, :file_path, :class_nesting, :class_nesting_depth
134
+ alias_method :file_name, :singular_name
135
+
136
+ def assign_names!(name)
137
+ @name = name
138
+ base_name, @class_path, @file_path, @class_nesting, @class_nesting_depth = extract_modules(@name)
139
+ @class_name_without_nesting, @singular_name, @plural_name = inflect_names(base_name)
140
+ if @class_nesting.empty?
141
+ @class_name = @class_name_without_nesting
142
+ else
143
+ @class_name = "#{@class_nesting}::#{@class_name_without_nesting}"
144
+ end
145
+ end
146
+
147
+ # Extract modules from filesystem-style or ruby-style path:
148
+ # good/fun/stuff
149
+ # Good::Fun::Stuff
150
+ # produce the same results.
151
+ def extract_modules(name)
152
+ modules = name.include?('/') ? name.split('/') : name.split('::')
153
+ name = modules.pop
154
+ path = modules.map { |m| m.underscore }
155
+ file_path = (path + [name.underscore]).join('/')
156
+ nesting = modules.map { |m| m.camelize }.join('::')
157
+ [name, path, file_path, nesting, modules.size]
158
+ end
159
+
160
+ def inflect_names(name)
161
+ camel = name.camelize
162
+ under = camel.underscore
163
+ plural = under.pluralize
164
+ [camel, under, plural]
165
+ end
166
+
167
+ end
168
+ end
169
+
170
+ RubiGen::Base.send(:include,SproutCore::GeneratorHelper)
@@ -0,0 +1,42 @@
1
+ module SproutCore
2
+
3
+ module Helpers
4
+
5
+ module CaptureHelper
6
+
7
+ # Captures the resulting value of the block and returns it
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
+ block.call(*args).to_s
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
29
+ end
30
+
31
+ # executes the passed block, placing the resulting content into a variable called
32
+ # @content_for_area_name. You can insert this content later by including this
33
+ # variable or by calling yield(:area_name)
34
+ #
35
+ def content_for(name, &block)
36
+ eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)"
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,80 @@
1
+ # The helper methods here are used to build the main index template file for
2
+ # a SproutCore application. See the commented index.rhtml in the plugin for
3
+ # example usage.
4
+ #
5
+ module SproutCore
6
+ module Helpers
7
+
8
+ module StaticHelper
9
+
10
+ # This method will return the HTML to link to all the stylesheets required
11
+ # by the named bundle. If you pass no options, the current client will be
12
+ # used.
13
+ #
14
+ # bundle_name = the name of the bundle to render or nil to use the current
15
+ # :language => the language to render. defaults to current language
16
+ #
17
+ def stylesheets_for_client(bundle_name = nil, opts = {})
18
+
19
+ opts[:language] ||= language
20
+
21
+ # Get bundle
22
+ cur_bundle = bundle_name.nil? ? bundle : library.bundle_for(bundle_name)
23
+
24
+ # Convert to a list of required bundles
25
+ all_bundles = cur_bundle.all_required_bundles
26
+
27
+ # For each bundle, get the ordered list of stylsheet urls
28
+ urls = []
29
+ all_bundles.each do |b|
30
+ urls += b.sorted_stylesheet_entries(opts).map { |x| x.url }
31
+ urls += (b.stylesheet_libs || [])
32
+ end
33
+
34
+ # Convert to HTML and return
35
+ urls = urls.map do |url|
36
+ %( <link href="#{url}" rel="stylesheet" type="text/css" />)
37
+ end
38
+ urls.join("\n")
39
+ end
40
+
41
+ # This method will return the HTML to link to all the javascripts required
42
+ # by the client. If you pass no options, the current client will be used.
43
+ #
44
+ # client_name = the name of the client to render or nil to use the current
45
+ # :language => the language to render. defaults to @language.
46
+ #
47
+ def javascripts_for_client(bundle_name = nil, opts = {})
48
+
49
+ opts[:language] ||= language
50
+
51
+ # Get bundle
52
+ cur_bundle = bundle_name.nil? ? bundle : library.bundle_for(bundle_name)
53
+
54
+ # Convert to a list of required bundles
55
+ all_bundles = cur_bundle.all_required_bundles
56
+
57
+ # For each bundle, get the ordered list of stylsheet urls
58
+ urls = []
59
+ all_bundles.each do |b|
60
+ urls += b.sorted_javascript_entries(opts).map { |x| x.url }
61
+ urls += (b.javascript_libs || [])
62
+ end
63
+
64
+ # Convert to HTML and return
65
+ urls = urls.map do |url|
66
+ %( <script type="text/javascript" src="#{url}"></script>)
67
+ end
68
+ urls.join("\n")
69
+ end
70
+
71
+ # Returns the URL for the named resource
72
+ def static_url(resource_name, opts = {})
73
+ opts[:language] ||= language
74
+ entry = bundle.find_resource_entry(resource_name, opts)
75
+ entry.nil? ? '' : entry.url
76
+ end
77
+ end
78
+
79
+ end
80
+ end