chive 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -1
- data/app/assets/javascript/chive/application.js +8 -1
- data/app/assets/stylesheets/chive/application.scss +1 -13
- data/app/controllers/chive/application_controller.rb +1 -1
- data/app/controllers/chive/articles_controller.rb +4 -3
- data/app/controllers/chive/feed_controller.rb +10 -0
- data/app/controllers/concerns/chive/user_concerns.rb +14 -1
- data/app/helpers/chive/application_helper.rb +0 -4
- data/app/models/chive/article.rb +49 -0
- data/app/views/chive/articles/_form.html.erb +14 -12
- data/app/views/chive/articles/_pagination.html.erb +7 -0
- data/app/views/chive/articles/_status.html.erb +16 -0
- data/app/views/chive/articles/index.html.erb +14 -9
- data/app/views/chive/articles/show.html.erb +19 -12
- data/app/views/chive/feed/index.rss.builder +19 -0
- data/app/views/layouts/chive/_flash.html.erb +1 -1
- data/app/views/layouts/chive/application.html.erb +6 -4
- data/config/routes.rb +1 -1
- data/db/migrate/20210331030111_add_unique_slug_to_chive_articles.rb +5 -0
- data/db/migrate/20210331061401_add_non_unique_indexes_to_chive_articles.rb +8 -0
- data/db/seeds.rb +1 -1
- data/lib/chive/engine.rb +13 -1
- data/lib/chive/version.rb +1 -1
- data/lib/chive.rb +12 -0
- data/lib/generators/chive/migrations_generator.rb +2 -2
- data/lib/generators/chive/seeds_generator.rb +1 -1
- data/lib/tasks/chive_tasks.rake +28 -0
- data/templates/chive.rb.tt +7 -0
- metadata +11 -7
- data/app/assets/javascript/ckeditor/config.js +0 -56
- data/app/helpers/chive/articles_helper.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebdbc5cf2ede969b8749328cdfd9923723b1bfd48c02e4e3a2220c0551780bb8
|
4
|
+
data.tar.gz: 2103ecb3b44a599644af0f1e0a3fd4a559324c7456b4e9501af108fd39addab1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 965fca49ecae82243be60508620a276ac287739e8eea1871bb8496927cfbb8b2a88551b5d6406a5557e643c53e19192105b324ef7136a29cbb17e152be402df6
|
7
|
+
data.tar.gz: 2acb628957d7dee8f6dae2ccf384214d4e2fb45fdb578a22d7a8572cd261b7c78741973c62f2d8328e1adb8690357a69ae865bccb384d8c65a780354f9674a0e
|
data/README.md
CHANGED
@@ -125,7 +125,15 @@ end
|
|
125
125
|
You can make the blog your home page by changing the `Chive::Engine` path to `/`:
|
126
126
|
|
127
127
|
```ruby
|
128
|
-
|
128
|
+
Rails.application.routes.draw do
|
129
|
+
|
130
|
+
# [...etc.]
|
131
|
+
|
132
|
+
# If you mount Chive on the home page, make sure it's the last route you
|
133
|
+
# define. Otherwise `Chive::Engine#index` will process all your website's
|
134
|
+
# paths before the other routes have a chance to evaluate them.
|
135
|
+
mount Chive::Engine => '/'
|
136
|
+
end
|
129
137
|
```
|
130
138
|
|
131
139
|
## Customizing the Layout
|
@@ -167,3 +175,19 @@ end
|
|
167
175
|
The `only: [:index, :show]` option limits the resource to the public pages.
|
168
176
|
|
169
177
|
Now you can make your own views at `app/views/blog/index.html.erb` and `app/views/blog/show.html.erb`.
|
178
|
+
|
179
|
+
## Third-Party Libraries
|
180
|
+
|
181
|
+
Chive uses the following libraries and plugins:
|
182
|
+
|
183
|
+
- [acts-as-taggable-on](https://github.com/mbleigh/acts-as-taggable-on)
|
184
|
+
- [bootstrap](https://github.com/twbs/bootstrap-rubygem)
|
185
|
+
- [ckeditor](https://github.com/galetahub/ckeditor)
|
186
|
+
- [flatpickr](https://github.com/flatpickr/flatpickr)
|
187
|
+
- [jquery-rails](https://github.com/rails/jquery-rails)
|
188
|
+
- [will_paginate](https://github.com/mislav/will_paginate)
|
189
|
+
|
190
|
+
## Sites Using Chive
|
191
|
+
|
192
|
+
- [gamefic.com](https://gamefic.com)
|
193
|
+
- [moviecrank.com](https://moviecrank.com)
|
@@ -6,12 +6,14 @@
|
|
6
6
|
//= require popper
|
7
7
|
//= require bootstrap-sprockets
|
8
8
|
|
9
|
+
//= require flatpickr
|
10
|
+
|
9
11
|
/**
|
10
12
|
* Preview an image before upload
|
11
13
|
*
|
12
14
|
* Example:
|
13
15
|
*
|
14
|
-
* <%= image_tag '
|
16
|
+
* <%= image_tag 'blank', class: 'image-preview' %>
|
15
17
|
* <%= check_box_tag :delete_preview, 'delete', false, class: 'delete-preview' %>
|
16
18
|
* <%= f.file_field :image, class: 'image-upload', data: {preview: '.image-preview', delete: '.delete-preview' } %>
|
17
19
|
*/
|
@@ -69,3 +71,8 @@ $(function () {
|
|
69
71
|
}
|
70
72
|
});
|
71
73
|
});
|
74
|
+
|
75
|
+
$(function () {
|
76
|
+
flatpickr('.flatpickr-date');
|
77
|
+
flatpickr('.flatpickr-datetime', { enableTime: true });
|
78
|
+
});
|
@@ -1,5 +1,6 @@
|
|
1
1
|
@import "bootstrap";
|
2
2
|
@import "./pagination";
|
3
|
+
@import "flatpickr";
|
3
4
|
|
4
5
|
#header {
|
5
6
|
background-color: #f2efe9;
|
@@ -13,23 +14,10 @@
|
|
13
14
|
}
|
14
15
|
|
15
16
|
.flash {
|
16
|
-
text-align: center;
|
17
17
|
margin-top: -2em;
|
18
18
|
margin-bottom: 2em;
|
19
19
|
}
|
20
20
|
|
21
|
-
.header-nav {
|
22
|
-
text-align: right;
|
23
|
-
|
24
|
-
.btn {
|
25
|
-
margin-left: 0.5em;
|
26
|
-
}
|
27
|
-
}
|
28
|
-
|
29
|
-
#footer {
|
30
|
-
padding-top: 1em;
|
31
|
-
}
|
32
|
-
|
33
21
|
.btn.btn-primary, .btn.btn-outline-primary {
|
34
22
|
min-width: 5rem;
|
35
23
|
}
|
@@ -11,16 +11,17 @@ module Chive
|
|
11
11
|
# GET /articles
|
12
12
|
# GET /articles.json
|
13
13
|
def index
|
14
|
-
@articles = if
|
14
|
+
@articles = if user_can_chive? && !params.key?(:public)
|
15
15
|
Article.latest
|
16
16
|
else
|
17
17
|
Article.latest_published
|
18
|
-
end.paginate(page: params[:page])
|
18
|
+
end.paginate(page: params[:page], per_page: Chive.per_page)
|
19
19
|
end
|
20
20
|
|
21
21
|
# GET /articles/1
|
22
22
|
# GET /articles/1.json
|
23
23
|
def show
|
24
|
+
raise ActionController::RoutingError.new('Not Found') unless @article
|
24
25
|
end
|
25
26
|
|
26
27
|
# GET /articles/new
|
@@ -80,7 +81,7 @@ module Chive
|
|
80
81
|
|
81
82
|
# Use callbacks to share common setup or constraints between actions.
|
82
83
|
def set_article
|
83
|
-
@article = Article.
|
84
|
+
@article = Article.find_by(slug: params[:slug])
|
84
85
|
end
|
85
86
|
|
86
87
|
# Only allow a list of trusted parameters through.
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module Chive
|
2
2
|
module UserConcerns
|
3
|
-
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
helper_method :user_can_chive?
|
7
|
+
helper_method :chive_user
|
8
|
+
end
|
4
9
|
|
5
10
|
def authenticate_chive_user
|
6
11
|
if Chive.use_devise?
|
@@ -16,5 +21,13 @@ module Chive
|
|
16
21
|
def chive_user
|
17
22
|
send("current_#{Chive.user_model.underscore}") if Chive.use_devise?
|
18
23
|
end
|
24
|
+
|
25
|
+
def user_can_chive?
|
26
|
+
if Chive.use_devise?
|
27
|
+
user_signed_in?
|
28
|
+
else
|
29
|
+
Rails.env.development?
|
30
|
+
end
|
31
|
+
end
|
19
32
|
end
|
20
33
|
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
module Chive
|
2
2
|
module ApplicationHelper
|
3
|
-
def chive_user
|
4
|
-
send("current_#{Chive.user_model.underscore}") if Chive.use_devise?
|
5
|
-
end
|
6
|
-
|
7
3
|
# Needed to fix polymorphic_mappings.
|
8
4
|
# @see https://github.com/rails/rails/issues/31325#issuecomment-560135329
|
9
5
|
def method_missing(method, *args, &block)
|
data/app/models/chive/article.rb
CHANGED
@@ -7,6 +7,16 @@ module Chive
|
|
7
7
|
|
8
8
|
acts_as_taggable_on :tags
|
9
9
|
|
10
|
+
validates :title, presence: true
|
11
|
+
|
12
|
+
before_validation :set_slug
|
13
|
+
validate :slug_is_parameter
|
14
|
+
validates :slug, presence: true, uniqueness: true
|
15
|
+
|
16
|
+
validate :valid_status
|
17
|
+
|
18
|
+
before_save :maybe_summarize
|
19
|
+
|
10
20
|
def byline
|
11
21
|
return custom_byline if custom_byline.present?
|
12
22
|
return real_author_name if real_author_name.present?
|
@@ -22,6 +32,23 @@ module Chive
|
|
22
32
|
end
|
23
33
|
|
24
34
|
def published?
|
35
|
+
self.status == 'publish'
|
36
|
+
end
|
37
|
+
|
38
|
+
def draft?
|
39
|
+
self.status == 'draft'
|
40
|
+
end
|
41
|
+
|
42
|
+
def public?
|
43
|
+
self.status == 'publish' && !expired?
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_param
|
47
|
+
slug
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_slug
|
51
|
+
self.slug = Chive.slug_formatter.call(self) if slug.blank?
|
25
52
|
end
|
26
53
|
|
27
54
|
def self.latest
|
@@ -32,5 +59,27 @@ module Chive
|
|
32
59
|
now = DateTime.now
|
33
60
|
latest.where('published_at <= ? AND (expired_at >= ? OR expired_at IS NULL) AND status = ?', now, now, 'publish')
|
34
61
|
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def valid_status
|
66
|
+
errors.add(:status, :invalid) unless ['publish', 'draft'].include?(status)
|
67
|
+
end
|
68
|
+
|
69
|
+
def slug_is_parameter
|
70
|
+
errors.add(:slug, 'must be a valid parameter') unless slug.parameterize == slug
|
71
|
+
end
|
72
|
+
|
73
|
+
def maybe_summarize
|
74
|
+
return unless autosummary
|
75
|
+
self.summary = summarize_body
|
76
|
+
end
|
77
|
+
|
78
|
+
def summarize_body
|
79
|
+
doc = Nokogiri::HTML.parse(body)
|
80
|
+
paras = doc.css('p')
|
81
|
+
return if paras.empty? || paras.one?
|
82
|
+
paras.first.text
|
83
|
+
end
|
35
84
|
end
|
36
85
|
end
|
@@ -2,18 +2,20 @@
|
|
2
2
|
|
3
3
|
<%= form_for @article, html: { multipart: true } do |f| %>
|
4
4
|
<div class="row">
|
5
|
-
<
|
6
|
-
<h1><%= params[:action].capitalize %> Article</h1>
|
7
|
-
</div>
|
8
|
-
<nav class="col header-nav">
|
5
|
+
<nav class="col text-right">
|
9
6
|
<%= f.submit 'Save', class: 'btn btn-primary' %>
|
10
|
-
<%= link_to 'Cancel',
|
7
|
+
<%= link_to 'Cancel', @article, class: 'btn btn-secondary' %>
|
11
8
|
<% if params[:action] == 'edit' %>
|
12
9
|
<%= link_to "Delete", '#', class: 'btn btn-outline-danger', data: { toggle: 'modal', target: '#delete-modal' } %>
|
13
10
|
<%= render partial: 'delete_modal' %>
|
14
11
|
<% end %>
|
15
12
|
</nav>
|
16
13
|
</div>
|
14
|
+
<div class="row">
|
15
|
+
<div class="col">
|
16
|
+
<h1><%= params[:action].capitalize %> Article</h1>
|
17
|
+
</div>
|
18
|
+
</div>
|
17
19
|
<% if @article.errors.any? %>
|
18
20
|
<div id="error_explanation">
|
19
21
|
<h2><%= pluralize(@article.errors.count, "error") %> errors prohibited this article from being saved:</h2>
|
@@ -32,7 +34,7 @@
|
|
32
34
|
<div class="col-md-9">
|
33
35
|
<div class="form-group">
|
34
36
|
<%= f.label :body %>
|
35
|
-
<%= f.cktext_area :body, class: 'form-control' %>
|
37
|
+
<%= f.cktext_area :body, class: 'form-control', ckeditor: { height: 512 } %>
|
36
38
|
</div>
|
37
39
|
</div>
|
38
40
|
<div class="col-md-3">
|
@@ -40,23 +42,23 @@
|
|
40
42
|
<%= f.label :image %>
|
41
43
|
<div class="image-previews">
|
42
44
|
<div class="image-container">
|
43
|
-
|
45
|
+
<img src="/assets/chive/no-image.png" class="align-middle" />
|
44
46
|
</div>
|
45
47
|
<div>
|
46
48
|
<% if @article.image.attached? %>
|
47
49
|
<div class="image-container">
|
48
50
|
<%= image_tag @article.image.variant(resize: '250x250'), class: 'attached-image' if @article.image.attached? %>
|
49
51
|
</div>
|
50
|
-
<label class="delete-image">
|
52
|
+
<label class="delete-image btn">
|
51
53
|
<%= check_box_tag :delete_image, @article.image.id, false %>
|
52
54
|
</label>
|
53
55
|
<% end %>
|
54
56
|
</div>
|
55
57
|
<div>
|
56
58
|
<div class="image-container">
|
57
|
-
|
59
|
+
<img src="/assets/chive/blank.png" class="image-preview" />
|
58
60
|
</div>
|
59
|
-
<label class="delete-preview">
|
61
|
+
<label class="delete-preview btn">
|
60
62
|
<%= check_box_tag :delete_preview, 'delete', false %>
|
61
63
|
</label>
|
62
64
|
</div>
|
@@ -97,11 +99,11 @@
|
|
97
99
|
</div>
|
98
100
|
<div class="form-group col-sm-4">
|
99
101
|
<%= f.label :published_at, 'Publish Date' %>
|
100
|
-
<%= f.
|
102
|
+
<%= f.text_field :published_at, class: 'form-control flatpickr-datetime' %>
|
101
103
|
</div>
|
102
104
|
<div class="form-group col-sm-4">
|
103
105
|
<%= f.label :exipred_at, 'Expire Date' %>
|
104
|
-
<%= f.
|
106
|
+
<%= f.text_field :expired_at, class: 'form-control flatpickr-datetime' %>
|
105
107
|
</div>
|
106
108
|
</div>
|
107
109
|
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% if user_can_chive? %>
|
2
|
+
<p>
|
3
|
+
<% if article.draft? %><span class="badge badge-info">Draft</span><% end %>
|
4
|
+
<% if article.expired? %><span class="badge badge-info">Expired</span><% end %>
|
5
|
+
<% unless article.public? %>
|
6
|
+
<% if chive_user %>
|
7
|
+
<span class="badge badge-info">Visible to authors</span>
|
8
|
+
<% elsif Rails.env.development? %>
|
9
|
+
<span class="badge badge-info">Visible in development</span>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
12
|
+
<% if !article.draft? && !article.public? %>
|
13
|
+
<span class="badge badge-danger">Status: <%= article.status %></span>
|
14
|
+
<% end %>
|
15
|
+
</p>
|
16
|
+
<% end %>
|
@@ -1,21 +1,26 @@
|
|
1
1
|
<section>
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
<% if user_can_chive? %>
|
3
|
+
<div class="row">
|
4
|
+
<nav class="col text-right">
|
5
|
+
<%= link_to "New Article", new_article_path, class: 'btn btn-outline-primary' %>
|
6
|
+
</nav>
|
7
|
+
</div>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<%= render 'pagination' %>
|
7
11
|
|
8
12
|
<% @articles.each do |article| %>
|
13
|
+
<div class="row mb-4">
|
14
|
+
</div>
|
9
15
|
<article>
|
10
16
|
<h2 class="large"><%= link_to article.title, article_path(article) %></h2>
|
11
17
|
<address>by <%= article.byline %> on <%= article.published_at %></address>
|
12
18
|
<p>
|
13
19
|
<%= raw article.summary %>
|
14
|
-
<%= link_to 'Read More', article_path(article) %>
|
15
20
|
</p>
|
21
|
+
<%= render 'status', article: article %>
|
16
22
|
</article>
|
17
23
|
<% end %>
|
18
|
-
|
19
|
-
|
20
|
-
</div>
|
24
|
+
|
25
|
+
<%= render 'pagination' %>
|
21
26
|
</section>
|
@@ -1,26 +1,33 @@
|
|
1
|
+
<% if user_can_chive? %>
|
2
|
+
<div class="row mb-4">
|
3
|
+
<nav class="col text-right">
|
4
|
+
<%= link_to "Edit", edit_article_path(@article), class: 'btn btn-outline-primary' %>
|
5
|
+
<%= render partial: 'delete_modal' %>
|
6
|
+
</nav>
|
7
|
+
</div>
|
8
|
+
<% end %>
|
9
|
+
|
1
10
|
<section>
|
2
11
|
<article>
|
3
12
|
<div class="row">
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
13
|
+
<% if @article.image.attached? %>
|
14
|
+
<div class="col-auto">
|
15
|
+
<%= image_tag @article.image.variant(resize: '400x300') %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
<div class="col-md">
|
8
19
|
<h1><%= @article.title %></h1>
|
9
20
|
<address>by <%= @article.byline %> on <%= @article.published_at %></address>
|
10
21
|
<p>
|
11
22
|
<small><%= @article.tag_list.to_s %></small>
|
12
23
|
</p>
|
24
|
+
<%= render 'status', article: @article %>
|
13
25
|
</div>
|
14
|
-
<nav class="col header-nav">
|
15
|
-
<% if user_can_chive? %>
|
16
|
-
<%= link_to "Edit", edit_article_path(@article), class: 'btn btn-outline-primary' %>
|
17
|
-
<%= link_to "Delete", '#', class: 'btn btn-outline-danger', data: { toggle: 'modal', target: '#delete-modal' } %>
|
18
|
-
<%= render partial: 'delete_modal' %>
|
19
|
-
<% end %>
|
20
|
-
</nav>
|
21
26
|
</div>
|
22
27
|
<div class="row">
|
23
|
-
|
28
|
+
<div class="col">
|
29
|
+
<%= raw @article.body %>
|
30
|
+
</div>
|
24
31
|
</div>
|
25
32
|
</article>
|
26
33
|
</section>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
xml.instruct! :xml, :version => "1.0"
|
2
|
+
xml.rss :version => "2.0" do
|
3
|
+
xml.channel do
|
4
|
+
xml.title "Your Blog Title"
|
5
|
+
xml.description "A blog about software and chocolate"
|
6
|
+
# xml.link chive.articles_url
|
7
|
+
xml.link 'https://castwide.com'
|
8
|
+
|
9
|
+
for article in @articles
|
10
|
+
xml.item do
|
11
|
+
xml.title article.title
|
12
|
+
xml.description article.summary
|
13
|
+
xml.pubDate article.published_at.to_s(:rfc822)
|
14
|
+
xml.link chive.article_url(article)
|
15
|
+
xml.guid chive.article_url(article)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% unless flash.empty? %>
|
2
|
-
<div class="
|
2
|
+
<div class="alert alert-warning alert-dismissible fade show text-center" role="alert">
|
3
3
|
<% flash.each do |type, msg| %>
|
4
4
|
<div class="container <%= type %>">
|
5
5
|
<%= msg %>
|
@@ -13,9 +13,9 @@
|
|
13
13
|
<div class="container">
|
14
14
|
<div class="row justify-content-between">
|
15
15
|
<div class="col">
|
16
|
-
<h1 class="header-title"><%= link_to '
|
16
|
+
<h1 class="header-title"><%= link_to 'Articles', articles_path, class: 'header-link align-middle' %></h1>
|
17
17
|
</div>
|
18
|
-
<nav class="
|
18
|
+
<nav class="col text-right">
|
19
19
|
<%= render "layouts/chive/userbox" %>
|
20
20
|
</nav>
|
21
21
|
</div>
|
@@ -27,8 +27,10 @@
|
|
27
27
|
<%= yield %>
|
28
28
|
</main>
|
29
29
|
|
30
|
-
<footer class="container">
|
31
|
-
<
|
30
|
+
<footer class="container text-center mb-4">
|
31
|
+
<p>
|
32
|
+
<small>Powered by Chive</small>
|
33
|
+
</p>
|
32
34
|
</footer>
|
33
35
|
</body>
|
34
36
|
</html>
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,8 @@
|
|
1
|
+
class AddNonUniqueIndexesToChiveArticles < ActiveRecord::Migration[6.0]
|
2
|
+
def change
|
3
|
+
add_index :chive_articles, :author_id, unique: false
|
4
|
+
add_index :chive_articles, :status, unique: false
|
5
|
+
add_index :chive_articles, :published_at, unique: false
|
6
|
+
add_index :chive_articles, :expired_at, unique: false
|
7
|
+
end
|
8
|
+
end
|
data/db/seeds.rb
CHANGED
data/lib/chive/engine.rb
CHANGED
@@ -4,10 +4,22 @@ module Chive
|
|
4
4
|
class Engine < ::Rails::Engine
|
5
5
|
isolate_namespace Chive
|
6
6
|
|
7
|
-
initializer 'chive.assets' do |app|
|
7
|
+
initializer 'chive.assets.precompile' do |app|
|
8
8
|
app.config.assets.precompile += fetch_asset_names
|
9
9
|
end
|
10
10
|
|
11
|
+
# Enhance the assets:precompile task with the chive:public_assets task to
|
12
|
+
# ensure that the main app can access this engine's assets in production.
|
13
|
+
rake_tasks do
|
14
|
+
load Chive::Engine.root.join('lib', 'tasks', 'chive_tasks.rake')
|
15
|
+
|
16
|
+
if Rake::Task.task_defined?('assets:precompile')
|
17
|
+
Rake::Task['assets:precompile'].enhance do
|
18
|
+
Rake::Task['chive:public_assets'].invoke
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
11
23
|
private
|
12
24
|
|
13
25
|
def fetch_asset_names
|
data/lib/chive/version.rb
CHANGED
data/lib/chive.rb
CHANGED
@@ -42,5 +42,17 @@ module Chive
|
|
42
42
|
def public_layout
|
43
43
|
@public_layout ||= 'chive/application'
|
44
44
|
end
|
45
|
+
|
46
|
+
attr_writer :slug_formatter
|
47
|
+
|
48
|
+
def slug_formatter
|
49
|
+
@slug_formatter ||= proc { |article| article.title.parameterize }
|
50
|
+
end
|
51
|
+
|
52
|
+
attr_writer :per_page
|
53
|
+
|
54
|
+
def per_page
|
55
|
+
@per_page ||= 10
|
56
|
+
end
|
45
57
|
end
|
46
58
|
end
|
@@ -16,8 +16,8 @@ Generate migrations for Chive.
|
|
16
16
|
.map { |f| File.basename(f) }
|
17
17
|
.each do |src|
|
18
18
|
title = src.gsub /^[0-9]+_/, ''
|
19
|
-
migration_template src, "db/migrate/#{title}", {
|
20
|
-
migration_file_name: File.basename(src, '.rb')
|
19
|
+
migration_template src, "db/migrate/#{title}.rb", {
|
20
|
+
migration_file_name: "#{File.basename(src, '.rb')}"
|
21
21
|
}
|
22
22
|
end
|
23
23
|
end
|
data/lib/tasks/chive_tasks.rake
CHANGED
@@ -29,4 +29,32 @@ namespace :chive do
|
|
29
29
|
sh 'rails generate chive:seeds'
|
30
30
|
sh 'rails generate chive:initializer --devise'
|
31
31
|
end
|
32
|
+
|
33
|
+
# This task is necessary to ensure that Chive's compiled assets are
|
34
|
+
# available from the main app in production. the CKEditor gem performs a
|
35
|
+
# similar operation.
|
36
|
+
desc 'Create public versions of Chive assets'
|
37
|
+
task public_assets: :environment do
|
38
|
+
fingerprint = /\-[0-9a-f]{32,64}\./
|
39
|
+
path = Rails.root.join('public', 'assets', 'chive', '**', '*')
|
40
|
+
|
41
|
+
Dir[path].each do |file|
|
42
|
+
next unless file =~ fingerprint
|
43
|
+
nondigest = file.sub fingerprint, '.'
|
44
|
+
|
45
|
+
if !File.exist?(nondigest) || File.mtime(file) > File.mtime(nondigest)
|
46
|
+
FileUtils.cp file, nondigest, verbose: true, preserve: true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'Rewrite article slugs'
|
52
|
+
task slugs: :environment do
|
53
|
+
Chive::Article.all.each do |article|
|
54
|
+
rewrite = Chive.slug_formatter.call(article)
|
55
|
+
puts "#{article.slug} -> #{rewrite}"
|
56
|
+
article.slug = rewrite
|
57
|
+
article.save!
|
58
|
+
end
|
59
|
+
end
|
32
60
|
end
|
data/templates/chive.rb.tt
CHANGED
@@ -19,4 +19,11 @@ Chive.setup do |config|
|
|
19
19
|
<% end %>
|
20
20
|
# The layout to use for public pages
|
21
21
|
# config.public_layout = 'chive/application'
|
22
|
+
|
23
|
+
# The slug formatter. This proc should generate a unique param for the
|
24
|
+
# article's URL, e.g., `my-article-title`
|
25
|
+
# config.slug_formatter = proc { |article| article.title.parameterize }
|
26
|
+
|
27
|
+
# The number of articles to display per page
|
28
|
+
# config.per_page = 10
|
22
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acts-as-taggable-on
|
@@ -144,30 +144,34 @@ files:
|
|
144
144
|
- app/assets/images/chive/icon-undo.png
|
145
145
|
- app/assets/images/chive/no-image.png
|
146
146
|
- app/assets/javascript/chive/application.js
|
147
|
-
- app/assets/javascript/ckeditor/config.js
|
148
147
|
- app/assets/stylesheets/chive/application.scss
|
149
148
|
- app/assets/stylesheets/chive/articles.css
|
150
149
|
- app/assets/stylesheets/chive/pagination.sass
|
151
150
|
- app/controllers/chive/application_controller.rb
|
152
151
|
- app/controllers/chive/articles_controller.rb
|
152
|
+
- app/controllers/chive/feed_controller.rb
|
153
153
|
- app/controllers/concerns/chive/user_concerns.rb
|
154
154
|
- app/helpers/chive/application_helper.rb
|
155
|
-
- app/helpers/chive/articles_helper.rb
|
156
155
|
- app/jobs/chive/application_job.rb
|
157
156
|
- app/mailers/chive/application_mailer.rb
|
158
157
|
- app/models/chive/application_record.rb
|
159
158
|
- app/models/chive/article.rb
|
160
159
|
- app/views/chive/articles/_delete_modal.erb
|
161
160
|
- app/views/chive/articles/_form.html.erb
|
161
|
+
- app/views/chive/articles/_pagination.html.erb
|
162
|
+
- app/views/chive/articles/_status.html.erb
|
162
163
|
- app/views/chive/articles/edit.html.erb
|
163
164
|
- app/views/chive/articles/index.html.erb
|
164
165
|
- app/views/chive/articles/new.html.erb
|
165
166
|
- app/views/chive/articles/show.html.erb
|
167
|
+
- app/views/chive/feed/index.rss.builder
|
166
168
|
- app/views/layouts/chive/_flash.html.erb
|
167
169
|
- app/views/layouts/chive/_userbox.html.erb
|
168
170
|
- app/views/layouts/chive/application.html.erb
|
169
171
|
- config/routes.rb
|
170
172
|
- db/migrate/20210327092716_create_chive_articles.rb
|
173
|
+
- db/migrate/20210331030111_add_unique_slug_to_chive_articles.rb
|
174
|
+
- db/migrate/20210331061401_add_non_unique_indexes_to_chive_articles.rb
|
171
175
|
- db/seeds.rb
|
172
176
|
- lib/chive.rb
|
173
177
|
- lib/chive/ckeditor_authorization.rb
|
@@ -190,7 +194,7 @@ homepage: https://castwide.com
|
|
190
194
|
licenses:
|
191
195
|
- MIT
|
192
196
|
metadata: {}
|
193
|
-
post_install_message:
|
197
|
+
post_install_message:
|
194
198
|
rdoc_options: []
|
195
199
|
require_paths:
|
196
200
|
- lib
|
@@ -206,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
210
|
version: '0'
|
207
211
|
requirements: []
|
208
212
|
rubygems_version: 3.2.0
|
209
|
-
signing_key:
|
213
|
+
signing_key:
|
210
214
|
specification_version: 4
|
211
215
|
summary: Blog plugin for Rails
|
212
216
|
test_files: []
|
@@ -1,56 +0,0 @@
|
|
1
|
-
CKEDITOR.editorConfig = function( config )
|
2
|
-
{
|
3
|
-
// Define changes to default configuration here. For example:
|
4
|
-
// config.language = 'fr';
|
5
|
-
// config.uiColor = '#AADC6E';
|
6
|
-
|
7
|
-
config.height = 420;
|
8
|
-
|
9
|
-
/* Filebrowser routes */
|
10
|
-
// The location of an external file browser, that should be launched when "Browse Server" button is pressed.
|
11
|
-
config.filebrowserBrowseUrl = "/ckeditor/attachment_files";
|
12
|
-
|
13
|
-
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Flash dialog.
|
14
|
-
config.filebrowserFlashBrowseUrl = "/ckeditor/attachment_files";
|
15
|
-
|
16
|
-
// The location of a script that handles file uploads in the Flash dialog.
|
17
|
-
config.filebrowserFlashUploadUrl = "/ckeditor/attachment_files";
|
18
|
-
|
19
|
-
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Link tab of Image dialog.
|
20
|
-
config.filebrowserImageBrowseLinkUrl = "/ckeditor/pictures";
|
21
|
-
|
22
|
-
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Image dialog.
|
23
|
-
config.filebrowserImageBrowseUrl = "/ckeditor/pictures";
|
24
|
-
|
25
|
-
// The location of a script that handles file uploads in the Image dialog.
|
26
|
-
config.filebrowserImageUploadUrl = "/ckeditor/pictures?";
|
27
|
-
|
28
|
-
// The location of a script that handles file uploads.
|
29
|
-
config.filebrowserUploadUrl = "/ckeditor/attachment_files";
|
30
|
-
|
31
|
-
config.allowedContent = true;
|
32
|
-
config.filebrowserUploadMethod = 'form';
|
33
|
-
|
34
|
-
// Toolbar groups configuration.
|
35
|
-
config.toolbar = [
|
36
|
-
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ], items: [ 'Source'] },
|
37
|
-
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
|
38
|
-
// { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ], items: [ 'Find', 'Replace', '-', 'SelectAll', '-', 'Scayt' ] },
|
39
|
-
// { name: 'forms', items: [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
|
40
|
-
{ name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
|
41
|
-
{ name: 'insert', items: [ 'Image', 'Flash', 'Table', 'HorizontalRule', 'SpecialChar' ] },
|
42
|
-
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
|
43
|
-
'/',
|
44
|
-
{ name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
|
45
|
-
{ name: 'colors', items: [ 'TextColor', 'BGColor' ] },
|
46
|
-
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] }
|
47
|
-
];
|
48
|
-
|
49
|
-
config.toolbar_mini = [
|
50
|
-
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
|
51
|
-
{ name: 'styles', items: [ 'Font', 'FontSize' ] },
|
52
|
-
{ name: 'colors', items: [ 'TextColor', 'BGColor' ] },
|
53
|
-
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
|
54
|
-
{ name: 'insert', items: [ 'Image', 'Table', 'HorizontalRule', 'SpecialChar' ] }
|
55
|
-
];
|
56
|
-
};
|