feather_cms 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/README.md +46 -0
  4. data/Rakefile +1 -0
  5. data/feather_cms.gemspec +24 -0
  6. data/lib/feather_cms/config.rb +54 -0
  7. data/lib/feather_cms/model.rb +59 -0
  8. data/lib/feather_cms/railtie.rb +13 -0
  9. data/lib/feather_cms/template_cache.rb +52 -0
  10. data/lib/feather_cms/version.rb +3 -0
  11. data/lib/feather_cms/view_helper.rb +20 -0
  12. data/lib/feather_cms.rb +19 -0
  13. data/lib/generators/feather_cms/USAGE +10 -0
  14. data/lib/generators/feather_cms/feather_cms_generator.rb +63 -0
  15. data/lib/generators/feather_cms/templates/bootstrap.css +3992 -0
  16. data/lib/generators/feather_cms/templates/codemirror/codemirror.css +117 -0
  17. data/lib/generators/feather_cms/templates/codemirror/codemirror.js +2909 -0
  18. data/lib/generators/feather_cms/templates/codemirror/feather_cms.js +13 -0
  19. data/lib/generators/feather_cms/templates/codemirror/modes/css.js +124 -0
  20. data/lib/generators/feather_cms/templates/codemirror/modes/htmlmixed.js +83 -0
  21. data/lib/generators/feather_cms/templates/codemirror/modes/javascript.js +360 -0
  22. data/lib/generators/feather_cms/templates/codemirror/modes/xml.js +267 -0
  23. data/lib/generators/feather_cms/templates/codemirror/util/dialog.css +23 -0
  24. data/lib/generators/feather_cms/templates/codemirror/util/dialog.js +63 -0
  25. data/lib/generators/feather_cms/templates/codemirror/util/foldcode.js +186 -0
  26. data/lib/generators/feather_cms/templates/codemirror/util/formatting.js +294 -0
  27. data/lib/generators/feather_cms/templates/codemirror/util/javascript-hint.js +134 -0
  28. data/lib/generators/feather_cms/templates/codemirror/util/match-highlighter.js +44 -0
  29. data/lib/generators/feather_cms/templates/codemirror/util/overlay.js +51 -0
  30. data/lib/generators/feather_cms/templates/codemirror/util/runmode.js +49 -0
  31. data/lib/generators/feather_cms/templates/codemirror/util/search.js +114 -0
  32. data/lib/generators/feather_cms/templates/codemirror/util/searchcursor.js +117 -0
  33. data/lib/generators/feather_cms/templates/codemirror/util/simple-hint.css +16 -0
  34. data/lib/generators/feather_cms/templates/codemirror/util/simple-hint.js +68 -0
  35. data/lib/generators/feather_cms/templates/controller.rb +34 -0
  36. data/lib/generators/feather_cms/templates/form.html.erb +40 -0
  37. data/lib/generators/feather_cms/templates/index.html.erb +11 -0
  38. data/lib/generators/feather_cms/templates/initializer.rb +5 -0
  39. data/lib/generators/feather_cms/templates/layout.html.erb +52 -0
  40. data/lib/generators/feather_cms/templates/migration.rb +13 -0
  41. data/lib/generators/feather_cms/templates/model.rb +3 -0
  42. metadata +98 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in feather_cms.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Motivation
2
+ We have felt the pain of integrating static pages into a Rails application. There are plenty of gems available for this (Radiant, Locomotiv, etc.) but they are very heavy for what we need.
3
+
4
+ So, we built FeatherCMS. As the name suggests, its a Do-It-Yourself, lightweight CMS - just pages, caching and nothing more!
5
+
6
+ # Usage
7
+ Add the gem to your Gemfile
8
+
9
+ gem 'feather_cms'
10
+
11
+ Now, generate the pages
12
+
13
+ $ rake db:migrate
14
+
15
+ $ rails g feather_cms about_us jobs team
16
+
17
+ This generates a route, the controller action and the view for each page. Start the server and use the URL http://localhost:3000/feathers/pages to go to the admin panel.
18
+
19
+ This has basic HTTP authentication setup.The default username and password are feather/password and you can change this in feathers_controller.rb
20
+
21
+ http_basic_authenticate_with name: 'feather', password: 'password', except: :published
22
+
23
+ # Features
24
+
25
+ * Creates a route for each static page.
26
+ * Caching the static pages.
27
+ * Creates the view in app/views/feathers folder
28
+ * Easily customization FeathersController
29
+ * CodeMirror Editor for syntax highlighting. (Default: HTML)
30
+ * Storage is file (default) or database.
31
+
32
+ # Caveats
33
+ You may need to ensure that the public/system folder exists (for file storage)
34
+
35
+ # TODO
36
+
37
+ * Move the basic authentication to the config/initializers/feather_cms.rb
38
+ * Override the default authentication strategy from the controller
39
+ * Move the code from generated controller to the gem (if required)
40
+
41
+ # Contribute
42
+ Fork away and send me pull requests!
43
+
44
+ # License
45
+ The MIT license
46
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "feather_cms/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "feather_cms"
7
+ s.version = FeatherCms::VERSION
8
+ s.authors = ["Jiren Patel"]
9
+ s.email = ["jiren@joshsoftware.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Lightweight do it youself cms}
12
+ s.description = %q{Lightweight do it youself cms}
13
+
14
+ s.rubyforge_project = "feather_cms"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
@@ -0,0 +1,54 @@
1
+ module FeatherCms
2
+ class Config
3
+ class << self
4
+ attr_accessor :cache_max_limit, :cache_permanent_keys
5
+ attr_accessor :template_store_type
6
+
7
+ @@config = {
8
+ :template_store_path => 'templates',
9
+ :use_version => true,
10
+ :template_extenstion => 'html'
11
+ }
12
+
13
+ def init(&block)
14
+ yield self if block_given?
15
+
16
+ template_store_type = (template_store_type || :file).to_sym
17
+ FeatherCms::TemplateCache.init
18
+ Dir.mkdir(template_store_path) unless Dir.exists?(template_store_path)
19
+
20
+ if defined?(ActionView::Helpers)
21
+ ActionView::Helpers.send(:include, FeatherCms::ViewHelper)
22
+ end
23
+
24
+ if defined?(Rails)
25
+ @@config[:layouts] = Dir.entries(Rails.root.to_s + '/app/views/layouts').reject do |i|
26
+ i.start_with?('.', '_', 'feather_layout')
27
+ end.collect{|l| l.split('.').first}
28
+ end
29
+ end
30
+
31
+ def template_store_path=(value)
32
+ @@config[:template_store_path] = value
33
+ end
34
+
35
+ def template_store_path
36
+ @@config[:template_store_path]
37
+ end
38
+
39
+ def template_extenstion=(value)
40
+ @@config[:template_extenstion] = value
41
+ end
42
+
43
+ def template_extenstion
44
+ @@config[:template_extenstion]
45
+ end
46
+
47
+ def layouts
48
+ @@config[:layouts]
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,59 @@
1
+ module FeatherCms
2
+ module Model
3
+ module ClassMethods
4
+ def template_content_field(name)
5
+ _cms_content_fields_ << name
6
+ return unless Config.template_store_type == :file
7
+
8
+ attr_accessor name.to_sym
9
+
10
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
11
+ def #{name}
12
+ @#{name} || _cms_content(:#{name})
13
+ end
14
+ METHOD
15
+
16
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
17
+ def #{name}_changed?
18
+ @#{name} != _cms_content(:#{name})
19
+ end
20
+ METHOD
21
+ end
22
+
23
+ def _cms_content_fields_
24
+ @_cms_content_fields_ ||= []
25
+ end
26
+
27
+ def define_feather_cms_callbacks
28
+ after_destroy { |template|
29
+ self.class._cms_content_fields_.each do |f|
30
+ TemplateCache.delete_file(_template_path(f))
31
+ end
32
+ }
33
+
34
+ after_save { |template|
35
+ self.class._cms_content_fields_.each do |f|
36
+ TemplateCache.write_to_file_and_cache(send(f), template_name(f))
37
+ end
38
+ }
39
+ end
40
+ end
41
+
42
+ module InstanceMethods
43
+
44
+ def template_name(field_name)
45
+ "#{self.class.name.downcase}_#{field_name}_#{self.id}.#{Config.template_extenstion}"
46
+ end
47
+
48
+ def _template_path(field)
49
+ File.join([Config.template_store_path, template_name(file)])
50
+ end
51
+
52
+ def _cms_content(field)
53
+ return nil if self.id.nil?
54
+ TemplateCache.cache_file(template_name(field))
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails'
2
+
3
+ module FeatherCms
4
+ module Railtie
5
+ class Railtie < ::Rails::Railtie
6
+ if ::Rails.version.to_f >= 3.1
7
+ config.before_configuration do |app|
8
+ app.config.assets.paths << Rails.root.join("app", "assets", "codemirror")
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,52 @@
1
+ module FeatherCms
2
+ class TemplateCache
3
+ class << self
4
+
5
+ def init(options = {})
6
+ @@_cache ||= {}
7
+ @@options = options
8
+ end
9
+
10
+ def [](key)
11
+ @@_cache[key.to_s]
12
+ end
13
+
14
+ def []=(k,v)
15
+ @@_cache[k.to_s] = v
16
+ end
17
+
18
+ def cache_file(name)
19
+ return self[name] if exist?(name)
20
+
21
+ file = _file_path(name)
22
+ self[file] = File.read(file) if File.exist?(file)
23
+ end
24
+
25
+ def write_to_file_and_cache(content, file)
26
+ return if cache_file(file) == content
27
+ self[file] = content
28
+ File.open(_file_path(file), 'wb') {|f| f.write(content) }
29
+ end
30
+
31
+ def exist?(name)
32
+ @@_cache.key?(name.to_s)
33
+ end
34
+
35
+ def clear(name = nil)
36
+ name ? @@_cache.delete(name.to_s) : @@_cache.clear
37
+ end
38
+
39
+ def delete_file(name)
40
+ file = _file_path(name)
41
+ File.delete(file) if File.exist?(file)
42
+ @@_cache.delete(name)
43
+ end
44
+
45
+ private
46
+ def _file_path(name)
47
+ File.join([Config.template_store_path, name])
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module FeatherCms
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,20 @@
1
+ module FeatherCms
2
+ module ViewHelper
3
+ def feather_cms_include_tag
4
+ javascript_include_tag('codemirror', 'modes/htmlmixed', 'modes/javascript',
5
+ 'modes/xml', 'modes/css', 'feather_cms') +
6
+ stylesheet_link_tag('codemirror')
7
+ end
8
+
9
+ def feather_cms_template(object_name, method, options = {})
10
+ options[:class] = "#{options[:class]} codemirror_feather_cms"
11
+ text_area(object_name, method, options = {})
12
+ end
13
+
14
+ def feather_cms_template_tag(name, content = nil, options = {})
15
+ options[:class] = "#{options[:class]} codemirror_feather_cms"
16
+ text_area_tag(name, content = nil, options = {})
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ require "feather_cms/version"
2
+ require "feather_cms/template_cache"
3
+ require "feather_cms/config"
4
+ require "feather_cms/model"
5
+ require "feather_cms/view_helper"
6
+ require "feather_cms/railtie" if defined?(Rails)
7
+
8
+ module FeatherCms
9
+ include Model
10
+
11
+ def self.included(base)
12
+ base.extend FeatherCms::Model::ClassMethods
13
+ if Config.template_store_type == :file
14
+ base.define_feather_cms_callbacks
15
+ end
16
+ base.template_content_field :content
17
+ base.send(:include, FeatherCms::Model::InstanceMethods)
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ Description:
2
+ - Feather cms
3
+
4
+
5
+ Example:
6
+ rails generate feather_cms about_us jobs [storage=file or db]
7
+
8
+ This will create:
9
+ - Add config file 'feather_cms.eb'
10
+ - Add Codemirror javascript and css
@@ -0,0 +1,63 @@
1
+ class FeatherCmsGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+ argument :attributes, :type => :array, :banner => "about_us jobs"
4
+ argument :name, :type => :string, :default => "feather_cms", :required => false
5
+ argument :storage, :type => :string , :default => 'file'
6
+
7
+ def create_cms_files
8
+ @pages = attributes.collect(&:name)
9
+
10
+ unless ['file', 'db'].include?(storage)
11
+ puts "Valid storaage type are db,file"
12
+ storaage = 'file'
13
+ end
14
+ @storaage = storaage
15
+
16
+ template 'initializer.rb', 'config/initializers/feather_cms.rb'
17
+ template 'controller.rb', 'app/controllers/feathers_controller.rb'
18
+ template 'model.rb', 'app/models/feather_page.rb'
19
+
20
+ migration_file = Dir.glob("db/migrate/[0-9]*_*.rb").grep(/\d+_create_feather_pages.rb$/).first
21
+ migration_number = if migration_file
22
+ migration_file.gsub(/_create_feather_pages.rb|db|migrate|\//, '')
23
+ else
24
+ Time.now.utc.to_s.gsub(/[- :UTC]/, '')
25
+ end
26
+
27
+ template 'migration.rb', "db/migrate/#{migration_number}_create_feather_pages.rb"
28
+
29
+ route %{scope '/feathers' do
30
+ match 'page/:type/(:status)' => 'feathers#page', :as => :feather_page
31
+ get 'pages' => 'feathers#index', :as => :feather_pages
32
+ get 'preivew/:type/(:status)' => 'feathers#preivew', :as => 'feather_page_preview'
33
+ end
34
+ get 'page/:type' => 'feathers#published', :as => 'feather_published_page'}
35
+ end
36
+
37
+ def copy_view_files
38
+ @pages = attributes.collect(&:name)
39
+ base_path = File.join("app/views/feathers")
40
+ #empty_directory base_path
41
+ template 'layout.html.erb', 'app/views/layouts/feather_layout.html.erb'
42
+ template 'index.html.erb', File.join(base_path, 'index.html.erb')
43
+
44
+ @pages.each do |type|
45
+ @type = type
46
+ @path = File.join(base_path, "#{type}.html.erb")
47
+ template 'form.html.erb', @path
48
+ end
49
+ end
50
+
51
+ def add_static_files
52
+ if Rails.version > '3.0.9'
53
+ directory 'codemirror', 'app/assets/codemirror'
54
+ copy_file "bootstrap.css", 'app/assets/stylesheets/bootstrap.css'
55
+ else
56
+ directory 'codemirror', 'public/codemirror'
57
+ copy_file "bootstrap.css", 'public/stylesheets/bootstrap.css'
58
+ end
59
+ end
60
+
61
+
62
+
63
+ end