bridgetown-core 1.0.0.alpha9 → 1.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -0
- data/bin/bridgetown +6 -1
- data/bridgetown-core.gemspec +4 -3
- data/lib/bridgetown-core/collection.rb +6 -6
- data/lib/bridgetown-core/commands/base.rb +18 -18
- data/lib/bridgetown-core/commands/build.rb +1 -1
- data/lib/bridgetown-core/commands/clean.rb +2 -2
- data/lib/bridgetown-core/commands/console.rb +1 -0
- data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +27 -0
- data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +216 -0
- data/lib/bridgetown-core/commands/esbuild/migrate-from-webpack.rb +47 -0
- data/lib/bridgetown-core/commands/esbuild/setup.rb +4 -0
- data/lib/bridgetown-core/commands/esbuild/update.rb +4 -0
- data/lib/bridgetown-core/commands/esbuild.rb +83 -0
- data/lib/bridgetown-core/commands/new.rb +80 -10
- data/lib/bridgetown-core/commands/plugins.rb +1 -1
- data/lib/bridgetown-core/commands/webpack/enable-postcss.rb +1 -1
- data/lib/bridgetown-core/commands/webpack/update.rb +3 -3
- data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +1 -1
- data/lib/bridgetown-core/commands/webpack.rb +3 -3
- data/lib/bridgetown-core/component.rb +9 -3
- data/lib/bridgetown-core/concerns/site/configurable.rb +6 -0
- data/lib/bridgetown-core/concerns/site/content.rb +4 -4
- data/lib/bridgetown-core/concerns/site/extensible.rb +8 -0
- data/lib/bridgetown-core/concerns/site/processable.rb +23 -4
- data/lib/bridgetown-core/concerns/site/ssr.rb +2 -17
- data/lib/bridgetown-core/configurations/minitesting.rb +1 -1
- data/lib/bridgetown-core/configurations/purgecss.rb +2 -1
- data/lib/bridgetown-core/configurations/render/render.yaml.erb +3 -0
- data/lib/bridgetown-core/configurations/stimulus.rb +41 -12
- data/lib/bridgetown-core/configurations/tailwindcss/css_imports.css +5 -0
- data/lib/bridgetown-core/configurations/tailwindcss.rb +31 -2
- data/lib/bridgetown-core/configurations/turbo/turbo_transitions.js +48 -0
- data/lib/bridgetown-core/configurations/turbo.rb +15 -5
- data/lib/bridgetown-core/configurations/vercel/vercel.json +45 -0
- data/lib/bridgetown-core/configurations/vercel/vercel_url.rb +12 -0
- data/lib/bridgetown-core/configurations/vercel.rb +4 -0
- data/lib/bridgetown-core/converters/erb_templates.rb +7 -9
- data/lib/bridgetown-core/converters/ruby_templates.rb +1 -1
- data/lib/bridgetown-core/converters/serbea_templates.rb +5 -8
- data/lib/bridgetown-core/drops/drop.rb +1 -1
- data/lib/bridgetown-core/drops/resource_drop.rb +28 -5
- data/lib/bridgetown-core/errors.rb +21 -0
- data/lib/bridgetown-core/generators/prototype_generator.rb +3 -3
- data/lib/bridgetown-core/helpers.rb +3 -2
- data/lib/bridgetown-core/hooks.rb +51 -20
- data/lib/bridgetown-core/model/base.rb +24 -1
- data/lib/bridgetown-core/model/origin.rb +4 -6
- data/lib/bridgetown-core/model/repo_origin.rb +48 -0
- data/lib/bridgetown-core/rack/boot.rb +5 -9
- data/lib/bridgetown-core/rack/roda.rb +4 -5
- data/lib/bridgetown-core/rack/routes.rb +44 -10
- data/lib/bridgetown-core/rack/static_indexes.rb +2 -0
- data/lib/bridgetown-core/resource/base.rb +3 -1
- data/lib/bridgetown-core/ruby_template_view.rb +11 -0
- data/lib/bridgetown-core/site.rb +5 -0
- data/lib/bridgetown-core/tags/{webpack_path.rb → asset_path.rb} +7 -9
- data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +2 -1
- data/lib/bridgetown-core/utils/loaders_manager.rb +17 -0
- data/lib/bridgetown-core/utils.rb +88 -30
- data/lib/bridgetown-core/version.rb +1 -1
- data/lib/bridgetown-core/watcher.rb +74 -70
- data/lib/bridgetown-core.rb +1 -0
- data/lib/site_template/Gemfile.erb +17 -11
- data/lib/site_template/README.md +2 -2
- data/lib/site_template/{Rakefile → Rakefile.erb} +15 -0
- data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.erb +11 -0
- data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.rb +5 -0
- data/lib/site_template/TEMPLATES/erb/_layouts/default.erb +15 -0
- data/lib/site_template/TEMPLATES/erb/_layouts/page.erb +7 -0
- data/lib/site_template/TEMPLATES/erb/_layouts/post.erb +7 -0
- data/lib/site_template/TEMPLATES/erb/_partials/_footer.erb +3 -0
- data/lib/site_template/TEMPLATES/erb/_partials/_head.erb +10 -0
- data/lib/site_template/{src → TEMPLATES/liquid}/_components/footer.liquid +0 -0
- data/lib/site_template/TEMPLATES/liquid/_components/head.liquid +10 -0
- data/lib/site_template/TEMPLATES/liquid/_components/navbar.liquid +11 -0
- data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/default.liquid +2 -2
- data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/page.liquid +0 -0
- data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/post.liquid +0 -0
- data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.rb +5 -0
- data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.serb +11 -0
- data/lib/site_template/TEMPLATES/serbea/_layouts/default.serb +15 -0
- data/lib/site_template/TEMPLATES/serbea/_layouts/page.serb +7 -0
- data/lib/site_template/TEMPLATES/serbea/_layouts/post.serb +7 -0
- data/lib/site_template/TEMPLATES/serbea/_partials/_footer.serb +3 -0
- data/lib/site_template/TEMPLATES/serbea/_partials/_head.serb +10 -0
- data/lib/site_template/frontend/javascript/index.js.erb +7 -3
- data/lib/site_template/frontend/styles/index.css +71 -6
- data/lib/site_template/package.json.erb +24 -9
- data/lib/site_template/ruby-version.erb +1 -0
- data/lib/site_template/server/roda_app.rb +5 -3
- data/lib/site_template/server/routes/hello.rb.sample +1 -1
- data/lib/site_template/src/images/logo.svg +91 -0
- data/lib/site_template/src/index.md.erb +22 -0
- data/lib/site_template/src/posts.md.erb +28 -0
- metadata +70 -22
- data/lib/bridgetown-core/configurations/swup.rb +0 -37
- data/lib/site_template/frontend/styles/index.scss +0 -17
- data/lib/site_template/src/_components/head.liquid +0 -10
- data/lib/site_template/src/_components/navbar.liquid +0 -5
- data/lib/site_template/src/_layouts/home.liquid +0 -7
- data/lib/site_template/src/images/.keep +0 -1
- data/lib/site_template/src/index.md +0 -7
- data/lib/site_template/src/posts.md +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6a9d2528b695e8e0cf1016e12d9ef4f83ea3983568db4b20e740f5256024990
|
4
|
+
data.tar.gz: 8cfdc7484ba7f011cac11708667eb93e3fa27400269b7a548fc1cbc80dee37c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98523ff2520d3428505ba743408fd20f4672cdfdebdb50fe914b025b7e63e6d661f923cdd6ee0d27c9f8cd126fc08b8b522206461b5e5862b6ddc7b30fcfe02c
|
7
|
+
data.tar.gz: 795673a2a1e3b44aa0624fbf1c7bb0e9bac35d2f3882dd45d309f70346777896a9ed75c1993f186f2a3adfc94df0d5c69e0beb71a7fbeaea3aa7ac5bf774400f
|
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/**/*
|
@@ -31,6 +32,10 @@ Performance/CollectionLiteralInLoop:
|
|
31
32
|
Exclude:
|
32
33
|
- test/test_filters.rb
|
33
34
|
|
35
|
+
Style/OpenStructUse:
|
36
|
+
Exclude:
|
37
|
+
- test/**/*.rb
|
38
|
+
|
34
39
|
Style/StringConcatenation:
|
35
40
|
Exclude:
|
36
41
|
- test/test_apply_command.rb
|
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
|
-
|
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
|
data/bridgetown-core.gemspec
CHANGED
@@ -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", "
|
34
|
-
s.add_runtime_dependency("activesupport", "
|
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.
|
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")
|
@@ -53,4 +53,5 @@ Gem::Specification.new do |s|
|
|
53
53
|
s.add_runtime_dependency("thor", "~> 1.1")
|
54
54
|
s.add_runtime_dependency("tilt", "~> 2.0")
|
55
55
|
s.add_runtime_dependency("webrick", "~> 1.7")
|
56
|
+
s.add_runtime_dependency("zeitwerk", "~> 2.5")
|
56
57
|
end
|
@@ -297,12 +297,6 @@ module Bridgetown
|
|
297
297
|
resources << resource if site.config.unpublished || resource.published?
|
298
298
|
end
|
299
299
|
|
300
|
-
private
|
301
|
-
|
302
|
-
def container
|
303
|
-
@container ||= site.config["collections_dir"]
|
304
|
-
end
|
305
|
-
|
306
300
|
def sort_resources!
|
307
301
|
if metadata["sort_by"].is_a?(String)
|
308
302
|
sort_resources_by_key!
|
@@ -312,6 +306,12 @@ module Bridgetown
|
|
312
306
|
resources.reverse! if metadata.sort_direction == "descending"
|
313
307
|
end
|
314
308
|
|
309
|
+
private
|
310
|
+
|
311
|
+
def container
|
312
|
+
@container ||= site.config["collections_dir"]
|
313
|
+
end
|
314
|
+
|
315
315
|
# A custom sort function based on Schwartzian transform
|
316
316
|
# Refer https://byparker.com/blog/2017/schwartzian-transform-faster-sorting/ for details
|
317
317
|
def sort_resources_by_key!
|
@@ -34,41 +34,42 @@ module Bridgetown
|
|
34
34
|
rake.display_tasks_and_comments
|
35
35
|
end
|
36
36
|
|
37
|
-
|
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.
|
52
|
-
rake
|
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
|
-
|
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
|
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
|
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
|
-
|
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(
|
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,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
|