bridgetown-core 1.0.0.alpha11 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/bin/bridgetown +6 -1
  4. data/bridgetown-core.gemspec +3 -3
  5. data/lib/bridgetown-core/commands/base.rb +18 -18
  6. data/lib/bridgetown-core/commands/build.rb +1 -1
  7. data/lib/bridgetown-core/commands/clean.rb +2 -2
  8. data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +27 -0
  9. data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +216 -0
  10. data/lib/bridgetown-core/commands/esbuild/migrate-from-webpack.rb +47 -0
  11. data/lib/bridgetown-core/commands/esbuild/setup.rb +4 -0
  12. data/lib/bridgetown-core/commands/esbuild/update.rb +4 -0
  13. data/lib/bridgetown-core/commands/esbuild.rb +83 -0
  14. data/lib/bridgetown-core/commands/new.rb +80 -10
  15. data/lib/bridgetown-core/commands/webpack/enable-postcss.rb +1 -1
  16. data/lib/bridgetown-core/commands/webpack/update.rb +3 -3
  17. data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +1 -1
  18. data/lib/bridgetown-core/commands/webpack.rb +3 -3
  19. data/lib/bridgetown-core/component.rb +9 -3
  20. data/lib/bridgetown-core/concerns/site/configurable.rb +4 -0
  21. data/lib/bridgetown-core/concerns/site/content.rb +4 -4
  22. data/lib/bridgetown-core/configurations/purgecss.rb +2 -1
  23. data/lib/bridgetown-core/configurations/stimulus.rb +40 -12
  24. data/lib/bridgetown-core/configurations/tailwindcss/css_imports.css +5 -0
  25. data/lib/bridgetown-core/configurations/tailwindcss.rb +31 -2
  26. data/lib/bridgetown-core/configurations/turbo/turbo_transitions.js +48 -0
  27. data/lib/bridgetown-core/configurations/turbo.rb +15 -5
  28. data/lib/bridgetown-core/converters/erb_templates.rb +1 -1
  29. data/lib/bridgetown-core/converters/ruby_templates.rb +1 -1
  30. data/lib/bridgetown-core/converters/serbea_templates.rb +1 -1
  31. data/lib/bridgetown-core/errors.rb +21 -0
  32. data/lib/bridgetown-core/helpers.rb +3 -2
  33. data/lib/bridgetown-core/model/origin.rb +4 -6
  34. data/lib/bridgetown-core/rack/boot.rb +5 -9
  35. data/lib/bridgetown-core/ruby_template_view.rb +4 -0
  36. data/lib/bridgetown-core/tags/{webpack_path.rb → asset_path.rb} +7 -9
  37. data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +2 -1
  38. data/lib/bridgetown-core/utils.rb +63 -9
  39. data/lib/bridgetown-core/version.rb +1 -1
  40. data/lib/bridgetown-core/watcher.rb +34 -34
  41. data/lib/bridgetown-core.rb +1 -0
  42. data/lib/site_template/Gemfile.erb +17 -11
  43. data/lib/site_template/README.md +2 -2
  44. data/lib/site_template/{Rakefile → Rakefile.erb} +15 -0
  45. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.erb +11 -0
  46. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.rb +5 -0
  47. data/lib/site_template/TEMPLATES/erb/_layouts/default.erb +15 -0
  48. data/lib/site_template/TEMPLATES/erb/_layouts/page.erb +7 -0
  49. data/lib/site_template/TEMPLATES/erb/_layouts/post.erb +7 -0
  50. data/lib/site_template/TEMPLATES/erb/_partials/_footer.erb +3 -0
  51. data/lib/site_template/TEMPLATES/erb/_partials/_head.erb +10 -0
  52. data/lib/site_template/{src → TEMPLATES/liquid}/_components/footer.liquid +0 -0
  53. data/lib/site_template/TEMPLATES/liquid/_components/head.liquid +10 -0
  54. data/lib/site_template/TEMPLATES/liquid/_components/navbar.liquid +11 -0
  55. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/default.liquid +2 -2
  56. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/page.liquid +0 -0
  57. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/post.liquid +0 -0
  58. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.rb +5 -0
  59. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.serb +11 -0
  60. data/lib/site_template/TEMPLATES/serbea/_layouts/default.serb +15 -0
  61. data/lib/site_template/TEMPLATES/serbea/_layouts/page.serb +7 -0
  62. data/lib/site_template/TEMPLATES/serbea/_layouts/post.serb +7 -0
  63. data/lib/site_template/TEMPLATES/serbea/_partials/_footer.serb +3 -0
  64. data/lib/site_template/TEMPLATES/serbea/_partials/_head.serb +10 -0
  65. data/lib/site_template/frontend/javascript/index.js.erb +7 -3
  66. data/lib/site_template/frontend/styles/index.css +71 -6
  67. data/lib/site_template/package.json.erb +24 -9
  68. data/lib/site_template/ruby-version.erb +1 -0
  69. data/lib/site_template/server/roda_app.rb +5 -3
  70. data/lib/site_template/server/routes/hello.rb.sample +1 -1
  71. data/lib/site_template/src/images/logo.svg +91 -0
  72. data/lib/site_template/src/index.md.erb +22 -0
  73. data/lib/site_template/src/posts.md.erb +28 -0
  74. metadata +53 -22
  75. data/lib/bridgetown-core/configurations/swup.rb +0 -37
  76. data/lib/site_template/frontend/styles/index.scss +0 -17
  77. data/lib/site_template/src/_components/head.liquid +0 -10
  78. data/lib/site_template/src/_components/navbar.liquid +0 -5
  79. data/lib/site_template/src/_layouts/home.liquid +0 -7
  80. data/lib/site_template/src/images/.keep +0 -1
  81. data/lib/site_template/src/index.md +0 -7
  82. data/lib/site_template/src/posts.md +0 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09c13a3ec4bb37595ede90e5536eca3159812d06c482397d971d1130eab3ceab'
4
- data.tar.gz: 48cd4b6488ba57a185e510f00e6986b8514ad33887b7710431c40d9efcae4f45
3
+ metadata.gz: b6953f85017e90090c0078b710b3e447b69366bd9fed38bd5e307ee72ae3181c
4
+ data.tar.gz: 863dcdcea016110ae4e05922f7357b866bd2a77998b5da78ffb92819238c59c4
5
5
  SHA512:
6
- metadata.gz: '008f32b43e009a8349bc69fe01277c9a7ebdef2c7062d8c0dc331826d0eac394491a75b48892629d5a835eeef12e435c573d4c811ec33441555ec820870157d6'
7
- data.tar.gz: b6cf7933d50093c1332b1b39f5764768a3d8cdc3ff91b115e3d31790afa350826815f30e7d3e8c3891ddffea236f40b8e5b52268ec8eb019b4e20f319f1171ef
6
+ metadata.gz: eb6a1aa56f1544fcc37c4e204df417b5d7d37fa0e219e6a484872cdf4defee1c165fda09f4f30486d64635ef9ab6cf6db3edc8c63316dd3e61ab37be1394443c
7
+ data.tar.gz: 81b03e750b6fe6b25c1fbb2e62350f2c2776bf4902c236c5299f90c653720037e74ae8500bf71d928825efd3d83c651ad1d80523cb1362a1db2100d8f88daef9
data/.rubocop.yml CHANGED
@@ -12,6 +12,7 @@ AllCops:
12
12
  - tmp/**/*
13
13
  - test/source/**/*
14
14
  - test/resources/src/_pages/*.rb
15
+ - lib/site_template/TEMPLATES/**/*
15
16
  - lib/site_template/Rakefile
16
17
  - lib/site_template/config.ru
17
18
  - lib/site_template/config/**/*
data/bin/bridgetown CHANGED
@@ -34,4 +34,9 @@ end
34
34
  ENV["RACK_ENV"] = ENV["BRIDGETOWN_ENV"]
35
35
 
36
36
  require "bridgetown-core/commands/base"
37
- Bridgetown::Commands::Base.start unless output_version
37
+ begin
38
+ Bridgetown::Commands::Base.start unless output_version
39
+ rescue StandardError => e
40
+ Bridgetown::Errors.print_build_error(e)
41
+ exit(false)
42
+ end
@@ -30,15 +30,15 @@ Gem::Specification.new do |s|
30
30
 
31
31
  s.required_ruby_version = ">= 2.7.0"
32
32
 
33
- s.add_runtime_dependency("activemodel", "~> 6.0")
34
- s.add_runtime_dependency("activesupport", "~> 6.0")
33
+ s.add_runtime_dependency("activemodel", [">= 6.0", "< 8.0"])
34
+ s.add_runtime_dependency("activesupport", [">= 6.0", "< 8.0"])
35
35
  s.add_runtime_dependency("addressable", "~> 2.4")
36
36
  s.add_runtime_dependency("amazing_print", "~> 1.2")
37
37
  s.add_runtime_dependency("colorator", "~> 1.0")
38
38
  s.add_runtime_dependency("erubi", "~> 1.9")
39
39
  s.add_runtime_dependency("faraday", "~> 1.0")
40
40
  s.add_runtime_dependency("faraday_middleware", "~> 1.0")
41
- s.add_runtime_dependency("hash_with_dot_access", "~> 1.0")
41
+ s.add_runtime_dependency("hash_with_dot_access", "~> 1.2")
42
42
  s.add_runtime_dependency("i18n", "~> 1.0")
43
43
  s.add_runtime_dependency("kramdown", "~> 2.1")
44
44
  s.add_runtime_dependency("kramdown-parser-gfm", "~> 1.0")
@@ -34,41 +34,42 @@ module Bridgetown
34
34
  rake.display_tasks_and_comments
35
35
  end
36
36
 
37
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Style/GlobalVars
37
+ def load_rake_tasks(rake)
38
+ rake.load_rakefile
39
+ tasks = rake.instance_variable_get(:@tasks)
40
+ rake.instance_variable_set(:@tasks, tasks.reject do |_k, v|
41
+ v.locations.first&.include?("/lib/rails/tasks/") ||
42
+ v.locations.first&.include?("/lib/rake/dsl_definition")
43
+ end)
44
+ end
45
+
46
+ # rubocop:disable Style/GlobalVars
38
47
  def handle_no_command_error(cmd, _has_namespace = $thor_runner)
39
48
  require "rake"
40
49
  Rake::TaskManager.record_task_metadata = true
41
50
 
42
51
  Rake.with_application do |rake|
43
- rake.instance_variable_set(:@name, "bridgetown")
44
52
  rake.standard_exception_handling do
45
53
  rakefile, _location = rake.find_rakefile_location
46
54
  unless rakefile
47
- puts "No Rakefile found (searching: #{rake.class::DEFAULT_RAKEFILES.join(", ")})\n"
55
+ puts "No Rakefile found (searching: #{rake.class::DEFAULT_RAKEFILES.join(", ")})\n\n" # rubocop:disable Layout/LineLength
48
56
  new.invoke("help")
49
57
  return # rubocop:disable Lint/NonLocalExitFromIterator
50
58
  end
51
- rake.load_rakefile
52
- rake.top_level
53
- end
54
- cmd = cmd.split("[")
55
- args = []
56
- if cmd[1]
57
- args = cmd[1].gsub("\\,", "__COMMA__").delete_suffix!("]").split(",").map do |item|
58
- item.gsub("__COMMA__", ",")
59
- end
59
+ rake.init("bridgetown")
60
+ load_rake_tasks(rake)
60
61
  end
61
62
 
62
- if Rake::Task.task_defined?(cmd[0])
63
- Rake::Task[cmd[0]].invoke(*args)
63
+ if Rake::Task.task_defined?(cmd.split("[")[0])
64
+ rake.top_level
64
65
  else
65
- puts "Unknown task: #{cmd[0]}\n\nHere's a list of tasks you can run:"
66
+ puts "Unknown task: #{cmd.split("[")[0]}\n\nHere's a list of tasks you can run:"
66
67
  display_rake_tasks(rake)
67
68
  end
68
69
  end
69
70
  end
70
71
  end
71
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Style/GlobalVars
72
+ # rubocop:enable Style/GlobalVars
72
73
 
73
74
  desc "dream", "There's a place where that idea still exists as a reality"
74
75
  def dream
@@ -101,8 +102,7 @@ module Bridgetown
101
102
  rakefile, _location = rake.find_rakefile_location
102
103
  return unless rakefile # rubocop:disable Lint/NonLocalExitFromIterator
103
104
 
104
- rake.load_rakefile
105
- rake.top_level
105
+ self.class.load_rake_tasks(rake)
106
106
  puts "Available Rake Tasks:"
107
107
  self.class.display_rake_tasks(rake)
108
108
  end
@@ -77,7 +77,7 @@ module Bridgetown
77
77
  end
78
78
  Bridgetown.logger.info "Generating…"
79
79
  @site.process
80
- Bridgetown.logger.info "Done! 🎉", "#{"Completed".green} in less than" \
80
+ Bridgetown.logger.info "Done! 🎉", "#{"Completed".bold.green} in less than" \
81
81
  " #{(Time.now - t).ceil(2)} seconds."
82
82
 
83
83
  return unless config_options[:using_puma]
@@ -21,12 +21,12 @@ module Bridgetown
21
21
  destination = config["destination"]
22
22
  metadata_file = File.join(config["root_dir"], ".bridgetown-metadata")
23
23
  cache_dir = File.join(config["root_dir"], config["cache_dir"])
24
- webpack_dir = File.join(config["root_dir"], ".bridgetown-webpack")
24
+ bundling_dir = File.join(config["root_dir"], ".bridgetown-cache", "frontend-bundling")
25
25
 
26
26
  remove(destination, checker_func: :directory?)
27
27
  remove(metadata_file, checker_func: :file?)
28
28
  remove(cache_dir, checker_func: :directory?)
29
- remove(webpack_dir, checker_func: :directory?)
29
+ remove(bundling_dir, checker_func: :directory?)
30
30
  end
31
31
 
32
32
  protected
@@ -0,0 +1,27 @@
1
+ const build = require("./config/esbuild.defaults.js")
2
+
3
+ // Update this if you need to configure a destination folder other than `output`
4
+ const outputFolder = "output"
5
+
6
+ // You can customize this as you wish, perhaps to add new esbuild plugins.
7
+ //
8
+ // Eg:
9
+ //
10
+ // ```
11
+ // const path = require("path")
12
+ // const esbuildCopy = require('esbuild-plugin-copy').default
13
+ // const esbuildOptions = {
14
+ // plugins: [
15
+ // esbuildCopy({
16
+ // assets: {
17
+ // from: [path.resolve(__dirname, 'node_modules/somepackage/files/*')],
18
+ // to: [path.resolve(__dirname, 'output/_bridgetown/somepackage/files')],
19
+ // },
20
+ // verbose: false
21
+ // }),
22
+ // ]
23
+ // }
24
+ // ```
25
+ const esbuildOptions = {}
26
+
27
+ build(outputFolder, esbuildOptions)
@@ -0,0 +1,216 @@
1
+ // This file is created and managed by Bridgetown.
2
+ // Instead of editing this file, add your overrides to `esbuild.config.js`
3
+ //
4
+ // To update this file to the latest version provided by Bridgetown,
5
+ // run `bridgetown esbuild update`. Any changes to this file will be overwritten
6
+ // when an update is applied hence we strongly recommend adding overrides to
7
+ // `esbuild.config.js` instead of editing this file.
8
+ //
9
+ // Shipped with Bridgetown v<%= Bridgetown::VERSION %>
10
+
11
+ const path = require("path")
12
+ const fsLib = require("fs")
13
+ const fs = fsLib.promises
14
+ const glob = require("glob")
15
+ const postcss = require("postcss")
16
+ const postCssImport = require("postcss-import")
17
+ const readCache = require("read-cache")
18
+
19
+ // Glob plugin derived from:
20
+ // https://github.com/thomaschaaf/esbuild-plugin-import-glob
21
+ // https://github.com/xiaohui-zhangxh/jsbundling-rails/commit/b15025dcc20f664b2b0eb238915991afdbc7cb58
22
+ const importGlobPlugin = () => ({
23
+ name: "import-glob",
24
+ setup: (build) => {
25
+ build.onResolve({ filter: /\*/ }, async (args) => {
26
+ if (args.resolveDir === "") {
27
+ return; // Ignore unresolvable paths
28
+ }
29
+
30
+ const adjustedPath = args.path.replace(/^bridgetownComponents\//, "../../src/_components/")
31
+
32
+ return {
33
+ path: adjustedPath,
34
+ namespace: "import-glob",
35
+ pluginData: {
36
+ path: adjustedPath,
37
+ resolveDir: args.resolveDir,
38
+ },
39
+ }
40
+ })
41
+
42
+ build.onLoad({ filter: /.*/, namespace: "import-glob" }, async (args) => {
43
+ const files = glob.sync(args.pluginData.path, {
44
+ cwd: args.pluginData.resolveDir,
45
+ }).sort()
46
+
47
+ const importerCode = `
48
+ ${files
49
+ .map((module, index) => `import * as module${index} from '${module}'`)
50
+ .join(';')}
51
+ const modules = {${files
52
+ .map((module, index) => `
53
+ "${module.replace("../../src/_components/", "")}": module${index},`)
54
+ .join("")}
55
+ };
56
+ export default modules;
57
+ `
58
+
59
+ return { contents: importerCode, resolveDir: args.pluginData.resolveDir }
60
+ })
61
+ },
62
+ })
63
+
64
+ const postCssPlugin = (options) => ({
65
+ name: "postcss",
66
+ async setup(build) {
67
+ // Process .css files with PostCSS
68
+ build.onLoad({ filter: /\.(css)$/ }, async (args) => {
69
+ const additionalFilePaths = []
70
+ const css = await fs.readFile(args.path, "utf8")
71
+
72
+ // Configure import plugin so PostCSS can properly resolve `@import`ed CSS files
73
+ const importPlugin = postCssImport({
74
+ filter: itemPath => {
75
+ // We'll want to track any imports later when in watch mode
76
+ additionalFilePaths.push(path.resolve(path.dirname(args.path), itemPath))
77
+ return true
78
+ },
79
+ load: async filename => {
80
+ let contents = await readCache(filename, "utf-8")
81
+ const filedir = path.dirname(filename)
82
+
83
+ // We need to transform `url(...)` in imported CSS so the filepaths are properly
84
+ // relative to the entrypoint. Seems icky to have to hack this! C'est la vie...
85
+ contents = contents.replace(/url\(['"]?\.\/(.*?)['"]?\)/g, (_match, p1) => {
86
+ const relpath = path.relative(args.path, path.resolve(filedir, p1)).replace(/^\.\.\//, "")
87
+ return `url("${relpath}")`
88
+ })
89
+ return contents
90
+ }
91
+ })
92
+
93
+ // Process the file through PostCSS
94
+ const result = await postcss([importPlugin, ...options.plugins]).process(css, {
95
+ map: true,
96
+ ...options.options,
97
+ from: args.path,
98
+ });
99
+
100
+ return {
101
+ contents: result.css,
102
+ loader: "css",
103
+ watchFiles: [args.path, ...additionalFilePaths],
104
+ }
105
+ })
106
+ },
107
+ })
108
+
109
+ // Set up defaults and generate frontend bundling manifest file
110
+ const bridgetownPreset = (outputFolder) => ({
111
+ name: "bridgetownPreset",
112
+ async setup(build) {
113
+ // Ensure any imports anywhere starting with `/` are left verbatim
114
+ // so they can be used in-browser for actual `src` repo files
115
+ build.onResolve({ filter: /^\// }, args => {
116
+ return { path: args.path, external: true }
117
+ })
118
+
119
+ build.onStart(() => {
120
+ console.log("esbuild: frontend bundling started...")
121
+ })
122
+
123
+ // Generate the final output manifest
124
+ build.onEnd(async (result) => {
125
+ if (!result.metafile) {
126
+ console.warn("esbuild: build process error, cannot write manifest")
127
+ return
128
+ }
129
+
130
+ const manifest = {}
131
+ const entrypoints = []
132
+
133
+ // We don't need `frontend/` cluttering up everything
134
+ const stripPrefix = (str) => str.replace(/^frontend\//, "")
135
+
136
+ // For calculating the file size of bundle output
137
+ const fileSize = (path) => {
138
+ const { size } = fsLib.statSync(path)
139
+ const i = Math.floor(Math.log(size) / Math.log(1024))
140
+ return (size / Math.pow(1024, i)).toFixed(2) * 1 + ['B', 'KB', 'MB', 'GB', 'TB'][i]
141
+ }
142
+
143
+ // Let's loop through all the various outputs
144
+ for (const key in result.metafile.outputs) {
145
+ const value = result.metafile.outputs[key]
146
+ const inputs = Object.keys(value.inputs)
147
+ const pathShortener = new RegExp(`^${outputFolder}\\/_bridgetown\\/static\\/`, "g")
148
+ const outputPath = key.replace(pathShortener, "")
149
+
150
+ if (value.entryPoint) {
151
+ // We have an entrypoint!
152
+ manifest[stripPrefix(value.entryPoint)] = outputPath
153
+ entrypoints.push([outputPath, fileSize(key)])
154
+ } else if (key.match(/index(\.js)?\.[^-.]*\.css/) && inputs.find(item => item.endsWith("index.css"))) {
155
+ // Special treatment for index.css
156
+ manifest[stripPrefix(inputs.find(item => item.endsWith("index.css")))] = outputPath
157
+ entrypoints.push([outputPath, fileSize(key)])
158
+ } else if (inputs.length > 0) {
159
+ // Naive implementation, we'll just grab the first input and hope it's accurate
160
+ manifest[stripPrefix(inputs[0])] = outputPath
161
+ }
162
+ }
163
+
164
+ const manifestFolder = path.join(process.cwd(), ".bridgetown-cache", "frontend-bundling")
165
+ await fs.mkdir(manifestFolder, { recursive: true })
166
+ await fs.writeFile(path.join(manifestFolder, "manifest.json"), JSON.stringify(manifest))
167
+
168
+ console.log("esbuild: frontend bundling complete!")
169
+ console.log("esbuild: entrypoints processed:")
170
+ entrypoints.forEach(entrypoint => {
171
+ const [entrypointName, entrypointSize] = entrypoint
172
+ console.log(` - ${entrypointName}: ${entrypointSize}`)
173
+ })
174
+ })
175
+ }
176
+ })
177
+
178
+ // Load the PostCSS config from postcss.config.js or whatever else is a supported location/format
179
+ const postcssrc = require("postcss-load-config")
180
+ const postCssConfig = postcssrc.sync()
181
+
182
+ module.exports = (outputFolder, esbuildOptions) => {
183
+ esbuildOptions.plugins = esbuildOptions.plugins || []
184
+ // Add the PostCSS & glob plugins to the top of the plugin stack
185
+ esbuildOptions.plugins.unshift(postCssPlugin(postCssConfig))
186
+ esbuildOptions.plugins.unshift(importGlobPlugin())
187
+ // Add the Bridgetown preset to the bottom of the plugin stack
188
+ esbuildOptions.plugins.push(bridgetownPreset(outputFolder))
189
+
190
+ // esbuild, take it away!
191
+ require("esbuild").build({
192
+ bundle: true,
193
+ loader: {
194
+ ".jpg": "file",
195
+ ".png": "file",
196
+ ".gif": "file",
197
+ ".svg": "file",
198
+ ".woff": "file",
199
+ ".woff2": "file",
200
+ ".ttf": "file",
201
+ ".eot": "file",
202
+ },
203
+ resolveExtensions: [".tsx",".ts",".jsx",".js",".css",".json",".js.rb"],
204
+ nodePaths: ["frontend/javascript", "frontend/styles"],
205
+ watch: process.argv.includes("--watch"),
206
+ minify: process.argv.includes("--minify"),
207
+ sourcemap: true,
208
+ target: "es2016",
209
+ entryPoints: ["frontend/javascript/index.js"],
210
+ entryNames: "[dir]/[name].[hash]",
211
+ outdir: path.join(process.cwd(), `${outputFolder}/_bridgetown/static`),
212
+ publicPath: "/_bridgetown/static",
213
+ metafile: true,
214
+ ...esbuildOptions,
215
+ }).catch(() => process.exit(1))
216
+ }
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Layout/LineLength
4
+
5
+ if package_json["devDependencies"].key?("sass")
6
+ say "Unable to migrate, project uses Sass. Please migrate to PostCSS first before migrating to esbuild."
7
+ return
8
+ end
9
+
10
+ remove_file "webpack.config.js"
11
+ remove_file "config/webpack.defaults.js"
12
+
13
+ apply find_in_source_paths("setup.rb"), verbose: false
14
+
15
+ default_postcss_config = File.expand_path("../../../site_template/postcss.config.js.erb", __dir__)
16
+ template default_postcss_config, "postcss.config.js"
17
+
18
+ unless Bridgetown.environment.test?
19
+ required_packages = %w(esbuild glob postcss postcss-flexbugs-fixes postcss-preset-env postcss-import postcss-load-config)
20
+ redundant_packages = %w(esbuild-loader webpack webpack-cli webpack-manifest-plugin webpack-merge css-loader file-loader mini-css-extract-plugin postcss-loader)
21
+
22
+ say "Installing required packages"
23
+
24
+ gsub_file "package.json", %r! "postcss-focus-within": "^4.0.0",?!, ""
25
+
26
+ run "yarn add -D #{required_packages.join(" ")}"
27
+
28
+ packages_to_remove = package_json["devDependencies"].slice(*redundant_packages).keys
29
+ unless packages_to_remove.empty?
30
+ confirm = ask "\nThe following packages will be removed: \n\n#{packages_to_remove.join("\n")}\n\nWould you like to continue? [Yn]"
31
+ return unless confirm.casecmp?("Y")
32
+
33
+ run "yarn remove #{packages_to_remove.join(" ")}"
34
+ end
35
+ end
36
+
37
+ gsub_file "Rakefile", %(desc "Build the frontend with Webpack for deployment"), %(desc "Build the frontend with esbuild for deployment")
38
+ gsub_file "Rakefile", %(desc "Watch the frontend with Webpack during development"), %(desc "Watch the frontend with esbuild during development")
39
+ gsub_file "Rakefile", %(sh "yarn run webpack-build"), %(sh "yarn run esbuild")
40
+ gsub_file "Rakefile", %(sh "yarn run webpack-dev --color"), %(sh "yarn run esbuild-dev")
41
+ gsub_file "package.json", %("webpack-build": "webpack --mode production"), %("esbuild": "node esbuild.config.js --minify")
42
+ gsub_file "package.json", %("webpack-dev": "webpack --mode development -w"), %("esbuild-dev": "node esbuild.config.js --watch")
43
+
44
+ say "🎉 Migration steps to esbuild finished!"
45
+ say "Make sure you replace your `webpack_path` helpers with `asset_path` helpers in your templates"
46
+
47
+ # rubocop:enable Layout/LineLength
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ template "esbuild.defaults.js.erb", "config/esbuild.defaults.js"
4
+ copy_file "esbuild.config.js", force: true
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ template "esbuild.defaults.js.erb", "config/esbuild.defaults.js", force: true
4
+ say "🎉 esbuild configuration updated successfully!"
@@ -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