bridgetown-core 1.0.0 → 1.1.0.beta1

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -1
  3. data/lib/bridgetown-core/collection.rb +37 -20
  4. data/lib/bridgetown-core/commands/concerns/actions.rb +3 -2
  5. data/lib/bridgetown-core/commands/configure.rb +1 -1
  6. data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +95 -12
  7. data/lib/bridgetown-core/commands/new.rb +10 -9
  8. data/lib/bridgetown-core/commands/plugins.rb +2 -0
  9. data/lib/bridgetown-core/commands/start.rb +3 -0
  10. data/lib/bridgetown-core/commands/webpack/update.rb +2 -2
  11. data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +11 -2
  12. data/lib/bridgetown-core/component.rb +13 -7
  13. data/lib/bridgetown-core/concerns/localizable.rb +20 -0
  14. data/lib/bridgetown-core/concerns/prioritizable.rb +44 -0
  15. data/lib/bridgetown-core/concerns/publishable.rb +11 -1
  16. data/lib/bridgetown-core/concerns/site/configurable.rb +2 -10
  17. data/lib/bridgetown-core/concerns/site/localizable.rb +5 -1
  18. data/lib/bridgetown-core/concerns/site/ssr.rb +3 -3
  19. data/lib/bridgetown-core/concerns/site/writable.rb +28 -0
  20. data/lib/bridgetown-core/configuration.rb +2 -0
  21. data/lib/bridgetown-core/configurations/bt-postcss/postcss.config.js +5 -3
  22. data/lib/bridgetown-core/configurations/bt-postcss.rb +1 -1
  23. data/lib/bridgetown-core/configurations/lit/esbuild-plugins.js +21 -0
  24. data/lib/bridgetown-core/configurations/lit/happy-days.lit.js +26 -0
  25. data/lib/bridgetown-core/configurations/lit/lit-components-entry.js +1 -0
  26. data/lib/bridgetown-core/configurations/lit/lit-ssr.config.js +6 -0
  27. data/lib/bridgetown-core/configurations/lit.rb +95 -0
  28. data/lib/bridgetown-core/configurations/open-props/variables.css.erb +11 -0
  29. data/lib/bridgetown-core/configurations/open-props.rb +21 -0
  30. data/lib/bridgetown-core/configurations/ruby2js/hello_world.js.rb +9 -0
  31. data/lib/bridgetown-core/configurations/ruby2js.rb +67 -0
  32. data/lib/bridgetown-core/configurations/shoelace.rb +50 -0
  33. data/lib/bridgetown-core/configurations/tailwindcss.rb +16 -2
  34. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
  35. data/lib/bridgetown-core/drops/generated_page_drop.rb +2 -1
  36. data/lib/bridgetown-core/drops/resource_drop.rb +2 -1
  37. data/lib/bridgetown-core/errors.rb +5 -5
  38. data/lib/bridgetown-core/filters/translation_filters.rb +11 -0
  39. data/lib/bridgetown-core/filters/url_filters.rb +37 -10
  40. data/lib/bridgetown-core/filters.rb +3 -0
  41. data/lib/bridgetown-core/frontmatter_defaults.rb +14 -8
  42. data/lib/bridgetown-core/generated_page.rb +1 -0
  43. data/lib/bridgetown-core/kramdown/parser/gfm.rb +36 -0
  44. data/lib/bridgetown-core/model/base.rb +1 -2
  45. data/lib/bridgetown-core/plugin.rb +6 -37
  46. data/lib/bridgetown-core/plugin_manager.rb +3 -2
  47. data/lib/bridgetown-core/rack/boot.rb +5 -0
  48. data/lib/bridgetown-core/rack/logger.rb +14 -4
  49. data/lib/bridgetown-core/rack/roda.rb +102 -8
  50. data/lib/bridgetown-core/rack/routes.rb +67 -2
  51. data/lib/bridgetown-core/resource/base.rb +4 -6
  52. data/lib/bridgetown-core/resource/destination.rb +18 -0
  53. data/lib/bridgetown-core/resource/permalink_processor.rb +6 -4
  54. data/lib/bridgetown-core/resource/relations.rb +1 -1
  55. data/lib/bridgetown-core/utils/aux.rb +2 -1
  56. data/lib/bridgetown-core/utils/require_gems.rb +3 -6
  57. data/lib/bridgetown-core/utils.rb +24 -11
  58. data/lib/bridgetown-core/version.rb +2 -2
  59. data/lib/bridgetown-core/watcher.rb +19 -6
  60. data/lib/bridgetown-core.rb +8 -2
  61. data/lib/site_template/README.md +2 -2
  62. data/lib/site_template/bridgetown.config.yml +3 -0
  63. data/lib/site_template/frontend/javascript/index.js.erb +1 -0
  64. data/lib/site_template/frontend/styles/syntax-highlighting.css +77 -0
  65. data/lib/site_template/package.json.erb +18 -17
  66. data/lib/site_template/server/roda_app.rb +3 -6
  67. data/lib/site_template/src/404.html +2 -1
  68. data/lib/site_template/src/500.html +10 -0
  69. metadata +20 -5
  70. data/lib/bridgetown-core/publisher.rb +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fdb62333635d80ceb9561a0cd9be68f0220ea729c8ac4505bb8e4460894075e1
4
- data.tar.gz: f7377127b4d64846e694d8ba4c032706ed161ea1595cf8dbf3eca3d2b6e4692d
3
+ metadata.gz: 95b4ce1888886fbccd72391216d1298ce7d20e6bfb506ceedab3208881b4d25c
4
+ data.tar.gz: 712ddfbba10913becc4fb800a499ce602d9e2848f395b87cf8c205d97000ab2e
5
5
  SHA512:
6
- metadata.gz: 051a34337053c1370745d37a7cc3def36e1623193e4c03e0b1006d06280303ad5442c289465185314f916dbcf2aa1b1123990ca196041b03bf3804a03b36f695
7
- data.tar.gz: d5adcc3f8c7c7938bbc220329c002c7cea281f4e21f8ea2bab685dabaffe48c5acca3998482d1e0ec6d0c7c172751c0c6b34481821f51b5d1ccc687b137e55a5
6
+ metadata.gz: 1efd58dbca74ae1f3903bd91e225c28abb74131a5b1bc1885b7cac696d5f97a6a1ee7b973fed4d9ad2a90fec9ccc610f4ab19c4cb60666bfeafc0f4cda28f715
7
+ data.tar.gz: 545fe04a5338166bf02927395c131d65a822b524b551865bc558dd1e4ffa4c1438ace43bad4fe09a29e980c77d458bcc9876a249bbf4598d45764f471693521b
data/.rubocop.yml CHANGED
@@ -11,12 +11,17 @@ AllCops:
11
11
  - vendor/**/*
12
12
  - tmp/**/*
13
13
  - test/source/**/*
14
- - test/resources/src/_pages/*.rb
14
+ - test/resources/src/**/*.rb
15
+ - lib/bridgetown-core/commands/base.rb
16
+ - lib/bridgetown-core/commands/plugins.rb
17
+ - lib/bridgetown-core/configurations/ruby2js/**/*
18
+ - lib/bridgetown-core/rack/roda.rb
15
19
  - lib/site_template/TEMPLATES/**/*
16
20
  - lib/site_template/Rakefile
17
21
  - lib/site_template/config.ru
18
22
  - lib/site_template/config/**/*
19
23
  - lib/site_template/plugins/site_builder.rb
24
+ - lib/site_template/server/roda_app.rb
20
25
 
21
26
  Lint/ConstantDefinitionInBlock:
22
27
  Exclude:
@@ -20,11 +20,11 @@ module Bridgetown
20
20
  end
21
21
 
22
22
  def builtin?
23
- label.in? %w(posts pages data).freeze
23
+ @is_builtin ||= label.in?(%w(posts pages data).freeze)
24
24
  end
25
25
 
26
26
  def data?
27
- label == "data"
27
+ @is_data ||= label == "data"
28
28
  end
29
29
 
30
30
  # Fetch the Resources in this collection.
@@ -215,7 +215,7 @@ module Bridgetown
215
215
  # Used by Resource's permalink processor
216
216
  # @return [String]
217
217
  def default_permalink
218
- metadata.fetch("permalink", "/:collection/:path/")
218
+ metadata.fetch("permalink", "/:locale/:collection/:path/")
219
219
  end
220
220
 
221
221
  # Extract options for this collection from the site configuration.
@@ -270,32 +270,29 @@ module Bridgetown
270
270
 
271
271
  # Read in resource from repo path
272
272
  # @param full_path [String]
273
- def read_resource(full_path, manifest: nil) # rubocop:todo Metrics/AbcSize
274
- scheme = manifest ? "plugin" : "repo"
275
- id = +"#{scheme}://#{label}.collection/"
276
- id += "#{manifest.origin}/" if manifest
277
- id += Addressable::URI.escape(
278
- Pathname(full_path).relative_path_from(
279
- manifest ? Pathname(manifest.content) : Pathname(site.source)
280
- ).to_s
281
- ).gsub("#", "%23")
282
- model = Bridgetown::Model::Base.find(id)
283
-
284
- if model.attributes.key?(:locale) && model.locale.to_sym == :multi
273
+ def read_resource(full_path, manifest: nil)
274
+ model_relative_path = relative_model_path_for(full_path, manifest: manifest)
275
+ model = Bridgetown::Model::Base.find(model_id_from_relative_path(model_relative_path,
276
+ manifest: manifest))
277
+
278
+ if model_is_multi_locale?(model, model_relative_path)
285
279
  site.config.available_locales.each do |locale|
286
280
  model.locale = locale
287
- add_model_resource model
281
+ add_resource_from_model model
288
282
  end
289
283
  return
290
284
  end
291
285
 
292
- add_model_resource model
286
+ add_resource_from_model model
293
287
  end
294
288
 
295
- def add_model_resource(model)
296
- resource = model.to_resource.read!
297
- resources << resource if site.config.unpublished || resource.published?
289
+ # @param model [Bridgetown::Model::Base]
290
+ def add_resource_from_model(model)
291
+ model.to_resource.read!.tap do |resource|
292
+ resources << resource if resource.publishable?
293
+ end
298
294
  end
295
+ alias_method :add_model_resource, :add_resource_from_model
299
296
 
300
297
  def sort_resources!
301
298
  if metadata["sort_by"].is_a?(String)
@@ -365,5 +362,25 @@ module Bridgetown
365
362
  self
366
363
  )
367
364
  end
365
+
366
+ def relative_model_path_for(full_path, manifest: nil)
367
+ Pathname(full_path).relative_path_from(
368
+ manifest ? Pathname(manifest.content) : Pathname(site.source)
369
+ ).to_s
370
+ end
371
+
372
+ def model_id_from_relative_path(model_relative_path, manifest: nil)
373
+ scheme = manifest ? "plugin" : "repo"
374
+ id = +"#{scheme}://#{label}.collection/"
375
+ id += "#{manifest.origin}/" if manifest
376
+ id += Addressable::URI.escape(model_relative_path).gsub("#", "%23")
377
+ id
378
+ end
379
+
380
+ def model_is_multi_locale?(model, model_relative_path)
381
+ (model.attributes.key?(:locale) && model.locale.to_sym == :multi) ||
382
+ File.extname(File.basename(model_relative_path, ".*")) == ".multi" ||
383
+ site.frontmatter_defaults.all(model_relative_path, label.to_sym)["locale"].to_s == "multi"
384
+ end
368
385
  end
369
386
  end
@@ -54,7 +54,8 @@ module Bridgetown
54
54
 
55
55
  def add_bridgetown_plugin(gemname, version: nil)
56
56
  version = " -v \"#{version}\"" if version
57
- run "bundle add #{gemname}#{version} -g bridgetown_plugins"
57
+ run "bundle add #{gemname}#{version} -g bridgetown_plugins",
58
+ env: { "BUNDLE_GEMFILE" => File.join(destination_root, "Gemfile") }
58
59
  rescue SystemExit
59
60
  say_status :run, "Gem not added due to bundler error", :red
60
61
  end
@@ -79,7 +80,7 @@ module Bridgetown
79
80
 
80
81
  def determine_remote_filename(arg)
81
82
  if arg.end_with?(".rb")
82
- arg.split("/").yield_self do |segments|
83
+ arg.split("/").then do |segments|
83
84
  arg.sub!(%r!/#{segments.last}$!, "")
84
85
  segments.last
85
86
  end
@@ -60,7 +60,7 @@ module Bridgetown
60
60
 
61
61
  def configurations
62
62
  inside self.class.source_root do
63
- return Dir.glob("*.rb").map { |file| file.sub(".rb", "") }
63
+ return Dir.glob("*.rb").map { |file| file.sub(".rb", "") }.sort
64
64
  end
65
65
  end
66
66
 
@@ -11,11 +11,33 @@
11
11
  const path = require("path")
12
12
  const fsLib = require("fs")
13
13
  const fs = fsLib.promises
14
+ const { pathToFileURL, fileURLToPath } = require("url")
14
15
  const glob = require("glob")
15
16
  const postcss = require("postcss")
16
17
  const postCssImport = require("postcss-import")
17
18
  const readCache = require("read-cache")
18
19
 
20
+ // Detect if an NPM package is available
21
+ const moduleAvailable = name => {
22
+ try {
23
+ require.resolve(name)
24
+ return true
25
+ } catch (e) { }
26
+ return false
27
+ }
28
+
29
+ // Generate a Source Map URL (used by the Sass plugin)
30
+ const generateSourceMappingURL = sourceMap => {
31
+ const data = Buffer.from(JSON.stringify(sourceMap), "utf-8").toString("base64")
32
+ return `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${data} */`
33
+ }
34
+
35
+ // Import Sass if available
36
+ let sass
37
+ if (moduleAvailable("sass")) {
38
+ sass = require("sass")
39
+ }
40
+
19
41
  // Glob plugin derived from:
20
42
  // https://github.com/thomaschaaf/esbuild-plugin-import-glob
21
43
  // https://github.com/xiaohui-zhangxh/jsbundling-rails/commit/b15025dcc20f664b2b0eb238915991afdbc7cb58
@@ -61,24 +83,23 @@ const importGlobPlugin = () => ({
61
83
  },
62
84
  })
63
85
 
64
- const postCssPlugin = (options) => ({
86
+ // Plugin for PostCSS
87
+ const postCssPlugin = (options, configuration) => ({
65
88
  name: "postcss",
66
89
  async setup(build) {
67
90
  // Process .css files with PostCSS
68
- build.onLoad({ filter: /\.(css)$/ }, async (args) => {
91
+ build.onLoad({ filter: (configuration.filter || /\.css$/) }, async (args) => {
69
92
  const additionalFilePaths = []
70
93
  const css = await fs.readFile(args.path, "utf8")
71
94
 
72
95
  // Configure import plugin so PostCSS can properly resolve `@import`ed CSS files
73
96
  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
- },
97
+ filter: itemPath => !itemPath.startsWith("/"), // ensure it doesn't try to import source-relative paths
79
98
  load: async filename => {
80
99
  let contents = await readCache(filename, "utf-8")
81
100
  const filedir = path.dirname(filename)
101
+ // We'll want to track any imports later when in watch mode:
102
+ additionalFilePaths.push(filename)
82
103
 
83
104
  // We need to transform `url(...)` in imported CSS so the filepaths are properly
84
105
  // relative to the entrypoint. Seems icky to have to hack this! C'est la vie...
@@ -106,6 +127,65 @@ const postCssPlugin = (options) => ({
106
127
  },
107
128
  })
108
129
 
130
+ // Plugin for Sass
131
+ const sassPlugin = (options) => ({
132
+ name: "sass",
133
+ async setup(build) {
134
+ // Process .scss and .sass files with Sass
135
+ build.onLoad({ filter: /\.(sass|scss)$/ }, async (args) => {
136
+ if (!sass) {
137
+ console.error("error: Sass is not installed. Try running `yarn add sass` and then building again.")
138
+ return
139
+ }
140
+
141
+ const modulesFolder = pathToFileURL("node_modules/")
142
+
143
+ const localOptions = {
144
+ importers: [{
145
+ // An importer that redirects relative URLs starting with "~" to
146
+ // `node_modules`.
147
+ findFileUrl(url) {
148
+ if (!url.startsWith('~')) return null
149
+ return new URL(url.substring(1), modulesFolder)
150
+ }
151
+ }],
152
+ sourceMap: true,
153
+ ...options
154
+ }
155
+ const result = sass.compile(args.path, localOptions)
156
+
157
+ const watchPaths = result.loadedUrls
158
+ .filter((x) => x.protocol === "file:" && !x.pathname.startsWith(modulesFolder.pathname))
159
+ .map((x) => x.pathname)
160
+
161
+ let cssOutput = result.css.toString()
162
+
163
+ if (result.sourceMap) {
164
+ const basedir = process.cwd()
165
+ const sourceMap = result.sourceMap
166
+
167
+ const promises = sourceMap.sources.map(async source => {
168
+ const sourceFile = await fs.readFile(fileURLToPath(source), "utf8")
169
+ return sourceFile
170
+ })
171
+ sourceMap.sourcesContent = await Promise.all(promises)
172
+
173
+ sourceMap.sources = sourceMap.sources.map(source => {
174
+ return path.relative(basedir, fileURLToPath(source))
175
+ })
176
+
177
+ cssOutput += '\n' + generateSourceMappingURL(sourceMap)
178
+ }
179
+
180
+ return {
181
+ contents: cssOutput,
182
+ loader: "css",
183
+ watchFiles: [args.path, ...watchPaths],
184
+ }
185
+ })
186
+ },
187
+ })
188
+
109
189
  // Set up defaults and generate frontend bundling manifest file
110
190
  const bridgetownPreset = (outputFolder) => ({
111
191
  name: "bridgetownPreset",
@@ -151,9 +231,9 @@ const bridgetownPreset = (outputFolder) => ({
151
231
  // We have an entrypoint!
152
232
  manifest[stripPrefix(value.entryPoint)] = outputPath
153
233
  entrypoints.push([outputPath, fileSize(key)])
154
- } else if (key.match(/index(\.js)?\.[^-.]*\.css/) && inputs.find(item => item.endsWith("index.css"))) {
234
+ } else if (key.match(/index(\.js)?\.[^-.]*\.css/) && inputs.find(item => item.match(/\.(s?css|sass)$/))) {
155
235
  // Special treatment for index.css
156
- manifest[stripPrefix(inputs.find(item => item.endsWith("index.css")))] = outputPath
236
+ manifest[stripPrefix(inputs.find(item => item.match(/\.(s?css|sass)$/)))] = outputPath
157
237
  entrypoints.push([outputPath, fileSize(key)])
158
238
  } else if (inputs.length > 0) {
159
239
  // Naive implementation, we'll just grab the first input and hope it's accurate
@@ -182,9 +262,12 @@ const postCssConfig = postcssrc.sync()
182
262
  module.exports = (outputFolder, esbuildOptions) => {
183
263
  esbuildOptions.plugins = esbuildOptions.plugins || []
184
264
  // Add the PostCSS & glob plugins to the top of the plugin stack
185
- esbuildOptions.plugins.unshift(postCssPlugin(postCssConfig))
265
+ esbuildOptions.plugins.unshift(postCssPlugin(postCssConfig, esbuildOptions.postCssPluginConfig || {}))
266
+ if (esbuildOptions.postCssPluginConfig) delete esbuildOptions.postCssPluginConfig
186
267
  esbuildOptions.plugins.unshift(importGlobPlugin())
187
- // Add the Bridgetown preset to the bottom of the plugin stack
268
+ // Add the Sass plugin
269
+ esbuildOptions.plugins.push(sassPlugin(esbuildOptions.sassOptions || {}))
270
+ // Add the Bridgetown preset
188
271
  esbuildOptions.plugins.push(bridgetownPreset(outputFolder))
189
272
 
190
273
  // esbuild, take it away!
@@ -200,7 +283,7 @@ module.exports = (outputFolder, esbuildOptions) => {
200
283
  ".ttf": "file",
201
284
  ".eot": "file",
202
285
  },
203
- resolveExtensions: [".tsx",".ts",".jsx",".js",".css",".json",".js.rb"],
286
+ resolveExtensions: [".tsx", ".ts", ".jsx", ".js", ".css", ".scss", ".sass", ".json", ".js.rb"],
204
287
  nodePaths: ["frontend/javascript", "frontend/styles"],
205
288
  watch: process.argv.includes("--watch"),
206
289
  minify: process.argv.includes("--minify"),
@@ -43,7 +43,7 @@ module Bridgetown
43
43
  desc: "Skip 'yarn install'"
44
44
  class_option :"use-sass",
45
45
  type: :boolean,
46
- desc: "(Webpack only) Create a Sass configuration instead of using PostCSS"
46
+ desc: "Set up a Sass configuration for your stylesheet"
47
47
 
48
48
  DOCSURL = "https://bridgetownrb.com/docs"
49
49
 
@@ -62,11 +62,6 @@ module Bridgetown
62
62
  def new_site
63
63
  raise ArgumentError, "You must specify a path." if args.empty?
64
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
-
70
65
  new_site_path = File.expand_path(args.join(" "), Dir.pwd)
71
66
  @site_name = new_site_path.split(File::SEPARATOR).last
72
67
 
@@ -98,7 +93,11 @@ module Bridgetown
98
93
  end
99
94
 
100
95
  def postcss_option
101
- !(frontend_bundling_option == "webpack" && options["use-sass"])
96
+ !options["use-sass"]
97
+ end
98
+
99
+ def disable_postcss?
100
+ options["use-sass"] && options["frontend-bundling"] == "webpack"
102
101
  end
103
102
 
104
103
  def create_site(new_site_path)
@@ -116,6 +115,7 @@ module Bridgetown
116
115
  template("frontend/javascript/index.js.erb", "frontend/javascript/index.js")
117
116
  template("src/index.md.erb", "src/index.md")
118
117
  template("src/posts.md.erb", "src/posts.md")
118
+ copy_file("frontend/styles/syntax-highlighting.css")
119
119
 
120
120
  case options["templates"]
121
121
  when "erb"
@@ -126,11 +126,11 @@ module Bridgetown
126
126
  setup_liquid_templates
127
127
  end
128
128
 
129
+ postcss_option ? configure_postcss : configure_sass
130
+
129
131
  if frontend_bundling_option == "esbuild"
130
- configure_postcss
131
132
  invoke(Esbuild, ["setup"], {})
132
133
  else
133
- postcss_option ? configure_postcss : configure_sass
134
134
  invoke(Webpack, ["setup"], {})
135
135
  end
136
136
  end
@@ -165,6 +165,7 @@ module Bridgetown
165
165
  end
166
166
 
167
167
  def configure_sass
168
+ template("postcss.config.js.erb", "postcss.config.js") unless disable_postcss?
168
169
  copy_file("frontend/styles/index.css", "frontend/styles/index.scss")
169
170
  end
170
171
 
@@ -120,6 +120,7 @@ module Bridgetown
120
120
  " return to your site root.")
121
121
  puts
122
122
 
123
+ # rubocop: disable Style/RedundantCondition
123
124
  Dir.chdir dir do
124
125
  ENV["BRIDGETOWN_SITE"] = site.root_dir
125
126
  if ENV["SHELL"]
@@ -128,6 +129,7 @@ module Bridgetown
128
129
  system("/bin/sh")
129
130
  end
130
131
  end
132
+ # rubocop: enable Style/RedundantCondition
131
133
 
132
134
  puts
133
135
  Bridgetown.logger.info("Done!", "You're back in #{Dir.pwd.green}")
@@ -70,6 +70,9 @@ module Bridgetown
70
70
  end
71
71
 
72
72
  cli = Puma::CLI.new puma_args
73
+ cli.launcher.events.on_stopped do
74
+ Bridgetown::Hooks.trigger :site, :server_shutdown
75
+ end
73
76
  cli.run
74
77
  end
75
78
 
@@ -7,11 +7,11 @@ say "🎉 Webpack configuration updated successfully!"
7
7
 
8
8
  return if Bridgetown.environment.test?
9
9
 
10
- required_packages = %w(esbuild esbuild-loader webpack@5.39.1 webpack-cli@4.7.2 webpack-manifest-plugin@3.1.1)
10
+ required_packages = %w(esbuild esbuild-loader css-loader@6.7.1 webpack@5.72.0 webpack-cli@4.9.2 webpack-manifest-plugin@5.0.0)
11
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
12
 
13
13
  say "Installing required packages"
14
- run "yarn add -D #{required_packages.join(" ")}"
14
+ run "yarn add -D --tilde #{required_packages.join(" ")}"
15
15
 
16
16
  packages_to_remove = package_json["devDependencies"].slice(*redundant_packages).keys
17
17
  unless packages_to_remove.empty?
@@ -41,7 +41,9 @@ const cssRules = {
41
41
  {
42
42
  loader: "css-loader",
43
43
  options: {
44
- url: url => !url.startsWith('/'),
44
+ url: {
45
+ filter: url => !url.startsWith('/')
46
+ },
45
47
  importLoaders: 1
46
48
  }
47
49
  }
@@ -49,7 +51,14 @@ const cssRules = {
49
51
  mode: '<%= self.config.uses_postcss? ? "postcss" : "sass" %>',
50
52
 
51
53
  postcss: () => {
52
- cssRules.use.push("postcss-loader")
54
+ cssRules.use.push({
55
+ loader: "postcss-loader",
56
+ options: {
57
+ postcssOptions: {
58
+ config: "postcss.config.js"
59
+ }
60
+ }
61
+ })
53
62
  return { test: cssRules.test, use: cssRules.use }
54
63
  },
55
64
 
@@ -4,7 +4,7 @@ module Bridgetown
4
4
  class Component
5
5
  extend Forwardable
6
6
 
7
- def_delegators :@view_context, :helpers, :liquid_render, :partial
7
+ def_delegators :@view_context, :liquid_render, :partial
8
8
 
9
9
  # @return [Bridgetown::Site]
10
10
  attr_reader :site # will be nil unless you explicitly set a `@site` ivar
@@ -32,14 +32,12 @@ module Bridgetown
32
32
  def renderer_for_ext(ext, &block)
33
33
  @_tmpl ||= case ext.to_s
34
34
  when "erb"
35
- include ERBCapture
36
35
  Tilt::ErubiTemplate.new(component_template_path,
37
36
  outvar: "@_erbout",
38
37
  bufval: "Bridgetown::OutputBuffer.new",
39
38
  engine_class: Bridgetown::ERBEngine,
40
39
  &block)
41
- when "serb" # requires serbea
42
- include Serbea::Helpers
40
+ when "serb"
43
41
  Tilt::SerbeaTemplate.new(component_template_path, &block)
44
42
  when "slim" # requires bridgetown-slim
45
43
  Slim::Template.new(component_template_path, &block)
@@ -166,12 +164,20 @@ module Bridgetown
166
164
  def _renderer
167
165
  @_renderer ||= begin
168
166
  ext = File.extname(self.class.component_template_path).delete_prefix(".")
169
- self.class.renderer_for_ext(ext) { self.class.component_template_content }
167
+ self.class.renderer_for_ext(ext) { self.class.component_template_content }.tap do |rn|
168
+ self.class.include(rn.is_a?(Tilt::SerbeaTemplate) ? Serbea::Helpers : ERBCapture)
169
+ end
170
170
  end
171
171
  end
172
172
 
173
+ def helpers
174
+ @helpers ||= Bridgetown::RubyTemplateView::Helpers.new(
175
+ self, view_context&.site || Bridgetown::Current.site
176
+ )
177
+ end
178
+
173
179
  def method_missing(method, *args, **kwargs, &block)
174
- if view_context && helpers.respond_to?(method.to_sym)
180
+ if helpers.respond_to?(method.to_sym)
175
181
  helpers.send method.to_sym, *args, **kwargs, &block
176
182
  else
177
183
  super
@@ -179,7 +185,7 @@ module Bridgetown
179
185
  end
180
186
 
181
187
  def respond_to_missing?(method, include_private = false)
182
- (view_context && helpers.respond_to?(method.to_sym, include_private)) || super
188
+ helpers.respond_to?(method.to_sym, include_private) || super
183
189
  end
184
190
  end
185
191
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Localizable
5
+ def all_locales
6
+ result_set = case self
7
+ when Bridgetown::Resource::Base
8
+ collection.resources
9
+ when Bridgetown::GeneratedPage
10
+ site.generated_pages
11
+ else
12
+ []
13
+ end
14
+
15
+ result_set.select { |item| item.data.slug == data.slug }.sort_by do |item|
16
+ site.config.available_locales.index item.data.locale
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Prioritizable
5
+ module ClassMethods
6
+ # @!method priorities
7
+ # @return [Hash<Symbol, Object>]
8
+
9
+ # Get or set the priority of this class. When called without an
10
+ # argument it returns the priority. When an argument is given, it will
11
+ # set the priority.
12
+ #
13
+ # @param priority [Symbol] new priority (optional)
14
+ # Valid options are: `:lowest`, `:low`, `:normal`, `:high`, `:highest`
15
+ # @return [Symbol]
16
+ def priority(priority = nil)
17
+ @priority ||= nil
18
+ @priority = priority if priority && priorities.key?(priority)
19
+ @priority || :normal
20
+ end
21
+
22
+ # Spaceship is priority [higher -> lower]
23
+ #
24
+ # @param other [Class] The class to be compared.
25
+ # @return [Integer] -1, 0, 1.
26
+ def <=>(other)
27
+ priorities[other.priority] <=> priorities[priority]
28
+ end
29
+ end
30
+
31
+ def self.included(klass)
32
+ klass.extend ClassMethods
33
+ klass.class_attribute :priorities, instance_accessor: false
34
+ end
35
+
36
+ # Spaceship is priority [higher -> lower]
37
+ #
38
+ # @param other [object] The object to be compared.
39
+ # @return [Integer] -1, 0, 1.
40
+ def <=>(other)
41
+ self.class <=> other.class
42
+ end
43
+ end
44
+ end
@@ -2,9 +2,19 @@
2
2
 
3
3
  module Bridgetown
4
4
  module Publishable
5
- # Whether the file is published or not, as indicated in YAML front-matter
5
+ # Whether the resource is published or not, as indicated in YAML front-matter
6
6
  def published?
7
7
  !(data.key?("published") && data["published"] == false)
8
8
  end
9
+
10
+ def publishable?
11
+ return true if collection.data?
12
+ return false unless published? || @site.config.unpublished
13
+
14
+ future_allowed = collection.metadata.future || @site.config.future
15
+ this_time = date.is_a?(Date) ? date.to_time.to_i : date.to_i
16
+
17
+ future_allowed || this_time <= @site.time.to_i
18
+ end
9
19
  end
10
20
  end
@@ -38,7 +38,7 @@ class Bridgetown::Site
38
38
  # @param strip_slash_only [Boolean] set to true if you wish "/" to be returned as ""
39
39
  # @return [String]
40
40
  def base_path(strip_slash_only: false)
41
- (config[:base_path] || config[:baseurl]).yield_self do |path|
41
+ (config[:base_path] || config[:baseurl]).then do |path|
42
42
  strip_slash_only ? path.to_s.sub(%r{^/$}, "") : path
43
43
  end
44
44
  end
@@ -61,14 +61,6 @@ class Bridgetown::Site
61
61
  @frontmatter_defaults ||= Bridgetown::FrontmatterDefaults.new(self)
62
62
  end
63
63
 
64
- # Returns the current instance of {Publisher} or creates a new instance of
65
- # {Publisher} if one doesn't exist.
66
- #
67
- # @return [Publisher] Returns an instance of {Publisher}
68
- def publisher
69
- @publisher ||= Bridgetown::Publisher.new(self)
70
- end
71
-
72
64
  # Prefix a path or paths with the {#root_dir} directory.
73
65
  #
74
66
  # @see Bridgetown.sanitized_path
@@ -166,7 +158,7 @@ class Bridgetown::Site
166
158
  plugin_components_load_paths = Bridgetown::PluginManager.source_manifests
167
159
  .filter_map(&:components)
168
160
 
169
- local_components_load_paths = config["components_dir"].yield_self do |dir|
161
+ local_components_load_paths = config["components_dir"].then do |dir|
170
162
  dir.is_a?(Array) ? dir : [dir]
171
163
  end
172
164
  local_components_load_paths.map! do |dir|
@@ -7,11 +7,15 @@ class Bridgetown::Site
7
7
  def locale
8
8
  @locale ||= begin
9
9
  locale = ENV.fetch("BRIDGETOWN_LOCALE", config[:default_locale]).to_sym
10
- Dir["#{in_source_dir("_locales")}/*.yml"].each do |locale_path|
10
+ Dir["#{in_source_dir("_locales")}/*.{json,rb,yml}"].each do |locale_path|
11
11
  I18n.load_path << locale_path
12
12
  end
13
13
  I18n.available_locales = config[:available_locales]
14
14
  I18n.default_locale = locale
15
+ I18n.fallbacks = (config[:available_locales] + [:en]).uniq.to_h do |available_locale|
16
+ [available_locale, [available_locale, locale, :en].uniq]
17
+ end
18
+ locale
15
19
  end
16
20
  end
17
21