village 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +29 -0
- data/Guardfile +9 -0
- data/MIT-LICENSE +20 -0
- data/README.md +255 -0
- data/Rakefile +29 -0
- data/app/controllers/village/articles_controller.rb +27 -0
- data/app/controllers/village/pages_controller.rb +16 -0
- data/app/views/layouts/village.html.haml +22 -0
- data/app/views/village/articles/_addthis.html.haml +8 -0
- data/app/views/village/articles/_analytics.html.haml +13 -0
- data/app/views/village/articles/_article.html.haml +25 -0
- data/app/views/village/articles/_comments.html.haml +8 -0
- data/app/views/village/articles/_feed_link.html.haml +2 -0
- data/app/views/village/articles/_sidebar.html.haml +13 -0
- data/app/views/village/articles/index.atom.builder +26 -0
- data/app/views/village/articles/index.html.haml +11 -0
- data/app/views/village/articles/index.rss.builder +31 -0
- data/app/views/village/articles/show.html.haml +9 -0
- data/app/views/village/pages/show.html.haml +1 -0
- data/lib/generators/base.rb +178 -0
- data/lib/generators/village/articles/USAGE +6 -0
- data/lib/generators/village/articles/articles_generator.rb +50 -0
- data/lib/generators/village/setup/USAGE +5 -0
- data/lib/generators/village/setup/setup_generator.rb +67 -0
- data/lib/generators/village/setup/templates/2001-01-01-example-article.markdown +8 -0
- data/lib/generators/village/setup/templates/example-page.markdown +10 -0
- data/lib/generators/village/setup/templates/views/articles/_addthis.html.haml +8 -0
- data/lib/generators/village/setup/templates/views/articles/_analytics.html.haml +13 -0
- data/lib/generators/village/setup/templates/views/articles/_article.html.haml +25 -0
- data/lib/generators/village/setup/templates/views/articles/_comments.html.haml +8 -0
- data/lib/generators/village/setup/templates/views/articles/_feed_link.html.haml +2 -0
- data/lib/generators/village/setup/templates/views/articles/_sidebar.html.haml +13 -0
- data/lib/generators/village/setup/templates/views/articles/index.atom.builder +26 -0
- data/lib/generators/village/setup/templates/views/articles/index.html.haml +11 -0
- data/lib/generators/village/setup/templates/views/articles/index.rss.builder +31 -0
- data/lib/generators/village/setup/templates/views/articles/show.html.haml +9 -0
- data/lib/generators/village/setup/templates/views/pages/show.html.haml +1 -0
- data/lib/generators/village/setup/templates/views/village.css +72 -0
- data/lib/generators/village/setup/templates/views/village.html.haml +22 -0
- data/lib/generators/village/setup/templates/village_config.yml +81 -0
- data/lib/village.rb +4 -0
- data/lib/village/article.rb +125 -0
- data/lib/village/attributes.rb +21 -0
- data/lib/village/config.rb +53 -0
- data/lib/village/engine.rb +11 -0
- data/lib/village/file_model.rb +83 -0
- data/lib/village/page.rb +10 -0
- data/lib/village/routes.rb +16 -0
- metadata +158 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
- if Village::Config.disqus_short_name?
|
2
|
+
#disqus_thread
|
3
|
+
- if ENV['RAILS_ENV'] == :development
|
4
|
+
:javascript
|
5
|
+
var disqus_developer = true;
|
6
|
+
%script{:type => 'text/javascript', :src => "http://#{Village::Config.disqus_short_name}.disqus.com/embed.js", :async => true}
|
7
|
+
%noscript
|
8
|
+
%a(href="http://#{Village::Config.disqus_short_name}.disqus.com/embed.js?url=ref") View comments.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%h4
|
2
|
+
Categories
|
3
|
+
- unless Village::Article.categories.nil?
|
4
|
+
%ul
|
5
|
+
- Village::Article.categories.each do |category|
|
6
|
+
%li= link_to "#{category[0]} (#{category[1]})", village_articles_path(:category => category[0])
|
7
|
+
|
8
|
+
%h4
|
9
|
+
Tags
|
10
|
+
- unless Village::Article.tags.nil?
|
11
|
+
%ul
|
12
|
+
- Village::Article.tags.each do |tag|
|
13
|
+
%li= link_to "#{tag[0]} (#{tag[1]})", village_articles_path(:tag => tag[0])
|
@@ -0,0 +1,26 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.feed :xmlns => 'http://www.w3.org/2005/Atom' do
|
3
|
+
xml.title Village::Config.title
|
4
|
+
xml.link village_articles_url(:format => :atom)
|
5
|
+
xml.id village_articles_url
|
6
|
+
xml.updated Village::Article.feed_last_modified.xmlschema
|
7
|
+
|
8
|
+
Village::Article.feed.each do |article|
|
9
|
+
xml.entry do
|
10
|
+
xml.title article.title, :type => :text
|
11
|
+
xml.link :href => village_article_url(article), :rel => :alternate, :type => 'text/html'
|
12
|
+
xml.published article.timestamp.xmlschema
|
13
|
+
xml.updated article.last_modified.xmlschema
|
14
|
+
if article.author?
|
15
|
+
xml.author do
|
16
|
+
xml.name article.author[:name]
|
17
|
+
xml.email article.author[:email]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
xml.id village_article_url(article)
|
21
|
+
xml.content :type => :html, 'xml:base' => village_article_url(article) do
|
22
|
+
xml.cdata! article.content_html
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
= render 'analytics'
|
2
|
+
= render 'feed_link'
|
3
|
+
%section#sidebar
|
4
|
+
= render 'sidebar'
|
5
|
+
|
6
|
+
%section#articles
|
7
|
+
- if collection.present?
|
8
|
+
= render :partial => 'article', :collection => collection, :locals => { :summary => true }
|
9
|
+
= paginate collection
|
10
|
+
- else
|
11
|
+
No articles found.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
xml.instruct! :xml, :version => "1.0"
|
2
|
+
xml.rss :version => "2.0" do
|
3
|
+
xml.channel do
|
4
|
+
xml.title Village::Config.title
|
5
|
+
xml.description Village::Config.subtitle
|
6
|
+
xml.link village_articles_url(:format => :rss)
|
7
|
+
xml.generator village_articles_url(:format => :rss)
|
8
|
+
xml.lastBuildDate Village::Article.feed_last_modified
|
9
|
+
|
10
|
+
for article in Village::Article.feed
|
11
|
+
xml.item do
|
12
|
+
xml.title article.title
|
13
|
+
xml.description :type => :html, 'xml:base' => village_article_url(article) do
|
14
|
+
xml.cdata! article.summary_html
|
15
|
+
end
|
16
|
+
xml.pubDate article.timestamp.xmlschema
|
17
|
+
xml.link :href => village_article_url(article), :rel => :alternate, :type => 'text/html'
|
18
|
+
xml.guid village_article_url(article)
|
19
|
+
if article.author.present?
|
20
|
+
xml.author do
|
21
|
+
xml.name article.author[:name]
|
22
|
+
xml.email article.author[:email]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
if article.tags?
|
26
|
+
xml.category article.tags.join(",")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
~ @resource.content_html
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'bundler'
|
3
|
+
require 'bundler/dsl'
|
4
|
+
|
5
|
+
module Village
|
6
|
+
module Generators
|
7
|
+
class Base < Rails::Generators::Base #:nodoc:
|
8
|
+
|
9
|
+
def self.source_root
|
10
|
+
@_village_source_root = File.expand_path(File.join(File.dirname(__FILE__), 'village', generator_name, 'templates'))
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.banner
|
14
|
+
"rails generate village:#{generator_name} #{self.arguments.map{ |a| a.usage }.join(' ')} [options]"
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def root_path(path)
|
20
|
+
File.expand_path(File.join(File.dirname(__FILE__), 'village', path))
|
21
|
+
end
|
22
|
+
|
23
|
+
def destination_path(path)
|
24
|
+
File.join(destination_root, path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_exists?(path)
|
28
|
+
File.exist? destination_path(path)
|
29
|
+
end
|
30
|
+
|
31
|
+
def folder_exists?(path)
|
32
|
+
File.directory? path
|
33
|
+
end
|
34
|
+
|
35
|
+
def class_exists?(class_name)
|
36
|
+
klass = Rails.application.class.parent_name.constantize.const_get(class_name)
|
37
|
+
return klass.is_a?(Class)
|
38
|
+
rescue NameError
|
39
|
+
return false
|
40
|
+
end
|
41
|
+
|
42
|
+
def extract(filepath,destinationpath,foldername)
|
43
|
+
begin
|
44
|
+
print_notes("Extracting #{filepath}")
|
45
|
+
system("tar -C '#{destination_path(destinationpath)}' -xzf '#{root_path(filepath)}' #{foldername}/")
|
46
|
+
rescue Exception => e
|
47
|
+
raise e
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def asking(messages,&block)
|
52
|
+
opt = ask("=> #{messages} [yes]")
|
53
|
+
if opt == "yes" || opt.blank?
|
54
|
+
yield
|
55
|
+
end
|
56
|
+
rescue Exception => e
|
57
|
+
raise e
|
58
|
+
end
|
59
|
+
|
60
|
+
def print_notes(message,notes = "notes",color = :yellow)
|
61
|
+
unless message.blank?
|
62
|
+
puts '', '='*80
|
63
|
+
say_status "#{notes}", "#{message}", color
|
64
|
+
puts '='*80, ''; sleep 0.5
|
65
|
+
else
|
66
|
+
puts "\n"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def print_usage
|
71
|
+
self.class.help(Thor::Base.shell.new)
|
72
|
+
exit
|
73
|
+
end
|
74
|
+
|
75
|
+
def install_local_gem(name,version = nil)
|
76
|
+
::Bundler.with_clean_env do
|
77
|
+
if version
|
78
|
+
`gem install #{name} -v=#{version}`
|
79
|
+
else
|
80
|
+
`gem install #{name}`
|
81
|
+
end
|
82
|
+
end
|
83
|
+
$? == 0 ? true : false
|
84
|
+
rescue Exception => e
|
85
|
+
raise e
|
86
|
+
end
|
87
|
+
|
88
|
+
def check_local_gem?(name,version = nil)
|
89
|
+
::Bundler.with_clean_env do
|
90
|
+
if version
|
91
|
+
`gem list #{name} -i -v=#{version}`
|
92
|
+
else
|
93
|
+
`gem list #{name} -i`
|
94
|
+
end
|
95
|
+
end
|
96
|
+
$? == 0 ? true : false
|
97
|
+
rescue Exception => e
|
98
|
+
raise e
|
99
|
+
end
|
100
|
+
|
101
|
+
def refresh_bundle
|
102
|
+
::Bundler.with_clean_env do
|
103
|
+
`bundle`
|
104
|
+
end
|
105
|
+
rescue Exception => e
|
106
|
+
raise e
|
107
|
+
end
|
108
|
+
|
109
|
+
def gemfile_included?(name)
|
110
|
+
::Bundler.with_clean_env do
|
111
|
+
`bundle show #{name}`
|
112
|
+
end
|
113
|
+
$?.exitstatus == 0 ? true : false
|
114
|
+
rescue Exception => e
|
115
|
+
raise e
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_required_gems?(*names)
|
119
|
+
names.each do |name|
|
120
|
+
return false unless gemfile_included? name
|
121
|
+
end
|
122
|
+
true
|
123
|
+
rescue Exception => e
|
124
|
+
raise e
|
125
|
+
end
|
126
|
+
|
127
|
+
def check_some_gems?(*names)
|
128
|
+
names.each do |name|
|
129
|
+
return true if gemfile_included? name
|
130
|
+
end
|
131
|
+
false
|
132
|
+
rescue Exception => e
|
133
|
+
raise e
|
134
|
+
end
|
135
|
+
|
136
|
+
def rails_3_1?
|
137
|
+
Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR >= 1
|
138
|
+
end
|
139
|
+
|
140
|
+
def copy_asset(source, *args, &block)
|
141
|
+
if rails_3_1?
|
142
|
+
if args.first =~ /^public/
|
143
|
+
args.first.gsub!(/^public/,"app/assets")
|
144
|
+
end
|
145
|
+
if args.first.include?("javascripts/application.js") or args.first.include?("stylesheets/application.css")
|
146
|
+
last_line = IO.readlines(args.first).last
|
147
|
+
content = IO.read(File.expand_path(find_in_source_paths(source.to_s)))
|
148
|
+
content.gsub!(/images/,"assets")
|
149
|
+
inject_into_file args.first, :after => last_line do
|
150
|
+
content
|
151
|
+
end
|
152
|
+
return
|
153
|
+
end
|
154
|
+
end
|
155
|
+
copy_file(source, *args, &block)
|
156
|
+
end
|
157
|
+
|
158
|
+
def remove_asset(path, config={})
|
159
|
+
if rails_3_1?
|
160
|
+
if path =~ /^public/
|
161
|
+
path.gsub!(/^public/,"app/assets")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
remove_asset(path, config)
|
165
|
+
end
|
166
|
+
|
167
|
+
def rails_app_name
|
168
|
+
Rails.application.class.name.split('::')[0..-2].join.titleize
|
169
|
+
end
|
170
|
+
|
171
|
+
def git_config(name)
|
172
|
+
value = `git config --get #{name}`.chomp
|
173
|
+
value if $?.success?
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'generators/base'
|
2
|
+
|
3
|
+
module Village
|
4
|
+
module Generators
|
5
|
+
class ArticlesGenerator < Base
|
6
|
+
|
7
|
+
argument :slug, :type => :string, :required => true
|
8
|
+
class_option :date, :type => :string, :group => :runtime, :desc => 'Publish date for the article'
|
9
|
+
|
10
|
+
def check_slug
|
11
|
+
unless slug =~ /^[A-Za-z0-9\-\.]+$/
|
12
|
+
puts 'Invalid slug - valid characters include letters, digits and dashes.'
|
13
|
+
exit
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_date
|
18
|
+
if options.date && options.date !~ /^\d{4}-\d{2}-\d{2}$/
|
19
|
+
puts 'Invalid date - please use the following format: YYYY-MM-DD, eg. 2011-01-01.'
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def generate_article
|
25
|
+
@date_str, @slug, @extension = File.basename(filename).match(/^(\d+-\d+-\d+)-(.*)(\.[^.]+)$/).captures
|
26
|
+
create_file "app/views/articles/#{@date_str}-#{@slug}#{@extension}" do
|
27
|
+
"---\n" +
|
28
|
+
"title: #{@slug.titleize}\n" +
|
29
|
+
"summary: summary goes here ...\n" +
|
30
|
+
"categories: ['category']\n" +
|
31
|
+
"tags: ['tag']\n" +
|
32
|
+
"---\n\n" +
|
33
|
+
"CONTENT GOES HERE ..."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def filename
|
40
|
+
"#{publish_date}-#{slug.downcase}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def publish_date
|
44
|
+
date = options.date.present? ? Time.zone.parse(options.date) : Time.zone.now
|
45
|
+
date.strftime('%Y-%m-%d')
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'generators/base'
|
2
|
+
|
3
|
+
module Village
|
4
|
+
module Generators
|
5
|
+
class SetupGenerator < Base #:nodoc:
|
6
|
+
|
7
|
+
class_option :pages, :desc => 'Setup village:pages for static pages', :type => :boolean, :default => true
|
8
|
+
class_option :articles, :desc => 'Setup village:articles for blog engine', :type => :boolean, :default => true
|
9
|
+
|
10
|
+
def setup
|
11
|
+
template 'village_config.yml', 'config/village_config.yml'
|
12
|
+
gem "haml-rails"
|
13
|
+
refresh_bundle
|
14
|
+
setup_pages if options.pages
|
15
|
+
setup_articles if options.articles
|
16
|
+
setup_markdown
|
17
|
+
rescue Exception => e
|
18
|
+
print_notes(e.message,"error",:red)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def setup_pages
|
23
|
+
asking "would you like to setup village:pages for static page?" do
|
24
|
+
empty_directory "app/views/pages"
|
25
|
+
route "village :pages"
|
26
|
+
copy_file 'example-page.markdown', 'app/views/pages/example-page.markdown'
|
27
|
+
asking "would you to copy village:pages views application directory?" do
|
28
|
+
empty_directory "app/views/village/pages/"
|
29
|
+
directory "views/pages", "app/views/village/pages/", :recursive => true
|
30
|
+
copy_file 'views/village.html.haml', 'app/views/layouts/village.html.haml', :force => true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def setup_articles
|
36
|
+
asking "would you like to setup village:articles for blog engine?" do
|
37
|
+
empty_directory "app/views/articles"
|
38
|
+
copy_asset 'views/village.css', 'public/stylesheets/village.css'
|
39
|
+
print_notes "copied default village stylesheets.css you can change it later!"
|
40
|
+
copy_file '2001-01-01-example-article.markdown', 'app/views/articles/2001-01-01-example-article.markdown'
|
41
|
+
route "village :articles"
|
42
|
+
gem "kaminari"
|
43
|
+
refresh_bundle
|
44
|
+
asking "would you to copy village:articles views directory?" do
|
45
|
+
empty_directory "app/views/village/articles/"
|
46
|
+
directory "views/articles", "app/views/village/articles/", :recursive => true
|
47
|
+
copy_file 'views/village.html.haml', 'app/views/layouts/village.html.haml', :force => true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def setup_markdown
|
53
|
+
markdown = ["RDiscount", "Redcarpet", "BlueCloth", "Kramdown", "Maruku"]
|
54
|
+
unless check_some_gems?(*markdown.map { |m| m.downcase })
|
55
|
+
puts "Please choose markdown engine you wish to use:"
|
56
|
+
markdown.each_with_index { |value,index| puts "#{index+1}.#{value}" }
|
57
|
+
mkd = ask(">")
|
58
|
+
markdown.each_with_index do |value,index|
|
59
|
+
gem "#{value.downcase}" if (index + 1) == mkd.to_i
|
60
|
+
end
|
61
|
+
refresh_bundle
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
---
|
2
|
+
title: Example Article
|
3
|
+
tags: ["Example", "Markdown"]
|
4
|
+
---
|
5
|
+
|
6
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
7
|
+
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
---
|
2
|
+
title: "Example Page"
|
3
|
+
keywords: ["sooner", "you", "like"]
|
4
|
+
---
|
5
|
+
|
6
|
+
# Another Header
|
7
|
+
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
9
|
+
|
10
|
+
[Reference](http://daringfireball.net/projects/markdown/syntax)
|