thesis 0.0.1 → 0.0.4

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 (38) hide show
  1. data/README.md +147 -7
  2. data/lib/assets/javascripts/thesis/hallo.js +2949 -0
  3. data/lib/assets/javascripts/thesis/thesis.js.coffee +27 -0
  4. data/lib/assets/javascripts/thesis.js +2 -0
  5. data/lib/assets/stylesheets/thesis/thesis.css.scss +16 -0
  6. data/lib/assets/stylesheets/thesis.css +4 -0
  7. data/lib/generators/thesis/install/install_generator.rb +108 -0
  8. data/lib/generators/thesis/install/templates/migrations/create_page.rb +18 -0
  9. data/lib/generators/thesis/install/templates/migrations/create_page_content.rb +15 -0
  10. data/lib/generators/thesis/install/templates/page_templates/default.html.erb +38 -0
  11. data/lib/generators/thesis/install/templates/page_templates/default.html.haml +29 -0
  12. data/lib/generators/thesis/install/templates/page_templates/default.html.slim +29 -0
  13. data/lib/tasks/thesis_tasks.rake +4 -0
  14. data/lib/thesis/colorizer.rb +51 -0
  15. data/lib/thesis/controllers/controller_helpers.rb +39 -0
  16. data/lib/thesis/controllers/thesis_controller.rb +53 -0
  17. data/lib/thesis/engine.rb +5 -0
  18. data/lib/thesis/exceptions.rb +17 -0
  19. data/lib/thesis/models/page.rb +43 -0
  20. data/lib/thesis/models/page_content.rb +41 -0
  21. data/lib/thesis/railtie.rb +12 -0
  22. data/lib/thesis/routing/route_constraint.rb +7 -0
  23. data/lib/thesis/routing/routes.rb +10 -0
  24. data/lib/thesis/version.rb +1 -1
  25. data/lib/thesis.rb +10 -1
  26. data/spec/factories/page_contents.rb +7 -0
  27. data/spec/factories/pages.rb +9 -0
  28. data/spec/lib/thesis/controllers/thesis_controller_spec.rb +68 -0
  29. data/spec/lib/thesis/models/page_content_spec.rb +33 -0
  30. data/spec/lib/thesis/models/page_spec.rb +49 -0
  31. data/spec/spec_helper.rb +64 -0
  32. metadata +58 -14
  33. data/.gitignore +0 -17
  34. data/Gemfile +0 -4
  35. data/LICENSE.txt +0 -22
  36. data/Rakefile +0 -1
  37. data/lib/thesis/base.rb +0 -5
  38. data/thesis.gemspec +0 -19
@@ -0,0 +1,27 @@
1
+ Thesis =
2
+ setup: ->
3
+ if this.requirements()
4
+ this.bindings()
5
+
6
+
7
+ requirements: ->
8
+ if jQuery.ui
9
+ true
10
+ else
11
+ alert "jQuery UI not included. Thesis will not work properly without it."
12
+ false
13
+
14
+ page_is_editable: ->
15
+ $("#thesis-editor").length > 0
16
+
17
+ bindings: ->
18
+ thesis = $("#thesis-editor")
19
+ if thesis
20
+ thesis.append $("<div></div>").addClass("thesis-container")
21
+ .append $("<h3></h3>").text("Thesis Editor")
22
+
23
+
24
+ jQuery ($)->
25
+ Thesis.setup()
26
+
27
+ # window.Thesis = Thesis # Enable if necessary
@@ -0,0 +1,2 @@
1
+ //= require ./thesis/hallo
2
+ //= require ./thesis/thesis
@@ -0,0 +1,16 @@
1
+ #thesis-editor {
2
+ display: block;
3
+ width:100%;
4
+ clear:both;
5
+ height:100px;
6
+ background-color:#343434;
7
+ color:#ECECEC;
8
+ border:solid 2px #444444;
9
+
10
+ & .thesis-container {
11
+ max-width: 960px;
12
+ margin: 0 auto;
13
+ }
14
+ }
15
+
16
+
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= require_self
3
+ *= require_tree .
4
+ */
@@ -0,0 +1,108 @@
1
+ require 'rails/generators/migration'
2
+
3
+ module Thesis
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ desc "install or upgrade Thesis"
11
+
12
+ def self.next_migration_number(path)
13
+ unless @prev_migration_nr
14
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
15
+ else
16
+ @prev_migration_nr += 1
17
+ end
18
+ @prev_migration_nr.to_s
19
+ end
20
+
21
+ def copy_migrations
22
+ migration_template "migrations/create_page.rb", "db/migrate/create_page.rb"
23
+ migration_template "migrations/create_page_content.rb", "db/migrate/create_page_content.rb"
24
+ end
25
+
26
+ def create_folders
27
+ copy_file "page_templates/default.html.slim", "app/views/page_templates/default.html.slim" if Slim
28
+ copy_file "page_templates/default.html.haml", "app/views/page_templates/default.html.haml" if Haml
29
+ copy_file "page_templates/default.html.erb", "app/views/page_templates/default.html.erb" unless Haml || Slim
30
+ end
31
+
32
+ def set_up_routes
33
+ route "thesis_routes # This needs to be the last route!"
34
+ end
35
+
36
+ def install_js
37
+ filename = "app/assets/javascripts/application.js"
38
+ existing = File.binread("#{filename}").include?("require thesis")
39
+
40
+ if existing && generating?
41
+ say_status("skipped", "insert into #{filename}", :yellow)
42
+ else
43
+ insert_into_file "#{filename}", after: %r{//= require +['"]?jquery_ujs['"]?} do
44
+ "\n//= require jquery-ui" +
45
+ "\n//= require thesis"
46
+ end
47
+ end
48
+ end
49
+
50
+ def install_css
51
+ filename = "app/assets/stylesheets/application.css.scss"
52
+ existing = File.binread("#{filename}").include?("require thesis")
53
+
54
+ if existing && generating?
55
+ say_status("skipped", "insert into #{filename}", :yellow)
56
+ else
57
+ insert_into_file "#{filename}", after: %r{ *= require_self} do
58
+ "\n *= require thesis"
59
+ end
60
+ end
61
+ end
62
+
63
+ def install_page_is_editable
64
+ filename = "app/controllers/application_controller.rb"
65
+ existing = File.binread("#{filename}").include?("def page_is_editable?")
66
+
67
+ if existing && generating?
68
+ say_status("skipped", "insert into #{filename}", :yellow)
69
+ else
70
+ insert_into_file "#{filename}", after: %r{ protect_from_forgery} do
71
+ "\n" +
72
+ "\n # Thesis authentication" +
73
+ "\n def page_is_editable?(page)" +
74
+ "\n # Add your own criteria here for editing privileges. Examples:" +
75
+ "\n # current_user.admin? # Basic admin" +
76
+ "\n # can? :update, page # CanCan" +
77
+ "\n true # EVERYONE has access right now." +
78
+ "\n end"
79
+ end
80
+ end
81
+ end
82
+
83
+ def complete_message
84
+ require "thesis/colorizer"
85
+
86
+ if generating?
87
+ puts " "
88
+ puts " Thesis installed.".green
89
+ puts " Now run `rake db:migrate` to set up your database.".pink
90
+ else
91
+ puts " "
92
+ puts " Thesis uninstalled.".red
93
+ puts " You will need to remove the database tables manually if you've already run `rake db:migrate`.".pink
94
+ end
95
+ end
96
+
97
+ protected
98
+
99
+ def generating?
100
+ :invoke == behavior
101
+ end
102
+
103
+ def destroying?
104
+ :revoke == behavior
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,18 @@
1
+ class CreatePage < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :pages do |t|
4
+ t.integer :parent_id
5
+ t.string :name
6
+ t.string :slug
7
+ t.string :title
8
+ t.string :description
9
+ t.integer :sort_order, default: 0, null: false
10
+ t.string :template, default: "default", null: false
11
+ t.timestamps
12
+ end
13
+ end
14
+
15
+ def self.down
16
+ drop_table :pages
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ class CreatePageContent < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :page_contents do |t|
4
+ t.integer :page_id, null: false
5
+ t.string :name, null: false
6
+ t.text :content, default: "Edit This Content Area"
7
+ t.string :content_type, default: :html
8
+ t.timestamps
9
+ end
10
+ end
11
+
12
+ def self.down
13
+ drop_table :page_contents
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= current_page.title %></title>
5
+ <meta type="description" content="<%= current_page.content("Description", :text) %>" />
6
+
7
+ <%= stylesheet_link_tag "application", :media => "all" %>
8
+ <%= javascript_include_tag "application" %>
9
+ <%= csrf_meta_tags %>
10
+ </head>
11
+ <body>
12
+ <%= thesis_editor %>
13
+ <header>
14
+ <h1><%= current_page.title %></h1>
15
+ </header>
16
+
17
+ <nav>
18
+ <ul>
19
+ <% root_pages.each do |p| %>
20
+ <li><%= link_to p.name, p.path %></li>
21
+ <% end %>
22
+ </ul>
23
+ </nav>
24
+
25
+ <article>
26
+ <div class="main-image"><%= current_page.content("Main Image", :image) %></div>
27
+ <div class="content"><%= current_page.content("Main Content", :html) %></div>
28
+ </article>
29
+
30
+ <aside>
31
+ <%= current_page.content("Sidebar Content", :html) %>
32
+ </aside>
33
+
34
+ <footer>
35
+ <p><%= current_page.content("Footer Content", :text) %></p>
36
+ </footer>
37
+ </body>
38
+ </html>
@@ -0,0 +1,29 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= current_page.title
5
+ %meta{ content: current_page.content("Description", :text), type: "description" }
6
+
7
+ = stylesheet_link_tag "application", :media => "all"
8
+ = javascript_include_tag "application"
9
+ = csrf_meta_tags
10
+ %body
11
+ = thesis_editor
12
+
13
+ %header
14
+ %h1= current_page.title
15
+
16
+ %nav
17
+ %ul
18
+ - root_pages.each do |p|
19
+ %li= link_to p.name, p.path
20
+
21
+ %article
22
+ .main-image= current_page.content("Main Image", :image)
23
+ .content= current_page.content("Main Content", :html)
24
+
25
+ %aside
26
+ = current_page.content("Sidebar Content", :html)
27
+
28
+ %footer
29
+ %p= current_page.content("Footer Content", :text)
@@ -0,0 +1,29 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title= current_page.title
5
+ meta content=current_page.content("Description", :text) type="description"
6
+
7
+ = stylesheet_link_tag "application", :media => "all"
8
+ = javascript_include_tag "application"
9
+ = csrf_meta_tags
10
+ body
11
+ = thesis_editor
12
+
13
+ header
14
+ h1= current_page.title
15
+
16
+ nav
17
+ ul
18
+ - root_pages.each do |p|
19
+ li= link_to p.name, p.path
20
+
21
+ article
22
+ .main-image= current_page.content("Main Image", :image)
23
+ .content= current_page.content("Main Content", :html)
24
+
25
+ aside
26
+ = current_page.content("Sidebar Content", :html)
27
+
28
+ footer
29
+ p= current_page.content("Footer Content", :text)
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :thesis do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,51 @@
1
+ class String
2
+ # colorization
3
+ def colorize(color_code)
4
+ "\e[#{color_code}m#{self}\e[0m"
5
+ end
6
+
7
+ def red
8
+ colorize 31
9
+ end
10
+
11
+ def green
12
+ colorize 32
13
+ end
14
+
15
+ def yellow
16
+ colorize 33
17
+ end
18
+
19
+ def pink
20
+ colorize 35
21
+ end
22
+
23
+ def gray
24
+ colorize 37
25
+ end
26
+
27
+ def brown
28
+ colorize 33
29
+ end
30
+
31
+ def blue
32
+ colorize 34
33
+ end
34
+
35
+ def magenta
36
+ colorize 35
37
+ end
38
+
39
+ def cyan
40
+ colorize 36
41
+ end
42
+
43
+ def bold
44
+ colorize 1
45
+ end
46
+
47
+ def blink
48
+ colorize 5
49
+ end
50
+
51
+ end
@@ -0,0 +1,39 @@
1
+ module Thesis
2
+ module ControllerHelpers
3
+ module ClassMethods
4
+ def class_method_here
5
+ # Sample
6
+ end
7
+ end
8
+
9
+ def self.included(base)
10
+ raise ActiveRecordRequired.new("Currently, Thesis only works with ActiveRecord.") unless defined? ActiveRecord
11
+
12
+ # base.extend ClassMethods
13
+ # base.helper_method :class_method_here
14
+ end
15
+
16
+ def current_page
17
+ @current_page ||= Page.where(slug: request.fullpath).first
18
+ end
19
+
20
+ def root_pages
21
+ @root_pages ||= Page.where(parent_id: nil).order("sort_order ASC").all
22
+ end
23
+
24
+ def page_is_editable?(page)
25
+ raise RequiredMethodNotImplemented.new("Add a `page_is_editable?(page)` method to your controller that returns true or false.")
26
+ end
27
+
28
+ def thesis_editor
29
+ "<div id='thesis-editor'></div>".html_safe if page_is_editable?(current_page)
30
+ end
31
+ end
32
+ end
33
+
34
+ if defined? ActionController::Base
35
+ ActionController::Base.class_eval do
36
+ include Thesis::ControllerHelpers
37
+ helper_method :current_page, :root_pages, :page_is_editable?, :thesis_editor
38
+ end
39
+ end
@@ -0,0 +1,53 @@
1
+ module Thesis
2
+ class ThesisController < ActionController::Base
3
+ include ControllerHelpers
4
+
5
+ def show
6
+ raise ActionController::RoutingError.new('Not Found') unless current_page
7
+
8
+ if current_page.template && template_exists?("page_templates/#{current_page.template}")
9
+ render "page_templates/#{current_page.template}"
10
+ else
11
+ raise PageRequiresTemplate.new("Page requires a template but none was specified.")
12
+ end
13
+ end
14
+
15
+ def new_page
16
+ page = Page.new
17
+ return head :forbidden unless page_is_editable?(page)
18
+
19
+ update_page_attributes page
20
+
21
+ head page.save ? :ok : :not_acceptable
22
+ end
23
+
24
+ def update_page
25
+ page = current_page
26
+ return head :forbidden unless page_is_editable?(page)
27
+
28
+ update_page_attributes page
29
+
30
+ head page.save ? :ok : :not_acceptable
31
+ end
32
+
33
+ def page_attributes
34
+ [ :name, :title, :description, :parent_id ]
35
+ end
36
+
37
+ def update_page_attributes(page)
38
+ page_attributes.each { |a| page.send("#{a}=", params[a]) if params[a] }
39
+ page
40
+ end
41
+
42
+ protected
43
+
44
+ def page_is_editable?(page)
45
+ appcon = ApplicationController.new
46
+ if appcon.respond_to?("page_is_editable?")
47
+ appcon.page_is_editable?(page)
48
+ else
49
+ raise RequiredMethodNotImplemented.new("Add a `page_is_editable?(page)` method to your controller that returns true or false.")
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,5 @@
1
+ module Thesis
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Thesis
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ module Thesis
2
+ # A generic Thesis exception
3
+ class Error < StandardError; end
4
+
5
+ # When a required method is not implemented
6
+ class RequiredMethodNotImplemented < StandardError; end
7
+
8
+ # ActiveRecord is the only ORM that works with this currently
9
+ class ActiveRecordRequired < StandardError; end
10
+
11
+ # 404s
12
+ # class PageNotFound < ActionController::RoutingError; end
13
+
14
+ # No template specified
15
+ class PageRequiresTemplate < StandardError; end
16
+
17
+ end
@@ -0,0 +1,43 @@
1
+ module Thesis
2
+ class Page < ActiveRecord::Base
3
+ self.table_name = "pages"
4
+
5
+ belongs_to :parent, class_name: "Page"
6
+ has_many :subpages, class_name: "Page", foreign_key: "parent_id", order: "sort_order ASC"
7
+ has_many :page_contents
8
+
9
+ before_validation :update_slug
10
+ after_save :update_subpage_slugs
11
+
12
+ validates :slug, uniqueness: { message: "There's already a page like that. Change your page name." }, presence: true
13
+
14
+ def update_slug
15
+ self.slug = "/" << self.name.parameterize
16
+ self.slug = "#{parent.slug.to_s}#{self.slug.to_s}" if parent
17
+ end
18
+
19
+ def update_subpage_slugs
20
+ subpages.each(&:save) if slug_changed?
21
+ end
22
+
23
+ def content(name, content_type = :html)
24
+ pc = find_or_create_page_content(name, content_type)
25
+ pc.render
26
+ end
27
+
28
+ def path
29
+ self.slug
30
+ end
31
+
32
+ protected
33
+
34
+ def find_or_create_page_content(name, content_type)
35
+ page_content = self.page_contents.where(name: name).first_or_create do |pc|
36
+ pc.content = "Edit This Area"
37
+ end
38
+ page_content.content_type = content_type
39
+ page_content.save if page_content.changed?
40
+ page_content
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ module Thesis
2
+ class PageContent < ActiveRecord::Base
3
+ self.table_name = "page_contents"
4
+
5
+ belongs_to :page
6
+
7
+ def render
8
+ case self.content_type.to_sym
9
+ when :html
10
+ render_html
11
+ when :text
12
+ render_text
13
+ else
14
+ render_html
15
+ end
16
+ end
17
+
18
+ protected
19
+
20
+ def render_html
21
+ h = "<div class='thesis-content thesis-content-html' data-thesis-content-id='#{self.id}'>" +
22
+ "#{self.content}" +
23
+ "</div>"
24
+ h.html_safe
25
+ end
26
+
27
+ def render_text
28
+ h = "<span class='thesis-content thesis-content-text' data-thesis-content-id='#{self.id}'>" +
29
+ "#{self.content}" +
30
+ "</span>"
31
+ h.html_safe
32
+ end
33
+
34
+ def render_image
35
+ h = "<div class='thesis-content thesis-content-image'>" +
36
+ "<img src='#{self.content}' />" +
37
+ "</div>"
38
+ h.html_safe
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,12 @@
1
+ require 'thesis'
2
+ require 'rails'
3
+
4
+ module Thesis
5
+ class Railtie < Rails::Railtie
6
+ railtie_name :thesis
7
+
8
+ rake_tasks do
9
+ # load File.join(File.dirname(__FILE__), "tasks/db.rake") # Load rake tasks here
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module Thesis
2
+ class RouteConstraint
3
+ def self.matches?(request)
4
+ Page.where(slug: request.path.to_s).select("id").first.present?
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+ def thesis_routes
4
+ # Page crud (AJAX)
5
+ post "thesis/new_page", "thesis/thesis#new_page"
6
+
7
+ get "*slug" => 'thesis/thesis#show', constraints: ::Thesis::RouteConstraint
8
+ end
9
+ end
10
+ end
@@ -1,3 +1,3 @@
1
1
  module Thesis
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/thesis.rb CHANGED
@@ -1,5 +1,14 @@
1
+ require "thesis/engine"
1
2
  require "thesis/version"
2
- require "thesis/base"
3
+ require "thesis/exceptions"
4
+ require "thesis/controllers/controller_helpers" # Included into ActionController::Base
5
+ require "thesis/controllers/thesis_controller"
6
+ require "thesis/routing/route_constraint"
7
+ require "thesis/routing/routes"
8
+
9
+ # Models
10
+ require "thesis/models/page"
11
+ require "thesis/models/page_content"
3
12
 
4
13
  module Thesis
5
14
  end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :page_content, class: Thesis::PageContent do
3
+ name "Content Block"
4
+ content "<h1>Some Header</h1><p>A little paragraph.</p>"
5
+ content_type "html"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+ factory :page, class: Thesis::Page do
3
+ name "Some Page"
4
+ slug "some-page"
5
+ title "An Awesome Page"
6
+ description "A description goes here"
7
+ template "default"
8
+ end
9
+ end