rsence 2.1.11 → 2.2.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 (216) hide show
  1. data/INSTALL.rdoc +5 -3
  2. data/README.rdoc +23 -22
  3. data/VERSION +1 -1
  4. data/conf/default_conf.yaml +65 -29
  5. data/conf/rsence_command_strings.yaml +101 -71
  6. data/js/comm/autosync/autosync.js +3 -3
  7. data/js/comm/jsloader/jsloader.js +16 -3
  8. data/js/comm/queue/queue.js +1 -1
  9. data/js/comm/transporter/transporter.js +106 -83
  10. data/js/comm/values/values.js +8 -2
  11. data/js/controls/button/button.js +9 -4
  12. data/js/controls/button/themes/default/button.css +1 -1
  13. data/js/controls/checkbox/themes/default/checkbox.css +1 -1
  14. data/js/controls/dialogs/sheet/sheet.js +27 -18
  15. data/js/controls/radiobutton/themes/default/radiobutton.css +1 -1
  16. data/js/controls/searchfield/searchfield.coffee +2 -0
  17. data/js/controls/searchfield/themes/default/searchfield.css +96 -0
  18. data/js/controls/searchfield/themes/default/searchfield.html +12 -0
  19. data/js/controls/searchfield/themes/default/searchfield_parts1-ie6.gif +0 -0
  20. data/js/controls/searchfield/themes/default/searchfield_parts1.png +0 -0
  21. data/js/controls/sliders/slider/slider.js +7 -1
  22. data/js/controls/stepper/stepper.js +6 -1
  23. data/js/controls/stringview/stringview.js +50 -39
  24. data/js/controls/tab/tab.js +103 -7
  25. data/js/controls/tab/themes/default/tab.css +2 -0
  26. data/js/controls/textarea/themes/default/textarea.css +4 -0
  27. data/js/controls/textcontrol/textcontrol.js +32 -2
  28. data/js/controls/textcontrol/themes/default/textcontrol.css +17 -2
  29. data/js/controls/uploader/themes/default/uploader.css +3 -3
  30. data/js/controls/uploader/themes/default/uploader.html +1 -1
  31. data/js/controls/uploader/uploader.coffee +110 -0
  32. data/js/controls/window/themes/default/window.css +28 -5
  33. data/js/controls/window/themes/default/window.html +2 -0
  34. data/js/controls/window/window.js +5 -1
  35. data/js/core/class/class.js +22 -4
  36. data/js/core/elem/elem.coffee +816 -0
  37. data/js/core/event/event.js +2 -2
  38. data/js/core/rsence_ns/rsence_ns.coffee +31 -0
  39. data/js/core/rsence_ns/rsence_ns.js +6 -6
  40. data/js/datetime/calendar/calendar.coffee +307 -0
  41. data/js/datetime/calendar/themes/default/calendar.css +90 -9
  42. data/js/datetime/calendar/themes/default/calendar.html +11 -0
  43. data/js/datetime/calendar/themes/default/calendar_bg-ie6.gif +0 -0
  44. data/js/datetime/calendar/themes/default/calendar_bg.png +0 -0
  45. data/js/datetime/calendar/themes/default/calendar_parts1-ie6.gif +0 -0
  46. data/js/datetime/calendar/themes/default/calendar_parts1.png +0 -0
  47. data/js/datetime/calendar/themes/default/calendar_parts2-ie6.gif +0 -0
  48. data/js/datetime/calendar/themes/default/calendar_parts2.png +0 -0
  49. data/js/datetime/datetimepicker/datetimepicker.js +217 -0
  50. data/js/datetime/datetimevalue/datetimevalue.js +22 -5
  51. data/js/datetime/timesheet/themes/default/timesheet.css +51 -22
  52. data/js/datetime/timesheet/themes/default/timesheet.html +4 -2
  53. data/js/datetime/timesheet/timesheet.js +782 -192
  54. data/js/datetime/timesheet_item/themes/default/timesheet_item.css +42 -11
  55. data/js/datetime/timesheet_item/themes/default/timesheet_item.html +4 -2
  56. data/js/datetime/timesheet_item/themes/default/timesheet_item_icons.png +0 -0
  57. data/js/datetime/timesheet_item/timesheet_item.js +158 -254
  58. data/js/datetime/timesheet_item_edit/timesheet_item_edit.js +0 -274
  59. data/js/foundation/application/application.js +52 -9
  60. data/js/foundation/control/eventresponder/eventresponder.js +7 -4
  61. data/js/foundation/control/valueaction/valueaction.js +71 -0
  62. data/js/foundation/eventmanager/eventmanager.js +71 -33
  63. data/js/foundation/geom/rect/rect.js +39 -7
  64. data/js/foundation/json_renderer/json_renderer.js +278 -62
  65. data/js/foundation/locale_settings/locale_settings.js +131 -0
  66. data/js/foundation/system/system.js +40 -13
  67. data/js/foundation/thememanager/thememanager.js +21 -0
  68. data/js/foundation/view/markupview/markupview.js +12 -12
  69. data/js/foundation/view/view.js +221 -27
  70. data/js/graphics/svgcontrol/svgcontrol.js +400 -0
  71. data/js/lists/checkboxlist/checkboxlist.js +18 -7
  72. data/js/lists/listitems/listitems.js +52 -38
  73. data/js/lists/radiobuttonlist/radiobuttonlist.js +23 -7
  74. data/js/menus/menuitem/menuitem.js +5 -0
  75. data/js/menus/menuitem/themes/default/menuitem.css +45 -0
  76. data/js/menus/menuitem/themes/default/menuitem.html +4 -0
  77. data/js/menus/minimenu/minimenu.js +47 -16
  78. data/js/menus/minimenuitem/minimenuitem.js +62 -0
  79. data/js/menus/{minimenu/minimenuitem → minimenuitem}/themes/default/minimenuitem.css +2 -2
  80. data/js/menus/{minimenu/minimenuitem → minimenuitem}/themes/default/minimenuitem.html +0 -0
  81. data/js/menus/{minimenu/minimenuitem → minimenuitem}/themes/default/minimenuitem_checkmark.png +0 -0
  82. data/js/menus/popupmenu/popupmenu.js +14 -0
  83. data/js/menus/popupmenu/themes/default/popupmenu.css +65 -0
  84. data/js/menus/popupmenu/themes/default/popupmenu.html +7 -0
  85. data/js/menus/popupmenu/themes/default/popupmenu.png +0 -0
  86. data/js/no_pkg/no_pkg.js +2 -0
  87. data/js/util/reloadapp/reloadapp.js +1 -1
  88. data/js/views/scrollview/scrollview.js +6 -0
  89. data/lib/rsence.rb +136 -3
  90. data/lib/rsence/argv.rb +218 -0
  91. data/lib/rsence/argv/argv_util.rb +58 -0
  92. data/lib/rsence/argv/env_check.rb +58 -0
  93. data/lib/rsence/argv/help_argv.rb +15 -0
  94. data/lib/rsence/argv/initenv_argv.rb +218 -0
  95. data/lib/rsence/argv/save_argv.rb +92 -0
  96. data/lib/rsence/argv/startup_argv.rb +118 -0
  97. data/lib/rsence/argv/status_argv.rb +132 -0
  98. data/lib/rsence/argv/test_port.rb +32 -0
  99. data/lib/{daemon → rsence}/daemon.rb +67 -23
  100. data/lib/{conf/default.rb → rsence/default_config.rb} +18 -10
  101. data/lib/{plugins → rsence}/dependencies.rb +0 -0
  102. data/lib/{util → rsence}/gzstring.rb +0 -0
  103. data/lib/rsence/http.rb +3 -0
  104. data/lib/{http → rsence/http}/broker.rb +106 -19
  105. data/lib/{http → rsence/http}/rackup.rb +0 -0
  106. data/lib/{http → rsence/http}/request.rb +0 -4
  107. data/lib/{http → rsence/http}/response.rb +0 -1
  108. data/lib/{session → rsence}/msg.rb +17 -1
  109. data/lib/{plugins → rsence}/pluginmanager.rb +29 -12
  110. data/lib/{plugins → rsence}/plugins.rb +7 -7
  111. data/lib/{plugins → rsence/plugins}/gui_plugin.rb +8 -3
  112. data/lib/{plugins → rsence/plugins}/guiparser.rb +9 -6
  113. data/lib/{plugins → rsence/plugins}/plugin.rb +23 -4
  114. data/lib/{plugins → rsence/plugins}/plugin_base.rb +11 -1
  115. data/lib/{plugins → rsence/plugins}/plugin_plugins.rb +2 -2
  116. data/lib/{plugins → rsence/plugins}/plugin_sqlite_db.rb +0 -0
  117. data/lib/{plugins → rsence/plugins}/servlet.rb +0 -0
  118. data/lib/{session → rsence}/sessionmanager.rb +101 -39
  119. data/lib/{session → rsence}/sessionstorage.rb +30 -16
  120. data/lib/{daemon → rsence}/sigcomm.rb +0 -0
  121. data/lib/{transporter → rsence}/transporter.rb +13 -11
  122. data/lib/{values/hvalue.rb → rsence/value.rb} +6 -1
  123. data/lib/{values → rsence}/valuemanager.rb +1 -1
  124. data/plugins/client_pkg/client_pkg.rb +14 -4
  125. data/plugins/client_pkg/info.yaml +2 -2
  126. data/plugins/client_pkg/lib/client_pkg_build.rb +145 -45
  127. data/plugins/client_pkg/lib/client_pkg_cache.rb +1 -1
  128. data/plugins/client_pkg/lib/client_pkg_serve.rb +1 -1
  129. data/plugins/main/main.rb +43 -3
  130. data/plugins/main/tmpl/index.html +2 -10
  131. data/plugins/main/values.yaml +3 -1
  132. data/plugins/ticket/lib/common.rb +6 -3
  133. data/plugins/ticket/ticket.rb +11 -3
  134. metadata +144 -174
  135. data/js/comm/autosync/js.inc +0 -0
  136. data/js/comm/js.inc +0 -0
  137. data/js/comm/jsloader/js.inc +0 -0
  138. data/js/comm/queue/js.inc +0 -0
  139. data/js/comm/session/js.inc +0 -0
  140. data/js/comm/sessionwatcher/js.inc +0 -0
  141. data/js/comm/transporter/js.inc +0 -0
  142. data/js/comm/urlresponder/js.inc +0 -0
  143. data/js/comm/values/js.inc +0 -0
  144. data/js/controls/button/js.inc +0 -0
  145. data/js/controls/checkbox/js.inc +0 -0
  146. data/js/controls/dialogs/alert_sheet/js.inc +0 -0
  147. data/js/controls/dialogs/confirm_sheet/js.inc +0 -0
  148. data/js/controls/dialogs/sheet/js.inc +0 -0
  149. data/js/controls/imageview/js.inc +0 -0
  150. data/js/controls/passwordcontrol/js.inc +0 -0
  151. data/js/controls/progress/progressbar/js.inc +0 -0
  152. data/js/controls/progress/progressindicator/js.inc +0 -0
  153. data/js/controls/radiobutton/js.inc +0 -0
  154. data/js/controls/sliders/slider/js.inc +0 -0
  155. data/js/controls/sliders/vslider/js.inc +0 -0
  156. data/js/controls/stepper/js.inc +0 -0
  157. data/js/controls/stringview/js.inc +0 -0
  158. data/js/controls/tab/js.inc +0 -0
  159. data/js/controls/textarea/js.inc +0 -0
  160. data/js/controls/textcontrol/js.inc +0 -0
  161. data/js/controls/uploader/js.inc +0 -0
  162. data/js/controls/uploader/uploader.js +0 -154
  163. data/js/controls/validatorview/js.inc +0 -0
  164. data/js/controls/window/js.inc +0 -0
  165. data/js/core/class/js.inc +0 -0
  166. data/js/core/elem/elem.js +0 -1325
  167. data/js/core/elem/js.inc +0 -0
  168. data/js/core/event/js.inc +0 -0
  169. data/js/core/iefix/js.inc +0 -0
  170. data/js/core/rsence_ns/js.inc +0 -0
  171. data/js/datetime/calendar/calendar.js +0 -198
  172. data/js/datetime/calendar/js.inc +0 -0
  173. data/js/datetime/datetimevalue/js.inc +0 -0
  174. data/js/datetime/timesheet/js.inc +0 -0
  175. data/js/datetime/timesheet/old_timesheet.js +0 -292
  176. data/js/datetime/timesheet/themes/default/old_timesheet.css +0 -30
  177. data/js/datetime/timesheet/themes/default/old_timesheet.html +0 -2
  178. data/js/datetime/timesheet_item/js.inc +0 -0
  179. data/js/datetime/timesheet_item/old_timesheet_item.js +0 -308
  180. data/js/datetime/timesheet_item/themes/default/old_timesheet_item.css +0 -42
  181. data/js/datetime/timesheet_item/themes/default/old_timesheet_item.html +0 -8
  182. data/js/datetime/timesheet_item_edit/js.inc +0 -0
  183. data/js/datetime/timesheet_item_edit/old_timesheet_item_edit.js +0 -274
  184. data/js/foundation/application/js.inc +0 -0
  185. data/js/foundation/control/controldefaults/js.inc +0 -0
  186. data/js/foundation/control/dummyvalue/js.inc +0 -0
  187. data/js/foundation/control/dyncontrol/js.inc +0 -0
  188. data/js/foundation/control/eventresponder/js.inc +0 -0
  189. data/js/foundation/control/js.inc +0 -0
  190. data/js/foundation/control/valuematrix/js.inc +0 -0
  191. data/js/foundation/control/valueresponder/js.inc +0 -0
  192. data/js/foundation/eventmanager/js.inc +0 -0
  193. data/js/foundation/geom/point/js.inc +0 -0
  194. data/js/foundation/geom/rect/js.inc +0 -0
  195. data/js/foundation/json_renderer/js.inc +0 -0
  196. data/js/foundation/system/js.inc +0 -0
  197. data/js/foundation/thememanager/js.inc +0 -0
  198. data/js/foundation/value/js.inc +0 -0
  199. data/js/foundation/view/js.inc +0 -0
  200. data/js/foundation/view/markupview/js.inc +0 -0
  201. data/js/foundation/view/morphanimation/js.inc +0 -0
  202. data/js/foundation/view/viewdefaults/js.inc +0 -0
  203. data/js/lists/checkboxlist/js.inc +0 -0
  204. data/js/lists/listitems/js.inc +0 -0
  205. data/js/lists/propertylist/js.inc +0 -0
  206. data/js/lists/propertylist/propertylisteditor/js.inc +0 -0
  207. data/js/lists/radiobuttonlist/js.inc +0 -0
  208. data/js/menus/minimenu/js.inc +0 -0
  209. data/js/menus/minimenu/minimenuitem/js.inc +0 -0
  210. data/js/menus/minimenu/minimenuitem/minimenuitem.js +0 -33
  211. data/js/util/reloadapp/js.inc +0 -0
  212. data/js/util/sha/js.inc +0 -0
  213. data/js/views/centerview/js.inc +0 -0
  214. data/js/views/inlineview/js.inc +0 -0
  215. data/js/views/scrollview/js.inc +0 -0
  216. data/lib/conf/argv.rb +0 -880
@@ -14,7 +14,7 @@ module RSence
14
14
  require 'sequel'
15
15
 
16
16
  ## HValue class for session restoration
17
- require 'values/hvalue'
17
+ require 'rsence/value'
18
18
 
19
19
  # SessionStorage doesn't do anything by itself, it's simply
20
20
  # the superclass for SessionManager that does all the boring
@@ -218,8 +218,12 @@ module RSence
218
218
  @sessions[ses_id] = ses_data
219
219
  @session_keys[ ses_key ] = ses_id
220
220
  @session_cookie_keys[ ses_data[:cookie_key] ] = ses_id
221
+ if @plugins
222
+ @plugins.delegate( :load_ses_id, ses_id )
223
+ @plugins.delegate( :load_ses, ses_data )
224
+ end
221
225
  rescue => e
222
- warn "Unable to restore session id: #{ses_id}, error: #{e.inspect}"
226
+ warn "Unable to load session: #{ses_id}, because: #{e.message}"
223
227
  @db[:rsence_session].filter(:id => ses_id).delete
224
228
  @db[:rsence_uploads].filter(:ses_id => ses_id).delete
225
229
  end
@@ -236,19 +240,26 @@ module RSence
236
240
  end
237
241
  puts "Storing sessions..." if RSence.args[:verbose]
238
242
  db_open
239
- @sessions.each_key do |ses_id|
240
- ses_data = @sessions[ ses_id ]
241
- ses_data_dump = Marshal.dump( ses_data )
242
- @db[:rsence_session].filter(
243
- :id => ses_id
244
- ).update(
245
- :cookie_key => ses_data[:cookie_key],
246
- :ses_key => ses_data[:ses_key],
247
- :user_id => ses_data[:user_id],
248
- :ses_data => ses_data_dump.to_sequel_blob,
249
- :ses_timeout => ses_data[:timeout],
250
- :ses_stored => Time.now.to_i
251
- )
243
+ @sessions.each do |ses_id,ses_data|
244
+ if @plugins
245
+ @plugins.delegate( :dump_ses, ses_data )
246
+ @plugins.delegate( :dump_ses_id, ses_id )
247
+ end
248
+ begin
249
+ ses_data_dump = Marshal.dump( ses_data )
250
+ @db[:rsence_session].filter(
251
+ :id => ses_id
252
+ ).update(
253
+ :cookie_key => ses_data[:cookie_key],
254
+ :ses_key => ses_data[:ses_key],
255
+ :user_id => ses_data[:user_id],
256
+ :ses_data => ses_data_dump.to_sequel_blob,
257
+ :ses_timeout => ses_data[:timeout],
258
+ :ses_stored => Time.now.to_i
259
+ )
260
+ rescue => e
261
+ warn "Unable to dump session: #{ses_id}, because: #{e.message}"
262
+ end
252
263
  end
253
264
  db_close
254
265
  end
@@ -296,7 +307,10 @@ module RSence
296
307
  @sessions.delete( ses_id )
297
308
 
298
309
  # Removes all ticket-based storage bound to the session
299
- @plugins[:ticket].expire_ses_id( ses_id ) if @plugins
310
+ if @plugins
311
+ @plugins.delegate( :expire_ses, ses_data )
312
+ @plugins.delegate( :expire_ses_id, ses_id )
313
+ end
300
314
 
301
315
  # target -> source cleanup
302
316
  if @clone_sources.has_key?( ses_id )
File without changes
@@ -8,13 +8,13 @@
8
8
 
9
9
 
10
10
  # ValueManager synchronizes value objects
11
- require 'values/valuemanager'
11
+ require 'rsence/valuemanager'
12
12
 
13
13
  # SessionManager creates, validates, stores and expires sessions
14
- require 'session/sessionmanager'
14
+ require 'rsence/sessionmanager'
15
15
 
16
16
  # PluginManager handles all the plugins
17
- require 'plugins/pluginmanager'
17
+ require 'rsence/pluginmanager'
18
18
 
19
19
 
20
20
  module RSence
@@ -36,6 +36,7 @@ module RSence
36
36
  attr_accessor :plugins
37
37
 
38
38
  def initialize
39
+ RSence.transporter = self
39
40
  @config = RSence.config[:transporter_conf]
40
41
  @accept_req = false
41
42
  core_pkgs = {
@@ -50,7 +51,10 @@ module RSence
50
51
  :resolved_categories => core_pkgs
51
52
  })
52
53
  @valuemanager = ValueManager.new
54
+ RSence.value_manager = @valuemanager
53
55
  @sessions = SessionManager.new( self )
56
+ @plugins.sessions = @sessions
57
+ RSence.session_manager = @sessions
54
58
  if RSence.config[:session_conf][:reset_sessions]
55
59
  puts "Resetting all sessions..."
56
60
  @sessions.reset_sessions()
@@ -81,17 +85,15 @@ module RSence
81
85
 
82
86
  def shutdown
83
87
  online=false
84
- @plugins.shutdown
85
88
  @sessions.shutdown
89
+ @plugins.shutdown
86
90
  end
87
91
 
88
92
  def servlet( request_type, request, response )
89
93
  broker_urls = RSence.config[:broker_urls]
90
94
  uri = request.fullpath
91
95
 
92
- if @plugins.match_servlet( request_type, request, response, {} )
93
- return true
94
- elsif request_type == :post
96
+ if request_type == :post
95
97
  ## /x handles xhr without cookies
96
98
  if uri == broker_urls[:x] and @sessions.accept_requests
97
99
  xhr( request, response, { :cookies => true, :servlet => false } )
@@ -102,7 +104,7 @@ module RSence
102
104
  return true
103
105
  end
104
106
  end
105
- return false
107
+ return @plugins.match_servlet( request_type, request, response, @sessions.servlet_cookie_ses( request, response ) )
106
108
  end
107
109
 
108
110
  # wrapper for the session manager stop client functionality
@@ -200,7 +202,7 @@ module RSence
200
202
 
201
203
  begin
202
204
  @plugins.delegate( :restore_ses, msg )
203
- msg.session[:plugin_incr] == @plugins.incr
205
+ msg.session[:plugin_incr] = @plugins.incr
204
206
  rescue => e
205
207
  response_success = false
206
208
  xhr_error_handler( msg, :plugin_delegate_restore_ses_error, e.message )
@@ -211,7 +213,7 @@ module RSence
211
213
 
212
214
  begin
213
215
  @plugins.delegate( :init_ses, msg )
214
- msg.session[:plugin_incr] == @plugins.incr
216
+ msg.session[:plugin_incr] = @plugins.incr
215
217
  rescue => e
216
218
  response_success = false
217
219
  xhr_error_handler( msg, :plugin_delegate_init_ses_error, e.message )
@@ -230,7 +232,7 @@ module RSence
230
232
 
231
233
  elsif msg.refresh_page?( @plugins.incr ) and @config[:client_autoreload]
232
234
  while msg.refresh_page?( @plugins.incr )
233
- msg.session[:plugin_incr] == @plugins.incr
235
+ msg.session[:plugin_incr] = @plugins.incr
234
236
  sleep 0.5
235
237
  end
236
238
  # Forces the client to reload, if plugins are incremented
@@ -176,10 +176,11 @@ module RSence
176
176
 
177
177
  # @private Handle updates from the client.
178
178
  def from_client( msg, data )
179
-
180
179
  # only process changes, if different from the one already stored.
181
180
  if @data != data
182
181
 
182
+ # puts "data sync from client: #{@data.inspect} -> #{data.inspect} (#{@meta[:name]})"
183
+
183
184
  ## set takes care of the setting..
184
185
  @data = data
185
186
 
@@ -270,6 +271,10 @@ module RSence
270
271
  end
271
272
  end
272
273
  alias die die!
274
+
275
+ def inspect
276
+ "#<RSence::HValue value_id:#{@value_id.inspect}, valid: #{@is_valid.inspect}, sync: #{@sync.inspect}, is_new_to_client: #{@is_new_to_client.inspect}, meta: #{@meta.inspect[0..100]}, data: #{@data.inspect[0..100]} ...>"
277
+ end
273
278
 
274
279
  end
275
280
 
@@ -9,7 +9,7 @@
9
9
 
10
10
 
11
11
  # Require needed value types (hvalue supports bool/float/int/string)
12
- require 'values/hvalue'
12
+ require 'rsence/value'
13
13
 
14
14
  # RandomGenerator produces unique, random values
15
15
  require 'randgen'
@@ -32,7 +32,7 @@ class ClientPkgPlugin < Servlet
32
32
  @log_file = nil
33
33
  end
34
34
  def log( str )
35
- if RSence.args[:verbose]
35
+ if RSence.args[:verbose] or not RSence.args[:suppress_build_messages]
36
36
  puts str
37
37
  return
38
38
  else
@@ -55,18 +55,24 @@ class ClientPkgPlugin < Servlet
55
55
  end
56
56
 
57
57
  def rebuild_client
58
- until not @build_busy
59
- puts "build busy, sleeping.."
60
- sleep 0.5
58
+ while @build_busy
59
+ puts "-- build busy, sleeping.. --"
60
+ sleep 0.1
61
61
  end
62
62
  @build_busy = true
63
63
  @last_change = Time.now.to_i
64
64
  @client_build.setup_dirs
65
65
  @client_build.run
66
+ @client_cache = ClientPkgCache.new
66
67
  @client_cache.set_cache( @client_build.js, @client_build.gz, @client_build.themes )
68
+ RSence.plugin_manager.incr! if RSence.config[:transporter_conf][:client_autoreload]
67
69
  @build_busy = false
68
70
  end
69
71
 
72
+ def ready?
73
+ return (not @build_busy)
74
+ end
75
+
70
76
  def open
71
77
  if not @thr and RSence.args[:autoupdate]
72
78
  @thr = Thread.new do
@@ -136,6 +142,10 @@ class ClientPkgPlugin < Servlet
136
142
  def squeeze( js )
137
143
  return @client_build.squeeze( js )
138
144
  end
145
+
146
+ def coffee( src )
147
+ return @client_build.coffee( src )
148
+ end
139
149
 
140
150
  def init
141
151
 
@@ -3,7 +3,7 @@
3
3
  title: Client Resource Package
4
4
 
5
5
  # The human-readable version of the package
6
- version: 2.1.0
6
+ version: 2.2.0
7
7
 
8
8
  # A brief description of the package (rdoc formatting supported)
9
9
  description: |
@@ -17,7 +17,7 @@ description: |
17
17
  reloadable: false
18
18
 
19
19
  # System version requirement.
20
- sys_version: '>= 2.1.0'
20
+ sys_version: '>= 2.2.0'
21
21
 
22
22
  category: :system
23
23
 
@@ -7,9 +7,16 @@
7
7
  ##
8
8
 
9
9
 
10
- require 'jsmin_c'
10
+ require 'jsminc'
11
11
  require 'jscompress'
12
12
  require 'html_min'
13
+ begin
14
+ require 'coffee-script'
15
+ RSence.config[:client_pkg][:coffee_supported] = true
16
+ rescue LoadError
17
+ warn "CoffeeScript not installed. Install the 'coffee-script' gem to enable."
18
+ RSence.config[:client_pkg][:coffee_supported] = false
19
+ end
13
20
 
14
21
 
15
22
  class ClientPkgBuild
@@ -99,7 +106,7 @@ class ClientPkgBuild
99
106
  :gzip => gz_css
100
107
  }
101
108
  @theme_sizes[ theme_name ][:css][0] += File.stat( src_file_css ).size
102
- @theme_sizes[ theme_name ][:css][1] += css_data.size
109
+ @theme_sizes[ theme_name ][:css][1] += css_data.bytesize
103
110
  @css_by_theme[ theme_name ][ bundle_name ] = css_data
104
111
  end
105
112
  end
@@ -113,7 +120,7 @@ class ClientPkgBuild
113
120
  :gzip => gz_html
114
121
  }
115
122
  @theme_sizes[ theme_name ][:html][0] += File.stat( src_file_html ).size
116
- @theme_sizes[ theme_name ][:html][1] += html_data.size
123
+ @theme_sizes[ theme_name ][:html][1] += html_data.bytesize
117
124
  @html_by_theme[ theme_name ][ bundle_name ] = html_data
118
125
  end
119
126
  end
@@ -123,7 +130,7 @@ class ClientPkgBuild
123
130
  end
124
131
  end
125
132
 
126
- def add_bundle( bundle_name, bundle_path, entries )
133
+ def add_bundle( bundle_name, bundle_path, entries, has_js=false, has_coffee=false )
127
134
  has_themes = entries.include?( 'themes' ) and File.directory?( File.join( bundle_path, 'themes' ) )
128
135
  if @bundles_found.has_key?( bundle_name )
129
136
  @logger.log( "JSBuilder ERROR: duplicate bundles with the name #{bundle_name.inspect} found." )
@@ -136,11 +143,41 @@ class ClientPkgBuild
136
143
  warn "JSBuilder WARNING: bundle name #{bundle_name.inspect} does not belong to any package, skipping.." if ARGV.include?('-d')
137
144
  return true
138
145
  end
139
- js_data = read_file( File.join( bundle_path, bundle_name+'.js' ) )
146
+ if has_coffee and @coffee_supported
147
+ begin
148
+ coffee_start = Time.new.to_f
149
+ coffee_path = File.join( bundle_path, bundle_name+'.coffee' )
150
+ coffee_timestamp = File.stat( coffee_path ).mtime.to_i
151
+ has_cache_compiled = @coffee_cache[:path_compiled].has_key?( coffee_path )
152
+ has_cache_timestamp = @coffee_cache[:path_timestamp].has_key?( coffee_path )
153
+ has_cache_entry = has_cache_compiled and has_cache_timestamp
154
+ has_cached = ( has_cache_entry and ( @coffee_cache[:path_timestamp][coffee_path] == coffee_timestamp ) )
155
+ if has_cached
156
+ js_data = @coffee_cache[:path_compiled][coffee_path]
157
+ else
158
+ coffee_src = read_file( coffee_path )
159
+ js_data = CoffeeScript.compile( coffee_src, :bare => true )
160
+ @coffee_cache[:path_timestamp][coffee_path] = coffee_timestamp
161
+ @coffee_cache[:path_compiled][coffee_path] = js_data
162
+ end
163
+ @coffee_time += ( Time.new.to_f - coffee_start )
164
+ rescue CoffeeScript::CompilationError
165
+ if has_js
166
+ js_data = %{console.log( "WARNING: CoffeeScript complilation failed for source file #{coffee_path}, using the js variant instead." );}
167
+ js_data += read_file( File.join( bundle_path, bundle_name+'.js' ) )
168
+ else
169
+ js_data = %{console.log( "WARNING: CoffeeScript complilation failed for source file #{coffee_path}" );}
170
+ end
171
+ end
172
+ elsif not has_js
173
+ js_data = %{console.log( "ERROR: CoffeeScript not suuported and no JS source available for #{bundle_path}" );}
174
+ else
175
+ js_data = read_file( File.join( bundle_path, bundle_name+'.js' ) )
176
+ end
140
177
  @bundles_found[ bundle_name ] = {
141
178
  :path => bundle_path,
142
179
  :js_data => js_data,
143
- :js_size => js_data.size,
180
+ :js_size => js_data.bytesize,
144
181
  :has_themes => has_themes
145
182
  }
146
183
  if has_themes
@@ -157,10 +194,13 @@ class ClientPkgBuild
157
194
  # the name of src_dir (src_dir itself is a full path)
158
195
  dir_name = File.split( src_dir )[1]
159
196
  # bundles are defined as directories with a js file of the same name plus the 'js.inc' tagfile
160
- is_bundle = dir_entries.include?( @js_inc ) and dir_entries.include?( dir_name+'.js' )
197
+ not_disabled = ( not dir_entries.include?( 'disabled' ) )
198
+ has_js = dir_entries.include?( dir_name+'.js' )
199
+ has_coffee = dir_entries.include?( dir_name+'.coffee' )
200
+ is_bundle = not_disabled and ( has_js or has_coffee )
161
201
  # if src_dir is detected as a bundle, handle it in add_bundle
162
202
  if is_bundle
163
- add_bundle( dir_name, src_dir, dir_entries )
203
+ add_bundle( dir_name, src_dir, dir_entries, has_js, has_coffee )
164
204
  end
165
205
  # descend into the sub-directory:
166
206
  dir_entries.each do | dir_entry |
@@ -193,37 +233,30 @@ class ClientPkgBuild
193
233
  @logger.log( " : | |" )
194
234
  end
195
235
  @destination_files.each_key do | package_name |
196
- jsc_data = @destination_files[package_name]
197
- unless @debug
198
- unless @no_whitespace_removal
199
- jsc_data = @jsmin.minimize( jsc_data ) #.strip
200
- end
201
- unless @no_obfuscation
202
- jsc_data = pre_convert( jsc_data )
203
- end
204
- end
205
- @js[package_name] = jsc_data.strip
236
+ jsc_data = process_js( @destination_files[package_name] )
237
+ @js[package_name] = jsc_data
206
238
  unless @no_gzip
207
- gz_data = gzip_string( @js[package_name] )
239
+ gz_data = gzip_string( jsc_data )
208
240
  @gz[package_name] = gz_data
209
241
  end
210
242
  unless @quiet
211
- js_size = @destination_files[ package_name ].size
212
- jsc_size = jsc_data.size
243
+ js_size = @destination_files[ package_name ].bytesize
244
+ jsc_size = jsc_data.bytesize
213
245
  if @no_gzip
214
246
  gz_size = -1
215
247
  else
216
- gz_size = gz_data.size
248
+ gz_size = gz_data.bytesize
217
249
  end
218
250
  print_stat( package_name, js_size, jsc_size, gz_size )
219
251
  end
220
252
  end
221
253
  end
222
254
 
223
- def squeeze( js )
255
+ def squeeze( js, is_coffee=false )
224
256
  unless @no_whitespace_removal
225
257
  begin
226
- js = @jsmin.minimize( js )#.strip
258
+ # js = @jsmin.minimize( js )#.strip
259
+ js = JSMinC.minify( js )
227
260
  rescue IndexError => e
228
261
  warn "js can't get smaller using js; just ignoring jsmin"
229
262
  end
@@ -234,6 +267,35 @@ class ClientPkgBuild
234
267
  end
235
268
  return js.strip
236
269
  end
270
+
271
+ def coffee( src )
272
+ begin
273
+ js = CoffeeScript.compile( src, :bare => true )
274
+ rescue ExecJS::RuntimeError => e
275
+ warn "ExecJS RuntimeError, invalid CoffeScript supplied:\n----\n#{src}----\n"
276
+ js = "function(){console.log('ERROR; invalid CoffeeScript supplied: #{src.to_json}');}"
277
+ rescue CoffeeScript::CompilationError
278
+ warn "Invalid CoffeeScript supplied:\n----\n#{src}----\n"
279
+ js = "function(){console.log('ERROR; invalid CoffeeScript supplied: #{src.to_json}');}"
280
+ rescue
281
+ js = "function(){console.log('ERROR; CoffeeScript compilation failed: #{src.to_json}');}"
282
+ end
283
+ js = squeeze( js )
284
+ return js[1..-3] if js.start_with?('(') and js.end_with?(');')
285
+ return js
286
+ end
287
+
288
+ def process_js( src_in )
289
+ if @debug
290
+ return src_in
291
+ else
292
+ src_out = src_in
293
+ # src_out = @jsmin.minimize( src_out ) unless @no_whitespace_removal
294
+ src_out = JSMinC.minify( src_out ) unless @no_whitespace_removal
295
+ src_out = pre_convert( src_out ) unless @no_obfuscation
296
+ return src_out.strip
297
+ end
298
+ end
237
299
 
238
300
  def build_themes
239
301
  unless @quiet
@@ -250,24 +312,21 @@ class ClientPkgBuild
250
312
  theme_html_js_arr.push "HThemeManager._tmplCache[#{theme_name.to_json}]=#{html_templates.to_json}; "
251
313
  theme_html_js_arr.push "HNoComponentCSS.push(#{theme_name.to_json});"
252
314
  theme_html_js_arr.push "HNoCommonCSS.push(#{theme_name.to_json});"
253
- theme_html_js_arr.push "HThemeManager._cssUrl( #{theme_name.to_json}, #{(theme_name+'_theme').to_json}, HThemeManager.themePath, null );"
254
- theme_html_js_arr.push "HThemeManager.useCSS(#{theme_css_template_data.to_json}); "
255
- theme_html_js = theme_html_js_arr.join('')
256
- unless @debug
257
- unless @no_whitespace_removal
258
- theme_html_js = @jsmin.minimize( theme_html_js ) #.strip
259
- end
260
- unless @no_obfuscation
261
- theme_html_js = pre_convert( theme_html_js )
262
- end
263
- end
264
- @js[theme_name+'_theme'] = theme_html_js.strip
315
+ theme_html_js_arr.push %{
316
+ HThemeManager._pushStart( function(){
317
+ var _this = HThemeManager;
318
+ _this._cssUrl( #{theme_name.to_json}, #{(theme_name+'_theme').to_json}, _this.themePath, null );
319
+ _this.useCSS(#{theme_css_template_data.to_json});
320
+ } );
321
+ }
322
+ theme_html_js = process_js( theme_html_js_arr.join('') )
323
+ @js[theme_name+'_theme'] = theme_html_js
265
324
  unless @no_gzip
266
325
  theme_html_gz = gzip_string( @js[theme_name+'_theme'] )
267
326
  @gz[theme_name+'_theme'] = theme_html_gz
268
327
  end
269
328
  unless @quiet
270
- print_stat( "#{theme_name}/html", @theme_sizes[theme_name][:html][0], @theme_sizes[theme_name][:html][1], theme_html_gz.size )
329
+ print_stat( "#{theme_name}/html", @theme_sizes[theme_name][:html][0], @theme_sizes[theme_name][:html][1], theme_html_gz.bytesize )
271
330
  end
272
331
  @themes[theme_name][:css][theme_name+'_theme'] = {
273
332
  :data => theme_css_template_data,
@@ -278,16 +337,47 @@ class ClientPkgBuild
278
337
  @themes[theme_name][:css][theme_name+'_theme'][:gzip] = theme_css_template_data_gz
279
338
  end
280
339
  unless @quiet
281
- print_stat( "#{theme_name}/css", @theme_sizes[theme_name][:css][0], @theme_sizes[theme_name][:css][1], theme_css_template_data_gz.size )
340
+ print_stat( "#{theme_name}/css", @theme_sizes[theme_name][:css][0], @theme_sizes[theme_name][:css][1], theme_css_template_data_gz.bytesize )
282
341
  print_stat( "#{theme_name}/gfx", @theme_sizes[theme_name][:gfx], -1, -1 )
283
342
  @logger.log( '' )
284
343
  end
285
344
  end
286
345
  end
287
346
 
347
+ def build_compound_packages
348
+ unless @quiet
349
+ @logger.log( '' )
350
+ @logger.log( "Compound package..............: Original | Minimized | Compressed" )
351
+ @logger.log( " : | |" )
352
+ end
353
+ @compound_config.each do |pkg_name, js_order|
354
+ pkg_parts = []
355
+ js_order.each do |js_pkg|
356
+ pkg_part = @js[ js_pkg ]
357
+ pkg_parts.push( pkg_part )
358
+ end
359
+ js_src = pkg_parts.join('')
360
+ @js[ pkg_name ] = js_src
361
+ unless @no_gzip
362
+ gz_data = gzip_string( js_src )
363
+ @gz[ pkg_name ] = gz_data
364
+ end
365
+ unless @quiet
366
+ js_size = js_src.bytesize
367
+ if @no_gzip
368
+ gz_size = -1
369
+ else
370
+ gz_size = gz_data.bytesize
371
+ end
372
+ print_stat( pkg_name, js_size, -1, gz_size )
373
+ end
374
+ end
375
+ end
376
+
288
377
  def run
289
378
 
290
379
  time_start = Time.now.to_f*10000
380
+ @coffee_time = 0
291
381
 
292
382
  # hash of bundles per bundle name per theme; @html_by_theme[theme_name][bundle_name] = bundle_data
293
383
  @html_by_theme = {}
@@ -307,7 +397,8 @@ class ClientPkgBuild
307
397
  end
308
398
  @bundles_found = {} # populated by add_bundle
309
399
  @conversion_stats = {} # populated by add_hints
310
- @src_dirs.each do | src_dir |
400
+ src_dirs = @src_dirs.clone
401
+ src_dirs.each do | src_dir |
311
402
  find_bundles( src_dir )
312
403
  end
313
404
  @destination_files = {} # rename to package_products
@@ -325,11 +416,14 @@ class ClientPkgBuild
325
416
  end
326
417
 
327
418
  build_indexes
328
- minimize_data
329
419
  build_themes
420
+ minimize_data
421
+ build_compound_packages
330
422
 
331
- ms_taken = ((Time.now.to_f*10000)-time_start).to_i/10.0
332
- @logger.log( "Time taken: #{ms_taken}ms\n\n" )
423
+ ms_taken = ((Time.now.to_f*10000)-time_start).round/10.0
424
+ coffee_taken = (@coffee_time*10000).round/10.0
425
+ without_coffee = ((ms_taken - coffee_taken)*10).round/10.0
426
+ @logger.log( "Time taken:\n .coffee: #{coffee_taken}ms\n other: #{without_coffee}ms\n total: #{ms_taken}ms\n\n" )
333
427
 
334
428
  end
335
429
 
@@ -449,6 +543,12 @@ class ClientPkgBuild
449
543
 
450
544
  def initialize( config, logger )
451
545
 
546
+ @coffee_supported = config[:coffee_supported]
547
+ @coffee_cache = {
548
+ :path_timestamp => {},
549
+ :path_compiled => {}
550
+ }
551
+
452
552
  @logger = logger
453
553
 
454
554
  # src_dirs is supposed to be an array of js source directories
@@ -480,7 +580,7 @@ class ClientPkgBuild
480
580
  @html_min = HTMLMin.new
481
581
 
482
582
  # JSMin removes js white-space (makes the source shorter)
483
- @jsmin = JSMin.new
583
+ # @jsmin = JSMin.new
484
584
 
485
585
  # makes sure the specified dirs are ok
486
586
  return if not setup_dirs
@@ -502,9 +602,9 @@ class ClientPkgBuild
502
602
  @no_gzip = config[:no_gzip]
503
603
  @no_obfuscation = config[:no_obfuscation]
504
604
  @no_whitespace_removal = config[:no_whitespace_removal]
505
- @js_inc = config[:js_inc]
506
605
  @debug = RSence.args[:debug]
507
- @quiet = (not RSence.args[:verbose])
606
+ @quiet = (not RSence.args[:verbose] and RSence.args[:suppress_build_messages])
607
+ @compound_config = config[:compound_packages]
508
608
  end
509
609
 
510
610
  def find_newer( src_dir, newer_than )