spontaneous 0.2.0.beta1 → 0.2.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (335) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.locat +42 -0
  4. data/.travis/gemfiles/Gemfile.empty +7 -0
  5. data/.travis.yml +18 -0
  6. data/Gemfile +12 -8
  7. data/LICENSE +1 -1
  8. data/Rakefile +15 -157
  9. data/Readme.markdown +1 -1
  10. data/application/css/core.css.scss +22 -146
  11. data/application/css/definitions.css.scss +7 -3
  12. data/application/css/dialogue.css.scss +26 -1
  13. data/application/css/editing.css.scss +70 -28
  14. data/application/css/font.css.scss +1 -1
  15. data/application/css/popover.css.scss +2 -0
  16. data/application/css/top.css.scss +231 -0
  17. data/application/js/add_alias_dialogue.js +1 -1
  18. data/application/js/add_home_dialogue.js +1 -1
  19. data/application/js/ajax.js +61 -31
  20. data/application/js/box.js +4 -4
  21. data/application/js/conflicted_field_dialogue.js +1 -1
  22. data/application/js/content.js +5 -5
  23. data/application/js/dom.js +5 -0
  24. data/application/js/edit_panel.js +1 -0
  25. data/application/js/editing.js +1 -1
  26. data/application/js/extensions.js +8 -0
  27. data/application/js/field/boolean.js +31 -0
  28. data/application/js/field/file.js +32 -4
  29. data/application/js/field/image.js +24 -9
  30. data/application/js/field/markdown.js +87 -59
  31. data/application/js/field/select.js +1 -1
  32. data/application/js/field/webvideo.js +6 -1
  33. data/application/js/init.js +2 -2
  34. data/application/js/jquery-selection-position.js +130 -0
  35. data/application/js/location.js +4 -25
  36. data/application/js/meta_view/user_admin.js +2 -2
  37. data/application/js/metadata.js +2 -2
  38. data/application/js/page_browser.js +1 -1
  39. data/application/js/panel/root_menu.js +0 -1
  40. data/application/js/popover.js +27 -12
  41. data/application/js/popover_view.js +20 -4
  42. data/application/js/preview.js +31 -16
  43. data/application/js/progress.js +22 -21
  44. data/application/js/publish.js +18 -7
  45. data/application/js/sharded_upload.js +9 -6
  46. data/application/js/spontaneous.js +3 -1
  47. data/application/js/top_bar.js +264 -173
  48. data/application/js/upload.js +12 -5
  49. data/application/js/upload_manager.js +4 -3
  50. data/application/js/user.js +1 -2
  51. data/application/js/views/box_view.js +1 -1
  52. data/application/js/views/page_view.js +16 -5
  53. data/application/js/views/piece_view.js +5 -4
  54. data/application/static/font/fontawesome-webfont-1c66a4738b40ef0f6b1abca0ba9a796d.ttf +0 -0
  55. data/application/views/index.erb +6 -14
  56. data/application/views/login.erb +6 -25
  57. data/application/views/schema_modification_error.html.erb +3 -7
  58. data/db/migrations/20130114120000_create_revision_tables.rb +2 -2
  59. data/db/migrations/20130813111009_increase_path_length.rb +14 -0
  60. data/gem-public_cert.pem +20 -0
  61. data/lib/spontaneous/asset/app_compiler.rb +44 -0
  62. data/lib/spontaneous/asset/environment.rb +225 -0
  63. data/lib/spontaneous/asset.rb +2 -67
  64. data/lib/spontaneous/box.rb +0 -1
  65. data/lib/spontaneous/capistrano/deploy.rb +2 -2
  66. data/lib/spontaneous/capistrano/sync.rb +1 -1
  67. data/lib/spontaneous/cli/init.rb +36 -13
  68. data/lib/spontaneous/cli/server.rb +0 -1
  69. data/lib/spontaneous/cli/site.rb +2 -1
  70. data/lib/spontaneous/cli.rb +3 -1
  71. data/lib/spontaneous/collections/entry_set.rb +4 -12
  72. data/lib/spontaneous/collections/hash_with_fallback.rb +20 -0
  73. data/lib/spontaneous/collections/prototype_set.rb +6 -5
  74. data/lib/spontaneous/crypt.rb +2 -2
  75. data/lib/spontaneous/data_mapper/content_model/associations.rb +115 -63
  76. data/lib/spontaneous/data_mapper.rb +1 -1
  77. data/lib/spontaneous/errors.rb +6 -0
  78. data/lib/spontaneous/extensions/object_space.rb +6 -0
  79. data/lib/spontaneous/facet.rb +1 -0
  80. data/lib/spontaneous/field/base.rb +86 -13
  81. data/lib/spontaneous/field/boolean.rb +65 -0
  82. data/lib/spontaneous/field/file.rb +17 -6
  83. data/lib/spontaneous/field/html.rb +13 -0
  84. data/lib/spontaneous/field/image/size.rb +76 -0
  85. data/lib/spontaneous/field/image.rb +99 -414
  86. data/lib/spontaneous/field/tags.rb +36 -0
  87. data/lib/spontaneous/field/update.rb +1 -1
  88. data/lib/spontaneous/field/webvideo/fallback.rb +41 -0
  89. data/lib/spontaneous/field/webvideo/vimeo.rb +113 -0
  90. data/lib/spontaneous/field/webvideo/vine.rb +94 -0
  91. data/lib/spontaneous/field/webvideo/youtube.rb +133 -0
  92. data/lib/spontaneous/field/webvideo.rb +100 -250
  93. data/lib/spontaneous/field.rb +1 -1
  94. data/lib/spontaneous/generators/site/Gemfile.tt +5 -14
  95. data/lib/spontaneous/generators/site/assets/README.md +20 -0
  96. data/lib/spontaneous/generators/site/assets/css/site.scss +8 -0
  97. data/lib/spontaneous/generators/site/assets/js/site.js +6 -0
  98. data/lib/spontaneous/generators/site/config/deploy.rb.tt +9 -0
  99. data/lib/spontaneous/generators/site/config/user_levels.yml +14 -3
  100. data/lib/spontaneous/generators/site/public/README.md +12 -0
  101. data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +2 -2
  102. data/lib/spontaneous/generators/site.rb +77 -35
  103. data/lib/spontaneous/layout.rb +6 -7
  104. data/lib/spontaneous/loader.rb +21 -13
  105. data/lib/spontaneous/media/file.rb +22 -9
  106. data/lib/spontaneous/media/image/attributes.rb +33 -0
  107. data/lib/spontaneous/media/image/format/gif.rb +4 -0
  108. data/lib/spontaneous/media/image/format/jpg.rb +17 -0
  109. data/lib/spontaneous/media/image/format/png.rb +4 -0
  110. data/lib/spontaneous/media/image/format/webp.rb +26 -0
  111. data/lib/spontaneous/media/image/format.rb +79 -0
  112. data/lib/spontaneous/media/image/optimizer.rb +69 -0
  113. data/lib/spontaneous/media/image/processor.rb +17 -0
  114. data/lib/spontaneous/media/image/renderable.rb +52 -0
  115. data/lib/spontaneous/media/image/skeptick.rb +70 -0
  116. data/lib/spontaneous/media/image.rb +50 -0
  117. data/lib/spontaneous/media/temp_file.rb +4 -0
  118. data/lib/spontaneous/media.rb +1 -0
  119. data/lib/spontaneous/model/core/aliases.rb +14 -8
  120. data/lib/spontaneous/model/core/boxes.rb +5 -2
  121. data/lib/spontaneous/model/core/entries.rb +4 -0
  122. data/lib/spontaneous/model/core/entry.rb +1 -0
  123. data/lib/spontaneous/model/core/fields.rb +5 -2
  124. data/lib/spontaneous/model/core/locks.rb +16 -0
  125. data/lib/spontaneous/model/core/media.rb +1 -15
  126. data/lib/spontaneous/model/core.rb +31 -1
  127. data/lib/spontaneous/model/page/controllers.rb +2 -2
  128. data/lib/spontaneous/model/page/formats.rb +1 -4
  129. data/lib/spontaneous/model/page/layouts.rb +6 -2
  130. data/lib/spontaneous/model/page/locks.rb +8 -2
  131. data/lib/spontaneous/model/page/page_tree.rb +2 -2
  132. data/lib/spontaneous/model/page/paths.rb +74 -9
  133. data/lib/spontaneous/model/page.rb +11 -3
  134. data/lib/spontaneous/model.rb +6 -6
  135. data/lib/spontaneous/output/context/render_cache.rb +23 -0
  136. data/lib/spontaneous/output/context.rb +56 -30
  137. data/lib/spontaneous/output/helpers/script_helper.rb +9 -53
  138. data/lib/spontaneous/output/helpers/stylesheet_helper.rb +8 -40
  139. data/lib/spontaneous/output/template/renderer.rb +17 -5
  140. data/lib/spontaneous/output.rb +0 -1
  141. data/lib/spontaneous/paths.rb +6 -2
  142. data/lib/spontaneous/permissions/access_key.rb +18 -0
  143. data/lib/spontaneous/permissions/user.rb +1 -1
  144. data/lib/spontaneous/permissions.rb +4 -1
  145. data/lib/spontaneous/plugins/application/state.rb +19 -12
  146. data/lib/spontaneous/prototypes/field_prototype.rb +14 -8
  147. data/lib/spontaneous/published_revision.rb +7 -0
  148. data/lib/spontaneous/publishing/immediate.rb +43 -34
  149. data/lib/spontaneous/publishing/revision.rb +9 -6
  150. data/lib/spontaneous/rack/asset_server.rb +20 -0
  151. data/lib/spontaneous/rack/back/alias.rb +46 -0
  152. data/lib/spontaneous/rack/back/application_assets.rb +28 -0
  153. data/lib/spontaneous/rack/back/base.rb +34 -0
  154. data/lib/spontaneous/rack/back/changes.rb +19 -0
  155. data/lib/spontaneous/rack/back/content.rb +54 -0
  156. data/lib/spontaneous/rack/back/events.rb +38 -0
  157. data/lib/spontaneous/rack/back/field.rb +37 -0
  158. data/lib/spontaneous/rack/back/file.rb +118 -0
  159. data/lib/spontaneous/rack/back/helpers.rb +71 -0
  160. data/lib/spontaneous/rack/back/index.rb +16 -0
  161. data/lib/spontaneous/rack/back/login.rb +47 -0
  162. data/lib/spontaneous/rack/back/map.rb +24 -0
  163. data/lib/spontaneous/rack/back/page.rb +46 -0
  164. data/lib/spontaneous/rack/back/preview.rb +43 -0
  165. data/lib/spontaneous/rack/back/schema.rb +30 -0
  166. data/lib/spontaneous/rack/back/site.rb +25 -0
  167. data/lib/spontaneous/rack/back/site_assets.rb +13 -0
  168. data/lib/spontaneous/rack/back/unsupported_browser.rb +7 -0
  169. data/lib/spontaneous/rack/{user_admin.rb → back/user_admin.rb} +2 -5
  170. data/lib/spontaneous/rack/back.rb +85 -764
  171. data/lib/spontaneous/rack/cacheable_file.rb +3 -3
  172. data/lib/spontaneous/rack/front.rb +16 -9
  173. data/lib/spontaneous/rack/middleware/authenticate.rb +65 -0
  174. data/lib/spontaneous/rack/middleware/csrf.rb +66 -0
  175. data/lib/spontaneous/rack/middleware/reloader.rb +52 -0
  176. data/lib/spontaneous/rack/middleware/scope.rb +60 -0
  177. data/lib/spontaneous/rack/middleware.rb +6 -0
  178. data/lib/spontaneous/rack/page_controller.rb +18 -5
  179. data/lib/spontaneous/rack/public.rb +17 -11
  180. data/lib/spontaneous/rack.rb +34 -24
  181. data/lib/spontaneous/revision.rb +29 -2
  182. data/lib/spontaneous/schema/uid.rb +4 -3
  183. data/lib/spontaneous/schema/uid_map.rb +5 -24
  184. data/lib/spontaneous/schema.rb +1 -0
  185. data/lib/spontaneous/search/database.rb +8 -0
  186. data/lib/spontaneous/search/field.rb +1 -1
  187. data/lib/spontaneous/search/index.rb +3 -5
  188. data/lib/spontaneous/server.rb +1 -1
  189. data/lib/spontaneous/simultaneous.rb +1 -1
  190. data/lib/spontaneous/site/features.rb +4 -5
  191. data/lib/spontaneous/site/helpers.rb +22 -5
  192. data/lib/spontaneous/site/instance.rb +2 -2
  193. data/lib/spontaneous/site/selectors.rb +22 -3
  194. data/lib/spontaneous/storage/cloud.rb +13 -9
  195. data/lib/spontaneous/storage/local.rb +11 -6
  196. data/lib/spontaneous/style.rb +40 -23
  197. data/lib/spontaneous/utils/database/mysql_dumper.rb +1 -1
  198. data/lib/spontaneous/utils/smush_it.rb +1 -1
  199. data/lib/spontaneous/version.rb +1 -1
  200. data/lib/spontaneous.rb +35 -33
  201. data/spontaneous.gemspec +53 -787
  202. data/test/experimental/test_crypt.rb +56 -56
  203. data/test/experimental/test_features.rb +16 -27
  204. data/test/fixtures/assets/public1/css/data.css.scss +3 -0
  205. data/test/fixtures/assets/public1/css/image1.css.scss +4 -0
  206. data/test/fixtures/assets/public1/css/import.css.scss +1 -0
  207. data/test/fixtures/assets/public1/css/urlhash.css.scss +3 -0
  208. data/test/fixtures/assets/public1/js/a.js +1 -1
  209. data/test/fixtures/assets/public1/js/all.js +4 -0
  210. data/test/fixtures/assets/public1/js/{m.coffee → m.js.coffee} +1 -0
  211. data/test/fixtures/assets/public1/x.js +1 -0
  212. data/test/fixtures/assets/public2/css/all.css +4 -0
  213. data/test/fixtures/assets/public2/css/missing.css.scss +3 -0
  214. data/test/fixtures/assets/public2/i/y.png +0 -0
  215. data/test/fixtures/assets/public2/js/b.js +1 -1
  216. data/test/fixtures/assets/public2/js/c.js +1 -1
  217. data/test/fixtures/images/size.extended.webp +0 -0
  218. data/test/fixtures/images/size.lossless.webp +0 -0
  219. data/test/fixtures/images/size.lossy.webp +0 -0
  220. data/test/fixtures/schema/before.yml +4 -4
  221. data/test/fixtures/schema/schema.yml +1 -1
  222. data/test/fixtures/templates/aliases/aaa.html.cut +0 -0
  223. data/test/fixtures/templates/extended/partial_with_renderer.html.cut +1 -0
  224. data/test/fixtures/templates/extended/with_includes_and_renderer.html.cut +2 -0
  225. data/test/functional/test_application.rb +108 -106
  226. data/test/functional/test_back.rb +924 -930
  227. data/test/functional/test_front.rb +285 -238
  228. data/test/functional/test_user_manager.rb +75 -100
  229. data/test/integration/test_installation.rb +1 -1
  230. data/test/support/matchers.rb +12 -0
  231. data/test/support/minitest.rb +121 -0
  232. data/test/support/rack.rb +45 -0
  233. data/test/support/test_start_finish.rb +103 -0
  234. data/test/test_helper.rb +21 -68
  235. data/test/test_integration_helper.rb +1 -3
  236. data/test/unit/test_alias.rb +432 -408
  237. data/test/unit/test_asset_bundler.rb +58 -58
  238. data/test/unit/test_assets.rb +485 -155
  239. data/test/unit/test_async.rb +16 -37
  240. data/test/unit/test_authentication.rb +425 -457
  241. data/test/unit/test_boxes.rb +191 -191
  242. data/test/unit/test_changesets.rb +244 -254
  243. data/test/unit/test_config.rb +128 -142
  244. data/test/unit/test_content.rb +313 -359
  245. data/test/unit/test_content_inheritance.rb +29 -30
  246. data/test/unit/test_datamapper.rb +1205 -1080
  247. data/test/unit/test_datamapper_content.rb +49 -51
  248. data/test/unit/test_extensions.rb +23 -23
  249. data/test/unit/test_fields.rb +1488 -1180
  250. data/test/unit/test_formats.rb +158 -158
  251. data/test/unit/test_generators.rb +98 -40
  252. data/test/unit/test_helpers.rb +73 -76
  253. data/test/unit/test_image_size.rb +53 -22
  254. data/test/unit/test_images.rb +164 -165
  255. data/test/unit/test_layouts.rb +133 -122
  256. data/test/unit/test_logger.rb +14 -17
  257. data/test/unit/test_media.rb +69 -84
  258. data/test/unit/test_modifications.rb +513 -525
  259. data/test/unit/test_page.rb +462 -361
  260. data/test/unit/test_permissions.rb +379 -364
  261. data/test/unit/test_piece.rb +67 -75
  262. data/test/unit/test_plugins.rb +82 -89
  263. data/test/unit/test_prototype_set.rb +215 -216
  264. data/test/unit/test_prototypes.rb +114 -124
  265. data/test/unit/test_publishing.rb +252 -289
  266. data/test/unit/test_render.rb +167 -115
  267. data/test/unit/test_revisions.rb +436 -444
  268. data/test/unit/test_schema.rb +339 -309
  269. data/test/unit/test_search.rb +577 -574
  270. data/test/unit/test_serialisation.rb +136 -147
  271. data/test/unit/test_site.rb +252 -227
  272. data/test/unit/test_skeptick.rb +130 -0
  273. data/test/unit/test_storage.rb +46 -40
  274. data/test/unit/test_structure.rb +57 -66
  275. data/test/unit/test_styles.rb +104 -104
  276. data/test/unit/test_templates.rb +72 -57
  277. data/test/unit/test_type_hierarchy.rb +15 -16
  278. data/test/unit/test_visibility.rb +239 -257
  279. metadata +455 -326
  280. data/application/js/vendor/JS.Class-2.1.5/CHANGELOG +0 -283
  281. data/application/js/vendor/JS.Class-2.1.5/MIT-LICENSE +0 -30
  282. data/application/js/vendor/JS.Class-2.1.5/README +0 -30
  283. data/application/js/vendor/JS.Class-2.1.5/min/command.js +0 -1
  284. data/application/js/vendor/JS.Class-2.1.5/min/comparable.js +0 -1
  285. data/application/js/vendor/JS.Class-2.1.5/min/constant_scope.js +0 -1
  286. data/application/js/vendor/JS.Class-2.1.5/min/decorator.js +0 -1
  287. data/application/js/vendor/JS.Class-2.1.5/min/enumerable.js +0 -1
  288. data/application/js/vendor/JS.Class-2.1.5/min/forwardable.js +0 -1
  289. data/application/js/vendor/JS.Class-2.1.5/min/hash.js +0 -1
  290. data/application/js/vendor/JS.Class-2.1.5/min/linked_list.js +0 -1
  291. data/application/js/vendor/JS.Class-2.1.5/min/loader.js +0 -1
  292. data/application/js/vendor/JS.Class-2.1.5/min/method_chain.js +0 -1
  293. data/application/js/vendor/JS.Class-2.1.5/min/observable.js +0 -1
  294. data/application/js/vendor/JS.Class-2.1.5/min/package.js +0 -1
  295. data/application/js/vendor/JS.Class-2.1.5/min/proxy.js +0 -1
  296. data/application/js/vendor/JS.Class-2.1.5/min/ruby.js +0 -1
  297. data/application/js/vendor/JS.Class-2.1.5/min/set.js +0 -1
  298. data/application/js/vendor/JS.Class-2.1.5/min/stack_trace.js +0 -1
  299. data/application/js/vendor/JS.Class-2.1.5/min/state.js +0 -1
  300. data/application/js/vendor/JS.Class-2.1.5/min/stdlib.js +0 -16
  301. data/application/js/vendor/jquery-1.6.2.min.js +0 -18
  302. data/application/js/vendor/jquery-ui-1.8.16.custom.min.js +0 -791
  303. data/application/js/vendor/jquery-ui-1.8.9.custom.min.js +0 -415
  304. data/application/static/font/fontawesome-webfont-5c5c21100a346972a82c34c5e96ffcfe.ttf +0 -0
  305. data/application/static/select-arrow-6e7dd3745b00e934b0d7a3250c46558b.png +0 -0
  306. data/bin/limit-upload +0 -5
  307. data/bin/unlimit-upload +0 -3
  308. data/lib/spontaneous/asset/file.rb +0 -25
  309. data/lib/spontaneous/asset/source.rb +0 -28
  310. data/lib/spontaneous/image_size.rb +0 -123
  311. data/lib/spontaneous/output/assets/compression.rb +0 -58
  312. data/lib/spontaneous/output/assets.rb +0 -32
  313. data/lib/spontaneous/rack/around_back.rb +0 -20
  314. data/lib/spontaneous/rack/around_front.rb +0 -27
  315. data/lib/spontaneous/rack/around_preview.rb +0 -22
  316. data/lib/spontaneous/rack/assets.rb +0 -126
  317. data/lib/spontaneous/rack/authentication.rb +0 -20
  318. data/lib/spontaneous/rack/cookie_authentication.rb +0 -38
  319. data/lib/spontaneous/rack/helpers.rb +0 -52
  320. data/lib/spontaneous/rack/http.rb +0 -18
  321. data/lib/spontaneous/rack/media.rb +0 -30
  322. data/lib/spontaneous/rack/query_authentication.rb +0 -35
  323. data/lib/spontaneous/rack/reloader.rb +0 -45
  324. data/lib/spontaneous/rack/user_helpers.rb +0 -28
  325. /data/{README → application/js/field/markdown/text_command.js} +0 -0
  326. /data/application/js/vendor/{JS.Class-2.1.5/min/core.js → js.class-2.1.5.min.js} +0 -0
  327. /data/test/fixtures/assets/public1/css/{a.scss → a.css.scss} +0 -0
  328. /data/{lib/spontaneous/generators/site/public/css/site.scss → test/fixtures/assets/public1/x.css} +0 -0
  329. /data/{lib/spontaneous/generators/site/public/js/.empty_directory → test/fixtures/assets/public1/x.png} +0 -0
  330. /data/test/fixtures/assets/public2/css/{b.scss → b.css.scss} +0 -0
  331. /data/test/fixtures/assets/public2/js/{n.coffee → n.js.coffee} +0 -0
  332. /data/test/fixtures/back/{public → assets}/css/sass_include.scss +0 -0
  333. /data/test/fixtures/back/{public → assets}/css/sass_template.scss +0 -0
  334. /data/test/fixtures/back/{public → assets}/js/coffeescript.coffee +0 -0
  335. /data/{lib/spontaneous/generators/site/public/js/site.js → test/fixtures/templates/aliases/aa_alias.html.cut} +0 -0
@@ -1,7 +1,10 @@
1
1
 
2
2
  module Spontaneous::Output::Context
3
+ autoload :RenderCache, 'spontaneous/output/context/render_cache'
4
+
3
5
  module ContextCore
4
- attr_accessor :__renderer
6
+ include RenderCache
7
+ attr_accessor :_renderer
5
8
 
6
9
  def navigation(depth = 1, &block)
7
10
  case depth
@@ -37,10 +40,36 @@ module Spontaneous::Output::Context
37
40
  Spontaneous.development?
38
41
  end
39
42
 
43
+ def development?
44
+ Spontaneous.development?
45
+ end
46
+
40
47
  def root
41
48
  Spontaneous::Site.root
42
49
  end
43
50
 
51
+ def site_page(path)
52
+ Spontaneous::Site[path]
53
+ end
54
+
55
+ def asset_environment
56
+ _with_render_cache('asset.environment') do
57
+ Spontaneous::Asset::Environment.new(self)
58
+ end
59
+ end
60
+
61
+ def asset_path(path, options = {})
62
+ asset_environment.find(path, options).try(:first)
63
+ end
64
+
65
+ def asset_url(path, options = {})
66
+ "url(#{asset_path(path, options)})"
67
+ end
68
+
69
+ def site
70
+ Spontaneous::Site.instance
71
+ end
72
+
44
73
  def publishing?
45
74
  false
46
75
  end
@@ -57,6 +86,10 @@ module Spontaneous::Output::Context
57
86
  content.map { |c| yield(c) } if block_given?
58
87
  end
59
88
 
89
+ def this
90
+ __target
91
+ end
92
+
60
93
  def content
61
94
  __target.iterable
62
95
  end
@@ -87,6 +120,17 @@ module Spontaneous::Output::Context
87
120
  __target.owner.pieces.last == self
88
121
  end
89
122
 
123
+ # template takes an existing first-pass template, converts it to a second pass template
124
+ # and then returns the result for inclusion.
125
+ # This lets you share templates between the publish step and the request step.
126
+ # Useful for things like search results where you want to list the results using the same
127
+ # layout that you used in the static list
128
+ def template(template_path)
129
+ __loader.template(template_path).convert(Spontaneous::Output::Template::RequestSyntax)
130
+ end
131
+
132
+ alias_method :defer, :template
133
+
90
134
  def __format
91
135
  __loader.format
92
136
  end
@@ -109,37 +153,14 @@ module Spontaneous::Output::Context
109
153
  # use of shared caches that are held by it.
110
154
  def __render_content(content)
111
155
  if content.respond_to?(:render_using)
112
- content.render_using(__renderer, __format, self)
156
+ content.render_using(_renderer, __format, self)
113
157
  else
114
158
  content.render(__format, self)
115
159
  end
116
160
  end
117
161
  end
118
162
 
119
- module RenderCache
120
- def _render_cache_value(key)
121
- __renderer.render_cache[key]
122
- end
123
-
124
- def _render_cache_set_value(key, value)
125
- __renderer.render_cache[key] = value
126
- end
127
-
128
- def _render_cache_key?(key)
129
- __renderer.render_cache.key?(key)
130
- end
131
-
132
- def _with_render_cache(key, &value_block)
133
- if _render_cache_key?(key)
134
- _render_cache_value(key)
135
- else
136
- _render_cache_set_value(key, yield)
137
- end
138
- end
139
- end
140
-
141
163
  module PublishContext
142
- include RenderCache
143
164
 
144
165
  def root
145
166
  _with_render_cache("site.root") do
@@ -147,15 +168,21 @@ module Spontaneous::Output::Context
147
168
  end
148
169
  end
149
170
 
150
- def compressed_scripts(scripts)
171
+ def site_page(path)
172
+ _with_render_cache("site_page.#{path}") do
173
+ super
174
+ end
175
+ end
176
+
177
+ def scripts(*scripts)
151
178
  _with_render_cache(scripts.join(",")) do
152
- super(scripts)
179
+ super
153
180
  end
154
181
  end
155
182
 
156
- def compressed_stylesheets(stylesheets)
183
+ def stylesheets(*stylesheets)
157
184
  _with_render_cache(stylesheets.join(",")) do
158
- super(stylesheets)
185
+ super
159
186
  end
160
187
  end
161
188
 
@@ -175,5 +202,4 @@ module Spontaneous::Output::Context
175
202
 
176
203
  module RequestContext
177
204
  end
178
-
179
205
  end
@@ -7,67 +7,23 @@ module Spontaneous::Output::Helpers
7
7
  extend self
8
8
 
9
9
  def scripts(*args)
10
- scripts = args.flatten
11
- options = scripts.extract_options!
12
- compress = (live? or (publishing? and options[:force_compression]))
13
- return compressed_scripts(scripts) if compress
14
- scripts.map { |script| script_tag(script) }.join("\n")
10
+ script_urls(*args).map { |script|
11
+ script_tag(script)
12
+ }.join("\n")
13
+ end
14
+
15
+ def script_urls(*args)
16
+ options = args.extract_options!
17
+ options.update(:development => development?)
18
+ asset_environment.js(args.flatten, options)
15
19
  end
16
20
 
17
21
  alias_method :script, :scripts
18
22
 
19
23
  def script_tag(src)
20
- src = "#{src}.js" unless src =~ /\.js$/o
21
24
  %(<script type="text/javascript" src="#{src}"></script>)
22
25
  end
23
26
 
24
- def convert_coffeescript(url)
25
- S::Output::Assets.compile_coffeescript(url)
26
- end
27
-
28
- def compressed_scripts(scripts)
29
- file_paths = scripts.map { |script| [script, S::Output::Assets.find_file("#{script}.js", "#{script}.coffee")] }
30
- invalid, file_paths = file_paths.partition { |url, path| path.nil? }
31
-
32
- tags = []
33
- unless file_paths.empty?
34
- # in order to compile coffeescript efficiently, avoiding multiple anonymous function wrappers
35
- # but keeping the files in the correct order
36
- # first partition files into js & coffee groups:
37
- types = file_paths.slice_between { |(purl, ppath), (url, path)| File.extname(ppath) != File.extname(path) }
38
- # then iterate through each group to concatenate the source into a single string (src)
39
- js = types.map { |type|
40
- ext = nil
41
- src = type.map { |url, path|
42
- ext = File.extname(path)
43
- File.read(path)
44
- }.join
45
- # then compile the concatenated src if it's coffeescript
46
- case ext
47
- when ".coffee"
48
- CoffeeScript.compile src
49
- else
50
- src
51
- end
52
- }.join
53
-
54
- compressed, hash = compress_js_string(js)
55
- output_path = Spontaneous::Output::Assets.path_for(revision, "#{hash}.js")
56
-
57
- FileUtils.mkdir_p(File.dirname(output_path))
58
- File.open(output_path, "w") { |file| file.write(compressed) }
59
-
60
- tags = [script_tag(Spontaneous::Output::Assets.url(hash))]
61
- end
62
-
63
- tags.concat invalid.map { |src, path| script_tag(src) }
64
- tags.join("\n")
65
- end
66
-
67
- def compress_js_string(js_string)
68
- Spontaneous::Output::Assets::Compression.shine_compress_string(js_string, :js)
69
- end
70
-
71
27
  Spontaneous::Output::Helpers.register_helper(self, :html)
72
28
  end
73
29
  end
@@ -7,55 +7,23 @@ module Spontaneous::Output::Helpers
7
7
  extend self
8
8
 
9
9
  def stylesheets(*args)
10
- stylesheets = args.flatten
11
- options = stylesheets.extract_options!
12
- compress_stylesheets = (live? or (publishing? and options[:force_compression]))
13
-
14
- return compressed_stylesheets(stylesheets) if compress_stylesheets
15
-
16
- stylesheets.map do |stylesheet|
10
+ stylesheet_urls(*args).map { |stylesheet|
17
11
  stylesheet_tag(stylesheet)
18
- end.join("\n")
12
+ }.join("\n")
13
+ end
14
+
15
+ def stylesheet_urls(*args)
16
+ options = args.extract_options!
17
+ options.update(:development => development?)
18
+ asset_environment.css(args.flatten, options)
19
19
  end
20
20
 
21
21
  alias_method :stylesheet, :stylesheets
22
22
 
23
23
  def stylesheet_tag(href)
24
- href = "#{href}.css" unless href =~ /\.css$/o
25
24
  %(<link rel="stylesheet" href="#{href}" />)
26
25
  end
27
26
 
28
- def compressed_stylesheets(stylesheets)
29
- file_paths = stylesheets.map { |style| [style, S::Output::Assets.find_file("#{style}.scss", "#{style}.css")] }
30
- invalid, file_paths = file_paths.partition { |url, path| path.nil? }
31
- roots = Spontaneous.instance.paths.expanded(:public)
32
-
33
- tags = []
34
- css = file_paths.map { |url, path|
35
- case path
36
- when /\.scss$/o
37
- load_paths = roots + [File.dirname(path), File.dirname(path) / "sass"]
38
- ::Sass::Engine.for_file(path, {
39
- :load_paths => load_paths,
40
- :cache => false,
41
- :style => :compressed
42
- }).render
43
- else
44
- File.read(path)
45
- end
46
- }.join
47
- compressed, hash = compress_css_string(css)
48
- output_path = Spontaneous::Output::Assets.path_for(revision, "#{hash}.css")
49
- FileUtils.mkdir_p(File.dirname(output_path))
50
- File.open(output_path, "w") { |file| file.write(compressed) }
51
- tags = [stylesheet_tag(Spontaneous::Output::Assets.url(hash))]
52
- tags.join("\n")
53
- end
54
-
55
- def compress_css_string(css_string)
56
- Spontaneous::Output::Assets::Compression.shine_compress_string(css_string, :css)
57
- end
58
-
59
27
  Spontaneous::Output::Helpers.register_helper(self, :html)
60
28
  end
61
29
  end
@@ -18,24 +18,32 @@ module Spontaneous::Output::Template
18
18
 
19
19
  def render(output, params = {})
20
20
  output.model.with_visible do
21
- engine.render(output.content, context(output, params), output.name.to_s)
21
+ engine.render(output.content, context(output, params), output.name)
22
22
  end
23
23
  end
24
24
 
25
25
  def render_string(template_string, output, params = {})
26
26
  output.model.with_visible do
27
- engine.render_string(template_string, context(output, params), output.name.to_s)
27
+ engine.render_string(template_string, context(output, params), output.name)
28
28
  end
29
29
  end
30
30
 
31
31
  def context(output, params)
32
32
  context_class(output).new(output.content, params).tap do |context|
33
- context.__renderer = self
33
+ context._renderer = renderer_for_context
34
34
  end
35
35
  end
36
36
 
37
+ def renderer_for_context
38
+ self
39
+ end
40
+
37
41
  def context_class(output)
38
- context_cache[output.name] ||= generate_context_class(output)
42
+ if Spontaneous.development?
43
+ generate_context_class(output)
44
+ else
45
+ context_cache[output.name] ||= generate_context_class(output)
46
+ end
39
47
  end
40
48
 
41
49
  def context_cache
@@ -146,8 +154,12 @@ module Spontaneous::Output::Template
146
154
  request_renderer.render_string(rendered, output, params)
147
155
  end
148
156
 
157
+ def renderer_for_context
158
+ @renderer_for_context ||= PublishRenderer.new(@cache)
159
+ end
160
+
149
161
  def request_renderer
150
- @request_renderer ||= RequestRenderer.new
162
+ @request_renderer ||= RequestRenderer.new(@cache)
151
163
  end
152
164
  end
153
165
  end
@@ -155,7 +155,6 @@ module Spontaneous
155
155
  autoload :Template, "spontaneous/output/template"
156
156
  autoload :Context, "spontaneous/output/context"
157
157
  autoload :Helpers, "spontaneous/output/helpers"
158
- autoload :Assets, "spontaneous/output/assets"
159
158
  end
160
159
  end
161
160
 
@@ -4,17 +4,21 @@ require 'pathname'
4
4
 
5
5
  module Spontaneous
6
6
  class Paths < ::Hash
7
+ # TODO: Move this kind of stuff into the Revision class
8
+ # Instead of throwing around revision numbers we should
9
+ # be throwing around Revision instances. It is fecking OO
10
+ # after all...
7
11
  def self.pad_revision_number(revision)
8
12
  revision.to_s.rjust(5, "0")
9
13
  end
10
14
 
11
15
  def initialize(root)
12
16
  @root = File.expand_path(root)
13
- super()
17
+ super() { |hash, key| hash[key] = [] }
14
18
  end
15
19
 
16
20
  def add(category, *paths)
17
- self[category] = paths
21
+ self[category].concat(paths)
18
22
  end
19
23
 
20
24
  def expanded(category)
@@ -36,5 +36,23 @@ module Spontaneous::Permissions
36
36
  def access!(ip_address = nil)
37
37
  self.update(:last_access_at => Time.now, :last_access_ip => ip_address)
38
38
  end
39
+
40
+ CSFR_SEP = ":".freeze
41
+
42
+ def generate_csrf_token
43
+ salt = Spontaneous::Permissions.random_string(32)
44
+ [salt, generate_csrf_hash(salt)].join(CSFR_SEP)
45
+ end
46
+
47
+ def csrf_token_valid?(token)
48
+ return false if token.nil?
49
+ salt, fingerprint = token.split(CSFR_SEP)
50
+ generate_csrf_hash(salt) == fingerprint
51
+ end
52
+
53
+ def generate_csrf_hash(salt)
54
+ fingerprint = [salt, key_id].join(CSFR_SEP)
55
+ Spontaneous::Permissions.crypto_hash(fingerprint)
56
+ end
39
57
  end
40
58
  end
@@ -98,7 +98,7 @@ module Spontaneous::Permissions
98
98
  end
99
99
 
100
100
  def encrypt_password(clear_password)
101
- Spontaneous::Crypt.hash(clear_password)
101
+ Spontaneous::Crypt.hash_password(clear_password)
102
102
  end
103
103
 
104
104
  def upgrade_authentication(auth)
@@ -1,6 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'base58'
4
3
  require 'securerandom'
5
4
 
6
5
  module Spontaneous
@@ -29,6 +28,10 @@ module Spontaneous
29
28
  def random_string(length)
30
29
  SecureRandom.urlsafe_base64(length)[0...(length)]
31
30
  end
31
+
32
+ def crypto_hash(string, algorithm = Digest::SHA1)
33
+ algorithm.new.update(string).hexdigest
34
+ end
32
35
  end
33
36
  end
34
37
  end
@@ -5,19 +5,26 @@ module Spontaneous::Plugins::Application
5
5
  extend Spontaneous::Concern
6
6
 
7
7
  module ClassMethods
8
+ @@semaphore = Mutex.new
9
+
8
10
  def init(options={})
9
- # return false if loaded?
10
- self.environment = (options.delete(:environment) || ENV["SPOT_ENV"] || :development)
11
- self.mode = options.delete(:mode) || ENV["SPOT_MODE"] || :back
12
- root = options.delete(:root) || ENV["SPOT_ROOT"] || Dir.pwd
13
- site = Spontaneous::Site.instantiate(root, environment, mode)
14
- lib = File.expand_path(File.join(root, "lib"))
15
- $:.push(lib) unless $:.include?(lib)
16
- Spontaneous::Logger.setup(:log_level => options[:log_level], :logfile => options[:logfile], :cli => options[:cli])
17
- site.initialize!
18
- site.schema.validate! if self.mode == :console
19
- logger.warn "Auto login is enabled and set to '#{site.config.auto_login}'. Please ensure this is disabled in production mode by removing the 'auto_login' setting from your environment file." if site.config.auto_login and mode == :back
20
- Thread.current[:spontaneous_loaded] = true
11
+ @@semaphore.synchronize do
12
+ self.environment = (options.delete(:environment) || ENV["SPOT_ENV"] || :development)
13
+ self.mode = options.delete(:mode) || ENV["SPOT_MODE"] || :back
14
+ root = options.delete(:root) || ENV["SPOT_ROOT"] || Dir.pwd
15
+ site = Spontaneous::Site.instantiate(root, environment, mode)
16
+ lib = File.expand_path(File.join(root, "lib"))
17
+ $:.push(lib) unless $:.include?(lib)
18
+ Spontaneous::Logger.setup(:log_level => options[:log_level], :logfile => options[:logfile], :cli => options[:cli])
19
+ site.initialize!
20
+ site.schema.validate! if self.mode == :console
21
+ if site.config.auto_login && mode == :back
22
+ logger.warn "Auto login is enabled and set to '#{site.config.auto_login}'.\n" \
23
+ " Please ensure this is disabled in production mode by removing the\n" \
24
+ " 'auto_login' setting from your environment file."
25
+ end
26
+ Thread.current[:spontaneous_loaded] = true
27
+ end
21
28
  end
22
29
 
23
30
  # This is called after definition of the Content model.
@@ -10,13 +10,15 @@ module Spontaneous::Prototypes
10
10
  @name = name
11
11
  @extend = [blocks].flatten.push(block).compact
12
12
 
13
- parse_options(options)
14
-
15
13
  # if the type is nil then try the name, this will assign sensible defaults
16
14
  # to fields like 'image' or 'date'
17
15
  @base_class = Spontaneous::Field[type || name]
18
16
 
19
- owner.const_set("#{name.to_s.camelize}Field", instance_class)
17
+ parse_options(@base_class, options)
18
+
19
+
20
+ field_class_name = "#{name.to_s.camelize}Field"
21
+ owner.const_set(field_class_name, instance_class)
20
22
 
21
23
  self
22
24
  end
@@ -52,11 +54,12 @@ module Spontaneous::Prototypes
52
54
  @name.to_s.titleize
53
55
  end
54
56
 
55
- def parse_options(options)
56
- @options = {
57
- :default => '',
58
- :comment => false
59
- }.merge(options)
57
+ def parse_options(field_class, options)
58
+ @options = default_options(field_class).merge(options)
59
+ end
60
+
61
+ def default_options(field_class)
62
+ {:default => '', :comment => false }.merge(field_class.default_options)
60
63
  end
61
64
 
62
65
  def instance_class
@@ -96,6 +99,9 @@ module Spontaneous::Prototypes
96
99
  @options[:comment]
97
100
  end
98
101
 
102
+ def fallback
103
+ @options[:fallback]
104
+ end
99
105
 
100
106
  # default read level is None, i.e. every logged in user can read the field
101
107
  def read_level
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+
3
+ module Spontaneous
4
+ class PublishedRevision < Sequel::Model(:revisions)
5
+
6
+ end
7
+ end
@@ -87,15 +87,13 @@ module Spontaneous
87
87
  abort_publish_at_exit
88
88
  }
89
89
  before_publish
90
- begin
91
- @content_model.publish(revision, modified_page_list) do
92
- render_revision
93
- end
94
- after_publish
95
- rescue ::Exception => e
96
- abort_publish(e)
97
- raise(e)
90
+ @content_model.publish(revision, modified_page_list) do
91
+ render_revision
98
92
  end
93
+ after_publish
94
+ rescue ::Exception => e # Catch even interrupts because we definitely need to cleanup
95
+ abort_publish(e)
96
+ raise(e)
99
97
  end
100
98
 
101
99
  def render_revision
@@ -215,21 +213,25 @@ module Spontaneous
215
213
  public_dirs.each do |public_src|
216
214
  next unless public_src.exist?
217
215
  public_src = public_src.realpath
218
- Dir[public_src.to_s / "**/*"].each do |src|
219
- src = Pathname.new(src)
220
- # insert facet namespace in front of path to keep URLs consistent across
221
- # the back & front servers
222
- dest = [facet.file_namespace, src.relative_path_from(public_src).to_s].compact
223
- dest = (public_dest + File.join(dest))
224
- if src.directory?
225
- dest.mkpath
226
- else
227
- copy_public_file(src, dest)
228
- end
216
+ Dir[public_src.to_s / "**/*"].each do |file|
217
+ copy_facet_public_dir(facet, file, public_src, public_dest)
229
218
  end
230
219
  end
231
220
  end
232
221
 
222
+ def copy_facet_public_dir(facet, original, public_src, public_dest)
223
+ original = Pathname.new(original)
224
+ # insert facet namespace in front of path to keep URLs consistent across
225
+ # the back & front servers
226
+ dest = File.join [facet.file_namespace, original.relative_path_from(public_src).to_s].compact
227
+ dest = public_dest + dest
228
+ if original.directory?
229
+ dest.mkpath
230
+ else
231
+ copy_public_file(original, dest)
232
+ end
233
+ end
234
+
233
235
  def copy_public_file(src, dest)
234
236
  # TODO: Add coffeescript compilation.
235
237
  # Should be implemented using sprockets
@@ -286,27 +288,34 @@ module Spontaneous
286
288
 
287
289
  def after_publish
288
290
  update_progress("finalising")
289
- S::Revision.create(:revision => revision, :published_at => now)
290
- Spontaneous::Site.send(:set_published_revision, revision)
291
- tmp = Spontaneous.revision_dir(revision) / "tmp"
292
- FileUtils.mkdir_p(tmp) unless ::File.exists?(tmp)
293
- write_revision(revision)
294
-
295
291
  begin
296
- Spontaneous::Site.trigger(:after_publish, revision)
297
- Spontaneous::Site.send(:pending_revision=, nil)
298
- Spontaneous::Content.cleanup_revisions(revision, keep_revisions)
292
+ tmp = Spontaneous.revision_dir(revision) / "tmp"
293
+ FileUtils.mkdir_p(tmp) unless ::File.exists?(tmp)
294
+ activate_revision
299
295
  update_progress("complete")
300
- rescue Exception => e
296
+ rescue => e
301
297
  # if a post publish hook raises an exception then we want to roll everything back
302
- S::Revision.filter(:revision => revision).delete
303
- Spontaneous::Site.send(:set_published_revision, @previous_revision)
304
- write_revision(@previous_revision)
305
- abort_publish(e)
298
+ deactivate_revision
306
299
  raise e
307
300
  end
308
301
  end
309
302
 
303
+ def activate_revision
304
+ S::PublishedRevision.create(:revision => revision, :published_at => now)
305
+ Spontaneous::Site.send(:set_published_revision, revision)
306
+ write_revision(revision)
307
+ Spontaneous::Site.trigger(:after_publish, revision)
308
+ Spontaneous::Site.send(:pending_revision=, nil)
309
+ Spontaneous::Content.cleanup_revisions(revision, keep_revisions)
310
+ end
311
+
312
+ def deactivate_revision
313
+ S::PublishedRevision.filter(:revision => revision).delete
314
+ Spontaneous::Site.send(:set_published_revision, @previous_revision)
315
+ write_revision(@previous_revision)
316
+ abort_publish(e)
317
+ end
318
+
310
319
  # Makes the revision live on the filesystem by symlinking the revisions/current
311
320
  # directory to the revision directory and writing the current revision to the
312
321
  # revisions/REVISION file.
@@ -324,7 +333,7 @@ module Spontaneous
324
333
  end
325
334
 
326
335
  def abort_publish(exception)
327
- if r = S::Site.pending_revision
336
+ if (r = S::Site.pending_revision)
328
337
  update_progress("aborting")
329
338
  FileUtils.rm_r(Spontaneous.revision_dir(revision)) if File.exists?(Spontaneous.revision_dir(revision))
330
339
  Spontaneous::Site.send(:pending_revision=, nil)
@@ -28,7 +28,7 @@ module Spontaneous::Publishing
28
28
  yield if block_given?
29
29
  end
30
30
  set_source_timestamps
31
- rescue ::Exception => e
31
+ rescue => e
32
32
  @revision.delete
33
33
  raise e
34
34
  end
@@ -157,11 +157,9 @@ module Spontaneous::Publishing
157
157
  end
158
158
 
159
159
  def self.delete_all(model)
160
- revisions = tables(model).
161
- map { |table| revision_from_table(model, table) }.
162
- map { |r| new(model, r) }
160
+ revisions = tables(model).map { |table| for_table(model, table) }
163
161
 
164
- # Don't call the full #delete because it is much more efficient
162
+ # Don't call the full Revision#delete because it is much more efficient
165
163
  # to delete the contents of the revision tables in a single
166
164
  # command rather than revision by revision
167
165
  revisions.each(&:delete_table)
@@ -191,6 +189,11 @@ module Spontaneous::Publishing
191
189
  ds.filter(:revision => revision, &block)
192
190
  end
193
191
 
192
+ def self.for_table(model, table)
193
+ r = revision_from_table(model, table)
194
+ new(model, r)
195
+ end
196
+
194
197
  def self.revision_from_table(model, table)
195
198
  model.mapper.revision_from_table(table)
196
199
  end
@@ -345,7 +348,7 @@ module Spontaneous::Publishing
345
348
  end
346
349
 
347
350
  def archive_dataset(&block)
348
- _dataset(history_table, &block)
351
+ _dataset(archive_table, &block)
349
352
  end
350
353
 
351
354
  def _dataset(table, &block)