spontaneous 0.1.0.alpha1 → 0.2.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 (413) hide show
  1. data/Gemfile +40 -35
  2. data/LICENSE +20 -0
  3. data/Rakefile +39 -42
  4. data/Readme.markdown +155 -0
  5. data/application/css/definitions.scss +3 -0
  6. data/application/css/editing.scss +9 -4
  7. data/application/css/min/565d4c25e82148acb01c45c8d675b37a08676d77.css +1 -0
  8. data/application/css/min/84dbe894ea96eafd321c30823d630817bfc4b03b.css +1 -0
  9. data/application/css/min/d1b54ff4847c613618267ca1c15658e2aee0a4e5.css +1 -0
  10. data/application/css/v2.scss +144 -50
  11. data/application/js/add_alias_dialogue.js +18 -8
  12. data/application/js/ajax.js +1 -1
  13. data/application/js/authentication.js +8 -1
  14. data/application/js/box.js +37 -7
  15. data/application/js/box_container.js +1 -1
  16. data/application/js/compatibility.js +7 -0
  17. data/application/js/content.js +7 -0
  18. data/application/js/content_area.js +4 -0
  19. data/application/js/edit_panel.js +44 -18
  20. data/application/js/editing.js +12 -0
  21. data/application/js/event_source.js +17 -0
  22. data/application/js/extensions.js +2 -0
  23. data/application/js/field_types/file_field.js +2 -1
  24. data/application/js/field_types/image_field.js +35 -48
  25. data/application/js/field_types/long_string_field.js +12 -0
  26. data/application/js/field_types/markdown_field.js +2 -5
  27. data/application/js/field_types/string_field.js +5 -1
  28. data/application/js/field_types/webvideo_field.js +15 -0
  29. data/application/js/init.js +1 -0
  30. data/application/js/location.js +30 -19
  31. data/application/js/login.js +1 -2
  32. data/application/js/min/2a0c2962537a3181fedfff5c92596ba6d3122dc9.js +3 -0
  33. data/application/js/min/4cf1c493d3379ecba5287758c61238034c0893f9.js +2 -0
  34. data/application/js/min/78ac6b99d96750bb6b9f9aad4cb9cd91cd03f391.js +3 -0
  35. data/application/js/min/c8efb9b9f7c3f6613fcebc6be60f605b6570a382.js +90 -0
  36. data/application/js/page.js +1 -0
  37. data/application/js/page_entry.js +6 -40
  38. data/application/js/preview.js +2 -3
  39. data/application/js/top_bar.js +76 -31
  40. data/application/js/upload.js +5 -2
  41. data/application/js/upload_manager.js +2 -81
  42. data/application/js/vendor/jquery-1.7.1.min.js +4 -0
  43. data/application/js/vendor/jquery-ui-1.8.16.custom.min.js +791 -0
  44. data/application/js/views.js +3 -3
  45. data/application/js/views/box_view.js +164 -83
  46. data/application/js/views/page_piece_view.js +2 -2
  47. data/application/js/views/page_view.js +46 -15
  48. data/application/js/views/piece_view.js +29 -8
  49. data/application/static/diagonal-texture.png +0 -0
  50. data/application/static/item-buttons-highlight.png +0 -0
  51. data/application/static/plus-box.png +0 -0
  52. data/application/static/plus_alt.svg +8 -0
  53. data/application/static/slot-up-arrow.png +0 -0
  54. data/application/views/{index.erubis → index.erb} +9 -5
  55. data/application/views/{login.erubis → login.erb} +14 -10
  56. data/application/views/schema_modification_error.html.erb +18 -6
  57. data/application/views/{unsupported.erubis → unsupported.erb} +0 -0
  58. data/bin/spot +15 -2
  59. data/db/migrations/20100610142136_init.rb +2 -2
  60. data/db/migrations/20101130104334_timestamps.rb +2 -2
  61. data/db/migrations/20110209152710_users_and_groups.rb +11 -11
  62. data/db/migrations/20120106171423_visibility_path.rb +19 -0
  63. data/db/migrations/20120107124541_owner_id.rb +19 -0
  64. data/docs/recipe-interface-screenshot.png +0 -0
  65. data/lib/cutaneous.rb +11 -10
  66. data/lib/cutaneous/context_helper.rb +119 -14
  67. data/lib/cutaneous/preview_context.rb +4 -3
  68. data/lib/cutaneous/preview_renderer.rb +1 -6
  69. data/lib/cutaneous/publish_context.rb +1 -0
  70. data/lib/cutaneous/{first_pass_renderer.rb → publish_renderer.rb} +2 -6
  71. data/lib/cutaneous/publish_template.rb +62 -0
  72. data/lib/cutaneous/publish_token_parser.rb +8 -0
  73. data/lib/cutaneous/renderer.rb +4 -2
  74. data/lib/cutaneous/request_context.rb +1 -0
  75. data/lib/cutaneous/{second_pass_renderer.rb → request_renderer.rb} +2 -5
  76. data/lib/cutaneous/request_template.rb +11 -0
  77. data/lib/cutaneous/request_token_parser.rb +9 -0
  78. data/lib/cutaneous/token_parser.rb +125 -0
  79. data/lib/sequel/plugins/content_table_inheritance.rb +19 -12
  80. data/lib/sequel/plugins/scoped_table_name.rb +45 -0
  81. data/lib/spontaneous.rb +123 -126
  82. data/lib/spontaneous/box.rb +127 -47
  83. data/lib/spontaneous/box_style.rb +39 -22
  84. data/lib/spontaneous/change.rb +2 -2
  85. data/lib/spontaneous/cli.rb +1 -0
  86. data/lib/spontaneous/cli/base.rb +12 -4
  87. data/lib/spontaneous/cli/console.rb +72 -0
  88. data/lib/spontaneous/cli/server.rb +36 -12
  89. data/lib/spontaneous/cli/site.rb +175 -1
  90. data/lib/spontaneous/collections/box_set.rb +19 -1
  91. data/lib/spontaneous/collections/entry_set.rb +70 -22
  92. data/lib/spontaneous/collections/field_set.rb +3 -3
  93. data/lib/spontaneous/collections/prototype_set.rb +28 -0
  94. data/lib/spontaneous/config.rb +14 -5
  95. data/lib/spontaneous/content.rb +23 -24
  96. data/lib/spontaneous/errors.rb +20 -4
  97. data/lib/spontaneous/extensions/array.rb +2 -2
  98. data/lib/spontaneous/extensions/json.rb +1 -1
  99. data/lib/spontaneous/extensions/nil.rb +13 -0
  100. data/lib/spontaneous/facet.rb +61 -7
  101. data/lib/spontaneous/field_types.rb +1 -3
  102. data/lib/spontaneous/field_types/date_field.rb +1 -0
  103. data/lib/spontaneous/field_types/field.rb +32 -15
  104. data/lib/spontaneous/field_types/image_field.rb +138 -69
  105. data/lib/spontaneous/field_types/location_field.rb +59 -0
  106. data/lib/spontaneous/field_types/long_string_field.rb +13 -0
  107. data/lib/spontaneous/field_types/markdown_field.rb +2 -1
  108. data/lib/spontaneous/field_types/string_field.rb +2 -2
  109. data/lib/spontaneous/field_types/webvideo_field.rb +255 -0
  110. data/lib/spontaneous/generators/page/inline.html.cut +1 -1
  111. data/lib/spontaneous/generators/page/page.html.cut.tt +5 -4
  112. data/lib/spontaneous/generators/page/page.rb.tt +1 -5
  113. data/lib/spontaneous/generators/site.rb +1 -0
  114. data/lib/spontaneous/generators/site/.gitignore +2 -0
  115. data/lib/spontaneous/generators/site/Gemfile.tt +3 -5
  116. data/lib/spontaneous/generators/site/config/environment.rb.tt +1 -0
  117. data/lib/spontaneous/generators/site/config/environments/development.rb.tt +3 -1
  118. data/lib/spontaneous/generators/site/config/environments/production.rb.tt +3 -1
  119. data/lib/spontaneous/generators/site/config/indexes.rb.tt +23 -0
  120. data/lib/spontaneous/generators/site/public/css/{site.css → site.scss} +0 -0
  121. data/lib/spontaneous/generators/site/schema/box.rb.tt +5 -0
  122. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +11 -5
  123. data/lib/spontaneous/image_size.rb +0 -1
  124. data/lib/spontaneous/loader.rb +335 -218
  125. data/lib/spontaneous/logger.rb +7 -2
  126. data/lib/spontaneous/media.rb +64 -59
  127. data/lib/spontaneous/media/file.rb +74 -0
  128. data/lib/spontaneous/page.rb +47 -18
  129. data/lib/spontaneous/page_piece.rb +29 -27
  130. data/lib/spontaneous/paths.rb +0 -1
  131. data/lib/spontaneous/permissions.rb +3 -21
  132. data/lib/spontaneous/permissions/user.rb +5 -1
  133. data/lib/spontaneous/permissions/user_level.rb +6 -7
  134. data/lib/spontaneous/piece.rb +12 -7
  135. data/lib/spontaneous/plugins/aliases.rb +76 -31
  136. data/lib/spontaneous/plugins/allowed_types.rb +36 -37
  137. data/lib/spontaneous/plugins/application/facets.rb +7 -10
  138. data/lib/spontaneous/plugins/application/features.rb +17 -0
  139. data/lib/spontaneous/plugins/application/paths.rb +25 -31
  140. data/lib/spontaneous/plugins/application/render.rb +1 -5
  141. data/lib/spontaneous/plugins/application/serialisation.rb +2 -0
  142. data/lib/spontaneous/plugins/application/state.rb +6 -9
  143. data/lib/spontaneous/plugins/boxes.rb +65 -40
  144. data/lib/spontaneous/plugins/controllers.rb +22 -22
  145. data/lib/spontaneous/plugins/entries.rb +149 -150
  146. data/lib/spontaneous/plugins/entry.rb +50 -35
  147. data/lib/spontaneous/plugins/field/editor_class.rb +13 -0
  148. data/lib/spontaneous/plugins/fields.rb +41 -33
  149. data/lib/spontaneous/plugins/instance_code.rb +9 -9
  150. data/lib/spontaneous/plugins/layouts.rb +31 -35
  151. data/lib/spontaneous/plugins/media.rb +31 -32
  152. data/lib/spontaneous/plugins/page/formats.rb +56 -31
  153. data/lib/spontaneous/plugins/page/request.rb +15 -9
  154. data/lib/spontaneous/plugins/page_search.rb +30 -31
  155. data/lib/spontaneous/plugins/page_tree.rb +59 -12
  156. data/lib/spontaneous/plugins/paths.rb +84 -79
  157. data/lib/spontaneous/plugins/permissions.rb +26 -28
  158. data/lib/spontaneous/plugins/prototypes.rb +42 -37
  159. data/lib/spontaneous/plugins/publishing.rb +50 -94
  160. data/lib/spontaneous/plugins/render.rb +8 -16
  161. data/lib/spontaneous/plugins/schema_hierarchy.rb +20 -21
  162. data/lib/spontaneous/plugins/schema_id.rb +33 -25
  163. data/lib/spontaneous/plugins/schema_title.rb +3 -4
  164. data/lib/spontaneous/plugins/serialisation.rb +32 -35
  165. data/lib/spontaneous/plugins/site/features.rb +32 -0
  166. data/lib/spontaneous/plugins/site/instance.rb +3 -2
  167. data/lib/spontaneous/plugins/site/level.rb +18 -0
  168. data/lib/spontaneous/plugins/site/map.rb +2 -1
  169. data/lib/spontaneous/plugins/site/publishing.rb +56 -59
  170. data/lib/spontaneous/plugins/site/revisions.rb +24 -19
  171. data/lib/spontaneous/plugins/site/schema.rb +33 -0
  172. data/lib/spontaneous/plugins/site/search.rb +43 -0
  173. data/lib/spontaneous/plugins/site/selectors.rb +35 -30
  174. data/lib/spontaneous/plugins/site/storage.rb +63 -0
  175. data/lib/spontaneous/plugins/site_map.rb +23 -25
  176. data/lib/spontaneous/plugins/styles.rb +35 -43
  177. data/lib/spontaneous/plugins/supertype.rb +3 -1
  178. data/lib/spontaneous/plugins/visibility.rb +90 -83
  179. data/lib/spontaneous/prototypes/box_prototype.rb +55 -25
  180. data/lib/spontaneous/prototypes/field_prototype.rb +66 -19
  181. data/lib/spontaneous/prototypes/style_prototype.rb +2 -2
  182. data/lib/spontaneous/publishing.rb +1 -1
  183. data/lib/spontaneous/publishing/immediate.rb +128 -49
  184. data/lib/spontaneous/publishing/simultaneous.rb +70 -0
  185. data/lib/spontaneous/rack.rb +38 -26
  186. data/lib/spontaneous/rack/around_back.rb +3 -23
  187. data/lib/spontaneous/rack/around_preview.rb +3 -8
  188. data/lib/spontaneous/rack/assets.rb +7 -6
  189. data/lib/spontaneous/rack/authentication.rb +21 -0
  190. data/lib/spontaneous/rack/back.rb +310 -331
  191. data/lib/spontaneous/rack/cacheable_file.rb +27 -0
  192. data/lib/spontaneous/rack/cookie_authentication.rb +38 -0
  193. data/lib/spontaneous/rack/css.rb +43 -0
  194. data/lib/spontaneous/rack/event_source.rb +31 -0
  195. data/lib/spontaneous/rack/front.rb +30 -8
  196. data/lib/spontaneous/rack/helpers.rb +31 -0
  197. data/lib/spontaneous/rack/media.rb +22 -21
  198. data/lib/spontaneous/rack/public.rb +2 -1
  199. data/lib/spontaneous/rack/query_authentication.rb +35 -0
  200. data/lib/spontaneous/rack/reloader.rb +6 -3
  201. data/lib/spontaneous/rack/user_helpers.rb +28 -0
  202. data/lib/spontaneous/render.rb +64 -23
  203. data/lib/spontaneous/render/context_base.rb +143 -0
  204. data/lib/spontaneous/render/format.rb +24 -19
  205. data/lib/spontaneous/render/helpers.rb +14 -0
  206. data/lib/spontaneous/render/helpers/html_helper.rb +69 -0
  207. data/lib/spontaneous/render/helpers/script_helper.rb +17 -0
  208. data/lib/spontaneous/render/helpers/stylesheet_helper.rb +16 -0
  209. data/lib/spontaneous/render/preview_context.rb +8 -0
  210. data/lib/spontaneous/render/preview_renderer.rb +6 -0
  211. data/lib/spontaneous/render/publish_context.rb +22 -0
  212. data/lib/spontaneous/render/published_renderer.rb +12 -13
  213. data/lib/spontaneous/render/publishing_renderer.rb +3 -0
  214. data/lib/spontaneous/render/render_cache.rb +26 -0
  215. data/lib/spontaneous/render/renderer.rb +5 -1
  216. data/lib/spontaneous/render/request_context.rb +8 -0
  217. data/lib/spontaneous/schema.rb +56 -24
  218. data/lib/spontaneous/schema/schema_modification.rb +2 -2
  219. data/lib/spontaneous/schema/uid.rb +22 -106
  220. data/lib/spontaneous/schema/uid_map.rb +120 -0
  221. data/lib/spontaneous/search.rb +11 -0
  222. data/lib/spontaneous/search/compound_indexer.rb +26 -0
  223. data/lib/spontaneous/search/database.rb +72 -0
  224. data/lib/spontaneous/search/field.rb +95 -0
  225. data/lib/spontaneous/search/index.rb +184 -0
  226. data/lib/spontaneous/search/results.rb +34 -0
  227. data/lib/spontaneous/server.rb +5 -1
  228. data/lib/spontaneous/site.rb +56 -16
  229. data/lib/spontaneous/storage.rb +22 -0
  230. data/lib/spontaneous/storage/backend.rb +10 -0
  231. data/lib/spontaneous/storage/cloud.rb +104 -0
  232. data/lib/spontaneous/storage/local.rb +52 -0
  233. data/lib/spontaneous/style.rb +27 -9
  234. data/lib/spontaneous/version.rb +1 -1
  235. data/spontaneous.gemspec +719 -0
  236. data/test/disabled/test_slots.rb +1 -1
  237. data/test/experimental/test_cutaneous.rb +309 -0
  238. data/test/experimental/test_features.rb +129 -0
  239. data/test/fixtures/application/views/{index.erubis → index.erb} +0 -0
  240. data/test/fixtures/back/public/css/sass_include.scss +5 -0
  241. data/test/fixtures/back/public/css/sass_template.scss +4 -0
  242. data/test/fixtures/example_application/templates/client_project.html.cut +4 -4
  243. data/test/fixtures/example_application/templates/client_project/images.html.cut +1 -1
  244. data/test/fixtures/example_application/templates/client_projects.html.cut +2 -2
  245. data/test/fixtures/example_application/templates/inline_image.html.cut +1 -1
  246. data/test/fixtures/example_application/templates/layouts/home.html.cut +7 -7
  247. data/test/fixtures/example_application/templates/layouts/info.html.cut +1 -1
  248. data/test/fixtures/example_application/templates/layouts/project.html.cut +4 -4
  249. data/test/fixtures/example_application/templates/layouts/projects.html.cut +2 -2
  250. data/test/fixtures/example_application/templates/project.html.cut +2 -2
  251. data/test/fixtures/example_application/templates/project/inline.html.cut +3 -3
  252. data/test/fixtures/example_application/templates/project_image.html.cut +1 -1
  253. data/test/fixtures/example_application/templates/text.html.cut +1 -1
  254. data/test/fixtures/fields/youtube_api_response.xml +102 -0
  255. data/test/fixtures/layouts/layouts/custom4.html.cut +0 -0
  256. data/test/fixtures/plugins/schema_plugin/public/css/plugin.css +1 -0
  257. data/test/fixtures/plugins/schema_plugin/public/js/plugin.js +1 -0
  258. data/test/fixtures/plugins/schema_plugin/public/static.html +1 -0
  259. data/test/fixtures/plugins/schema_plugin/public/subdir/image.gif +1 -0
  260. data/test/fixtures/plugins/schema_plugin/public/subdir/include1.scss +3 -0
  261. data/test/fixtures/plugins/schema_plugin/public/subdir/sass.scss +4 -0
  262. data/test/fixtures/plugins/schema_plugin/public/subdir/sass/include2.scss +4 -0
  263. data/test/fixtures/public/templates/layouts/default.html.cut +1 -1
  264. data/test/fixtures/public/templates/layouts/default.pdf.cut +1 -1
  265. data/test/fixtures/public/templates/layouts/default.rss.cut +1 -1
  266. data/test/fixtures/public/templates/layouts/dynamic.html.cut +1 -1
  267. data/test/fixtures/schema_modification/config/database.yml +0 -0
  268. data/test/fixtures/schema_modification/config/environment.rb +2 -0
  269. data/test/fixtures/schema_modification/schema/box.rb +1 -0
  270. data/test/fixtures/schema_modification/schema/custom_box.rb +1 -0
  271. data/test/fixtures/schema_modification/schema/page.rb +6 -0
  272. data/test/fixtures/schema_modification/schema/piece.rb +1 -0
  273. data/test/fixtures/search/config/database.yml +1 -0
  274. data/test/fixtures/search/config/indexes.rb +4 -0
  275. data/test/fixtures/serialisation/root_hash.yaml.erb +16 -20
  276. data/test/fixtures/storage/cloud/environment.rb +12 -0
  277. data/test/fixtures/storage/default/environment.rb +1 -0
  278. data/test/fixtures/templates/aliases/layouts/c_alias.html.cut +1 -1
  279. data/test/fixtures/templates/content/include.html.cut +1 -1
  280. data/test/fixtures/templates/content/include_dir.html.cut +1 -1
  281. data/test/fixtures/templates/content/included.epub.cut +1 -1
  282. data/test/fixtures/templates/content/included.html.cut +1 -1
  283. data/test/fixtures/templates/content/partial/included.html.cut +1 -1
  284. data/test/fixtures/templates/content/preprocess.html.cut +1 -1
  285. data/test/fixtures/templates/content/second.html.cut +1 -1
  286. data/test/fixtures/templates/content/template.epub.cut +1 -1
  287. data/test/fixtures/templates/content/template.html.cut +1 -1
  288. data/test/fixtures/templates/default_style_class.html.cut +1 -1
  289. data/test/fixtures/templates/engine/braces.html.cut +6 -0
  290. data/test/fixtures/templates/engine/multiline.html.cut +5 -0
  291. data/test/fixtures/templates/extended/grandparent.html.cut +7 -7
  292. data/test/fixtures/templates/extended/main.html.cut +5 -5
  293. data/test/fixtures/templates/extended/parent.html.cut +10 -8
  294. data/test/fixtures/templates/extended/partial.html.cut +1 -0
  295. data/test/fixtures/templates/extended/partial_with_locals.html.cut +1 -0
  296. data/test/fixtures/templates/extended/with_includes.html.cut +9 -0
  297. data/test/fixtures/templates/extended/with_includes_and_locals.html.cut +9 -0
  298. data/test/fixtures/templates/layouts/entries.html.cut +7 -7
  299. data/test/fixtures/templates/layouts/page_style.html.cut +1 -1
  300. data/test/fixtures/templates/layouts/params.html.cut +1 -1
  301. data/test/fixtures/templates/layouts/preview_render.html.cut +2 -2
  302. data/test/fixtures/templates/layouts/standard_page.html.cut +1 -1
  303. data/test/fixtures/templates/layouts/subdir_style.html.cut +1 -1
  304. data/test/fixtures/templates/layouts/template_params.html.cut +1 -1
  305. data/test/fixtures/templates/layouts/variables.html.cut +7 -0
  306. data/test/fixtures/templates/page_class/inline_style.html.cut +1 -1
  307. data/test/fixtures/templates/preview_render/variables.html.cut +1 -0
  308. data/test/fixtures/templates/publishing/templates/layouts/dynamic.html.cut +1 -0
  309. data/test/fixtures/templates/publishing/templates/layouts/dynamic.rtf.cut +1 -0
  310. data/test/fixtures/templates/publishing/templates/layouts/static.html.cut +1 -0
  311. data/test/fixtures/templates/template_class/anonymous_style.html.cut +2 -2
  312. data/test/fixtures/templates/template_class/complex_template.html.cut +4 -4
  313. data/test/fixtures/templates/template_class/complex_template.pdf.cut +4 -4
  314. data/test/fixtures/templates/template_class/default_template_style.html.cut +2 -2
  315. data/test/fixtures/templates/template_class/images_with_template.html.cut +3 -3
  316. data/test/fixtures/templates/template_class/slots_template.html.cut +3 -3
  317. data/test/fixtures/templates/template_class/slots_template.pdf.cut +3 -3
  318. data/test/fixtures/templates/template_class/this_template.epub.cut +1 -1
  319. data/test/fixtures/templates/template_class/this_template.html.cut +1 -1
  320. data/test/fixtures/templates/template_class/this_template.pdf.cut +1 -1
  321. data/test/fixtures/templates/with_default_style_class.html.cut +1 -1
  322. data/test/functional/test_application.rb +19 -15
  323. data/test/functional/test_back.rb +130 -98
  324. data/test/functional/test_front.rb +72 -28
  325. data/test/javascript/test_dom.rb +1 -1
  326. data/test/javascript/test_markdown.rb +1 -1
  327. data/test/slow/test_publishing.rb +94 -75
  328. data/test/slow/test_visibility.rb +47 -14
  329. data/test/test_helper.rb +30 -3
  330. data/test/ui/test_page_editing.rb +1 -1
  331. data/test/unit/test_alias.rb +200 -16
  332. data/test/unit/test_authentication.rb +26 -28
  333. data/test/unit/test_boxes.rb +146 -75
  334. data/test/unit/test_config.rb +42 -20
  335. data/test/unit/test_content.rb +156 -37
  336. data/test/unit/test_content_inheritance.rb +4 -2
  337. data/test/unit/test_extensions.rb +7 -1
  338. data/test/unit/test_fields.rb +558 -290
  339. data/test/{experimental → unit}/test_formats.rb +42 -3
  340. data/test/unit/test_generators.rb +3 -2
  341. data/test/unit/test_helpers.rb +54 -0
  342. data/test/unit/test_image_size.rb +1 -1
  343. data/test/unit/test_images.rb +51 -40
  344. data/test/unit/test_layouts.rb +21 -4
  345. data/test/unit/test_logger.rb +1 -1
  346. data/test/unit/test_media.rb +165 -7
  347. data/test/unit/test_page.rb +158 -27
  348. data/test/unit/test_permissions.rb +170 -187
  349. data/test/unit/test_piece.rb +27 -9
  350. data/test/unit/test_plugins.rb +153 -0
  351. data/test/unit/test_prototype_set.rb +60 -2
  352. data/test/unit/test_prototypes.rb +81 -20
  353. data/test/unit/test_render.rb +97 -9
  354. data/test/unit/test_schema.rb +167 -120
  355. data/test/unit/test_search.rb +588 -0
  356. data/test/unit/test_serialisation.rb +26 -10
  357. data/test/unit/test_site.rb +42 -25
  358. data/test/unit/test_storage.rb +88 -0
  359. data/test/unit/test_structure.rb +11 -5
  360. data/test/unit/test_styles.rb +64 -3
  361. data/test/unit/test_table_scoping.rb +76 -0
  362. data/test/unit/test_templates.rb +69 -31
  363. data/test/unit/test_type_hierarchy.rb +9 -1
  364. metadata +274 -208
  365. data/Gemfile.lock +0 -146
  366. data/application/css/min/54ee0ed3c7fac7632bd5c020d69e9a2503e0c88c.css +0 -1
  367. data/application/css/min/c256adc144e2bdd0b0539356b04eb62db01e1dc3.css +0 -1
  368. data/application/js/edit_dialogue.js +0 -137
  369. data/application/js/min/492a209de8ee955fa9c729a765377495001e11b1.js +0 -17
  370. data/application/js/min/80f684d77c940887a1d4a63e3a96102e993baa98.js +0 -88
  371. data/application/js/min/c7140ec9475e5bf868b901e0621338d7d162358b.js +0 -3
  372. data/application/js/min/f07f2bd6630ee31e1c2288ec223383d8f0658ba6.js +0 -2
  373. data/application/js/vendor/.DS_Store +0 -0
  374. data/application/js/vendor/JS.Class-2.1.5/src/command.js +0 -93
  375. data/application/js/vendor/JS.Class-2.1.5/src/comparable.js +0 -37
  376. data/application/js/vendor/JS.Class-2.1.5/src/constant_scope.js +0 -48
  377. data/application/js/vendor/JS.Class-2.1.5/src/core.js +0 -1060
  378. data/application/js/vendor/JS.Class-2.1.5/src/decorator.js +0 -50
  379. data/application/js/vendor/JS.Class-2.1.5/src/enumerable.js +0 -505
  380. data/application/js/vendor/JS.Class-2.1.5/src/forwardable.js +0 -22
  381. data/application/js/vendor/JS.Class-2.1.5/src/hash.js +0 -334
  382. data/application/js/vendor/JS.Class-2.1.5/src/linked_list.js +0 -114
  383. data/application/js/vendor/JS.Class-2.1.5/src/loader.js +0 -553
  384. data/application/js/vendor/JS.Class-2.1.5/src/method_chain.js +0 -172
  385. data/application/js/vendor/JS.Class-2.1.5/src/observable.js +0 -55
  386. data/application/js/vendor/JS.Class-2.1.5/src/package.js +0 -472
  387. data/application/js/vendor/JS.Class-2.1.5/src/proxy.js +0 -58
  388. data/application/js/vendor/JS.Class-2.1.5/src/ruby.js +0 -44
  389. data/application/js/vendor/JS.Class-2.1.5/src/set.js +0 -332
  390. data/application/js/vendor/JS.Class-2.1.5/src/stack_trace.js +0 -151
  391. data/application/js/vendor/JS.Class-2.1.5/src/state.js +0 -95
  392. data/application/js/vendor/JS.Class-2.1.5/src/stdlib.js +0 -2612
  393. data/application/js/vendor/jquery-1.4.2.min.js +0 -154
  394. data/application/js/vendor/jquery-1.4.3.min.js +0 -166
  395. data/application/js/vendor/jquery-1.5.1.min.js +0 -16
  396. data/application/js/vendor/jquery-1.5.1rc1.min.js +0 -24
  397. data/application/js/vendor/jquery-ui-1.8.6.custom.min.js +0 -265
  398. data/application/js/vendor/jquery-ui-1.8.custom.min.js +0 -106
  399. data/application/js/vendor/jquery.hotkeys-0.7.9.js +0 -248
  400. data/application/js/vendor/jquery.hotkeys-0.7.9.min.js +0 -19
  401. data/application/js/vendor/jsdiff.js +0 -169
  402. data/lib/cutaneous/first_pass_parser.rb +0 -23
  403. data/lib/cutaneous/parser_core.rb +0 -18
  404. data/lib/cutaneous/second_pass_parser.rb +0 -23
  405. data/lib/sequel/plugins/yajl_serialization.rb +0 -154
  406. data/lib/spontaneous/plugins.rb +0 -20
  407. data/lib/spontaneous/proxy_object.rb +0 -12
  408. data/lib/spontaneous/publishing/fire_and_forget.rb +0 -57
  409. data/lib/spontaneous/render/context.rb +0 -100
  410. data/spontaneous.gemspec.tmpl +0 -66
  411. data/test/experimental/test_plugins.rb +0 -64
  412. data/test/fixtures/templates/publishing/layouts/dynamic.html.cut +0 -1
  413. data/test/fixtures/templates/publishing/layouts/static.html.cut +0 -1
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous::Extensions
4
+ module NilClass
5
+ def /(alternative)
6
+ alternative
7
+ end
8
+ end # String
9
+ end # Extensions
10
+
11
+ class NilClass
12
+ include Spontaneous::Extensions::NilClass
13
+ end
@@ -2,18 +2,36 @@
2
2
 
3
3
  module Spontaneous
4
4
  class Facet
5
+
5
6
  def initialize(root)
6
- @root = root
7
+ @root = File.expand_path(root)
7
8
  paths.add :lib, ["lib", "**/*.rb"]
8
9
  paths.add :schema, ["schema", "**/*.rb"]
9
10
  paths.add :templates, "templates"
10
11
  paths.add :config, "config"
12
+ paths.add :public, "public"
11
13
  paths.add :tasks, ["lib/tasks", "**/*.rake"]
12
14
  paths.add :migrations, ["db/migrations", "**/*.rake"]
13
15
  paths.add :plugins, ["plugins", "*"]
14
16
  paths.add :features, "features"
15
17
  end
16
18
 
19
+
20
+ def root(*path)
21
+ return @root if path.empty?
22
+ File.join(@root, path)
23
+ end
24
+
25
+ def name
26
+ File.basename(root)
27
+ end
28
+
29
+ # used by publishing mechanism to place files into the appropriate subdirectories
30
+ # in the public folder.
31
+ def file_namespace
32
+ name
33
+ end
34
+
17
35
  def paths
18
36
  @paths ||= Spontaneous::Paths.new(@root)
19
37
  end
@@ -28,19 +46,55 @@ module Spontaneous
28
46
  end
29
47
  end
30
48
 
49
+ def load_indexes!
50
+ paths.expanded(:config).each do |config_path|
51
+ index_file = config_path / "indexes.rb"
52
+ Kernel.load(index_file) if File.exists?(index_file)
53
+ end
54
+ end
55
+
31
56
  def init!
32
57
  end
33
58
 
34
59
  def load!
35
- Spontaneous::Loader.load_classes(load_paths)
60
+ load_order.each { |category| load_files(category) }
61
+ end
62
+
63
+ def load_files(category)
64
+ loaders[category].load!
65
+ end
66
+
67
+
68
+ def reload_all!
69
+ load_order.each { |category| loaders[category].reload! }
70
+ end
71
+ alias_method :reload!, :reload_all!
72
+
73
+ def load_order
74
+ [:lib, :schema]
75
+ end
76
+
77
+ def loaders
78
+ @loaders ||= \
79
+ begin
80
+ use_reloader = config.reload_classes
81
+ {
82
+ :schema => Spontaneous::SchemaLoader.new(schema_load_paths, use_reloader),
83
+ :lib => Spontaneous::Loader.new(load_paths, use_reloader)
84
+ }
85
+ end
36
86
  end
37
87
 
38
88
  def load_paths
39
- load_paths = []
40
- [:lib, :schema].each do |category|
41
- load_paths += paths.expanded(category)
42
- end
43
- load_paths
89
+ load_paths_for_category(:lib)
90
+ end
91
+
92
+ def schema_load_paths
93
+ load_paths_for_category(:schema)
94
+ end
95
+
96
+ def load_paths_for_category(category)
97
+ self.paths.expanded(category)
44
98
  end
45
99
 
46
100
  end # Facet
@@ -1,7 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
-
4
-
5
3
  module Spontaneous
6
4
  module FieldTypes
7
5
 
@@ -35,6 +33,6 @@ module Spontaneous
35
33
  end
36
34
  end
37
35
 
38
- [:string, :image, :date, :markdown].each do |type|
36
+ [:string, :long_string, :image, :date, :markdown, :location, :webvideo].each do |type|
39
37
  require "spontaneous/field_types/#{type}_field"
40
38
  end
@@ -4,6 +4,7 @@
4
4
  module Spontaneous
5
5
  module FieldTypes
6
6
  class DateField < Field
7
+ include Spontaneous::Plugins::Field::EditorClass
7
8
  end
8
9
 
9
10
  DateField.register
@@ -4,9 +4,11 @@
4
4
  module Spontaneous
5
5
  module FieldTypes
6
6
  class Field
7
+ extend Plugins
7
8
 
8
9
  def self.register(*labels)
9
10
  labels = self.labels if labels.empty?
11
+ # logger.debug("Registering #{self} as #{labels.join(", ")}")
10
12
  FieldTypes.register(self, *labels)
11
13
  self
12
14
  end
@@ -15,6 +17,14 @@ module Spontaneous
15
17
  [self.name.demodulize.gsub(/Field$/, '').underscore]
16
18
  end
17
19
 
20
+ def self.inherited(subclass, real_caller = nil)
21
+ if self.respond_to?(:editor_class)
22
+ editor_class = self.editor_class
23
+ subclass.singleton_class.send(:define_method, :editor_class) do
24
+ editor_class
25
+ end
26
+ end
27
+ end
18
28
  # def self.prototype=(prototype)
19
29
  # @prototype = prototype
20
30
  # end
@@ -33,9 +43,12 @@ module Spontaneous
33
43
  end
34
44
  end
35
45
 
46
+
36
47
  attr_accessor :owner, :name, :unprocessed_value, :template_params, :version
37
48
  attr_reader :processed_values
38
49
 
50
+ alias_method :values, :processed_values
51
+
39
52
 
40
53
  def initialize(params={}, from_db=false)
41
54
  @processed_values = {}
@@ -108,7 +121,7 @@ module Spontaneous
108
121
  # override this to return custom values derived from (un)processed_value
109
122
  # alias_method :value, :processed_value
110
123
  def value(format=:html)
111
- processed_values[format] || unprocessed_value
124
+ processed_values[format.to_sym] || unprocessed_value
112
125
  end
113
126
  alias_method :processed_value, :value
114
127
 
@@ -116,6 +129,10 @@ module Spontaneous
116
129
  false
117
130
  end
118
131
 
132
+ def indexable_value
133
+ unprocessed_value
134
+ end
135
+
119
136
  def to_s(format = :html)
120
137
  value(format).to_s
121
138
  end
@@ -186,28 +203,36 @@ module Spontaneous
186
203
  # "spontaneous:previewedit:end:field id:#{owner.id} name:#{self.name}"
187
204
  # end
188
205
 
189
- def export
206
+ def export(user)
190
207
  {
191
208
  :name => name.to_s,
192
209
  :id => schema_id.to_s,
193
210
  :unprocessed_value => unprocessed_value,
194
- :processed_value => value(:html),
195
- :values => processed_values,
211
+ :processed_value => ui_preview_value,
196
212
  :version => version
197
213
  }
198
214
  end
199
215
 
216
+ def ui_preview_value
217
+ value(:html)
218
+ end
219
+
200
220
  def inspect
201
221
  %(#<#{self.class.name}:#{self.object_id} #{self.serialize_db.inspect}>)
202
222
  end
203
223
 
204
224
  def blank?
205
- value.blank?
225
+ unprocessed_value.blank?
206
226
  end
207
227
 
208
- def empty?
209
- value.empty?
228
+ alias_method :empty?, :blank?
229
+
230
+
231
+ def /(field)
232
+ return field if self.blank?
233
+ self
210
234
  end
235
+ alias_method :'|', :/
211
236
 
212
237
  protected
213
238
 
@@ -233,14 +258,6 @@ module Spontaneous
233
258
  @preprocessed = nil
234
259
  end
235
260
 
236
- def method_missing(method_name, *args)
237
- if self.has_attribute?(method_name)
238
- attribute_get(method_name, *args)
239
- else
240
- super
241
- end
242
- end
243
-
244
261
  def set_unprocessed_value(new_value)
245
262
  # initial_value should only be set once so that it can act as a test for field modification
246
263
  @initial_value ||= new_value
@@ -1,5 +1,6 @@
1
1
  # encoding: UTF-8
2
2
 
3
+ require 'tempfile'
3
4
  require 'mini_magick'
4
5
  require 'delegate'
5
6
 
@@ -49,9 +50,15 @@ module Spontaneous
49
50
  def to_s
50
51
  src
51
52
  end
53
+
54
+ def /(value)
55
+ return value if self.blank?
56
+ self
57
+ end
52
58
  end
53
59
 
54
60
  class ImageField < Field
61
+ include Spontaneous::Plugins::Field::EditorClass
55
62
  include ImageFieldUtilities
56
63
 
57
64
  def self.accepts
@@ -66,7 +73,7 @@ module Spontaneous
66
73
  def #{name}
67
74
  sizes[:#{name}]
68
75
  end
69
- IMAGE
76
+ IMAGE
70
77
  end
71
78
  end
72
79
 
@@ -79,7 +86,7 @@ module Spontaneous
79
86
  end
80
87
 
81
88
  def self.size_definitions
82
- @size_definitions ||= {}
89
+ @size_definitions ||= superclass.respond_to?(:size_definitions) ? superclass.size_definitions.dup : {}
83
90
  end
84
91
 
85
92
  def image?
@@ -129,33 +136,49 @@ module Spontaneous
129
136
  sizes[:original].src
130
137
  end
131
138
 
132
- def generate(output, image_path)
133
- return { :src => image_path } unless File.exist?(image_path)
134
- image = ImageProcessor.new(image_path)
135
- result = \
139
+ def generate(output, media_file)
140
+ return { :src => media_file } if media_file.is_a?(String)#File.exist?(image_path)
141
+ image = ImageProcessor.new(media_file)
142
+ # Create a tempfile here that will be kept open for the duration of the block
143
+ # this is used in #apply to hold a copy of the processed image data rather than
144
+ # rely on the minimagick generated tempfiles which can get closed
145
+ result = Tempfile.open("image_#{output}") do |tempfile|
136
146
  case output
137
147
  when :original
138
148
  image
139
149
  else
140
150
  process = self.class.size_definitions[output]
141
- image.apply(process, output)
151
+ image.apply(process, output, tempfile)
142
152
  end
153
+ end
143
154
  result.serialize
144
155
  end
145
156
 
146
157
  def preprocess(image_path)
147
- filename = nil
158
+ filename = mimetype = nil
148
159
  case image_path
149
160
  when Hash
161
+ mimetype = image_path[:type]
150
162
  filename = image_path[:filename]
151
163
  image_path = image_path[:tempfile].path
152
164
  when String
153
165
  # return image_path unless File.exist?(image_path)
166
+ filename = ::File.basename(image_path)
154
167
  end
155
168
  return image_path unless File.exist?(image_path)
156
- media_path = owner.make_media_file(image_path, filename)
157
- set_unprocessed_value(File.expand_path(media_path))
158
- media_path
169
+ # media_path = owner.make_media_file(image_path, filename)
170
+ media_file = Spontaneous::Media::File.new(owner, filename, mimetype)
171
+ media_file.copy(image_path)
172
+ set_unprocessed_value(File.expand_path(media_file.filepath))
173
+ # media_path
174
+ # image_path
175
+ media_file
176
+ end
177
+
178
+ def export(user = nil)
179
+ super(user).merge({
180
+ :processed_value => processed_values
181
+ })
159
182
  end
160
183
  end
161
184
 
@@ -183,78 +206,118 @@ module Spontaneous
183
206
  def inspect
184
207
  %(<#{self.class.name}: src=#{src.inspect} width="#{width}" height="#{height}">)
185
208
  end
209
+
210
+ def blank?
211
+ src.blank?
212
+ end
213
+
214
+ alias_method :empty?, :blank?
186
215
  end
187
216
 
188
217
  class ImageProcessor
189
218
  include ImageFieldUtilities
190
219
 
191
- class ImageDelegator < Delegator
192
- attr_reader :image
220
+ class ImageDelegator < SimpleDelegator
193
221
 
194
222
  def initialize(image)
195
- super
196
- @image = image
223
+ super(image)
197
224
  end
198
225
 
199
- def __getobj__
200
- @image
201
- end
226
+ alias_method :image, :__getobj__
202
227
 
203
- def __setobj__(obj)
204
- @image = obj
228
+ def format(*args, &block)
229
+ image.format(*args, &block)
205
230
  end
206
231
 
207
- def __run__(process)
208
- combine_options do |c|
209
- cb = CommandDelegator.new(c)
210
- cb.__run__(process)
232
+ def fit(width, height)
233
+ image.combine_options do |c|
234
+ c.add_command(:geometry, "#{width}x#{height}>")
211
235
  end
212
236
  end
213
- end
214
237
 
215
- class CommandDelegator < Delegator
216
- def initialize(command_builder)
217
- super
218
- @command_builder = command_builder
238
+ def crop(width, height)
239
+ image.combine_options do |c|
240
+ dimensions = "#{width}x#{height}"
241
+ c.add_command(:geometry, "#{dimensions}^")
242
+ c.add_command(:gravity, "center")
243
+ c.add_command(:crop, "#{dimensions}+0+0!")
244
+ end
219
245
  end
220
246
 
221
- def __getobj__
222
- @command_builder
247
+ def width(width)
248
+ image.combine_options do |c|
249
+ c.add_command(:geometry, "#{width}x>")
250
+ end
223
251
  end
224
252
 
225
- def __setobj__(obj)
226
- @command_builder = obj
253
+ def height(height)
254
+ image.combine_options do |c|
255
+ c.add_command(:geometry, "x#{height}>")
256
+ end
227
257
  end
228
258
 
229
- def __run__(process)
230
- instance_eval(&process)
259
+ def greyscale
260
+ image.combine_options do |c|
261
+ c.add_command(:type, "Grayscale")
262
+ end
231
263
  end
232
264
 
233
- def fit(width, height)
234
- add(:geometry, "#{width}x#{height}>")
265
+ def composite(other_image_path, output_extension = "jpg", &block)
266
+ File.open(other_image_path) do |other_image|
267
+ new_image = image.composite(other_image, output_extension, &block)
268
+ image.path = new_image.path
269
+ end
235
270
  end
236
271
 
237
- def crop(width, height)
238
- dimensions = "#{width}x#{height}"
239
- add(:geometry, "#{dimensions}^")
240
- add(:gravity, "center")
241
- add(:crop, "#{dimensions}+0+0!")
242
- end
272
+ def border_radius(radius, bg_color = nil)
273
+ @image.format('png') if bg_color.nil? or bg_color == 'transparent'
274
+ puts @image.path
275
+ c = MiniMagick::CommandBuilder.new('convert')
276
+ c << @image.path
277
+ c.add_command(:format, "roundrectangle 0,0 %[fx:w-1],%[fx:h-1], 10,10")
278
+ c.add_command(:write, "info:tmp.mvg")
279
+ c << @image.path
280
+
281
+ puts c.command
282
+ # @image.run(c)
283
+ sub = Subexec.run(c.command, :timeout => MiniMagick.timeout)
284
+
285
+ c = MiniMagick::CommandBuilder.new('convert')
286
+
287
+ c << @image.path
288
+ # c.add_command(:write, "info:tmp.mvg")
289
+ c.add_command(:matte)
290
+ c.add_command(:bordercolor, "none")
291
+ c.add_command(:border, "0")
292
+ c.push('\\(')
293
+ c.push("+clone")
294
+ c.add_command(:alpha, 'transparent')
295
+ c.add_command(:background, 'white')
296
+ c.add_command(:fill, 'white')
297
+ c.add_command(:stroke, 'none')
298
+ c.add_command(:strokewidth, '0')
299
+ c.add_command(:draw, "@tmp.mvg")
300
+ c.push('\\)')
301
+ c.add_command(:compose, 'DstIn')
302
+ c.add_command(:composite)
303
+ c << @image.path
304
+ puts c.command
305
+ @image.run(c)
243
306
 
244
- def width(width)
245
- add(:geometry, "#{width}x>")
246
307
  end
247
308
 
248
- def height(height)
249
- add(:geometry, "x#{height}>")
250
- end
251
309
 
252
- def greyscale
253
- add(:type, "Grayscale")
310
+ def __run__(process)
311
+ instance_eval(&process)
254
312
  end
255
313
 
256
314
  def method_missing(method, *args, &block)
257
- __getobj__.send(method, *args, &block)
315
+ params = args.map(&:to_s)
316
+ if image.respond_to?(method)
317
+ image.__send__(method, *params, &block)
318
+ else
319
+ image.method_missing(method, *params, &block)
320
+ end
258
321
  end
259
322
  end
260
323
 
@@ -262,17 +325,13 @@ module Spontaneous
262
325
 
263
326
  attr_reader :path
264
327
 
265
- def initialize(path)
266
- @path = File.expand_path(path)
328
+ def initialize(media_file)
329
+ @media_file = media_file
330
+ @path = media_file.source
267
331
  end
268
332
 
269
333
  def src
270
- @src ||= \
271
- begin
272
- media_dir = Spontaneous.media_dir
273
- src = path.sub(%r{^#{media_dir}}, '')
274
- File.join("/#{File.basename(media_dir)}", src)
275
- end
334
+ @media_file.url
276
335
  end
277
336
 
278
337
  def filesize
@@ -291,24 +350,31 @@ module Spontaneous
291
350
  @dimensions ||= Spontaneous::ImageSize.read(path)
292
351
  end
293
352
 
294
- def apply(process, name)
353
+ def apply(process, name, tempfile)
295
354
  image = ::MiniMagick::Image.open(path)
296
355
  processor = ImageProcessor::ImageDelegator.new(image)
297
356
  processor.__run__(process)
298
- file_path = filename_for_size(name)
299
- image.write(file_path)
357
+ file = @media_file.rename(filename_for_size(name, image))
358
+ # copy the image into the tempfile provided by the parent #generate call
359
+ # this stops us from using a tempfile that is out of our control and can
360
+ # be closed before we're done
361
+ FileUtils.cp(image.path, tempfile.path)
362
+ file.copy(tempfile)
300
363
 
301
- ImageProcessor.new(file_path)
364
+ ImageProcessor.new(file)
302
365
  end
303
366
 
304
- def filename_for_size(name)
305
- directory = File.dirname(path)
306
- original_filename = File.basename(path)
367
+ def filename_for_size(name, image)
368
+ original_filename = @media_file.filename
307
369
  parts = original_filename.split('.')
308
- ext = parts[-1]
370
+
371
+ # use the image format for the extension because tempfiles generated by
372
+ # mini_magick don't have extensions
373
+ # I hate the "jpeg" extension though
374
+ ext = image[:format].downcase.gsub(/^jpeg$/, "jpg")
309
375
  base = parts[0..-2].join('.')
310
376
  filename = [base, name, ext].join('.')
311
- File.join(directory, filename)
377
+ filename
312
378
  end
313
379
 
314
380
  def serialize
@@ -320,10 +386,13 @@ module Spontaneous
320
386
  :path => path
321
387
  }
322
388
  end
389
+
390
+ def inspect
391
+ %(#<ImageProcessor:#{self.object_id} @media_file=#{@media_file.inspect}>)
392
+ end
323
393
  end
324
394
 
325
395
  ImageField.register(:image, :photo)
326
396
 
327
397
  end
328
398
  end
329
-