sproutit-sproutcore 1.0.0.20090407205609

Sign up to get free protection for your applications and to get access to all the features.
Files changed (382) hide show
  1. data/Buildfile +115 -0
  2. data/History.txt +7 -0
  3. data/README.txt +102 -0
  4. data/Rakefile +54 -0
  5. data/Todo.txt +1 -0
  6. data/bin/sc-build +13 -0
  7. data/bin/sc-build-number +13 -0
  8. data/bin/sc-gen +13 -0
  9. data/bin/sc-init +13 -0
  10. data/bin/sc-manifest +13 -0
  11. data/bin/sc-server +13 -0
  12. data/bin/sproutcore +14 -0
  13. data/buildtasks/build.rake +73 -0
  14. data/buildtasks/entry.rake +59 -0
  15. data/buildtasks/manifest.rake +469 -0
  16. data/buildtasks/render.rake +21 -0
  17. data/buildtasks/target.rake +42 -0
  18. data/gen/Buildfile +16 -0
  19. data/gen/app/Buildfile +36 -0
  20. data/gen/app/README +1 -0
  21. data/gen/app/USAGE +13 -0
  22. data/gen/app/templates/apps/{target_name}/core.js +27 -0
  23. data/gen/app/templates/apps/{target_name}/english.lproj/loading.rhtml +9 -0
  24. data/gen/app/templates/apps/{target_name}/english.lproj/main_page.js +22 -0
  25. data/gen/app/templates/apps/{target_name}/english.lproj/strings.js +15 -0
  26. data/gen/app/templates/apps/{target_name}/main.js +30 -0
  27. data/gen/controller/Buildfile +18 -0
  28. data/gen/controller/README +1 -0
  29. data/gen/controller/USAGE +13 -0
  30. data/gen/controller/templates/controllers/{filename}.js +18 -0
  31. data/gen/controller/templates/tests/controllers/{filename}.js +15 -0
  32. data/gen/framework/Buildfile +36 -0
  33. data/gen/framework/README +1 -0
  34. data/gen/framework/USAGE +13 -0
  35. data/gen/framework/templates/frameworks/{target_name}/core.js +21 -0
  36. data/gen/framework/templates/frameworks/{target_name}/english.lproj/strings.js +15 -0
  37. data/gen/language/Buildfile +26 -0
  38. data/gen/language/README +1 -0
  39. data/gen/language/USAGE +13 -0
  40. data/gen/language/templates/{filename}/strings.js +14 -0
  41. data/gen/model/Buildfile +16 -0
  42. data/gen/model/README +1 -0
  43. data/gen/model/USAGE +15 -0
  44. data/gen/model/templates/fixtures/{filename}.js +35 -0
  45. data/gen/model/templates/models/{filename}.js +19 -0
  46. data/gen/model/templates/tests/models/{filename}.js +15 -0
  47. data/gen/project/Buildfile +45 -0
  48. data/gen/project/INIT +3 -0
  49. data/gen/project/README +1 -0
  50. data/gen/project/USAGE +2 -0
  51. data/gen/project/templates/{filename}/Buildfile +7 -0
  52. data/gen/project/templates/{filename}/README +7 -0
  53. data/gen/test/Buildfile +25 -0
  54. data/gen/test/README +1 -0
  55. data/gen/test/USAGE +12 -0
  56. data/gen/test/templates/tests/{filename}.js +15 -0
  57. data/gen/theme/Buildfile +36 -0
  58. data/gen/theme/README +1 -0
  59. data/gen/theme/USAGE +13 -0
  60. data/gen/theme/templates/themes/{target_name}/english.lproj/strings.js +15 -0
  61. data/gen/view/Buildfile +18 -0
  62. data/gen/view/README +1 -0
  63. data/gen/view/USAGE +13 -0
  64. data/gen/view/templates/tests/views/{filename}.js +15 -0
  65. data/gen/view/templates/views/{filename}.js +18 -0
  66. data/lib/sproutcore.rb +130 -0
  67. data/lib/sproutcore/builders/base.rb +79 -0
  68. data/lib/sproutcore/builders/combine.rb +37 -0
  69. data/lib/sproutcore/builders/html.rb +177 -0
  70. data/lib/sproutcore/builders/javascript.rb +55 -0
  71. data/lib/sproutcore/builders/minify.rb +67 -0
  72. data/lib/sproutcore/builders/sass.rb +55 -0
  73. data/lib/sproutcore/builders/strings.rb +44 -0
  74. data/lib/sproutcore/builders/stylesheet.rb +40 -0
  75. data/lib/sproutcore/builders/test.rb +58 -0
  76. data/lib/sproutcore/builders/test_index.rb +26 -0
  77. data/lib/sproutcore/buildfile.rb +483 -0
  78. data/lib/sproutcore/buildfile/build_task.rb +33 -0
  79. data/lib/sproutcore/buildfile/buildfile_dsl.rb +162 -0
  80. data/lib/sproutcore/buildfile/cloneable.rb +34 -0
  81. data/lib/sproutcore/buildfile/early_time.rb +29 -0
  82. data/lib/sproutcore/buildfile/invocation_chain.rb +64 -0
  83. data/lib/sproutcore/buildfile/namespace.rb +33 -0
  84. data/lib/sproutcore/buildfile/string_ext.rb +198 -0
  85. data/lib/sproutcore/buildfile/task.rb +304 -0
  86. data/lib/sproutcore/buildfile/task_arguments.rb +86 -0
  87. data/lib/sproutcore/buildfile/task_manager.rb +193 -0
  88. data/lib/sproutcore/deprecated/view_helper.rb +662 -0
  89. data/lib/sproutcore/helpers/capture_helper.rb +30 -0
  90. data/lib/sproutcore/helpers/cssmin.rb +202 -0
  91. data/lib/sproutcore/helpers/dom_id_helper.rb +21 -0
  92. data/lib/sproutcore/helpers/entry_sorter.rb +105 -0
  93. data/lib/sproutcore/helpers/packed_optimizer.rb +102 -0
  94. data/lib/sproutcore/helpers/static_helper.rb +268 -0
  95. data/lib/sproutcore/helpers/tag_helper.rb +117 -0
  96. data/lib/sproutcore/helpers/text_helper.rb +303 -0
  97. data/lib/sproutcore/models/generator.rb +493 -0
  98. data/lib/sproutcore/models/hash_struct.rb +109 -0
  99. data/lib/sproutcore/models/manifest.rb +342 -0
  100. data/lib/sproutcore/models/manifest_entry.rb +232 -0
  101. data/lib/sproutcore/models/project.rb +270 -0
  102. data/lib/sproutcore/models/target.rb +403 -0
  103. data/lib/sproutcore/rack/builder.rb +269 -0
  104. data/lib/sproutcore/rack/dev.rb +51 -0
  105. data/lib/sproutcore/rack/docs.rb +24 -0
  106. data/lib/sproutcore/rack/proxy.rb +92 -0
  107. data/lib/sproutcore/rack/service.rb +141 -0
  108. data/lib/sproutcore/rack/test_runner.rb +24 -0
  109. data/lib/sproutcore/render_engines/erubis.rb +55 -0
  110. data/lib/sproutcore/render_engines/haml.rb +39 -0
  111. data/lib/sproutcore/tools.rb +311 -0
  112. data/lib/sproutcore/tools/build.rb +80 -0
  113. data/lib/sproutcore/tools/build_number.rb +23 -0
  114. data/lib/sproutcore/tools/gen.rb +99 -0
  115. data/lib/sproutcore/tools/init.rb +40 -0
  116. data/lib/sproutcore/tools/manifest.rb +84 -0
  117. data/lib/sproutcore/tools/server.rb +45 -0
  118. data/spec/buildtasks/build/copy_spec.rb +60 -0
  119. data/spec/buildtasks/build/spec_helper.rb +36 -0
  120. data/spec/buildtasks/manifest/catalog_spec.rb +48 -0
  121. data/spec/buildtasks/manifest/hide_buildfiles_spec.rb +125 -0
  122. data/spec/buildtasks/manifest/localize_spec.rb +97 -0
  123. data/spec/buildtasks/manifest/prepare_build_tasks/combine_spec.rb +246 -0
  124. data/spec/buildtasks/manifest/prepare_build_tasks/css_spec.rb +87 -0
  125. data/spec/buildtasks/manifest/prepare_build_tasks/html_spec.rb +175 -0
  126. data/spec/buildtasks/manifest/prepare_build_tasks/javascript_spec.rb +65 -0
  127. data/spec/buildtasks/manifest/prepare_build_tasks/minify_spec.rb +70 -0
  128. data/spec/buildtasks/manifest/prepare_build_tasks/packed_spec.rb +152 -0
  129. data/spec/buildtasks/manifest/prepare_build_tasks/sass_spec.rb +98 -0
  130. data/spec/buildtasks/manifest/prepare_build_tasks/strings_spec.rb +64 -0
  131. data/spec/buildtasks/manifest/prepare_build_tasks/tests_spec.rb +163 -0
  132. data/spec/buildtasks/manifest/prepare_spec.rb +43 -0
  133. data/spec/buildtasks/manifest/spec_helper.rb +35 -0
  134. data/spec/buildtasks/target_spec.rb +214 -0
  135. data/spec/fixtures/builder_tests/Buildfile +15 -0
  136. data/spec/fixtures/builder_tests/apps/combine_test/a.js +1 -0
  137. data/spec/fixtures/builder_tests/apps/combine_test/b.js +1 -0
  138. data/spec/fixtures/builder_tests/apps/combine_test/c.js +1 -0
  139. data/spec/fixtures/builder_tests/apps/combine_test/english.lproj/a.css +1 -0
  140. data/spec/fixtures/builder_tests/apps/combine_test/english.lproj/b.css +1 -0
  141. data/spec/fixtures/builder_tests/apps/combine_test/english.lproj/c.css +1 -0
  142. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/bar1_sample.rhtml +2 -0
  143. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/erb_sample.html.erb +1 -0
  144. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/icons/image.png +0 -0
  145. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/image.jpg +0 -0
  146. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/rhtml_sample.rhtml +1 -0
  147. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/strings.js +4 -0
  148. data/spec/fixtures/builder_tests/apps/html_test/english.lproj/style.css +0 -0
  149. data/spec/fixtures/builder_tests/apps/html_test/french.lproj/french-icons/fr.png +0 -0
  150. data/spec/fixtures/builder_tests/apps/html_test/french.lproj/strings.js +4 -0
  151. data/spec/fixtures/builder_tests/apps/html_test/lib/layout_template.rhtml +1 -0
  152. data/spec/fixtures/builder_tests/apps/html_test/scripts.js +0 -0
  153. data/spec/fixtures/builder_tests/apps/javascript_test/sc_static.js +15 -0
  154. data/spec/fixtures/builder_tests/apps/javascript_test/sc_super.js +4 -0
  155. data/spec/fixtures/builder_tests/apps/javascript_test/strings.js +7 -0
  156. data/spec/fixtures/builder_tests/apps/sass_test/sample.sass +3 -0
  157. data/spec/fixtures/builder_tests/apps/strings_test/lproj/strings.js +8 -0
  158. data/spec/fixtures/builder_tests/apps/stylesheet_test/build_directives.css +9 -0
  159. data/spec/fixtures/builder_tests/apps/stylesheet_test/sc_static.css +12 -0
  160. data/spec/fixtures/builder_tests/apps/test_test/lib/alt_layout.rhtml +1 -0
  161. data/spec/fixtures/builder_tests/apps/test_test/lib/test_layout.rhtml +3 -0
  162. data/spec/fixtures/builder_tests/apps/test_test/tests/qunit_test.js +1 -0
  163. data/spec/fixtures/builder_tests/apps/test_test/tests/qunit_test2.js +1 -0
  164. data/spec/fixtures/builder_tests/apps/test_test/tests/rhtml_test.rhtml +4 -0
  165. data/spec/fixtures/builder_tests/frameworks/debug/core.js +0 -0
  166. data/spec/fixtures/builder_tests/frameworks/debug/english.lproj/dummy.css +0 -0
  167. data/spec/fixtures/builder_tests/frameworks/qunit/core.js +0 -0
  168. data/spec/fixtures/builder_tests/frameworks/qunit/english.lproj/dummy.css +0 -0
  169. data/spec/fixtures/builder_tests/frameworks/req_target_1/english.lproj/req_style_1.css +0 -0
  170. data/spec/fixtures/builder_tests/frameworks/req_target_1/english.lproj/strings.js +4 -0
  171. data/spec/fixtures/builder_tests/frameworks/req_target_1/english.lproj/test.rhtml +1 -0
  172. data/spec/fixtures/builder_tests/frameworks/req_target_1/req_js_1.js +0 -0
  173. data/spec/fixtures/builder_tests/frameworks/req_target_2/english.lproj/req_style_2.css +0 -0
  174. data/spec/fixtures/builder_tests/frameworks/req_target_2/english.lproj/test.rhtml +1 -0
  175. data/spec/fixtures/builder_tests/frameworks/req_target_2/javascript.js +1 -0
  176. data/spec/fixtures/builder_tests/frameworks/req_target_2/lib/alt_layout.rhtml +0 -0
  177. data/spec/fixtures/builder_tests/frameworks/req_target_2/req_js_2.js +0 -0
  178. data/spec/fixtures/builder_tests/themes/sample_theme/Buildfile +1 -0
  179. data/spec/fixtures/buildfiles/basic/Buildfile +16 -0
  180. data/spec/fixtures/buildfiles/basic/task_module.rake +6 -0
  181. data/spec/fixtures/buildfiles/installed/Buildfile +7 -0
  182. data/spec/fixtures/buildfiles/installed/Buildfile2 +5 -0
  183. data/spec/fixtures/buildfiles/project_test/Buildfile +4 -0
  184. data/spec/fixtures/buildfiles/project_test/not_project/Buildfile +2 -0
  185. data/spec/fixtures/buildfiles/project_test/not_project/child/PLACEHOLDER +0 -0
  186. data/spec/fixtures/entry_for_project/Buildfile +1 -0
  187. data/spec/fixtures/entry_for_project/apps/test_app/entry.txt +0 -0
  188. data/spec/fixtures/entry_for_project/apps/test_app/frameworks/nested/PLACEHOLDER +0 -0
  189. data/spec/fixtures/entry_for_project/frameworks/shared/PLACEHOLDER +0 -0
  190. data/spec/fixtures/find_targets/custom/Buildfile +8 -0
  191. data/spec/fixtures/find_targets/custom/bars/bar1/bars/bar1/PLACEHOLDER +0 -0
  192. data/spec/fixtures/find_targets/custom/bars/bar1/bars/bar2/PLACEHOLDER +0 -0
  193. data/spec/fixtures/find_targets/custom/bars/bar1/foos/foo1/PLACEHOLDER +0 -0
  194. data/spec/fixtures/find_targets/custom/bars/bar1/foos/foo2/PLACEHOLDER +0 -0
  195. data/spec/fixtures/find_targets/custom/foos/custom_foos/Buildfile +5 -0
  196. data/spec/fixtures/find_targets/custom/foos/custom_foos/custom_foodir/foo1/PLACEHOLDER +0 -0
  197. data/spec/fixtures/find_targets/custom/foos/custom_foos/custom_foodir/foo2/PLACEHOLDER +0 -0
  198. data/spec/fixtures/find_targets/custom/foos/custom_foos/foos/not_foo1/PLACEHOLDER +0 -0
  199. data/spec/fixtures/find_targets/custom/foos/foo1/bars/bar1/PLACEHOLDER +0 -0
  200. data/spec/fixtures/find_targets/custom/foos/foo1/bars/bar2/PLACEHOLDER +0 -0
  201. data/spec/fixtures/find_targets/nested/Buildfile +8 -0
  202. data/spec/fixtures/find_targets/nested/apps/app1/Buildfile +1 -0
  203. data/spec/fixtures/find_targets/nested/apps/app1/apps/nested_app/PLACEHOLDER +0 -0
  204. data/spec/fixtures/find_targets/standard/Apps/app1/frameworks/framework1/PLACEHOLDER +0 -0
  205. data/spec/fixtures/find_targets/standard/Apps/app1/frameworks/framework2/PLACEHOLDER +0 -0
  206. data/spec/fixtures/find_targets/standard/clients/client1/PLACEHOLDER +0 -0
  207. data/spec/fixtures/find_targets/standard/frameworks/framework1/frameworks/framework1/PLACEHOLDER +0 -0
  208. data/spec/fixtures/find_targets/standard/frameworks/framework2/PLACEHOLDER +0 -0
  209. data/spec/fixtures/find_targets/standard/themes/theme1/PLACEHOLDER +0 -0
  210. data/spec/fixtures/find_targets/standard/themes/theme2/PLACEHOLDER +0 -0
  211. data/spec/fixtures/languages/apps/caps_long_names/English.lproj/PLACEHOLDER +0 -0
  212. data/spec/fixtures/languages/apps/caps_long_names/FreNCH.lproj/PLACEHOLDER +0 -0
  213. data/spec/fixtures/languages/apps/caps_long_names/UnknOWN.lproj/PLACEHOLDER +0 -0
  214. data/spec/fixtures/languages/apps/long_names/english.lproj/PLACEHOLDER +0 -0
  215. data/spec/fixtures/languages/apps/long_names/french.lproj/PLACEHOLDER +0 -0
  216. data/spec/fixtures/languages/apps/long_names/german.lproj/PLACEHOLDER +0 -0
  217. data/spec/fixtures/languages/apps/long_names/italian.lproj/PLACEHOLDER +0 -0
  218. data/spec/fixtures/languages/apps/long_names/japanese.lproj/PLACEHOLDER +0 -0
  219. data/spec/fixtures/languages/apps/long_names/spanish.lproj/PLACEHOLDER +0 -0
  220. data/spec/fixtures/languages/apps/long_names/unknown.lproj/PLACEHOLDER +0 -0
  221. data/spec/fixtures/languages/apps/no_names/PLACEHOLDER +0 -0
  222. data/spec/fixtures/languages/apps/short_names/de.lproj/PLACEHOLDER +0 -0
  223. data/spec/fixtures/languages/apps/short_names/en-CA.lproj/PLACEHOLDER +0 -0
  224. data/spec/fixtures/languages/apps/short_names/en-GB.lproj/PLACEHOLDER +0 -0
  225. data/spec/fixtures/languages/apps/short_names/en-US.lproj/PLACEHOLDER +0 -0
  226. data/spec/fixtures/languages/apps/short_names/en.lproj/PLACEHOLDER +0 -0
  227. data/spec/fixtures/languages/apps/short_names/es.lproj/PLACEHOLDER +0 -0
  228. data/spec/fixtures/languages/apps/short_names/foo.lproj/PLACEHOLDER +0 -0
  229. data/spec/fixtures/languages/apps/short_names/fr.lproj/PLACEHOLDER +0 -0
  230. data/spec/fixtures/languages/apps/short_names/it.lproj/PLACEHOLDER +0 -0
  231. data/spec/fixtures/languages/apps/short_names/ja.lproj/PLACEHOLDER +0 -0
  232. data/spec/fixtures/ordered_entries/apps/no_requires/1.js +1 -0
  233. data/spec/fixtures/ordered_entries/apps/no_requires/B.js +1 -0
  234. data/spec/fixtures/ordered_entries/apps/no_requires/a.js +1 -0
  235. data/spec/fixtures/ordered_entries/apps/no_requires/a/a.js +1 -0
  236. data/spec/fixtures/ordered_entries/apps/no_requires/a/b.js +1 -0
  237. data/spec/fixtures/ordered_entries/apps/no_requires/b/a.js +1 -0
  238. data/spec/fixtures/ordered_entries/apps/no_requires/c.js +1 -0
  239. data/spec/fixtures/ordered_entries/apps/no_requires/core.js +1 -0
  240. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/B.css +0 -0
  241. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/a.css +0 -0
  242. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/a/a.css +0 -0
  243. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/a/b.css +0 -0
  244. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/b/a.css +0 -0
  245. data/spec/fixtures/ordered_entries/apps/no_requires/english.lproj/c.css +0 -0
  246. data/spec/fixtures/ordered_entries/apps/no_requires/lproj/strings.js +1 -0
  247. data/spec/fixtures/ordered_entries/apps/no_requires/utils.js +1 -0
  248. data/spec/fixtures/ordered_entries/apps/with_requires/a.js +2 -0
  249. data/spec/fixtures/ordered_entries/apps/with_requires/b.js +3 -0
  250. data/spec/fixtures/ordered_entries/apps/with_requires/c.js +2 -0
  251. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/a.css +2 -0
  252. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/b.css +2 -0
  253. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/c.css +2 -0
  254. data/spec/fixtures/ordered_entries/apps/with_requires/english.lproj/d.js +1 -0
  255. data/spec/fixtures/real_world/Buildfile +12 -0
  256. data/spec/fixtures/real_world/apps/account/README +1 -0
  257. data/spec/fixtures/real_world/apps/calendar/README +1 -0
  258. data/spec/fixtures/real_world/apps/contacts/README_BEFORE_EDITING +1 -0
  259. data/spec/fixtures/real_world/apps/files/README +1 -0
  260. data/spec/fixtures/real_world/apps/mail/README +1 -0
  261. data/spec/fixtures/real_world/apps/mobile_photos/README +1 -0
  262. data/spec/fixtures/real_world/apps/photos/README +1 -0
  263. data/spec/fixtures/real_world/apps/uploader/README +1 -0
  264. data/spec/fixtures/real_world/frameworks/core_files/PLACEHOLDER +0 -0
  265. data/spec/fixtures/real_world/frameworks/core_photos/PLACEHOLDER +0 -0
  266. data/spec/fixtures/real_world/frameworks/shared/PLACEHOLDER +0 -0
  267. data/spec/fixtures/real_world/frameworks/sproutcore/Buildfile +26 -0
  268. data/spec/fixtures/real_world/frameworks/sproutcore/README +1 -0
  269. data/spec/fixtures/real_world/frameworks/sproutcore/apps/docs/PLACEHOLDER +0 -0
  270. data/spec/fixtures/real_world/frameworks/sproutcore/apps/test_runner/PLACEHOLDER +0 -0
  271. data/spec/fixtures/real_world/frameworks/sproutcore/core.js +0 -0
  272. data/spec/fixtures/real_world/frameworks/sproutcore/debug/debug-resource.html +0 -0
  273. data/spec/fixtures/real_world/frameworks/sproutcore/debug/sample_debug.js +0 -0
  274. data/spec/fixtures/real_world/frameworks/sproutcore/demo2.js +0 -0
  275. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/debug/sample_debug-loc.js +0 -0
  276. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/demo.css +4 -0
  277. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/demo.html +1 -0
  278. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/demo2.sass +0 -0
  279. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/file_extension_test.haml +0 -0
  280. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/file_extension_test.html.erb +1 -0
  281. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/file_extension_test.rhtml +0 -0
  282. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/fixtures/sample_fixtures-loc.js +0 -0
  283. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/has_require.css +4 -0
  284. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/no_require.css +1 -0
  285. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/no_sc_resource.rhtml +1 -0
  286. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/protocols/sample-loc.js +0 -0
  287. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/sc_resource.css +6 -0
  288. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/sc_resource.rhtml +3 -0
  289. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/strings.js +1 -0
  290. data/spec/fixtures/real_world/frameworks/sproutcore/english.lproj/tests/sample-loc.js +0 -0
  291. data/spec/fixtures/real_world/frameworks/sproutcore/fixtures/sample-json-fixture.json +1 -0
  292. data/spec/fixtures/real_world/frameworks/sproutcore/fixtures/sample_fixtures.js +0 -0
  293. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/application/PLACEHOLDER +0 -0
  294. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/costello/core.js +0 -0
  295. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/data_store/PLACEHOLDER +0 -0
  296. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/debug/PLACEHOLDER +0 -0
  297. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/desktop/PLACEHOLDER +0 -0
  298. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/empty_theme/PLACEHOLDER +0 -0
  299. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/foundation/PLACEHOLDER +0 -0
  300. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/mobile/PLACEHOLDER +0 -0
  301. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/qunit/PLACEHOLDER +0 -0
  302. data/spec/fixtures/real_world/frameworks/sproutcore/frameworks/uploader/PLACEHOLDER +0 -0
  303. data/spec/fixtures/real_world/frameworks/sproutcore/french.lproj/french-resource.js +0 -0
  304. data/spec/fixtures/real_world/frameworks/sproutcore/french.lproj/strings.js +1 -0
  305. data/spec/fixtures/real_world/frameworks/sproutcore/german.lproj/german-resource.js +0 -0
  306. data/spec/fixtures/real_world/frameworks/sproutcore/german.lproj/strings.js +0 -0
  307. data/spec/fixtures/real_world/frameworks/sproutcore/has_require.js +4 -0
  308. data/spec/fixtures/real_world/frameworks/sproutcore/lib/index.html +1 -0
  309. data/spec/fixtures/real_world/frameworks/sproutcore/no_require.js +1 -0
  310. data/spec/fixtures/real_world/frameworks/sproutcore/protocols/sample.js +0 -0
  311. data/spec/fixtures/real_world/frameworks/sproutcore/sc_resource.js +6 -0
  312. data/spec/fixtures/real_world/frameworks/sproutcore/tests/nested/sample1.js +0 -0
  313. data/spec/fixtures/real_world/frameworks/sproutcore/tests/nested/sample2.js +0 -0
  314. data/spec/fixtures/real_world/frameworks/sproutcore/tests/sample.js +0 -0
  315. data/spec/fixtures/real_world/frameworks/sproutcore/tests/sample.rhtml +1 -0
  316. data/spec/fixtures/real_world/frameworks/sproutcore/themes/standard_theme/README +0 -0
  317. data/spec/fixtures/real_world/frameworks/sproutcore/views/view.js +1 -0
  318. data/spec/fixtures/real_world/generators/sample_custom/Buildfile +0 -0
  319. data/spec/fixtures/real_world/generators/sample_custom/templates/{filename}.js +1 -0
  320. data/spec/fixtures/recursive_project/Buildfile +8 -0
  321. data/spec/fixtures/recursive_project/frameworks/sproutcore/frameworks/costello/PLACEHOLDER +0 -0
  322. data/spec/lib/builders/combine_spec.rb +67 -0
  323. data/spec/lib/builders/html_spec.rb +577 -0
  324. data/spec/lib/builders/javascript_spec.rb +81 -0
  325. data/spec/lib/builders/sass_spec.rb +43 -0
  326. data/spec/lib/builders/spec_helper.rb +30 -0
  327. data/spec/lib/builders/strings_spec.rb +52 -0
  328. data/spec/lib/builders/stylesheet_spec.rb +63 -0
  329. data/spec/lib/builders/test_index_spec.rb +44 -0
  330. data/spec/lib/builders/test_spec.rb +135 -0
  331. data/spec/lib/buildfile/config_for_spec.rb +81 -0
  332. data/spec/lib/buildfile/define_spec.rb +59 -0
  333. data/spec/lib/buildfile/dup_spec.rb +65 -0
  334. data/spec/lib/buildfile/invoke_spec.rb +130 -0
  335. data/spec/lib/buildfile/load_spec.rb +49 -0
  336. data/spec/lib/buildfile/task/dup_spec.rb +55 -0
  337. data/spec/lib/buildfile/task_defined_spec.rb +17 -0
  338. data/spec/lib/buildfile_commands/build_task_spec.rb +19 -0
  339. data/spec/lib/buildfile_commands/config_spec.rb +97 -0
  340. data/spec/lib/buildfile_commands/import_spec.rb +17 -0
  341. data/spec/lib/buildfile_commands/namespace_spec.rb +18 -0
  342. data/spec/lib/buildfile_commands/proxies_spec.rb +38 -0
  343. data/spec/lib/buildfile_commands/replace_task_spec.rb +29 -0
  344. data/spec/lib/buildfile_commands/task_spec.rb +36 -0
  345. data/spec/lib/helpers/packing_optimizer/optimize_spec.rb +26 -0
  346. data/spec/lib/models/hash_struct/deep_clone_spec.rb +27 -0
  347. data/spec/lib/models/hash_struct/has_options_spec.rb +32 -0
  348. data/spec/lib/models/hash_struct/hash_spec.rb +64 -0
  349. data/spec/lib/models/hash_struct/merge_spec.rb +26 -0
  350. data/spec/lib/models/hash_struct/method_missing.rb +41 -0
  351. data/spec/lib/models/manifest/add_entry_spec.rb +36 -0
  352. data/spec/lib/models/manifest/add_transform_spec.rb +90 -0
  353. data/spec/lib/models/manifest/build_spec.rb +78 -0
  354. data/spec/lib/models/manifest/entry_for_spec.rb +94 -0
  355. data/spec/lib/models/manifest/find_entry.rb +84 -0
  356. data/spec/lib/models/manifest/prepare_spec.rb +62 -0
  357. data/spec/lib/models/manifest_entry/cacheable_url_spec.rb +31 -0
  358. data/spec/lib/models/manifest_entry/prepare_spec.rb +54 -0
  359. data/spec/lib/models/project/add_target_spec.rb +44 -0
  360. data/spec/lib/models/project/buildfile_spec.rb +35 -0
  361. data/spec/lib/models/project/find_targets_for_spec.rb +77 -0
  362. data/spec/lib/models/project/load_nearest_project_spec.rb +23 -0
  363. data/spec/lib/models/project/target_for_spec.rb +33 -0
  364. data/spec/lib/models/project/targets_spec.rb +62 -0
  365. data/spec/lib/models/target/compute_build_number_spec.rb +125 -0
  366. data/spec/lib/models/target/config_spec.rb +30 -0
  367. data/spec/lib/models/target/expand_required_targets_spec.rb +48 -0
  368. data/spec/lib/models/target/installed_languages_spec.rb +47 -0
  369. data/spec/lib/models/target/lproj_for_spec.rb +38 -0
  370. data/spec/lib/models/target/manifest_for_spec.rb +42 -0
  371. data/spec/lib/models/target/parent_target_spec.rb +21 -0
  372. data/spec/lib/models/target/prepare_spec.rb +53 -0
  373. data/spec/lib/models/target/required_targets_spec.rb +119 -0
  374. data/spec/lib/models/target/target_for_spec.rb +56 -0
  375. data/spec/lib/tools/build_number_spec.rb +28 -0
  376. data/spec/lib/tools/gen_spec.rb +207 -0
  377. data/spec/lib/tools/tools_spec.rb +78 -0
  378. data/spec/spec_helper.rb +138 -0
  379. data/sproutcore.gemspec +47 -0
  380. data/vendor/github_gem_lint.rb +22 -0
  381. data/vendor/yui-compressor/yuicompressor-2.4.2.jar +0 -0
  382. metadata +1084 -0
@@ -0,0 +1,268 @@
1
+ # ===========================================================================
2
+ # Project: Abbot - SproutCore Build Tools
3
+ # Copyright: ©2009 Apple, Inc.
4
+ # portions copyright @2006-2009 Sprout Systems, Inc.
5
+ # and contributors
6
+ # ===========================================================================
7
+
8
+ # The helper methods here are used to build the main index template file for
9
+ # a SproutCore application. See the commented index.rhtml in the plugin for
10
+ # example usage.
11
+ #
12
+ module SC
13
+ module Helpers
14
+
15
+ module StaticHelper
16
+
17
+ # This method will return the HTML to link to all the stylesheets
18
+ # required by the named bundle. If you pass no options, the current
19
+ # client will be used.
20
+ #
21
+ # bundle_name = the name of the bundle to render or nil to use the
22
+ # current :language => the language to render. defaults to current
23
+ # language
24
+ #
25
+ def stylesheets_for_client(target_name = nil, opts = nil)
26
+
27
+ # normalize params
28
+ if target_name.kind_of?(Hash) && opts.nil?
29
+ opts = target_name
30
+ target_name = nil
31
+ end
32
+ opts = {} if opts.nil?
33
+
34
+ # process options
35
+ include_method = opts[:include_method] ||= :link
36
+ t = target_name ? target.target_for(target_name) : target
37
+
38
+ # collect urls from entries
39
+ urls = []
40
+ combine_stylesheets = t.config.combine_stylesheets
41
+ combined_entries(t, opts, 'stylesheet.css', 'stylesheet-packed.css') do |cur_target, cur_entry|
42
+ # include either the entry URL or URL of ordered entries
43
+ # depending on setup
44
+ if combine_stylesheets
45
+ urls << cur_entry.cacheable_url
46
+ else
47
+ urls += cur_entry.ordered_entries.map { |e| e.cacheable_url }
48
+ end
49
+
50
+ # add any stylesheet libs from the target
51
+ urls += (cur_target.config.stylesheet_libs || [])
52
+ end
53
+
54
+ # Convert to HTML and return
55
+ urls = urls.map do |url|
56
+ if include_method == :import
57
+ %( @import url('#{url}');)
58
+ else
59
+ %( <link href="#{url}" rel="stylesheet" type="text/css" />)
60
+ end
61
+ end
62
+
63
+ # if include style is @import, surround with style tags
64
+ if include_method == :import
65
+ %(<style type="text/css">\n#{urls * "\n"}</style>)
66
+ else
67
+ urls.join("\n")
68
+ end
69
+ end
70
+
71
+ # This method will return the HTML to link to all the javascripts
72
+ # required by the client. If you pass no options, the current client
73
+ # will be used.
74
+ #
75
+ # client_name = the name of the client to render or nil to use the
76
+ # current :language => the language to render. defaults to @language.
77
+ #
78
+ def javascripts_for_client(target_name = nil, opts = {})
79
+
80
+ # normalize params
81
+ if target_name.kind_of?(Hash) && opts.nil?
82
+ opts = target_name
83
+ target_name = nil
84
+ end
85
+ opts = {} if opts.nil?
86
+
87
+ # process options
88
+ t = target_name ? target.target_for(target_name) : target
89
+
90
+ # collect urls from entries
91
+ urls = []
92
+ combine_javascript = t.config.combine_javascript
93
+ combined_entries(t, opts, 'javascript.js', 'javascript-packed.js') do |cur_target, cur_entry|
94
+
95
+ # include either the entry URL or URL of ordered entries
96
+ # depending on setup
97
+ if combine_javascript
98
+ urls << cur_entry.cacheable_url
99
+ else
100
+ urls += cur_entry.ordered_entries.map { |e| e.cacheable_url }
101
+ end
102
+
103
+ # add any stylesheet libs from the target
104
+ urls += (cur_target.config.javascript_libs || [])
105
+ end
106
+
107
+ # Convert to HTML and return
108
+ urls = urls.map do |url|
109
+ %( <script type="text/javascript" src="#{url}"></script>)
110
+ end
111
+
112
+ # Add preferred language definition...
113
+ urls << %(<script type="text/javascript">String.preferredLanguage = "#{language}";</script>)
114
+
115
+ urls.join("\n")
116
+ end
117
+
118
+ # Returns the URL for the named resource
119
+ def sc_static(resource_name, opts = {})
120
+
121
+ # determine which manifest to search. if a language is explicitly
122
+ # specified, lookup manifest for that language. otherwise use
123
+ # current manifest.
124
+ m = self.manifest
125
+ if opts[:language]
126
+ m = target.manifest_for(:language => opts[:language]).build!
127
+ end
128
+
129
+ entry = m.find_entry(resource_name)
130
+ entry.nil? ? '' : entry.cacheable_url
131
+ end
132
+ alias_method :static_url, :sc_static
133
+
134
+ # Allows you to specify HTML resource this html template should be
135
+ # merged into. Optionally also specify the layout file to use when
136
+ # building this resource.
137
+ #
138
+ # == Example
139
+ # <% sc_resource :foo, :layout => 'sproutcore:lib/index.html' %>
140
+ #
141
+ def sc_resource(resource_name, opts = nil)
142
+ opts = opts.nil? ? (resource_name.kind_of?(Hash) ? resource_name : {}) : opts
143
+ @layout = opts[:layout] if opts[:layout]
144
+ return ''
145
+ end
146
+
147
+ # Localizes the passed string, using the optional passed options.
148
+ def loc(string, opts = {})
149
+ string = string.nil? ? '' : string.to_s
150
+ language = opts[:language] || self.language
151
+ return strings_hash(language)[string] || string
152
+ end
153
+
154
+ # Returns the CSS class name dictated by the current theme. You can
155
+ # also pass an optional default value to use if no theme is specified
156
+ # in the config. The value returned here will use either the
157
+ # theme_name set in the target's config or the theme_name set by the
158
+ # theme framework, if set.
159
+ def theme_name(opts ={})
160
+ ret = opts[:default] || 'sc-theme'
161
+ if target.config.theme_name
162
+ ret = target.config.theme_name
163
+ elsif target.config.theme
164
+ if theme_target = target.target_for(target.config.theme)
165
+ ret = theme_target.config.theme_name || ret
166
+ end
167
+ end
168
+ return ret
169
+ end
170
+
171
+ def title
172
+ target.config.title || target.target_name.to_s.sub(/^\//,'').gsub(/[-_\/]/,' ').split(' ').map { |x| x.capitalize }.join(' ')
173
+ end
174
+
175
+ private
176
+
177
+ # Returns a merged strings hash from all of the required bundles. Used
178
+ # by loc()
179
+ #
180
+ # === Params
181
+ # for_language:: the language you want the hash for
182
+ #
183
+ # === Returns
184
+ # params hash
185
+ #
186
+ def strings_hash(for_language)
187
+ ret = (@strings_hashes ||= {})[for_language]
188
+ return ret unless ret.nil?
189
+
190
+ # Need to generate hash.
191
+
192
+ # get the default manifest for the current target. will be used to
193
+ # select other manifests.
194
+ m = (for_language == self.language) ? self.manifest : target.manifest_for(:language => for_language)
195
+
196
+ # get all of the targets to merge...
197
+ ret = {}
198
+ targets = (target.expand_required_targets + [target])
199
+ targets.each do |t|
200
+ # get the manifest for the target
201
+ cur_manifest = (t == target) ? m : t.manifest_for(m.variation)
202
+ cur_manifest.build!
203
+
204
+ # ...and find a strings entry, if there is one.
205
+ strings_entry = cur_manifest.entries(:hidden => true).find { |e| e.entry_type == :strings }
206
+ next if strings_entry.nil?
207
+
208
+ # then load the strings
209
+ strings_entry.stage!
210
+ next if !File.exist?(strings_entry.staging_path)
211
+ strings_hash = YAML.load(File.read(strings_entry.staging_path))
212
+ next if strings_hash.nil? # could not load...
213
+
214
+ # if strings loaded, merge into ret...
215
+ ret = ret.merge(strings_hash)
216
+ end
217
+
218
+ # save in cache.
219
+ @strings_hashes[for_language] = ret
220
+ return ret # done!
221
+ end
222
+
223
+ # Find all of the combined entries.
224
+ def combined_entries(t, opts, entry_name, packed_entry_name=nil, &block)
225
+
226
+ # choose manifest variant. default to current manifest variant
227
+ # if no explicit language was passed.
228
+ v = opts[:language] ? { :language => opts[:language] } : manifest.variation
229
+
230
+ # choose which targets to include packed and unpacked
231
+ targets = expand_required_targets(t)
232
+ if t.config.use_packed && packed_entry_name # must pass to activate
233
+ packed, unpacked = SC::Helpers::PackedOptimizer.optimize(targets)
234
+ unpacked << t # always use unpacked for main target
235
+ else
236
+ packed = []
237
+ unpacked = targets + [t] # always use unpacked
238
+ end
239
+
240
+ # deal with packed targets...
241
+ packed.each do |t|
242
+ # get the manifest for the target
243
+ cur_manifest = t.manifest_for(v).build!
244
+
245
+ # get the stylesheet or js entry for it...
246
+ entry = cur_manifest.entry_for packed_entry_name
247
+ next if entry.nil? || !entry.composite? # no stylesheet or js
248
+
249
+ yield(t, entry)
250
+ end
251
+
252
+ unpacked.each do |t|
253
+ # get the manifest for the target
254
+ cur_manifest = t.manifest_for(v).build!
255
+
256
+ # get the stylesheet or js entry for it...
257
+ entry = cur_manifest.entry_for entry_name
258
+ next if entry.nil? || !entry.composite? # no stylesheet or js
259
+
260
+ yield(t, entry)
261
+ end
262
+ end
263
+
264
+
265
+ end
266
+
267
+ end
268
+ end
@@ -0,0 +1,117 @@
1
+ # ===========================================================================
2
+ # Project: Abbot - SproutCore Build Tools
3
+ # Copyright: ©2009 Apple, Inc.
4
+ # portions copyright @2006-2009 Sprout Systems, Inc.
5
+ # and contributors
6
+ # ===========================================================================
7
+
8
+ require 'cgi'
9
+ require 'erb'
10
+
11
+ # Borrowed from Rails 2.0.2
12
+
13
+ module SC
14
+ module Helpers #:nodoc:
15
+ # Use these methods to generate HTML tags programmatically when you can't use
16
+ # a Builder. By default, they output XHTML compliant tags.
17
+ module TagHelper
18
+ include ERB::Util
19
+
20
+ # Returns an empty HTML tag of type +name+ which by default is XHTML
21
+ # compliant. Setting +open+ to true will create an open tag compatible
22
+ # with HTML 4.0 and below. Add HTML attributes by passing an attributes
23
+ # hash to +options+. For attributes with no value like (disabled and
24
+ # readonly), give it a value of true in the +options+ hash. You can use
25
+ # symbols or strings for the attribute names.
26
+ #
27
+ # tag("br")
28
+ # # => <br />
29
+ # tag("br", nil, true)
30
+ # # => <br>
31
+ # tag("input", { :type => 'text', :disabled => true })
32
+ # # => <input type="text" disabled="disabled" />
33
+ def tag(name, options = nil, open = false)
34
+ "<#{name}#{tag_options(options) if options}" + (open ? ">" : " />")
35
+ end
36
+
37
+ # Returns an HTML block tag of type +name+ surrounding the +content+. Add
38
+ # HTML attributes by passing an attributes hash to +options+. For attributes
39
+ # with no value like (disabled and readonly), give it a value of true in
40
+ # the +options+ hash. You can use symbols or strings for the attribute names.
41
+ #
42
+ # content_tag(:p, "Hello world!")
43
+ # # => <p>Hello world!</p>
44
+ # content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
45
+ # # => <div class="strong"><p>Hello world!</p></div>
46
+ # content_tag("select", options, :multiple => true)
47
+ # # => <select multiple="multiple">...options...</select>
48
+ #
49
+ # Instead of passing the content as an argument, you can also use a block
50
+ # in which case, you pass your +options+ as the second parameter.
51
+ #
52
+ # <% content_tag :div, :class => "strong" do -%>
53
+ # Hello world!
54
+ # <% end -%>
55
+ # # => <div class="strong"><p>Hello world!</p></div>
56
+ def content_tag(name, content_or_options_with_block = nil, options = nil, &block)
57
+ if block_given?
58
+ options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
59
+ content = capture(&block)
60
+ content_tag = content_tag_string(name, content, options)
61
+ block_is_within_action_view?(block) ? concat(content_tag, block.binding) : content_tag
62
+ else
63
+ content = content_or_options_with_block
64
+ content_tag_string(name, content, options)
65
+ end
66
+ end
67
+
68
+ # Returns a CDATA section with the given +content+. CDATA sections
69
+ # are used to escape blocks of text containing characters which would
70
+ # otherwise be recognized as markup. CDATA sections begin with the string
71
+ # <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
72
+ #
73
+ # cdata_section("<hello world>")
74
+ # # => <![CDATA[<hello world>]]>
75
+ def cdata_section(content)
76
+ "<![CDATA[#{content}]]>"
77
+ end
78
+
79
+ # Returns the escaped +html+ without affecting existing escaped entities.
80
+ #
81
+ # escape_once("1 > 2 &amp; 3")
82
+ # # => "1 &lt; 2 &amp; 3"
83
+ def escape_once(html)
84
+ fix_double_escape(html_escape(html.to_s))
85
+ end
86
+
87
+ private
88
+ def content_tag_string(name, content, options)
89
+ tag_options = options ? tag_options(options) : ""
90
+ "<#{name}#{tag_options}>#{content}</#{name}>"
91
+ end
92
+
93
+ def tag_options(options)
94
+ cleaned_options = convert_booleans(options.stringify_keys.reject {|key, value| value.nil?})
95
+ ' ' + cleaned_options.map {|key, value| %(#{key}="#{escape_once(value)}")}.sort * ' ' unless cleaned_options.empty?
96
+ end
97
+
98
+ def convert_booleans(options)
99
+ %w( disabled readonly multiple ).each { |a| boolean_attribute(options, a) }
100
+ options
101
+ end
102
+
103
+ def boolean_attribute(options, attribute)
104
+ options[attribute] ? options[attribute] = attribute : options.delete(attribute)
105
+ end
106
+
107
+ # Fix double-escaped entities, such as &amp;amp;, &amp;#123;, etc.
108
+ def fix_double_escape(escaped)
109
+ escaped.gsub(/&amp;([a-z]+|(#\d+));/i) { "&#{$1};" }
110
+ end
111
+
112
+ def block_is_within_action_view?(block)
113
+ eval("defined? _erbout", block.binding)
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,303 @@
1
+ # ===========================================================================
2
+ # Project: Abbot - SproutCore Build Tools
3
+ # Copyright: ©2009 Apple, Inc.
4
+ # portions copyright @2006-2009 Sprout Systems, Inc.
5
+ # and contributors
6
+ # ===========================================================================
7
+
8
+ require File.join(SC::LIBPATH, 'sproutcore', 'helpers', 'tag_helper')
9
+ #require 'html/document'
10
+
11
+ # Borrowed from Rails 2.0.2
12
+
13
+ module SC
14
+ module Helpers #:nodoc:
15
+ # The TextHelper Module provides a set of methods for filtering, formatting
16
+ # and transforming strings that can reduce the amount of inline Ruby code in
17
+ # your views. These helper methods extend ActionView making them callable
18
+ # within your template files as shown in the following example which truncates
19
+ # the title of each post to 10 characters.
20
+ #
21
+ # <% @posts.each do |post| %>
22
+ # # post == 'This is my title'
23
+ # Title: <%= truncate(post.title, 10) %>
24
+ # <% end %>
25
+ # => Title: This is my...
26
+ module TextHelper
27
+ # The preferred method of outputting text in your views is to use the
28
+ # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods
29
+ # do not operate as expected in an eRuby code block. If you absolutely must
30
+ # output text within a code block, you can use the concat method.
31
+ #
32
+ # <% concat "hello", binding %>
33
+ # is equivalent to using:
34
+ # <%= "hello" %>
35
+ def concat(string, binding)
36
+ renderer.concat(string, binding)
37
+ end
38
+
39
+ # Highlights one or more +phrases+ everywhere in +text+ by inserting it into
40
+ # a +highlighter+ string. The highlighter can be specialized by passing +highlighter+
41
+ # as a single-quoted string with \1 where the phrase is to be inserted.
42
+ #
43
+ # highlight('You searched for: rails', 'rails')
44
+ # # => You searched for: <strong class="highlight">rails</strong>
45
+ #
46
+ # highlight('You searched for: rails', ['for', 'rails'], '<em>\1</em>')
47
+ # # => You searched <em>for</em>: <em>rails</em>
48
+ def highlight(text, phrases, highlighter = '<strong class="highlight">\1</strong>')
49
+ if text.blank? || phrases.blank?
50
+ text
51
+ else
52
+ match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
53
+ text.gsub(/(#{match})/i, highlighter)
54
+ end
55
+ end
56
+
57
+ # Attempts to pluralize the +singular+ word unless +count+ is 1. If +plural+
58
+ # is supplied, it will use that when count is > 1, if the ActiveSupport Inflector
59
+ # is loaded, it will use the Inflector to determine the plural form, otherwise
60
+ # it will just add an 's' to the +singular+ word.
61
+ #
62
+ # pluralize(1, 'person') => 1 person
63
+ # pluralize(2, 'person') => 2 people
64
+ # pluralize(3, 'person', 'users') => 3 users
65
+ def pluralize(count, singular, plural = nil)
66
+ "#{count || 0} " + if count == 1 || count == '1'
67
+ singular
68
+ elsif plural
69
+ plural
70
+ else
71
+ singular.plural
72
+ end
73
+ end
74
+
75
+ begin
76
+ unless Object.const_defined?(:RedCloth)
77
+ gem "RedCloth"
78
+ require 'redcloth'
79
+ end
80
+
81
+ # Returns the text with all the Textile codes turned into HTML tags.
82
+ # <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
83
+ # is available</i>.
84
+ def textilize(text)
85
+ if text.blank?
86
+ ""
87
+ else
88
+ textilized = RedCloth.new(text, [ :hard_breaks ])
89
+ textilized.hard_breaks = true if textilized.respond_to?("hard_breaks=")
90
+ textilized.to_html
91
+ end
92
+ end
93
+
94
+ # Returns the text with all the Textile codes turned into HTML tags,
95
+ # but without the bounding <p> tag that RedCloth adds.
96
+ # <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
97
+ # is available</i>.
98
+ def textilize_without_paragraph(text)
99
+ textiled = textilize(text)
100
+ if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
101
+ if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end
102
+ return textiled
103
+ end
104
+ rescue LoadError
105
+ # We can't really help what's not there
106
+ end
107
+
108
+ begin
109
+ unless Object.const_defined?(:BlueCloth)
110
+ begin
111
+ require 'bluecloth'
112
+ rescue
113
+ gem 'bluecloth'
114
+ require 'bluecloth'
115
+ end
116
+ end
117
+
118
+ # Returns the text with all the Markdown codes turned into HTML tags.
119
+ # <i>This method is only available if BlueCloth[http://www.deveiate.org/projects/BlueCloth]
120
+ # is available</i>.
121
+ def markdown(text)
122
+ text.blank? ? "" : BlueCloth.new(text).to_html
123
+ end
124
+ rescue LoadError
125
+ # We can't really help what's not there
126
+ end
127
+
128
+ # Returns +text+ transformed into HTML using simple formatting rules.
129
+ # Two or more consecutive newlines(<tt>\n\n</tt>) are considered as a
130
+ # paragraph and wrapped in <tt><p></tt> tags. One newline (<tt>\n</tt>) is
131
+ # considered as a linebreak and a <tt><br /></tt> tag is appended. This
132
+ # method does not remove the newlines from the +text+.
133
+ def simple_format(text)
134
+ content_tag 'p', text.to_s.
135
+ gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
136
+ gsub(/\n\n+/, "</p>\n\n<p>"). # 2+ newline -> paragraph
137
+ gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
138
+ end
139
+
140
+ # Turns all urls and email addresses into clickable links. The +link+ parameter
141
+ # will limit what should be linked. You can add html attributes to the links using
142
+ # +href_options+. Options for +link+ are <tt>:all</tt> (default),
143
+ # <tt>:email_addresses</tt>, and <tt>:urls</tt>.
144
+ #
145
+ # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") =>
146
+ # Go to <a href="http://www.rubyonrails.org">http://www.rubyonrails.org</a> and
147
+ # say hello to <a href="mailto:david@loudthinking.com">david@loudthinking.com</a>
148
+ #
149
+ # If a block is given, each url and email address is yielded and the
150
+ # result is used as the link text.
151
+ #
152
+ # auto_link(post.body, :all, :target => '_blank') do |text|
153
+ # truncate(text, 15)
154
+ # end
155
+ def auto_link(text, link = :all, href_options = {}, &block)
156
+ return '' if text.blank?
157
+ case link
158
+ when :all then auto_link_urls(auto_link_email_addresses(text, &block), href_options, &block)
159
+ when :email_addresses then auto_link_email_addresses(text, &block)
160
+ when :urls then auto_link_urls(text, href_options, &block)
161
+ end
162
+ end
163
+
164
+ # Strips link tags from +text+ leaving just the link label.
165
+ #
166
+ # strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
167
+ # => Ruby on Rails
168
+ def strip_links(text)
169
+ text.gsub(/<a\b.*?>(.*?)<\/a>/mi, '\1')
170
+ end
171
+
172
+ # Creates a Cycle object whose _to_s_ method cycles through elements of an
173
+ # array every time it is called. This can be used for example, to alternate
174
+ # classes for table rows:
175
+ #
176
+ # <% @items.each do |item| %>
177
+ # <tr class="<%= cycle("even", "odd") -%>">
178
+ # <td>item</td>
179
+ # </tr>
180
+ # <% end %>
181
+ #
182
+ # You can use named cycles to allow nesting in loops. Passing a Hash as
183
+ # the last parameter with a <tt>:name</tt> key will create a named cycle.
184
+ # You can manually reset a cycle by calling reset_cycle and passing the
185
+ # name of the cycle.
186
+ #
187
+ # <% @items.each do |item| %>
188
+ # <tr class="<%= cycle("even", "odd", :name => "row_class")
189
+ # <td>
190
+ # <% item.values.each do |value| %>
191
+ # <span style="color:<%= cycle("red", "green", "blue", :name => "colors") -%>">
192
+ # value
193
+ # </span>
194
+ # <% end %>
195
+ # <% reset_cycle("colors") %>
196
+ # </td>
197
+ # </tr>
198
+ # <% end %>
199
+ def cycle(first_value, *values)
200
+ if (values.last.instance_of? Hash)
201
+ params = values.pop
202
+ name = params[:name]
203
+ else
204
+ name = "default"
205
+ end
206
+ values.unshift(first_value)
207
+
208
+ cycle = get_cycle(name)
209
+ if (cycle.nil? || cycle.values != values)
210
+ cycle = set_cycle(name, Cycle.new(*values))
211
+ end
212
+ return cycle.to_s
213
+ end
214
+
215
+ # Resets a cycle so that it starts from the first element the next time
216
+ # it is called. Pass in +name+ to reset a named cycle.
217
+ def reset_cycle(name = "default")
218
+ cycle = get_cycle(name)
219
+ cycle.reset unless cycle.nil?
220
+ end
221
+
222
+ class Cycle #:nodoc:
223
+ attr_reader :values
224
+
225
+ def initialize(first_value, *values)
226
+ @values = values.unshift(first_value)
227
+ reset
228
+ end
229
+
230
+ def reset
231
+ @index = 0
232
+ end
233
+
234
+ def to_s
235
+ value = @values[@index].to_s
236
+ @index = (@index + 1) % @values.size
237
+ return value
238
+ end
239
+ end
240
+
241
+ private
242
+ # The cycle helpers need to store the cycles in a place that is
243
+ # guaranteed to be reset every time a page is rendered, so it
244
+ # uses an instance variable of ActionView::Base.
245
+ def get_cycle(name)
246
+ @_cycles = Hash.new unless defined?(@_cycles)
247
+ return @_cycles[name]
248
+ end
249
+
250
+ def set_cycle(name, cycle_object)
251
+ @_cycles = Hash.new unless defined?(@_cycles)
252
+ @_cycles[name] = cycle_object
253
+ end
254
+
255
+ AUTO_LINK_RE = %r{
256
+ ( # leading text
257
+ <\w+.*?>| # leading HTML tag, or
258
+ [^=!:'"/]| # leading punctuation, or
259
+ ^ # beginning of line
260
+ )
261
+ (
262
+ (?:https?://)| # protocol spec, or
263
+ (?:www\.) # www.*
264
+ )
265
+ (
266
+ [-\w]+ # subdomain or domain
267
+ (?:\.[-\w]+)* # remaining subdomains or domain
268
+ (?::\d+)? # port
269
+ (?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path
270
+ (?:\?[\w\+%&=.;-]+)? # query string
271
+ (?:\#[\w\-]*)? # trailing anchor
272
+ )
273
+ ([[:punct:]]|\s|<|$) # trailing text
274
+ }x unless const_defined?(:AUTO_LINK_RE)
275
+
276
+ # Turns all urls into clickable links. If a block is given, each url
277
+ # is yielded and the result is used as the link text.
278
+ def auto_link_urls(text, href_options = {})
279
+ extra_options = tag_options(href_options.stringify_keys) || ""
280
+ text.gsub(AUTO_LINK_RE) do
281
+ all, a, b, c, d = $&, $1, $2, $3, $4
282
+ if a =~ /<a\s/i # don't replace URL's that are already linked
283
+ all
284
+ else
285
+ text = b + c
286
+ text = yield(text) if block_given?
287
+ %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>#{d})
288
+ end
289
+ end
290
+ end
291
+
292
+ # Turns all email addresses into clickable links. If a block is given,
293
+ # each email is yielded and the result is used as the link text.
294
+ def auto_link_email_addresses(text)
295
+ text.gsub(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
296
+ text = $1
297
+ text = yield(text) if block_given?
298
+ %{<a href="mailto:#{$1}">#{text}</a>}
299
+ end
300
+ end
301
+ end
302
+ end
303
+ end