bunko 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.
- checksums.yaml +7 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +41 -0
- data/CLAUDE.md +351 -0
- data/LICENSE.txt +21 -0
- data/README.md +641 -0
- data/ROADMAP.md +519 -0
- data/Rakefile +10 -0
- data/lib/bunko/configuration.rb +180 -0
- data/lib/bunko/controllers/acts_as.rb +22 -0
- data/lib/bunko/controllers/collection.rb +160 -0
- data/lib/bunko/controllers.rb +5 -0
- data/lib/bunko/models/acts_as.rb +24 -0
- data/lib/bunko/models/post_methods/publishable.rb +51 -0
- data/lib/bunko/models/post_methods/sluggable.rb +47 -0
- data/lib/bunko/models/post_methods/word_countable.rb +76 -0
- data/lib/bunko/models/post_methods.rb +75 -0
- data/lib/bunko/models/post_type_methods.rb +18 -0
- data/lib/bunko/models.rb +6 -0
- data/lib/bunko/railtie.rb +22 -0
- data/lib/bunko/routing/mapper_methods.rb +103 -0
- data/lib/bunko/routing.rb +4 -0
- data/lib/bunko/version.rb +5 -0
- data/lib/bunko.rb +11 -0
- data/lib/tasks/bunko/add.rake +259 -0
- data/lib/tasks/bunko/helpers.rb +25 -0
- data/lib/tasks/bunko/install.rake +125 -0
- data/lib/tasks/bunko/sample_data.rake +128 -0
- data/lib/tasks/bunko/setup.rake +186 -0
- data/lib/tasks/support/sample_data_generator.rb +399 -0
- data/lib/tasks/templates/INSTALL.md +62 -0
- data/lib/tasks/templates/config/initializers/bunko.rb.tt +45 -0
- data/lib/tasks/templates/controllers/controller.rb.tt +25 -0
- data/lib/tasks/templates/controllers/pages_controller.rb.tt +29 -0
- data/lib/tasks/templates/db/migrate/create_post_types.rb.tt +14 -0
- data/lib/tasks/templates/db/migrate/create_posts.rb.tt +31 -0
- data/lib/tasks/templates/models/post.rb.tt +8 -0
- data/lib/tasks/templates/models/post_type.rb.tt +8 -0
- data/lib/tasks/templates/views/collections/index.html.erb.tt +67 -0
- data/lib/tasks/templates/views/collections/show.html.erb.tt +39 -0
- data/lib/tasks/templates/views/layouts/bunko_footer.html.erb.tt +3 -0
- data/lib/tasks/templates/views/layouts/bunko_nav.html.erb.tt +9 -0
- data/lib/tasks/templates/views/layouts/bunko_styles.html.erb.tt +3 -0
- data/lib/tasks/templates/views/pages/show.html.erb.tt +16 -0
- data/sig/bunko.rbs +4 -0
- metadata +116 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class <%= controller_name %> < ApplicationController
|
|
4
|
+
bunko_collection :<%= collection_name %>
|
|
5
|
+
|
|
6
|
+
# The bunko_collection method automatically provides index and show actions.
|
|
7
|
+
#
|
|
8
|
+
# To customize, you can override these methods:
|
|
9
|
+
#
|
|
10
|
+
# def index
|
|
11
|
+
# super # calls bunko_collection's index
|
|
12
|
+
# # Add your customizations here
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# def show
|
|
16
|
+
# super # calls bunko_collection's show
|
|
17
|
+
# # Add your customizations here
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# Available instance variables in your views:
|
|
21
|
+
# - @posts (index action)
|
|
22
|
+
# - @post (show action)
|
|
23
|
+
# - @collection_name
|
|
24
|
+
# - @pagination
|
|
25
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class PagesController < ApplicationController
|
|
4
|
+
def show
|
|
5
|
+
# Extract page slug from request path (not user-controllable params)
|
|
6
|
+
# This prevents path traversal attacks via query string manipulation
|
|
7
|
+
# e.g., GET /about?page=../../admin/users
|
|
8
|
+
page_slug = request.path.split('/').reject(&:empty?).last
|
|
9
|
+
|
|
10
|
+
@post = Post.published.find_by(
|
|
11
|
+
post_type: PostType.find_by(name: "pages"),
|
|
12
|
+
slug: page_slug
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
unless @post
|
|
16
|
+
raise ActiveRecord::RecordNotFound, "Page not found"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Check if a custom view exists for this page
|
|
20
|
+
# Use DB-validated slug to prevent rendering arbitrary templates
|
|
21
|
+
# e.g., app/views/pages/about.html.erb
|
|
22
|
+
if template_exists?(@post.slug, "pages")
|
|
23
|
+
render @post.slug
|
|
24
|
+
else
|
|
25
|
+
# Otherwise render the default show.html.erb
|
|
26
|
+
render :show
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePostTypes < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
4
|
+
def change
|
|
5
|
+
create_table :post_types do |t|
|
|
6
|
+
t.string :name, null: false # Identifier (e.g., "blog", "case_studies")
|
|
7
|
+
t.string :title, null: false # Display name (e.g., "Blog", "Case Studies")
|
|
8
|
+
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
add_index :post_types, :name, unique: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreatePosts < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
4
|
+
def change
|
|
5
|
+
create_table :posts do |t|
|
|
6
|
+
t.string :title, null: false
|
|
7
|
+
t.string :slug, null: false
|
|
8
|
+
<% if use_json_content? -%>
|
|
9
|
+
t.jsonb :content
|
|
10
|
+
<% else -%>
|
|
11
|
+
t.text :content
|
|
12
|
+
<% end -%>
|
|
13
|
+
t.references :post_type, null: false, foreign_key: true
|
|
14
|
+
t.string :status, null: false, default: "draft"
|
|
15
|
+
t.datetime :published_at
|
|
16
|
+
<% if include_seo_fields? -%>
|
|
17
|
+
|
|
18
|
+
# SEO fields
|
|
19
|
+
t.string :title_tag
|
|
20
|
+
t.text :meta_description
|
|
21
|
+
<% end -%>
|
|
22
|
+
|
|
23
|
+
# Metrics
|
|
24
|
+
t.integer :word_count
|
|
25
|
+
|
|
26
|
+
t.timestamps
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
add_index :posts, [:post_type_id, :slug], unique: true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class PostType < ApplicationRecord
|
|
4
|
+
acts_as_bunko_post_type
|
|
5
|
+
|
|
6
|
+
# All standard Bunko behavior (associations, validations) is included via acts_as_bunko_post_type
|
|
7
|
+
# Add custom validations, associations, or methods below as needed
|
|
8
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<%%= render "shared/bunko_styles" %>
|
|
2
|
+
<%%= render "shared/bunko_nav" %>
|
|
3
|
+
|
|
4
|
+
<main class="container <%= collection_name %>-index">
|
|
5
|
+
<h1><%= collection_title %></h1>
|
|
6
|
+
|
|
7
|
+
<%% if @posts.any? %>
|
|
8
|
+
<div class="posts">
|
|
9
|
+
<%% @posts.each do |post| %>
|
|
10
|
+
<article class="post-preview">
|
|
11
|
+
<h2>
|
|
12
|
+
<% if is_collection %>
|
|
13
|
+
<%# Collections link to canonical PostType URLs %>
|
|
14
|
+
<%%= link_to post.title, send("#{post.post_type.name.singularize}_path", post.slug) %>
|
|
15
|
+
<% else %>
|
|
16
|
+
<%# PostTypes link to their own show page %>
|
|
17
|
+
<%%= link_to post.title, <%= path_helper %>(post.slug) %>
|
|
18
|
+
<% end %>
|
|
19
|
+
</h2>
|
|
20
|
+
|
|
21
|
+
<div class="post-meta">
|
|
22
|
+
<strong>
|
|
23
|
+
<%% if post.published_at %>
|
|
24
|
+
<time datetime="<%%= post.published_at.iso8601 %>">
|
|
25
|
+
<%%= post.published_at.strftime("%B %d, %Y") %>
|
|
26
|
+
</time>
|
|
27
|
+
<%% end %>
|
|
28
|
+
|
|
29
|
+
<%% if post.reading_time %>
|
|
30
|
+
<span> • </span>
|
|
31
|
+
<span class="reading-time">
|
|
32
|
+
<%%= post.reading_time %> min read
|
|
33
|
+
</span>
|
|
34
|
+
<%% end %>
|
|
35
|
+
</strong>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<%% if post.content.present? %>
|
|
39
|
+
<div class="post-excerpt">
|
|
40
|
+
<%%= post.excerpt(length: 200) %>
|
|
41
|
+
</div>
|
|
42
|
+
<%% end %>
|
|
43
|
+
</article>
|
|
44
|
+
<%% end %>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<%% if @pagination[:total_pages] > 1 %>
|
|
48
|
+
<section class="pagination" style=display: flex; justify-content: space-between;">
|
|
49
|
+
<%% if @pagination[:prev_page] %>
|
|
50
|
+
<%%= link_to "← Previous", <%= index_path_helper %>(page: @pagination[:current_page] - 1), class: "pagination-prev" %>
|
|
51
|
+
<%% end %>
|
|
52
|
+
|
|
53
|
+
<span class="pagination-info">
|
|
54
|
+
Page <%%= @pagination[:current_page] %> of <%%= @pagination[:total_pages] %>
|
|
55
|
+
</span>
|
|
56
|
+
|
|
57
|
+
<%% if @pagination[:next_page] %>
|
|
58
|
+
<%%= link_to "Next →", <%= index_path_helper %>(page: @pagination[:current_page] + 1), class: "pagination-next" %>
|
|
59
|
+
<%% end %>
|
|
60
|
+
</section>
|
|
61
|
+
<%% end %>
|
|
62
|
+
<%% else %>
|
|
63
|
+
<p class="no-posts">No <%= collection_title.downcase %> posts yet.</p>
|
|
64
|
+
<%% end %>
|
|
65
|
+
</main>
|
|
66
|
+
|
|
67
|
+
<%%= render "shared/bunko_footer" %>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<%%= render "shared/bunko_styles" %>
|
|
2
|
+
<%%= render "shared/bunko_nav" %>
|
|
3
|
+
|
|
4
|
+
<main class="container">
|
|
5
|
+
<article class="post">
|
|
6
|
+
<header class="post-header">
|
|
7
|
+
<h1><%%= @post.title %></h1>
|
|
8
|
+
|
|
9
|
+
<div class="post-meta">
|
|
10
|
+
<%% if @post.published_at %>
|
|
11
|
+
<time datetime="<%%= @post.published_at.iso8601 %>">
|
|
12
|
+
<%%= @post.published_at.strftime("%B %d, %Y") %>
|
|
13
|
+
</time>
|
|
14
|
+
<%% end %>
|
|
15
|
+
|
|
16
|
+
<%% if @post.reading_time %>
|
|
17
|
+
<span> • </span>
|
|
18
|
+
<span class="reading-time">
|
|
19
|
+
<%%= @post.reading_time %> min read
|
|
20
|
+
</span>
|
|
21
|
+
<%% end %>
|
|
22
|
+
</div>
|
|
23
|
+
</header>
|
|
24
|
+
|
|
25
|
+
<div class="post-content">
|
|
26
|
+
<% if format == "html" -%>
|
|
27
|
+
<%%= sanitize(@post.content) %>
|
|
28
|
+
<% else -%>
|
|
29
|
+
<%%= simple_format(@post.content) %>
|
|
30
|
+
<% end -%>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<footer class="post-footer">
|
|
34
|
+
<%%= link_to "← Back to <%= collection_title %>", <%= index_path_helper %>, class: "back-link" %>
|
|
35
|
+
</footer>
|
|
36
|
+
</article>
|
|
37
|
+
</main>
|
|
38
|
+
|
|
39
|
+
<%%= render "shared/bunko_footer" %>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<header class="container">
|
|
2
|
+
<nav style="gap: 1rem;">
|
|
3
|
+
<%%= link_to "Home", root_path %>
|
|
4
|
+
|
|
5
|
+
<div style="display: flex; gap: 1rem; flex-wrap: wrap; justify-content: end;">
|
|
6
|
+
<%%# bunko_collection_links - additional collections will be added here unless you delete this line %>
|
|
7
|
+
</div>
|
|
8
|
+
</nav>
|
|
9
|
+
</header>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<%%# Bunko ships our basic view files with https://picocss.com/ to give you a basic styled experience. %>
|
|
2
|
+
<%%# Feel free to delete this partial and references as you add your own design. %>
|
|
3
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<%%= render "shared/bunko_styles" %>
|
|
2
|
+
<%%= render "shared/bunko_nav" %>
|
|
3
|
+
|
|
4
|
+
<main class="container">
|
|
5
|
+
<article class="page">
|
|
6
|
+
<header class="page-header">
|
|
7
|
+
<h1><%%= @post.title %></h1>
|
|
8
|
+
</header>
|
|
9
|
+
|
|
10
|
+
<div class="page-content">
|
|
11
|
+
<%%= sanitize(@post.content) %>
|
|
12
|
+
</div>
|
|
13
|
+
</article>
|
|
14
|
+
</main>
|
|
15
|
+
|
|
16
|
+
<%%= render "shared/bunko_footer" %>
|
data/sig/bunko.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: bunko
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Kane Jamison
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '8.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '8.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: sqlite3
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.0'
|
|
40
|
+
description: Bunko provides a lightweight CMS structure for Rails based on a 'one
|
|
41
|
+
model, infinite collections' philosophy. Create multiple content collections (blog,
|
|
42
|
+
docs, changelog) without duplicate code or migrations.
|
|
43
|
+
email:
|
|
44
|
+
- 918780+kanejamison@users.noreply.github.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- ".standard.yml"
|
|
50
|
+
- CHANGELOG.md
|
|
51
|
+
- CLAUDE.md
|
|
52
|
+
- LICENSE.txt
|
|
53
|
+
- README.md
|
|
54
|
+
- ROADMAP.md
|
|
55
|
+
- Rakefile
|
|
56
|
+
- lib/bunko.rb
|
|
57
|
+
- lib/bunko/configuration.rb
|
|
58
|
+
- lib/bunko/controllers.rb
|
|
59
|
+
- lib/bunko/controllers/acts_as.rb
|
|
60
|
+
- lib/bunko/controllers/collection.rb
|
|
61
|
+
- lib/bunko/models.rb
|
|
62
|
+
- lib/bunko/models/acts_as.rb
|
|
63
|
+
- lib/bunko/models/post_methods.rb
|
|
64
|
+
- lib/bunko/models/post_methods/publishable.rb
|
|
65
|
+
- lib/bunko/models/post_methods/sluggable.rb
|
|
66
|
+
- lib/bunko/models/post_methods/word_countable.rb
|
|
67
|
+
- lib/bunko/models/post_type_methods.rb
|
|
68
|
+
- lib/bunko/railtie.rb
|
|
69
|
+
- lib/bunko/routing.rb
|
|
70
|
+
- lib/bunko/routing/mapper_methods.rb
|
|
71
|
+
- lib/bunko/version.rb
|
|
72
|
+
- lib/tasks/bunko/add.rake
|
|
73
|
+
- lib/tasks/bunko/helpers.rb
|
|
74
|
+
- lib/tasks/bunko/install.rake
|
|
75
|
+
- lib/tasks/bunko/sample_data.rake
|
|
76
|
+
- lib/tasks/bunko/setup.rake
|
|
77
|
+
- lib/tasks/support/sample_data_generator.rb
|
|
78
|
+
- lib/tasks/templates/INSTALL.md
|
|
79
|
+
- lib/tasks/templates/config/initializers/bunko.rb.tt
|
|
80
|
+
- lib/tasks/templates/controllers/controller.rb.tt
|
|
81
|
+
- lib/tasks/templates/controllers/pages_controller.rb.tt
|
|
82
|
+
- lib/tasks/templates/db/migrate/create_post_types.rb.tt
|
|
83
|
+
- lib/tasks/templates/db/migrate/create_posts.rb.tt
|
|
84
|
+
- lib/tasks/templates/models/post.rb.tt
|
|
85
|
+
- lib/tasks/templates/models/post_type.rb.tt
|
|
86
|
+
- lib/tasks/templates/views/collections/index.html.erb.tt
|
|
87
|
+
- lib/tasks/templates/views/collections/show.html.erb.tt
|
|
88
|
+
- lib/tasks/templates/views/layouts/bunko_footer.html.erb.tt
|
|
89
|
+
- lib/tasks/templates/views/layouts/bunko_nav.html.erb.tt
|
|
90
|
+
- lib/tasks/templates/views/layouts/bunko_styles.html.erb.tt
|
|
91
|
+
- lib/tasks/templates/views/pages/show.html.erb.tt
|
|
92
|
+
- sig/bunko.rbs
|
|
93
|
+
homepage: https://github.com/kanejamison/bunko
|
|
94
|
+
licenses:
|
|
95
|
+
- MIT
|
|
96
|
+
metadata:
|
|
97
|
+
homepage_uri: https://github.com/kanejamison/bunko
|
|
98
|
+
changelog_uri: https://github.com/kanejamison/bunko/blob/main/CHANGELOG.md
|
|
99
|
+
rdoc_options: []
|
|
100
|
+
require_paths:
|
|
101
|
+
- lib
|
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
|
+
requirements:
|
|
104
|
+
- - ">="
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '3.2'
|
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '0'
|
|
112
|
+
requirements: []
|
|
113
|
+
rubygems_version: 3.6.9
|
|
114
|
+
specification_version: 4
|
|
115
|
+
summary: A simple and lightweight content management system for Rails.
|
|
116
|
+
test_files: []
|