rubyception 0.0.2

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 (227) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +30 -0
  3. data/Rakefile +42 -0
  4. data/app/assets/javascripts/rubyception/app.coffee +4 -0
  5. data/app/assets/javascripts/rubyception/application.coffee +17 -0
  6. data/app/assets/javascripts/rubyception/application.js +15 -0
  7. data/app/assets/javascripts/rubyception/collections/backtrace_lines.coffee +4 -0
  8. data/app/assets/javascripts/rubyception/collections/entries.coffee +3 -0
  9. data/app/assets/javascripts/rubyception/collections/lines.coffee +3 -0
  10. data/app/assets/javascripts/rubyception/init.coffee +10 -0
  11. data/app/assets/javascripts/rubyception/lib/backbone.js +1431 -0
  12. data/app/assets/javascripts/rubyception/lib/inflections.js +659 -0
  13. data/app/assets/javascripts/rubyception/lib/jenny.coffee +262 -0
  14. data/app/assets/javascripts/rubyception/lib/milk.coffee +261 -0
  15. data/app/assets/javascripts/rubyception/lib/mousetrap.js +7 -0
  16. data/app/assets/javascripts/rubyception/lib/underscore-min.js +32 -0
  17. data/app/assets/javascripts/rubyception/models/backtrace_line.coffee +2 -0
  18. data/app/assets/javascripts/rubyception/models/entry.coffee +2 -0
  19. data/app/assets/javascripts/rubyception/models/line.coffee +2 -0
  20. data/app/assets/javascripts/rubyception/routers/log.coffee +45 -0
  21. data/app/assets/javascripts/rubyception/shBrushSql.js +66 -0
  22. data/app/assets/javascripts/rubyception/shCore.js +17 -0
  23. data/app/assets/javascripts/rubyception/template.js +1 -0
  24. data/app/assets/javascripts/rubyception/views/backtrace_lines/backtrace_line.coffee +8 -0
  25. data/app/assets/javascripts/rubyception/views/backtrace_lines/index.coffee +16 -0
  26. data/app/assets/javascripts/rubyception/views/entries/entry.coffee +49 -0
  27. data/app/assets/javascripts/rubyception/views/entries/index.coffee +79 -0
  28. data/app/assets/javascripts/rubyception/views/lines/index.coffee +5 -0
  29. data/app/assets/javascripts/rubyception/views/lines/line.coffee +10 -0
  30. data/app/assets/javascripts/rubyception/views/logs/show.coffee +8 -0
  31. data/app/assets/stylesheets/rubyception/application.css +13 -0
  32. data/app/assets/stylesheets/rubyception/application.sass +12 -0
  33. data/app/assets/stylesheets/rubyception/backtrace_lines.sass +66 -0
  34. data/app/assets/stylesheets/rubyception/default.sass +35 -0
  35. data/app/assets/stylesheets/rubyception/entries.sass +57 -0
  36. data/app/assets/stylesheets/rubyception/lines.sass +41 -0
  37. data/app/assets/stylesheets/rubyception/shCore.css +226 -0
  38. data/app/assets/stylesheets/rubyception/shThemeDefault.css +117 -0
  39. data/app/controllers/rubyception/application_controller.rb +4 -0
  40. data/app/controllers/rubyception/templating_controller.rb +22 -0
  41. data/app/helpers/rubyception/application_helper.rb +9 -0
  42. data/app/models/rubyception/entry.rb +108 -0
  43. data/app/models/rubyception/line.rb +55 -0
  44. data/app/views/layouts/rubyception/application.haml +15 -0
  45. data/app/views/rubyception/application/index.haml +0 -0
  46. data/app/views/rubyception/backtrace_lines/_backtrace_line.haml +5 -0
  47. data/app/views/rubyception/backtrace_lines/_index.haml +7 -0
  48. data/app/views/rubyception/entries/_entry.haml +12 -0
  49. data/app/views/rubyception/entries/_index.haml +1 -0
  50. data/app/views/rubyception/lines/_index.haml +3 -0
  51. data/app/views/rubyception/lines/_line.haml +2 -0
  52. data/app/views/rubyception/lines/action_controller/_exist_fragment.haml +0 -0
  53. data/app/views/rubyception/lines/action_controller/_expire_fragment.haml +0 -0
  54. data/app/views/rubyception/lines/action_controller/_expire_page.haml +0 -0
  55. data/app/views/rubyception/lines/action_controller/_halted_callback.haml +0 -0
  56. data/app/views/rubyception/lines/action_controller/_process_action.haml +0 -0
  57. data/app/views/rubyception/lines/action_controller/_read_fragment.haml +0 -0
  58. data/app/views/rubyception/lines/action_controller/_redirect_to.haml +0 -0
  59. data/app/views/rubyception/lines/action_controller/_send_data.haml +0 -0
  60. data/app/views/rubyception/lines/action_controller/_send_file.haml +0 -0
  61. data/app/views/rubyception/lines/action_controller/_start_processing.haml +0 -0
  62. data/app/views/rubyception/lines/action_controller/_write_fragment.haml +0 -0
  63. data/app/views/rubyception/lines/action_controller/_write_page.haml +0 -0
  64. data/app/views/rubyception/lines/action_mailer/_deliver.haml +0 -0
  65. data/app/views/rubyception/lines/action_mailer/_receive.haml +0 -0
  66. data/app/views/rubyception/lines/action_view/_render_partial.haml +3 -0
  67. data/app/views/rubyception/lines/action_view/_render_template.haml +6 -0
  68. data/app/views/rubyception/lines/active_record/_identity.haml +3 -0
  69. data/app/views/rubyception/lines/active_record/_sql.haml +4 -0
  70. data/app/views/rubyception/lines/active_resource/_request.haml +0 -0
  71. data/app/views/rubyception/lines/active_support/_cache_delete.haml +0 -0
  72. data/app/views/rubyception/lines/active_support/_cache_exist.haml +0 -0
  73. data/app/views/rubyception/lines/active_support/_cache_fetch_hit.haml +0 -0
  74. data/app/views/rubyception/lines/active_support/_cache_generate.haml +0 -0
  75. data/app/views/rubyception/lines/active_support/_cache_read.haml +0 -0
  76. data/app/views/rubyception/lines/active_support/_cache_write.haml +0 -0
  77. data/config/initializers/sass.rb +4 -0
  78. data/config/initializers/websocket_server.rb +23 -0
  79. data/config/routes.rb +3 -0
  80. data/config/templating.yml +39 -0
  81. data/db/development.sqlite3 +0 -0
  82. data/lib/rubyception.rb +6 -0
  83. data/lib/rubyception/catcher.rb +12 -0
  84. data/lib/rubyception/engine.rb +5 -0
  85. data/lib/rubyception/subscriber.rb +30 -0
  86. data/lib/rubyception/templating.rb +48 -0
  87. data/lib/rubyception/version.rb +3 -0
  88. data/lib/rubyception/websocket_server.rb +30 -0
  89. data/lib/tasks/rubyception_tasks.rake +4 -0
  90. data/lib/tasks/templates.rake +7 -0
  91. data/test/dummy/README.rdoc +261 -0
  92. data/test/dummy/Rakefile +7 -0
  93. data/test/dummy/app/assets/javascripts/application.js +15 -0
  94. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  95. data/test/dummy/app/controllers/application_controller.rb +3 -0
  96. data/test/dummy/app/controllers/tasks_controller.rb +4 -0
  97. data/test/dummy/app/helpers/application_helper.rb +2 -0
  98. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  99. data/test/dummy/app/views/tasks/index.html.erb +1 -0
  100. data/test/dummy/config.ru +4 -0
  101. data/test/dummy/config/application.rb +59 -0
  102. data/test/dummy/config/boot.rb +10 -0
  103. data/test/dummy/config/database.yml +25 -0
  104. data/test/dummy/config/environment.rb +5 -0
  105. data/test/dummy/config/environments/development.rb +37 -0
  106. data/test/dummy/config/environments/production.rb +67 -0
  107. data/test/dummy/config/environments/test.rb +37 -0
  108. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  109. data/test/dummy/config/initializers/inflections.rb +15 -0
  110. data/test/dummy/config/initializers/mime_types.rb +5 -0
  111. data/test/dummy/config/initializers/secret_token.rb +7 -0
  112. data/test/dummy/config/initializers/session_store.rb +8 -0
  113. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  114. data/test/dummy/config/locales/en.yml +5 -0
  115. data/test/dummy/config/routes.rb +5 -0
  116. data/test/dummy/db/development.sqlite3 +0 -0
  117. data/test/dummy/log/development.log +183 -0
  118. data/test/dummy/public/404.html +26 -0
  119. data/test/dummy/public/422.html +26 -0
  120. data/test/dummy/public/500.html +25 -0
  121. data/test/dummy/public/favicon.ico +0 -0
  122. data/test/dummy/script/rails +6 -0
  123. data/test/dummy/tmp/cache/assets/C2A/A50/sprockets%2F502789294f7d708459013948aa30c91c +0 -0
  124. data/test/dummy/tmp/cache/assets/C76/720/sprockets%2F610e52016b025a1ce3828a39a7e93981 +0 -0
  125. data/test/dummy/tmp/cache/assets/C7E/740/sprockets%2F8703235e74ff13492a454a492b24b7c5 +0 -0
  126. data/test/dummy/tmp/cache/assets/C86/920/sprockets%2Fc4933e5c2861e44ab07485567259fa32 +0 -0
  127. data/test/dummy/tmp/cache/assets/C9C/F10/sprockets%2F33864d14794ad865eed8829535780ad9 +0 -0
  128. data/test/dummy/tmp/cache/assets/CA1/8B0/sprockets%2F2fb362180bfba307350968110ec6f454 +0 -0
  129. data/test/dummy/tmp/cache/assets/CAD/770/sprockets%2Fc5914c960063cf7cdcd50130a7637485 +0 -0
  130. data/test/dummy/tmp/cache/assets/CAD/DB0/sprockets%2Fe276db0373d02afa09f069436349328d +0 -0
  131. data/test/dummy/tmp/cache/assets/CAE/140/sprockets%2F6350953af3f774482a51481f8cd0a3c3 +0 -0
  132. data/test/dummy/tmp/cache/assets/CB0/010/sprockets%2F1c103104469484b76897daa3d04c6ee9 +0 -0
  133. data/test/dummy/tmp/cache/assets/CB2/E10/sprockets%2F7b063ac8c2e913114d098d89e60228e5 +0 -0
  134. data/test/dummy/tmp/cache/assets/CB5/EA0/sprockets%2Fe98d20291409af69a7316a86c45da651 +0 -0
  135. data/test/dummy/tmp/cache/assets/CB9/B80/sprockets%2F07c32ba22a6489f062e48df8830667d8 +0 -0
  136. data/test/dummy/tmp/cache/assets/CBE/630/sprockets%2F476aa283807fdd8203e98d3137686eb5 +0 -0
  137. data/test/dummy/tmp/cache/assets/CBE/A10/sprockets%2F7f66283cb01647a7c4cf954b62919c29 +0 -0
  138. data/test/dummy/tmp/cache/assets/CC8/DC0/sprockets%2F302790cf97013f80dc311cf2ad0a6342 +0 -0
  139. data/test/dummy/tmp/cache/assets/CD1/8E0/sprockets%2Fe898f78743c913b3855e1786cc58ec61 +0 -0
  140. data/test/dummy/tmp/cache/assets/CD2/510/sprockets%2F32995b414c804ddbb00f5504841f5e1b +0 -0
  141. data/test/dummy/tmp/cache/assets/CD6/EE0/sprockets%2F8666c05da70453c6e7cda433411192af +0 -0
  142. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  143. data/test/dummy/tmp/cache/assets/CE4/F70/sprockets%2F538e295f0a0d9311c8259bf029ec680f +0 -0
  144. data/test/dummy/tmp/cache/assets/CE5/3E0/sprockets%2F7b916f5404e1ee4a943e921d6523a97b +0 -0
  145. data/test/dummy/tmp/cache/assets/CE9/D20/sprockets%2F9dd235d6e21764622b79bf65cf15349a +0 -0
  146. data/test/dummy/tmp/cache/assets/CF2/2F0/sprockets%2F314b4a0885d2efea526a19f539987e96 +0 -0
  147. data/test/dummy/tmp/cache/assets/CFB/750/sprockets%2F42c8014c71d022dd4c60ed1e963b076a +0 -0
  148. data/test/dummy/tmp/cache/assets/D03/BA0/sprockets%2F7c98f37658deed89f88b13d429262a75 +0 -0
  149. data/test/dummy/tmp/cache/assets/D07/3B0/sprockets%2F2ca3210b7cff57c3299aea8507803f32 +0 -0
  150. data/test/dummy/tmp/cache/assets/D08/7E0/sprockets%2F47ed6467d629e22254ca2b0d13c863bb +0 -0
  151. data/test/dummy/tmp/cache/assets/D0F/970/sprockets%2F0461a7c825c4bb945e2f5daf00974f64 +0 -0
  152. data/test/dummy/tmp/cache/assets/D10/E40/sprockets%2Fa39042b3a568331554c57725fedfcf3e +0 -0
  153. data/test/dummy/tmp/cache/assets/D13/740/sprockets%2F98a98bb8bc60c8b170c451195e44e42d +0 -0
  154. data/test/dummy/tmp/cache/assets/D14/BE0/sprockets%2Faa69f1166262379365d818afcf4fa3b3 +0 -0
  155. data/test/dummy/tmp/cache/assets/D15/C40/sprockets%2F8fe3d124a7582df0a47c44743f3e3d85 +0 -0
  156. data/test/dummy/tmp/cache/assets/D1B/210/sprockets%2F567244d0d8f2733c6d1826ee82c76dce +0 -0
  157. data/test/dummy/tmp/cache/assets/D2C/BD0/sprockets%2F17c8f4a03e52cd0d6b85605b0abd7413 +0 -0
  158. data/test/dummy/tmp/cache/assets/D2D/BE0/sprockets%2Fcdcde17900d6ad0c72c14390808a35b3 +0 -0
  159. data/test/dummy/tmp/cache/assets/D30/800/sprockets%2F6ad46c52755a4a6c0b81250fc72ae17c +0 -0
  160. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  161. data/test/dummy/tmp/cache/assets/D34/E20/sprockets%2Fc81175b2bb38464d022abb2d9b18bf87 +0 -0
  162. data/test/dummy/tmp/cache/assets/D38/420/sprockets%2Fc893136e3c5e0cb051358b8c01fc6b9c +0 -0
  163. data/test/dummy/tmp/cache/assets/D3C/C50/sprockets%2F52be58b70628a1836b3cea8bd096ee22 +0 -0
  164. data/test/dummy/tmp/cache/assets/D3E/980/sprockets%2F5e82819b1fe416d230b10d76abd948df +0 -0
  165. data/test/dummy/tmp/cache/assets/D3F/A80/sprockets%2F5e2ee04b0c2b6417f9ab728692a738cd +0 -0
  166. data/test/dummy/tmp/cache/assets/D41/340/sprockets%2Ffdc1e8bf346373a650e6d082f522a59e +0 -0
  167. data/test/dummy/tmp/cache/assets/D41/920/sprockets%2F64c94c28c60bbb70d9a3b9e972ae3057 +0 -0
  168. data/test/dummy/tmp/cache/assets/D47/BB0/sprockets%2F40929a27da40e05aa0b4aa0173f1ebb1 +0 -0
  169. data/test/dummy/tmp/cache/assets/D49/740/sprockets%2Fbcb0e6511f88b9af6d70380c86a57b79 +0 -0
  170. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  171. data/test/dummy/tmp/cache/assets/D50/940/sprockets%2Ff601e768c1f96abd3d019e7f7564e3c9 +0 -0
  172. data/test/dummy/tmp/cache/assets/D53/460/sprockets%2F64e051e79ebdaa56bd989d67831f941d +0 -0
  173. data/test/dummy/tmp/cache/assets/D58/150/sprockets%2F70d598d088bce2f8078c80866be9cff0 +0 -0
  174. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  175. data/test/dummy/tmp/cache/assets/D66/E40/sprockets%2F0cd4ea4f30e313f641b96be80a13cf98 +0 -0
  176. data/test/dummy/tmp/cache/assets/D69/5A0/sprockets%2F8a630d58f110eeeffad123986912bae1 +0 -0
  177. data/test/dummy/tmp/cache/assets/D69/E10/sprockets%2F3d4d98cb1ad46a0b7635b75993c2ac0d +0 -0
  178. data/test/dummy/tmp/cache/assets/D6A/920/sprockets%2F9f1c0c3ad8aae418e1004d5cf54f5479 +0 -0
  179. data/test/dummy/tmp/cache/assets/D6B/A70/sprockets%2Fff1bd1557a03e82f5c2c45d58b661a4f +0 -0
  180. data/test/dummy/tmp/cache/assets/D6F/6B0/sprockets%2F1e2a322de4879106937ede70ffa2da6e +0 -0
  181. data/test/dummy/tmp/cache/assets/D70/780/sprockets%2F6c6a33bccf82b144dbd7982f0854f8b0 +0 -0
  182. data/test/dummy/tmp/cache/assets/D73/C90/sprockets%2F9752db727fd681d97becb91a17ad302d +0 -0
  183. data/test/dummy/tmp/cache/assets/D74/A50/sprockets%2Fe50162da67fdab880a08590f618dfc8e +0 -0
  184. data/test/dummy/tmp/cache/assets/D75/270/sprockets%2Fef0b31d47f8f9acc69f0234019b737ee +0 -0
  185. data/test/dummy/tmp/cache/assets/D77/320/sprockets%2F0c96ad8de5e6a049f5df53415baa4697 +0 -0
  186. data/test/dummy/tmp/cache/assets/D7A/CF0/sprockets%2Fb7e1aa09c7c42e2b98895e16dbc839b6 +0 -0
  187. data/test/dummy/tmp/cache/assets/D7B/110/sprockets%2F55184d1c2bc87fc49369d69e10be7adf +0 -0
  188. data/test/dummy/tmp/cache/assets/D81/A40/sprockets%2Ff886784e31a152dc32fdf5cf782d6bd9 +0 -0
  189. data/test/dummy/tmp/cache/assets/D91/AE0/sprockets%2Fab00df33bbe0ef2939b4d43e042e4d77 +0 -0
  190. data/test/dummy/tmp/cache/assets/D9E/1A0/sprockets%2F69bf83cb71b257071ba6db37bdea78f1 +0 -0
  191. data/test/dummy/tmp/cache/assets/D9E/840/sprockets%2Fc8da1010ea3b0a24bd101a2dd319dc4c +0 -0
  192. data/test/dummy/tmp/cache/assets/DA0/880/sprockets%2F89c46cad03e38a94663bfaac1b8d95d0 +0 -0
  193. data/test/dummy/tmp/cache/assets/DA1/950/sprockets%2F1ea6768fec37a8ee2ad758d4152ae1d2 +0 -0
  194. data/test/dummy/tmp/cache/assets/DA1/D40/sprockets%2Ffd605d648ad0a46b3e3ef9cf089a51b6 +0 -0
  195. data/test/dummy/tmp/cache/assets/DA1/FB0/sprockets%2Fe8cba462fd2940b4be7bf2d294fd7209 +0 -0
  196. data/test/dummy/tmp/cache/assets/DA9/140/sprockets%2Fa9dc7b7a71d4a92925c654f09d17fefa +0 -0
  197. data/test/dummy/tmp/cache/assets/DAA/960/sprockets%2F486294de7d016fa0ec65f0f9efa2e19f +0 -0
  198. data/test/dummy/tmp/cache/assets/DAB/9E0/sprockets%2Fa425c97bf53c87ea907267ce66ad5deb +0 -0
  199. data/test/dummy/tmp/cache/assets/DB3/1D0/sprockets%2F095c6e852a938bbfb9fc98a9ea105ee8 +0 -0
  200. data/test/dummy/tmp/cache/assets/DC3/C60/sprockets%2F0c49e61f99da10cf7acc0cac7736b23a +0 -0
  201. data/test/dummy/tmp/cache/assets/DC7/E70/sprockets%2Fdae539d9ce457212fabb2abf298e112d +0 -0
  202. data/test/dummy/tmp/cache/assets/DC8/C90/sprockets%2F880a4acdf2b3dec03f783e63ed10e6e3 +0 -0
  203. data/test/dummy/tmp/cache/assets/DD0/DE0/sprockets%2Fdd9bcfaa02c63a17f16d84fb523fd886 +0 -0
  204. data/test/dummy/tmp/cache/assets/DD0/E10/sprockets%2F7ff09d9b55239e81c67ac0bd1cd60cfb +0 -0
  205. data/test/dummy/tmp/cache/assets/DD3/140/sprockets%2Fdcdc4960e9f9381cbaec40b2f26c8f53 +0 -0
  206. data/test/dummy/tmp/cache/assets/DD4/340/sprockets%2Ff2cff1054cf9ff3d947f1372db9b6aa2 +0 -0
  207. data/test/dummy/tmp/cache/assets/DD7/F90/sprockets%2F3cbb2ecff5ff45927078c4490a93bfeb +0 -0
  208. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  209. data/test/dummy/tmp/cache/assets/DE2/3D0/sprockets%2F503d37fdad31b11af5bd20b78ee3eaa0 +0 -0
  210. data/test/dummy/tmp/cache/assets/DF5/440/sprockets%2Fadaab579f5cf709a6c31b2fe40404ede +0 -0
  211. data/test/dummy/tmp/cache/assets/DFC/4A0/sprockets%2Fb2e7beb7a4bdf292c1b627bf0f84d9f0 +0 -0
  212. data/test/dummy/tmp/cache/assets/E02/C10/sprockets%2Fdd42eb4f61a99477f901cc31ddda7cfd +0 -0
  213. data/test/dummy/tmp/cache/assets/E04/610/sprockets%2Fd7d96ebe1affa231845c03c78ff6eaa7 +0 -0
  214. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  215. data/test/dummy/tmp/cache/assets/E14/060/sprockets%2F7d7d19b9786dbc0f535478bcdcdc8fce +0 -0
  216. data/test/dummy/tmp/cache/assets/E27/F00/sprockets%2F8abb689fab00eaa7301adf5d198f4dce +0 -0
  217. data/test/dummy/tmp/cache/assets/E2B/870/sprockets%2F22736cce6575f0dd0fcedb11ece9cc8a +0 -0
  218. data/test/dummy/tmp/cache/assets/E31/FB0/sprockets%2Fa8bb4c8b0dc7cc0affd698f7e2a27d72 +0 -0
  219. data/test/dummy/tmp/cache/assets/E3B/E00/sprockets%2F4e3fffccff7a681b16a92b6caf8ef761 +0 -0
  220. data/test/dummy/tmp/cache/assets/E57/9C0/sprockets%2Fb3ca68a8872ea6d2cc2bcbfe01a7fde6 +0 -0
  221. data/test/dummy/tmp/cache/assets/E69/200/sprockets%2Ff2e92a9a60ccdd889dd57cd5bdfed0f2 +0 -0
  222. data/test/dummy/tmp/cache/assets/E6B/860/sprockets%2Ffde862d9eef7ace776b5e3ebc470bcb4 +0 -0
  223. data/test/dummy/tmp/cache/assets/F4A/1F0/sprockets%2Ffceff42fa3bdfb2eafbcad5a77ad38ee +0 -0
  224. data/test/integration/navigation_test.rb +10 -0
  225. data/test/rubyception_test.rb +7 -0
  226. data/test/test_helper.rb +15 -0
  227. metadata +495 -0
@@ -0,0 +1,262 @@
1
+ $.ajaxSetup
2
+ beforeSend:(xhr)->
3
+ xhr.setRequestHeader 'Accept', 'application/json'
4
+ cache: false
5
+
6
+ ViewHelpers=
7
+ el_template:(path)->
8
+ attrs = {}
9
+ attrs = @model.attrs() if @model
10
+ html = @template path, attrs
11
+ $(@el).html html
12
+ fire:(event)->
13
+ $(@el).trigger event
14
+ bind_render:->
15
+ _.bindAll @ , 'render'
16
+ @collection.bind 'add' , @add
17
+ @collection.bind 'reset', @render
18
+ validate:->
19
+ Backbone.Validation.bind @,
20
+ invalid: (view, attr, error, selector)->
21
+ l = $("label[for=document_#{attr}]").html()
22
+ $('.errors').addClass 'on'
23
+ $('.errors').append "<tr class='error'><td class='name'>#{l}</td><td>#{error}</td></tr>"
24
+
25
+ ModelHelpers=
26
+ get:(attr)->
27
+ old_attr = @attributes[attr]
28
+ is_function = typeof @[attr] is 'function'
29
+ return @[attr](old_attr) if is_function
30
+ old_attr
31
+ attrs:->
32
+ attrs = {}
33
+ self = @
34
+ attrs = @toJSON()
35
+ attrs['id'] = @id if @id
36
+ _.each attrs, (value,attr)=>
37
+ attrs[attr] = @get attr
38
+ attrs
39
+ CollectionHelpers =
40
+ # @collection.collect
41
+ # ---------------
42
+ #
43
+ # This method is best used with the BackboneHelpers.collect
44
+ # In your view that has a collection you can call collect on
45
+ # the collection and it will render the the individual models
46
+ # if you used BackboneHelpers.collect to render the current
47
+ # view all you have to do now is:
48
+ #
49
+ # (assuming @collect 'projects' was called)
50
+ # @collection.collect
51
+ #
52
+ # This would render the template 'projects/index' and attach
53
+ # it the '.projects'
54
+ #
55
+ # if you don't want to render a template because it already exists
56
+ # you can just set has_template_index to false
57
+ collect:->
58
+ e = $ @context.el
59
+ find = arguments[0]
60
+ has_find = find isnt undefined
61
+ options = arguments[1]
62
+ options ||= {}
63
+
64
+ ti = options.template_index
65
+ delete options.template_index
66
+ template_index = ti
67
+ template_index = "#{@name}/index" if ti is undefined
68
+ e
69
+ html = @context.template template_index, options.args || {}
70
+
71
+ hti = options.has_template_index
72
+ delete options.has_template_index
73
+ e.html html if hti != false
74
+
75
+ t = options.template
76
+ delete options.template
77
+ template = "#{@name}/#{@name.singularize()}"
78
+ template = t if t isnt undefined
79
+ selector = e
80
+ selector = e.find(find) if has_find
81
+ primer = options.primer || template_index
82
+ selector.html ''
83
+
84
+ p = options.primer
85
+ delete options.primer
86
+ if @length == 0 && p
87
+ html = @context.template "#{primer}_primer", {}
88
+ e.html html
89
+ else
90
+ for model in @context.collection.models
91
+ options['model'] = model
92
+ e = @context.partial null, template, options
93
+ selector.append e.el
94
+ BackboneHelpers =
95
+ redirect_on_browse:->
96
+ if @browsing()
97
+ return window.location.pathname = '/signup'
98
+ else
99
+ false
100
+ browsing:->
101
+ $('body').hasClass('logged_out')
102
+ hash:(i=null)->
103
+ e = window.location.hash.replace /#/, ''
104
+ e = e.replace /\?.+$/, ''
105
+ e = e.split '/'
106
+ if i then e[i] else e
107
+ template: (path,data)->
108
+ template = null
109
+ eval "template = Template.#{path.replace(/\//g,'.')}"
110
+ throw "template is undefined: Template.#{path.replace(/\//g,'.')}" if template is undefined
111
+ Milk.render template, data
112
+
113
+ # collect
114
+ # ---------------
115
+ # This method makes it easy to quickly render a collection.
116
+ # all you need to do is pass in the name of the collection you
117
+ # want to be rendered eg.
118
+ #
119
+ # collect 'projects'
120
+ #
121
+ # If your dealing with an association:
122
+ #
123
+ # collect 'projects/tasks', id: 5
124
+ #
125
+ # It will create a collection in this case App.Collections.Projects
126
+ # with the model being App.Models.Project and an url with '/projects'.
127
+ # The collection will be assigned to the @collection instance variable
128
+ # so you can reference it in your view. It will not invoke fetch().
129
+ #
130
+ # It will also called @partial '.projects', 'projects/index' and
131
+ # attach the collection and whatever options you pass to to the
132
+ # collect method.
133
+ #
134
+ # If you want to override the el of the partial you just need to specify
135
+ # the el the option. eg.
136
+ #
137
+ # @collect 'users', el: '.people'
138
+ #
139
+ # If you want to override the partial path thats being used in the partial you just
140
+ # need to specify the template option (probably should not be called template since
141
+ # that might confuse people with the actual template being render) eg.
142
+ #
143
+ # #collect 'users', template: 'awesome_people/index'
144
+ #
145
+ # If you want to override the model being use you need to pass just the
146
+ # model name to the model option eg.
147
+ #
148
+ # @collect 'groups', model: 'community'
149
+ #
150
+ collect:->
151
+ name = arguments[0]
152
+ options = arguments[1]
153
+ options ||= {}
154
+
155
+ url = options.url if options.url
156
+
157
+ url ||= if name.match(/\//)
158
+ e = name.split '/'
159
+ context = e[0]
160
+ name = e[1]
161
+ reg = new RegExp "#{context}\\/(\\d+)"
162
+ id = options.id
163
+ "/api/#{context}/#{id}/#{name}"
164
+ else
165
+ "/api/#{name}"
166
+ klass = name.camelize()
167
+ has_model = options['model'] isnt undefined
168
+ model_name = if has_model
169
+ model_name = options['model']
170
+ delete options['model']
171
+ model_name.camelize()
172
+ else if @model_name
173
+ model_name = @model_name
174
+ model_name.camelize()
175
+ else
176
+ klass.singularize()
177
+ @collection = if @options.collection isnt undefined
178
+ collection = options['collection']
179
+ delete options['collection']
180
+ collection
181
+ else
182
+ new App.Collections[klass]
183
+ result_model = @result_model || "#{model_name}Result"
184
+ if App.Models[result_model]
185
+ @collection.results_model = new App.Models[result_model]()
186
+ @collection.results_model.collection = @collection
187
+ @collection.url = url
188
+ @collection.model = App.Models[model_name]
189
+ @collection.name = name
190
+ options ||= {}
191
+ options.collection = @collection
192
+
193
+ selector = ".#{name}"
194
+ if options['el'] isnt undefined
195
+ selector = options['el']
196
+ delete options['el']
197
+
198
+ template = "#{name}/index"
199
+ if options['template'] isnt undefined
200
+ template = options['template']
201
+ delete options['template']
202
+ e = @partial selector, template, options
203
+ @collection.context = e
204
+ @collection
205
+ partial:->
206
+ el = arguments[0]
207
+ name = arguments[1]
208
+ options = arguments[2]
209
+ scope = 'App'
210
+ if name.match /admin/
211
+ scope = 'Admin'
212
+ name = name.replace /admin\//, ''
213
+ e = name.split '/'
214
+ options ||= {}
215
+ options['el'] = el if el != null
216
+ p = (item.camelize() for item in e)
217
+ eval "var p = new #{scope}.Views.#{p.join('.')}(options)"
218
+ instance_var = e.join('_')
219
+ @[instance_var] = p
220
+ post:(url,success,data)->
221
+ token = $("meta[name='csrf-token']").attr('content')
222
+ data['authenticity_token'] = token
223
+ $.ajax
224
+ type : 'post'
225
+ url : url,
226
+ data : data
227
+ dataType : 'json'
228
+ context : this
229
+ success : success
230
+ get:(url,success,data)->
231
+ $.ajax
232
+ url : url,
233
+ data : data
234
+ dataType : 'json'
235
+ context : this
236
+ success : success
237
+ resize:->
238
+ App.Helpers.Base.resize_panels()
239
+ _.extend Backbone.Router.prototype , BackboneHelpers
240
+ _.extend Backbone.View.prototype , BackboneHelpers
241
+ _.extend Backbone.View.prototype , ViewHelpers
242
+ _.extend Backbone.Model.prototype , ModelHelpers
243
+ _.extend Backbone.Collection.prototype, CollectionHelpers
244
+
245
+
246
+
247
+ cx_backbone_common =
248
+ sync: (method, model, options) ->
249
+ # Changed attributes will be available here if model.saveChanges was called instead of model.save
250
+ if method == 'update' && model.changedAttributes()
251
+ options.data = JSON.stringify(model.changedAttributes())
252
+ options.contentType = 'application/json';
253
+ Backbone.sync.call(this, method, model, options)
254
+
255
+ cx_backbone_model =
256
+ # Calling this method instead of set will force sync to only send changed attributes
257
+ # Changed event will not be triggered until after the model is synced
258
+ saveChanges: (attrs) ->
259
+ @save(attrs, {wait: true})
260
+
261
+ _.extend(Backbone.Model.prototype, cx_backbone_common, cx_backbone_model)
262
+ _.extend(Backbone.Collection.prototype, cx_backbone_common)
@@ -0,0 +1,261 @@
1
+ # Milk is a simple, fast way to get more Mustache into your CoffeeScript and
2
+ # Javascript.
3
+ #
4
+ # Mustache templates are reasonably simple -- plain text templates are
5
+ # sprinkled with "tags", which are (by default) a pair of curly braces
6
+ # surrounding some bit of content. A good resource for Mustache can be found
7
+ # [here](mustache.github.com).
8
+ TemplateCache = {}
9
+
10
+ # Tags used for working with data get their data by looking up a name in a
11
+ # context stack. This name corresponds to a key in a hash, and the stack is
12
+ # searched top to bottom for an object with given key. Dots in names are
13
+ # special: a single dot ('.') is "top of stack", and dotted names like 'a.b.c'
14
+ # do a chained lookups.
15
+ Find = (name, stack, value = null) ->
16
+ return stack[stack.length - 1] if name == '.'
17
+ [name, parts...] = name.split(/\./)
18
+ for i in [stack.length - 1...-1]
19
+ continue unless stack[i]?
20
+ continue unless typeof stack[i] == 'object' and name of (ctx = stack[i])
21
+ value = ctx[name]
22
+ break
23
+
24
+ value = Find(part, [value]) for part in parts
25
+
26
+ # If we find a function in the stack, we'll treat it as a method, and call it
27
+ # with `this` bound to the element it came from. If a method returns a
28
+ # function, we treat it as a lambda, which doesn't have a bound `this`.
29
+ if value instanceof Function
30
+ value = do (value) -> ->
31
+ val = value.apply(ctx, arguments)
32
+ return (val instanceof Function) and val.apply(null, arguments) or val
33
+
34
+ # Null values will be coerced to the empty string.
35
+ return value
36
+
37
+ # Parsed templates are expanded by simply calling each function in turn.
38
+ Expand = (obj, tmpl, args...) -> (f.call(obj, args...) for f in tmpl).join('')
39
+
40
+ # For parsing, we'll basically need a template string to parse. We do need to
41
+ # remember to take the tag delimiters into account for the cache -- different
42
+ # parse trees can exist for the same template string!
43
+ Parse = (template, delimiters = ['{{','}}'], section = null) ->
44
+ cache = (TemplateCache[delimiters.join(' ')] ||= {})
45
+ return cache[template] if template of cache
46
+
47
+ buffer = []
48
+
49
+ # We'll use a regular expression to handle tag discovery. A proper parser
50
+ # might be faster, but this is simpler, and certainly fast enough for now.
51
+ # Since the tag delimiters may change over time, we'll want to rebuild the
52
+ # regex when they change.
53
+ BuildRegex = ->
54
+ [tagOpen, tagClose] = delimiters
55
+ return ///
56
+ ([\s\S]*?) # Capture the pre-tag content
57
+ ([#{' '}\t]*) # Capture the pre-tag whitespace
58
+ (?: #{tagOpen} \s* # Match the opening tag
59
+ (?:
60
+ (!) \s* ([\s\S]+?) | # Comments
61
+ (=) \s* ([\s\S]+?) \s* = | # Set Delimiters
62
+ ({) \s* (\w[\S]*?) \s* } | # Triple Mustaches
63
+ ([^0-9a-zA-Z._!={]?) \s* ([\w.][\S]*?) # Everything else
64
+ )
65
+ \s* #{tagClose} ) # Match the closing tag
66
+ ///gm
67
+
68
+ tagPattern = BuildRegex()
69
+ tagPattern.lastIndex = pos = (section || { start: 0 }).start
70
+
71
+ # Useful errors should always be prefered - we should compile as much
72
+ # relevant information as possible.
73
+ parseError = (pos, msg) ->
74
+ (endOfLine = /$/gm).lastIndex = pos
75
+ endOfLine.exec(template)
76
+
77
+ parsedLines = template.substr(0, pos).split('\n')
78
+ lineNo = parsedLines.length
79
+ lastLine = parsedLines[lineNo - 1]
80
+ tagStart = contentEnd + whitespace.length
81
+ lastTag = template.substr(tagStart + 1, pos - tagStart - 1)
82
+
83
+ indent = new Array(lastLine.length - lastTag.length + 1).join(' ')
84
+ carets = new Array(lastTag.length + 1).join('^')
85
+ lastLine = lastLine + template.substr(pos, endOfLine.lastIndex - pos)
86
+
87
+ error = new Error()
88
+ error[key] = e[key] for key of e =
89
+ "message": "#{msg}\n\nLine #{lineNo}:\n#{lastLine}\n#{indent}#{carets}"
90
+ "error": msg, "line": lineNo, "char": indent.length, "tag": lastTag
91
+ return error
92
+
93
+ # As we start matching things, let's pull out our captures and build indices.
94
+ while match = tagPattern.exec(template)
95
+ [content, whitespace] = match[1..2]
96
+ type = match[3] || match[5] || match[7] || match[9]
97
+ tag = match[4] || match[6] || match[8] || match[10]
98
+
99
+ contentEnd = (pos + content.length) - 1
100
+ pos = tagPattern.lastIndex
101
+
102
+ # Standalone tags are tags on lines without any non-whitespace characters.
103
+ isStandalone = (contentEnd == -1 or template.charAt(contentEnd) == '\n') &&
104
+ template.charAt(pos) in [ undefined, '', '\r', '\n' ]
105
+
106
+ # We should just add static content to the buffer.
107
+ buffer.push(do (content) -> -> content) if content
108
+
109
+ # If we're dealing with a standalone tag that's not interpolation, we
110
+ # should consume the newline immediately following the tag. If we're not,
111
+ # we need to buffer the whitespace we captured earlier.
112
+ if isStandalone and type not in ['', '&', '{']
113
+ pos += 1 if template.charAt(pos) == '\r'
114
+ pos += 1 if template.charAt(pos) == '\n'
115
+ else if whitespace
116
+ buffer.push(do (whitespace) -> -> whitespace)
117
+ contentEnd += whitespace.length
118
+ whitespace = ''
119
+
120
+ # Now we'll handle the tag itself:
121
+ switch type
122
+
123
+ # Comment tags should simply be ignored.
124
+ when '!' then break
125
+
126
+ # Interpolations are handled by finding the value in the context stack,
127
+ # calling and rendering lambdas, and escaping the value if appropriate.
128
+ when '', '&', '{'
129
+ buildInterpolationTag = (name, is_unescaped) ->
130
+ return (context) ->
131
+ if (value = Find(name, context) ? '') instanceof Function
132
+ value = Expand(this, Parse("#{value()}"), arguments...)
133
+ value = @escape("#{value}") unless is_unescaped
134
+ return "#{value}"
135
+ buffer.push(buildInterpolationTag(tag, type))
136
+
137
+ # Partial data is looked up lazily by the given function, indented as
138
+ # appropriate, and then rendered.
139
+ when '>'
140
+ buildPartialTag = (name, indentation) ->
141
+ return (context, partials) ->
142
+ partial = partials(name).toString()
143
+ partial = partial.replace(/^(?=.)/gm, indentation) if indentation
144
+ return Expand(this, Parse(partial), arguments...)
145
+ buffer.push(buildPartialTag(tag, whitespace))
146
+
147
+ # Sections and Inverted Sections make a recursive parsing pass, allowing
148
+ # us to use the call stack to handle section parsing. This will go until
149
+ # it reaches the matching End Section tag, when it will return the
150
+ # (cached!) template it parsed, along with the index it stopped at.
151
+ when '#', '^'
152
+ sectionInfo =
153
+ name: tag, start: pos
154
+ error: parseError(tagPattern.lastIndex, "Unclosed section '#{tag}'!")
155
+ [tmpl, pos] = Parse(template, delimiters, sectionInfo)
156
+
157
+ # Sections are rendered by finding the value in the context stack,
158
+ # coercing it into an array (unless the value is falsey), and rendering
159
+ # the template with each element of the array taking a turn atop the
160
+ # context stack. If the value was a function, the template is filtered
161
+ # through it before rendering.
162
+ sectionInfo['#'] = buildSectionTag = (name, delims, raw) ->
163
+ return (context) ->
164
+ value = Find(name, context) || []
165
+ tmpl = if value instanceof Function then value(raw) else raw
166
+ value = [value] unless value instanceof Array
167
+ parsed = Parse(tmpl || '', delims)
168
+
169
+ context.push(value)
170
+ result = for v in value
171
+ context[context.length - 1] = v
172
+ Expand(this, parsed, arguments...)
173
+ context.pop()
174
+
175
+ return result.join('')
176
+
177
+ # Inverted Sections render under almost opposite conditions: their
178
+ # contents will only be rendered when the retrieved value is either
179
+ # falsey or an empty array.
180
+ sectionInfo['^'] = buildInvertedSectionTag = (name, delims, raw) ->
181
+ return (context) ->
182
+ value = Find(name, context) || []
183
+ value = [1] unless value instanceof Array
184
+ value = if value.length is 0 then Parse(raw, delims) else []
185
+ return Expand(this, value, arguments...)
186
+
187
+ buffer.push(sectionInfo[type](tag, delimiters, tmpl))
188
+
189
+ # When the parser encounters an End Section tag, it runs a couple of
190
+ # quick sanity checks, then returns control back to its caller.
191
+ when '/'
192
+ unless section?
193
+ error = "End Section tag '#{tag}' found, but not in section!"
194
+ else if tag != (name = section.name)
195
+ error = "End Section tag closes '#{tag}'; expected '#{name}'!"
196
+ throw parseError(tagPattern.lastIndex, error) if error
197
+
198
+ template = template[section.start..contentEnd]
199
+ cache[template] = buffer
200
+ return [template, pos]
201
+
202
+ # The Set Delimiters tag needs to update the delimiters after some error
203
+ # checking, and rebuild the regular expression we're using to match tags.
204
+ when '='
205
+ unless (delimiters = tag.split(/\s+/)).length == 2
206
+ error = "Set Delimiters tags should have two and only two values!"
207
+ throw parseError(tagPattern.lastIndex, error) if error
208
+
209
+ escape = /[-[\]{}()*+?.,\\^$|#]/g
210
+ delimiters = (d.replace(escape, "\\$&") for d in delimiters)
211
+ tagPattern = BuildRegex()
212
+
213
+ # Any other tag type is probably a typo.
214
+ else
215
+ throw parseError(tagPattern.lastIndex, "Unknown tag type -- #{type}")
216
+
217
+ # Now that we've finished with this tag, we prepare to parse the next one!
218
+ tagPattern.lastIndex = if pos? then pos else template.length
219
+
220
+ # At this point, we've parsed all the tags. If we've still got a `section`,
221
+ # someone left a section tag open.
222
+ throw section.error if section?
223
+
224
+ # All the tags is not all the content; if there's anything left over, append
225
+ # it to the buffer. Then we'll cache the buffer and return it!
226
+ buffer.push(-> template[pos..]) unless template.length == pos
227
+ return cache[template] = buffer
228
+
229
+ # ### Public API
230
+
231
+ # The exported object (globally `Milk` in browsers) forms Milk's public API:
232
+ Milk =
233
+ VERSION: '1.2.0'
234
+ # Helpers are a form of context, implicitly on the bottom of the stack. This
235
+ # is a global value, and may be either an object or an array.
236
+ helpers: []
237
+ # Partials may also be provided globally.
238
+ partials: null
239
+ # The `escape` method performs basic content escaping, and may be either
240
+ # called or overridden with an alternate escaping mechanism.
241
+ escape: (value) ->
242
+ entities = { '&': 'amp', '"': 'quot', '<': 'lt', '>': 'gt' }
243
+ return value.replace(/[&"<>]/g, (ch) -> "&#{ entities[ch] };")
244
+ # Rendering is simple: given a template and some data, it populates the
245
+ # template. If your template uses Partial Tags, you may also supply a hash or
246
+ # a function, or simply override `Milk.partials`. There is no Step Three.
247
+ render: (template, data, partials = null) ->
248
+ unless (partials ||= @partials || {}) instanceof Function
249
+ partials = do (partials) -> (name) ->
250
+ throw "Unknown partial '#{name}'!" unless name of partials
251
+ return Find(name, [partials])
252
+
253
+ context = if @helpers instanceof Array then @helpers else [@helpers]
254
+ return Expand(this, Parse(template), context.concat([data]), partials)
255
+
256
+ # Happy hacking!
257
+ if exports?
258
+ exports[key] = Milk[key] for key of Milk
259
+ else
260
+ this.Milk = Milk
261
+