frozen_rails 0.0.2 → 0.0.3

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +78 -2
  3. data/lib/frozen_rails/appendable.rb +14 -0
  4. data/lib/frozen_rails/bundleable.rb +11 -0
  5. data/lib/frozen_rails/generator.rb +14 -0
  6. data/lib/frozen_rails/taggable.rb +59 -0
  7. data/lib/frozen_rails/version.rb +1 -1
  8. data/lib/frozen_rails.rb +0 -1
  9. data/lib/generators/frozen/db_generator.rb +68 -0
  10. data/lib/generators/frozen/dx_generator.rb +41 -0
  11. data/lib/generators/frozen/md_generator.rb +119 -0
  12. data/lib/generators/frozen/rails_generator.rb +39 -0
  13. data/lib/generators/frozen/seo_generator.rb +109 -0
  14. data/lib/generators/frozen/ssg_generator.rb +36 -0
  15. data/lib/generators/frozen/templates/db/avo.rb +10 -0
  16. data/lib/generators/frozen/templates/db/friendly_id.rb +14 -0
  17. data/lib/generators/frozen/templates/db/sqlite_uuid.rb +31 -0
  18. data/lib/generators/frozen/templates/db/static_db.rb +6 -0
  19. data/lib/generators/frozen/templates/dx/lib/templates/erb/scaffold/_form.html.erb.tt +1 -0
  20. data/lib/generators/frozen/templates/dx/lib/templates/erb/scaffold/edit.html.erb.tt +1 -0
  21. data/lib/generators/frozen/templates/dx/lib/templates/erb/scaffold/index.html.erb.tt +14 -0
  22. data/lib/generators/frozen/templates/dx/lib/templates/erb/scaffold/new.html.erb.tt +1 -0
  23. data/lib/generators/frozen/templates/dx/lib/templates/erb/scaffold/partial.html.erb.tt +17 -0
  24. data/lib/generators/frozen/templates/dx/lib/templates/erb/scaffold/show.html.erb.tt +7 -0
  25. data/lib/generators/frozen/templates/dx/lib/templates/rails/scaffold_controller/api_controller.rb.tt +22 -0
  26. data/lib/generators/frozen/templates/dx/lib/templates/rails/scaffold_controller/controller.rb.tt +19 -0
  27. data/lib/generators/frozen/templates/md/controllers/categories_controller.rb +11 -0
  28. data/lib/generators/frozen/templates/md/controllers/pages_controller.rb +7 -0
  29. data/lib/generators/frozen/templates/md/helpers/markdown_helper.rb +16 -0
  30. data/lib/generators/frozen/templates/md/initializers/decant_extensions.rb +17 -0
  31. data/lib/generators/frozen/templates/md/models/category.rb +36 -0
  32. data/lib/generators/frozen/templates/md/models/concerns/linkable.rb +42 -0
  33. data/lib/generators/frozen/templates/md/models/page.rb +14 -0
  34. data/lib/generators/frozen/templates/md/pages/frozen-rails.md +12 -0
  35. data/lib/generators/frozen/templates/md/pages/rails-static/rails-static-logo.webp +0 -0
  36. data/lib/generators/frozen/templates/md/pages/rails-static.md +17 -0
  37. data/lib/generators/frozen/templates/md/views/categories/index.html.erb +5 -0
  38. data/lib/generators/frozen/templates/md/views/categories/show.html.erb +13 -0
  39. data/lib/generators/frozen/templates/md/views/pages/show.html.erb +5 -0
  40. data/lib/generators/frozen/templates/seo/_og_meta_tags.html.erb +3 -0
  41. data/lib/generators/frozen/templates/seo/robots_generatable.rb +14 -0
  42. data/lib/generators/frozen/templates/seo/sitemap.rb +15 -0
  43. data/lib/generators/frozen/templates/seo/sitemap_entry.rb +12 -0
  44. data/lib/generators/frozen/templates/ui/cable.yml +5 -0
  45. data/lib/generators/frozen/templates/ui/hotkey_controller.js +9 -0
  46. data/lib/generators/frozen/ui_generator.rb +81 -0
  47. metadata +61 -6
  48. data/lib/frozen_rails/railtie.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e185eb3c340edef2f4261d427c7f89af260850823fd580424605617747da9737
4
- data.tar.gz: fd604198415fdede3bf2e27565c96550d747d14a92c1faf04308c0fa99c764b0
3
+ metadata.gz: 4a88e369b28d7f01071814ba007495f9a1d573d3b8c0b0c59b0e48decb22637d
4
+ data.tar.gz: ea76d23b0fcedf87e504189e8019e39d21dc6ffe7b203cac5446a07d84cebe97
5
5
  SHA512:
6
- metadata.gz: d618e3625585a1b41fa98665773113f9d12826881054dbcc38d9287829ad5b2fc1f4efabef3a4485542342280083845e4fbaaf0e786bbbfdb778479c00a6dcd0
7
- data.tar.gz: c8b5371939545258ea853ed909f6acbe046874c914dfea7b2fd6d03e0aca75ca08c4bd879778ccaced3f25568347531175cdbab2b052ace3e2fb178181340716
6
+ metadata.gz: b8d60e302866a07592e7f2b1c5605583cffa49f2084c31a390441eb3f69a50859565ec0e0c72211ad551bb0715bc754d45be654552cea32e162f0afb99bb99dd
7
+ data.tar.gz: 2dd187e1d486d6b299fd731a7575d8e6560674ffe0e3e99479ff92fa0432c6c699c3d3085368d97a010bd63a8bf8527e79f37731d926ad03c92b697f2bd51679
data/README.md CHANGED
@@ -4,7 +4,12 @@
4
4
 
5
5
  # Frozen Rails
6
6
 
7
- TBD
7
+ DISCLAIMER: I generated this repo with AI and haven't tested it yet.
8
+ I will verify manually verify the functionality and use AI to generate a test suite as soon as I get to it. Until then, use at your own risk.
9
+
10
+ This repo automates the instructions from [rails-static.com](https://rails-static.com) and some additional setup which was created by me.
11
+
12
+ Running the full setup `bin/rails g frozen:rails` should turn a fresh Rails application into a full static-site generator that supports Markdown AND structured data (SQLite). The SSG is very developer-focused and might be cumbersome to use for non-devs.
8
13
 
9
14
  ## Installation
10
15
 
@@ -33,7 +38,78 @@ gem "frozen_rails"
33
38
 
34
39
  ## Usage
35
40
 
36
- TBD
41
+ The gem ships with Rails generators under the `frozen` namespace. After including `frozen_rails` in your Rails application the following generators will be available:
42
+
43
+ ```bash
44
+ # ✅ passes, ✅ works correctly, ❌ has test suite
45
+
46
+ # - Adds `decant` with a custom extension.
47
+ # - Adds `kramdown`, `rouge` and ERB interpolation for `.md` files.
48
+ # - Adds application scaffold.
49
+
50
+ bin/rails g frozen:md
51
+ # - Prompts for a rouge theme. Pass `--rouge_theme=name` to run non-interactive.
52
+ ```
53
+
54
+ ```bash
55
+ # ✅ passes, ✅ works correctly, ❌ has test suite
56
+
57
+ # - Adds `parklife`
58
+ # - Adds `.gitlab-ci.yml` and tweaks parklife config.
59
+
60
+ bin/rails g frozen:ssg
61
+ ```
62
+
63
+ ```bash
64
+ # ✅ passes, ❓ works correctly, ❌ has test suite
65
+
66
+ # - sqlite uuid patch
67
+ # - static_db initializer
68
+ # - friendly_id and Avo configuration
69
+
70
+ bin/rails g frozen:db
71
+ ```
72
+
73
+ ```bash
74
+ # ✅ passes, ❓ works correctly, ❌ has test suite
75
+
76
+ # - SEO helpers
77
+ # - sitemap/robots skeleton
78
+
79
+ bin/rails g frozen:seo
80
+ ```
81
+
82
+ ```bash
83
+ # ✅ passes, ❓ works correctly, ❌ has test suite
84
+
85
+ # - water.css
86
+ # - sample importmap pin
87
+ # - Hotwire Spark & Action Cable configuration
88
+ # - Stimulus hotkey controller
89
+
90
+ bin/rails g frozen:ui
91
+ ```
92
+
93
+ ```bash
94
+ # ✅ passes, ❓ works correctly, ❌ has test suite
95
+
96
+ # - copy custom lib templates
97
+ # - add autoload/generator config to application.rb
98
+
99
+ bin/rails g frozen:dx
100
+ ```
101
+
102
+ ```bash
103
+ # ✅ passes, ❓ works correctly, ❌ has test suite
104
+
105
+ # Full Rails setup (runs all frozen generators in order)
106
+
107
+ bin/rails g frozen:rails
108
+ ```
109
+
110
+ ```bash
111
+ # FUTURE: frozen:meetup
112
+ ```
37
113
 
38
114
  ## Contributing
39
115
 
@@ -0,0 +1,14 @@
1
+ module Appendable
2
+ extend ActiveSupport::Concern
3
+
4
+ private
5
+
6
+ def append_to_application_config(content)
7
+ inject_into_file "config/application.rb", optimize_indentation("\n#{content}", 4), before: / end\nend(?:\n)\z/, verbose: false
8
+ end
9
+
10
+ def append_to_routes(content)
11
+ inject_into_file "config/routes.rb", optimize_indentation("\n#{content}", 2), before: /end(?:\n)\z/, verbose: false
12
+ end
13
+
14
+ end
@@ -0,0 +1,11 @@
1
+ module Bundleable
2
+ extend ActiveSupport::Concern
3
+
4
+ private
5
+
6
+ def bundle!
7
+ Bundler.with_unbundled_env do
8
+ system "bundle install"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "frozen_rails/appendable"
5
+ require "frozen_rails/bundleable"
6
+ require "frozen_rails/taggable"
7
+
8
+ module FrozenRails
9
+ class Generator < Rails::Generators::Base
10
+ include Appendable
11
+ include Bundleable
12
+ include Taggable
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+ module Taggable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ class_option :cleanup_frozen_tags, type: :boolean, default: true, hide: true
6
+ end
7
+
8
+ private
9
+
10
+ def add_frozen_gems(content, env: nil)
11
+ add_frozen_gemfile_tags(env:)
12
+ insert_into_file "Gemfile", optimize_indentation("#{content}\n", env ? 2 : 0), before: frozen_end_tag(env:)
13
+ cleanup_frozen_tags!(env:)
14
+ end
15
+
16
+ def frozen_start_tag(env: nil)
17
+ env_attribute = env ? " env=\"#{env}\"" : ""
18
+ "# <frozen_rails#{env_attribute}>"
19
+ end
20
+
21
+ def frozen_end_tag(env: nil)
22
+ frozen_start_tag(env:).gsub('# <', '# </')
23
+ end
24
+
25
+ def add_frozen_gemfile_tags(env: nil)
26
+ unless File.read("Gemfile").include?(frozen_start_tag(env:))
27
+ newlines = env ? "\n" : "\n\n"
28
+ tags = "#{frozen_start_tag(env:)}#{newlines}#{frozen_end_tag(env:)}"
29
+ insert_into_file "Gemfile", tags, after: frozen_tags_after(env:)
30
+ end
31
+ end
32
+
33
+ def frozen_tags_after(env: nil)
34
+ case env
35
+ when nil
36
+ /frozen_rails[^\n]*\n/
37
+ when 'local'
38
+ "group :development, :test do\n"
39
+ when 'development'
40
+ "group :development do\n"
41
+ else
42
+ raise "Unsupported env!"
43
+ end
44
+ end
45
+
46
+ def cleanup_frozen_tags!(env: nil)
47
+ if options[:cleanup_frozen_tags]
48
+ gsub_file! "Gemfile", /[^\n]*#{frozen_start_tag(env:)}[^\n]*\n/, ''
49
+ gsub_file! "Gemfile", /[^\n]*#{frozen_end_tag(env:)}[^\n]*\n/, ''
50
+ end
51
+ end
52
+
53
+ def cleanup_all_frozen_tags!
54
+ cleanup_frozen_tags!
55
+ cleanup_frozen_tags!(env: 'local')
56
+ cleanup_frozen_tags!(env: 'development')
57
+ end
58
+
59
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FrozenRails # :nodoc:
4
- VERSION = "0.0.2"
4
+ VERSION = "0.0.3"
5
5
  end
data/lib/frozen_rails.rb CHANGED
@@ -1,4 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "frozen_rails/version"
4
- require "frozen_rails/railtie" if defined?(Rails::Railtie)
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "frozen_rails/generator"
4
+
5
+ module Frozen
6
+ module Generators
7
+ class DbGenerator < FrozenRails::Generator
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "Prepare a Rails app for SQLite UUIDs, static_db, Avo and FriendlyId"
11
+
12
+ def add_gems
13
+ add_frozen_gems <<~RUBY
14
+ # frozen:db
15
+ gem "sqlite_extensions-uuid"
16
+ gem "static_db"
17
+ gem "friendly_id"
18
+ RUBY
19
+
20
+ add_frozen_gems <<~RUBY, env: "local"
21
+ # frozen:db
22
+ gem "avo", ">= 3.2"
23
+ RUBY
24
+ end
25
+
26
+ def bundle_gems
27
+ bundle!
28
+ end
29
+
30
+ # configure database.yml for sqlite uuid extension
31
+ def configure_database_yml
32
+ return unless File.exist?("config/database.yml")
33
+
34
+ inject_into_file "config/database.yml", after: "adapter: sqlite3\n" do
35
+ <<~YML
36
+ extensions:
37
+ - <%= SqliteExtensions::UUID.to_path %>
38
+ YML
39
+ end
40
+ end
41
+
42
+ # create initializer for sqlite uuid generator patch
43
+ def create_sqlite_uuid_initializer
44
+ template "db/sqlite_uuid.rb", "config/initializers/sqlite_uuid.rb"
45
+ end
46
+
47
+ # create initializer for static_db configuration
48
+ def create_static_db_initializer
49
+ template "db/static_db.rb", "config/initializers/static_db.rb"
50
+ end
51
+
52
+ # create friendly_id initializer
53
+ def create_friendly_id_initializer
54
+ template "db/friendly_id.rb", "config/initializers/friendly_id.rb"
55
+ end
56
+
57
+ # create a minimal avo initializer stub
58
+ def create_avo_initializer
59
+ template "db/avo.rb", "config/initializers/avo.rb"
60
+ end
61
+
62
+ # reminder to run generators
63
+ def post_install_reminders
64
+ say_status :info, "Run `rails generate friendly_id` to create slug migrations."
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "frozen_rails/generator"
4
+
5
+ module Frozen
6
+ module Generators
7
+ class DxGenerator < FrozenRails::Generator
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "Install developer experience helpers: custom lib templates and generator config"
11
+
12
+ # copy over the lib folder content from static example
13
+ def copy_lib_templates
14
+ directory "dx/lib", "lib"
15
+ end
16
+
17
+ # inject configuration into config/application.rb
18
+ def configure_application
19
+ return unless File.exist?("config/application.rb")
20
+
21
+ inject_into_file "config/application.rb",
22
+ after: "class Application < Rails::Application\n" do
23
+ <<~RUBY
24
+ # Please, add to the `ignore` list any other `lib` subdirectories that do
25
+ # not contain `.rb` files, or that should not be reloaded or eager loaded.
26
+ # Common ones are `templates`, `generators`, or `middleware`, for example.
27
+ config.autoload_lib(ignore: %w[assets tasks])
28
+
29
+ config.generators do |g|
30
+ g.orm :active_record, primary_key_type: :uuid
31
+ g.test_framework false
32
+ end
33
+
34
+ config.active_storage.draw_routes = true
35
+
36
+ RUBY
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "frozen_rails/generator"
4
+
5
+ module Frozen
6
+ module Generators
7
+ class MdGenerator < FrozenRails::Generator
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ # When absent, the generator will prompt interactively (unless running non-interactively).
11
+ class_option :rouge_theme, type: :string, desc: "Rouge theme to install (runs non-interactive if provided)"
12
+
13
+ desc "Set up markdown-powered content with Decant, kramdown, ERB processing and Rouge highlighting"
14
+
15
+ def add_gems
16
+ add_frozen_gems <<~RUBY
17
+ # frozen:md
18
+ gem "decant"
19
+ gem "kramdown"
20
+ gem "kramdown-parser-gfm"
21
+ gem "rouge"
22
+ RUBY
23
+ end
24
+
25
+ def bundle_gems
26
+ bundle!
27
+ end
28
+
29
+ def create_content_directory
30
+ empty_directory "content/pages"
31
+ end
32
+
33
+ def copy_files
34
+ app_files = [
35
+ "controllers/categories_controller.rb",
36
+ "controllers/pages_controller.rb",
37
+ "helpers/markdown_helper.rb",
38
+ "models/concerns/linkable.rb",
39
+ "models/category.rb",
40
+ "models/page.rb",
41
+ "views/categories/index.html.erb",
42
+ "views/categories/show.html.erb",
43
+ "views/pages/show.html.erb",
44
+ ]
45
+
46
+ app_files.each do |app_file|
47
+ copy_file "md/#{app_file}", "app/#{app_file}"
48
+ end
49
+
50
+ config_files = [
51
+ "initializers/decant_extensions.rb",
52
+ ]
53
+
54
+ config_files.each do |config_file|
55
+ copy_file "md/#{config_file}", "config/#{config_file}"
56
+ end
57
+
58
+ content_files = [
59
+ "pages/frozen-rails.md",
60
+ "pages/rails-static.md",
61
+ "pages/rails-static/rails-static-logo.webp",
62
+ ]
63
+
64
+ content_files.each do |content_file|
65
+ copy_file "md/#{content_file}", "content/#{content_file}"
66
+ end
67
+ end
68
+
69
+ def add_config
70
+ append_to_application_config <<~RUBY
71
+ # frozen:md
72
+ config.assets.paths << Rails.root.join("content")
73
+ config.action_dispatch.rescue_responses["Decant::FileNotFound"] = :not_found
74
+ RUBY
75
+ end
76
+
77
+ # Add routes for pages
78
+ def add_routes
79
+ append_to_routes <<~RUBY
80
+ # frozen:md
81
+ root "categories#index"
82
+
83
+ # Use `Regexp.union` instead of array for constraints!
84
+ # https://github.com/rails/rails/issues/47726
85
+ constraints slug: Regexp.union(Category.all.map(&:slug)) do
86
+ resources :categories, param: :slug, only: [:index, :show]
87
+ end
88
+
89
+ resources :pages, param: :slug, only: [:show]
90
+ RUBY
91
+ end
92
+
93
+ def generate_rouge_css_stylesheet
94
+ theme = options[:rouge_theme]
95
+
96
+ if theme.blank? && behavior == :invoke && $stdin.tty?
97
+ # Run in subshell so we pick up newly installed gem without needing to require it in the current process.
98
+ themes = `bundle exec ruby -e "require 'rouge'; puts Rouge::Theme.registry.keys.sort"`.split("\n")
99
+
100
+ say_status :info, "Available Rouge themes (#{themes.size}):", :blue
101
+ themes.each_with_index { |t, i| say " #{i + 1}. #{t}" }
102
+
103
+ answer = ask("Choose a theme (name or number) [github]")
104
+
105
+ theme = if /^\d+$/.match?(answer)
106
+ themes[answer.to_i - 1]
107
+ else
108
+ answer.presence
109
+ end
110
+ end
111
+
112
+ theme ||= "github"
113
+
114
+ say_status :info, "Generating Rouge CSS for theme #{theme}", :blue
115
+ run "rougify style #{theme} > app/assets/stylesheets/rouge.css"
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "frozen_rails/taggable"
5
+
6
+ module Frozen
7
+ module Generators
8
+ # A meta-generator that runs the other frozen generators in a sensible order.
9
+ class RailsGenerator < Rails::Generators::Base
10
+ include Taggable
11
+
12
+ desc "Run all frozen setup generators (md, db, seo, ui, dx, ssg)"
13
+
14
+ # The method name doesn't matter much; Thor runs all public methods in
15
+ # order defined by source.
16
+ def run_all
17
+ say_status :info, "invoking frozen:md"
18
+ invoke "frozen:md", [], cleanup_frozen_tags: false
19
+
20
+ say_status :info, "invoking frozen:db"
21
+ invoke "frozen:db", [], cleanup_frozen_tags: false
22
+
23
+ say_status :info, "invoking frozen:seo"
24
+ invoke "frozen:seo", [], cleanup_frozen_tags: false
25
+
26
+ say_status :info, "invoking frozen:ui"
27
+ invoke "frozen:ui", [], cleanup_frozen_tags: false
28
+
29
+ say_status :info, "invoking frozen:dx"
30
+ invoke "frozen:dx", [], cleanup_frozen_tags: false
31
+
32
+ say_status :info, "invoking frozen:ssg"
33
+ invoke "frozen:ssg", [], cleanup_frozen_tags: false
34
+
35
+ cleanup_all_frozen_tags!
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "frozen_rails/generator"
4
+
5
+ module Frozen
6
+ module Generators
7
+ class SeoGenerator < FrozenRails::Generator
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "Add SEO helpers, metadata partials and sitemap/robots models"
11
+
12
+ # add meta partial and update layout
13
+ def create_og_partial
14
+ template "seo/_og_meta_tags.html.erb", "app/views/layouts/_og_meta_tags.html.erb"
15
+ end
16
+
17
+ def inject_layout_tags
18
+ return unless File.exist?("app/views/layouts/application.html.erb")
19
+
20
+ inject_into_file "app/views/layouts/application.html.erb",
21
+ after: "<head>\n" do
22
+ <<~ERB
23
+ <%= render 'layouts/og_meta_tags', tags: {
24
+ title: title,
25
+ description: description,
26
+ image: image_url('og-image.jpg'),
27
+ author: author,
28
+ type: "website",
29
+ site_name: site_name,
30
+ url: canonical_url,
31
+ } %>
32
+
33
+ <%= tag :link, rel: "canonical", href: canonical_url %>
34
+
35
+ <%= favicon_link_tag 'favicon.ico', sizes: '32x32' %>
36
+ <%= favicon_link_tag 'icon.svg', type: 'image/svg+xml' %>
37
+ <%= favicon_link_tag 'apple-touch-icon.png', rel: 'apple-touch-icon' %>
38
+
39
+ <%= tag :meta, name: "robots", content: robots_content %>
40
+
41
+ ERB
42
+ end
43
+ end
44
+
45
+ # helpers for meta tags
46
+ def add_application_helpers
47
+ unless File.exist?("app/helpers/application_helper.rb")
48
+ create_file "app/helpers/application_helper.rb", "module ApplicationHelper\nend\n"
49
+ end
50
+
51
+ inject_into_file "app/helpers/application_helper.rb",
52
+ after: "module ApplicationHelper\n" do
53
+ <<~RUBY
54
+ def site_name
55
+ "Rails Static"
56
+ end
57
+
58
+ def title
59
+ [ @page&.title.presence, site_name ].uniq.compact.join(" · ")
60
+ end
61
+
62
+ def description
63
+ @page.frontmatter&.dig(:description)
64
+ end
65
+
66
+ def author
67
+ "François Catuhe"
68
+ end
69
+
70
+ def canonical_url
71
+ url_for(only_path: false)
72
+ end
73
+
74
+ def robots_content
75
+ Rails.env.production? ? "index, follow" : "noindex, nofollow"
76
+ end
77
+
78
+ def og_meta_tag(key, content)
79
+ case key
80
+ when :title, :description, :image
81
+ tag(:meta, name: key, property: "og:\#{key}", content: content)
82
+ when :author
83
+ tag(:meta, name: key, content: content)
84
+ else
85
+ tag(:meta, property: "og:\#{key}", content: content)
86
+ end
87
+ end
88
+
89
+ RUBY
90
+ end
91
+ end
92
+
93
+ def add_favicon_notice
94
+ say_status :info, "Add favicons (favicon.ico, icon.svg, apple-touch-icon.png) to app/assets/images and create og-image.jpg"
95
+ end
96
+
97
+ # sitemap models
98
+ def create_sitemap_models
99
+ template "seo/sitemap.rb", "app/models/sitemap.rb"
100
+ template "seo/sitemap_entry.rb", "app/models/sitemap/entry.rb"
101
+ template "seo/robots_generatable.rb", "app/models/sitemap/robots_generatable.rb"
102
+ end
103
+
104
+ def remove_default_robots
105
+ remove_file "public/robots.txt" if File.exist?("public/robots.txt")
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "frozen_rails/generator"
4
+
5
+ module Frozen
6
+ module Generators
7
+ class SsgGenerator < FrozenRails::Generator
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ desc "Set up Parklife static site generation with CI workflows and helper scripts"
11
+
12
+ def add_gems
13
+ add_frozen_gems <<~RUBY
14
+ # frozen:ssg
15
+ gem "parklife-rails"
16
+ RUBY
17
+ end
18
+
19
+ def bundle_gems
20
+ bundle!
21
+ end
22
+
23
+ def run_parklife_init
24
+ unless system("bundle exec parklife init --rails --github-pages")
25
+ say_status :warn, "Unable to run parklife init. Please execute manually!"
26
+ end
27
+ end
28
+
29
+ def setup_gitlab_pages
30
+ copy_file "ssg/.gitlab-ci.yml", ".gitlab-ci.yml"
31
+ comment_lines "Parkfile", /config\.nested_index = false/
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generated by frozen:db
4
+ # Minimal Avo configuration; adjust as needed.
5
+ Avo.configure do |config|
6
+ config.root_path = "/avo"
7
+ config.authorization_client = nil
8
+ config.explicit_authorization = true
9
+ config.click_row_to_view_record = true
10
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # generated by frozen:db
4
+ FriendlyId.defaults do |config|
5
+ # enable the most common modules
6
+ config.use :reserved
7
+ config.use :slugged
8
+ config.use :finders
9
+ config.use :history
10
+
11
+ # a UUID will be appended automatically when a unique slug cannot be generated
12
+ # suitable reserved words to avoid can be declared here.
13
+ config.reserved_words = %w[new edit index session login logout users admin]
14
+ end