spontaneous 0.1.0.alpha1

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 (556) hide show
  1. data/Gemfile +49 -0
  2. data/Gemfile.lock +146 -0
  3. data/LICENSE +0 -0
  4. data/README +0 -0
  5. data/Rakefile +284 -0
  6. data/Readme.markdown +7 -0
  7. data/application/css/add_alias_dialogue.scss +27 -0
  8. data/application/css/definitions.scss +249 -0
  9. data/application/css/developer.scss +9 -0
  10. data/application/css/editing.scss +649 -0
  11. data/application/css/login.scss +91 -0
  12. data/application/css/min/54ee0ed3c7fac7632bd5c020d69e9a2503e0c88c.css +1 -0
  13. data/application/css/min/c256adc144e2bdd0b0539356b04eb62db01e1dc3.css +1 -0
  14. data/application/css/popover.scss +335 -0
  15. data/application/css/schema_error.scss +90 -0
  16. data/application/css/spontaneous.scss +111 -0
  17. data/application/css/unsupported.scss +16 -0
  18. data/application/css/v2.scss +1606 -0
  19. data/application/css/variables.scss +80 -0
  20. data/application/js/add_alias_dialogue.js +59 -0
  21. data/application/js/add_home_dialogue.js +59 -0
  22. data/application/js/ajax.js +99 -0
  23. data/application/js/authentication.js +22 -0
  24. data/application/js/box.js +104 -0
  25. data/application/js/box_container.js +82 -0
  26. data/application/js/compatibility.js +132 -0
  27. data/application/js/conflicted_field_dialogue.js +92 -0
  28. data/application/js/content.js +224 -0
  29. data/application/js/content_area.js +44 -0
  30. data/application/js/dialogue.js +196 -0
  31. data/application/js/dom.js +71 -0
  32. data/application/js/edit_dialogue.js +137 -0
  33. data/application/js/edit_panel.js +232 -0
  34. data/application/js/editing.js +42 -0
  35. data/application/js/entry.js +13 -0
  36. data/application/js/extensions.js +104 -0
  37. data/application/js/field.js +4 -0
  38. data/application/js/field_preview.js +55 -0
  39. data/application/js/field_types/date_field.js +16 -0
  40. data/application/js/field_types/file_field.js +71 -0
  41. data/application/js/field_types/image_field.js +358 -0
  42. data/application/js/field_types/markdown_field.js +656 -0
  43. data/application/js/field_types/string_field.js +185 -0
  44. data/application/js/image.js +72 -0
  45. data/application/js/init.js +34 -0
  46. data/application/js/load.js +4 -0
  47. data/application/js/location.js +157 -0
  48. data/application/js/login.js +53 -0
  49. data/application/js/min/492a209de8ee955fa9c729a765377495001e11b1.js +17 -0
  50. data/application/js/min/80f684d77c940887a1d4a63e3a96102e993baa98.js +88 -0
  51. data/application/js/min/b8abf302a824c35385ff517b34111e1710ff3b37.js +2 -0
  52. data/application/js/min/c7140ec9475e5bf868b901e0621338d7d162358b.js +3 -0
  53. data/application/js/min/f07f2bd6630ee31e1c2288ec223383d8f0658ba6.js +2 -0
  54. data/application/js/page.js +43 -0
  55. data/application/js/page_browser.js +147 -0
  56. data/application/js/page_entry.js +47 -0
  57. data/application/js/popover.js +99 -0
  58. data/application/js/popover_view.js +56 -0
  59. data/application/js/preview.js +64 -0
  60. data/application/js/progress.js +358 -0
  61. data/application/js/properties.js +90 -0
  62. data/application/js/publish.js +187 -0
  63. data/application/js/require.js +129 -0
  64. data/application/js/sharded_upload.js +206 -0
  65. data/application/js/side_bar.js +30 -0
  66. data/application/js/spontaneous.js +6 -0
  67. data/application/js/state.js +64 -0
  68. data/application/js/status_bar.js +47 -0
  69. data/application/js/top_bar.js +368 -0
  70. data/application/js/types.js +98 -0
  71. data/application/js/upload.js +88 -0
  72. data/application/js/upload_manager.js +319 -0
  73. data/application/js/user.js +37 -0
  74. data/application/js/vendor/.DS_Store +0 -0
  75. data/application/js/vendor/JS.Class-2.1.5/CHANGELOG +283 -0
  76. data/application/js/vendor/JS.Class-2.1.5/MIT-LICENSE +30 -0
  77. data/application/js/vendor/JS.Class-2.1.5/README +30 -0
  78. data/application/js/vendor/JS.Class-2.1.5/min/command.js +1 -0
  79. data/application/js/vendor/JS.Class-2.1.5/min/comparable.js +1 -0
  80. data/application/js/vendor/JS.Class-2.1.5/min/constant_scope.js +1 -0
  81. data/application/js/vendor/JS.Class-2.1.5/min/core.js +1 -0
  82. data/application/js/vendor/JS.Class-2.1.5/min/decorator.js +1 -0
  83. data/application/js/vendor/JS.Class-2.1.5/min/enumerable.js +1 -0
  84. data/application/js/vendor/JS.Class-2.1.5/min/forwardable.js +1 -0
  85. data/application/js/vendor/JS.Class-2.1.5/min/hash.js +1 -0
  86. data/application/js/vendor/JS.Class-2.1.5/min/linked_list.js +1 -0
  87. data/application/js/vendor/JS.Class-2.1.5/min/loader.js +1 -0
  88. data/application/js/vendor/JS.Class-2.1.5/min/method_chain.js +1 -0
  89. data/application/js/vendor/JS.Class-2.1.5/min/observable.js +1 -0
  90. data/application/js/vendor/JS.Class-2.1.5/min/package.js +1 -0
  91. data/application/js/vendor/JS.Class-2.1.5/min/proxy.js +1 -0
  92. data/application/js/vendor/JS.Class-2.1.5/min/ruby.js +1 -0
  93. data/application/js/vendor/JS.Class-2.1.5/min/set.js +1 -0
  94. data/application/js/vendor/JS.Class-2.1.5/min/stack_trace.js +1 -0
  95. data/application/js/vendor/JS.Class-2.1.5/min/state.js +1 -0
  96. data/application/js/vendor/JS.Class-2.1.5/min/stdlib.js +16 -0
  97. data/application/js/vendor/JS.Class-2.1.5/src/command.js +93 -0
  98. data/application/js/vendor/JS.Class-2.1.5/src/comparable.js +37 -0
  99. data/application/js/vendor/JS.Class-2.1.5/src/constant_scope.js +48 -0
  100. data/application/js/vendor/JS.Class-2.1.5/src/core.js +1060 -0
  101. data/application/js/vendor/JS.Class-2.1.5/src/decorator.js +50 -0
  102. data/application/js/vendor/JS.Class-2.1.5/src/enumerable.js +505 -0
  103. data/application/js/vendor/JS.Class-2.1.5/src/forwardable.js +22 -0
  104. data/application/js/vendor/JS.Class-2.1.5/src/hash.js +334 -0
  105. data/application/js/vendor/JS.Class-2.1.5/src/linked_list.js +114 -0
  106. data/application/js/vendor/JS.Class-2.1.5/src/loader.js +553 -0
  107. data/application/js/vendor/JS.Class-2.1.5/src/method_chain.js +172 -0
  108. data/application/js/vendor/JS.Class-2.1.5/src/observable.js +55 -0
  109. data/application/js/vendor/JS.Class-2.1.5/src/package.js +472 -0
  110. data/application/js/vendor/JS.Class-2.1.5/src/proxy.js +58 -0
  111. data/application/js/vendor/JS.Class-2.1.5/src/ruby.js +44 -0
  112. data/application/js/vendor/JS.Class-2.1.5/src/set.js +332 -0
  113. data/application/js/vendor/JS.Class-2.1.5/src/stack_trace.js +151 -0
  114. data/application/js/vendor/JS.Class-2.1.5/src/state.js +95 -0
  115. data/application/js/vendor/JS.Class-2.1.5/src/stdlib.js +2612 -0
  116. data/application/js/vendor/crypto-2.3.0-crypto.js +160 -0
  117. data/application/js/vendor/crypto-2.3.0-sha1.js +91 -0
  118. data/application/js/vendor/diff_match_patch.js +2153 -0
  119. data/application/js/vendor/jquery-1.4.2.min.js +154 -0
  120. data/application/js/vendor/jquery-1.4.3.min.js +166 -0
  121. data/application/js/vendor/jquery-1.5.1.min.js +16 -0
  122. data/application/js/vendor/jquery-1.5.1rc1.min.js +24 -0
  123. data/application/js/vendor/jquery-1.6.2.min.js +18 -0
  124. data/application/js/vendor/jquery-ui-1.8.6.custom.min.js +265 -0
  125. data/application/js/vendor/jquery-ui-1.8.9.custom.min.js +415 -0
  126. data/application/js/vendor/jquery-ui-1.8.custom.min.js +106 -0
  127. data/application/js/vendor/jquery.hotkeys-0.7.9.js +248 -0
  128. data/application/js/vendor/jquery.hotkeys-0.7.9.min.js +19 -0
  129. data/application/js/vendor/jsdiff.js +169 -0
  130. data/application/js/views/box_view.js +229 -0
  131. data/application/js/views/page_piece_view.js +45 -0
  132. data/application/js/views/page_view.js +238 -0
  133. data/application/js/views/piece_view.js +178 -0
  134. data/application/js/views.js +110 -0
  135. data/application/static/editing-0-noise.png +0 -0
  136. data/application/static/editing-1-noise.png +0 -0
  137. data/application/static/editing-texture-1.png +0 -0
  138. data/application/static/editing-texture.png +0 -0
  139. data/application/static/editing-toolbar-shadow-bottom.png +0 -0
  140. data/application/static/editing-toolbar-shadow-top.png +0 -0
  141. data/application/static/favicon.ico +0 -0
  142. data/application/static/inner-glow.png +0 -0
  143. data/application/static/item-buttons.png +0 -0
  144. data/application/static/location-arrow.png +0 -0
  145. data/application/static/logo-400px-transparent.png +0 -0
  146. data/application/static/missing.png +0 -0
  147. data/application/static/orange-down-arrow.png +0 -0
  148. data/application/static/page-browser-next.png +0 -0
  149. data/application/static/paper-texture-dark.png +0 -0
  150. data/application/static/px.gif +0 -0
  151. data/application/static/select-arrow-root.png +0 -0
  152. data/application/static/select-arrow.png +0 -0
  153. data/application/static/slot-down-arrow.png +0 -0
  154. data/application/static/splash.png +0 -0
  155. data/application/static/spontaneous.png +0 -0
  156. data/application/static/spot.png +0 -0
  157. data/application/static/spot.svg +40 -0
  158. data/application/static/texture.png +0 -0
  159. data/application/views/index.erubis +46 -0
  160. data/application/views/login.erubis +69 -0
  161. data/application/views/schema_modification_error.html.erb +61 -0
  162. data/application/views/unsupported.erubis +23 -0
  163. data/bin/limit-upload +5 -0
  164. data/bin/spot +10 -0
  165. data/bin/unlimit-upload +3 -0
  166. data/config/nginx.conf +60 -0
  167. data/db/migrations/20100610142136_init.rb +66 -0
  168. data/db/migrations/20101130104334_timestamps.rb +44 -0
  169. data/db/migrations/20101202113205_site_publishing_flags.rb +12 -0
  170. data/db/migrations/20101206124543_aliases.rb +16 -0
  171. data/db/migrations/20110201133550_visibility.rb +27 -0
  172. data/db/migrations/20110209152710_users_and_groups.rb +58 -0
  173. data/db/migrations/20110215133910_boxes.rb +25 -0
  174. data/db/migrations/20110521114145_remove_slots_and_entries.rb +21 -0
  175. data/db/migrations/20110604192145_rename_schema_id_columns.rb +22 -0
  176. data/db/migrations/20110805141925_rename_site_to_state.rb +11 -0
  177. data/lib/cutaneous/context_helper.rb +82 -0
  178. data/lib/cutaneous/first_pass_parser.rb +23 -0
  179. data/lib/cutaneous/first_pass_renderer.rb +18 -0
  180. data/lib/cutaneous/parser_core.rb +18 -0
  181. data/lib/cutaneous/preview_context.rb +31 -0
  182. data/lib/cutaneous/preview_renderer.rb +15 -0
  183. data/lib/cutaneous/publish_context.rb +9 -0
  184. data/lib/cutaneous/renderer.rb +122 -0
  185. data/lib/cutaneous/request_context.rb +8 -0
  186. data/lib/cutaneous/second_pass_parser.rb +23 -0
  187. data/lib/cutaneous/second_pass_renderer.rb +18 -0
  188. data/lib/cutaneous.rb +47 -0
  189. data/lib/sequel/plugins/content_table_inheritance.rb +196 -0
  190. data/lib/sequel/plugins/yajl_serialization.rb +154 -0
  191. data/lib/spontaneous/application/feature.rb +9 -0
  192. data/lib/spontaneous/application/plugin.rb +13 -0
  193. data/lib/spontaneous/application.rb +8 -0
  194. data/lib/spontaneous/box.rb +232 -0
  195. data/lib/spontaneous/box_style.rb +64 -0
  196. data/lib/spontaneous/change.rb +107 -0
  197. data/lib/spontaneous/cli/adapter.rb +13 -0
  198. data/lib/spontaneous/cli/base.rb +184 -0
  199. data/lib/spontaneous/cli/console.rb +0 -0
  200. data/lib/spontaneous/cli/media.rb +13 -0
  201. data/lib/spontaneous/cli/server.rb +50 -0
  202. data/lib/spontaneous/cli/site.rb +46 -0
  203. data/lib/spontaneous/cli/sync.rb +42 -0
  204. data/lib/spontaneous/cli/tasks.rb +9 -0
  205. data/lib/spontaneous/cli.rb +83 -0
  206. data/lib/spontaneous/collections/box_set.rb +56 -0
  207. data/lib/spontaneous/collections/change_set.rb +43 -0
  208. data/lib/spontaneous/collections/entry_set.rb +83 -0
  209. data/lib/spontaneous/collections/field_set.rb +53 -0
  210. data/lib/spontaneous/collections/prototype_set.rb +131 -0
  211. data/lib/spontaneous/collections/style_set.rb +13 -0
  212. data/lib/spontaneous/config.rb +156 -0
  213. data/lib/spontaneous/constants.rb +24 -0
  214. data/lib/spontaneous/content.rb +113 -0
  215. data/lib/spontaneous/content_query.rb +17 -0
  216. data/lib/spontaneous/errors.rb +48 -0
  217. data/lib/spontaneous/extensions/array.rb +18 -0
  218. data/lib/spontaneous/extensions/class.rb +17 -0
  219. data/lib/spontaneous/extensions/hash.rb +18 -0
  220. data/lib/spontaneous/extensions/json.rb +26 -0
  221. data/lib/spontaneous/extensions/kernel.rb +7 -0
  222. data/lib/spontaneous/extensions/object.rb +30 -0
  223. data/lib/spontaneous/extensions/object_space.rb +12 -0
  224. data/lib/spontaneous/extensions/string.rb +44 -0
  225. data/lib/spontaneous/facet.rb +47 -0
  226. data/lib/spontaneous/field_types/date_field.rb +12 -0
  227. data/lib/spontaneous/field_types/field.rb +252 -0
  228. data/lib/spontaneous/field_types/image_field.rb +329 -0
  229. data/lib/spontaneous/field_types/markdown_field.rb +37 -0
  230. data/lib/spontaneous/field_types/string_field.rb +14 -0
  231. data/lib/spontaneous/field_types.rb +40 -0
  232. data/lib/spontaneous/generators/page/inline.html.cut +1 -0
  233. data/lib/spontaneous/generators/page/page.html.cut.tt +4 -0
  234. data/lib/spontaneous/generators/page/page.rb.tt +9 -0
  235. data/lib/spontaneous/generators/page.rb +38 -0
  236. data/lib/spontaneous/generators/site/.gitignore +4 -0
  237. data/lib/spontaneous/generators/site/Gemfile.tt +31 -0
  238. data/lib/spontaneous/generators/site/Rakefile.tt +6 -0
  239. data/lib/spontaneous/generators/site/config/back.ru +7 -0
  240. data/lib/spontaneous/generators/site/config/boot.rb +19 -0
  241. data/lib/spontaneous/generators/site/config/database.yml.tt +21 -0
  242. data/lib/spontaneous/generators/site/config/deploy.rb.tt +0 -0
  243. data/lib/spontaneous/generators/site/config/environment.rb.tt +8 -0
  244. data/lib/spontaneous/generators/site/config/environments/development.rb.tt +15 -0
  245. data/lib/spontaneous/generators/site/config/environments/production.rb.tt +5 -0
  246. data/lib/spontaneous/generators/site/config/front.ru +8 -0
  247. data/lib/spontaneous/generators/site/config/user_levels.yml +22 -0
  248. data/lib/spontaneous/generators/site/lib/site.rb.tt +4 -0
  249. data/lib/spontaneous/generators/site/lib/tasks/site.rake.tt +8 -0
  250. data/lib/spontaneous/generators/site/public/css/site.css +0 -0
  251. data/lib/spontaneous/generators/site/public/favicon.ico +0 -0
  252. data/lib/spontaneous/generators/site/public/js/.empty_directory +0 -0
  253. data/lib/spontaneous/generators/site/public/js/site.js +0 -0
  254. data/lib/spontaneous/generators/site/public/robots.txt +0 -0
  255. data/lib/spontaneous/generators/site/schema/.map +1 -0
  256. data/lib/spontaneous/generators/site/schema/page.rb.tt +8 -0
  257. data/lib/spontaneous/generators/site/schema/piece.rb.tt +4 -0
  258. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +13 -0
  259. data/lib/spontaneous/generators/site.rb +77 -0
  260. data/lib/spontaneous/generators.rb +23 -0
  261. data/lib/spontaneous/image_size.rb +117 -0
  262. data/lib/spontaneous/json.rb +33 -0
  263. data/lib/spontaneous/layout.rb +15 -0
  264. data/lib/spontaneous/loader.rb +280 -0
  265. data/lib/spontaneous/logger.rb +369 -0
  266. data/lib/spontaneous/media.rb +84 -0
  267. data/lib/spontaneous/page.rb +92 -0
  268. data/lib/spontaneous/page_controller.rb +18 -0
  269. data/lib/spontaneous/page_piece.rb +77 -0
  270. data/lib/spontaneous/paths.rb +30 -0
  271. data/lib/spontaneous/permissions/access_group.rb +50 -0
  272. data/lib/spontaneous/permissions/access_key.rb +35 -0
  273. data/lib/spontaneous/permissions/user.rb +167 -0
  274. data/lib/spontaneous/permissions/user_level.rb +177 -0
  275. data/lib/spontaneous/permissions.rb +55 -0
  276. data/lib/spontaneous/piece.rb +30 -0
  277. data/lib/spontaneous/plugins/aliases.rb +128 -0
  278. data/lib/spontaneous/plugins/allowed_types.rb +173 -0
  279. data/lib/spontaneous/plugins/application/facets.rb +25 -0
  280. data/lib/spontaneous/plugins/application/paths.rb +137 -0
  281. data/lib/spontaneous/plugins/application/render.rb +29 -0
  282. data/lib/spontaneous/plugins/application/serialisation.rb +16 -0
  283. data/lib/spontaneous/plugins/application/state.rb +86 -0
  284. data/lib/spontaneous/plugins/boxes.rb +84 -0
  285. data/lib/spontaneous/plugins/controllers.rb +52 -0
  286. data/lib/spontaneous/plugins/entries.rb +193 -0
  287. data/lib/spontaneous/plugins/entry.rb +51 -0
  288. data/lib/spontaneous/plugins/fields.rb +103 -0
  289. data/lib/spontaneous/plugins/instance_code.rb +18 -0
  290. data/lib/spontaneous/plugins/layouts.rb +87 -0
  291. data/lib/spontaneous/plugins/media.rb +41 -0
  292. data/lib/spontaneous/plugins/page/formats.rb +67 -0
  293. data/lib/spontaneous/plugins/page/request.rb +89 -0
  294. data/lib/spontaneous/plugins/page_search.rb +64 -0
  295. data/lib/spontaneous/plugins/page_tree.rb +25 -0
  296. data/lib/spontaneous/plugins/paths.rb +125 -0
  297. data/lib/spontaneous/plugins/permissions.rb +63 -0
  298. data/lib/spontaneous/plugins/prototypes.rb +84 -0
  299. data/lib/spontaneous/plugins/publishing.rb +255 -0
  300. data/lib/spontaneous/plugins/render.rb +24 -0
  301. data/lib/spontaneous/plugins/schema_hierarchy.rb +76 -0
  302. data/lib/spontaneous/plugins/schema_id.rb +60 -0
  303. data/lib/spontaneous/plugins/schema_title.rb +33 -0
  304. data/lib/spontaneous/plugins/serialisation.rb +67 -0
  305. data/lib/spontaneous/plugins/site/instance.rb +22 -0
  306. data/lib/spontaneous/plugins/site/map.rb +19 -0
  307. data/lib/spontaneous/plugins/site/publishing.rb +74 -0
  308. data/lib/spontaneous/plugins/site/revisions.rb +28 -0
  309. data/lib/spontaneous/plugins/site/selectors.rb +41 -0
  310. data/lib/spontaneous/plugins/site_map.rb +34 -0
  311. data/lib/spontaneous/plugins/styles.rb +119 -0
  312. data/lib/spontaneous/plugins/supertype.rb +11 -0
  313. data/lib/spontaneous/plugins/visibility.rb +151 -0
  314. data/lib/spontaneous/plugins.rb +20 -0
  315. data/lib/spontaneous/prototypes/box_prototype.rb +168 -0
  316. data/lib/spontaneous/prototypes/field_prototype.rb +112 -0
  317. data/lib/spontaneous/prototypes/layout_prototype.rb +17 -0
  318. data/lib/spontaneous/prototypes/style_prototype.rb +42 -0
  319. data/lib/spontaneous/proxy_object.rb +12 -0
  320. data/lib/spontaneous/publishing/fire_and_forget.rb +57 -0
  321. data/lib/spontaneous/publishing/immediate.rb +197 -0
  322. data/lib/spontaneous/publishing/threaded.rb +25 -0
  323. data/lib/spontaneous/publishing.rb +10 -0
  324. data/lib/spontaneous/rack/around_back.rb +44 -0
  325. data/lib/spontaneous/rack/around_front.rb +29 -0
  326. data/lib/spontaneous/rack/around_preview.rb +26 -0
  327. data/lib/spontaneous/rack/assets.rb +98 -0
  328. data/lib/spontaneous/rack/back.rb +729 -0
  329. data/lib/spontaneous/rack/front.rb +41 -0
  330. data/lib/spontaneous/rack/http.rb +18 -0
  331. data/lib/spontaneous/rack/media.rb +29 -0
  332. data/lib/spontaneous/rack/public.rb +232 -0
  333. data/lib/spontaneous/rack/reloader.rb +42 -0
  334. data/lib/spontaneous/rack/static.rb +25 -0
  335. data/lib/spontaneous/rack.rb +55 -0
  336. data/lib/spontaneous/render/context.rb +100 -0
  337. data/lib/spontaneous/render/development_renderer.rb +14 -0
  338. data/lib/spontaneous/render/engine.rb +19 -0
  339. data/lib/spontaneous/render/format/html.rb +5 -0
  340. data/lib/spontaneous/render/format.rb +70 -0
  341. data/lib/spontaneous/render/preview_renderer.rb +18 -0
  342. data/lib/spontaneous/render/published_renderer.rb +54 -0
  343. data/lib/spontaneous/render/publishing_renderer.rb +13 -0
  344. data/lib/spontaneous/render/renderer.rb +46 -0
  345. data/lib/spontaneous/render.rb +173 -0
  346. data/lib/spontaneous/revision.rb +7 -0
  347. data/lib/spontaneous/schema/schema_modification.rb +260 -0
  348. data/lib/spontaneous/schema/uid.rb +221 -0
  349. data/lib/spontaneous/schema.rb +295 -0
  350. data/lib/spontaneous/server.rb +65 -0
  351. data/lib/spontaneous/site.rb +87 -0
  352. data/lib/spontaneous/state.rb +53 -0
  353. data/lib/spontaneous/style.rb +144 -0
  354. data/lib/spontaneous/tasks/database.rake +9 -0
  355. data/lib/spontaneous/tasks.rb +5 -0
  356. data/lib/spontaneous/version.rb +6 -0
  357. data/lib/spontaneous.rb +179 -0
  358. data/spontaneous.gemspec.tmpl +66 -0
  359. data/test/disabled/test_slots.rb +287 -0
  360. data/test/experimental/test_formats.rb +92 -0
  361. data/test/experimental/test_plugins.rb +64 -0
  362. data/test/fixtures/application/css/test.less +5 -0
  363. data/test/fixtures/application/js/test.js +1 -0
  364. data/test/fixtures/application/static/favicon.ico +1 -0
  365. data/test/fixtures/application/static/test.html +1 -0
  366. data/test/fixtures/application/views/index.erubis +1 -0
  367. data/test/fixtures/back/public/test.html +1 -0
  368. data/test/fixtures/back/templates/layouts/standard.html.cut +1 -0
  369. data/test/fixtures/config/config/environment.rb +4 -0
  370. data/test/fixtures/config/config/environments/development.rb +13 -0
  371. data/test/fixtures/config/config/environments/production.rb +22 -0
  372. data/test/fixtures/config/config/environments/staging.rb +2 -0
  373. data/test/fixtures/example_application/Gemfile +6 -0
  374. data/test/fixtures/example_application/Gemfile.lock +76 -0
  375. data/test/fixtures/example_application/Rakefile +6 -0
  376. data/test/fixtures/example_application/config/back.rb +15 -0
  377. data/test/fixtures/example_application/config/back.ru +8 -0
  378. data/test/fixtures/example_application/config/back.yml +8 -0
  379. data/test/fixtures/example_application/config/boot.rb +16 -0
  380. data/test/fixtures/example_application/config/database.yml +24 -0
  381. data/test/fixtures/example_application/config/environment.rb +4 -0
  382. data/test/fixtures/example_application/config/environments/development.rb +16 -0
  383. data/test/fixtures/example_application/config/environments/production.rb +21 -0
  384. data/test/fixtures/example_application/config/environments/staging.rb +1 -0
  385. data/test/fixtures/example_application/config/front.rb +8 -0
  386. data/test/fixtures/example_application/config/front.ru +8 -0
  387. data/test/fixtures/example_application/config/front.yml +8 -0
  388. data/test/fixtures/example_application/config/schema.yml +48 -0
  389. data/test/fixtures/example_application/config/unicorn.rb +1 -0
  390. data/test/fixtures/example_application/config/user_levels.yml +19 -0
  391. data/test/fixtures/example_application/public/css/test.css +0 -0
  392. data/test/fixtures/example_application/public/favicon.ico +1 -0
  393. data/test/fixtures/example_application/public/js/test.js +0 -0
  394. data/test/fixtures/example_application/public/test.html +1 -0
  395. data/test/fixtures/example_application/schema/client_project.rb +18 -0
  396. data/test/fixtures/example_application/schema/client_projects.rb +8 -0
  397. data/test/fixtures/example_application/schema/home_page.rb +22 -0
  398. data/test/fixtures/example_application/schema/info_page.rb +13 -0
  399. data/test/fixtures/example_application/schema/inline_image.rb +11 -0
  400. data/test/fixtures/example_application/schema/page.rb +4 -0
  401. data/test/fixtures/example_application/schema/piece.rb +3 -0
  402. data/test/fixtures/example_application/schema/project.rb +21 -0
  403. data/test/fixtures/example_application/schema/project_image.rb +18 -0
  404. data/test/fixtures/example_application/schema/projects_page.rb +12 -0
  405. data/test/fixtures/example_application/schema/text.rb +8 -0
  406. data/test/fixtures/example_application/templates/client_project/images.html.cut +1 -0
  407. data/test/fixtures/example_application/templates/client_project.html.cut +4 -0
  408. data/test/fixtures/example_application/templates/client_projects.html.cut +6 -0
  409. data/test/fixtures/example_application/templates/info_page/inline.html.cut +0 -0
  410. data/test/fixtures/example_application/templates/inline_image.html.cut +1 -0
  411. data/test/fixtures/example_application/templates/layouts/home.html.cut +15 -0
  412. data/test/fixtures/example_application/templates/layouts/info.html.cut +3 -0
  413. data/test/fixtures/example_application/templates/layouts/project.html.cut +13 -0
  414. data/test/fixtures/example_application/templates/layouts/projects.html.cut +11 -0
  415. data/test/fixtures/example_application/templates/layouts/standard.html.cut +0 -0
  416. data/test/fixtures/example_application/templates/project/inline.html.cut +5 -0
  417. data/test/fixtures/example_application/templates/project.html.cut +5 -0
  418. data/test/fixtures/example_application/templates/project_image.html.cut +1 -0
  419. data/test/fixtures/example_application/templates/text.html.cut +1 -0
  420. data/test/fixtures/images/rose.greyscale.jpg +0 -0
  421. data/test/fixtures/images/rose.jpg +0 -0
  422. data/test/fixtures/images/size.gif +0 -0
  423. data/test/fixtures/images/size.jpg +0 -0
  424. data/test/fixtures/images/size.png24 +0 -0
  425. data/test/fixtures/images/size.png8 +0 -0
  426. data/test/fixtures/layouts/layouts/custom1.html.cut +1 -0
  427. data/test/fixtures/layouts/layouts/custom1.pdf.cut +0 -0
  428. data/test/fixtures/layouts/layouts/custom1.xml.cut +0 -0
  429. data/test/fixtures/layouts/layouts/custom2.html.cut +1 -0
  430. data/test/fixtures/layouts/layouts/custom3.html.cut +0 -0
  431. data/test/fixtures/layouts/layouts/standard.html.cut +1 -0
  432. data/test/fixtures/media/101/003/rose.jpg +0 -0
  433. data/test/fixtures/permissions/config/user_levels.yml +9 -0
  434. data/test/fixtures/permissions/media/image.jpg +0 -0
  435. data/test/fixtures/plugins/schema_plugin/init.rb +1 -0
  436. data/test/fixtures/plugins/schema_plugin/schema/external.rb +5 -0
  437. data/test/fixtures/plugins/schema_plugin/templates/external.html.cut +1 -0
  438. data/test/fixtures/plugins/schema_plugin/templates/from_plugin.html.cut +0 -0
  439. data/test/fixtures/plugins/schema_plugin/templates/layouts/from_plugin.html.cut +0 -0
  440. data/test/fixtures/public/templates/layouts/default.html.cut +1 -0
  441. data/test/fixtures/public/templates/layouts/default.pdf.cut +1 -0
  442. data/test/fixtures/public/templates/layouts/default.rss.cut +1 -0
  443. data/test/fixtures/public/templates/layouts/dynamic.html.cut +1 -0
  444. data/test/fixtures/public/templates/layouts/standard.html.cut +0 -0
  445. data/test/fixtures/schema/before.yml +24 -0
  446. data/test/fixtures/schema/resolvable.yml +12 -0
  447. data/test/fixtures/schema/schema.yml +7 -0
  448. data/test/fixtures/serialisation/class_hash.yaml.erb +53 -0
  449. data/test/fixtures/serialisation/root_hash.yaml.erb +184 -0
  450. data/test/fixtures/sharding/rose.jpg +0 -0
  451. data/test/fixtures/sharding/xaa +0 -0
  452. data/test/fixtures/sharding/xab +0 -0
  453. data/test/fixtures/sharding/xac +0 -0
  454. data/test/fixtures/sharding/xad +0 -0
  455. data/test/fixtures/sharding/xae +0 -0
  456. data/test/fixtures/sharding/xaf +0 -0
  457. data/test/fixtures/sharding/xag +0 -0
  458. data/test/fixtures/styles/box_a/runny.html.cut +0 -0
  459. data/test/fixtures/styles/box_a.html.cut +1 -0
  460. data/test/fixtures/styles/named2.html.cut +1 -0
  461. data/test/fixtures/styles/orange/apple.html.cut +1 -0
  462. data/test/fixtures/styles/template_class/named1.html.cut +1 -0
  463. data/test/fixtures/styles/template_class/results.html.cut +1 -0
  464. data/test/fixtures/styles/template_class/walky.html.cut +0 -0
  465. data/test/fixtures/styles/template_class.epub.cut +0 -0
  466. data/test/fixtures/styles/template_class.html.cut +1 -0
  467. data/test/fixtures/styles/template_class.pdf.cut +0 -0
  468. data/test/fixtures/styles/template_sub_class1.html.cut +1 -0
  469. data/test/fixtures/templates/aliases/a/a_style.html.cut +0 -0
  470. data/test/fixtures/templates/aliases/a/page.html.cut +0 -0
  471. data/test/fixtures/templates/aliases/a_alias/a_alias_style.html.cut +0 -0
  472. data/test/fixtures/templates/aliases/layouts/b.html.cut +1 -0
  473. data/test/fixtures/templates/aliases/layouts/b_alias.html.cut +1 -0
  474. data/test/fixtures/templates/aliases/layouts/c_alias.html.cut +1 -0
  475. data/test/fixtures/templates/boxes/blank_content/things.html.cut +1 -0
  476. data/test/fixtures/templates/boxes/my_box_class/christy.html.cut +1 -0
  477. data/test/fixtures/templates/boxes/thangs.html.cut +1 -0
  478. data/test/fixtures/templates/boxes/with_template_box.html.cut +1 -0
  479. data/test/fixtures/templates/content/include.html.cut +1 -0
  480. data/test/fixtures/templates/content/include_dir.html.cut +1 -0
  481. data/test/fixtures/templates/content/included.epub.cut +1 -0
  482. data/test/fixtures/templates/content/included.html.cut +1 -0
  483. data/test/fixtures/templates/content/partial/included.html.cut +1 -0
  484. data/test/fixtures/templates/content/preprocess.html.cut +1 -0
  485. data/test/fixtures/templates/content/second.html.cut +1 -0
  486. data/test/fixtures/templates/content/template.epub.cut +1 -0
  487. data/test/fixtures/templates/content/template.html.cut +1 -0
  488. data/test/fixtures/templates/default_style_class.html.cut +1 -0
  489. data/test/fixtures/templates/direct.html.cut +1 -0
  490. data/test/fixtures/templates/extended/grandparent.html.cut +10 -0
  491. data/test/fixtures/templates/extended/main.html.cut +6 -0
  492. data/test/fixtures/templates/extended/parent.html.cut +10 -0
  493. data/test/fixtures/templates/layouts/entries.html.cut +7 -0
  494. data/test/fixtures/templates/layouts/page_style.html.cut +1 -0
  495. data/test/fixtures/templates/layouts/params.html.cut +1 -0
  496. data/test/fixtures/templates/layouts/preview_render.html.cut +2 -0
  497. data/test/fixtures/templates/layouts/standard_page.html.cut +1 -0
  498. data/test/fixtures/templates/layouts/subdir_style.html.cut +1 -0
  499. data/test/fixtures/templates/layouts/template_params.html.cut +1 -0
  500. data/test/fixtures/templates/page_class/inline_style.html.cut +1 -0
  501. data/test/fixtures/templates/preview_render/inline.html.cut +0 -0
  502. data/test/fixtures/templates/publishing/layouts/dynamic.html.cut +1 -0
  503. data/test/fixtures/templates/publishing/layouts/static.html.cut +1 -0
  504. data/test/fixtures/templates/template_class/anonymous_style.html.cut +4 -0
  505. data/test/fixtures/templates/template_class/another_template.html.cut +0 -0
  506. data/test/fixtures/templates/template_class/complex_template.html.cut +6 -0
  507. data/test/fixtures/templates/template_class/complex_template.pdf.cut +6 -0
  508. data/test/fixtures/templates/template_class/default_template_style.html.cut +4 -0
  509. data/test/fixtures/templates/template_class/images_with_template.html.cut +5 -0
  510. data/test/fixtures/templates/template_class/slots_template.html.cut +5 -0
  511. data/test/fixtures/templates/template_class/slots_template.pdf.cut +5 -0
  512. data/test/fixtures/templates/template_class/this_template.epub.cut +1 -0
  513. data/test/fixtures/templates/template_class/this_template.html.cut +1 -0
  514. data/test/fixtures/templates/template_class/this_template.pdf.cut +1 -0
  515. data/test/fixtures/templates/with_default_style_class.html.cut +1 -0
  516. data/test/functional/test_application.rb +176 -0
  517. data/test/functional/test_back.rb +902 -0
  518. data/test/functional/test_front.rb +571 -0
  519. data/test/javascript/test_dom.rb +94 -0
  520. data/test/javascript/test_markdown.rb +97 -0
  521. data/test/slow/test_publishing.rb +987 -0
  522. data/test/slow/test_visibility.rb +250 -0
  523. data/test/support/custom_matchers.rb +77 -0
  524. data/test/support/timing.rb +23 -0
  525. data/test/test_helper.rb +164 -0
  526. data/test/test_javascript.rb +34 -0
  527. data/test/ui/test_page_editing.rb +167 -0
  528. data/test/ui_helper.rb +114 -0
  529. data/test/unit/test_alias.rb +254 -0
  530. data/test/unit/test_authentication.rb +510 -0
  531. data/test/unit/test_boxes.rb +497 -0
  532. data/test/unit/test_config.rb +156 -0
  533. data/test/unit/test_content.rb +221 -0
  534. data/test/unit/test_content_inheritance.rb +103 -0
  535. data/test/unit/test_extensions.rb +14 -0
  536. data/test/unit/test_fields.rb +392 -0
  537. data/test/unit/test_generators.rb +97 -0
  538. data/test/unit/test_image_size.rb +25 -0
  539. data/test/unit/test_images.rb +265 -0
  540. data/test/unit/test_layouts.rb +111 -0
  541. data/test/unit/test_logger.rb +80 -0
  542. data/test/unit/test_media.rb +70 -0
  543. data/test/unit/test_page.rb +244 -0
  544. data/test/unit/test_permissions.rb +834 -0
  545. data/test/unit/test_piece.rb +80 -0
  546. data/test/unit/test_prototype_set.rb +192 -0
  547. data/test/unit/test_prototypes.rb +102 -0
  548. data/test/unit/test_render.rb +359 -0
  549. data/test/unit/test_schema.rb +1009 -0
  550. data/test/unit/test_serialisation.rb +215 -0
  551. data/test/unit/test_site.rb +145 -0
  552. data/test/unit/test_structure.rb +85 -0
  553. data/test/unit/test_styles.rb +417 -0
  554. data/test/unit/test_templates.rb +224 -0
  555. data/test/unit/test_type_hierarchy.rb +28 -0
  556. metadata +1017 -0
@@ -0,0 +1,168 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'hwia'
4
+
5
+ module Spontaneous::Prototypes
6
+ class BoxPrototype
7
+
8
+ attr_reader :name, :options, :owner
9
+
10
+ def initialize(owner, name, options, &block)
11
+ @owner = owner
12
+ @name = name.to_sym
13
+ @options = options
14
+ @extend = block
15
+ end
16
+
17
+ def field_prototypes
18
+ instance_class.field_prototypes
19
+ end
20
+
21
+ def style_prototypes
22
+ instance_class.style_prototypes
23
+ end
24
+
25
+ def schema_id
26
+ instance_class.schema_id
27
+ end
28
+
29
+
30
+ def schema_name
31
+ instance_class.schema_name
32
+ end
33
+
34
+ def schema_owner
35
+ owner
36
+ end
37
+
38
+ def owner_sid
39
+ schema_owner.schema_id
40
+ end
41
+
42
+ def get_instance(owner)
43
+ instance = instance_class.new(name, self, owner)
44
+ end
45
+
46
+ def field_defaults
47
+ @options[:fields]
48
+ end
49
+
50
+ def instance_class
51
+ @_instance_class ||= create_instance_class
52
+ end
53
+
54
+ def create_instance_class
55
+ Class.new(box_base_class).tap do |instance_class|
56
+ box_owner = owner
57
+ box_name = name
58
+ instance_class.instance_eval do
59
+ singleton_class.__send__(:define_method, :schema_name) do
60
+ "box/#{box_owner.schema_id}/#{box_name}"
61
+ end
62
+ singleton_class.__send__(:define_method, :schema_owner) do
63
+ box_owner
64
+ end
65
+ singleton_class.__send__(:define_method, :owner_sid) do
66
+ box_owner.schema_id
67
+ end
68
+ end
69
+ if @extend
70
+ instance_class.class_eval(&@extend)
71
+ end
72
+ end.tap do |klass|
73
+ # doing this means we get proper names for the anonymous box classes
74
+ owner.const_set("#{name.to_s.camelize}Box", klass)
75
+ end
76
+ end
77
+
78
+ def box_base_class
79
+ box_class = Spontaneous::Box # AnonymousBox
80
+ class_name = @options[:type] || @options[:class]
81
+ box_class = class_name.to_s.constantize if class_name
82
+ # box_class = Class.new(box_class) do
83
+ # def self.inherited(subclass)
84
+ # subclasses << subclass
85
+ # end
86
+ # end
87
+ box_class
88
+ end
89
+
90
+ ## failed attempt to exclude anonymous boxes from the list of schema classes
91
+ ## actually easier to keep them in, despite later problems with UID creation
92
+ ## because this way their fields & styles are automatically validated
93
+ # class AnonymousBox < Spontaneous::Box
94
+ # def self.schema_class?
95
+ # false
96
+ # end
97
+ # end
98
+
99
+ def title
100
+ @options[:title] || default_title
101
+ end
102
+
103
+ def default_style
104
+ @options[:style]
105
+ end
106
+
107
+ def default_title
108
+ name.to_s.titleize.gsub(/\band\b/i, '&')
109
+ end
110
+
111
+ def field_prototypes
112
+ instance_class.field_prototypes
113
+ end
114
+
115
+ # default read level is None, i.e. every logged in user can read the field
116
+ def read_level
117
+ level_name = @options[:read_level] || @options[:user_level] || :none
118
+ Spontaneous::Permissions[level_name]
119
+ end
120
+
121
+ # default write level is the first level above None
122
+ def write_level
123
+ level_name = @options[:write_level] || @options[:user_level] || Spontaneous::Permissions::UserLevel.minimum.to_sym
124
+ Spontaneous::Permissions[level_name]
125
+ end
126
+
127
+ # TODO: must be able to make these into a module
128
+ def readable?
129
+ Spontaneous::Permissions.has_level?(read_level)
130
+ end
131
+
132
+ def writable?
133
+ Spontaneous::Permissions.has_level?(write_level)
134
+ end
135
+
136
+ def style
137
+ @options[:style]# || name
138
+ end
139
+
140
+ def readable_fields
141
+ instance_class.readable_fields
142
+ end
143
+
144
+ def allowed_types
145
+ if writable?
146
+ types = []
147
+ instance_class.allowed.select { |a| a.readable? }.each do |a|
148
+ types.concat(a.instance_classes)
149
+ end
150
+ types
151
+ else
152
+ []
153
+ end
154
+ end
155
+
156
+ def export
157
+ allowed = allowed_types.map { |c| c.ui_class }
158
+ {
159
+ :name => name.to_s,
160
+ :id => schema_id.to_s,
161
+ :title => title,
162
+ :writable => writable?,
163
+ :allowed_types => allowed,
164
+ :fields => readable_fields.map { |name| instance_class.field_prototypes[name].export },
165
+ }
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,112 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Spontaneous::Prototypes
5
+ class FieldPrototype
6
+ attr_reader :owner, :name
7
+
8
+ def initialize(owner, name, type, options={})
9
+ @owner = owner
10
+ @name = name
11
+ # if the type is nil then try the name, this will assign sensible defaults
12
+ # to fields like 'image' or 'date'
13
+ base_class = Spontaneous::FieldTypes[type || name]
14
+ if block_given?
15
+ @field_class = Class.new(base_class, &Proc.new)
16
+ @field_class.singleton_class.send(:define_method, :name) do
17
+ base_class.name
18
+ end
19
+ else
20
+ @field_class = base_class
21
+ end
22
+
23
+ # @field_class.prototype = self
24
+ parse_options(options)
25
+ end
26
+
27
+ def schema_name
28
+ "field/#{owner.schema_id}/#{name}"
29
+ end
30
+
31
+ def schema_id
32
+ Spontaneous::Schema.schema_id(self)
33
+ end
34
+
35
+ def schema_owner
36
+ owner
37
+ end
38
+
39
+ def owner_sid
40
+ schema_owner.schema_id
41
+ end
42
+
43
+ # alias_method :id, :schema_id
44
+
45
+ def title(new_title=nil)
46
+ self.title = new_title if new_title
47
+ @title || @options[:title] || default_title
48
+ end
49
+
50
+ def title=(new_title)
51
+ @title = new_title
52
+ end
53
+
54
+ def default_title
55
+ @name.to_s.titleize
56
+ end
57
+
58
+ def parse_options(options)
59
+ @options = {
60
+ :default => '',
61
+ :comment => false
62
+ }.merge(options)
63
+ end
64
+
65
+ def field_class
66
+ @field_class
67
+ end
68
+
69
+ def default
70
+ @options[:default]
71
+ end
72
+
73
+ def comment
74
+ @options[:comment]
75
+ end
76
+
77
+
78
+ # default read level is None, i.e. every logged in user can read the field
79
+ def read_level
80
+ level_name = @options[:read_level] || @options[:user_level] || :none
81
+ Spontaneous::Permissions[level_name]
82
+ end
83
+
84
+ # default write level is the first level above None
85
+ def write_level
86
+ level_name = @options[:write_level] || @options[:user_level] || Spontaneous::Permissions::UserLevel.minimum.to_sym
87
+ Spontaneous::Permissions[level_name]
88
+ end
89
+
90
+ def to_field(values=nil)
91
+ default_values = values.nil?
92
+ values = {
93
+ :name => self.name,
94
+ :unprocessed_value => default
95
+ }.merge(values || {})
96
+ self.field_class.new(values, !default_values).tap do |field|
97
+ field.prototype = self
98
+ end
99
+ end
100
+
101
+ def export
102
+ {
103
+ :name => name.to_s,
104
+ :schema_id => schema_id.to_s,
105
+ :type => field_class.ui_class,
106
+ :title => title,
107
+ :comment => comment || "",
108
+ :writable => Spontaneous::Permissions.has_level?(write_level)
109
+ }
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Prototypes
4
+ class LayoutPrototype < StylePrototype
5
+ def schema_name
6
+ "layout/#{owner.schema_id}/#{name}"
7
+ end
8
+
9
+ def layout(owner)
10
+ Spontaneous::Layout.new(owner, self)
11
+ end
12
+
13
+ def formats
14
+ Spontaneous::Render.formats(self)
15
+ end
16
+ end # LayoutPrototype
17
+ end # Spontaneous::Prototypes
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Prototypes
4
+ class StylePrototype
5
+ attr_reader :owner, :name, :options
6
+
7
+ def initialize(owner, name, options = {})
8
+ @owner, @name, @options = owner, name, options
9
+ end
10
+
11
+ def default?
12
+ options[:default]
13
+ end
14
+
15
+ def schema_name
16
+ "style/#{owner.schema_id}/#{name}"
17
+ end
18
+
19
+ def schema_owner
20
+ owner
21
+ end
22
+
23
+ def owner_sid
24
+ schema_owner.schema_id
25
+ end
26
+
27
+ def style(owner)
28
+ Spontaneous::Style.new(owner, self)
29
+ end
30
+
31
+ def schema_id
32
+ Spontaneous::Schema.schema_id(self)
33
+ end
34
+
35
+ def export
36
+ {
37
+ :name => name.to_s,
38
+ :schema_id => schema_id.to_s
39
+ }
40
+ end
41
+ end # StylePrototype
42
+ end # Spontaneous::Prototypes
@@ -0,0 +1,12 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous
4
+ class ProxyObject
5
+ alias_method :proxy_class, :class
6
+ alias_method :__class__, :class
7
+ alias_method :__methods__, :methods
8
+ alias_method :__is_a?, :is_a?
9
+ instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|object_id|proxy_class/ }
10
+ end
11
+ end
12
+
@@ -0,0 +1,57 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'fire_and_forget'
4
+
5
+ module Spontaneous
6
+ module Publishing
7
+ class FireAndForget
8
+ FAF = ::FireAndForget
9
+
10
+ def self.task_name
11
+ # TODO: add site name to this to make it unique on a server
12
+ :publish
13
+ end
14
+
15
+ def self.register_task
16
+ publish_binary = (Pathname.new(Spontaneous.gem_dir) + "bin/spot publish").expand_path.to_s
17
+ site_root = Pathname.new(Spontaneous.root).expand_path.to_s
18
+ niceness = S.config.publish_niceness || 15
19
+ # TODO: make nice value configurable
20
+ FAF.add_task(task_name, publish_binary, niceness, {
21
+ "site" => site_root,
22
+ "logfile" => "log/publish.log",
23
+ "environment" => Spontaneous.env
24
+ }, {})
25
+ end
26
+
27
+ register_task
28
+
29
+ def self.status
30
+ FAF.get_status(task_name)
31
+ end
32
+
33
+ def self.status=(status)
34
+ FAF.set_status(task_name, status)
35
+ end
36
+
37
+ attr_reader :revision
38
+
39
+ def initialize(revision)
40
+ @revision = revision
41
+ end
42
+
43
+ def task_name
44
+ self.class.task_name
45
+ end
46
+
47
+ def publish_changes(change_list)
48
+ FAF.fire(task_name, {"changes" => change_list})
49
+ end
50
+
51
+ def publish_all
52
+ FAF.fire(task_name)
53
+ end
54
+ end # FireAndForget
55
+ end # Publishing
56
+ end # Spontaneous
57
+
@@ -0,0 +1,197 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous
4
+ module Publishing
5
+ class Immediate
6
+
7
+ def self.status
8
+ @status ||= ""
9
+ end
10
+
11
+ def self.status=(status)
12
+ @status = status
13
+ end
14
+
15
+ attr_reader :revision
16
+
17
+ def initialize(revision)
18
+ @revision = revision
19
+ logger.info { "Publishing revision #{@revision}"}
20
+ end
21
+
22
+ def publish_changes(change_list)
23
+ changes = change_list.flatten.map { |c|
24
+ c.is_a?(S::Change) ? c : S::Change[c]
25
+ }
26
+ all_changes = S::Change.all
27
+ if changes == all_changes
28
+ # publish_all is quicker
29
+ publish_all
30
+ else
31
+ change_set = Spontaneous::Collections::ChangeSet.new(changes)
32
+ publish(change_set.page_ids)
33
+
34
+ changes.each do |change|
35
+ change.destroy
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ def publish_all
42
+ # maybe someone will make a change while we're publishing the site
43
+ # (but after we've duplicated the tables)
44
+ # so save the current list of changes
45
+ # TODO: make sure this is robust
46
+ changes = S::Change.all
47
+ publish(nil)
48
+ changes.each do |change|
49
+ change.destroy
50
+ end
51
+ end
52
+
53
+ # Called from the Format#render method to provide progress reports
54
+ def page_rendered(page)
55
+ @pages_rendered += 1
56
+ set_status("rendering", percent_complete)
57
+ logger.info { "Rendered page #{page.path}" }
58
+ end
59
+
60
+ protected
61
+
62
+ def pages
63
+ @pages ||= S::Page.order(:depth)
64
+ end
65
+
66
+ def formats
67
+ # TODO: read the actual config for the available formats
68
+ [:html]
69
+ end
70
+
71
+ def render_stages
72
+ # TODO: when search infrastructure is in place modify this to include the indexing steps
73
+ 1
74
+ end
75
+
76
+ def publish(pages)
77
+ at_exit {
78
+ abort_publish_at_exit
79
+ }
80
+ before_publish
81
+ begin
82
+ S::Content.publish(revision, pages) do
83
+ render_revision
84
+ end
85
+ after_publish
86
+ rescue Exception => e
87
+ abort_publish(e)
88
+ raise(e)
89
+ end
90
+ end
91
+
92
+ def render_revision
93
+ @pages_rendered = 0
94
+ S::Content.with_identity_map do
95
+ S::Render.with_publishing_renderer do
96
+ set_status("rendering:0")
97
+ formats.each do |format|
98
+ S::Render.render_pages(revision, pages, format, self)
99
+ end
100
+ # only set this after indexing is complete (if any)
101
+ set_status("rendering:100")
102
+ end
103
+ end
104
+ set_status("copying_files")
105
+ copy_static_files
106
+ generate_rackup_file
107
+ end
108
+
109
+ # Used to calculate the progress percentage
110
+ def total_pages_to_render
111
+ @total_pages ||= formats.inject(0) do |total, format|
112
+ total += pages.find_all { |page| page.formats.include?(format) }.count
113
+ end
114
+ end
115
+
116
+ def percent_complete
117
+ ((@pages_rendered || 0).to_f / (total_pages_to_render * render_stages).to_f) * 100.0
118
+ end
119
+
120
+ def set_status(state, progress='*')
121
+ self.class.status = "#{state}:#{progress}"
122
+ end
123
+
124
+ def generate_rackup_file
125
+ # use the real path to the app rather than the symlink in order to sandbox the live site
126
+ # not sure that this is a good idea: it would force a publish for every deploy
127
+ # which is only sometimes appropriate/desirable
128
+ path = Pathname.new(Spontaneous.root).realpath.to_s
129
+ # TODO: enable custom rack middleware by changing config/front into a proper rackup file
130
+ rackup = 'config/front.ru'
131
+ template = (<<-RACKUP).gsub(/^ +/, '')
132
+ # This is an automatically generated file *DO NOT EDIT*
133
+ # To configure your Rack application make your changes in
134
+ # '#{path}/#{rackup}'
135
+
136
+ # Set the revision to display
137
+ ENV["#{Spontaneous::SPOT_REVISION_NUMBER}"] = '#{revision}'
138
+ ENV["#{Spontaneous::SPOT_ROOT}"] = '#{path}'
139
+
140
+ # Change to the absolute path of our application and load the Rack config
141
+ root = '#{path}'
142
+ Dir.chdir(root)
143
+ eval(::File.read('#{rackup}'), binding, ::File.join(root, '#{rackup}'), __LINE__)
144
+
145
+ RACKUP
146
+ rack_file = Spontaneous.revision_dir(revision) / 'config.ru'
147
+ File.open(rack_file, 'w') { |f| f.write(template) }
148
+ end
149
+
150
+ def copy_static_files
151
+ public_dest = Pathname.new(Spontaneous.revision_dir(revision) / 'public')
152
+ public_src = Pathname.new(Spontaneous.root / 'public').realpath
153
+ FileUtils.mkdir_p(public_dest) unless File.exists?(public_dest)
154
+ Dir[public_src.to_s / "**/*"].each do |src|
155
+ src = Pathname.new(src)
156
+ dest = (public_dest + src.relative_path_from(public_src))
157
+ if src.directory?
158
+ dest.mkpath
159
+ else
160
+ FileUtils.ln(src, dest, :force => true)
161
+ end
162
+ end
163
+ end
164
+
165
+ def before_publish
166
+ set_status("initialising")
167
+ S::Site.send(:pending_revision=, revision)
168
+ end
169
+
170
+ def after_publish
171
+ set_status("finalising")
172
+ S::Revision.create(:revision => revision, :published_at => Time.now)
173
+ S::Site.send(:set_published_revision, revision)
174
+ S::Site.send(:pending_revision=, nil)
175
+ tmp = Spontaneous.revision_dir(revision) / "tmp"
176
+ FileUtils.mkdir_p(tmp) unless ::File.exists?(tmp)
177
+ system("ln -nsf #{Spontaneous.revision_dir(revision)} #{Spontaneous.revision_dir}")
178
+ set_status("complete")
179
+ end
180
+
181
+ def abort_publish_at_exit
182
+ abort_publish(nil)
183
+ end
184
+
185
+ def abort_publish(exception)
186
+ if r = S::Site.pending_revision
187
+ set_status("aborting")
188
+ FileUtils.rm_r(Spontaneous.revision_dir(revision)) if File.exists?(Spontaneous.revision_dir(revision))
189
+ S::Site.send(:pending_revision=, nil)
190
+ S::Content.delete_revision(revision)
191
+ puts exception.backtrace.join("\n")
192
+ set_status("error", exception)
193
+ end
194
+ end
195
+ end # Immediate
196
+ end # Publishing
197
+ end # Spontaneous
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous
4
+ module Publishing
5
+ class Threaded < Immediate
6
+
7
+ alias_method :immediate_publish_changes, :publish_changes
8
+
9
+ def publish_changes(change_list)
10
+ Thread.new do
11
+ immediate_publish_changes(change_list)
12
+ end
13
+ end
14
+
15
+ alias_method :immediate_publish_all, :publish_all
16
+
17
+ def publish_all
18
+ Thread.new do
19
+ immediate_publish_all
20
+ end
21
+ end
22
+ end # Forked
23
+ end # Publishing
24
+ end # Spontaneous
25
+
@@ -0,0 +1,10 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous
4
+ module Publishing
5
+ autoload :Immediate, "spontaneous/publishing/immediate"
6
+ autoload :Threaded, "spontaneous/publishing/threaded"
7
+ autoload :FireAndForget, "spontaneous/publishing/fire_and_forget"
8
+ end # Publishing
9
+ end # Spontaneous
10
+
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'less'
4
+
5
+ module Spontaneous
6
+ module Rack
7
+ class AroundBack
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def user(env)
13
+ if login = Site.config.auto_login
14
+ user = Spontaneous::Permissions::User[:login => login]
15
+ else
16
+ request = ::Rack::Request.new(env)
17
+ api_key = request.cookies[Spontaneous::Rack::Back::AUTH_COOKIE]
18
+ if api_key && key = Spontaneous::Permissions::AccessKey.authenticate(api_key)
19
+ key.user
20
+ else
21
+ nil
22
+ end
23
+ end
24
+ end
25
+
26
+ def call(env)
27
+ response = nil
28
+ Content.with_identity_map do
29
+ Spontaneous::Permissions.with_user(user(env)) do
30
+ S::Render.with_preview_renderer do
31
+ Change.record do
32
+ response = @app.call(env)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ response
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+ end
44
+