perron 0.17.0 → 1.0.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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +25 -2
  4. data/app/controllers/perron/concierge_controller.rb +13 -0
  5. data/app/controllers/perron/searches_controller.rb +48 -0
  6. data/app/helpers/perron/feeds_helper.rb +7 -0
  7. data/app/helpers/perron/markdown_helper.rb +3 -3
  8. data/app/helpers/perron/meta_tags_helper.rb +17 -0
  9. data/app/views/perron/concierge/show.html.erb +271 -0
  10. data/bin/release +19 -4
  11. data/lib/generators/rails/content/USAGE +45 -26
  12. data/lib/generators/rails/content/content_generator.rb +16 -13
  13. data/lib/generators/rails/content/templates/controller.rb.tt +7 -5
  14. data/lib/generators/rails/content/templates/model.rb.tt +4 -4
  15. data/lib/perron/assets/icon.png +0 -0
  16. data/lib/perron/assets/icon.svg +1 -0
  17. data/lib/perron/collection.rb +10 -1
  18. data/lib/perron/configuration.rb +13 -4
  19. data/lib/perron/content/data.rb +6 -2
  20. data/lib/perron/data_source/class_methods.rb +66 -0
  21. data/lib/perron/data_source/helper_context.rb +20 -0
  22. data/lib/perron/data_source/item.rb +37 -0
  23. data/lib/perron/{data → data_source}/proxy.rb +1 -1
  24. data/lib/perron/data_source.rb +140 -0
  25. data/lib/perron/development_feed_server.rb +69 -0
  26. data/lib/perron/engine.rb +41 -1
  27. data/lib/perron/errors.rb +2 -0
  28. data/lib/perron/feeds.rb +4 -3
  29. data/lib/perron/html_processor/absolute_urls.rb +27 -0
  30. data/lib/perron/html_processor/base.rb +2 -2
  31. data/lib/perron/html_processor.rb +7 -11
  32. data/lib/perron/install/README.md.tt +67 -0
  33. data/lib/{generators/perron/templates → perron/install}/initializer.rb.tt +8 -4
  34. data/lib/perron/install.rb +23 -0
  35. data/lib/perron/markdown.rb +2 -2
  36. data/lib/perron/output_server.rb +16 -2
  37. data/lib/perron/relation.rb +51 -0
  38. data/lib/perron/resource/adjacency.rb +70 -0
  39. data/lib/perron/resource/associations.rb +3 -3
  40. data/lib/perron/resource/class_methods.rb +10 -0
  41. data/lib/perron/resource/configuration.rb +16 -14
  42. data/lib/perron/resource/core.rb +11 -0
  43. data/lib/perron/resource/metadata.rb +10 -1
  44. data/lib/perron/resource/publishable.rb +2 -0
  45. data/lib/perron/resource/related/stop_words.rb +20 -20
  46. data/lib/perron/resource/related.rb +76 -54
  47. data/lib/perron/resource/scopes.rb +29 -0
  48. data/lib/perron/resource/searchable.rb +19 -0
  49. data/lib/perron/resource/sourceable.rb +39 -9
  50. data/lib/perron/resource/sweeper.rb +45 -0
  51. data/lib/perron/resource/table_of_content.rb +0 -18
  52. data/lib/perron/resource.rb +32 -20
  53. data/lib/perron/site/builder/assets.rb +1 -1
  54. data/lib/perron/site/builder/feeds/atom.erb +44 -0
  55. data/lib/perron/site/builder/feeds/atom.rb +41 -0
  56. data/lib/perron/site/builder/feeds/json.erb +19 -0
  57. data/lib/perron/site/builder/feeds/json.rb +7 -33
  58. data/lib/perron/site/builder/feeds/rss.erb +28 -0
  59. data/lib/perron/site/builder/feeds/rss.rb +6 -28
  60. data/lib/perron/site/builder/feeds/template.rb +63 -0
  61. data/lib/perron/site/builder/feeds.rb +8 -3
  62. data/lib/perron/site/builder/paths.rb +58 -14
  63. data/lib/perron/site/builder/route_resources.rb +79 -0
  64. data/lib/perron/site/builder/sitemap.rb +71 -20
  65. data/lib/perron/site/builder.rb +1 -1
  66. data/lib/perron/site/validate.rb +1 -2
  67. data/lib/perron/site.rb +10 -3
  68. data/lib/perron/tasks/build.rake +6 -0
  69. data/lib/perron/tasks/install.rake +12 -0
  70. data/lib/perron/version.rb +1 -1
  71. data/lib/perron.rb +1 -0
  72. data/perron.gemspec +1 -0
  73. metadata +45 -10
  74. data/app/helpers/feeds_helper.rb +0 -5
  75. data/app/helpers/meta_tags_helper.rb +0 -15
  76. data/lib/generators/perron/install_generator.rb +0 -32
  77. data/lib/generators/perron/templates/README.md.tt +0 -45
  78. data/lib/perron/data.rb +0 -180
  79. data/lib/perron/html_processor/syntax_highlight.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbf1b0d5483938df7b88423f3ecd72bffaf938eadcc49a3001a34fcb0156dfb9
4
- data.tar.gz: cd8871c7ef91a102a45bcebbcdc8bbf385db3a83ffb34948cd0d3e49c14d8237
3
+ metadata.gz: 72473e733aa6ec4313dc71e66b2a949dea6497b427e304cb4656be0d0a5fbc86
4
+ data.tar.gz: 37a57b14891cf3fef0dfb1a4c98b414852fdd1bd3f3e377c674e15673f6d2547
5
5
  SHA512:
6
- metadata.gz: 4d21cfbf61b54fb704990a23cbbf73285364e37ab722246c0202ecea37616398edcfe3fc9f841bc3cae9100108cb61e37200780c0e0ef667515f6e27319498e4
7
- data.tar.gz: bed9e2b68bf2a5697a72a6b3bcb2dfcdb6898b93e31b6bc68b169583462d9e4a4f3e345dec8470077b2566dd31860e8ca97ce83cd82b8a01aff889ad0d5a7d14
6
+ metadata.gz: 478b181f494c2c0ac54e996c0d9f289c7694bedbcd203fd435c9222ecdd07ad6c5a3f5e8baeb497ee2f77499e3580f0f915439d2feba1edf8ab42385285a7e96
7
+ data.tar.gz: 19750396f542ac909322aa5cd3ed247dc10a03509ab521bdb75dd0ae705c502e80b3431737d5c34eb42bcacda17c0ef0c35889cb65561339646f6eb7a2ee1e58
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
- gem "rails", "~> 7.2.0"
7
+ gem "appraisal"
8
8
 
9
9
  group :development do
10
10
  gem "standard", "~> 1.50.0"
data/Gemfile.lock CHANGED
@@ -1,9 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- perron (0.17.0)
4
+ perron (1.0.0)
5
5
  csv
6
6
  json
7
+ mata (~> 0.8.0)
7
8
  psych
8
9
  rails (>= 7.2.0)
9
10
 
@@ -81,6 +82,10 @@ GEM
81
82
  minitest (>= 5.1)
82
83
  securerandom (>= 0.3)
83
84
  tzinfo (~> 2.0, >= 2.0.5)
85
+ appraisal (2.5.0)
86
+ bundler
87
+ rake
88
+ thor (>= 0.14.0)
84
89
  ast (2.4.3)
85
90
  base64 (0.3.0)
86
91
  benchmark (0.4.1)
@@ -97,6 +102,14 @@ GEM
97
102
  drb (2.2.3)
98
103
  erb (5.0.1)
99
104
  erubi (1.13.1)
105
+ ffi (1.17.3-aarch64-linux-gnu)
106
+ ffi (1.17.3-aarch64-linux-musl)
107
+ ffi (1.17.3-arm-linux-gnu)
108
+ ffi (1.17.3-arm-linux-musl)
109
+ ffi (1.17.3-arm64-darwin)
110
+ ffi (1.17.3-x86_64-darwin)
111
+ ffi (1.17.3-x86_64-linux-gnu)
112
+ ffi (1.17.3-x86_64-linux-musl)
100
113
  globalid (1.2.1)
101
114
  activesupport (>= 6.1)
102
115
  i18n (1.14.7)
@@ -109,6 +122,10 @@ GEM
109
122
  json (2.12.2)
110
123
  language_server-protocol (3.17.0.5)
111
124
  lint_roller (1.1.0)
125
+ listen (3.10.0)
126
+ logger
127
+ rb-fsevent (~> 0.10, >= 0.10.3)
128
+ rb-inotify (~> 0.9, >= 0.9.10)
112
129
  logger (1.7.0)
113
130
  loofah (2.24.1)
114
131
  crass (~> 1.0.2)
@@ -119,6 +136,9 @@ GEM
119
136
  net-pop
120
137
  net-smtp
121
138
  marcel (1.0.4)
139
+ mata (0.8.0)
140
+ listen (~> 3.0)
141
+ rack (>= 3.0)
122
142
  mini_mime (1.1.5)
123
143
  mini_portile2 (2.8.9)
124
144
  minitest (5.27.0)
@@ -202,6 +222,9 @@ GEM
202
222
  zeitwerk (~> 2.6)
203
223
  rainbow (3.1.1)
204
224
  rake (13.3.0)
225
+ rb-fsevent (0.11.2)
226
+ rb-inotify (0.11.1)
227
+ ffi (~> 1.0)
205
228
  rdoc (6.14.2)
206
229
  erb
207
230
  psych (>= 4.0.0)
@@ -267,10 +290,10 @@ PLATFORMS
267
290
  x86_64-linux-musl
268
291
 
269
292
  DEPENDENCIES
293
+ appraisal
270
294
  debug (~> 1.11.0)
271
295
  minitest (~> 5.25, >= 5.25.5)
272
296
  perron!
273
- rails (~> 7.2.0)
274
297
  rake (~> 13.3.0)
275
298
  rouge (~> 4.6.0)
276
299
  standard (~> 1.50.0)
@@ -0,0 +1,13 @@
1
+ module Perron
2
+ class ConciergeController < ActionController::Base
3
+ def show
4
+ render :show
5
+ end
6
+
7
+ def run_command
8
+ system(params[:command])
9
+
10
+ redirect_back fallback_location: root_path
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Perron
4
+ class SearchesController < ApplicationController
5
+ before_action :force_json, only: %w[show]
6
+
7
+ def show
8
+ resources = search_scope.flat_map(&:all)
9
+ index = resources.map do |resource|
10
+ base_fields(resource).merge(additional_search_fields(resource))
11
+ end
12
+
13
+ render json: index
14
+ end
15
+
16
+ private
17
+
18
+ def force_json
19
+ request.format = :json
20
+ end
21
+
22
+ def search_scope
23
+ Perron
24
+ .configuration
25
+ .search_scope
26
+ .map { "Content::#{it.classify}".safe_constantize }
27
+ .compact_blank
28
+ end
29
+
30
+ def base_fields(resource)
31
+ {
32
+ slug: polymorphic_path(resource),
33
+ href: polymorphic_path(resource),
34
+ title: resource.try(:title) || resource.metadata.title,
35
+ headings: resource.extracted_headings.flatten.join(" "),
36
+ body: resource.sweeped_content
37
+ }
38
+ end
39
+
40
+ def additional_search_fields(resource)
41
+ return {} unless resource.class.search_fields_list.any?
42
+
43
+ resource.class.search_fields_list.to_h do |field|
44
+ [field, resource.public_send(field)]
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Perron
4
+ module FeedsHelper
5
+ def feeds(options = {}) = Perron::Feeds.new.render(options)
6
+ end
7
+ end
@@ -4,10 +4,10 @@ require "perron/markdown"
4
4
 
5
5
  module Perron
6
6
  module MarkdownHelper
7
- def markdownify(content = nil, options = {}, &block)
8
- processors = options.fetch(:process, [])
7
+ def markdownify(content = nil, process: [], resource: nil, &block)
8
+ text = block_given? ? capture(&block).strip_heredoc : content
9
9
 
10
- Perron::Markdown.render(content || capture(&block).strip_heredoc, processors: processors)
10
+ Perron::Markdown.render(text, processors: process, resource: resource || @resource)
11
11
  end
12
12
  end
13
13
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Perron
4
+ module MetaTagsHelper
5
+ def meta_tags(options = {}) = Perron::Metatags.new(resource.metadata).render(options)
6
+
7
+ private
8
+
9
+ Resource = Data.define(:path, :collection, :metadata, :published_at)
10
+
11
+ def resource
12
+ return Resource.new(request.path, nil, @metadata, nil) if @metadata.present?
13
+
14
+ @resource || Resource.new(request.path, nil, {}, nil)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,271 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>Welcome to Perron</title>
5
+ <meta charset="utf-8">
6
+
7
+ <link rel="icon" href="/icon.png" type="image/png">
8
+ <link rel="apple-touch-icon" href="/icon.png" sizes="512x512">
9
+
10
+ <style>
11
+ * { margin: 0; padding: 0; box-sizing: border-box; }
12
+ ul { list-style: none; }
13
+
14
+ a {
15
+ color: #1f2937;
16
+
17
+ &:hover: { text-decoration: none; }
18
+ }
19
+
20
+ body {
21
+ padding: 2rem 1rem;
22
+ min-height: 100vh;
23
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
24
+ line-height: 1.6;
25
+ color: #1f2937;
26
+ background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
27
+ }
28
+
29
+ .hero {
30
+ max-width: 72rem;
31
+ margin: 0 auto 4rem;
32
+ padding: 3rem 0;
33
+
34
+ h1 {
35
+ font-size: clamp(2rem, 5vw, 3.5rem);
36
+ font-weight: 900;
37
+ text-align: center;
38
+ color: #111827;
39
+ letter-spacing: -.025em;
40
+ }
41
+
42
+ ul {
43
+ display: grid;
44
+ row-gap: 1rem;
45
+ margin: 1rem auto 0;
46
+ max-width: 48rem;
47
+ padding: 1rem;
48
+ background: white;
49
+ border-radius: .5rem;
50
+ border: 1px solid #e5e7eb;
51
+
52
+ li {
53
+ border-radius: .5rem;
54
+
55
+ p { font-weight: 600; }
56
+
57
+ div {
58
+ display: grid;
59
+ grid-template-columns: 1fr min-content;
60
+ margin-top: .25rem;
61
+ padding: .75rem 1rem;
62
+ background-color: rgb(248 250 252);
63
+ border-radius: .5rem;
64
+ }
65
+
66
+ code {
67
+ font-size: .875rem;
68
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
69
+ font-weight: 500;
70
+ color: rgb(51 65 85);
71
+ overflow: auto;
72
+ white-space: nowrap;
73
+ user-select: all;
74
+ }
75
+
76
+ svg {
77
+ width: 1.125rem;
78
+ aspect-ratio: 1/1;
79
+ color: rgb(100 116 139);
80
+ }
81
+
82
+ input[type=submit] {
83
+ border: 0;
84
+ padding: .25rem 1rem;
85
+ font-size: .875rem;
86
+ font-weight: 300;
87
+ color: white;
88
+ background-color: rgb(249 115 22);
89
+ border-radius: .25rem;
90
+ transition: background-color 300ms ease;
91
+ cursor: pointer;
92
+
93
+ &:hover {
94
+ background-color: rgb(251 146 60);
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ .info {
102
+ display: grid;
103
+ gap: 2rem;
104
+ max-width: 6xl;
105
+ margin: 0 auto;
106
+ overflow-x: clip;
107
+
108
+ @media (min-width: 768px) {
109
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
110
+ }
111
+
112
+ li {
113
+ &:nth-child(odd) {
114
+ @media (min-width: 640px) {
115
+ transform: rotate(-1deg);
116
+ }
117
+ }
118
+
119
+ &:nth-child(even) {
120
+ @media (min-width: 640px) {
121
+ transform: rotate(1deg);
122
+ }
123
+ }
124
+ }
125
+
126
+ a {
127
+ display: block;
128
+ padding: 2rem 1.5rem;
129
+ text-decoration: none;
130
+ background: white;
131
+ border: 1px solid #e5e7eb;
132
+ border-radius: 1rem;
133
+ transition: all 300ms ease;
134
+
135
+ &:hover {
136
+ transform: translateY(-4px);
137
+ box-shadow: 0 20px 25px -5px rgb(0 0 0 / .1);
138
+ }
139
+
140
+ h2 {
141
+ font-size: 1.25rem;
142
+ font-weight: 700;
143
+ color: #111827;
144
+ }
145
+
146
+ p {
147
+ margin-top: .25rem;
148
+ color: #4b5563;
149
+ line-height: 1.7;
150
+
151
+ a {
152
+ color: #f97316;
153
+ text-decoration: none;
154
+ font-weight: 500;
155
+ transition: color 200ms ease;
156
+
157
+ &:hover {
158
+ color: #ea580c;
159
+ text-decoration: underline;
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+
166
+ .versions {
167
+ display: flex;
168
+ align-items: center;
169
+ justify-content: center;
170
+ column-gap: 1.5rem;
171
+ margin-top: 2rem;
172
+ font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
173
+ text-align: center;
174
+ color: #6b7280;
175
+ font-size: .75rem;
176
+ }
177
+ </style>
178
+ </head>
179
+
180
+ <body>
181
+ <section class="hero">
182
+ <h1>Welcome to Perron</h1>
183
+
184
+ <ul>
185
+ <li>
186
+ <p>
187
+ Create a collection
188
+ </p>
189
+
190
+ <div>
191
+ <code>bin/rails generate content Post</code>
192
+
193
+ <%= form_with url: perron_run_command_path do |form| %>
194
+ <%= form.hidden_field :command, value: "bin/rails generate content Post" %>
195
+
196
+ <% if defined?(Content::Post) %>
197
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm45.66,85.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z"/></svg>
198
+ <% else %>
199
+ <%= form.submit "Run" %>
200
+ <% end %>
201
+ <% end %>
202
+ </div>
203
+ </li>
204
+
205
+ <li>
206
+ <p>
207
+ Create your first content
208
+ </p>
209
+
210
+ <div>
211
+ <code>bin/rails generate content Post --new "My first post"</code>
212
+
213
+ <%= form_with url: perron_run_command_path do |form| %>
214
+ <%= form.hidden_field :command, value: 'bin/rails generate content Post --new "My first post"' %>
215
+
216
+ <% if File.file?("app/content/posts/untitled.md") %>
217
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm45.66,85.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z"/></svg>
218
+ <% else %>
219
+ <%= form.submit "Run" %>
220
+ <% end %>
221
+ <% end %>
222
+ </div>
223
+ </li>
224
+
225
+ <li>
226
+ <p>
227
+ Run the server, and visit <code><a href="/posts/">http://localhost:3000/posts/</a></code>
228
+ </p>
229
+
230
+ <div>
231
+ <code>bin/dev</code>
232
+ </div>
233
+ </li>
234
+ </ul>
235
+ </section>
236
+
237
+ <ul class="info">
238
+ <li>
239
+ <a href="https://perron.railsdesigner.com/docs/">
240
+ <h2>Documentation</h2>
241
+
242
+ <p>Visit the docs for more</p>
243
+ </a>
244
+ </li>
245
+
246
+ <li>
247
+ <a href="https://perron.railsdesigner.com/library/">
248
+ <h2>Library</h2>
249
+
250
+ <p>Check out the library for snippets, components and templates</p>
251
+ </a>
252
+ </li>
253
+
254
+ <li>
255
+ <a href="https://github.com/Rails-Designer/perron">
256
+ <h2>GitHub</h2>
257
+
258
+ <p>Check out Perron's source</p>
259
+ </a>
260
+ </li>
261
+ </ul>
262
+
263
+ <div class="versions">
264
+ <span>Ruby <%= RUBY_VERSION %></span>
265
+
266
+ <span>Rails <%= Rails.version %></span>
267
+
268
+ <span>Perron <%= Perron::VERSION %></span>
269
+ </div>
270
+ </body>
271
+ </html>
data/bin/release CHANGED
@@ -3,17 +3,32 @@
3
3
  VERSION=$1
4
4
 
5
5
  if [ -z "$VERSION" ]; then
6
- echo "Error: The version number is required."
7
- echo "Usage: $0 <version-number>"
6
+ echo "Error: Version number or bump type is required"
7
+ echo " Usage: $0 <major|minor|patch|version-number>"
8
+
8
9
  exit 1
9
10
  fi
10
11
 
12
+ if [[ "$VERSION" =~ ^(major|minor|patch)$ ]]; then
13
+ CURRENT=$(grep -o '"[^"]*"' ./lib/perron/version.rb | tr -d '"')
14
+ IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
15
+
16
+ case $VERSION in
17
+ major) VERSION="$((MAJOR + 1)).0.0" ;;
18
+ minor) VERSION="$MAJOR.$((MINOR + 1)).0" ;;
19
+ patch) VERSION="$MAJOR.$MINOR.$((PATCH + 1))" ;;
20
+ esac
21
+ fi
22
+
11
23
  printf "module Perron\n VERSION = \"$VERSION\"\nend\n" > ./lib/perron/version.rb
24
+
12
25
  bundle
26
+
13
27
  git add Gemfile.lock lib/perron/version.rb
14
28
  git commit -m "Bump version for $VERSION"
15
29
  git push
16
30
  git tag v$VERSION
17
31
  git push --tags
18
- gem build perron.gemspec
19
- gem push "perron-$VERSION.gem"
32
+
33
+ bundle exec rake build
34
+ gem push "pkg/perron-$VERSION.gem"
@@ -2,63 +2,82 @@ Description:
2
2
  Generates content model scaffold (controller, views, routes) or creates
3
3
  new content files from templates.
4
4
 
5
+ Arguments:
6
+ NAME Name of the content model (singular or plural)
7
+ actions Actions to generate (default: index show)
8
+
9
+ Options:
10
+ --new [TITLE] Create new content file instead of scaffold
11
+ --data [SOURCE...] Create data source files (default extension: .yml)
12
+ --force-plural Use plural form for model name and class
13
+ --[no-]include-root Include root action and route
14
+ (default: true for pages, false otherwise)
15
+ --inline Render show action inline instead of using view template
16
+
5
17
  Examples:
6
- Generate content scaffold:
18
+ Generate basic content scaffold:
7
19
  rails generate content Post
8
20
  rails generate content Post index
9
21
  rails generate content Post index show
10
22
 
11
- This will create:
23
+ Creates:
12
24
  app/content/posts/
13
25
  app/models/content/post.rb
14
26
  app/controllers/content/posts_controller.rb
15
27
  app/views/content/posts/index.html.erb
16
28
  app/views/content/posts/show.html.erb
17
29
 
18
- And adds: resources :posts, module: :content, only: %w[index show]
30
+ Adds route:
31
+ resources :posts, module: :content, only: %w[index show]
32
+
33
+ Generate inline show action:
34
+ rails generate content Post --inline
35
+
36
+ Creates controller with inline rendering:
37
+ def show
38
+ @resource = Content::Post.find!(params[:id])
39
+ render @resource.inline
40
+ end
41
+
42
+ Skips creating app/views/content/posts/show.html.erb
19
43
 
20
44
  Generate pages scaffold with root:
21
45
  rails generate content Page
22
46
 
23
- This will additionally create:
47
+ Additionally creates:
24
48
  app/content/pages/root.erb
25
- def root action in Content::PagesController
26
- root route in config/routes.rb (if not already defined)
49
+ root action in app/controllers/content/pages_controller.rb
50
+ root route in config/routes.rb
27
51
 
28
- Skip root generation for pages:
52
+ Control root generation:
29
53
  rails generate content Page --no-include-root
30
-
31
- Include root for non-pages content:
32
54
  rails generate content Article --include-root
33
55
 
34
- Generate content scaffold with data sources:
56
+ Generate scaffold with data sources:
35
57
  rails generate content Product --data countries products
36
58
  rails generate content Product --data countries.json products.yml
37
59
 
38
- This will additionally create data source files in app/content/products/
39
- and add sources/template_source class methods to the model.
60
+ Creates data source files in app/content/data/ and adds
61
+ .sources and .template_source class methods to the model.
40
62
 
41
63
  Create new content file from template:
42
64
  rails generate content Post --new
43
65
  rails generate content Post --new "My First Post"
44
66
 
45
- This will create a new content file in app/content/posts/ using:
46
- - YYYY-MM-DD-template.*.tt (if exists, with date prefix)
47
- - template.*.tt (if exists, without date prefix)
48
- - Empty file with frontmatter dashes (if no template)
67
+ Creates a new content file in app/content/posts/ using:
68
+ 1. Template file with strftime patterns (e.g., %Y-%m-%d-title.md.tt)
69
+ 2. Template file without strftime patterns (e.g., template.md.tt)
70
+ 3. Empty file with frontmatter dashes (if no template)
71
+
72
+ Template filename examples:
73
+ %Y-%m-%d-title.md.tt → 2026-03-10-my-post.md
74
+ %s-title.md.tt → 1741737600-my-post.md
75
+ %d-title.md.tt → 10-my-post.md
76
+ title.md.tt → my-post.md
77
+ %Y-%m.md.tt → 2026-03.md
49
78
 
50
79
  Template files support ERB:
51
80
  ---
52
81
  title: <%= @title %>
53
82
  published_at: <%= Time.current %>
54
83
  ---
55
-
56
- Arguments:
57
- NAME: Name of the content model (singular or plural)
58
- actions: Actions to generate (default: index show)
59
-
60
- Options:
61
- --new [TITLE]: Create new content file instead of scaffold
62
- --data [source1(.ext) source2(.ext)]: Create data source files (default extension: .yml)
63
- --force-plural: Use plural form for model name and class
64
- --[no-]include-root: Include root action and route (default: true for pages, false otherwise)