sproutcore 0.9.0

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 (270) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +269 -0
  4. data/README.txt +67 -0
  5. data/Rakefile +4 -0
  6. data/app_generators/sproutcore/USAGE +5 -0
  7. data/app_generators/sproutcore/sproutcore_generator.rb +66 -0
  8. data/app_generators/sproutcore/templates/README +77 -0
  9. data/app_generators/sproutcore/templates/environment.yml +4 -0
  10. data/bin/sc-build +145 -0
  11. data/bin/sc-gen +24 -0
  12. data/bin/sc-server +63 -0
  13. data/bin/sproutcore +21 -0
  14. data/clients/sc_docs/controllers/docs.js +118 -0
  15. data/clients/sc_docs/core.js +19 -0
  16. data/clients/sc_docs/english.lproj/body.css +159 -0
  17. data/clients/sc_docs/english.lproj/body.rhtml +33 -0
  18. data/clients/sc_docs/english.lproj/controls.css +0 -0
  19. data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
  20. data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
  21. data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
  22. data/clients/sc_docs/english.lproj/images/indicator.gif +0 -0
  23. data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
  24. data/clients/sc_docs/english.lproj/no_docs.rhtml +7 -0
  25. data/clients/sc_docs/english.lproj/strings.js +14 -0
  26. data/clients/sc_docs/english.lproj/warning.rhtml +6 -0
  27. data/clients/sc_docs/fixtures/doc.js +11 -0
  28. data/clients/sc_docs/main.js +21 -0
  29. data/clients/sc_docs/models/doc.js +9 -0
  30. data/clients/sc_docs/tests/controllers/docs.rhtml +21 -0
  31. data/clients/sc_docs/tests/models/doc.rhtml +21 -0
  32. data/clients/sc_docs/tests/views/doc_frame.rhtml +21 -0
  33. data/clients/sc_docs/tests/views/doc_label_view.rhtml +21 -0
  34. data/clients/sc_docs/views/doc_frame.js +33 -0
  35. data/clients/sc_docs/views/doc_label.js +20 -0
  36. data/clients/sc_test_runner/controllers/runner.js +175 -0
  37. data/clients/sc_test_runner/core.js +19 -0
  38. data/clients/sc_test_runner/english.lproj/body.css +151 -0
  39. data/clients/sc_test_runner/english.lproj/body.rhtml +35 -0
  40. data/clients/sc_test_runner/english.lproj/controls.css +0 -0
  41. data/clients/sc_test_runner/english.lproj/icons/small/next.png +0 -0
  42. data/clients/sc_test_runner/english.lproj/icons/small/reset.png +0 -0
  43. data/clients/sc_test_runner/english.lproj/images/gradients.png +0 -0
  44. data/clients/sc_test_runner/english.lproj/images/indicator.gif +0 -0
  45. data/clients/sc_test_runner/english.lproj/images/toolbar.png +0 -0
  46. data/clients/sc_test_runner/english.lproj/no_tests.rhtml +6 -0
  47. data/clients/sc_test_runner/english.lproj/strings.js +14 -0
  48. data/clients/sc_test_runner/english.lproj/warning.rhtml +6 -0
  49. data/clients/sc_test_runner/fixtures/test.js +12 -0
  50. data/clients/sc_test_runner/main.js +26 -0
  51. data/clients/sc_test_runner/models/test.js +11 -0
  52. data/clients/sc_test_runner/views/runner_frame.js +72 -0
  53. data/clients/sc_test_runner/views/test_label.js +20 -0
  54. data/config/hoe.rb +70 -0
  55. data/config/requirements.rb +17 -0
  56. data/environment.yml +9 -0
  57. data/frameworks/prototype/prototype.js +4186 -0
  58. data/frameworks/sproutcore/Core.js +378 -0
  59. data/frameworks/sproutcore/README +3 -0
  60. data/frameworks/sproutcore/controllers/array.js +236 -0
  61. data/frameworks/sproutcore/controllers/collection.js +305 -0
  62. data/frameworks/sproutcore/controllers/controller.js +323 -0
  63. data/frameworks/sproutcore/controllers/object.js +372 -0
  64. data/frameworks/sproutcore/drag/drag.js +549 -0
  65. data/frameworks/sproutcore/drag/drag_data_source.js +32 -0
  66. data/frameworks/sproutcore/drag/drag_source.js +64 -0
  67. data/frameworks/sproutcore/drag/drop_target.js +153 -0
  68. data/frameworks/sproutcore/english.lproj/blank.gif +0 -0
  69. data/frameworks/sproutcore/english.lproj/buttons.css +589 -0
  70. data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
  71. data/frameworks/sproutcore/english.lproj/inline_text_editor.css +21 -0
  72. data/frameworks/sproutcore/english.lproj/menu.css +121 -0
  73. data/frameworks/sproutcore/english.lproj/panels/background-fat.jpg +0 -0
  74. data/frameworks/sproutcore/english.lproj/panels/background-thin.jpg +0 -0
  75. data/frameworks/sproutcore/english.lproj/panels/bottom-edge.png +0 -0
  76. data/frameworks/sproutcore/english.lproj/panels/bottom-left-corner.png +0 -0
  77. data/frameworks/sproutcore/english.lproj/panels/bottom-right-corner.png +0 -0
  78. data/frameworks/sproutcore/english.lproj/panels/left-edge.png +0 -0
  79. data/frameworks/sproutcore/english.lproj/panels/overlay.png +0 -0
  80. data/frameworks/sproutcore/english.lproj/panels/right-edge.png +0 -0
  81. data/frameworks/sproutcore/english.lproj/panels/top-edge.png +0 -0
  82. data/frameworks/sproutcore/english.lproj/panels/top-left-corner.png +0 -0
  83. data/frameworks/sproutcore/english.lproj/panels/top-right-corner.png +0 -0
  84. data/frameworks/sproutcore/english.lproj/panes.css +155 -0
  85. data/frameworks/sproutcore/english.lproj/picker.css +22 -0
  86. data/frameworks/sproutcore/english.lproj/strings.js +15 -0
  87. data/frameworks/sproutcore/english.lproj/tab.css +23 -0
  88. data/frameworks/sproutcore/english.lproj/tests.css +67 -0
  89. data/frameworks/sproutcore/english.lproj/theme.css +77 -0
  90. data/frameworks/sproutcore/foundation/animator.js +670 -0
  91. data/frameworks/sproutcore/foundation/application.js +199 -0
  92. data/frameworks/sproutcore/foundation/array.js +348 -0
  93. data/frameworks/sproutcore/foundation/benchmark.js +211 -0
  94. data/frameworks/sproutcore/foundation/binding.js +384 -0
  95. data/frameworks/sproutcore/foundation/date.js +357 -0
  96. data/frameworks/sproutcore/foundation/error.js +39 -0
  97. data/frameworks/sproutcore/foundation/input_manager.js +153 -0
  98. data/frameworks/sproutcore/foundation/json.js +296 -0
  99. data/frameworks/sproutcore/foundation/mock.js +42 -0
  100. data/frameworks/sproutcore/foundation/node_descriptor.js +56 -0
  101. data/frameworks/sproutcore/foundation/object.js +777 -0
  102. data/frameworks/sproutcore/foundation/observable.js +451 -0
  103. data/frameworks/sproutcore/foundation/page.js +63 -0
  104. data/frameworks/sproutcore/foundation/path_module.js +413 -0
  105. data/frameworks/sproutcore/foundation/responder.js +310 -0
  106. data/frameworks/sproutcore/foundation/routes.js +371 -0
  107. data/frameworks/sproutcore/foundation/run_loop.js +21 -0
  108. data/frameworks/sproutcore/foundation/server.js +491 -0
  109. data/frameworks/sproutcore/foundation/set.js +96 -0
  110. data/frameworks/sproutcore/foundation/string.js +149 -0
  111. data/frameworks/sproutcore/foundation/undo_manager.js +186 -0
  112. data/frameworks/sproutcore/foundation/unittest.js +622 -0
  113. data/frameworks/sproutcore/foundation/utils.js +61 -0
  114. data/frameworks/sproutcore/globals/panels.js +182 -0
  115. data/frameworks/sproutcore/globals/popups.js +60 -0
  116. data/frameworks/sproutcore/globals/window.js +381 -0
  117. data/frameworks/sproutcore/lib/index.rhtml +66 -0
  118. data/frameworks/sproutcore/models/collection.js +395 -0
  119. data/frameworks/sproutcore/models/record.js +622 -0
  120. data/frameworks/sproutcore/models/store.js +295 -0
  121. data/frameworks/sproutcore/panes/dialog.js +16 -0
  122. data/frameworks/sproutcore/panes/manager.js +164 -0
  123. data/frameworks/sproutcore/panes/menu.js +45 -0
  124. data/frameworks/sproutcore/panes/overlay.js +231 -0
  125. data/frameworks/sproutcore/panes/pane.js +90 -0
  126. data/frameworks/sproutcore/panes/panel.js +19 -0
  127. data/frameworks/sproutcore/panes/picker.js +45 -0
  128. data/frameworks/sproutcore/tests/controllers/array.rhtml +86 -0
  129. data/frameworks/sproutcore/tests/controllers/controller.rhtml +273 -0
  130. data/frameworks/sproutcore/tests/controllers/object.rhtml +327 -0
  131. data/frameworks/sproutcore/tests/foundation/application.rhtml +125 -0
  132. data/frameworks/sproutcore/tests/foundation/array.rhtml +221 -0
  133. data/frameworks/sproutcore/tests/foundation/object.rhtml +69 -0
  134. data/frameworks/sproutcore/tests/globals/window.rhtml +45 -0
  135. data/frameworks/sproutcore/tests/panes/pane.rhtml +88 -0
  136. data/frameworks/sproutcore/tests/views/collection.rhtml +137 -0
  137. data/frameworks/sproutcore/tests/views/popup_button.rhtml +115 -0
  138. data/frameworks/sproutcore/tests/views/text_field.rhtml +37 -0
  139. data/frameworks/sproutcore/validators/credit_card.js +92 -0
  140. data/frameworks/sproutcore/validators/date.js +36 -0
  141. data/frameworks/sproutcore/validators/email.js +29 -0
  142. data/frameworks/sproutcore/validators/not_empty.js +24 -0
  143. data/frameworks/sproutcore/validators/number.js +55 -0
  144. data/frameworks/sproutcore/validators/password.js +78 -0
  145. data/frameworks/sproutcore/validators/validator.js +304 -0
  146. data/frameworks/sproutcore/views/button.js +425 -0
  147. data/frameworks/sproutcore/views/checkbox_field.js +30 -0
  148. data/frameworks/sproutcore/views/collection.js +1521 -0
  149. data/frameworks/sproutcore/views/container.js +62 -0
  150. data/frameworks/sproutcore/views/error_explanation.js +45 -0
  151. data/frameworks/sproutcore/views/field.js +214 -0
  152. data/frameworks/sproutcore/views/filter_button.js +29 -0
  153. data/frameworks/sproutcore/views/form.js +591 -0
  154. data/frameworks/sproutcore/views/image.js +141 -0
  155. data/frameworks/sproutcore/views/inline_text_editor.js +96 -0
  156. data/frameworks/sproutcore/views/label.js +176 -0
  157. data/frameworks/sproutcore/views/menu_item.js +90 -0
  158. data/frameworks/sproutcore/views/pagination.js +54 -0
  159. data/frameworks/sproutcore/views/popup_button.js +86 -0
  160. data/frameworks/sproutcore/views/popup_menu.js +137 -0
  161. data/frameworks/sproutcore/views/progress.js +100 -0
  162. data/frameworks/sproutcore/views/radio_field.js +107 -0
  163. data/frameworks/sproutcore/views/radio_group.js +48 -0
  164. data/frameworks/sproutcore/views/segmented.js +80 -0
  165. data/frameworks/sproutcore/views/select_field.js +272 -0
  166. data/frameworks/sproutcore/views/spinner.js +11 -0
  167. data/frameworks/sproutcore/views/tab.js +126 -0
  168. data/frameworks/sproutcore/views/text_field.js +179 -0
  169. data/frameworks/sproutcore/views/textarea_field.js +14 -0
  170. data/frameworks/sproutcore/views/toolbar.js +29 -0
  171. data/frameworks/sproutcore/views/view.js +1389 -0
  172. data/frameworks/sproutcore/views/workspace.js +170 -0
  173. data/generators/client/README +3 -0
  174. data/generators/client/USAGE +12 -0
  175. data/generators/client/client_generator.rb +53 -0
  176. data/generators/client/templates/core.js +19 -0
  177. data/generators/client/templates/english.lproj/body.css +0 -0
  178. data/generators/client/templates/english.lproj/body.rhtml +3 -0
  179. data/generators/client/templates/english.lproj/controls.css +0 -0
  180. data/generators/client/templates/english.lproj/strings.js +14 -0
  181. data/generators/client/templates/main.js +37 -0
  182. data/generators/controller/USAGE +16 -0
  183. data/generators/controller/controller_generator.rb +51 -0
  184. data/generators/controller/templates/controller.js +21 -0
  185. data/generators/controller/templates/test.rhtml +21 -0
  186. data/generators/framework/README +7 -0
  187. data/generators/framework/USAGE +12 -0
  188. data/generators/framework/framework_generator.rb +53 -0
  189. data/generators/framework/templates/core.js +20 -0
  190. data/generators/framework/templates/english.lproj/body.css +0 -0
  191. data/generators/framework/templates/english.lproj/body.rhtml +3 -0
  192. data/generators/framework/templates/english.lproj/controls.css +0 -0
  193. data/generators/framework/templates/english.lproj/strings.js +14 -0
  194. data/generators/language/USAGE +16 -0
  195. data/generators/language/language_generator.rb +47 -0
  196. data/generators/language/templates/strings.js +10 -0
  197. data/generators/model/USAGE +24 -0
  198. data/generators/model/model_generator.rb +55 -0
  199. data/generators/model/templates/fixture.js +11 -0
  200. data/generators/model/templates/model.js +20 -0
  201. data/generators/model/templates/test.rhtml +21 -0
  202. data/generators/test/USAGE +16 -0
  203. data/generators/test/templates/test.rhtml +21 -0
  204. data/generators/test/test_generator.rb +47 -0
  205. data/generators/view/USAGE +16 -0
  206. data/generators/view/templates/test.rhtml +21 -0
  207. data/generators/view/templates/view.js +20 -0
  208. data/generators/view/view_generator.rb +51 -0
  209. data/jsdoc/README.txt +119 -0
  210. data/jsdoc/app/DocFile.js +137 -0
  211. data/jsdoc/app/DocTag.js +110 -0
  212. data/jsdoc/app/Doclet.js +63 -0
  213. data/jsdoc/app/Dumper.js +143 -0
  214. data/jsdoc/app/JsDoc.js +103 -0
  215. data/jsdoc/app/JsHilite.js +45 -0
  216. data/jsdoc/app/JsIO.js +163 -0
  217. data/jsdoc/app/JsParse.js +385 -0
  218. data/jsdoc/app/JsPlate.js +130 -0
  219. data/jsdoc/app/JsTestrun.js +129 -0
  220. data/jsdoc/app/JsToke.js +564 -0
  221. data/jsdoc/app/Symbol.js +298 -0
  222. data/jsdoc/app/Transformer.js +14 -0
  223. data/jsdoc/app/Util.js +97 -0
  224. data/jsdoc/app/js.jar +0 -0
  225. data/jsdoc/app/run.js +144 -0
  226. data/jsdoc/plugins/min.js +316 -0
  227. data/jsdoc/plugins/strip.js +20 -0
  228. data/jsdoc/templates/sproutcore/class.tmpl +438 -0
  229. data/jsdoc/templates/sproutcore/default.css +241 -0
  230. data/jsdoc/templates/sproutcore/index.html +13 -0
  231. data/jsdoc/templates/sproutcore/index.tmpl +21 -0
  232. data/jsdoc/templates/sproutcore/prototype.js +4186 -0
  233. data/jsdoc/templates/sproutcore/publish.js +236 -0
  234. data/jsdoc/templates/sproutcore/splash.html +7 -0
  235. data/lib/sproutcore/build_tools/html_builder.rb +88 -0
  236. data/lib/sproutcore/build_tools/resource_builder.rb +194 -0
  237. data/lib/sproutcore/build_tools.rb +44 -0
  238. data/lib/sproutcore/bundle.rb +517 -0
  239. data/lib/sproutcore/bundle_manifest.rb +397 -0
  240. data/lib/sproutcore/generator_helper.rb +170 -0
  241. data/lib/sproutcore/helpers/capture_helper.rb +42 -0
  242. data/lib/sproutcore/helpers/static_helper.rb +80 -0
  243. data/lib/sproutcore/helpers/tag_helper.rb +110 -0
  244. data/lib/sproutcore/helpers/text_helper.rb +336 -0
  245. data/lib/sproutcore/helpers.rb +3 -0
  246. data/lib/sproutcore/jsdoc.rb +40 -0
  247. data/lib/sproutcore/jsmin.rb +247 -0
  248. data/lib/sproutcore/library.rb +258 -0
  249. data/lib/sproutcore/merb/bundle_controller.rb +179 -0
  250. data/lib/sproutcore/merb/router.rb +43 -0
  251. data/lib/sproutcore/merb.rb +27 -0
  252. data/lib/sproutcore/version.rb +9 -0
  253. data/lib/sproutcore/view_helpers/button_views.rb +302 -0
  254. data/lib/sproutcore/view_helpers/core_views.rb +284 -0
  255. data/lib/sproutcore/view_helpers/form_views.rb +258 -0
  256. data/lib/sproutcore/view_helpers/menu_views.rb +94 -0
  257. data/lib/sproutcore/view_helpers.rb +628 -0
  258. data/lib/sproutcore.rb +30 -0
  259. data/script/destroy +14 -0
  260. data/script/generate +14 -0
  261. data/script/txt2html +74 -0
  262. data/setup.rb +1585 -0
  263. data/spec/spec.opts +1 -0
  264. data/spec/spec_helper.rb +7 -0
  265. data/spec/sproutcore_spec.rb +11 -0
  266. data/tasks/deployment.rake +34 -0
  267. data/tasks/environment.rake +7 -0
  268. data/tasks/rspec.rake +21 -0
  269. data/tasks/website.rake +17 -0
  270. metadata +365 -0
@@ -0,0 +1,110 @@
1
+ require 'cgi'
2
+ require 'erb'
3
+
4
+ # Borrowed from Rails 2.0.2
5
+
6
+ module SproutCore
7
+ module Helpers #:nodoc:
8
+ # Use these methods to generate HTML tags programmatically when you can't use
9
+ # a Builder. By default, they output XHTML compliant tags.
10
+ module TagHelper
11
+ include ERB::Util
12
+
13
+ # Returns an empty HTML tag of type +name+ which by default is XHTML
14
+ # compliant. Setting +open+ to true will create an open tag compatible
15
+ # with HTML 4.0 and below. Add HTML attributes by passing an attributes
16
+ # hash to +options+. For attributes with no value like (disabled and
17
+ # readonly), give it a value of true in the +options+ hash. You can use
18
+ # symbols or strings for the attribute names.
19
+ #
20
+ # tag("br")
21
+ # # => <br />
22
+ # tag("br", nil, true)
23
+ # # => <br>
24
+ # tag("input", { :type => 'text', :disabled => true })
25
+ # # => <input type="text" disabled="disabled" />
26
+ def tag(name, options = nil, open = false)
27
+ "<#{name}#{tag_options(options) if options}" + (open ? ">" : " />")
28
+ end
29
+
30
+ # Returns an HTML block tag of type +name+ surrounding the +content+. Add
31
+ # HTML attributes by passing an attributes hash to +options+. For attributes
32
+ # with no value like (disabled and readonly), give it a value of true in
33
+ # the +options+ hash. You can use symbols or strings for the attribute names.
34
+ #
35
+ # content_tag(:p, "Hello world!")
36
+ # # => <p>Hello world!</p>
37
+ # content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
38
+ # # => <div class="strong"><p>Hello world!</p></div>
39
+ # content_tag("select", options, :multiple => true)
40
+ # # => <select multiple="multiple">...options...</select>
41
+ #
42
+ # Instead of passing the content as an argument, you can also use a block
43
+ # in which case, you pass your +options+ as the second parameter.
44
+ #
45
+ # <% content_tag :div, :class => "strong" do -%>
46
+ # Hello world!
47
+ # <% end -%>
48
+ # # => <div class="strong"><p>Hello world!</p></div>
49
+ def content_tag(name, content_or_options_with_block = nil, options = nil, &block)
50
+ if block_given?
51
+ options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
52
+ content = capture(&block)
53
+ content_tag = content_tag_string(name, content, options)
54
+ block_is_within_action_view?(block) ? concat(content_tag, block.binding) : content_tag
55
+ else
56
+ content = content_or_options_with_block
57
+ content_tag_string(name, content, options)
58
+ end
59
+ end
60
+
61
+ # Returns a CDATA section with the given +content+. CDATA sections
62
+ # are used to escape blocks of text containing characters which would
63
+ # otherwise be recognized as markup. CDATA sections begin with the string
64
+ # <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
65
+ #
66
+ # cdata_section("<hello world>")
67
+ # # => <![CDATA[<hello world>]]>
68
+ def cdata_section(content)
69
+ "<![CDATA[#{content}]]>"
70
+ end
71
+
72
+ # Returns the escaped +html+ without affecting existing escaped entities.
73
+ #
74
+ # escape_once("1 > 2 &amp; 3")
75
+ # # => "1 &lt; 2 &amp; 3"
76
+ def escape_once(html)
77
+ fix_double_escape(html_escape(html.to_s))
78
+ end
79
+
80
+ private
81
+ def content_tag_string(name, content, options)
82
+ tag_options = options ? tag_options(options) : ""
83
+ "<#{name}#{tag_options}>#{content}</#{name}>"
84
+ end
85
+
86
+ def tag_options(options)
87
+ cleaned_options = convert_booleans(options.stringify_keys.reject {|key, value| value.nil?})
88
+ ' ' + cleaned_options.map {|key, value| %(#{key}="#{escape_once(value)}")}.sort * ' ' unless cleaned_options.empty?
89
+ end
90
+
91
+ def convert_booleans(options)
92
+ %w( disabled readonly multiple ).each { |a| boolean_attribute(options, a) }
93
+ options
94
+ end
95
+
96
+ def boolean_attribute(options, attribute)
97
+ options[attribute] ? options[attribute] = attribute : options.delete(attribute)
98
+ end
99
+
100
+ # Fix double-escaped entities, such as &amp;amp;, &amp;#123;, etc.
101
+ def fix_double_escape(escaped)
102
+ escaped.gsub(/&amp;([a-z]+|(#\d+));/i) { "&#{$1};" }
103
+ end
104
+
105
+ def block_is_within_action_view?(block)
106
+ eval("defined? _erbout", block.binding)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,336 @@
1
+ require 'sproutcore/helpers/tag_helper'
2
+ #require 'html/document'
3
+
4
+ # Borrowed from Rails 2.0.2
5
+
6
+ module SproutCore
7
+ module Helpers #:nodoc:
8
+ # The TextHelper Module provides a set of methods for filtering, formatting
9
+ # and transforming strings that can reduce the amount of inline Ruby code in
10
+ # your views. These helper methods extend ActionView making them callable
11
+ # within your template files as shown in the following example which truncates
12
+ # the title of each post to 10 characters.
13
+ #
14
+ # <% @posts.each do |post| %>
15
+ # # post == 'This is my title'
16
+ # Title: <%= truncate(post.title, 10) %>
17
+ # <% end %>
18
+ # => Title: This is my...
19
+ module TextHelper
20
+ # The preferred method of outputting text in your views is to use the
21
+ # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods
22
+ # do not operate as expected in an eRuby code block. If you absolutely must
23
+ # output text within a code block, you can use the concat method.
24
+ #
25
+ # <% concat "hello", binding %>
26
+ # is equivalent to using:
27
+ # <%= "hello" %>
28
+ def concat(string, binding)
29
+ eval('_buf', binding) << string
30
+ end
31
+
32
+ # If +text+ is longer than +length+, +text+ will be truncated to the length of
33
+ # +length+ and the last three characters will be replaced with the +truncate_string+.
34
+ #
35
+ # truncate("Once upon a time in a world far far away", 14)
36
+ # => Once upon a...
37
+ def truncate(text, length = 30, truncate_string = "...")
38
+ if text.nil? then return end
39
+ l = length - truncate_string.chars.length
40
+ (text.chars.length > length ? text.chars[0...l] + truncate_string : text).to_s
41
+ end
42
+
43
+ # Highlights one or more +phrases+ everywhere in +text+ by inserting it into
44
+ # a +highlighter+ string. The highlighter can be specialized by passing +highlighter+
45
+ # as a single-quoted string with \1 where the phrase is to be inserted.
46
+ #
47
+ # highlight('You searched for: rails', 'rails')
48
+ # # => You searched for: <strong class="highlight">rails</strong>
49
+ #
50
+ # highlight('You searched for: rails', ['for', 'rails'], '<em>\1</em>')
51
+ # # => You searched <em>for</em>: <em>rails</em>
52
+ def highlight(text, phrases, highlighter = '<strong class="highlight">\1</strong>')
53
+ if text.blank? || phrases.blank?
54
+ text
55
+ else
56
+ match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
57
+ text.gsub(/(#{match})/i, highlighter)
58
+ end
59
+ end
60
+
61
+ # Extracts an excerpt from +text+ that matches the first instance of +phrase+.
62
+ # The +radius+ expands the excerpt on each side of +phrase+ by the number of characters
63
+ # defined in +radius+. If the excerpt radius overflows the beginning or end of the +text+,
64
+ # then the +excerpt_string+ will be prepended/appended accordingly. If the +phrase+
65
+ # isn't found, nil is returned.
66
+ #
67
+ # excerpt('This is an example', 'an', 5)
68
+ # => "...s is an examp..."
69
+ #
70
+ # excerpt('This is an example', 'is', 5)
71
+ # => "This is an..."
72
+ def excerpt(text, phrase, radius = 100, excerpt_string = "...")
73
+ if text.nil? || phrase.nil? then return end
74
+ phrase = Regexp.escape(phrase)
75
+
76
+ if found_pos = text.chars =~ /(#{phrase})/i
77
+ start_pos = [ found_pos - radius, 0 ].max
78
+ end_pos = [ found_pos + phrase.chars.length + radius, text.chars.length ].min
79
+
80
+ prefix = start_pos > 0 ? excerpt_string : ""
81
+ postfix = end_pos < text.chars.length ? excerpt_string : ""
82
+
83
+ prefix + text.chars[start_pos..end_pos].strip + postfix
84
+ else
85
+ nil
86
+ end
87
+ end
88
+
89
+ # Attempts to pluralize the +singular+ word unless +count+ is 1. If +plural+
90
+ # is supplied, it will use that when count is > 1, if the ActiveSupport Inflector
91
+ # is loaded, it will use the Inflector to determine the plural form, otherwise
92
+ # it will just add an 's' to the +singular+ word.
93
+ #
94
+ # pluralize(1, 'person') => 1 person
95
+ # pluralize(2, 'person') => 2 people
96
+ # pluralize(3, 'person', 'users') => 3 users
97
+ def pluralize(count, singular, plural = nil)
98
+ "#{count || 0} " + if count == 1 || count == '1'
99
+ singular
100
+ elsif plural
101
+ plural
102
+ elsif Object.const_defined?("Inflector")
103
+ Inflector.pluralize(singular)
104
+ else
105
+ singular + "s"
106
+ end
107
+ end
108
+
109
+ # Wraps the +text+ into lines no longer than +line_width+ width. This method
110
+ # breaks on the first whitespace character that does not exceed +line_width+.
111
+ #
112
+ # word_wrap('Once upon a time', 4)
113
+ # => Once\nupon\na\ntime
114
+ def word_wrap(text, line_width = 80)
115
+ text.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
116
+ end
117
+
118
+ begin
119
+ require_library_or_gem "redcloth" unless Object.const_defined?(:RedCloth)
120
+
121
+ # Returns the text with all the Textile codes turned into HTML tags.
122
+ # <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
123
+ # is available</i>.
124
+ def textilize(text)
125
+ if text.blank?
126
+ ""
127
+ else
128
+ textilized = RedCloth.new(text, [ :hard_breaks ])
129
+ textilized.hard_breaks = true if textilized.respond_to?("hard_breaks=")
130
+ textilized.to_html
131
+ end
132
+ end
133
+
134
+ # Returns the text with all the Textile codes turned into HTML tags,
135
+ # but without the bounding <p> tag that RedCloth adds.
136
+ # <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
137
+ # is available</i>.
138
+ def textilize_without_paragraph(text)
139
+ textiled = textilize(text)
140
+ if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
141
+ if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end
142
+ return textiled
143
+ end
144
+ rescue LoadError
145
+ # We can't really help what's not there
146
+ end
147
+
148
+ begin
149
+ require_library_or_gem "bluecloth" unless Object.const_defined?(:BlueCloth)
150
+
151
+ # Returns the text with all the Markdown codes turned into HTML tags.
152
+ # <i>This method is only available if BlueCloth[http://www.deveiate.org/projects/BlueCloth]
153
+ # is available</i>.
154
+ def markdown(text)
155
+ text.blank? ? "" : BlueCloth.new(text).to_html
156
+ end
157
+ rescue LoadError
158
+ # We can't really help what's not there
159
+ end
160
+
161
+ # Returns +text+ transformed into HTML using simple formatting rules.
162
+ # Two or more consecutive newlines(<tt>\n\n</tt>) are considered as a
163
+ # paragraph and wrapped in <tt><p></tt> tags. One newline (<tt>\n</tt>) is
164
+ # considered as a linebreak and a <tt><br /></tt> tag is appended. This
165
+ # method does not remove the newlines from the +text+.
166
+ def simple_format(text)
167
+ content_tag 'p', text.to_s.
168
+ gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
169
+ gsub(/\n\n+/, "</p>\n\n<p>"). # 2+ newline -> paragraph
170
+ gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
171
+ end
172
+
173
+ # Turns all urls and email addresses into clickable links. The +link+ parameter
174
+ # will limit what should be linked. You can add html attributes to the links using
175
+ # +href_options+. Options for +link+ are <tt>:all</tt> (default),
176
+ # <tt>:email_addresses</tt>, and <tt>:urls</tt>.
177
+ #
178
+ # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") =>
179
+ # Go to <a href="http://www.rubyonrails.org">http://www.rubyonrails.org</a> and
180
+ # say hello to <a href="mailto:david@loudthinking.com">david@loudthinking.com</a>
181
+ #
182
+ # If a block is given, each url and email address is yielded and the
183
+ # result is used as the link text.
184
+ #
185
+ # auto_link(post.body, :all, :target => '_blank') do |text|
186
+ # truncate(text, 15)
187
+ # end
188
+ def auto_link(text, link = :all, href_options = {}, &block)
189
+ return '' if text.blank?
190
+ case link
191
+ when :all then auto_link_urls(auto_link_email_addresses(text, &block), href_options, &block)
192
+ when :email_addresses then auto_link_email_addresses(text, &block)
193
+ when :urls then auto_link_urls(text, href_options, &block)
194
+ end
195
+ end
196
+
197
+ # Strips link tags from +text+ leaving just the link label.
198
+ #
199
+ # strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
200
+ # => Ruby on Rails
201
+ def strip_links(text)
202
+ text.gsub(/<a\b.*?>(.*?)<\/a>/mi, '\1')
203
+ end
204
+
205
+ # Creates a Cycle object whose _to_s_ method cycles through elements of an
206
+ # array every time it is called. This can be used for example, to alternate
207
+ # classes for table rows:
208
+ #
209
+ # <% @items.each do |item| %>
210
+ # <tr class="<%= cycle("even", "odd") -%>">
211
+ # <td>item</td>
212
+ # </tr>
213
+ # <% end %>
214
+ #
215
+ # You can use named cycles to allow nesting in loops. Passing a Hash as
216
+ # the last parameter with a <tt>:name</tt> key will create a named cycle.
217
+ # You can manually reset a cycle by calling reset_cycle and passing the
218
+ # name of the cycle.
219
+ #
220
+ # <% @items.each do |item| %>
221
+ # <tr class="<%= cycle("even", "odd", :name => "row_class")
222
+ # <td>
223
+ # <% item.values.each do |value| %>
224
+ # <span style="color:<%= cycle("red", "green", "blue", :name => "colors") -%>">
225
+ # value
226
+ # </span>
227
+ # <% end %>
228
+ # <% reset_cycle("colors") %>
229
+ # </td>
230
+ # </tr>
231
+ # <% end %>
232
+ def cycle(first_value, *values)
233
+ if (values.last.instance_of? Hash)
234
+ params = values.pop
235
+ name = params[:name]
236
+ else
237
+ name = "default"
238
+ end
239
+ values.unshift(first_value)
240
+
241
+ cycle = get_cycle(name)
242
+ if (cycle.nil? || cycle.values != values)
243
+ cycle = set_cycle(name, Cycle.new(*values))
244
+ end
245
+ return cycle.to_s
246
+ end
247
+
248
+ # Resets a cycle so that it starts from the first element the next time
249
+ # it is called. Pass in +name+ to reset a named cycle.
250
+ def reset_cycle(name = "default")
251
+ cycle = get_cycle(name)
252
+ cycle.reset unless cycle.nil?
253
+ end
254
+
255
+ class Cycle #:nodoc:
256
+ attr_reader :values
257
+
258
+ def initialize(first_value, *values)
259
+ @values = values.unshift(first_value)
260
+ reset
261
+ end
262
+
263
+ def reset
264
+ @index = 0
265
+ end
266
+
267
+ def to_s
268
+ value = @values[@index].to_s
269
+ @index = (@index + 1) % @values.size
270
+ return value
271
+ end
272
+ end
273
+
274
+ private
275
+ # The cycle helpers need to store the cycles in a place that is
276
+ # guaranteed to be reset every time a page is rendered, so it
277
+ # uses an instance variable of ActionView::Base.
278
+ def get_cycle(name)
279
+ @_cycles = Hash.new unless defined?(@_cycles)
280
+ return @_cycles[name]
281
+ end
282
+
283
+ def set_cycle(name, cycle_object)
284
+ @_cycles = Hash.new unless defined?(@_cycles)
285
+ @_cycles[name] = cycle_object
286
+ end
287
+
288
+ AUTO_LINK_RE = %r{
289
+ ( # leading text
290
+ <\w+.*?>| # leading HTML tag, or
291
+ [^=!:'"/]| # leading punctuation, or
292
+ ^ # beginning of line
293
+ )
294
+ (
295
+ (?:https?://)| # protocol spec, or
296
+ (?:www\.) # www.*
297
+ )
298
+ (
299
+ [-\w]+ # subdomain or domain
300
+ (?:\.[-\w]+)* # remaining subdomains or domain
301
+ (?::\d+)? # port
302
+ (?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path
303
+ (?:\?[\w\+%&=.;-]+)? # query string
304
+ (?:\#[\w\-]*)? # trailing anchor
305
+ )
306
+ ([[:punct:]]|\s|<|$) # trailing text
307
+ }x unless const_defined?(:AUTO_LINK_RE)
308
+
309
+ # Turns all urls into clickable links. If a block is given, each url
310
+ # is yielded and the result is used as the link text.
311
+ def auto_link_urls(text, href_options = {})
312
+ extra_options = tag_options(href_options.stringify_keys) || ""
313
+ text.gsub(AUTO_LINK_RE) do
314
+ all, a, b, c, d = $&, $1, $2, $3, $4
315
+ if a =~ /<a\s/i # don't replace URL's that are already linked
316
+ all
317
+ else
318
+ text = b + c
319
+ text = yield(text) if block_given?
320
+ %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>#{d})
321
+ end
322
+ end
323
+ end
324
+
325
+ # Turns all email addresses into clickable links. If a block is given,
326
+ # each email is yielded and the result is used as the link text.
327
+ def auto_link_email_addresses(text)
328
+ text.gsub(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
329
+ text = $1
330
+ text = yield(text) if block_given?
331
+ %{<a href="mailto:#{$1}">#{text}</a>}
332
+ end
333
+ end
334
+ end
335
+ end
336
+ end
@@ -0,0 +1,3 @@
1
+ # Helpers are mostly borrowed from Rails 2.0.2 with some additional features specifically
2
+ # for building client-side JavaScript.
3
+ Dir.glob(File.join(File.dirname(__FILE__),'helpers','**','*.rb')).each { |x| require x }
@@ -0,0 +1,40 @@
1
+ # This utility module will use jsdoc to create documentation from a SproutCore
2
+ # client. Note that for this to work you must have Java installed (sudder).
3
+ module SproutCore
4
+
5
+ module JSDoc
6
+
7
+ # Creates the documentation for the specified set of clients, replacing
8
+ # the contents of the output file. Requires some of the following
9
+ # options.
10
+ #
11
+ # :bundle => A Bundle instance - or -
12
+ # :files => Absolute paths to input files
13
+ # :build_path => absolute path to the build root. Uses the bundle if not provided.
14
+ def self.generate(opts = {})
15
+ bundle = opts[:bundle]
16
+ build_path = opts[:build_path] || File.join(bundle.build_root, '-docs', 'data')
17
+ raise "MISSING OPTION: :bundle => bundle or :build_path => path required for JSDoc" if build_path.nil?
18
+
19
+ # get the list of files to build for.
20
+ files = opts[:files]
21
+ if files.nil?
22
+ raise "MISSING OPTION: :bundle => bundle or :files => list of files required for JSDoc" if bundle.nil?
23
+ entries = bundle.entries_for(:javascript, :hidden => :include)
24
+ files = entries.map { |x| x.composite? ? nil : x.source_path }.compact.uniq
25
+ end
26
+
27
+ # Ensure directory exists
28
+ FileUtils.mkdir_p(build_path)
29
+
30
+ # Now run jsdoc
31
+ jsdoc_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'jsdoc'))
32
+ jar_path = File.join(jsdoc_root, 'app', 'js.jar')
33
+ runjs_path = File.join(jsdoc_root, 'app', 'run.js')
34
+ template_path = File.join(jsdoc_root, 'templates', 'sproutcore')
35
+
36
+ SC.logger.debug `java -Djsdoc.dir=#{jsdoc_root} -jar #{jar_path} #{runjs_path} -t=#{template_path} -d=#{build_path} #{files * ' '} -v`
37
+
38
+ end
39
+ end
40
+ end