feather_cms 0.0.1
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +46 -0
- data/Rakefile +1 -0
- data/feather_cms.gemspec +24 -0
- data/lib/feather_cms/config.rb +54 -0
- data/lib/feather_cms/model.rb +59 -0
- data/lib/feather_cms/railtie.rb +13 -0
- data/lib/feather_cms/template_cache.rb +52 -0
- data/lib/feather_cms/version.rb +3 -0
- data/lib/feather_cms/view_helper.rb +20 -0
- data/lib/feather_cms.rb +19 -0
- data/lib/generators/feather_cms/USAGE +10 -0
- data/lib/generators/feather_cms/feather_cms_generator.rb +63 -0
- data/lib/generators/feather_cms/templates/bootstrap.css +3992 -0
- data/lib/generators/feather_cms/templates/codemirror/codemirror.css +117 -0
- data/lib/generators/feather_cms/templates/codemirror/codemirror.js +2909 -0
- data/lib/generators/feather_cms/templates/codemirror/feather_cms.js +13 -0
- data/lib/generators/feather_cms/templates/codemirror/modes/css.js +124 -0
- data/lib/generators/feather_cms/templates/codemirror/modes/htmlmixed.js +83 -0
- data/lib/generators/feather_cms/templates/codemirror/modes/javascript.js +360 -0
- data/lib/generators/feather_cms/templates/codemirror/modes/xml.js +267 -0
- data/lib/generators/feather_cms/templates/codemirror/util/dialog.css +23 -0
- data/lib/generators/feather_cms/templates/codemirror/util/dialog.js +63 -0
- data/lib/generators/feather_cms/templates/codemirror/util/foldcode.js +186 -0
- data/lib/generators/feather_cms/templates/codemirror/util/formatting.js +294 -0
- data/lib/generators/feather_cms/templates/codemirror/util/javascript-hint.js +134 -0
- data/lib/generators/feather_cms/templates/codemirror/util/match-highlighter.js +44 -0
- data/lib/generators/feather_cms/templates/codemirror/util/overlay.js +51 -0
- data/lib/generators/feather_cms/templates/codemirror/util/runmode.js +49 -0
- data/lib/generators/feather_cms/templates/codemirror/util/search.js +114 -0
- data/lib/generators/feather_cms/templates/codemirror/util/searchcursor.js +117 -0
- data/lib/generators/feather_cms/templates/codemirror/util/simple-hint.css +16 -0
- data/lib/generators/feather_cms/templates/codemirror/util/simple-hint.js +68 -0
- data/lib/generators/feather_cms/templates/controller.rb +34 -0
- data/lib/generators/feather_cms/templates/form.html.erb +40 -0
- data/lib/generators/feather_cms/templates/index.html.erb +11 -0
- data/lib/generators/feather_cms/templates/initializer.rb +5 -0
- data/lib/generators/feather_cms/templates/layout.html.erb +52 -0
- data/lib/generators/feather_cms/templates/migration.rb +13 -0
- data/lib/generators/feather_cms/templates/model.rb +3 -0
- metadata +98 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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"
|
data/feather_cms.gemspec
ADDED
@@ -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,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
|
data/lib/feather_cms.rb
ADDED
@@ -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,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
|