blabs 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +15 -0
- data/app/assets/images/uploadify-cancel.png +0 -0
- data/app/assets/images/uploadify.swf +0 -0
- data/app/assets/javascripts/blabs.js +79 -0
- data/app/assets/javascripts/jquery.uploadify.min.js +16 -0
- data/app/assets/stylesheets/blabs/blog.sass +6 -0
- data/app/assets/stylesheets/uploadify.css.scss +92 -0
- data/app/controllers/blabs/blog_posts_controller.rb +131 -0
- data/app/controllers/blabs/images_controller.rb +35 -0
- data/app/controllers/blabs/published_blog_posts_controller.rb +30 -0
- data/app/controllers/blabs_controller.rb +31 -0
- data/app/helpers/blabs/blog_posts_helper.rb +114 -0
- data/app/models/blabs/blog_post.rb +70 -0
- data/app/models/blabs/image.rb +4 -0
- data/app/models/blabs/tag.rb +9 -0
- data/app/models/blabs/tagging.rb +9 -0
- data/app/uploaders/image_uploader.rb +65 -0
- data/app/views/blabs/blog_posts/_form.html.haml +54 -0
- data/app/views/blabs/blog_posts/_image.html.haml +5 -0
- data/app/views/blabs/blog_posts/_image_panel.html.haml +32 -0
- data/app/views/blabs/blog_posts/edit.html.haml +7 -0
- data/app/views/blabs/blog_posts/feed.atom.builder +15 -0
- data/app/views/blabs/blog_posts/index.html.haml +27 -0
- data/app/views/blabs/blog_posts/new.html.haml +7 -0
- data/app/views/blabs/blog_posts/show.html.haml +16 -0
- data/app/views/layouts/blabs.html.erb +21 -0
- data/config/routes.rb +16 -0
- data/db/migrate/20130802113537_create_blabs_tables.rb +23 -0
- data/db/migrate/20130909092406_add_extract_to_blog_posts.rb +5 -0
- data/db/migrate/20131209144117_create_tags.rb +16 -0
- data/lib/blabs.rb +53 -0
- data/lib/blabs/engine.rb +13 -0
- data/lib/blabs/version.rb +3 -0
- data/lib/generators/blabs_generator.rb +8 -0
- data/lib/tasks/blabs_tasks.rake +4 -0
- data/spec/controllers/blabs/blog_posts_controller_spec.rb +50 -0
- data/spec/controllers/blabs/published_blog_posts_controller_spec.rb +32 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +15 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/account.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +23 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/db/migrate/20130808145755_create_accounts.rb +9 -0
- data/spec/dummy/db/schema.rb +60 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/helpers/blabs/blog_posts_helper_spec.rb +50 -0
- data/spec/lib/blabs_spec.rb +8 -0
- data/spec/models/blabs/blog_post_spec.rb +76 -0
- data/spec/spec_helper.rb +19 -0
- metadata +356 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Blabs::BlogPostsHelper
|
4
|
+
EXTRACT_LENGTH = 600
|
5
|
+
|
6
|
+
def title(title)
|
7
|
+
content_for(:title, title)
|
8
|
+
content_tag(:h1, title)
|
9
|
+
end
|
10
|
+
|
11
|
+
def field_error(form, object, field)
|
12
|
+
if object.errors[field] && object.errors[field].size > 0
|
13
|
+
content_tag 'div', object.errors[field].first,
|
14
|
+
class: 'i i-info form-error'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def admin_controls(blog_post)
|
19
|
+
edit_link = link_to("Edit", edit_blabs_blog_post_path(blog_post))
|
20
|
+
publish_link = publish_or_unpublish_link(blog_post)
|
21
|
+
delete_link = link_to("Delete", blog_post, method: :delete, data: { confirm: "Are you sure?" })
|
22
|
+
raw [edit_link, publish_link, delete_link].join(" • ")
|
23
|
+
end
|
24
|
+
|
25
|
+
def formatted_body(text)
|
26
|
+
options = { autolink: true, lax_spacing: true, space_after_headers: true}
|
27
|
+
renderer = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
|
28
|
+
auto_link_username(renderer.render(text)).html_safe
|
29
|
+
end
|
30
|
+
|
31
|
+
def validate_layout
|
32
|
+
if !content_for?(:title) && !@blog_post.meta_title.blank?
|
33
|
+
raise "You need to put a title yield in your layouts title tag.\n
|
34
|
+
e.g. <title>My Blog - <%= yield(:title) %> </title>\n"
|
35
|
+
end
|
36
|
+
|
37
|
+
if !content_for?(:meta_tags)
|
38
|
+
raise "You need to put a meta_tags yield in your layouts head tag.\n
|
39
|
+
e.g. <%= yield(:meta_tags) %> </head>\n"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def pretty_date(date)
|
45
|
+
date.strftime("#{date.day.ordinalize} %B %Y") unless date.blank?
|
46
|
+
end
|
47
|
+
|
48
|
+
def extract(blog_post)
|
49
|
+
if blog_post.extract.present?
|
50
|
+
extract = blog_post.extract + " " + link_to("Read more", pretty_blog_post_path(blog_post), :class=>"more")
|
51
|
+
formatted_body(extract)
|
52
|
+
else
|
53
|
+
truncate_html(formatted_body(blog_post.body), length: EXTRACT_LENGTH,
|
54
|
+
omission: "... #{link_to("Read more", pretty_blog_post_path(blog_post), :class=>"more")}",
|
55
|
+
escape: false)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def show_meta_tags
|
60
|
+
content_for(:meta_tags) do
|
61
|
+
concat twitter_meta_tag("card", "summary")
|
62
|
+
concat twitter_meta_tag("site", Blabs.twitter_site_username)
|
63
|
+
concat twitter_meta_tag("creator", @blog_post.try(:author_twitter_username))
|
64
|
+
concat twitter_meta_tag("title", @blog_post.title)
|
65
|
+
|
66
|
+
sample = truncate(strip_tags(formatted_body(@blog_post.body)), length: EXTRACT_LENGTH)
|
67
|
+
|
68
|
+
concat twitter_meta_tag("description", sample.strip)
|
69
|
+
concat twitter_meta_tag("image", @blog_post.post_image_url)
|
70
|
+
|
71
|
+
concat open_graph_meta_tag("title", @blog_post.title)
|
72
|
+
concat open_graph_meta_tag("description", sample.strip)
|
73
|
+
concat open_graph_meta_tag("image", @blog_post.post_image_url)
|
74
|
+
concat open_graph_meta_tag("url", pretty_blog_post_url(@blog_post))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def index_meta_tags
|
79
|
+
content_for(:meta_tags) do
|
80
|
+
concat auto_discovery_link_tag :atom, "/blog/feed"
|
81
|
+
concat auto_discovery_link_tag :rss, "/blog/feed.rss"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def auto_link_username(body)
|
86
|
+
body.gsub(/@(\w+)/, %Q{<a href="https://twitter.com/\\1">@\\1</a>})
|
87
|
+
end
|
88
|
+
|
89
|
+
def display_author(blog_post)
|
90
|
+
if blog_post.author_twitter_username.blank?
|
91
|
+
blog_post.author
|
92
|
+
else
|
93
|
+
link_to(blog_post.author, "https://twitter.com/#{blog_post.author_twitter_username.delete("@")}")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
def publish_or_unpublish_link(blog_post)
|
99
|
+
if blog_post.published?
|
100
|
+
link_to("Unpublish", blabs_published_blog_posts_path(id: blog_post), method: :delete)
|
101
|
+
else
|
102
|
+
link_to("Publish", blabs_published_blog_posts_path(id: blog_post), method: :post)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def twitter_meta_tag(label, value)
|
107
|
+
tag(:meta, name: "twitter:#{label}", content: value)
|
108
|
+
end
|
109
|
+
|
110
|
+
def open_graph_meta_tag(label, value)
|
111
|
+
tag(:meta, property: "og:#{label}", content: value)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Blabs
|
2
|
+
class BlogPost < ActiveRecord::Base
|
3
|
+
self.table_name_prefix = 'blabs_'
|
4
|
+
|
5
|
+
validates :title, presence: true
|
6
|
+
validates :body, presence: true
|
7
|
+
validates :author, presence: true
|
8
|
+
validates :path, presence: true, uniqueness: true
|
9
|
+
|
10
|
+
serialize :extra_attributes, Hash
|
11
|
+
|
12
|
+
before_validation :set_path
|
13
|
+
before_validation :set_meta_title
|
14
|
+
|
15
|
+
has_many :taggings, class_name: "Blabs::Tagging", foreign_key: "blabs_blog_post_id"
|
16
|
+
has_many :tags, class_name: "Blabs::Tag", through: :taggings, foreign_key: "blabs_tag_id"
|
17
|
+
|
18
|
+
def self.tagged_with(name)
|
19
|
+
Tag.find_by_name!(name).blog_posts
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_param
|
23
|
+
path
|
24
|
+
end
|
25
|
+
|
26
|
+
def publish!
|
27
|
+
update_attributes(published: true, published_at: Time.now) unless published?
|
28
|
+
end
|
29
|
+
|
30
|
+
def unpublish!
|
31
|
+
update_attributes(published: false, published_at: nil) if published?
|
32
|
+
end
|
33
|
+
|
34
|
+
def toggle_publish!(value)
|
35
|
+
value ? publish! : unpublish!
|
36
|
+
end
|
37
|
+
|
38
|
+
def post_image_url
|
39
|
+
(Blabs.post_image_url_attribute && extra_attributes[Blabs.post_image_url_attribute]) || begin
|
40
|
+
find_link_regex = /\[([^\[]+)\]\(([^\)]+)\)/
|
41
|
+
body.match(find_link_regex) && $2
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def author_twitter_username
|
46
|
+
username = self[:author_twitter_username]
|
47
|
+
username.blank? ? "" : "@#{username}".squeeze("@")
|
48
|
+
end
|
49
|
+
|
50
|
+
def tag_list=(names)
|
51
|
+
self.tags = names.split(",").map do |n|
|
52
|
+
Blabs::Tag.where(name: n.strip).first_or_create!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def tag_list
|
57
|
+
self.tags.collect {|t| t.name }.join(", ")
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def set_path
|
63
|
+
self.path = self.title.parameterize if self.path.blank? && self.title.present?
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_meta_title
|
67
|
+
self.meta_title = self.title if self.meta_title.blank?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Blabs
|
2
|
+
class Tagging < ActiveRecord::Base
|
3
|
+
self.table_name_prefix = 'blabs_'
|
4
|
+
|
5
|
+
belongs_to :tag, class_name: "Blabs::Tag", foreign_key: "blabs_tag_id"
|
6
|
+
belongs_to :blog_post, class_name: "Blabs::BlogPost", foreign_key: "blabs_blog_post_id"
|
7
|
+
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'carrierwave/processing/mime_types'
|
3
|
+
|
4
|
+
class ImageUploader < CarrierWave::Uploader::Base
|
5
|
+
|
6
|
+
# Include RMagick or MiniMagick support:
|
7
|
+
# include CarrierWave::RMagick
|
8
|
+
include CarrierWave::MiniMagick
|
9
|
+
include CarrierWave::MimeTypes
|
10
|
+
|
11
|
+
# Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
|
12
|
+
# include Sprockets::Helpers::RailsHelper
|
13
|
+
# include Sprockets::Helpers::IsolatedHelper
|
14
|
+
|
15
|
+
# Choose what kind of storage to use for this uploader:
|
16
|
+
if Rails.env.production?
|
17
|
+
storage :fog
|
18
|
+
fog_credentials Blabs.fog_credentials
|
19
|
+
fog_directory Blabs.fog_directory
|
20
|
+
else
|
21
|
+
storage :file
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# Override the directory where uploaded files will be stored.
|
26
|
+
# This is a sensible default for uploaders that are meant to be mounted:
|
27
|
+
def store_dir
|
28
|
+
"uploads/#{model.class.to_s.underscore}/#{model.id}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Provide a default URL as a default if there hasn't been a file uploaded:
|
32
|
+
# def default_url
|
33
|
+
# # For Rails 3.1+ asset pipeline compatibility:
|
34
|
+
# # asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
|
35
|
+
#
|
36
|
+
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
|
37
|
+
# end
|
38
|
+
|
39
|
+
# Process files as they are uploaded:
|
40
|
+
# process :scale => [200, 300]
|
41
|
+
#
|
42
|
+
# def scale(width, height)
|
43
|
+
# # do something
|
44
|
+
# end
|
45
|
+
|
46
|
+
process :set_content_type
|
47
|
+
|
48
|
+
# Create different versions of your uploaded files:
|
49
|
+
version :thumb do
|
50
|
+
process :resize_to_fit => [60, 60]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Add a white list of extensions which are allowed to be uploaded.
|
54
|
+
# For images you might use something like this:
|
55
|
+
# def extension_white_list
|
56
|
+
# %w(jpg jpeg gif png)
|
57
|
+
# end
|
58
|
+
|
59
|
+
# Override the filename of the uploaded files:
|
60
|
+
# Avoid using model.id or version_name here, see uploader/store.rb for details.
|
61
|
+
# def filename
|
62
|
+
# "something.jpg" if original_filename
|
63
|
+
# end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
=form_for(@blog_post) do |f|
|
2
|
+
.col-lg-8
|
3
|
+
.form-group
|
4
|
+
= f.label :title
|
5
|
+
= f.text_field :title, class: "form-control", placeholder: "Give your blog post an interesting title"
|
6
|
+
= field_error(f, @blog_post, :title)
|
7
|
+
.row
|
8
|
+
.col-lg-6
|
9
|
+
.form-group
|
10
|
+
= f.label :author
|
11
|
+
= f.text_field :author, class: "form-control", placeholder: "You need to put your name in"
|
12
|
+
= field_error(f, @blog_post, :author)
|
13
|
+
.col-lg-6
|
14
|
+
.form-group
|
15
|
+
= f.label :author_twitter_username
|
16
|
+
= f.text_field :author_twitter_username, class: "form-control", placeholder: "Your twitter name (for the twitter summary card)"
|
17
|
+
= field_error(f, @blog_post, :author_twitter_username)
|
18
|
+
.form-group
|
19
|
+
= f.label :body
|
20
|
+
%p.pull-right= link_to("Markdown syntax (new window)", "http://daringfireball.net/projects/markdown/syntax", target: :window, tabIndex: -1)
|
21
|
+
= f.text_area :body, class: "form-control", placeholder: "Use markdown to write your blog post", rows: 25
|
22
|
+
= field_error(f, @blog_post, :body)
|
23
|
+
.form-group
|
24
|
+
= f.label :extract
|
25
|
+
%p.pull-right Leave blank to use the default extract
|
26
|
+
= f.text_area :extract, class: "form-control", placeholder: "Use markdown to write your extract", rows: 2
|
27
|
+
= field_error(f, @blog_post, :extract)
|
28
|
+
.form-group
|
29
|
+
= f.submit "Save (unpublished)", class: "btn btn-default"
|
30
|
+
= f.submit "Save and publish", class: "btn btn-default btn-success", name: "publish"
|
31
|
+
= f.submit "Preview", class: "btn btn-default btn-info", name: "preview"
|
32
|
+
or
|
33
|
+
= link_to "cancel", "/blog", data: { confirm: "Are you sure?" }
|
34
|
+
.col-lg-4.panel.panel-info
|
35
|
+
.panel-heading For SEO nerds
|
36
|
+
.well.well-sm If you don't put anything in here, a sensible default will be applied
|
37
|
+
.form-group
|
38
|
+
= f.label :meta_title
|
39
|
+
= f.text_field :meta_title, class: "form-control", placeholder: "Meta title - for you SEO nerds (will default to the title)"
|
40
|
+
= field_error(f, @blog_post, :meta_title)
|
41
|
+
.form-group
|
42
|
+
= f.label :path
|
43
|
+
= f.text_field :path, class: "form-control", placeholder: "The url - (will be defaulted to something sensible)"
|
44
|
+
= field_error(f, @blog_post, :path)
|
45
|
+
.form-group
|
46
|
+
= f.label :tag_list
|
47
|
+
= f.text_field :tag_list, class: "form-control", placeholder: "Comma delimited list of tags"
|
48
|
+
- if Blabs.extra_attributes.any?
|
49
|
+
.col-lg-4.panel.panel-info
|
50
|
+
- Blabs.extra_attributes.each do |attribute|
|
51
|
+
.form-group
|
52
|
+
= label_tag "blabs_blog_post[extra_attributes][#{attribute}]", attribute.to_s.humanize
|
53
|
+
= text_field_tag "blabs_blog_post[extra_attributes][#{attribute}]", @blog_post.extra_attributes[attribute], class: "form-control"
|
54
|
+
=render "image_panel"
|
@@ -0,0 +1,5 @@
|
|
1
|
+
%li.list-group-item.image[image]
|
2
|
+
= link_to(image_tag(image.image_url(:thumb)), image.image_url) if image.image?
|
3
|
+
= link_to("Add", image.image_url, class: "add-to-blog")
|
4
|
+
|
|
5
|
+
= link_to("Delete", blabs_image_path(image), :method => :delete, data: { confirm: "Are you sure?" }, :remote => :true)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
.col-lg-4.panel.panel-success
|
2
|
+
.panel-heading Images
|
3
|
+
.well.well-sm Upload an image, and then add it to the post with the add button
|
4
|
+
= fields_for Blabs::Image.new do |f|
|
5
|
+
= f.file_field :image, rel: blabs_images_path
|
6
|
+
%ul#images.list-group
|
7
|
+
= render partial: 'image', collection: @images
|
8
|
+
|
9
|
+
- key = Rails.application.config.session_options[:key]
|
10
|
+
= content_for :scripts do
|
11
|
+
:javascript
|
12
|
+
var upload_params = {};
|
13
|
+
var csrf_param = $('meta[name=csrf-param]').attr('content');
|
14
|
+
var csrf_token = $('meta[name=csrf-token]').attr('content');
|
15
|
+
upload_params[csrf_param] = encodeURI(encodeURIComponent(csrf_token));
|
16
|
+
upload_params['#{ key }'] = '#{ cookies[key] }';
|
17
|
+
|
18
|
+
var url = $('input#blabs_image_image').attr('rel');
|
19
|
+
$('input#blabs_image_image').uploadify({
|
20
|
+
'swf' : '#{ image_path("uploadify.swf") }',
|
21
|
+
'buttonText': "Upload image",
|
22
|
+
'uploader' : url,
|
23
|
+
'fileObjName' : 'blabs_image[image]',
|
24
|
+
'fileTypeExts' : '*.png;*.jpg;*.gif',
|
25
|
+
'multi' : true,
|
26
|
+
'formData' : upload_params,
|
27
|
+
'auto' : true,
|
28
|
+
'onUploadSuccess' : function(file, data, response) {
|
29
|
+
var newImage = $('#images').prepend(data);
|
30
|
+
$(document).trigger('new_image', $(newImage).attr("id"));
|
31
|
+
}
|
32
|
+
});
|
@@ -0,0 +1,15 @@
|
|
1
|
+
atom_feed do |feed|
|
2
|
+
feed.title @title
|
3
|
+
feed.updated @updated
|
4
|
+
|
5
|
+
@posts.each do |post|
|
6
|
+
feed.entry post do |entry|
|
7
|
+
entry.title post.title
|
8
|
+
entry.content formatted_body(post.body), type: 'html'
|
9
|
+
entry.updated(post.updated_at.strftime("%Y-%m-%dT%H:%M:%SZ"))
|
10
|
+
entry.author do |author|
|
11
|
+
author.name post.author
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
- index_meta_tags
|
2
|
+
|
3
|
+
.blabs-blog
|
4
|
+
%nav.blabs-navigation
|
5
|
+
- if blabs_admin_required && @blog_posts.any?
|
6
|
+
=link_to("New Blog Post", new_blabs_blog_post_path)
|
7
|
+
-if @blog_posts.none?
|
8
|
+
%article
|
9
|
+
%header
|
10
|
+
%h2.title You don't have any blog posts.
|
11
|
+
%p.authorship #{link_to("Why don't you create the first!", new_blabs_blog_post_path)}
|
12
|
+
|
13
|
+
-else
|
14
|
+
-@blog_posts.each do |blog_post|
|
15
|
+
%article
|
16
|
+
%header
|
17
|
+
%h2.title=link_to(blog_post.title, pretty_blog_post_path(blog_post))
|
18
|
+
%p.authorship #{display_author(blog_post)} • #{pretty_date(blog_post.published_at) || pretty_date(blog_post.created_at)}
|
19
|
+
%hr
|
20
|
+
.content.post-body
|
21
|
+
- if @blog_posts.size == 1
|
22
|
+
= formatted_body(blog_post.body)
|
23
|
+
- else
|
24
|
+
= extract(blog_post)
|
25
|
+
- if blabs_admin_required
|
26
|
+
.blabs-admin-controls
|
27
|
+
= admin_controls(blog_post)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
- content_for(:title, @blog_post.meta_title)
|
2
|
+
- show_meta_tags
|
3
|
+
- validate_layout
|
4
|
+
.blabs-blog
|
5
|
+
%nav.blabs-navigation
|
6
|
+
=link_to("< Back", "/blog")
|
7
|
+
%article
|
8
|
+
%header
|
9
|
+
%h1.title= @blog_post.title
|
10
|
+
%p.authorship #{display_author(@blog_post)} • #{pretty_date(@blog_post.published_at) || pretty_date(@blog_post.created_at)}
|
11
|
+
|
12
|
+
.content.post-body
|
13
|
+
= formatted_body(@blog_post.body)
|
14
|
+
- if blabs_admin_required
|
15
|
+
.blabs-admin-controls
|
16
|
+
= admin_controls(@blog_post)
|