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,221 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ require 'base58'
5
+
6
+ module Spontaneous
7
+ module Schema
8
+ class UID
9
+ @@instance_lock = Mutex.new
10
+ @@uid_lock = Mutex.new
11
+ @@uid_index = 0
12
+ @@instances = {}
13
+
14
+ extend Enumerable
15
+ include Comparable
16
+
17
+ def self.load(id, reference)
18
+ @@instance_lock.synchronize do
19
+ unless instance = @@instances[id]
20
+ instance = self.new(id, reference)
21
+ # check to make sure that the uid is valid first
22
+ # this ensures that UIDs are not created before their owners
23
+ # have uids
24
+ if instance.valid?
25
+ @@instances[id] = instance
26
+ else
27
+ instance = nil
28
+ end
29
+ end
30
+ instance
31
+ end
32
+ end
33
+
34
+ def self.create(reference)
35
+ unless instance = @@instances.values.detect { |i| i.reference == reference }
36
+ instance = self.load(generate(reference), reference)
37
+ end
38
+ instance
39
+ end
40
+
41
+ def existing_references
42
+ @@instances.values.map { |i| i.reference }
43
+ end
44
+
45
+ def self.create_for(obj)
46
+ create(obj.schema_name)
47
+ end
48
+
49
+ def self.destroy(uid)
50
+ @@instance_lock.synchronize do
51
+ @@instances.delete(uid.to_s)
52
+ uid.after_destroy
53
+ end
54
+ end
55
+
56
+ def self.clear!
57
+ @@instances = {}
58
+ end
59
+
60
+ def self.[](id)
61
+ return id if self === id
62
+ return nil if id.blank?
63
+ @@instances[id]
64
+ end
65
+
66
+ def self.get_id(reference)
67
+ self.find { |uid| uid.reference == reference }
68
+ end
69
+
70
+ def self.each
71
+ uids = @@instances.map { |id, instance| instance }
72
+ if block_given?
73
+ uids.each { |instance| yield(instance) }
74
+ else
75
+ uids.each
76
+ end
77
+ end
78
+
79
+ def self.get_inc
80
+ @@uid_lock.synchronize do
81
+ @@uid_index = (@@uid_index + 1) % 0xFFFF
82
+ end
83
+ end
84
+
85
+ def self.generate(ref = nil)
86
+ generate58(ref)
87
+ end
88
+
89
+ def self.generate58(ref)
90
+ # reverse the time so that sequential ids are more obviously different
91
+ oid = Base58.encode((Time.now.to_f * 1000).to_i).reverse
92
+ oid << Base58.encode(get_inc).rjust(3, '0')
93
+ end
94
+
95
+ def self.generate16(ref)
96
+ oid = ''
97
+ # 4 bytes current time
98
+ oid = (Time.now.to_f * 1000).to_i.to_s(16)
99
+ # 2 bytes inc
100
+ oid << get_inc.to_s(16).rjust(4, '0')
101
+ end
102
+
103
+ def self.export
104
+ Hash[ @@instances.map { |id, ref| [id, ref.reference] } ]
105
+ end
106
+
107
+ REFERENCE_SEP = "/".freeze
108
+
109
+ attr_reader :reference, :name, :category
110
+
111
+ def initialize(id, reference)
112
+ @id = id.freeze
113
+ read_reference(reference)
114
+ end
115
+
116
+ def read_reference(reference)
117
+ @reference = reference
118
+ @category, @owner_sid, @name = reference.split(REFERENCE_SEP)
119
+ @category = @category.to_sym
120
+ end
121
+
122
+ class << self
123
+ protected :new
124
+ end
125
+
126
+ def destroy
127
+ self.class.destroy(self)
128
+ end
129
+
130
+ def after_destroy
131
+ case @category
132
+ when :box
133
+ Spontaneous::Content.filter(:box_sid => @id).delete
134
+ end
135
+ end
136
+
137
+ def rewrite!(target)
138
+ target = target.schema_name if target.respond_to?(:schema_name)
139
+ read_reference(target)
140
+ @target = nil
141
+ end
142
+
143
+ def target
144
+ @target ||= find_target
145
+ end
146
+
147
+ def valid?
148
+ case @category
149
+ when :type
150
+ true
151
+ else
152
+ owner_sid
153
+ end
154
+ end
155
+
156
+ def orphaned?
157
+ target.nil?
158
+ end
159
+
160
+ def find_target
161
+ case @category
162
+ when :type
163
+ begin
164
+ @name.constantize
165
+ rescue NameError => e
166
+ nil
167
+ end
168
+ else
169
+ if owner
170
+ prototypes = \
171
+ case @category
172
+ when :box
173
+ owner.box_prototypes
174
+ when :field
175
+ owner.field_prototypes
176
+ when :style
177
+ owner.style_prototypes
178
+ when :layout
179
+ owner.layout_prototypes
180
+ end
181
+ prototypes[name.to_sym]
182
+ else
183
+ nil
184
+ end
185
+ end
186
+ end
187
+
188
+ def owner
189
+ return nil if owner_sid.nil?
190
+ owner_sid.target
191
+ end
192
+
193
+ alias_method :schema_owner, :owner
194
+
195
+ def owner_sid
196
+ self.class[@owner_sid]
197
+ end
198
+
199
+ def ==(obj)
200
+ super or obj == @id
201
+ end
202
+
203
+ def hash
204
+ @id.hash
205
+ end
206
+
207
+ def to_s
208
+ @id
209
+ end
210
+
211
+ def <=>(other)
212
+ self.to_s <=> other.to_s
213
+ end
214
+
215
+ def inspect
216
+ %(#<#{self.class}:"#{@id}" => "#{reference}">)
217
+ end
218
+ end
219
+
220
+ end
221
+ end
@@ -0,0 +1,295 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+
5
+ module Spontaneous
6
+ module Schema
7
+ autoload :UID, 'spontaneous/schema/uid'
8
+ autoload :SchemaModification, 'spontaneous/schema/schema_modification'
9
+ # schema class <=> uid map backed by a file
10
+ class PersistentMap
11
+ attr_reader :map, :inverse_map
12
+
13
+ def initialize(path)
14
+ @path = path
15
+ load_map
16
+ end
17
+
18
+ def schema_id(obj)
19
+ reference_to_id(obj.schema_name)
20
+ end
21
+
22
+ def reference_to_id(reference)
23
+ UID.get_id(reference)
24
+ end
25
+
26
+ def [](id)
27
+ if uid = UID[id]
28
+ uid.target
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ def load_map
35
+ if exists?
36
+ map = YAML.load_file(@path)
37
+ map.each do | uid, reference |
38
+ UID.load(uid, reference)
39
+ end
40
+ end
41
+ end
42
+
43
+ def exists?
44
+ ::File.exists?(@path)
45
+ end
46
+
47
+ # def invert_map
48
+ # @inverse_map = generate_inverse
49
+ # end
50
+
51
+ # def generate_inverse
52
+ # Hash[ UID.map { |uid| [uid.reference, uid]} ]
53
+ # end
54
+
55
+ def orphaned_ids
56
+ UID.select { |uid| uid.orphaned? }
57
+ end
58
+
59
+ def reload!
60
+ # invert_map
61
+ end
62
+ end
63
+
64
+ # schema class <=> uid map with no backing, each run will generate different uids and
65
+ # no schema validation errors will ever be thrown
66
+ # used for tests
67
+ class TransientMap < PersistentMap
68
+
69
+ def initialize(path)
70
+ end
71
+
72
+ def schema_id(obj)
73
+ if id = super
74
+ id
75
+ else
76
+ UID.create(obj.schema_name)
77
+ end
78
+ end
79
+
80
+ def orphaned_ids
81
+ []
82
+ end
83
+
84
+ def exists?
85
+ true
86
+ end
87
+ end
88
+
89
+ class << self
90
+ def schema_loader_class
91
+ @schema_loader_class ||= PersistentMap
92
+ end
93
+
94
+ def schema_loader_class=(klass)
95
+ UID.clear!
96
+ @map = nil
97
+ @schema_loader_class = klass
98
+ end
99
+
100
+ # validate the schema & attempt to fix anything that can be resolved without human
101
+ # interaction (i.e. pure additions)
102
+ def validate!
103
+ begin
104
+ validate_schema
105
+ rescue Spontaneous::SchemaModificationError => e
106
+ changes = e.modification
107
+ # if the map file is missing, then this is a first run and we can just
108
+ # create the thing by populating it with the current schema
109
+ if !map.exists?
110
+ logger.warn("Generating new schema")
111
+ generate_new_schema
112
+ else
113
+ if changes.resolvable?
114
+ logger.warn("Schema changed...")
115
+ while changes and changes.resolvable? do
116
+ logger.warn("Fixing automatically")
117
+ changes.resolve!
118
+ map.reload!
119
+ changes = perform_validation
120
+ end
121
+ write_schema
122
+ reload!
123
+ else
124
+ logger.warn("Unable to resolve schema changes")
125
+ raise e
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ def apply(action)
132
+ apply_fix(action.action, action.source, action.dest)
133
+ end
134
+
135
+ def apply_fix(action, source, dest=nil)
136
+ uid = S::Schema::UID[source]
137
+ case action
138
+ when :delete
139
+ uid.destroy
140
+ when :rename
141
+ uid.rewrite!(dest)
142
+ end
143
+ write_schema
144
+ reload!
145
+ validate!
146
+ end
147
+
148
+ def generate_new_schema
149
+ logger.info("Generating new schema map at #{schema_map_file}")
150
+ self.schema_loader_class = TransientMap
151
+ classes.each do | schema_class |
152
+ generate_schema_for(schema_class)
153
+ end
154
+ write_schema
155
+ self.schema_loader_class = PersistentMap
156
+ end
157
+
158
+ def write_schema
159
+ File.atomic_write(schema_map_file) do |file|
160
+ file.write(UID.export.to_yaml)
161
+ end
162
+ end
163
+
164
+ def generate_schema_for(obj)
165
+ UID.create_for(obj)
166
+ [:boxes, :fields, :styles, :layouts].each do |category|
167
+ if obj.respond_to?(category)
168
+ objects = obj.send(category)
169
+ objects.each do | c |
170
+ generate_schema_for(c)
171
+ end
172
+ end
173
+ end
174
+ end
175
+
176
+ # look for differences between identities found in schema map and
177
+ # those defined in the schema classes and raise an error if any
178
+ # are found
179
+ def validate_schema
180
+ modification = perform_validation
181
+ unless modification.nil?
182
+ raise Spontaneous::SchemaModificationError.new(modification)
183
+ end
184
+ end
185
+
186
+ def perform_validation
187
+ modification = nil
188
+ @missing_from_map = Hash.new { |hash, key| hash[key] = [] }
189
+ @missing_from_schema = []
190
+ validate_classes
191
+
192
+ unless @missing_from_map.empty? and @missing_from_schema.empty?
193
+ modification = SchemaModification.new(@missing_from_map, @missing_from_schema)
194
+ end
195
+ modification
196
+ end
197
+
198
+ def validate_classes
199
+ # will check that each of the classes in the schema has a
200
+ # corresponding id
201
+ self.classes.each do | schema_class |
202
+ schema_class.schema_validate
203
+ end
204
+
205
+ # now check that each of the ids in the map has a
206
+ # corresponding entry in the schema
207
+ find_orphaned_ids
208
+ end
209
+
210
+ def find_orphaned_ids
211
+ map.orphaned_ids.each do |uid|
212
+ @missing_from_schema << uid
213
+ end
214
+ end
215
+
216
+ def missing_id!(category, obj)
217
+ @missing_from_map[category] << obj
218
+ end
219
+
220
+
221
+ def export
222
+ self.content_classes.inject({}) do |hash, klass|
223
+ hash[klass.name] = klass.export
224
+ hash
225
+ end
226
+ end
227
+
228
+ def serialise_http
229
+ Spontaneous.serialise_http(export)
230
+ end
231
+
232
+ # all classes including boxes
233
+ def classes
234
+ @classes ||= []
235
+ end
236
+
237
+ # just subclasses of Content (excluding boxes)
238
+ # only need this for the serialisation (which doesn't include boxes)
239
+ def content_classes
240
+ classes = []
241
+ Content.subclasses.each do |klass|
242
+ classes << klass unless [Spontaneous::Page, Spontaneous::Piece].include?(klass)
243
+ recurse_classes(klass, classes)
244
+ end
245
+ classes.uniq
246
+ end
247
+
248
+ def recurse_classes(root_class, list)
249
+ root_class.subclasses.each do |klass|
250
+ list << klass unless list.include?(klass)
251
+ recurse_classes(klass, list)
252
+ end
253
+ end
254
+
255
+ # should only be used in tests
256
+ def reset!
257
+ Content.schema_reset!
258
+ @classes = []
259
+ reload!
260
+ end
261
+
262
+ def reload!
263
+ @map = nil
264
+ UID.clear!
265
+ end
266
+
267
+ def delete(klass)
268
+ classes.delete(klass)
269
+ end
270
+
271
+ def schema_map_file
272
+ @schema_map_file ||= Spontaneous.root / "config" / "schema.yml"
273
+ end
274
+
275
+ def schema_map_file=(path)
276
+ # force a reloading of the schema map
277
+ @map = nil
278
+ @schema_map_file = path
279
+ end
280
+
281
+ def map
282
+ @map ||= self.schema_loader_class.new(schema_map_file)
283
+ end
284
+
285
+ def schema_id(obj)
286
+ map.schema_id(obj)
287
+ end
288
+
289
+ def [](schema_id)
290
+ map[schema_id]
291
+ end
292
+ end
293
+ end
294
+ end
295
+
@@ -0,0 +1,65 @@
1
+ # encoding: UTF-8
2
+
3
+ # Rack::Handler.register('unicorn', 'Unicorn') if defined?(Unicorn)
4
+
5
+ ## thanks again to the stirling work of the Padrino guys & gals.
6
+ module Spontaneous
7
+
8
+ module Server
9
+
10
+ Handlers = %w[thin mongrel webrick] unless const_defined?(:Handlers)
11
+
12
+
13
+ def self.run!(options={})
14
+ host = options["host"] || Site.config.host || "0.0.0.0"
15
+ port = options["port"] || Site.config.port || 2012
16
+ adapter = options["adapter"] || Site.config.adapter
17
+
18
+ handler = nil
19
+
20
+ if adapter
21
+ begin
22
+ handler = ::Rack::Handler.get(adapter.downcase)
23
+ rescue => e
24
+ puts e
25
+ puts e.backtrace
26
+ raise LoadError, "Rack handler #{adapter} not supported. Please use one of #{Handlers.join(', ')}"
27
+ exit
28
+ end
29
+ else
30
+ handler = detect_handler
31
+ end
32
+ puts "=> Spontaneous:#{Spontaneous.mode.to_s.ljust(5, " ")} running on port #{host}:#{port} (PID #{$$})"
33
+
34
+ handler.run Spontaneous::Rack.application.to_app, :Host => host, :Port => port do |server|
35
+ term = Proc.new do
36
+ server.respond_to?(:stop!) ? server.stop! : server.stop
37
+ puts "=> Spontaneous:#{Spontaneous.mode.to_s.ljust(5, " ")} exiting..."
38
+ end
39
+ trap(:INT, &term)
40
+ trap(:TERM, &term)
41
+ end
42
+ rescue RuntimeError => e
43
+ if e.message =~ /no acceptor/
44
+ puts "=> Unable to run server, port #{port} is already in use"
45
+ else
46
+ raise e
47
+ end
48
+ rescue Errno::EADDRINUSE
49
+ puts "=> Unable to run server, port #{port} is already in use"
50
+ end
51
+
52
+ def self.detect_handler
53
+ Handlers.each do |handler_name|
54
+ begin
55
+ return ::Rack::Handler.get(handler_name.downcase)
56
+ rescue Exception => e
57
+ puts e
58
+ puts e.backtrace
59
+ end
60
+ end
61
+ raise LoadError, "No handlers available: #{Handlers.join(', ')}"
62
+ end
63
+ end # Server
64
+ end # Spontaneous
65
+
@@ -0,0 +1,87 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous
4
+ class Site < Spontaneous::Facet
5
+ extend Plugins
6
+
7
+ plugin Plugins::Site::Instance
8
+ plugin Plugins::Site::Publishing
9
+ plugin Plugins::Site::Revisions
10
+ plugin Plugins::Site::Selectors
11
+ plugin Plugins::Site::Map
12
+
13
+ attr_accessor :database
14
+ attr_reader :environment, :mode
15
+
16
+ def initialize(root, env, mode)
17
+ super(root)
18
+ @environment, @mode = env, mode
19
+ end
20
+
21
+ def initialize!
22
+ load_config!
23
+ connect_to_database!
24
+ find_plugins!
25
+ load_facets!
26
+ init_facets!
27
+ end
28
+
29
+ def init_facets!
30
+ facets.each do |facet|
31
+ facet.init!
32
+ end
33
+ end
34
+
35
+ def load_facets!
36
+ Spontaneous::Loader.load!
37
+ end
38
+
39
+ def load_paths
40
+ load_paths = []
41
+ [:lib, :schema].each do |category|
42
+ facets.each do |facet|
43
+ load_paths += facet.paths.expanded(category)
44
+ end
45
+ end
46
+ load_paths
47
+ end
48
+
49
+ def connect_to_database!
50
+ self.database = Sequel.connect(db_settings)
51
+ self.database.logger = logger if config.log_queries
52
+ end
53
+
54
+ def db_settings
55
+ config_dir = paths.expanded(:config).first
56
+ @db_settings = YAML.load_file(File.join(config_dir, "database.yml"))
57
+ self.config.db = @db_settings[environment]
58
+ end
59
+
60
+ def config
61
+ @config ||= Spontaneous::Config.new(environment, mode)
62
+ end
63
+
64
+ def find_plugins!
65
+ paths.expanded(:plugins).each do |glob|
66
+ Dir[glob].each do |path|
67
+ load_plugin(path)
68
+ end
69
+ end
70
+ end
71
+
72
+ def plugins
73
+ @plugins ||= []
74
+ end
75
+
76
+ def facets
77
+ [self] + plugins
78
+ end
79
+
80
+ def load_plugin(plugin_root)
81
+ plugin = Spontaneous::Application::Plugin.new(plugin_root)
82
+ self.plugins << plugin
83
+ plugin
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+
3
+
4
+ module Spontaneous
5
+ class State < Sequel::Model(:spontaneous_state)
6
+ class << self
7
+ alias_method :sequel_plugin, :plugin
8
+ end
9
+
10
+
11
+ @@instance = nil
12
+
13
+ class << self
14
+
15
+ def instance
16
+ return @@instance if @@instance
17
+ unless instance = self.first
18
+ instance = State.create(:revision => 1, :published_revision => 0)
19
+ end
20
+ instance
21
+ end
22
+
23
+ # def with_cache(&block)
24
+ # yield if @@instance
25
+ # @@instance = self.instance
26
+ # yield
27
+ # ensure
28
+ # @@instance = nil
29
+ # end
30
+
31
+ def working_revision
32
+ instance.revision
33
+ end
34
+
35
+ def revision
36
+ instance.revision
37
+ end
38
+
39
+ def published_revision
40
+ if ENV.key?(Spontaneous::SPOT_REVISION_NUMBER)
41
+ ENV[Spontaneous::SPOT_REVISION_NUMBER]
42
+ else
43
+ instance.published_revision
44
+ end
45
+ end
46
+
47
+ def pending_revision
48
+ instance.pending_revision
49
+ end
50
+
51
+ end
52
+ end
53
+ end