village 2.1.2
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/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
|
+
/ AddThis Button BEGIN
|
2
|
+
.addthis_toolbox.addthis_default_style
|
3
|
+
%a.addthis_button_facebook_like{"fb:like:layout" => "button_count"}
|
4
|
+
%a.addthis_button_tweet
|
5
|
+
%a.addthis_button_google_plusone{"g:plusone:size" => "medium"}
|
6
|
+
%a.addthis_counter.addthis_pill_style
|
7
|
+
%script{:src => "http://s7.addthis.com/js/250/addthis_widget.js#pubid=ra-4eade9351b25746b", :type => "text/javascript"}
|
8
|
+
/ AddThis Button END
|
@@ -0,0 +1,13 @@
|
|
1
|
+
- content_for :head do
|
2
|
+
- if Village::Config.google_analytics_code?
|
3
|
+
:plain
|
4
|
+
<script type="text/javascript">
|
5
|
+
var _gaq = _gaq || [];
|
6
|
+
_gaq.push(['_setAccount', '#{Village::Config.google_analytics_code}']);
|
7
|
+
_gaq.push(['_trackPageview']);
|
8
|
+
(function() {
|
9
|
+
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
10
|
+
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
11
|
+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
12
|
+
})();
|
13
|
+
</script>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
= content_tag_for :article, article do
|
2
|
+
%header
|
3
|
+
%h1= link_to article.title, article
|
4
|
+
= image_tag article.gravatar_url(:size => 32, :default => 'identicon'), :height => 32, :width => 32
|
5
|
+
.meta
|
6
|
+
%time{:pubdate => 'true', :datetime => article.timestamp.iso8601}
|
7
|
+
Posted on #{article.date.strftime '%e %B %Y'}
|
8
|
+
%span
|
9
|
+
by
|
10
|
+
= article.author[:name]
|
11
|
+
%p
|
12
|
+
- if article.categories?
|
13
|
+
Categories on:
|
14
|
+
- article.categories.each do |category|
|
15
|
+
= link_to category, village_articles_path(:category => category)
|
16
|
+
%p
|
17
|
+
- if article.tags?
|
18
|
+
Tags on:
|
19
|
+
- article.tags.each do |tag|
|
20
|
+
= link_to tag, village_articles_path(:tag => tag)
|
21
|
+
- if summary
|
22
|
+
= article.summary_html
|
23
|
+
%p.more= link_to 'Read more…'.html_safe, article
|
24
|
+
- else
|
25
|
+
~ article.content_html
|
@@ -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,72 @@
|
|
1
|
+
/* -- Reset ----------------------------------------------------------------- */
|
2
|
+
body,div,dl,dt,dd,ul,ol,li,h1,h2,h4,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0}
|
3
|
+
table{border-collapse:collapse;border-spacing:0}
|
4
|
+
fieldset,img{border:0}
|
5
|
+
address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit}
|
6
|
+
del,ins{text-decoration:none}
|
7
|
+
li{list-style:none}
|
8
|
+
caption,th{text-align:left}
|
9
|
+
h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400}
|
10
|
+
q:before,q:after{content:''}
|
11
|
+
abbr,acronym{border:0;font-variant:normal}
|
12
|
+
legend{color:#000}
|
13
|
+
input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit}
|
14
|
+
input,button,textarea,select{font-size:100%}
|
15
|
+
sup,sub{vertical-align:baseline}
|
16
|
+
header, sidebar, section, article, footer{display:block;}
|
17
|
+
|
18
|
+
/* -- Global ---------------------------------------------------------------- */
|
19
|
+
html{background:#F3F3F3;text-shadow:0px 1px 0px #fff;}
|
20
|
+
body{width:760px;margin:40px auto;font:14px/140% 'Helvetica Neue', Arial, Helvetica, Sans-Serif;}
|
21
|
+
a{color:#222;}
|
22
|
+
|
23
|
+
h1, h2, h3, h4, h5, h6{font-weight:bold;}
|
24
|
+
h1{font-size:26px;margin-bottom:5px;}
|
25
|
+
h1 a{text-decoration:none;}
|
26
|
+
h2{font-size:24px;padding-top:10px;margin:30px 0 20px;border-top:2px solid #ccc;}
|
27
|
+
h3{font-size:20px;margin-bottom:20px;}
|
28
|
+
h4{font-size:18px;margin-bottom:10px;}
|
29
|
+
h5, h6{font-size:16px;margin-bottom:5px;}
|
30
|
+
|
31
|
+
p{margin-bottom:20px;}
|
32
|
+
em{font-style:italic;}
|
33
|
+
sup{font-size:12px;vertical-align:super;}
|
34
|
+
sub{font-size:12px;vertical-align:sub;}
|
35
|
+
del{color:#666;font-style:line-through;}
|
36
|
+
abbr{border-bottom:1px dotted #bbb;color:#666;text-transform:uppercase;}
|
37
|
+
code{background:#eee;padding:2px 5px;font-family:Monospace;}
|
38
|
+
small{color:#999;font-size:12px;}
|
39
|
+
strong{font-weight:bold;}
|
40
|
+
blockquote{color:#666;font-size:16px;margin-left:20px;font-family:Georgia, Serif;}
|
41
|
+
|
42
|
+
/* code */
|
43
|
+
pre{background:#eee;margin-bottom:20px;padding:10px;border:1px solid #ccc;border-width:1px 0;}
|
44
|
+
|
45
|
+
/* lists */
|
46
|
+
ol, ul{margin:0 0 20px 20px;}
|
47
|
+
ol li{list-style:decimal inside;}
|
48
|
+
ul li{list-style:disc inside;}
|
49
|
+
|
50
|
+
/* -- Header ---------------------------------------------------------------- */
|
51
|
+
header#header {margin-bottom:40px;}
|
52
|
+
header#header h1 {font-size:42px;margin-bottom:20px;font-family:Georgia, Serif;font-weight:normal;}
|
53
|
+
header#header p {color:#999;}
|
54
|
+
|
55
|
+
/* -- Content --------------------------------------------------------------- */
|
56
|
+
section#content{}
|
57
|
+
|
58
|
+
section#content section article p{margin-bottom:10px;}
|
59
|
+
|
60
|
+
section#content article{margin-bottom:40px;}
|
61
|
+
section#content article header{overflow:hidden;}
|
62
|
+
section#content article header h1{}
|
63
|
+
section#content article header img{display:none;}
|
64
|
+
section#content article header .meta{color:#999;font-size:12px;}
|
65
|
+
|
66
|
+
/* -- Sidebar --------------------------------------------------------------- */
|
67
|
+
section#sidebar{position:absolute;top:10;right:0;margin-right:100px;}
|
68
|
+
section#sidebar ul{margin:0 0 3px 3px}
|
69
|
+
section#sidebar ul li{list-style:none inside;}
|
70
|
+
|
71
|
+
/* -- Footer ---------------------------------------------------------------- */
|
72
|
+
footer{margin-bottom:20px;}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title= Village::Config.title
|
5
|
+
= stylesheet_link_tag 'village'
|
6
|
+
= yield :head
|
7
|
+
%body
|
8
|
+
%header#header
|
9
|
+
%h1= link_to Village::Config.title, '/'
|
10
|
+
%p
|
11
|
+
= Village::Config.subtitle
|
12
|
+
%section#content
|
13
|
+
= yield
|
14
|
+
%footer
|
15
|
+
%small
|
16
|
+
- if Village::Config.author?
|
17
|
+
A #{link_to 'village', Village::Config.author[:url]} blog
|
18
|
+
= "by #{Village::Config.author[:name]}"
|
19
|
+
= "Copyright © #{Date.today.year}".html_safe
|
20
|
+
= link_to 'rss', village_articles_path(:rss)
|
21
|
+
|
|
22
|
+
= link_to 'atom', village_articles_path(:atom)
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# title & subtitle
|
2
|
+
# Title and subheading for your site. Used on the layout page and
|
3
|
+
# will be overriden in every page titles.
|
4
|
+
#
|
5
|
+
title: Your Site
|
6
|
+
subtitle: (change this text in config/village.yml)
|
7
|
+
|
8
|
+
# author
|
9
|
+
# You should really specify your content's author when generating an
|
10
|
+
# Atom feed. Specify at least one of name, uri or email, and Village will
|
11
|
+
# include it in your feed. See the Atom spec for more info:
|
12
|
+
#
|
13
|
+
# http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.feed
|
14
|
+
#
|
15
|
+
author:
|
16
|
+
name: Your Name
|
17
|
+
uri: http://yourhomepage.com
|
18
|
+
email: your@email.com
|
19
|
+
|
20
|
+
# layout
|
21
|
+
# The name of the layout file to be used by Village specified in "app/views/layouts",
|
22
|
+
# village will look for every pages / articles layouts for every request.
|
23
|
+
#
|
24
|
+
layout: "village"
|
25
|
+
|
26
|
+
# page_size
|
27
|
+
# the page size / PER_PAGE used by Kaminari for paginate your articles,
|
28
|
+
# the default is 5
|
29
|
+
#
|
30
|
+
# page_size: 5
|
31
|
+
|
32
|
+
# disqus_short_name
|
33
|
+
# If you want to use the Disqus service (http://disqus.com) to display
|
34
|
+
# comments on your site, register a Disqus account and then specify your
|
35
|
+
# site's short name here. A comment form will automatically be added to
|
36
|
+
# the bottom of your pages.
|
37
|
+
#
|
38
|
+
# disqus_short_name: mysite
|
39
|
+
|
40
|
+
# google_analytics_code
|
41
|
+
# Set this if you want Google Analytics to track traffic on your site.
|
42
|
+
# Probably best not to set a default value, but to set it in production.
|
43
|
+
#
|
44
|
+
# The production settings are used if you're deploying to Heroku, so
|
45
|
+
# scroll down a bit to set it in production even if you're not deploying
|
46
|
+
# to your own server.
|
47
|
+
#
|
48
|
+
# google_analytics_code: "UA-???????-?"
|
49
|
+
|
50
|
+
# -------------------------------
|
51
|
+
# ======== DEFAULT CONFIGURATIONS
|
52
|
+
# -------------------------------
|
53
|
+
#
|
54
|
+
# permalink_format
|
55
|
+
# Set this if you want change the default permalink_format
|
56
|
+
# the options are :
|
57
|
+
#
|
58
|
+
# "day" URL: http://localhost:3000/articles/2011/01/01/test-post
|
59
|
+
# "month" URL: http://localhost:3000/articles/2011/01/test-post
|
60
|
+
# "year" URL: http://localhost:3000/articles/2011/test-post
|
61
|
+
# "slug" URL: http://localhost:3000/articles/test-post
|
62
|
+
#
|
63
|
+
# the default village:articles will use permalink_format "day"
|
64
|
+
# You can also customize this throug route options
|
65
|
+
#
|
66
|
+
# permalink_format: day
|
67
|
+
|
68
|
+
# file_extensions
|
69
|
+
# Set this file_extensions which engine you want to use
|
70
|
+
# Village will accepts these formats :
|
71
|
+
#
|
72
|
+
# [ "erb", "rhtml", "erubis", "haml", "builder", "liquid",
|
73
|
+
# "markdown", "mkd", "md", "textile", "rdoc", "radius",
|
74
|
+
# "mab", "wiki", "mediawiki", "mw", "creole", "yajl" ]
|
75
|
+
#
|
76
|
+
# remember you have to set this settings with String
|
77
|
+
# inside an [Array]
|
78
|
+
# by default Village will accepts :markdown, :erb and :haml
|
79
|
+
#
|
80
|
+
# file_extensions: ["markdown", "erb", "haml"]
|
81
|
+
|
data/lib/village.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'gravtastic'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module Village
|
5
|
+
class Article < FileModel
|
6
|
+
include Gravtastic
|
7
|
+
is_gravtastic
|
8
|
+
|
9
|
+
CONTENT_PATH = "app/views/articles"
|
10
|
+
|
11
|
+
delegate :year, :month, :day, :to => :date
|
12
|
+
|
13
|
+
class Sanitizer < HTML::WhiteListSanitizer; self.allowed_tags -= %w(img a); end
|
14
|
+
|
15
|
+
TagHelper = Class.new.extend ActionView::Helpers::TagHelper
|
16
|
+
|
17
|
+
self.superclass.create_class_methods_on(Village::Article)
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def order
|
21
|
+
all.select(&:visible?).sort_by(&:date).reverse
|
22
|
+
end
|
23
|
+
|
24
|
+
def tags
|
25
|
+
@tags ||= all.map do |article|
|
26
|
+
article.tags if article.attributes[:tags].present?
|
27
|
+
end.compact.flatten.inject(Hash.new(0)) do |h,e|
|
28
|
+
h[e] += 1; h
|
29
|
+
end.inject({}) do |r, e|
|
30
|
+
r[e.first] = e.last; r
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def categories
|
35
|
+
@categories ||= all.map do |article|
|
36
|
+
article.categories if article.attributes[:categories].present?
|
37
|
+
end.compact.flatten.inject(Hash.new(0)) do |h,e|
|
38
|
+
h[e] += 1; h
|
39
|
+
end.inject({}) do |r, e|
|
40
|
+
r[e.first] = e.last; r
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def where(conditions = {})
|
45
|
+
conditions = conditions.symbolize_keys
|
46
|
+
conditions.assert_valid_keys :year, :month, :day, :slug, :to_param, :tag, :category
|
47
|
+
[:year, :month, :day].each do |key|
|
48
|
+
conditions[key] = conditions[key].to_i if conditions[key].present?
|
49
|
+
end
|
50
|
+
order.select do |article|
|
51
|
+
conditions.all? do |key, value|
|
52
|
+
case key
|
53
|
+
when :tag
|
54
|
+
article.tags.include?(value) if article.attributes[:tags].present?
|
55
|
+
when :category
|
56
|
+
article.categories.include?(value) if article.attributes[:categories].present?
|
57
|
+
else
|
58
|
+
article.send(key) == value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def feed
|
65
|
+
order.first(Village::Config.page_size)
|
66
|
+
end
|
67
|
+
|
68
|
+
def feed_last_modified
|
69
|
+
feed.first.try(:last_modified) || Time.now.utc
|
70
|
+
end
|
71
|
+
|
72
|
+
def reset!
|
73
|
+
@files = nil
|
74
|
+
@tags = nil
|
75
|
+
@categories = nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize(path)
|
80
|
+
super path
|
81
|
+
attributes[:permalink_format] = Village::Config.permalink_format
|
82
|
+
@date_str, @slug = File.basename(path).match(/^(\d+-\d+-\d+)-(.*)(\.[^.]+)$/).captures
|
83
|
+
end
|
84
|
+
|
85
|
+
def date
|
86
|
+
@date ||= Time.zone.parse(attributes[:date] || @date_str).to_date
|
87
|
+
end
|
88
|
+
|
89
|
+
def email
|
90
|
+
if attributes[:author] && attributes[:author][:email]
|
91
|
+
attributes[:author][:email]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def timestamp
|
96
|
+
date.to_time_in_current_zone
|
97
|
+
end
|
98
|
+
alias_method :last_modified, :timestamp
|
99
|
+
|
100
|
+
def visible?
|
101
|
+
timestamp <= Time.zone.now
|
102
|
+
end
|
103
|
+
|
104
|
+
def summary_html
|
105
|
+
if attributes[:summary].present?
|
106
|
+
TagHelper.content_tag :p, summary
|
107
|
+
else
|
108
|
+
html = Sanitizer.new.sanitize(content_html)
|
109
|
+
doc = Nokogiri::HTML.fragment(html)
|
110
|
+
para = doc.search('p').detect { |p| p.text.present? }
|
111
|
+
para.try(:to_html).try(:html_safe)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def to_param
|
116
|
+
case attributes[:permalink_format]
|
117
|
+
when :day then "%04d/%02d/%02d/%s" % [year, month, day, slug]
|
118
|
+
when :month then "%04d/%02d/%s" % [year, month, slug]
|
119
|
+
when :year then "%04d/%s" % [year, slug]
|
120
|
+
when :slug then slug
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|