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,247 @@
1
+ # This version of jsmin has been adapted for use in a module.
2
+
3
+ # jsmin.rb 2007-07-20
4
+ # Author: Uladzislau Latynski
5
+ # This work is a translation from C to Ruby of jsmin.c published by
6
+ # Douglas Crockford. Permission is hereby granted to use the Ruby
7
+ # version under the same conditions as the jsmin.c on which it is
8
+ # based.
9
+ #
10
+ # /* jsmin.c
11
+ # 2003-04-21
12
+ #
13
+ # Copyright (c) 2002 Douglas Crockford (www.crockford.com)
14
+ #
15
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
16
+ # this software and associated documentation files (the "Software"), to deal in
17
+ # the Software without restriction, including without limitation the rights to
18
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
19
+ # of the Software, and to permit persons to whom the Software is furnished to do
20
+ # so, subject to the following conditions:
21
+ #
22
+ # The above copyright notice and this permission notice shall be included in all
23
+ # copies or substantial portions of the Software.
24
+ #
25
+ # The Software shall be used for Good, not Evil.
26
+ #
27
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
+ # SOFTWARE.
34
+
35
+ module SproutCore
36
+
37
+ class JSMin
38
+ EOF = -1
39
+
40
+ # this will minify a single line
41
+ def self.run(str)
42
+ minifier = SproutCore::JSMin.new(str)
43
+ minifier.jsmin
44
+ minifier.stdout
45
+ end
46
+
47
+ def initialize(str)
48
+ @theA = ""
49
+ @theB = ""
50
+ @str = str || ''
51
+ @loc = 0
52
+ @stdout = ''
53
+ end
54
+
55
+ def stdin_getc
56
+ ret = @str.nil? || (@loc >= @str.size) ? nil : @str[@loc]
57
+ @loc += 1
58
+ return ret
59
+ end
60
+
61
+ def stdin_ungetc(str)
62
+ @loc -= 1
63
+ @loc = 0 if @loc < 0
64
+ end
65
+
66
+ def stdout_write(chr)
67
+ @stdout << chr
68
+ end
69
+
70
+ def stdout
71
+ return @stdout
72
+ end
73
+
74
+ #### JSMIN
75
+ ## To update, replace the text below with the latest jsmin.rb. Then replace:
76
+ ## $theA => @theA, $theB => @theB,
77
+ ## $stdin.getc => stdin_getc, $stdin.ungetc => stding_ungetc,
78
+ ## $stdout.write => stdout_write
79
+
80
+ # isAlphanum -- return true if the character is a letter, digit,
81
+ # underscore, dollar sign, or non-ASCII character
82
+ def isAlphanum(c)
83
+ return false if !c || c == EOF
84
+ return ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
85
+ (c >= 'A' && c <= 'Z') || c == '_' || c == '$' ||
86
+ c == '\\' || c[0] > 126)
87
+ end
88
+
89
+ # get -- return the next character from stdin. Watch out for lookahead.
90
+ # If the character is a control character, translate it to a space or
91
+ # linefeed.
92
+ def get()
93
+ c = stdin_getc
94
+ return EOF if(!c)
95
+ c = c.chr
96
+ return c if (c >= " " || c == "\n" || c.unpack("c") == EOF)
97
+ return "\n" if (c == "\r")
98
+ return " "
99
+ end
100
+
101
+ # Get the next character without getting it.
102
+ def peek()
103
+ lookaheadChar = stdin_getc
104
+ stdin_ungetc(lookaheadChar)
105
+ return lookaheadChar.chr
106
+ end
107
+
108
+ # mynext -- get the next character, excluding comments.
109
+ # peek() is used to see if a '/' is followed by a '/' or '*'.
110
+ def mynext()
111
+ c = get
112
+ if (c == "/")
113
+ if(peek == "/")
114
+ while(true)
115
+ c = get
116
+ if (c <= "\n")
117
+ return c
118
+ end
119
+ end
120
+ end
121
+ if(peek == "*")
122
+ get
123
+ while(true)
124
+ case get
125
+ when "*"
126
+ if (peek == "/")
127
+ get
128
+ return " "
129
+ end
130
+ when EOF
131
+ raise "Unterminated comment"
132
+ end
133
+ end
134
+ end
135
+ end
136
+ return c
137
+ end
138
+
139
+
140
+ # action -- do something! What you do is determined by the argument: 1
141
+ # Output A. Copy B to A. Get the next B. 2 Copy B to A. Get the next B.
142
+ # (Delete A). 3 Get the next B. (Delete B). action treats a string as a
143
+ # single character. Wow! action recognizes a regular expression if it is
144
+ # preceded by ( or , or =.
145
+ def action(a)
146
+ if(a==1)
147
+ stdout_write @theA
148
+ end
149
+ if(a==1 || a==2)
150
+ @theA = @theB
151
+ if (@theA == "\'" || @theA == "\"")
152
+ while (true)
153
+ stdout_write @theA
154
+ @theA = get
155
+ break if (@theA == @theB)
156
+ raise "Unterminated string literal" if (@theA <= "\n")
157
+ if (@theA == "\\")
158
+ stdout_write @theA
159
+ @theA = get
160
+ end
161
+ end
162
+ end
163
+ end
164
+ if(a==1 || a==2 || a==3)
165
+ @theB = mynext
166
+ if (@theB == "/" && (@theA == "(" || @theA == "," || @theA == "=" ||
167
+ @theA == ":" || @theA == "[" || @theA == "!" ||
168
+ @theA == "&" || @theA == "|" || @theA == "?" ||
169
+ @theA == "{" || @theA == "}" || @theA == ";" ||
170
+ @theA == "\n"))
171
+ stdout_write @theA
172
+ stdout_write @theB
173
+ while (true)
174
+ @theA = get
175
+ if (@theA == "/")
176
+ break
177
+ elsif (@theA == "\\")
178
+ stdout_write @theA
179
+ @theA = get
180
+ elsif (@theA <= "\n")
181
+ raise "Unterminated RegExp Literal"
182
+ end
183
+ stdout_write @theA
184
+ end
185
+ @theB = mynext
186
+ end
187
+ end
188
+ end
189
+
190
+ # jsmin -- Copy the input to the output, deleting the characters which are
191
+ # insignificant to JavaScript. Comments will be removed. Tabs will be
192
+ # replaced with spaces. Carriage returns will be replaced with linefeeds.
193
+ # Most spaces and linefeeds will be removed.
194
+ def jsmin
195
+ @theA = "\n"
196
+ action(3)
197
+ while (@theA != EOF)
198
+ case @theA
199
+ when " "
200
+ if (isAlphanum(@theB))
201
+ action(1)
202
+ else
203
+ action(2)
204
+ end
205
+ when "\n"
206
+ case (@theB)
207
+ when "{","[","(","+","-"
208
+ action(1)
209
+ when " "
210
+ action(3)
211
+ else
212
+ if (isAlphanum(@theB))
213
+ action(1)
214
+ else
215
+ action(2)
216
+ end
217
+ end
218
+ else
219
+ case (@theB)
220
+ when " "
221
+ if (isAlphanum(@theA))
222
+ action(1)
223
+ else
224
+ action(3)
225
+ end
226
+ when "\n"
227
+ case (@theA)
228
+ when "}","]",")","+","-","\"","\\", "'", '"'
229
+ action(1)
230
+ else
231
+ if (isAlphanum(@theA))
232
+ action(1)
233
+ else
234
+ action(3)
235
+ end
236
+ end
237
+ else
238
+ action(1)
239
+ end
240
+ end
241
+ end
242
+ end
243
+
244
+ ################ END JSMIN
245
+ end
246
+
247
+ end
@@ -0,0 +1,258 @@
1
+ require 'yaml'
2
+
3
+ module SproutCore
4
+
5
+ # Describes a single library that can contain one or more clients and frameworks.
6
+ # This class is used to automatically locate all installed libraries and to register the
7
+ # clients within them.
8
+ #
9
+ # Libraries are chained, with the child library replacing the parent library's settings.
10
+ # In general, the root library is always the current app while its parent libraries are
11
+ # those found in the load path or explicitly stated in the configs.
12
+ class Library
13
+
14
+ # Creates a chained set of libraries from the passed location and the load path
15
+ def self.library_for(root_path, opts = {})
16
+
17
+ # Find libraries in the search paths, build chain
18
+ root_path = File.expand_path(root_path)
19
+ paths = libraries_in($:).reject { |x| x == root_path }
20
+ paths.unshift(root_path)
21
+ ret = nil
22
+
23
+ # Convert chain to library objects. The last path processed should be
24
+ # the one passed in to this method.
25
+ while path = paths.pop
26
+ ret = self.new(path, opts, ret)
27
+ end
28
+
29
+ # Return library object for root_path
30
+ return ret
31
+ end
32
+
33
+ # Searches the array of paths, returning the array of paths that are actually libraries.
34
+ #
35
+ # ==== Params
36
+ # paths<Array>:: Array of libraries.
37
+ #
38
+ def self.libraries_in(paths)
39
+ ret = paths.map do |p|
40
+ p = File.expand_path(p) # expand
41
+ [p, p.gsub(/\/lib$/,'')].reject { |x| !is_library?(x) }
42
+ end
43
+ ret.flatten.compact.uniq
44
+ end
45
+
46
+ # Heuristically determine if a particular location is a library.
47
+ def self.is_library?(path)
48
+ has_it = %w(clients frameworks environment.yml).map do |x|
49
+ File.exists?(File.join(path, x))
50
+ end
51
+ return false unless has_it.pop
52
+ has_it.each { |x| return true if x }
53
+ return false
54
+ end
55
+
56
+ # The root path for this library
57
+ attr_reader :root_path
58
+
59
+ # The raw environment hash loaded from disk. Generally use computed_environment,
60
+ # which combines the parent.
61
+ attr_reader :environment
62
+
63
+ # The parent library, used for load order dependency
64
+ attr_accessor :next_library
65
+
66
+ # The client directories found in this library. This usually maps directly to a
67
+ # client name but it may not if you have set up some other options.
68
+ def client_directories
69
+ return @client_dirs unless @client_dirs.nil?
70
+ client_path = File.join(@root_path, 'clients')
71
+ if File.exists?(client_path)
72
+ @client_dirs = Dir.entries(client_path).reject do |x|
73
+ (/^\./ =~ x) || !File.directory?(File.join(client_path,x))
74
+ end
75
+ else
76
+ @client_dirs = []
77
+ end
78
+
79
+ return @client_dirs
80
+ end
81
+
82
+ # The framework directories found in this library
83
+ def framework_directories
84
+ return @framework_dirs unless @framework_dirs.nil?
85
+ framework_path = File.join(@root_path, 'frameworks')
86
+ if File.exists?(framework_path)
87
+ @framework_dirs = Dir.entries(framework_path).reject do |x|
88
+ (/^\./ =~ x) || !File.directory?(File.join(framework_path,x))
89
+ end
90
+ else
91
+ @framework_dirs = []
92
+ end
93
+
94
+ return @framework_dirs
95
+ end
96
+
97
+ # Returns all of the client names known to the current environment, including
98
+ # through parent libraries.
99
+ def client_names
100
+ return @cache_client_names unless @cache_client_names.nil?
101
+
102
+ ret = next_library.nil? ? [] : next_library.client_directories
103
+ ret += client_directories
104
+ return @cache_client_names = ret.compact.uniq.sort
105
+ end
106
+
107
+ # Returns all of the framework names known to the current environment, including
108
+ # through parent libraries.
109
+ def framework_names
110
+ return @cache_framework_names unless @cache_framework_names.nil?
111
+
112
+ ret = next_library.nil? ? [] : next_library.framework_directories
113
+ ret += framework_directories
114
+ return @cache_framework_names = ret.compact.uniq.sort
115
+ end
116
+
117
+ # ==== Returns
118
+ # A hash of all bundle names mapped to root url. This method is optimized for frequent
119
+ # requests so you can use it to route incoming requests.
120
+ def bundles_grouped_by_url
121
+ return @cached_bundles_by_url unless @cached_bundles_by_url.nil?
122
+ ret = {}
123
+ bundles.each { |b| ret[b.url_root] = b; ret[b.index_root] = b }
124
+ return @cached_bundles_by_url = ret
125
+ end
126
+
127
+ # ==== Returns
128
+ # A bundle for the specified name. If the bundle has not already been created, then
129
+ # it will be created.
130
+ def bundle_for(bundle_name)
131
+ bundle_name = bundle_name.to_sym
132
+ @bundles ||= {}
133
+ return @bundles[bundle_name] ||= Bundle.new(bundle_name, environment_for(bundle_name))
134
+ end
135
+
136
+ # ==== Returns
137
+ # All of the bundles for registered clients
138
+ def client_bundles
139
+ @cached_client_bundles ||= client_names.map { |x| bundle_for(x) }
140
+ end
141
+
142
+ # ==== Returns
143
+ # All of the bundles for registered frameworks
144
+ def framework_bundles
145
+ @cached_framework_bundles ||= framework_names.map { |x| bundle_for(x) }
146
+ end
147
+
148
+ # ==== Returns
149
+ # All known bundles, both framework & client
150
+ def bundles
151
+ @cached_all_bundles ||= (client_bundles + framework_bundles)
152
+ end
153
+
154
+ # Build all of the bundles in the library. This can take awhile but it is the simple
155
+ # way to get all of your code onto disk in a deployable state
156
+ def build(*languages)
157
+ (client_bundles + framework_bundles).each do |bundle|
158
+ puts "building: #{bundle.bundle_name}"
159
+ bundle.build(*languages)
160
+ end
161
+ end
162
+
163
+ # Returns the computed environment for a particular client or framework.
164
+ # This will go up the chain of parent libraries, retrieving and merging any known
165
+ # environment settings. The returned options are suitable for passing to the ClientBuilder
166
+ # for registration.
167
+ def environment_for(bundle_name)
168
+
169
+ is_local_client = client_directories.include?(bundle_name.to_s)
170
+ is_local_framework = framework_directories.include?(bundle_name.to_s)
171
+ ret = nil
172
+
173
+ # CASE 1: If named client or framework is local, then use our local settings
174
+ if (is_local_client || is_local_framework)
175
+
176
+ # start with local environment
177
+ ret = (environment[:all] || {}).dup
178
+
179
+ # Now fill in some default values based on what we know
180
+ # This should be enough to make the bundle load
181
+ ret[:bundle_name] = bundle_name.to_sym
182
+ ret[:bundle_type] = is_local_framework ? :framework : :client
183
+ ret[:requires] = [:prototype, :sproutcore] if ret[:requires].nil?
184
+
185
+ # Fill in the source_root since we know where this came from
186
+ ret[:source_root] = File.join(root_path, ret[:bundle_type].to_s.pluralize, bundle_name.to_s)
187
+
188
+ # CASE 2: Otherwise, if we have a next library, see if the next library has something
189
+ else
190
+ ret = next_library.nil? ? nil : next_library.environment_for(bundle_name)
191
+ end
192
+
193
+ # Final fixup
194
+ unless ret.nil?
195
+ # Always url_prefix & index_prefix are always used.
196
+ all = environment[:all] || {}
197
+ [:url_prefix, :all_prefix, :preferred_language].each do |key|
198
+ ret[key] = all[key] if all.include?(key)
199
+ end
200
+
201
+ # Either way, if we have local settings for this specific client, they override whatever
202
+ # we cooked up just now.
203
+ local_settings = environment[bundle_name.to_sym]
204
+ ret = ret.merge(local_settings) unless local_settings.nil?
205
+
206
+ # Always replace the library with self so that we get the correct root location for
207
+ # public paths, etc.
208
+ ret[:library] = self
209
+ end
210
+
211
+
212
+ # CASE 3: Next library doesn't know about this client. Neither do we. Even if the
213
+ # user has provided some environmental options, there is no source content, so just
214
+ # return nil
215
+ return ret
216
+ end
217
+
218
+ protected
219
+
220
+ # Load the library at the specified path. Loads the environment.yml if it exists
221
+ # and then detects all clients and frameworks in the library. If you pass any options,
222
+ # those will overlay any :all options you specify in your environment.yml file.
223
+ #
224
+ # You cannot create a library directly using this method. Instead is library_in()
225
+ #
226
+ def initialize(rp, opts = {}, next_lib = nil)
227
+ @root_path = rp
228
+ @next_library = next_lib
229
+ @load_opts = opts
230
+ load_environment!(opts)
231
+ end
232
+
233
+ # Internal method loads the actual environment
234
+ def load_environment!(opts=nil)
235
+ env_path = File.join(root_path, 'environment.yml')
236
+ env = {}
237
+ if File.exists?(env_path)
238
+ f = File.open(env_path)
239
+ env = YAML::load(f) rescue nil
240
+ f.close
241
+ end
242
+ env = {} if env.nil?
243
+
244
+ # symbolize
245
+ @environment = {}
246
+ env.each do |k,v|
247
+ @environment[k.to_sym] = v.respond_to?(:symbolize_keys) ? v.symbolize_keys : v
248
+ end
249
+
250
+ # Overlay :all opts, if passed
251
+ @environment[:all] = (@environment[:all] || {}).merge(opts) unless opts.nil?
252
+ end
253
+
254
+ end
255
+
256
+ end
257
+
258
+
@@ -0,0 +1,179 @@
1
+ require 'sproutcore/jsdoc'
2
+
3
+ module SproutCore
4
+ module Merb
5
+
6
+ # A subclass of this controller handles all incoming requests for the location it is
7
+ # mounted at. For index.html requests, it will rebuild the html file everytime it is
8
+ # requested if you are in development mode. For all other requests, it will build the
9
+ # resource one time and then return the file if it already exists.
10
+ class BundleController < ::Merb::Controller
11
+
12
+ def self.library_for_class(klass)
13
+ (@registered_libraries ||= {})[klass]
14
+ end
15
+
16
+ def self.register_library_for_class(library, klass)
17
+ (@registered_libraries ||= {})[klass] = library
18
+ end
19
+
20
+ # Entry point for all requests routed through the SproutCore controller. Example
21
+ # the request path to determine which bundle should handle the request.
22
+ def main
23
+
24
+ # Before we do anything, set the build_mode for the bundles. This shouldn't change
25
+ # during execution, but if we set this during the router call, the Merb.environment
26
+ # is sometimes not ready yet.
27
+ if ::Merb.environment.to_sym == :production
28
+ Bundle.build_mode = :production
29
+ else
30
+ ::SproutCore.logger.level = Logger::DEBUG
31
+ end
32
+
33
+ # Make sure we can service this with a bundle
34
+ raise(NotFound, "No SproutCore Bundle registered at this location.") if current_bundle.nil?
35
+
36
+ # Check for a few special urls that need to be rewritten
37
+ url = request.path
38
+ puts "BEFORE URL: #{url} current_bundle: #{current_bundle.bundle_name}"
39
+ if request.method == :get
40
+ url = rewrite_bundle_if(url, /^#{current_bundle.index_root}\/-tests/, :sc_test_runner)
41
+ url = rewrite_bundle_if(url, /^#{current_bundle.index_root}\/-docs/, :sc_docs)
42
+ end
43
+
44
+ # If we are in development mode, reload bundle first
45
+ current_bundle.reload! if current_bundle.build_mode == :development
46
+
47
+ puts "AFTER URL: #{url} current_bundle: #{current_bundle.bundle_name}"
48
+
49
+ # Get the normalized URL for the requested resource
50
+ url = current_bundle.normalize_url(url)
51
+
52
+
53
+ # Check for a few special urls for built-in services and route them off
54
+ case url
55
+ when "#{current_bundle.url_root}/-tests/index.js"
56
+ ret = handle_test(url)
57
+ when "#{current_bundle.index_root}/-docs"
58
+ ret = (request.method == :post) ? handle_doc(url) : handle_resource(url)
59
+
60
+ when "#{current_bundle.url_root}/-docs"
61
+ ret = (request.method == :post) ? handle_doc(url) : handle_resource(url)
62
+
63
+ else
64
+ ret = handle_resource(url)
65
+ end
66
+
67
+ # Done!
68
+ return ret
69
+ end
70
+
71
+ # Invoked whenever you request a regular resource
72
+ def handle_resource(url)
73
+
74
+ # Get the entry for the resource.
75
+ entry = current_bundle.entry_for_url(url, :hidden => :include)
76
+ raise(NotFound, "No matching entry in #{current_bundle.bundle_name}") if entry.nil?
77
+
78
+
79
+ build_path = entry.build_path
80
+
81
+ # Found an entry, build the resource. If the resource has already been built, this
82
+ # will not do much. If this the resource is an index.html file, force the build.
83
+ is_index = /\/index\.html$/ =~ url
84
+ puts "building: #{url} - is_index: #{is_index}"
85
+
86
+ current_bundle.build_entry(entry, :force => is_index, :hidden => :include)
87
+
88
+ # Move to final build path if necessary
89
+ if (build_path != entry.build_path) && File.exists?(entry.build_path)
90
+ FileUtils.mv(entry.build_path, build_path)
91
+ end
92
+
93
+ # And return the file. Set the content type using a mime-map borroed from Rack.
94
+ headers['Content-Type'] = entry.content_type
95
+ headers['Content-Length'] = File.size(build_path).to_s
96
+ ret = File.open(build_path)
97
+
98
+
99
+ # In development mode only, immediately delete built composite resources. We want
100
+ # each request to come directly to us.
101
+ if (current_bundle.build_mode == :development) && (!entry.cacheable?)
102
+ FileUtils.rm(build_path)
103
+ end
104
+
105
+ return ret
106
+ end
107
+
108
+ # Returns JSON containing all of the tests
109
+ def handle_test(url)
110
+ test_entries = current_bundle.entries_for(:test, :hidden => :include)
111
+ content_type = :json
112
+ ret = test_entries.map do |entry|
113
+ { :name => entry.filename.gsub(/^tests\//,''), :url => "#{entry.url}?#{entry.timestamp}" }
114
+ end
115
+ return ret.to_json
116
+ end
117
+
118
+ # If you POST to this URL, regenerates the docs.
119
+ def handle_doc(url)
120
+ JSDoc.generate :bundle => current_bundle
121
+ return "OK"
122
+ end
123
+
124
+ ######################################################################
125
+ ## Support Methods
126
+ ##
127
+
128
+ # Returns the library for this class
129
+ def library
130
+ ::SproutCore::Merb::BundleController.library_for_class(self.class)
131
+ end
132
+
133
+
134
+ # Returns the bundle for this request
135
+ def current_bundle
136
+ return @current_bundle unless @current_bundle.nil?
137
+
138
+ # Tear down the URL, looking for the first bundle
139
+ bundle_map = library.bundles_grouped_by_url
140
+ url = request.path.split('/')
141
+ ret = nil
142
+ while url.size > 0 && ret.nil?
143
+ ret = bundle_map[url.join('/')]
144
+ url.pop
145
+ end
146
+
147
+ # Try root path if nothing found
148
+ ret = bundle_map['/'] if ret.nil?
149
+
150
+ # Return
151
+ return (@current_bundle = ret)
152
+ end
153
+
154
+ # This method is used to redirect certain urls to an alternate bundle. If the
155
+ # match phrase matches the url, then both the url we use to fetch resources and the
156
+ # current_bundle will be swapped out.
157
+ #
158
+ # ===== Params
159
+ # url<String>:: The url to check
160
+ # match<Regex>:: The pattern to match and optionally later replace
161
+ # new_bundle_name<Symbol>:: The name of the new bundle to swap in if matched
162
+ #
163
+ # ===== Returns
164
+ # The rewritten url. May also change the value of current_bundle
165
+ #
166
+ def rewrite_bundle_if(url, match, new_bundle_name)
167
+ return url unless match =~ url
168
+ new_bundle = library.bundle_for(new_bundle_name)
169
+ if new_bundle
170
+ url = url.gsub(match, new_bundle.index_root)
171
+ @current_bundle = new_bundle
172
+ end
173
+ return url
174
+ end
175
+
176
+ end
177
+
178
+ end
179
+ end