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
|
+
/ 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
|