xhive 1.0.0.pre

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 (48) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +223 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/javascripts/xhive/application.js +15 -0
  5. data/app/assets/javascripts/xhive/loader.js.coffee +22 -0
  6. data/app/assets/javascripts/xhive/pages.js +2 -0
  7. data/app/assets/stylesheets/xhive/application.css +13 -0
  8. data/app/assets/stylesheets/xhive/pages.css +4 -0
  9. data/app/controllers/xhive/application_controller.rb +5 -0
  10. data/app/controllers/xhive/pages_controller.rb +24 -0
  11. data/app/controllers/xhive/stylesheets_controller.rb +16 -0
  12. data/app/controllers/xhive/widgets_controller.rb +16 -0
  13. data/app/helpers/xhive/application_helper.rb +39 -0
  14. data/app/models/xhive/anonymous_user.rb +6 -0
  15. data/app/models/xhive/mapper.rb +19 -0
  16. data/app/models/xhive/page.rb +19 -0
  17. data/app/models/xhive/site.rb +14 -0
  18. data/app/models/xhive/stylesheet.rb +29 -0
  19. data/app/presenters/xhive/base_presenter.rb +31 -0
  20. data/app/presenters/xhive/page_presenter.rb +23 -0
  21. data/app/presenters/xhive/stylesheet_presenter.rb +31 -0
  22. data/app/presenters/xhive/user_presenter.rb +8 -0
  23. data/app/views/layouts/xhive/application.html.erb +15 -0
  24. data/app/views/xhive/pages/show.html.erb +2 -0
  25. data/config/routes.rb +13 -0
  26. data/db/migrate/20121012191751_create_xhive_sites.rb +10 -0
  27. data/db/migrate/20121012193105_create_xhive_pages.rb +14 -0
  28. data/db/migrate/20121013235227_add_home_page_to_xhive_sites.rb +5 -0
  29. data/db/migrate/20121013235306_add_site_to_xhive_pages.rb +6 -0
  30. data/db/migrate/20121016224054_create_xhive_stylesheets.rb +13 -0
  31. data/db/migrate/20121016224326_add_slug_index_to_pages.rb +5 -0
  32. data/db/migrate/20121019185702_create_xhive_mappers.rb +13 -0
  33. data/lib/tasks/xhive_tasks.rake +4 -0
  34. data/lib/xhive/base_tag.rb +89 -0
  35. data/lib/xhive/controller.rb +24 -0
  36. data/lib/xhive/engine.rb +24 -0
  37. data/lib/xhive/hashy.rb +42 -0
  38. data/lib/xhive/presentable.rb +28 -0
  39. data/lib/xhive/router/base.rb +61 -0
  40. data/lib/xhive/router/cells.rb +36 -0
  41. data/lib/xhive/router/error.rb +14 -0
  42. data/lib/xhive/router/route.rb +77 -0
  43. data/lib/xhive/router.rb +10 -0
  44. data/lib/xhive/tag_factory.rb +21 -0
  45. data/lib/xhive/version.rb +3 -0
  46. data/lib/xhive/widgify.rb +53 -0
  47. data/lib/xhive.rb +12 -0
  48. metadata +271 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,223 @@
1
+ XHIVE
2
+ ======
3
+
4
+ xhive is a gem built for turning your Rails application into an AJAXified CMS.
5
+
6
+ # How it works
7
+
8
+ xhive converts your controller actions or [cells](https://github.com/apotonick/cells) into AJAX widgets.
9
+
10
+ It leverages the power of [Liquid](http://liquidmarkup.org/) creating a custom Liquid::Tag for every
11
+ widget, so it can be called from within any HTML template.
12
+
13
+ xhive also gives you the foundation of a CMS providing the following models:
14
+
15
+ * Site
16
+ * Page
17
+ * Stylesheet
18
+ * Image
19
+
20
+ Using this models along with the xhive widgets you will be able to build a fully functional CMS.
21
+
22
+ # Installation
23
+
24
+ Add xhive to your Gemfile
25
+
26
+ `gem 'xhive'`
27
+
28
+ Run bundle install
29
+
30
+ `bundle install`
31
+
32
+ Run xhive migrations
33
+
34
+ ```
35
+ rake xhive:install:migrations
36
+ rake db:migrate
37
+ ```
38
+
39
+ Include the custom stylesheets in your head tag.
40
+
41
+ `<%= include_custom_stylesheets %>`
42
+
43
+ Include the widgets loader just before your \<\\body\> tag.
44
+
45
+ `<%= initialize_widgets_loader %>`
46
+
47
+ # Usage
48
+
49
+ ## Widgify
50
+
51
+ ### Turning your controller actions into widgets
52
+
53
+ Let's say you have a Posts controller and you want to access the show action as a widget.
54
+
55
+ ```
56
+ app/controller/posts_controller.rb
57
+
58
+ class PostsController < ApplicationController
59
+ def show
60
+ @post = Post.find(params[:id])
61
+ end
62
+ end
63
+
64
+ app/views/posts/show.html.erb
65
+
66
+ <h1><%= @post.title %></h1>
67
+
68
+ <p><%= @post.body %></p>
69
+
70
+ config/routes.rb
71
+
72
+ resources :posts, :only => [:show]
73
+
74
+ ```
75
+ Just tell xhive to *widgify* your action:
76
+
77
+ ```
78
+ class PostsController < ApplicationController
79
+ widgify :show
80
+
81
+ def show
82
+ @post = Post.find(params[:id])
83
+ end
84
+ end
85
+ ```
86
+ And that's it. You will now be able to insert the content of any post from within an HTML template using:
87
+
88
+ {% posts_show id:1234 %}
89
+
90
+ This tag will make the browser insert the post content asynchronously into the HTML document.
91
+
92
+ xhive will also enforce the tag to include the :id parameter.
93
+
94
+ ### Using [cells](https://github.com/apotonick/cells) as reusable widgets
95
+
96
+ Let's use the same example to illustrate the use of cells with xhive.
97
+
98
+ We have a Posts cell and we want to use the show method as an AJAX widget.
99
+
100
+ ```
101
+ app/cells/posts_cell.rb
102
+
103
+ class PostsCell < Cell::Rails
104
+ def show(params)
105
+ @post = params[:id]
106
+ render
107
+ end
108
+ end
109
+
110
+ app/cells/posts/show.html.erb
111
+
112
+ <div class='post'>
113
+ <h1><%= @post.title %></h1>
114
+
115
+ <p><%= @post.body %></p>
116
+ </div>
117
+
118
+ ```
119
+ In this case, we need to tell xhive how we are mounting our widgets routes:
120
+
121
+ ```
122
+ config/initializers/xhive.rb
123
+
124
+ Xhive::Router::Cells.draw do |router|
125
+ router.mount 'posts/:id', :to => 'posts#show'
126
+ end
127
+ ```
128
+
129
+ And that's it. You will now be able to insert the content of any post from within an HTML template using:
130
+
131
+ {% posts_show id:1234 %}
132
+
133
+ This tag will make the browser insert the post content asynchronously into the HTML document.
134
+
135
+ xhive will also enforce the tag to include the :id parameter.
136
+
137
+ ## CMS features
138
+
139
+ Ok, I can include my cells and controller actions as widgets, but... how?
140
+
141
+ xhive provides you with some basic CMS infrastructure.
142
+
143
+ ### Creating your first dynamic page
144
+
145
+ To be able to use your widgets, you have to follow the following steps:
146
+
147
+ Create a Site
148
+
149
+ ```
150
+ site = Xhive::Site.create(:name => 'My awesome blog', :domain => 'localhost')
151
+ ```
152
+
153
+ Create a Page
154
+
155
+ ```
156
+ page = Xhive::Page.create(:name => 'home',
157
+ :title => 'My blog page',
158
+ :content => '<h1>Home</h1><p>{% posts_show id:1 %}</p>',
159
+ :site => site)
160
+ ```
161
+
162
+ Start the server
163
+
164
+ Now you can access the page on http://localhost:3000/pages/home.
165
+
166
+ This should display the post with id: 1 inside the home page.
167
+
168
+ ### Adding pages to your own custom data
169
+
170
+ You can also use the xhive pages from within you own data.
171
+
172
+ xhive provides the Xhive::Mapper to wire up your resources to xhive pages.
173
+
174
+ Create a new page to display all the posts
175
+
176
+ ```
177
+ posts_page = Xhive::Page.create(:name => 'posts',
178
+ :title => 'Blog Posts',
179
+ :content => '{% for post in posts %}{% posts_show id:post.id %}{% endfor %}',
180
+ :site => site)
181
+ ```
182
+
183
+ Create a new stylesheet to display your posts:
184
+
185
+ ```
186
+ stylesheet = Xhive::Stylesheet.create(:name => 'Posts',
187
+ :content => '.post {
188
+ h1 { font-size: 20px; color: blue; }
189
+ p { font-size: 12px; color: #000; }
190
+ }',
191
+ :site => site)
192
+ ```
193
+
194
+ Create a new mapper record for the posts resources
195
+
196
+ ```
197
+ mapper = Xhive::Mapper.create(:resource => 'Post', :action => 'index', :page => posts_page)
198
+ ```
199
+
200
+ From your posts controller, render the posts page
201
+
202
+ ```
203
+ class PostsController < ApplicationController
204
+ def index
205
+ @posts = Post.all.limit(10)
206
+ render_page_for 'Post', 'index', :posts => @posts
207
+ end
208
+ end
209
+ ```
210
+
211
+ Using this feature you can let the designers implement the HTML/CSS to display the posts in your site without your intervention.
212
+
213
+ TODO
214
+ ====
215
+
216
+ * Implement the Image model
217
+ * Remove as many dependencies as possible
218
+ * Improve test coverage
219
+
220
+ Disclaimer
221
+ ==========
222
+ This is a work in progress and still a proof of concept. Use at your own risk :P.
223
+
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Xhive'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require_tree .
@@ -0,0 +1,22 @@
1
+ class @WidgetLoader
2
+ @load: ->
3
+ $widgets = []
4
+
5
+ $("[data-widget='true']").each((index) ->
6
+ $widget = $(this)
7
+ baseUrl = $widget.data('url')
8
+ args = $widget.data('params')
9
+ url = "#{baseUrl}?#{args}"
10
+ $widgets.push $.ajax({
11
+ url: url,
12
+ success: (data) ->
13
+ $widget.html(data)
14
+ $widget.attr('data-widget', 'false')
15
+ })
16
+ )
17
+
18
+ if $widgets.length > 0
19
+ $.when.apply(null, $widgets).then( ->
20
+ WidgetLoader.load()
21
+ )
22
+
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,5 @@
1
+ module Xhive
2
+ class ApplicationController < ActionController::Base
3
+ extend Xhive::Controller
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ require_dependency "xhive/application_controller"
2
+
3
+ module Xhive
4
+ class PagesController < ApplicationController
5
+ extend Xhive::Widgify
6
+
7
+ widgify :widget
8
+
9
+ before_filter :load_page
10
+
11
+ def show
12
+ end
13
+
14
+ def widget
15
+ render :show
16
+ end
17
+
18
+ private
19
+
20
+ def load_page
21
+ @page = current_site.pages.find(params[:id])
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ require_dependency "xhive/application_controller"
2
+
3
+ module Xhive
4
+ class StylesheetsController < ApplicationController
5
+ respond_to :css
6
+
7
+ def index
8
+ render :text => StylesheetPresenter.all_compressed(Stylesheet.all)
9
+ end
10
+
11
+ def show
12
+ @style = Stylesheet.find(params[:id])
13
+ render :text => @style.presenter.compressed
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require_dependency "xhive/application_controller"
2
+
3
+ module Xhive
4
+ class WidgetsController < ApplicationController
5
+ def show
6
+ # Looks for a route matching the request path
7
+ route = Xhive::Router::Route.find(request.path)
8
+ # Gets the parameters from the request path and the query string
9
+ parameters = route.params_from(request.path).merge(params).with_indifferent_access
10
+ # Renders the corresponding cell#action
11
+ render :text => render_cell(route.klass.underscore.to_sym, route.action.to_sym, parameters), :status => 200
12
+ rescue => e
13
+ render :text => 'Not found', :status => 404
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module Xhive
2
+ module ApplicationHelper
3
+ def initialize_widgets_loader
4
+ "<script type='text/javascript'>WidgetLoader.load()</script>".html_safe
5
+ end
6
+
7
+ def include_custom_stylesheets
8
+ "<link href='#{stylesheets_path}' media='all' rel='stylesheet' type='text/css'/>".html_safe
9
+ end
10
+
11
+ def render_page_for(resource, action, options={})
12
+ page = current_site.mappers.page_for(resource, action)
13
+ render :text => page.presenter.render_content(options)
14
+ end
15
+
16
+ def current_site
17
+ domain = request.host
18
+ @current_site ||= Site.where(:domain => domain).first || Site.first
19
+ fail "No Site defined. Please create a default Site." unless @current_site.present?
20
+ @current_site
21
+ end
22
+
23
+ # Private: Returns a safe user, e.i. a logged user or a guest user.
24
+ #
25
+ # This is just a placeholder and should be implemented in the host app.
26
+ #
27
+ # Example:
28
+ #
29
+ # def safe_user
30
+ # current_user || AnonymousUser.new
31
+ # end
32
+ #
33
+ # Returns: an anonymous user.
34
+ #
35
+ def safe_user
36
+ AnonymousUser.new
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ module Xhive
2
+ class AnonymousUser < Xhive::Hashy
3
+ include Xhive::Presentable
4
+ self.presenter_class = 'Xhive::UserPresenter'
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ module Xhive
2
+ class Mapper < ActiveRecord::Base
3
+ attr_accessible :action, :page, :site, :resource
4
+
5
+ belongs_to :site
6
+ belongs_to :page
7
+
8
+ validates :resource, :presence => true
9
+ validates :action, :presence => true
10
+ validates :site, :presence => true
11
+ validates :page, :presence => true
12
+
13
+ def self.page_for(resource, action)
14
+ page = where(:resource => resource).where(:action => action).first.try(:page)
15
+ fail ActiveRecord::RecordNotFound unless page.present?
16
+ page
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'friendly_id'
2
+
3
+ module Xhive
4
+ class Page < ActiveRecord::Base
5
+ extend ::FriendlyId
6
+ friendly_id :name, use: :slugged
7
+
8
+ include Xhive::Presentable
9
+
10
+ attr_accessible :content, :meta_description, :meta_keywords, :name, :slug, :title, :site
11
+
12
+ belongs_to :site
13
+
14
+ validates :name, :presence => true, :uniqueness => { :scope => :site_id }
15
+ validates :title, :presence => true
16
+ validates :content, :presence => true
17
+ validates :site, :presence => true
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module Xhive
2
+ class Site < ActiveRecord::Base
3
+ attr_accessible :domain, :name, :home_page
4
+
5
+ has_many :pages
6
+ has_many :mappers
7
+ has_many :stylesheets
8
+
9
+ belongs_to :home_page, :class_name => 'Page'
10
+
11
+ validates :name, :presence => true
12
+ validates :domain, :presence => true
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ require 'friendly_id'
2
+ require 'sass'
3
+
4
+ module Xhive
5
+ class Stylesheet < ActiveRecord::Base
6
+ extend ::FriendlyId
7
+ friendly_id :name, use: :slugged
8
+
9
+ include Xhive::Presentable
10
+
11
+ attr_accessible :content, :name, :slug, :site
12
+
13
+ belongs_to :site
14
+
15
+ validates :name, :presence => true, :uniqueness => { :scope => :site_id }
16
+ validates :content, :presence => true
17
+ validates :site, :presence => true
18
+ validate :css_syntax, :if => Proc.new { self.content.present? }
19
+
20
+ private
21
+
22
+ def css_syntax
23
+ engine = Sass::Engine.new(content, :syntax => :scss)
24
+ engine.render
25
+ rescue Sass::SyntaxError => e
26
+ errors.add(:content, e.message)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ module Xhive
2
+ class BasePresenter
3
+ attr_reader :object
4
+
5
+ include ActionView::Helpers
6
+ include ActionView::Context
7
+ include Rails.application.routes.url_helpers
8
+
9
+ default_url_options[:host] = (Rails.application.config.action_mailer.default_url_options || {}).fetch(:host, 'localhost')
10
+
11
+ def initialize(object)
12
+ @object = object
13
+ end
14
+
15
+ def id
16
+ @object.id
17
+ end
18
+
19
+ private
20
+
21
+ def controller
22
+ ApplicationController.current_controller
23
+ end
24
+
25
+ def self.presents(name)
26
+ define_method(name) do
27
+ @object
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ module Xhive
2
+ class PagePresenter < Xhive::BasePresenter
3
+ presents :page
4
+ delegate :name, :title, :content, :meta_keywords, :meta_description, :to => :page
5
+
6
+ liquid_methods :name, :title, :content, :meta_keywords, :meta_description
7
+
8
+ def render_content(options={})
9
+ layout = ::Liquid::Template.parse("{{content}}").render({"content" => page.content})
10
+ text = ::Liquid::Template.parse(layout).render(
11
+ {'page' => self, 'user' => controller.safe_user.presenter}.merge(options.stringify_keys),
12
+ :registers => {:controller => controller}
13
+ )
14
+ result = text.html_safe
15
+ rescue => e
16
+ logger.debug "#{e.class.name}: #{e.message}"
17
+ logger.debug e.backtrace.join("/n")
18
+ result = ''
19
+ ensure
20
+ return result
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module Xhive
2
+ class StylesheetPresenter < Xhive::BasePresenter
3
+ presents :stylesheet
4
+ delegate :name, :content, :to => :stylesheet
5
+
6
+ liquid_methods :name, :content, :compressed
7
+
8
+ def compressed
9
+ self.class.compress(stylesheet.content)
10
+ end
11
+
12
+ def self.all_compressed(stylesheets)
13
+ stylesheets.inject('') do |result, stylesheet|
14
+ result << compress(stylesheet.content)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ # Private: compress stylesheet content
21
+ #
22
+ # content - The string containing the stylesheet content
23
+ #
24
+ # Returns: the compressed CSS
25
+ #
26
+ def self.compress(content)
27
+ engine = Sass::Engine.new(content, :syntax => :scss, :style => :compressed)
28
+ engine.render
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ module Xhive
2
+ class UserPresenter < Xhive::BasePresenter
3
+ presents :user
4
+ delegate :email, :first_name, :last_name, :to => :user
5
+
6
+ liquid_methods :email, :first_name, :last_name
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= @title || 'Xhive' %></title>
5
+ <%= stylesheet_link_tag "xhive/application", :media => "all" %>
6
+ <%= javascript_include_tag "xhive/application" %>
7
+ <%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js" %>
8
+ <%= include_custom_stylesheets %>
9
+ <%= csrf_meta_tags %>
10
+ </head>
11
+ <body>
12
+ <%= yield %>
13
+ <%= initialize_widgets_loader %>
14
+ </body>
15
+ </html>
@@ -0,0 +1,2 @@
1
+ <%= @page.presenter.render_content %>
2
+
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ Xhive::Engine.routes.draw do
2
+ resources :pages, :only => :show do
3
+ get 'widget', :on => :member
4
+ end
5
+
6
+ get 'stylesheets/custom.css', :to => 'stylesheets#index', :as => :stylesheets, :format => :css
7
+
8
+ resources :stylesheets, :only => :show, :format => :css
9
+
10
+ get 'widgets/*widget', :to => 'widgets#show'
11
+
12
+ root :to => 'pages#show'
13
+ end