bridgetown-core 1.0.0.alpha8 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/bin/bridgetown +14 -2
  4. data/bridgetown-core.gemspec +5 -4
  5. data/lib/bridgetown-core/collection.rb +6 -6
  6. data/lib/bridgetown-core/commands/base.rb +18 -18
  7. data/lib/bridgetown-core/commands/build.rb +1 -1
  8. data/lib/bridgetown-core/commands/clean.rb +2 -2
  9. data/lib/bridgetown-core/commands/concerns/configuration_overridable.rb +7 -0
  10. data/lib/bridgetown-core/commands/console.rb +39 -12
  11. data/lib/bridgetown-core/commands/doctor.rb +8 -5
  12. data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +27 -0
  13. data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +216 -0
  14. data/lib/bridgetown-core/commands/esbuild/migrate-from-webpack.rb +47 -0
  15. data/lib/bridgetown-core/commands/esbuild/setup.rb +4 -0
  16. data/lib/bridgetown-core/commands/esbuild/update.rb +4 -0
  17. data/lib/bridgetown-core/commands/esbuild.rb +83 -0
  18. data/lib/bridgetown-core/commands/new.rb +80 -10
  19. data/lib/bridgetown-core/commands/plugins.rb +1 -1
  20. data/lib/bridgetown-core/commands/webpack/enable-postcss.rb +1 -1
  21. data/lib/bridgetown-core/commands/webpack/update.rb +3 -3
  22. data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +1 -1
  23. data/lib/bridgetown-core/commands/webpack.rb +3 -3
  24. data/lib/bridgetown-core/component.rb +9 -3
  25. data/lib/bridgetown-core/concerns/site/configurable.rb +4 -0
  26. data/lib/bridgetown-core/concerns/site/content.rb +4 -4
  27. data/lib/bridgetown-core/concerns/site/extensible.rb +8 -0
  28. data/lib/bridgetown-core/concerns/site/processable.rb +22 -4
  29. data/lib/bridgetown-core/concerns/site/ssr.rb +2 -17
  30. data/lib/bridgetown-core/configurations/minitesting.rb +1 -1
  31. data/lib/bridgetown-core/configurations/purgecss.rb +2 -1
  32. data/lib/bridgetown-core/configurations/render/render.yaml.erb +3 -0
  33. data/lib/bridgetown-core/configurations/stimulus.rb +40 -12
  34. data/lib/bridgetown-core/configurations/tailwindcss/css_imports.css +5 -0
  35. data/lib/bridgetown-core/configurations/tailwindcss.rb +31 -2
  36. data/lib/bridgetown-core/configurations/turbo/turbo_transitions.js +48 -0
  37. data/lib/bridgetown-core/configurations/turbo.rb +15 -5
  38. data/lib/bridgetown-core/converters/erb_templates.rb +2 -2
  39. data/lib/bridgetown-core/converters/ruby_templates.rb +1 -1
  40. data/lib/bridgetown-core/converters/serbea_templates.rb +71 -0
  41. data/lib/bridgetown-core/drops/drop.rb +1 -1
  42. data/lib/bridgetown-core/drops/resource_drop.rb +28 -5
  43. data/lib/bridgetown-core/errors.rb +21 -0
  44. data/lib/bridgetown-core/generators/prototype_generator.rb +3 -3
  45. data/lib/bridgetown-core/helpers.rb +3 -2
  46. data/lib/bridgetown-core/hooks.rb +51 -20
  47. data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -3
  48. data/lib/bridgetown-core/model/base.rb +24 -1
  49. data/lib/bridgetown-core/model/origin.rb +4 -6
  50. data/lib/bridgetown-core/model/repo_origin.rb +48 -0
  51. data/lib/bridgetown-core/rack/boot.rb +5 -9
  52. data/lib/bridgetown-core/rack/roda.rb +4 -5
  53. data/lib/bridgetown-core/rack/routes.rb +44 -10
  54. data/lib/bridgetown-core/rack/static_indexes.rb +2 -0
  55. data/lib/bridgetown-core/resource/base.rb +2 -0
  56. data/lib/bridgetown-core/ruby_template_view.rb +4 -0
  57. data/lib/bridgetown-core/tags/{webpack_path.rb → asset_path.rb} +7 -9
  58. data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +2 -1
  59. data/lib/bridgetown-core/utils/loaders_manager.rb +11 -0
  60. data/lib/bridgetown-core/utils.rb +88 -30
  61. data/lib/bridgetown-core/version.rb +1 -1
  62. data/lib/bridgetown-core/watcher.rb +74 -70
  63. data/lib/bridgetown-core.rb +1 -1
  64. data/lib/site_template/Gemfile.erb +17 -11
  65. data/lib/site_template/README.md +2 -2
  66. data/lib/site_template/{Rakefile → Rakefile.erb} +15 -0
  67. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.erb +11 -0
  68. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.rb +5 -0
  69. data/lib/site_template/TEMPLATES/erb/_layouts/default.erb +15 -0
  70. data/lib/site_template/TEMPLATES/erb/_layouts/page.erb +7 -0
  71. data/lib/site_template/TEMPLATES/erb/_layouts/post.erb +7 -0
  72. data/lib/site_template/TEMPLATES/erb/_partials/_footer.erb +3 -0
  73. data/lib/site_template/TEMPLATES/erb/_partials/_head.erb +10 -0
  74. data/lib/site_template/{src → TEMPLATES/liquid}/_components/footer.liquid +0 -0
  75. data/lib/site_template/TEMPLATES/liquid/_components/head.liquid +10 -0
  76. data/lib/site_template/TEMPLATES/liquid/_components/navbar.liquid +11 -0
  77. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/default.liquid +2 -2
  78. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/page.liquid +0 -0
  79. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/post.liquid +0 -0
  80. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.rb +5 -0
  81. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.serb +11 -0
  82. data/lib/site_template/TEMPLATES/serbea/_layouts/default.serb +15 -0
  83. data/lib/site_template/TEMPLATES/serbea/_layouts/page.serb +7 -0
  84. data/lib/site_template/TEMPLATES/serbea/_layouts/post.serb +7 -0
  85. data/lib/site_template/TEMPLATES/serbea/_partials/_footer.serb +3 -0
  86. data/lib/site_template/TEMPLATES/serbea/_partials/_head.serb +10 -0
  87. data/lib/site_template/frontend/javascript/index.js.erb +7 -3
  88. data/lib/site_template/frontend/styles/index.css +71 -6
  89. data/lib/site_template/package.json.erb +24 -9
  90. data/lib/site_template/ruby-version.erb +1 -0
  91. data/lib/site_template/server/roda_app.rb +5 -3
  92. data/lib/site_template/server/routes/hello.rb.sample +1 -1
  93. data/lib/site_template/src/images/logo.svg +91 -0
  94. data/lib/site_template/src/index.md.erb +22 -0
  95. data/lib/site_template/src/posts.md.erb +28 -0
  96. metadata +82 -36
  97. data/lib/bridgetown-core/configurations/swup.rb +0 -37
  98. data/lib/site_template/frontend/styles/index.scss +0 -17
  99. data/lib/site_template/src/_components/head.liquid +0 -10
  100. data/lib/site_template/src/_components/navbar.liquid +0 -5
  101. data/lib/site_template/src/_layouts/home.liquid +0 -7
  102. data/lib/site_template/src/images/.keep +0 -1
  103. data/lib/site_template/src/index.md +0 -7
  104. data/lib/site_template/src/posts.md +0 -14
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Commands
5
+ class Esbuild < Thor::Group
6
+ include Thor::Actions
7
+ extend Summarizable
8
+
9
+ Registrations.register do
10
+ register(Esbuild, "esbuild", "esbuild ACTION", Esbuild.summary)
11
+ end
12
+
13
+ def self.banner
14
+ "bridgetown esbuild ACTION"
15
+ end
16
+ summary "Perform actions on the Bridgetown esbuild configuration"
17
+
18
+ def self.exit_on_failure?
19
+ true
20
+ end
21
+
22
+ def esbuild
23
+ @logger = Bridgetown.logger
24
+ return show_actions if args.empty?
25
+
26
+ action = args.first
27
+ if supported_actions.include?(action)
28
+ perform action
29
+ else
30
+ @logger.error "Error:".red, "🚨 Please enter a valid action."
31
+ say "\n"
32
+ show_actions
33
+ end
34
+ end
35
+
36
+ def self.source_root
37
+ File.expand_path("./esbuild", __dir__)
38
+ end
39
+
40
+ def self.destination_root
41
+ config.root_dir
42
+ end
43
+
44
+ protected
45
+
46
+ def config
47
+ @config ||= Bridgetown.configuration({ root_dir: Dir.pwd })
48
+ end
49
+
50
+ def package_json
51
+ @package_json ||= begin
52
+ package_json_file = File.read(Bridgetown.sanitized_path(config.root_dir, "package.json"))
53
+ JSON.parse(package_json_file)
54
+ end
55
+ end
56
+
57
+ def perform(action)
58
+ automation = find_in_source_paths("#{action}.rb")
59
+ inside(New.created_site_dir || Dir.pwd) do
60
+ apply automation, verbose: false
61
+ end
62
+ end
63
+
64
+ def show_actions
65
+ say "Available actions:\n".bold
66
+
67
+ longest_action = supported_actions.keys.max_by(&:size).size
68
+ supported_actions.each do |action, description|
69
+ say "#{action.ljust(longest_action).to_s.bold.blue}\t# #{description}"
70
+ end
71
+ end
72
+
73
+ def supported_actions
74
+ {
75
+ setup: "Sets up an esbuild integration with Bridgetown in your project",
76
+ update: "Updates the Bridgetown esbuild defaults to the latest available version",
77
+ "migrate-from-webpack":
78
+ "Removes Webpack from your project and installs/configures esbuild",
79
+ }.with_indifferent_access
80
+ end
81
+ end
82
+ end
83
+ end
@@ -24,6 +24,14 @@ module Bridgetown
24
24
  aliases: "-c",
25
25
  banner: "CONFIGURATION(S)",
26
26
  desc: "Comma separated list of bundled configurations to perform"
27
+ class_option :templates,
28
+ aliases: "-t",
29
+ banner: "liquid|erb|serbea",
30
+ desc: "Preferred template engine (defaults to Liquid)"
31
+ class_option :"frontend-bundling",
32
+ aliases: "-e",
33
+ banner: "esbuild|webpack",
34
+ desc: "Choose your frontend bundling stack (defaults to esbuild)"
27
35
  class_option :force,
28
36
  type: :boolean,
29
37
  desc: "Force creation even if PATH already exists"
@@ -33,9 +41,9 @@ module Bridgetown
33
41
  class_option :"skip-yarn",
34
42
  type: :boolean,
35
43
  desc: "Skip 'yarn install'"
36
- class_option :"use-postcss",
44
+ class_option :"use-sass",
37
45
  type: :boolean,
38
- desc: "Create an empty PostCSS configuration instead of using Sass"
46
+ desc: "(Webpack only) Create a Sass configuration instead of using PostCSS"
39
47
 
40
48
  DOCSURL = "https://bridgetownrb.com/docs"
41
49
 
@@ -54,6 +62,11 @@ module Bridgetown
54
62
  def new_site
55
63
  raise ArgumentError, "You must specify a path." if args.empty?
56
64
 
65
+ if frontend_bundling_option != "webpack" && options["use-sass"]
66
+ raise ArgumentError,
67
+ "To install Sass, you must choose Webpack (-e webpack) as your frontend bundler"
68
+ end
69
+
57
70
  new_site_path = File.expand_path(args.join(" "), Dir.pwd)
58
71
  @site_name = new_site_path.split(File::SEPARATOR).last
59
72
 
@@ -70,6 +83,8 @@ module Bridgetown
70
83
  say_status :create, new_site_path
71
84
  create_site new_site_path
72
85
  after_install new_site_path, args.join(" "), options
86
+ rescue ArgumentError => e
87
+ say_status :alert, e.message, :red
73
88
  end
74
89
 
75
90
  protected
@@ -78,24 +93,79 @@ module Bridgetown
78
93
  !options["force"] && Dir.exist?(path)
79
94
  end
80
95
 
96
+ def frontend_bundling_option
97
+ options["frontend-bundling"] == "webpack" ? "webpack" : "esbuild"
98
+ end
99
+
100
+ def postcss_option
101
+ !(frontend_bundling_option == "webpack" && options["use-sass"])
102
+ end
103
+
81
104
  def create_site(new_site_path)
82
- directory ".", ".", exclude_pattern: %r!\.erb|DS_Store$|\.(s[ac]|c)ss$!
105
+ directory ".", ".", exclude_pattern: %r!\.erb|TEMPLATES|DS_Store$|\.(s[ac]|c)ss$!
83
106
  FileUtils.chmod_R "u+w", new_site_path
84
107
 
85
108
  template(
86
109
  "src/_posts/0000-00-00-welcome-to-bridgetown.md.erb",
87
110
  "src/_posts/#{Time.now.strftime("%Y-%m-%d")}-welcome-to-bridgetown.md"
88
111
  )
112
+ template("ruby-version.erb", ".ruby-version")
89
113
  template("Gemfile.erb", "Gemfile")
114
+ template("Rakefile.erb", "Rakefile")
90
115
  template("package.json.erb", "package.json")
91
116
  template("frontend/javascript/index.js.erb", "frontend/javascript/index.js")
117
+ template("src/index.md.erb", "src/index.md")
118
+ template("src/posts.md.erb", "src/posts.md")
119
+
120
+ case options["templates"]
121
+ when "erb"
122
+ setup_erb_templates
123
+ when "serbea"
124
+ setup_serbea_templates
125
+ else
126
+ setup_liquid_templates
127
+ end
128
+
129
+ if frontend_bundling_option == "esbuild"
130
+ configure_postcss
131
+ invoke(Esbuild, ["setup"], {})
132
+ else
133
+ postcss_option ? configure_postcss : configure_sass
134
+ invoke(Webpack, ["setup"], {})
135
+ end
136
+ end
137
+
138
+ def setup_erb_templates
139
+ directory "TEMPLATES/erb/_layouts", "src/_layouts"
140
+ directory "TEMPLATES/erb/_components", "src/_components"
141
+ directory "TEMPLATES/erb/_partials", "src/_partials"
142
+ gsub_file "bridgetown.config.yml", %r!permalink: pretty\n!, <<~YML
143
+ permalink: pretty
144
+ template_engine: erb
145
+ YML
146
+ end
147
+
148
+ def setup_serbea_templates
149
+ directory "TEMPLATES/serbea/_layouts", "src/_layouts"
150
+ directory "TEMPLATES/serbea/_components", "src/_components"
151
+ directory "TEMPLATES/serbea/_partials", "src/_partials"
152
+ gsub_file "bridgetown.config.yml", %r!permalink: pretty\n!, <<~YML
153
+ permalink: pretty
154
+ template_engine: serbea
155
+ YML
156
+ end
92
157
 
93
- options["use-postcss"] ? configure_postcss : configure_sass
94
- invoke(Webpack, ["setup"], {})
158
+ def setup_liquid_templates
159
+ directory "TEMPLATES/liquid/_layouts", "src/_layouts"
160
+ directory "TEMPLATES/liquid/_components", "src/_components"
161
+ gsub_file "bridgetown.config.yml", %r!permalink: pretty\n!, <<~YML
162
+ permalink: pretty
163
+ template_engine: liquid
164
+ YML
95
165
  end
96
166
 
97
167
  def configure_sass
98
- copy_file("frontend/styles/index.scss")
168
+ copy_file("frontend/styles/index.css", "frontend/styles/index.scss")
99
169
  end
100
170
 
101
171
  def configure_postcss
@@ -159,9 +229,9 @@ module Bridgetown
159
229
  end
160
230
  @skipped_bundle = false
161
231
  rescue LoadError
162
- say_status :run, "Could not load Bundler. Bundle install skipped.", :red
232
+ say_status :alert, "Could not load Bundler. Bundle install skipped.", :red
163
233
  rescue SystemExit
164
- say_status :run, "Problem occured while running bundle install.", :red
234
+ say_status :alert, "Problem occured while running bundle install.", :red
165
235
  end
166
236
 
167
237
  def git_init(path)
@@ -171,7 +241,7 @@ module Bridgetown
171
241
  end
172
242
  end
173
243
  rescue SystemExit
174
- say_status :run, "Could not load git. git init skipped.", :red
244
+ say_status :alert, "Could not load git. git init skipped.", :red
175
245
  end
176
246
 
177
247
  def yarn_install(path)
@@ -182,7 +252,7 @@ module Bridgetown
182
252
  end
183
253
  @skipped_yarn = false
184
254
  rescue SystemExit
185
- say_status :run, "Could not load yarn. yarn install skipped.", :red
255
+ say_status :alert, "Could not load yarn. yarn install skipped.", :red
186
256
  end
187
257
  end
188
258
  end
@@ -187,7 +187,7 @@ module Bridgetown
187
187
  say_status "Done!", "Have fun writing your new #{name} plugin :)"
188
188
  say_status "Remember:", "Don't forget to rename the SamplePlugin" \
189
189
  " code identifiers and paths to your own" \
190
- " indentifer, as well as update your README " \
190
+ " indentifer, as well as update your README" \
191
191
  " and CHANGELOG files as necessary."
192
192
  end
193
193
 
@@ -6,7 +6,7 @@ template default_postcss_config, "postcss.config.js"
6
6
  template "webpack.defaults.js.erb", "config/webpack.defaults.js", force: true
7
7
 
8
8
  unless Bridgetown.environment.test?
9
- packages = %w(postcss@8.3.0 postcss-loader@4.3.0 postcss-flexbugs-fixes postcss-preset-env)
9
+ packages = %w(postcss postcss-loader postcss-flexbugs-fixes postcss-preset-env)
10
10
  run "yarn add -D #{packages.join(" ")}"
11
11
  run "yarn remove sass sass-loader"
12
12
  end
@@ -2,14 +2,14 @@
2
2
 
3
3
  # rubocop:disable Layout/LineLength
4
4
 
5
- required_packages = %w(esbuild esbuild-loader webpack@5.39.1 webpack-cli@4.7.2 webpack-manifest-plugin@3.1.1)
6
- redundant_packages = %w(@babel/core @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime @babel/preset-env babel-loader)
7
-
8
5
  template "webpack.defaults.js.erb", "config/webpack.defaults.js", force: true
9
6
  say "🎉 Webpack configuration updated successfully!"
10
7
 
11
8
  return if Bridgetown.environment.test?
12
9
 
10
+ required_packages = %w(esbuild esbuild-loader webpack@5.39.1 webpack-cli@4.7.2 webpack-manifest-plugin@3.1.1)
11
+ redundant_packages = %w(@babel/core @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime @babel/preset-env babel-loader)
12
+
13
13
  say "Installing required packages"
14
14
  run "yarn add -D #{required_packages.join(" ")}"
15
15
 
@@ -119,7 +119,7 @@ module.exports = {
119
119
  filename: "../css/[name].[contenthash].css",
120
120
  }),
121
121
  new WebpackManifestPlugin({
122
- fileName: path.resolve(rootDir, ".bridgetown-webpack", "manifest.json"),
122
+ fileName: path.resolve(rootDir, ".bridgetown-cache", "frontend-bundling", "manifest.json"),
123
123
  }),
124
124
  ],
125
125
  module: {
@@ -13,7 +13,7 @@ module Bridgetown
13
13
  def self.banner
14
14
  "bridgetown webpack ACTION"
15
15
  end
16
- summary "Perform actions on the bridgetown webpack configuration"
16
+ summary "Perform actions on the Bridgetown Webpack configuration"
17
17
 
18
18
  def self.exit_on_failure?
19
19
  true
@@ -72,8 +72,8 @@ module Bridgetown
72
72
 
73
73
  def supported_actions
74
74
  {
75
- setup: "Sets up a webpack integration with Bridgetown in your project",
76
- update: "Updates the Bridgetown webpack defaults to the latest available version",
75
+ setup: "Sets up a Webpack integration with Bridgetown in your project",
76
+ update: "Updates the Bridgetown Webpack defaults to the latest available version",
77
77
  "enable-postcss": "Configures PostCSS in your project",
78
78
  }.with_indifferent_access
79
79
  end
@@ -91,6 +91,12 @@ module Bridgetown
91
91
  def supported_template_extensions
92
92
  %w(erb serb slim haml)
93
93
  end
94
+
95
+ def path_for_errors
96
+ component_template_path
97
+ rescue RuntimeError
98
+ source_location
99
+ end
94
100
  end
95
101
 
96
102
  # If a content block was originally passed into via `render`, capture its output.
@@ -133,7 +139,7 @@ module Bridgetown
133
139
  rescue StandardError => e
134
140
  Bridgetown.logger.error "Component error:",
135
141
  "#{self.class} encountered an error while "\
136
- "rendering `#{self.class.component_template_path}'"
142
+ "rendering `#{self.class.path_for_errors}'"
137
143
  raise e
138
144
  end
139
145
 
@@ -165,7 +171,7 @@ module Bridgetown
165
171
  end
166
172
 
167
173
  def method_missing(method, *args, **kwargs, &block)
168
- if helpers.respond_to?(method.to_sym)
174
+ if view_context && helpers.respond_to?(method.to_sym)
169
175
  helpers.send method.to_sym, *args, **kwargs, &block
170
176
  else
171
177
  super
@@ -173,7 +179,7 @@ module Bridgetown
173
179
  end
174
180
 
175
181
  def respond_to_missing?(method, include_private = false)
176
- helpers.respond_to?(method.to_sym, include_private) || super
182
+ (view_context && helpers.respond_to?(method.to_sym, include_private)) || super
177
183
  end
178
184
  end
179
185
  end
@@ -146,6 +146,10 @@ class Bridgetown::Site
146
146
  @collections_path ||= dir_str.empty? ? source : in_source_dir(dir_str)
147
147
  end
148
148
 
149
+ def frontend_bundling_path
150
+ in_root_dir(".bridgetown-cache", "frontend-bundling")
151
+ end
152
+
149
153
  private
150
154
 
151
155
  # Disable Marshaling cache to disk in Safe Mode
@@ -67,7 +67,7 @@ class Bridgetown::Site
67
67
 
68
68
  # @return [Array<Bridgetown::Resource::TaxonomyType>]
69
69
  def taxonomy_types
70
- @taxonomy_types ||= config.taxonomies.map do |label, key_or_metadata|
70
+ @taxonomy_types ||= config.taxonomies.to_h do |label, key_or_metadata|
71
71
  key = key_or_metadata
72
72
  tax_metadata = if key_or_metadata.is_a? Hash
73
73
  key = key_or_metadata["key"]
@@ -79,7 +79,7 @@ class Bridgetown::Site
79
79
  [label, Bridgetown::Resource::TaxonomyType.new(
80
80
  site: self, label: label, key: key, metadata: tax_metadata
81
81
  ),]
82
- end.to_h.with_dot_access
82
+ end.with_dot_access
83
83
  end
84
84
 
85
85
  # Get all loaded resources.
@@ -110,11 +110,11 @@ class Bridgetown::Site
110
110
  generated_pages << generated_page
111
111
  end
112
112
 
113
- # Loads and memoizes the parsed Webpack manifest file (if available)
113
+ # Loads and memoizes the parsed frontend bundler manifest file (if available)
114
114
  # @return [Hash]
115
115
  def frontend_manifest
116
116
  @frontend_manifest ||= begin
117
- manifest_file = in_root_dir(".bridgetown-webpack", "manifest.json")
117
+ manifest_file = File.join(frontend_bundling_path, "manifest.json")
118
118
 
119
119
  JSON.parse(File.read(manifest_file)) if File.exist?(manifest_file)
120
120
  end
@@ -56,5 +56,13 @@ class Bridgetown::Site
56
56
  c.new(config)
57
57
  end
58
58
  end
59
+
60
+ # Shorthand for registering a site hook via {Bridgetown::Hooks}
61
+ # @param event [Symbol] name of the event (`:pre_read`, `:post_render`, etc.)
62
+ # @yield the block will be called when the event is triggered
63
+ # @yieldparam site the site which triggered the event hook
64
+ def on(event, reloadable: false, &block)
65
+ Bridgetown::Hooks.register_one :site, event, reloadable: reloadable, &block
66
+ end
59
67
  end
60
68
  end
@@ -23,9 +23,9 @@ class Bridgetown::Site
23
23
 
24
24
  # Reset all in-memory data and content.
25
25
  #
26
-
26
+ # @param soft [Boolean] if true, persist some state and do a light refresh of layouts and data
27
27
  # @return [void]
28
- def reset(soft: false)
28
+ def reset(soft: false) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
29
29
  self.time = Time.now
30
30
  if config["time"]
31
31
  self.time = Bridgetown::Utils.parse_date(
@@ -41,12 +41,30 @@ class Bridgetown::Site
41
41
  @documents = nil
42
42
  @docs_to_write = nil
43
43
  @liquid_renderer.reset
44
- frontmatter_defaults.reset unless soft
45
44
 
46
- Bridgetown::Cache.clear_if_config_changed config unless soft
45
+ if soft
46
+ refresh_layouts_and_data
47
+ else
48
+ frontmatter_defaults.reset
49
+ Bridgetown::Cache.clear_if_config_changed config
50
+ end
51
+
47
52
  Bridgetown::Hooks.trigger :site, (soft ? :after_soft_reset : :after_reset), self
48
53
  end
49
54
 
55
+ # Read layouts and merge any new data collection contents into the site data
56
+ def refresh_layouts_and_data
57
+ reader.read_layouts
58
+
59
+ collections.data.tap do |coll|
60
+ coll.resources.clear
61
+ coll.read
62
+ coll.merge_data_resources.each do |k, v|
63
+ data[k] = v # refresh site data
64
+ end
65
+ end
66
+ end
67
+
50
68
  # Read data from disk and load it into internal memory.
51
69
  # @return [void]
52
70
  def read
@@ -32,7 +32,7 @@ class Bridgetown::Site
32
32
  @ssr_enabled = true
33
33
  end
34
34
 
35
- def ssr_setup(&block) # rubocop:disable Metrics/AbcSize
35
+ def ssr_setup
36
36
  config.serving = true
37
37
  Bridgetown::Hooks.trigger :site, :pre_read, self
38
38
  defaults_reader.tap do |d|
@@ -46,27 +46,12 @@ class Bridgetown::Site
46
46
  end
47
47
  Bridgetown::Hooks.trigger :site, :post_read, self
48
48
 
49
- hook = block&.(self) # provide additional setup hook
49
+ yield self if block_given? # provide additional setup hook
50
50
  return if Bridgetown.env.production?
51
51
 
52
- @ssr_reload_hook = hook if hook.is_a?(Proc) && hook.lambda?
53
52
  Bridgetown::Watcher.watch(self, config)
54
53
  end
55
54
 
56
- def ssr_reload
57
- reset soft: true
58
- reader.read_layouts
59
-
60
- collections.data.tap do |coll|
61
- coll.resources.clear
62
- coll.read
63
- coll.merge_data_resources.each do |k, v|
64
- data[k] = v
65
- end
66
- end
67
- @ssr_reload_hook.() if @ssr_reload_hook.is_a?(Proc)
68
- end
69
-
70
55
  def disable_ssr
71
56
  Bridgetown.logger.info "SSR:", "now disabled."
72
57
  @ssr_enabled = false
@@ -82,7 +82,7 @@ create_file "plugins/test_output.rb" do
82
82
  <<~RUBY
83
83
  module TestOutput
84
84
  unless Bridgetown.env.development?
85
- Bridgetown::Hooks.register :site, :post_write do
85
+ Bridgetown::Hooks.register_one :site, :post_write do
86
86
  # Load test suite to run on exit
87
87
  require "nokogiri"
88
88
  Dir["test/**/*.rb"].each { |file| require_relative("../\#{file}") }
@@ -22,9 +22,10 @@ create_builder "purgecss.rb" do
22
22
  PURGE
23
23
  File.write(purgecss_file, config_js.strip)
24
24
  end
25
- manifest_file = site.in_root_dir(".bridgetown-webpack", "manifest.json")
25
+ manifest_file = File.join(site.frontend_bundling_path, "manifest.json")
26
26
  if File.exist?(manifest_file)
27
27
  manifest = JSON.parse(File.read(manifest_file))
28
+ # TODO: make this work with esbuild too
28
29
  css_file = manifest["main.css"].split("/").last
29
30
  css_path = ["output", "_bridgetown", "static", "css", css_file].join("/")
30
31
  Bridgetown.logger.info "PurgeCSS", "Purging \#{css_file}"
@@ -5,6 +5,9 @@ services:
5
5
  buildCommand: bin/bridgetown deploy
6
6
  staticPublishPath: ./output
7
7
  pullRequestPreviewsEnabled: true
8
+ envVars:
9
+ - key: BRIDGETOWN_ENV
10
+ value: production
8
11
  headers:
9
12
  - path: /*
10
13
  name: X-Frame-Options
@@ -4,25 +4,53 @@ require "fileutils"
4
4
 
5
5
  say "Installing Stimulus...", :green
6
6
 
7
- run("yarn add stimulus")
7
+ run("yarn add @hotwired/stimulus")
8
+ if Bridgetown::Utils.frontend_bundler_type == :webpack
9
+ run("yarn add @hotwired/stimulus-webpack-helpers")
10
+ end
8
11
 
9
12
  say 'Adding Stimulus to "frontend/javascript/index.js"...', :magenta
10
13
 
11
14
  javascript_import do
12
- <<~JS
13
- import { Application } from "stimulus"
14
- import { definitionsFromContext } from "stimulus/webpack-helpers"
15
- JS
15
+ if Bridgetown::Utils.frontend_bundler_type == :esbuild
16
+ <<~JS
17
+ import { Application } from "@hotwired/stimulus"
18
+ JS
19
+ else
20
+ <<~JS
21
+ import { Application } from "@hotwired/stimulus"
22
+ import { definitionsFromContext } from "@hotwired/stimulus-webpack-helpers"
23
+ JS
24
+ end
16
25
  end
17
26
 
18
27
  javascript_dir = File.join("frontend", "javascript")
19
28
 
20
29
  append_to_file(File.join(javascript_dir, "index.js")) do
21
- <<~JS
22
- const application = Application.start()
23
- const context = require.context("./controllers", true, /\.js$/)
24
- application.load(definitionsFromContext(context))
25
- JS
30
+ if Bridgetown::Utils.frontend_bundler_type == :esbuild
31
+ <<~JS
32
+
33
+ window.Stimulus = Application.start()
34
+
35
+ import controllers from "./controllers/**/*.{js,js.rb}"
36
+ Object.entries(controllers).forEach(([filename, controller]) => {
37
+ if (filename.includes("_controller.")) {
38
+ const identifier = filename.replace("./controllers/", "")
39
+ .replace(/_controller\..*$/, "")
40
+ .replace("/", "--")
41
+
42
+ Stimulus.register(identifier, controller.default)
43
+ }
44
+ })
45
+ JS
46
+ else
47
+ <<~JS
48
+
49
+ window.Stimulus = Application.start()
50
+ const context = require.context("./controllers", true, /\.js$/)
51
+ Stimulus.load(definitionsFromContext(context))
52
+ JS
53
+ end
26
54
  end
27
55
 
28
56
  controller_dir = File.join(javascript_dir, "controllers")
@@ -33,7 +61,7 @@ FileUtils.mkdir_p(controller_dir)
33
61
  say "Creating an example Stimulus Controller for you!...", :magenta
34
62
  create_file(File.join(controller_dir, "example_controller.js")) do
35
63
  <<~JS
36
- import { Controller } from "stimulus"
64
+ import { Controller } from "@hotwired/stimulus"
37
65
  export default class extends Controller {
38
66
  connect() {
39
67
  console.log("Hello, Stimulus!", this.element)
@@ -46,4 +74,4 @@ say "Stimulus successfully added", :green
46
74
 
47
75
  say "To start adding controllers, visit the `./frontend/javascript/controllers/` directory", :blue
48
76
  say "Make sure your controllers follow the `[name]_controller.js` convention", :blue
49
- say 'For further reading, check out "https://stimulus.hotwire.dev/"', :blue
77
+ say 'For further reading, check out "https://stimulus.hotwired.dev/"', :blue
@@ -1,3 +1,8 @@
1
+ /* If you need to add @import statements, do so up here */
2
+
3
+ @import "jit-refresh.css"; /* triggers frontend rebuilds */
4
+
5
+ /* Set up Tailwind imports */
1
6
  @tailwind base;
2
7
  @tailwind components;
3
8
  @tailwind utilities;
@@ -11,15 +11,22 @@ unless File.exist?("postcss.config.js")
11
11
  return
12
12
  end
13
13
 
14
+ say_status :tailwind, "Installing Tailwind CSS..."
15
+
14
16
  confirm = ask "This configuration will ovewrite your existing #{"postcss.config.js".bold.white}. Would you like to continue? [Yn]"
15
17
  return unless confirm.casecmp?("Y")
16
18
 
17
19
  run "yarn add -D tailwindcss"
18
20
  run "npx tailwindcss init"
19
21
 
20
- copy_file in_templates_dir("postcss.config.js"), "postcss.config.js", force: true
22
+ gsub_file "tailwind.config.js", "content: [],", <<~JS.strip
23
+ content: [
24
+ './src/**/*.{html,md,liquid,erb,serb}',
25
+ './frontend/javascript/**/*.js',
26
+ ],
27
+ JS
21
28
 
22
- run "bundle exec bridgetown configure purgecss"
29
+ copy_file in_templates_dir("postcss.config.js"), "postcss.config.js", force: true
23
30
 
24
31
  if File.exist?("frontend/styles/index.css")
25
32
  prepend_to_file "frontend/styles/index.css",
@@ -29,4 +36,26 @@ else
29
36
  say File.read(in_templates_dir("/css_imports.css"))
30
37
  end
31
38
 
39
+ create_file "frontend/styles/jit-refresh.css", "/* #{Time.now.to_i} */"
40
+
41
+ create_builder "tailwind_jit.rb" do
42
+ <<~RUBY
43
+ class Builders::TailwindJit < SiteBuilder
44
+ def build
45
+ hook :site, :pre_reload do |_, paths|
46
+ # Don't trigger refresh if it's a frontend-only change
47
+ next if paths.length == 1 && paths.first.ends_with?("manifest.json")
48
+
49
+ # Save out a comment file to trigger Tailwind's JIT
50
+ refresh_file = site.in_root_dir("frontend", "styles", "jit-refresh.css")
51
+ File.write refresh_file, "/* \#{Time.now.to_i} */"
52
+ throw :halt # don't continue the build, wait for watcher rebuild
53
+ end
54
+ end
55
+ end
56
+ RUBY
57
+ end
58
+
59
+ say_status :tailwind, "Tailwind CSS is now configured."
60
+
32
61
  # rubocop:enable all