sproutit-sproutcore 1.0.0.20090407205609

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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