chive 0.1.1 → 0.2.0

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -1
  3. data/app/assets/javascript/chive/application.js +8 -1
  4. data/app/assets/stylesheets/chive/application.scss +1 -13
  5. data/app/controllers/chive/application_controller.rb +1 -1
  6. data/app/controllers/chive/articles_controller.rb +4 -3
  7. data/app/controllers/chive/feed_controller.rb +10 -0
  8. data/app/controllers/concerns/chive/user_concerns.rb +14 -1
  9. data/app/helpers/chive/application_helper.rb +0 -4
  10. data/app/models/chive/article.rb +49 -0
  11. data/app/views/chive/articles/_form.html.erb +14 -12
  12. data/app/views/chive/articles/_pagination.html.erb +7 -0
  13. data/app/views/chive/articles/_status.html.erb +16 -0
  14. data/app/views/chive/articles/index.html.erb +14 -9
  15. data/app/views/chive/articles/show.html.erb +19 -12
  16. data/app/views/chive/feed/index.rss.builder +19 -0
  17. data/app/views/layouts/chive/_flash.html.erb +1 -1
  18. data/app/views/layouts/chive/application.html.erb +6 -4
  19. data/config/routes.rb +1 -1
  20. data/db/migrate/20210331030111_add_unique_slug_to_chive_articles.rb +5 -0
  21. data/db/migrate/20210331061401_add_non_unique_indexes_to_chive_articles.rb +8 -0
  22. data/db/seeds.rb +1 -1
  23. data/lib/chive/engine.rb +13 -1
  24. data/lib/chive/version.rb +1 -1
  25. data/lib/chive.rb +12 -0
  26. data/lib/generators/chive/migrations_generator.rb +2 -2
  27. data/lib/generators/chive/seeds_generator.rb +1 -1
  28. data/lib/tasks/chive_tasks.rake +28 -0
  29. data/templates/chive.rb.tt +7 -0
  30. metadata +11 -7
  31. data/app/assets/javascript/ckeditor/config.js +0 -56
  32. data/app/helpers/chive/articles_helper.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5518cd19d73a5810f596e2133cc1d7c24c805a5aa527bcf9d140cb4d6d5a5905
4
- data.tar.gz: d68b9899479eeb673d6f11fb9c425dba4e44a817872ae34902ac9dbaf48457c8
3
+ metadata.gz: ebdbc5cf2ede969b8749328cdfd9923723b1bfd48c02e4e3a2220c0551780bb8
4
+ data.tar.gz: 2103ecb3b44a599644af0f1e0a3fd4a559324c7456b4e9501af108fd39addab1
5
5
  SHA512:
6
- metadata.gz: da2b3bf280731a66918d42d16289c03c4c0980e3de78bf9cb16e337a0d4de22f81b1db6460128ebe21ed234a4b927ee1f860830a558e08f2f21f370d487fdd4b
7
- data.tar.gz: 40369e984d1fe8e2cc4295cb5170d2ac2c20985e72b71200610bd7b49f5ea1dd56c9b26759c3044365de42d4ba05f404868c52f72eb2d5cd53be330aec748685
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
- mount Chive::Engine => "/"
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 'chive/blank', class: 'image-preview' %>
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
  }
@@ -6,7 +6,7 @@ module Chive
6
6
 
7
7
  protect_from_forgery with: :exception
8
8
 
9
- after_action :store_action
9
+ after_action(:store_action) if Chive.use_devise?
10
10
 
11
11
  # Needed to fix polymorphic_mappings.
12
12
  # @see https://github.com/rails/rails/issues/31325#issuecomment-560135329
@@ -11,16 +11,17 @@ module Chive
11
11
  # GET /articles
12
12
  # GET /articles.json
13
13
  def index
14
- @articles = if (chive_user || Rails.env.development?) && !params.key?(:public)
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.find(params[:id])
84
+ @article = Article.find_by(slug: params[:slug])
84
85
  end
85
86
 
86
87
  # Only allow a list of trusted parameters through.
@@ -0,0 +1,10 @@
1
+ module Chive
2
+ class FeedController < ApplicationController
3
+ def index
4
+ @articles = Article.latest_published.limit(Chive.per_page)
5
+ respond_to do |format|
6
+ format.rss { render layout: false }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -1,6 +1,11 @@
1
1
  module Chive
2
2
  module UserConcerns
3
- extended ActiveSupport::Concern
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)
@@ -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
- <div class="col">
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', articles_path, class: 'btn btn-secondary' %>
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
- <%= image_tag 'chive/no-image', class: 'align-middle' %>
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
- <%= image_tag 'chive/blank', class: 'image-preview' %>
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.datetime_field :published_at, class: 'form-control datepicker-field' %>
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.datetime_field :expired_at, class: 'form-control datepicker-field' %>
106
+ <%= f.text_field :expired_at, class: 'form-control flatpickr-datetime' %>
105
107
  </div>
106
108
  </div>
107
109
  <% end %>
@@ -0,0 +1,7 @@
1
+ <div class="row mb-4">
2
+ <div class="col"></div>
3
+ <div class="flickr_pagination col-auto">
4
+ <%= will_paginate @articles %>
5
+ </div>
6
+ <div class="col"></div>
7
+ </div>
@@ -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
- <nav class="header-nav float-right">
3
- <% if user_can_chive? %>
4
- <%= link_to "New Article", new_article_path, class: 'btn btn-outline-primary' %>
5
- <% end %>
6
- </nav>
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
- <div class="digg_pagination">
19
- <%= will_paginate @articles, page_links: false, previous_label: '« Newer', next_label: 'Older »' %>
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
- <div class="float-left">
5
- <%= image_tag @article.image.variant(resize: '250x250') if @article.image.attached? %>
6
- </div>
7
- <div class="col">
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
- <%= raw @article.body %>
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="flash alert alert-warning alert-dismissible fade show" role="alert">
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 'Chive', articles_path, class: 'header-link align-middle' %></h1>
16
+ <h1 class="header-title"><%= link_to 'Articles', articles_path, class: 'header-link align-middle' %></h1>
17
17
  </div>
18
- <nav class="header-nav col">
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
- <small>Powered by Chive</small>
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
@@ -1,3 +1,3 @@
1
1
  Chive::Engine.routes.draw do
2
- resources :articles, path: '/'
2
+ resources :articles, path: '/', param: :slug
3
3
  end
@@ -0,0 +1,5 @@
1
+ class AddUniqueSlugToChiveArticles < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_index :chive_articles, :slug, unique: true
4
+ end
5
+ end
@@ -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
@@ -15,7 +15,7 @@ if Rails.env.development?
15
15
  <p>This is an example article created by the development seeds (db/seeds.rb).</p>
16
16
  ),
17
17
  author: user,
18
- status: 'published',
18
+ status: 'publish',
19
19
  published_at: DateTime.now
20
20
  )
21
21
  end
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
@@ -1,3 +1,3 @@
1
1
  module Chive
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
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
@@ -24,7 +24,7 @@ if Rails.env.development?
24
24
  <p>This is an example article created by the development seeds (db/seeds.rb).</p>
25
25
  ),
26
26
  author: user,
27
- status: 'published',
27
+ status: 'publish',
28
28
  published_at: DateTime.now
29
29
  )
30
30
  end
@@ -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
@@ -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.1.1
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: 2021-03-29 00:00:00.000000000 Z
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
- };
@@ -1,11 +0,0 @@
1
- module Chive
2
- module ArticlesHelper
3
- def user_can_chive?
4
- if Chive.use_devise?
5
- user_signed_in?
6
- else
7
- Rails.env.development?
8
- end
9
- end
10
- end
11
- end