spontaneous 0.2.0.alpha2 → 0.2.0.alpha3

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 (404) hide show
  1. data/Gemfile +3 -40
  2. data/Rakefile +29 -41
  3. data/Readme.markdown +21 -8
  4. data/application/css/add_alias_dialogue.css.scss +79 -0
  5. data/application/css/{v2.scss → core.css.scss} +537 -550
  6. data/application/css/{definitions.scss → definitions.css.scss} +121 -33
  7. data/application/css/dialogue.css.scss +409 -0
  8. data/application/css/{editing.scss → editing.css.scss} +25 -262
  9. data/application/css/font.css.scss +8 -0
  10. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  11. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  12. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_flat_10_000000_40x100.png +0 -0
  13. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  14. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  15. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  16. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  17. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  18. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  19. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_222222_256x240.png +0 -0
  20. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_228ef1_256x240.png +0 -0
  21. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_ef8c08_256x240.png +0 -0
  22. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_ffd27a_256x240.png +0 -0
  23. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_ffffff_256x240.png +0 -0
  24. data/application/css/jquery-ui-1.8.21.custom/ui-lightness.css.scss +565 -0
  25. data/application/css/{login.scss → login.css.scss} +4 -4
  26. data/application/css/meta.css.scss +331 -0
  27. data/application/css/{popover.scss → popover.css.scss} +9 -8
  28. data/application/css/{schema_error.scss → schema_error.css.scss} +4 -4
  29. data/application/css/spontaneous.css +5 -0
  30. data/application/css/unsupported.css.scss +42 -0
  31. data/application/js/add_alias_dialogue.js +72 -10
  32. data/application/js/ajax.js +50 -16
  33. data/application/js/compatibility.js +19 -15
  34. data/application/js/content.js +39 -36
  35. data/application/js/content_area.js +53 -5
  36. data/application/js/dialogue.js +17 -0
  37. data/application/js/dom.js +1 -1
  38. data/application/js/edit_panel.js +23 -8
  39. data/application/js/extensions.js +7 -2
  40. data/application/js/field_preview.js +2 -1
  41. data/application/js/field_types/date_field.js +11 -8
  42. data/application/js/field_types/file_field.js +188 -9
  43. data/application/js/field_types/image_field.js +46 -29
  44. data/application/js/field_types/markdown_field.js +57 -14
  45. data/application/js/field_types/select_field.js +72 -0
  46. data/application/js/field_types/string_field.js +8 -0
  47. data/application/js/field_types/webvideo_field.js +8 -0
  48. data/application/js/init.js +1 -7
  49. data/application/js/location.js +41 -13
  50. data/application/js/login.js +3 -0
  51. data/application/js/meta_view/user_admin.js +543 -0
  52. data/application/js/meta_view.js +1 -0
  53. data/application/js/metadata.js +20 -0
  54. data/application/js/page.js +17 -3
  55. data/application/js/page_browser.js +40 -30
  56. data/application/js/page_entry.js +4 -0
  57. data/application/js/panel/root_menu.js +66 -0
  58. data/application/js/popover.js +2 -2
  59. data/application/js/preview.js +1 -1
  60. data/application/js/publish.js +138 -30
  61. data/application/js/services.js +43 -0
  62. data/application/js/sharded_upload.js +2 -2
  63. data/application/js/spontaneous.js +64 -5
  64. data/application/js/state.js +20 -9
  65. data/application/js/top_bar.js +273 -150
  66. data/application/js/types.js +20 -15
  67. data/application/js/upload.js +1 -2
  68. data/application/js/user.js +18 -4
  69. data/application/js/vendor/date.js +104 -0
  70. data/application/js/vendor/jquery-ui-1.8.18.custom.min.js +356 -0
  71. data/application/js/views/box_view.js +15 -8
  72. data/application/js/views/page_piece_view.js +11 -8
  73. data/application/js/views/page_view.js +21 -3
  74. data/application/js/views/piece_view.js +19 -10
  75. data/application/js/views.js +3 -0
  76. data/application/static/chromelogo-200x52-45c7cbc93be080bea342df5fcda2ef8b.png +0 -0
  77. data/application/static/dot-texture-9eea29e4ac7ad9a772285252078ec127.png +0 -0
  78. data/application/static/editing-textarea-resize-s-b5af62365eb7e19ea4beccf7242d508e.png +0 -0
  79. data/application/static/editing-texture-1-42b06a3439752490988f30f2a06d5e7c.png +0 -0
  80. data/application/static/font/fontawesome-webfont-5c5c21100a346972a82c34c5e96ffcfe.ttf +0 -0
  81. data/application/static/loop_alt1-white-7894b458528e92216196cae26b4c2c96.svg +12 -0
  82. data/application/static/spontaneous-states-e91ec89db525c62da0105b97cdd781ce.png +0 -0
  83. data/application/views/index.erb +2 -2
  84. data/application/views/login.erb +4 -8
  85. data/application/views/schema_modification_error.html.erb +1 -4
  86. data/application/views/unsupported.erb +9 -7
  87. data/bin/spot +1 -1
  88. data/db/migrations/20110209152710_users_and_groups.rb +10 -10
  89. data/db/migrations/20120305112647_site_modification_time.rb +11 -0
  90. data/db/migrations/20120418153903_add_ownership_of_content.rb +14 -0
  91. data/db/migrations/20120423175416_add_pending_modifications.rb +21 -0
  92. data/db/migrations/20120525164947_add_field_versions.rb +27 -0
  93. data/lib/sequel/plugins/scoped_table_name.rb +10 -1
  94. data/lib/spontaneous/asset/file.rb +25 -0
  95. data/lib/spontaneous/asset/source.rb +28 -0
  96. data/lib/spontaneous/asset.rb +75 -0
  97. data/lib/spontaneous/box.rb +6 -4
  98. data/lib/spontaneous/capistrano/deploy.rb +47 -0
  99. data/lib/spontaneous/capistrano/sync.rb +81 -0
  100. data/lib/spontaneous/capistrano.rb +13 -0
  101. data/lib/spontaneous/change.rb +60 -68
  102. data/lib/spontaneous/cli/assets.rb +29 -0
  103. data/lib/spontaneous/cli/base.rb +0 -48
  104. data/lib/spontaneous/cli/console.rb +1 -1
  105. data/lib/spontaneous/cli/server.rb +6 -4
  106. data/lib/spontaneous/cli/site.rb +28 -17
  107. data/lib/spontaneous/cli/user.rb +107 -0
  108. data/lib/spontaneous/cli.rb +100 -4
  109. data/lib/spontaneous/collections/entry_set.rb +2 -2
  110. data/lib/spontaneous/collections/field_set.rb +48 -22
  111. data/lib/spontaneous/collections/prototype_set.rb +20 -13
  112. data/lib/spontaneous/constants.rb +3 -0
  113. data/lib/spontaneous/content.rb +22 -5
  114. data/lib/spontaneous/errors.rb +3 -3
  115. data/lib/spontaneous/extensions/array.rb +12 -0
  116. data/lib/spontaneous/extensions/enumerable.rb +30 -0
  117. data/lib/spontaneous/extensions/nil.rb +3 -1
  118. data/lib/spontaneous/extensions/string.rb +16 -0
  119. data/lib/spontaneous/field_types/date_field.rb +45 -2
  120. data/lib/spontaneous/field_types/field.rb +42 -9
  121. data/lib/spontaneous/field_types/file_field.rb +68 -0
  122. data/lib/spontaneous/field_types/image_field.rb +63 -0
  123. data/lib/spontaneous/field_types/select_field.rb +109 -0
  124. data/lib/spontaneous/field_types/string_field.rb +6 -1
  125. data/lib/spontaneous/field_types/webvideo_field.rb +85 -27
  126. data/lib/spontaneous/field_types.rb +1 -1
  127. data/lib/spontaneous/field_version.rb +8 -0
  128. data/lib/spontaneous/generators/page.rb +1 -1
  129. data/lib/spontaneous/generators/site/Capfile.tt +1 -4
  130. data/lib/spontaneous/generators/site/Gemfile.tt +13 -6
  131. data/lib/spontaneous/generators/site/config/deploy.rb.tt +28 -0
  132. data/lib/spontaneous/generators/site/config/environments/production.rb.tt +7 -2
  133. data/lib/spontaneous/generators/site.rb +1 -0
  134. data/lib/spontaneous/json.rb +34 -11
  135. data/lib/spontaneous/layout.rb +22 -0
  136. data/lib/spontaneous/media/file.rb +4 -0
  137. data/lib/spontaneous/output/assets/compression.rb +58 -0
  138. data/lib/spontaneous/output/assets.rb +32 -0
  139. data/lib/spontaneous/output/context.rb +179 -0
  140. data/lib/spontaneous/output/format/html.rb +5 -0
  141. data/lib/spontaneous/output/format/plain.rb +5 -0
  142. data/lib/spontaneous/output/format.rb +180 -0
  143. data/lib/spontaneous/output/helpers/classes_helper.rb +18 -0
  144. data/lib/spontaneous/{render/helpers/html_helper.rb → output/helpers/conditional_comment_helper.rb} +3 -12
  145. data/lib/spontaneous/output/helpers/script_helper.rb +73 -0
  146. data/lib/spontaneous/output/helpers/stylesheet_helper.rb +61 -0
  147. data/lib/spontaneous/output/helpers.rb +28 -0
  148. data/lib/spontaneous/output/template/engine.rb +59 -0
  149. data/lib/spontaneous/output/template/renderer.rb +153 -0
  150. data/lib/spontaneous/output/template.rb +21 -0
  151. data/lib/spontaneous/output.rb +163 -0
  152. data/lib/spontaneous/page.rb +2 -1
  153. data/lib/spontaneous/paths.rb +6 -1
  154. data/lib/spontaneous/permissions/access_key.rb +5 -5
  155. data/lib/spontaneous/permissions/user.rb +81 -35
  156. data/lib/spontaneous/permissions/user_level.rb +26 -22
  157. data/lib/spontaneous/plugins/aliases.rb +76 -12
  158. data/lib/spontaneous/plugins/allowed_types.rb +60 -18
  159. data/lib/spontaneous/plugins/application/paths.rb +0 -28
  160. data/lib/spontaneous/plugins/application/system.rb +35 -0
  161. data/lib/spontaneous/plugins/boxes.rb +4 -0
  162. data/lib/spontaneous/plugins/content_groups.rb +16 -0
  163. data/lib/spontaneous/plugins/entries.rb +50 -30
  164. data/lib/spontaneous/plugins/fields.rb +15 -0
  165. data/lib/spontaneous/plugins/layouts.rb +8 -2
  166. data/lib/spontaneous/plugins/modifications.rb +228 -0
  167. data/lib/spontaneous/plugins/page/formats.rb +67 -42
  168. data/lib/spontaneous/plugins/page/request.rb +10 -0
  169. data/lib/spontaneous/plugins/page/site_timestamps.rb +28 -0
  170. data/lib/spontaneous/plugins/paths.rb +15 -3
  171. data/lib/spontaneous/plugins/publishing.rb +124 -45
  172. data/lib/spontaneous/plugins/render.rb +13 -8
  173. data/lib/spontaneous/plugins/schema_hierarchy.rb +18 -6
  174. data/lib/spontaneous/plugins/site/helpers.rb +53 -0
  175. data/lib/spontaneous/plugins/site/hooks.rb +50 -0
  176. data/lib/spontaneous/plugins/site/map.rb +1 -1
  177. data/lib/spontaneous/plugins/site/paths.rb +13 -0
  178. data/lib/spontaneous/plugins/site/publishing.rb +6 -2
  179. data/lib/spontaneous/plugins/site/{revisions.rb → state.rb} +5 -1
  180. data/lib/spontaneous/plugins/site/storage.rb +4 -0
  181. data/lib/spontaneous/plugins/site/url.rb +15 -0
  182. data/lib/spontaneous/plugins/site_map.rb +13 -3
  183. data/lib/spontaneous/plugins/styles.rb +5 -1
  184. data/lib/spontaneous/plugins/visibility.rb +39 -12
  185. data/lib/spontaneous/prototypes/box_prototype.rb +4 -0
  186. data/lib/spontaneous/prototypes/field_prototype.rb +15 -10
  187. data/lib/spontaneous/publishing/event_client.rb +46 -0
  188. data/lib/spontaneous/publishing/immediate.rb +81 -44
  189. data/lib/spontaneous/publishing/simultaneous.rb +23 -6
  190. data/lib/spontaneous/publishing.rb +4 -3
  191. data/lib/spontaneous/rack/around_back.rb +1 -5
  192. data/lib/spontaneous/rack/around_front.rb +4 -4
  193. data/lib/spontaneous/rack/around_preview.rb +4 -3
  194. data/lib/spontaneous/rack/assets.rb +81 -54
  195. data/lib/spontaneous/rack/authentication.rb +0 -1
  196. data/lib/spontaneous/rack/back.rb +160 -72
  197. data/lib/spontaneous/rack/cookie_authentication.rb +2 -2
  198. data/lib/spontaneous/rack/css.rb +18 -15
  199. data/lib/spontaneous/rack/event_source.rb +9 -21
  200. data/lib/spontaneous/rack/fiber_pool.rb +26 -0
  201. data/lib/spontaneous/rack/front.rb +12 -4
  202. data/lib/spontaneous/rack/helpers.rb +35 -13
  203. data/lib/spontaneous/rack/js.rb +41 -0
  204. data/lib/spontaneous/rack/public.rb +34 -44
  205. data/lib/spontaneous/rack/sse.rb +18 -0
  206. data/lib/spontaneous/rack/static.rb +3 -0
  207. data/lib/spontaneous/rack/user_admin.rb +100 -0
  208. data/lib/spontaneous/rack/user_helpers.rb +1 -1
  209. data/lib/spontaneous/rack.rb +6 -2
  210. data/lib/spontaneous/schema.rb +31 -4
  211. data/lib/spontaneous/search/index.rb +19 -3
  212. data/lib/spontaneous/search/results.rb +1 -1
  213. data/lib/spontaneous/sequel.rb +17 -0
  214. data/lib/spontaneous/site.rb +11 -4
  215. data/lib/spontaneous/state.rb +11 -0
  216. data/lib/spontaneous/storage/cloud.rb +4 -0
  217. data/lib/spontaneous/storage/local.rb +11 -0
  218. data/lib/spontaneous/style.rb +2 -2
  219. data/lib/spontaneous/tasks/database.rake +21 -22
  220. data/lib/spontaneous/utils/database/mysql_dumper.rb +4 -0
  221. data/lib/spontaneous/utils/database/postgres_dumper.rb +78 -0
  222. data/lib/spontaneous/utils/database.rb +6 -3
  223. data/lib/spontaneous/utils/smart_quotes.rb +499 -0
  224. data/lib/spontaneous/utils/smush_it.rb +66 -0
  225. data/lib/spontaneous/utils.rb +3 -1
  226. data/lib/spontaneous/version.rb +2 -2
  227. data/lib/spontaneous.rb +25 -29
  228. data/spontaneous.gemspec +186 -106
  229. data/test/experimental/test_features.rb +1 -1
  230. data/test/fixtures/asset_pipeline/application/css/basic.css.scss +4 -0
  231. data/test/fixtures/asset_pipeline/application/css/complex.css.scss.erb +6 -0
  232. data/test/fixtures/asset_pipeline/application/css/simple.css +3 -0
  233. data/test/fixtures/asset_pipeline/application/css/spontaneous.css +7 -0
  234. data/test/fixtures/asset_pipeline/application/css/subdir/complex.css.scss.erb +6 -0
  235. data/test/fixtures/asset_pipeline/application/css/subdir/library.css.scss +1 -0
  236. data/test/fixtures/asset_pipeline/application/css/subdir/simple.css +3 -0
  237. data/test/fixtures/asset_pipeline/application/js/basic.js.coffee +1 -0
  238. data/test/fixtures/asset_pipeline/application/js/complex.js.coffee.erb +1 -0
  239. data/test/fixtures/asset_pipeline/application/js/login.js +1 -0
  240. data/test/fixtures/asset_pipeline/application/js/require.js +1 -0
  241. data/test/fixtures/asset_pipeline/application/js/simple.js +1 -0
  242. data/test/fixtures/asset_pipeline/application/js/spontaneous.js +5 -0
  243. data/test/fixtures/asset_pipeline/application/js/subdir/complex.js.coffee.erb +1 -0
  244. data/test/fixtures/asset_pipeline/application/js/subdir/library.js.coffee +1 -0
  245. data/test/fixtures/asset_pipeline/application/js/subdir/simple.js +1 -0
  246. data/test/fixtures/asset_pipeline/application/js/vendor/jquery.js +1 -0
  247. data/test/fixtures/asset_pipeline/application/static/dot-texture.png +0 -0
  248. data/test/fixtures/asset_pipeline/application/static/subdir/px.gif +0 -0
  249. data/test/fixtures/assets/public1/css/a.scss +1 -0
  250. data/test/fixtures/assets/public1/js/a.js +1 -0
  251. data/test/fixtures/assets/public1/js/m.coffee +1 -0
  252. data/test/fixtures/assets/public2/css/b.scss +1 -0
  253. data/test/fixtures/assets/public2/css/c.css +1 -0
  254. data/test/fixtures/assets/public2/js/b.js +1 -0
  255. data/test/fixtures/assets/public2/js/c.js +1 -0
  256. data/test/fixtures/assets/public2/js/n.coffee +1 -0
  257. data/test/fixtures/back/config/user_levels.yml +3 -0
  258. data/test/fixtures/back/public/js/coffeescript.coffee +1 -0
  259. data/test/fixtures/back/templates/layouts/standard.css.cut +1 -0
  260. data/test/fixtures/back/templates/layouts/standard.js.cut +1 -0
  261. data/test/fixtures/example_application/config/database.yml +4 -4
  262. data/test/fixtures/helpers/templates/layouts/standard.html.cut +1 -0
  263. data/test/fixtures/helpers/templates/layouts/standard.mobile.cut +1 -0
  264. data/test/fixtures/images/vimlogo.pdf +0 -0
  265. data/test/fixtures/outputs/templates/layouts/standard.atom.cut +1 -0
  266. data/test/fixtures/permissions/config/user_levels.yml +6 -3
  267. data/test/fixtures/serialisation/class_hash.yaml.erb +1 -0
  268. data/test/fixtures/serialisation/root_hash.yaml.erb +2 -2
  269. data/test/fixtures/templates/extended/grandparent.html.cut +7 -7
  270. data/test/fixtures/templates/extended/main.html.cut +5 -5
  271. data/test/fixtures/templates/extended/parent.html.cut +8 -8
  272. data/test/fixtures/templates/extended/partial_with_locals.html.cut +1 -1
  273. data/test/fixtures/templates/extended/with_includes.html.cut +6 -6
  274. data/test/fixtures/templates/extended/with_includes_and_locals.html.cut +6 -7
  275. data/test/fixtures/templates/layouts/entries.html.cut +4 -4
  276. data/test/fixtures/templates/layouts/standard.html.cut +1 -0
  277. data/test/fixtures/templates/layouts/variables.html.cut +1 -1
  278. data/test/fixtures/templates/publishing/templates/layouts/static.html.cut +1 -1
  279. data/test/fixtures/templates/publishing/templates/layouts/static.rtf.cut +1 -0
  280. data/test/fixtures/templates/template_class/complex_template.html.cut +2 -2
  281. data/test/fixtures/templates/template_class/complex_template.pdf.cut +2 -2
  282. data/test/fixtures/templates/template_class/default_template_style.html.cut +1 -1
  283. data/test/fixtures/templates/template_class/images_with_template.html.cut +2 -2
  284. data/test/fixtures/templates/template_class/slots_template.html.cut +2 -2
  285. data/test/fixtures/templates/template_class/slots_template.pdf.cut +2 -2
  286. data/test/fixtures/user_manager/config/user_levels.yml +9 -0
  287. data/test/functional/test_application.rb +7 -7
  288. data/test/functional/test_back.rb +352 -97
  289. data/test/functional/test_front.rb +71 -20
  290. data/test/functional/test_user_manager.rb +284 -0
  291. data/test/javascript/env.js +13505 -0
  292. data/test/javascript/test_markdown.rb +43 -3
  293. data/test/support/custom_matchers.rb +3 -2
  294. data/test/test_helper.rb +50 -9
  295. data/test/test_javascript.rb +13 -13
  296. data/test/ui_helper.rb +1 -1
  297. data/test/unit/test_alias.rb +79 -8
  298. data/test/unit/test_asset_bundler.rb +220 -0
  299. data/test/unit/test_assets.rb +213 -0
  300. data/test/unit/test_async.rb +55 -0
  301. data/test/unit/test_authentication.rb +52 -39
  302. data/test/unit/test_boxes.rb +20 -15
  303. data/test/unit/test_changesets.rb +261 -0
  304. data/test/unit/test_content.rb +73 -33
  305. data/test/unit/test_content_inheritance.rb +18 -18
  306. data/test/unit/test_extensions.rb +26 -0
  307. data/test/unit/test_fields.rb +303 -16
  308. data/test/unit/test_formats.rb +267 -34
  309. data/test/unit/test_helpers.rb +79 -2
  310. data/test/unit/test_images.rb +10 -0
  311. data/test/unit/test_layouts.rb +21 -13
  312. data/test/unit/test_modifications.rb +648 -0
  313. data/test/unit/test_page.rb +6 -2
  314. data/test/unit/test_permissions.rb +101 -27
  315. data/test/unit/test_piece.rb +4 -4
  316. data/test/unit/test_plugins.rb +3 -2
  317. data/test/unit/test_publishing.rb +332 -0
  318. data/test/unit/test_render.rb +118 -67
  319. data/test/unit/test_revisions.rb +546 -0
  320. data/test/unit/test_schema.rb +83 -1
  321. data/test/unit/test_search.rb +59 -0
  322. data/test/unit/test_serialisation.rb +2 -47
  323. data/test/unit/test_site.rb +217 -108
  324. data/test/unit/test_storage.rb +26 -0
  325. data/test/unit/test_structure.rb +2 -2
  326. data/test/unit/test_styles.rb +90 -75
  327. data/test/unit/test_table_scoping.rb +21 -17
  328. data/test/unit/test_templates.rb +75 -69
  329. data/test/{slow → unit}/test_visibility.rb +78 -22
  330. metadata +528 -221
  331. data/application/css/add_alias_dialogue.scss +0 -27
  332. data/application/css/min/14c2a35812c443001b15d8b12a4780f88c678035.css +0 -1
  333. data/application/css/min/565d4c25e82148acb01c45c8d675b37a08676d77.css +0 -1
  334. data/application/css/min/84dbe894ea96eafd321c30823d630817bfc4b03b.css +0 -1
  335. data/application/css/spontaneous.scss +0 -111
  336. data/application/css/unsupported.scss +0 -16
  337. data/application/css/variables.scss +0 -80
  338. data/application/js/min/2a0c2962537a3181fedfff5c92596ba6d3122dc9.js +0 -3
  339. data/application/js/min/4cf1c493d3379ecba5287758c61238034c0893f9.js +0 -2
  340. data/application/js/min/78ac6b99d96750bb6b9f9aad4cb9cd91cd03f391.js +0 -3
  341. data/application/js/min/b8abf302a824c35385ff517b34111e1710ff3b37.js +0 -2
  342. data/application/js/min/c8efb9b9f7c3f6613fcebc6be60f605b6570a382.js +0 -90
  343. data/application/static/diagonal-texture.png +0 -0
  344. data/application/static/editing-0-noise.png +0 -0
  345. data/application/static/editing-1-noise.png +0 -0
  346. data/application/static/editing-texture-1.png +0 -0
  347. data/application/static/editing-texture.png +0 -0
  348. data/application/static/editing-toolbar-shadow-bottom.png +0 -0
  349. data/application/static/editing-toolbar-shadow-top.png +0 -0
  350. data/application/static/inner-glow.png +0 -0
  351. data/application/static/item-buttons-highlight.png +0 -0
  352. data/application/static/item-buttons.png +0 -0
  353. data/application/static/paper-texture-dark.png +0 -0
  354. data/application/static/plus_alt.svg +0 -8
  355. data/application/static/select-arrow-root.png +0 -0
  356. data/application/static/slot-up-arrow.png +0 -0
  357. data/application/static/spontaneous.png +0 -0
  358. data/lib/cutaneous/context_helper.rb +0 -187
  359. data/lib/cutaneous/preview_context.rb +0 -32
  360. data/lib/cutaneous/preview_renderer.rb +0 -10
  361. data/lib/cutaneous/publish_context.rb +0 -10
  362. data/lib/cutaneous/publish_renderer.rb +0 -14
  363. data/lib/cutaneous/publish_template.rb +0 -62
  364. data/lib/cutaneous/publish_token_parser.rb +0 -8
  365. data/lib/cutaneous/renderer.rb +0 -124
  366. data/lib/cutaneous/request_context.rb +0 -9
  367. data/lib/cutaneous/request_renderer.rb +0 -15
  368. data/lib/cutaneous/request_template.rb +0 -11
  369. data/lib/cutaneous/request_token_parser.rb +0 -9
  370. data/lib/cutaneous/token_parser.rb +0 -125
  371. data/lib/cutaneous.rb +0 -48
  372. data/lib/spontaneous/render/context_base.rb +0 -143
  373. data/lib/spontaneous/render/development_renderer.rb +0 -14
  374. data/lib/spontaneous/render/engine.rb +0 -19
  375. data/lib/spontaneous/render/format/html.rb +0 -5
  376. data/lib/spontaneous/render/format.rb +0 -75
  377. data/lib/spontaneous/render/helpers/script_helper.rb +0 -17
  378. data/lib/spontaneous/render/helpers/stylesheet_helper.rb +0 -16
  379. data/lib/spontaneous/render/helpers.rb +0 -14
  380. data/lib/spontaneous/render/preview_context.rb +0 -8
  381. data/lib/spontaneous/render/preview_renderer.rb +0 -24
  382. data/lib/spontaneous/render/publish_context.rb +0 -22
  383. data/lib/spontaneous/render/published_renderer.rb +0 -53
  384. data/lib/spontaneous/render/publishing_renderer.rb +0 -16
  385. data/lib/spontaneous/render/render_cache.rb +0 -26
  386. data/lib/spontaneous/render/renderer.rb +0 -50
  387. data/lib/spontaneous/render/request_context.rb +0 -8
  388. data/lib/spontaneous/render.rb +0 -214
  389. data/test/experimental/test_cutaneous.rb +0 -309
  390. data/test/fixtures/application/css/test.less +0 -5
  391. data/test/slow/test_publishing.rb +0 -1006
  392. /data/application/css/{developer.scss → developer.css.scss} +0 -0
  393. /data/application/js/vendor/{jquery-1.7.1.min.js → jquery.js} +0 -0
  394. /data/application/static/{location-arrow.png → location-arrow-c1c1d3ca472481c61a0a5f8cb289d743.png} +0 -0
  395. /data/application/static/{missing.png → missing-911ce6dbd9f4602e0f3fbcd7e78846a2.png} +0 -0
  396. /data/application/static/{orange-down-arrow.png → orange-down-arrow-395ae1929e8662b2ff0977daf12c35bb.png} +0 -0
  397. /data/application/static/{page-browser-next.png → page-browser-next-ce781a242c23b980b99b9db7abc20b05.png} +0 -0
  398. /data/application/static/{plus-box.png → plus-box-dcde74a1e496f68298c9b443caa1c5d5.png} +0 -0
  399. /data/application/static/{select-arrow.png → select-arrow-6e7dd3745b00e934b0d7a3250c46558b.png} +0 -0
  400. /data/application/static/{slot-down-arrow.png → slot-down-arrow-59ad5f5ee5b52a7ebd00bca4b3104194.png} +0 -0
  401. /data/application/static/{splash.png → splash-65b493a714df9b8b3ab170103401b53d.png} +0 -0
  402. /data/application/static/{spot.png → spot-71fab1d2f065034f5fc15e7bea2ad36c.png} +0 -0
  403. /data/application/static/{spot.svg → spot-8505041082d8d3bbe8d34c29dddb3b7d.svg} +0 -0
  404. /data/application/static/{texture.png → texture-03f7627e8264b1d607113ab32c593a58.png} +0 -0
@@ -10,7 +10,7 @@ module Spontaneous::Permissions
10
10
  many_to_many :groups, :class => :'Spontaneous::Permissions::AccessGroup', :join_table => :spontaneous_groups_users
11
11
  one_to_many :access_keys, :class => :'Spontaneous::Permissions::AccessKey'
12
12
 
13
- set_restricted_columns(:crypted_password)
13
+ set_restricted_columns(:crypted_password, :salt)
14
14
 
15
15
  def_delegators :group, :level, :access_selector
16
16
 
@@ -18,18 +18,53 @@ module Spontaneous::Permissions
18
18
  Digest::SHA1.hexdigest("--#{salt}--#{clear_password}--")
19
19
  end
20
20
 
21
- def self.authenticate(login, clear_password)
21
+ def self.authenticate(login, clear_password, ip_address = nil)
22
22
  if user = self[:login => login, :disabled => false]
23
23
  crypted_password = user.encrypt_password(clear_password)
24
24
  if crypted_password == user.crypted_password
25
- access_key = user.logged_in!
25
+ access_key = user.logged_in!(ip_address)
26
26
  return access_key
27
27
  end
28
28
  end
29
29
  nil
30
30
  end
31
31
 
32
- attr_accessor :password, :password_confirmation
32
+ def self.create(attributes = {})
33
+ level = attributes.delete(:level) || attributes.delete("level")
34
+ user = super
35
+ user.update(:level => Spontaneous::Permissions[level]) if level && user
36
+ user
37
+ end
38
+
39
+ def self.export(user = nil)
40
+ users = self.order(:login).all
41
+ users = users.reject { |u| u.level > user.level } if user
42
+ exported = {}
43
+ exported[:users] = users.map { |u|
44
+ export_user(u)
45
+ }
46
+ base_level = user.nil? ? nil : user.level
47
+ exported[:levels] = UserLevel.all(base_level).map { |level|
48
+ { :level => level.to_s, :can_publish => level.can_publish?, :is_admin => level.admin? }
49
+ }
50
+ exported
51
+ end
52
+
53
+ def self.export_user(u)
54
+ keys = u.access_keys.map { |key|
55
+ {:last_access_at => key.last_access_at.httpdate, :last_access_ip => key.last_access_ip}
56
+ }
57
+ { :id => u.id,
58
+ :name => u.name,
59
+ :email => u.email,
60
+ :login => u.login,
61
+ :level => u.level.to_s,
62
+ :disabled => u.disabled?,
63
+ :keys => keys }
64
+ end
65
+
66
+ attr_accessor :password
67
+ alias_method :disabled?, :disabled
33
68
 
34
69
  ##
35
70
  # Find the highest access level available from all the groups we
@@ -43,13 +78,13 @@ module Spontaneous::Permissions
43
78
  access_keys.map(&:last_access_at).sort.last
44
79
  end
45
80
 
46
- def logged_in!
81
+ def logged_in!(ip_address = nil)
47
82
  self.last_login_at = Time.now
48
- generate_access_key
83
+ generate_access_key(ip_address)
49
84
  end
50
85
 
51
- def generate_access_key
52
- key = AccessKey.new
86
+ def generate_access_key(ip_address)
87
+ key = AccessKey.new(:last_access_ip => ip_address)
53
88
  self.add_access_key(key)
54
89
  self.save
55
90
  key
@@ -62,12 +97,28 @@ module Spontaneous::Permissions
62
97
  def before_save
63
98
  self.salt = Spontaneous::Permissions.random_string(32) if salt.blank?
64
99
  self.crypted_password = encrypt_password(password) unless password.blank?
65
- if self.disabled
66
- access_keys.each { | key | key.delete }
67
- end
100
+ clear_access_keys! if disabled?
68
101
  super
69
102
  end
70
103
 
104
+ def clear_access_keys!
105
+ access_keys.each { | key | key.delete }
106
+ end
107
+
108
+ def enabled?
109
+ !disabled?
110
+ end
111
+
112
+ def disable!
113
+ self.disabled = true
114
+ self.save
115
+ end
116
+
117
+ def enable!
118
+ self.disabled = false
119
+ self.save
120
+ end
121
+
71
122
  def after_create
72
123
  super
73
124
  ensure_group!
@@ -78,11 +129,6 @@ module Spontaneous::Permissions
78
129
  @password = new_password
79
130
  end
80
131
 
81
- def password_confirmation=(new_password)
82
- updating_password!
83
- @password_confirmation = new_password
84
- end
85
-
86
132
  def level=(level)
87
133
  ensure_group!
88
134
  group.level = level
@@ -98,7 +144,15 @@ module Spontaneous::Permissions
98
144
  end
99
145
 
100
146
  def developer?
101
- level.developer?
147
+ level.developer? || false
148
+ end
149
+
150
+ def can_publish?
151
+ level.can_publish? || false
152
+ end
153
+
154
+ def admin?
155
+ level.admin? || false
102
156
  end
103
157
 
104
158
  def export
@@ -106,7 +160,9 @@ module Spontaneous::Permissions
106
160
  :name => name,
107
161
  :email => email,
108
162
  :login => login,
109
- :developer => !!developer?
163
+ :can_publish => can_publish?,
164
+ :developer => developer?,
165
+ :admin => admin?
110
166
  }
111
167
  end
112
168
 
@@ -118,36 +174,26 @@ module Spontaneous::Permissions
118
174
 
119
175
  def validate
120
176
  super
121
- errors.add(:name, 'is required') if name.blank?
177
+ errors.add(:name, 'is required') if name.blank?
122
178
  errors.add(:email, 'is required') if email.blank?
123
- errors.add(:email, 'is invalid') unless email =~ /^[^@]+@.+$/
179
+ errors.add(:email, 'is invalid') unless email.blank? or email =~ /\A[^@]+@.+\z/
124
180
 
125
181
  if login.blank?
126
182
  errors.add(:login, 'is required')
127
183
  else
128
- errors.add(:login, 'should only contain letters, numbers & underscore') unless login =~ /^[a-zA-Z0-9_]+$/
184
+ errors.add(:login, 'should only contain letters, numbers & underscore') unless login =~ /\A[a-zA-Z0-9_]+\z/
129
185
  errors.add(:login, 'should be at least 3 letters long') if login.length < 3
130
186
  end
131
187
 
132
- if errors[:login].empty? && new?
133
- if User[:login => login]
134
- errors.add(:login, "must be unique, login '#{login}' already exists")
135
- end
188
+ if (u = User[:login => login]) && (u.id != id)
189
+ errors.add(:login, "must be unique, login '#{login}' already exists")
136
190
  end
137
191
 
138
192
  if new? || updating_password?
139
193
  if password.blank?
140
194
  errors.add(:password, 'is required')
141
- elsif password_confirmation.blank?
142
- errors.add(:password_confirmation, 'is required')
143
- else
144
- if password != password_confirmation
145
- errors.add(:password_confirmation, 'should match the password')
146
- else
147
- if password.length < 6
148
- errors.add(:password, 'is too short. It should be at least 6 characters')
149
- end
150
- end
195
+ elsif password.length < 8
196
+ errors.add(:password, 'should be at least 6 characters long')
151
197
  end
152
198
  end
153
199
  end
@@ -7,27 +7,26 @@ module Spontaneous::Permissions
7
7
 
8
8
  class Root
9
9
  private(:initialize)
10
- def self.>(level); true; end
11
- def self.>=(level); true; end
12
- def self.<=>(level); 1; end
13
- def self.to_s; 'root'; end
14
- def self.to_sym; :root; end
15
- def self.can_publish?; true; end
16
- def self.developer?; true; end
10
+ def self.>(level) ; level < Root ; end
11
+ def self.>=(level) ; true ; end
12
+ def self.<=>(level) ; 1 ; end
13
+ def self.to_s ; 'root'; end
14
+ def self.to_sym ; :root ; end
15
+ def self.can_publish? ; true ; end
16
+ def self.developer? ; true ; end
17
+ def self.admin? ; true ; end
17
18
  end
18
19
 
19
20
  class None
20
21
  private(:initialize)
21
- def self.>(level); false; end
22
- def self.>=(level)
23
- level.equal?(None)
24
- end
25
-
26
- def self.<=>(level); -1; end
27
- def self.to_s; 'none'; end
28
- def self.to_sym; :none; end
29
- def self.can_publish?; false; end
30
- def self.developer?; false; end
22
+ def self.>(level) ; false ; end
23
+ def self.>=(level) ; level.equal?(None); end
24
+ def self.<=>(level) ; -1 ; end
25
+ def self.to_s ; 'none'; end
26
+ def self.to_sym ; :none ; end
27
+ def self.can_publish? ; false ; end
28
+ def self.developer? ; false ; end
29
+ def self.admin? ; false ; end
31
30
  end
32
31
 
33
32
  class Level
@@ -80,11 +79,16 @@ module Spontaneous::Permissions
80
79
  end
81
80
 
82
81
  def can_publish?
83
- @permissions[:publish]
82
+ @permissions[:publish] || false
84
83
  end
85
84
 
86
85
  def developer?
87
- @permissions[:developer]
86
+ @permissions[:developer] || false
87
+ end
88
+
89
+ # Users with admin level can access the user manager interface
90
+ def admin?
91
+ @permissions[:admin] || false
88
92
  end
89
93
 
90
94
  def to_s
@@ -110,9 +114,9 @@ module Spontaneous::Permissions
110
114
  end
111
115
 
112
116
  def all(base_level = nil)
113
- list = store.to_a.sort { |a, b| a[1] <=> b[1] }
114
- list.reject! { |l| l[1] > get(base_level) } if base_level
115
- list.map { |l| l[0] }
117
+ list = store.values.sort { |a, b| a <=> b }
118
+ list.reject! { |l| l > get(base_level) } if base_level
119
+ list
116
120
  end
117
121
 
118
122
  def root
@@ -6,12 +6,12 @@ module Spontaneous::Plugins
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  included do
9
- many_to_one :target, :class => self, :reciprocal => :aliases
10
- one_to_many :aliases, :class => self, :key => :target_id, :reciprocal => :target
9
+ # '__target' rather than 'target' because we want to override the behaviour of the
10
+ # Content#target method only on classes that are aliases, and this is defined dynamically
11
+ many_to_one :__target, :class => self, :key => :target_id, :reciprocal => :aliases
12
+ one_to_many :aliases, :class => self, :key => :target_id, :reciprocal => :__target
11
13
  add_association_dependencies :aliases => :destroy
12
14
  end
13
- # def self.configure(base)
14
- # end
15
15
 
16
16
  module ClassMethods
17
17
  def alias_of(*args)
@@ -21,12 +21,15 @@ module Spontaneous::Plugins
21
21
  extend ClassAliasMethods
22
22
  include AliasMethods
23
23
  include PieceAliasMethods unless page?
24
- include PageAliasMethods if page?
24
+ include PageAliasMethods if page?
25
+ # alias_method :target, :__target
26
+ alias_method :target=, :__target=
25
27
  end
26
28
 
29
+
27
30
  alias_method :aliases, :alias_of
28
31
 
29
- def targets(owner = nil, box = nil)
32
+ def targets(owner = nil, box = nil, options = {})
30
33
  targets = []
31
34
  classes = []
32
35
  proc_args = [owner, box].compact
@@ -39,7 +42,7 @@ module Spontaneous::Plugins
39
42
  end
40
43
  end
41
44
  query = S::Content.filter(sti_key => classes.map { |c| c.to_s })
42
- if container_procs = @alias_options[:container]
45
+ if (container_procs = @alias_options[:container])
43
46
  containers = [container_procs].flatten.map { |p| p[*proc_args] }.flatten
44
47
  params = []
45
48
  containers.each do |container|
@@ -57,11 +60,24 @@ module Spontaneous::Plugins
57
60
  query = query.and(container_query)
58
61
  end
59
62
  targets.concat(query.all)
60
- if filter = @alias_options[:filter] and filter.is_a?(Proc)
61
- targets.select(&filter)
62
- else
63
- targets
63
+
64
+ if (filter = @alias_options[:filter]) and filter.is_a?(Proc)
65
+ filtered = []
66
+ targets.each { |target|
67
+ filtered << target if filter[*([target, owner, box][0...(filter.arity)])]
68
+ }
69
+ targets = filtered
70
+ end
71
+
72
+ if @alias_options[:unique] && box
73
+ existing = box.map { |entry| entry.target || entry }
74
+ targets.reject! { |target| existing.include?(target) }
75
+ end
76
+
77
+ if (query = options[:search])
78
+ targets.select! { |target| query === target.alias_title }
64
79
  end
80
+ targets
65
81
  end
66
82
 
67
83
  def target_class(class_definition)
@@ -75,9 +91,26 @@ module Spontaneous::Plugins
75
91
 
76
92
 
77
93
  module ClassAliasMethods
94
+ def for_target(target_id)
95
+ self.create(:target_id => target_id)
96
+ end
97
+
78
98
  def alias?
79
99
  true
80
100
  end
101
+
102
+ def use_configured_generator(generator_name, *args)
103
+ return nil unless @alias_options.key?(generator_name)
104
+ (generator = @alias_options[generator_name]).call(*args)
105
+ end
106
+
107
+ def lookup_target(target_id)
108
+ use_configured_generator(:lookup, target_id)
109
+ end
110
+
111
+ def target_slug(target)
112
+ use_configured_generator(:slug, target)
113
+ end
81
114
  end
82
115
 
83
116
  # included only in instances that are aliases
@@ -86,10 +119,25 @@ module Spontaneous::Plugins
86
119
  true
87
120
  end
88
121
 
122
+ def target
123
+ (_target = self.class.lookup_target(self.target_id)) and return _target
124
+ __target
125
+ end
126
+
89
127
  def field?(field_name)
90
128
  super || target.class.field?(field_name)
91
129
  end
92
130
 
131
+ def respond_to_missing?(name, include_private = false)
132
+ return true if target && target.respond_to?(name)
133
+ super
134
+ end
135
+
136
+ def respond_to?(name, include_private = false)
137
+ return true if target && target.respond_to?(name)
138
+ super
139
+ end
140
+
93
141
  def method_missing(method, *args)
94
142
  if target && target.respond_to?(method)
95
143
  if block_given?
@@ -108,6 +156,7 @@ module Spontaneous::Plugins
108
156
  end
109
157
 
110
158
  def style
159
+ return self.resolve_style(self.style_sid) unless target.respond_to?(:resolve_style)
111
160
  if self.class.styles.empty?
112
161
  target.resolve_style(style_sid)
113
162
  else
@@ -120,9 +169,21 @@ module Spontaneous::Plugins
120
169
  end
121
170
 
122
171
  def export(user = nil)
123
- super.merge(:target => target.shallow_export(user), :alias_title => target.alias_title, :alias_icon => target.exported_alias_icon)
172
+ super.merge(:target => exported_target(user), :alias_title => target.alias_title, :alias_icon => target.exported_alias_icon)
124
173
  end
125
174
 
175
+ def exported_target(user = nil)
176
+ case target
177
+ when S::Content
178
+ target.shallow_export(user)
179
+ else
180
+ target.to_json
181
+ end
182
+ end
183
+
184
+ def hidden?
185
+ super || target.nil? || (target.respond_to?(:hidden?) && target.hidden?)
186
+ end
126
187
  end
127
188
 
128
189
  module PieceAliasMethods
@@ -133,6 +194,9 @@ module Spontaneous::Plugins
133
194
 
134
195
  module PageAliasMethods
135
196
  def slug
197
+ unless target.respond_to?(:slug)
198
+ slug = self.class.target_slug(target) and return slug
199
+ end
136
200
  target.slug
137
201
  end
138
202
 
@@ -28,25 +28,42 @@ module Spontaneous::Plugins
28
28
  end
29
29
 
30
30
  def instance_class
31
- case @type
31
+ resolve_instance_class(@type)
32
+ end
33
+
34
+ def resolve_instance_class(name)
35
+ case name
32
36
  when Class
33
- @type
37
+ name
34
38
  when Symbol, String
35
- @type.to_s.constantize
39
+ name.to_s.constantize
36
40
  end
37
41
  end
38
42
 
39
- def styles
40
- configured_styles || all_styles
43
+ def styles(content)
44
+ configured_styles(content) || all_styles(content)
41
45
  end
42
46
 
43
- def configured_styles
44
- if (@options.key?(:styles) and styles = @options[:styles]) or \
45
- (@options.key?(:style) and styles = [@options[:style]].flatten)
47
+ def configured_styles(content)
48
+ if (styles = style_options)
46
49
  styles.map { |s| instance_class.find_named_style(s) }
47
50
  end
48
51
  end
49
52
 
53
+ def all_styles(content)
54
+ instance_class.styles
55
+ end
56
+
57
+ def default_style(content)
58
+ styles(content).first
59
+ end
60
+
61
+ def style_options
62
+ return Array(@options[:styles]) if @options.key?(:styles)
63
+ return Array(@options[:style]) if @options.key?(:style)
64
+ nil
65
+ end
66
+
50
67
  def includes?(type)
51
68
  if allow_subclasses
52
69
  instance_class.subclasses.include?(type)
@@ -63,14 +80,6 @@ module Spontaneous::Plugins
63
80
  end
64
81
  end
65
82
 
66
- def all_styles
67
- instance_class.styles
68
- end
69
-
70
- def default_style
71
- styles.first
72
- end
73
-
74
83
  def prototype
75
84
  @options[:prototype]
76
85
  end
@@ -86,6 +95,32 @@ module Spontaneous::Plugins
86
95
  alias_method :addable?, :readable?
87
96
  end
88
97
 
98
+ class AllowedGroup < AllowedType
99
+ def groups
100
+ @type
101
+ end
102
+
103
+ def instance_classes
104
+ schema = Spontaneous::Site.schema
105
+ names = groups.flat_map { |name| Spontaneous::Site.schema.groups[name] }
106
+ names.map { |name| resolve_instance_class(name) }.uniq
107
+ end
108
+
109
+ def includes?(type)
110
+ instance_classes.include?(type)
111
+ end
112
+
113
+ def configured_styles(content)
114
+ if (styles = style_options)
115
+ styles.map { |s| content.class.find_named_style(s) }
116
+ end
117
+ end
118
+
119
+ def all_styles(content)
120
+ content.class.styles
121
+ end
122
+ end
123
+
89
124
  module ClassMethods
90
125
  ##
91
126
  # Sets up an allowed type for a particular content type
@@ -114,6 +149,13 @@ module Spontaneous::Plugins
114
149
  # end
115
150
  end
116
151
 
152
+ def allow_group(*group_names)
153
+ options = group_names.extract_options!
154
+ allowed_types_config << AllowedGroup.new(group_names, options)
155
+ end
156
+
157
+ alias_method :allow_groups, :allow_group
158
+
117
159
  def allowed_types_config
118
160
  @_allowed_types ||= []
119
161
  end
@@ -155,7 +197,7 @@ module Spontaneous::Plugins
155
197
  # TODO: BOXES remove box reference here
156
198
  def style_for_content(content, box = nil)
157
199
  if allowed = allowed_type(content)
158
- allowed.default_style
200
+ allowed.default_style(content)
159
201
  else
160
202
  content.default_style
161
203
  end
@@ -163,7 +205,7 @@ module Spontaneous::Plugins
163
205
 
164
206
  def available_styles(content)
165
207
  if allowed = allowed_type(content)
166
- allowed.styles
208
+ allowed.styles(content)
167
209
  else
168
210
  content.class.styles
169
211
  end
@@ -9,14 +9,6 @@ module Spontaneous::Plugins::Application
9
9
  Spontaneous.instance.load_paths
10
10
  end
11
11
 
12
- def template_paths
13
- paths = []
14
- Spontaneous.facets.each do |facet|
15
- paths += facet.paths.expanded(:templates)
16
- end
17
- paths
18
- end
19
-
20
12
  def log_dir(*path)
21
13
  relative_dir(root / "log", *path)
22
14
  end
@@ -25,14 +17,6 @@ module Spontaneous::Plugins::Application
25
17
  relative_dir(root / "config", *path)
26
18
  end
27
19
 
28
- # def template_root=(template_root)
29
- # Spot::Render.template_root = template_root.nil? ? nil : File.expand_path(template_root)
30
- # end
31
-
32
- def template_root(*path)
33
- relative_dir(Spot::Render.template_root, *path)
34
- end
35
-
36
20
  def template_path(*args)
37
21
  File.join(template_root, *args)
38
22
  end
@@ -54,10 +38,6 @@ module Spontaneous::Plugins::Application
54
38
  Spontaneous.schema.schema_map_file = path
55
39
  end
56
40
 
57
- # def media_dir=(dir)
58
- # @media_dir = File.expand_path(dir)
59
- # end
60
-
61
41
  def media_dir(*path)
62
42
  Spontaneous.instance.media_dir(*path)
63
43
  end
@@ -87,18 +67,10 @@ module Spontaneous::Plugins::Application
87
67
  Spontaneous.instance.root(*path)
88
68
  end
89
69
 
90
- # def root=(root)
91
- # @root = File.expand_path(root)
92
- # end
93
-
94
70
  def revision_root(*path)
95
71
  Spontaneous.instance.revision_root(*path)
96
72
  end
97
73
 
98
- # def revision_root=(revision_dir)
99
- # @revision_dir = File.expand_path(revision_dir)
100
- # end
101
-
102
74
  def revision_dir(revision=nil, root = nil)
103
75
  Spontaneous.instance.revision_dir(revision, root)
104
76
  end
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'fiber'
4
+
5
+ module Spontaneous::Plugins::Application
6
+ module System
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def async?
11
+ defined?(::EM) && ::EM.reactor_running?
12
+ end
13
+
14
+ def system(cmd, timeout = 10)
15
+ return async_system(cmd) if async?
16
+ super(cmd)
17
+ end
18
+
19
+ # Invokes an asynchronous system call. Must be wrapped in a Fiber
20
+ # such as that provided by rack-fiber_pool
21
+ def async_system(cmd, timeout = 10)
22
+ deferrable = EM::DefaultDeferrable.new
23
+ fiber = Fiber.current
24
+ EM.system cmd do |output, status|
25
+ deferrable.succeed
26
+ fiber.resume [output, status]
27
+ end
28
+ deferrable.timeout timeout
29
+ deferrable.errback { }
30
+ output, status = Fiber.yield
31
+ status.success?
32
+ end
33
+ end
34
+ end
35
+ end
@@ -75,6 +75,10 @@ module Spontaneous::Plugins
75
75
  @boxes ||= Spontaneous::Collections::BoxSet.new(self)
76
76
  end
77
77
 
78
+ def pieces
79
+ boxes.flat_map { |b| b.pieces }
80
+ end
81
+
78
82
  def iterable
79
83
  boxes
80
84
  end
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Plugins
4
+ module ContentGroups
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ attr_reader :group_memberships
9
+
10
+ def group(*group_names)
11
+ @group_memberships = group_names
12
+ Spontaneous::Site.schema.add_group_member(self, group_names)
13
+ end
14
+ end
15
+ end
16
+ end