bridgetown-core 1.0.0.beta1 → 1.0.0

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +20 -16
  3. data/lib/bridgetown-core/concerns/site/configurable.rb +2 -0
  4. data/lib/bridgetown-core/concerns/site/processable.rb +1 -0
  5. data/lib/bridgetown-core/concerns/site/renderable.rb +27 -16
  6. data/lib/bridgetown-core/concerns/transformable.rb +62 -0
  7. data/lib/bridgetown-core/configurations/gh-pages/gh-pages.yml +33 -0
  8. data/lib/bridgetown-core/configurations/gh-pages.rb +16 -0
  9. data/lib/bridgetown-core/configurations/stimulus.rb +3 -2
  10. data/lib/bridgetown-core/configurations/vercel/vercel.json +45 -0
  11. data/lib/bridgetown-core/configurations/vercel/vercel_url.rb +12 -0
  12. data/lib/bridgetown-core/configurations/vercel.rb +4 -0
  13. data/lib/bridgetown-core/converters/erb_templates.rb +5 -7
  14. data/lib/bridgetown-core/converters/serbea_templates.rb +4 -7
  15. data/lib/bridgetown-core/generated_page.rb +81 -17
  16. data/lib/bridgetown-core/rack/roda.rb +0 -2
  17. data/lib/bridgetown-core/rack/routes.rb +20 -4
  18. data/lib/bridgetown-core/resource/base.rb +1 -1
  19. data/lib/bridgetown-core/resource/transformer.rb +21 -85
  20. data/lib/bridgetown-core/ruby_template_view.rb +7 -0
  21. data/lib/bridgetown-core/site.rb +5 -0
  22. data/lib/bridgetown-core/utils/loaders_manager.rb +6 -0
  23. data/lib/bridgetown-core/utils.rb +1 -1
  24. data/lib/bridgetown-core/version.rb +1 -1
  25. data/lib/bridgetown-core.rb +1 -1
  26. data/lib/site_template/Gemfile.erb +1 -1
  27. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.erb +4 -4
  28. data/lib/site_template/TEMPLATES/liquid/_components/navbar.liquid +4 -4
  29. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.serb +4 -4
  30. data/lib/site_template/bridgetown.config.yml +7 -3
  31. metadata +10 -5
  32. data/lib/bridgetown-core/renderer.rb +0 -169
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6953f85017e90090c0078b710b3e447b69366bd9fed38bd5e307ee72ae3181c
4
- data.tar.gz: 863dcdcea016110ae4e05922f7357b866bd2a77998b5da78ffb92819238c59c4
3
+ metadata.gz: fdb62333635d80ceb9561a0cd9be68f0220ea729c8ac4505bb8e4460894075e1
4
+ data.tar.gz: f7377127b4d64846e694d8ba4c032706ed161ea1595cf8dbf3eca3d2b6e4692d
5
5
  SHA512:
6
- metadata.gz: eb6a1aa56f1544fcc37c4e204df417b5d7d37fa0e219e6a484872cdf4defee1c165fda09f4f30486d64635ef9ab6cf6db3edc8c63316dd3e61ab37be1394443c
7
- data.tar.gz: 81b03e750b6fe6b25c1fbb2e62350f2c2776bf4902c236c5299f90c653720037e74ae8500bf71d928825efd3d83c651ad1d80523cb1362a1db2100d8f88daef9
6
+ metadata.gz: 051a34337053c1370745d37a7cc3def36e1623193e4c03e0b1006d06280303ad5442c289465185314f916dbcf2aa1b1123990ca196041b03bf3804a03b36f695
7
+ data.tar.gz: d5adcc3f8c7c7938bbc220329c002c7cea281f4e21f8ea2bab685dabaffe48c5acca3998482d1e0ec6d0c7c172751c0c6b34481821f51b5d1ccc687b137e55a5
@@ -5,23 +5,27 @@ const outputFolder = "output"
5
5
 
6
6
  // You can customize this as you wish, perhaps to add new esbuild plugins.
7
7
  //
8
- // Eg:
8
+ // ```
9
+ // const path = require("path")
10
+ // const esbuildCopy = require('esbuild-plugin-copy').default
11
+ // const esbuildOptions = {
12
+ // plugins: [
13
+ // esbuildCopy({
14
+ // assets: {
15
+ // from: [path.resolve(__dirname, 'node_modules/somepackage/files/*')],
16
+ // to: [path.resolve(__dirname, 'output/_bridgetown/somepackage/files')],
17
+ // },
18
+ // verbose: false
19
+ // }),
20
+ // ]
21
+ // }
22
+ // ```
9
23
  //
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
- // ```
24
+ // You can also support custom base_path deployments via changing `publicPath`.
25
+ //
26
+ // ```
27
+ // const esbuildOptions = { publicPath: "/my_subfolder/_bridgetown/static" }
28
+ // ```
25
29
  const esbuildOptions = {}
26
30
 
27
31
  build(outputFolder, esbuildOptions)
@@ -91,6 +91,8 @@ class Bridgetown::Site
91
91
  # {Bridgetown.sanitized_path} method.
92
92
  # @return [Array<String>] Return an array of updated paths if multiple paths given.
93
93
  def in_source_dir(*paths)
94
+ # TODO: this operation is expensive across thousands of iterations. Look for ways
95
+ # to workaround use of this wherever possible...
94
96
  paths.reduce(source) do |base, path|
95
97
  Bridgetown.sanitized_path(base, path.to_s)
96
98
  end
@@ -41,6 +41,7 @@ class Bridgetown::Site
41
41
  @documents = nil
42
42
  @docs_to_write = nil
43
43
  @liquid_renderer.reset
44
+ tmp_cache.clear
44
45
 
45
46
  if soft
46
47
  refresh_layouts_and_data
@@ -10,7 +10,7 @@ class Bridgetown::Site
10
10
  Bridgetown::Hooks.trigger :site, :pre_render, self
11
11
  execute_inline_ruby_for_layouts!
12
12
  render_resources
13
- render_generated_pages
13
+ generated_pages.each(&:transform!)
14
14
  Bridgetown::Hooks.trigger :site, :post_render, self
15
15
  end
16
16
 
@@ -46,6 +46,32 @@ class Bridgetown::Site
46
46
  matches
47
47
  end
48
48
 
49
+ # @return [Array<Bridgetown::Layout>]
50
+ def validated_layouts_for(convertible, layout_name)
51
+ layout = layouts[layout_name]
52
+ warn_on_missing_layout convertible, layout, layout_name
53
+
54
+ layout_list = Set.new([layout])
55
+ while layout
56
+ layout_name = layout.data.layout
57
+ layout = layouts[layout_name]
58
+ warn_on_missing_layout convertible, layout, layout_name
59
+
60
+ layout_list << layout
61
+ end
62
+
63
+ layout_list.to_a.compact
64
+ end
65
+
66
+ def warn_on_missing_layout(convertible, layout, layout_name)
67
+ return unless layout.nil? && layout_name
68
+
69
+ Bridgetown.logger.warn(
70
+ "Build Warning:",
71
+ "Layout '#{layout_name}' requested via #{convertible.relative_path} does not exist."
72
+ )
73
+ end
74
+
49
75
  # Renders all resources
50
76
  # @return [void]
51
77
  def render_resources
@@ -58,14 +84,6 @@ class Bridgetown::Site
58
84
  end
59
85
  end
60
86
 
61
- # Renders all generated pages
62
- # @return [void]
63
- def render_generated_pages
64
- generated_pages.each do |page|
65
- render_page page
66
- end
67
- end
68
-
69
87
  # Renders a content item while ensuring site locale is set if the data is available.
70
88
  # @param item [Document, Page, Bridgetown::Resource::Base] The item to render
71
89
  # @yield Runs the block in between locale setting and resetting
@@ -80,12 +98,5 @@ class Bridgetown::Site
80
98
  yield
81
99
  end
82
100
  end
83
-
84
- # Regenerates a content item using {Renderer}
85
- # @param item [Page] The page to render
86
- # @return [void]
87
- def render_page(page)
88
- Bridgetown::Renderer.new(self, page).run
89
- end
90
101
  end
91
102
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Transformable
5
+ # Transforms an input document by running it through available converters
6
+ # (requires a `converter` method to be present on the including class)
7
+ #
8
+ # @param document [Bridgetown::GeneratedPage, Bridgetown::Resource::Base]
9
+ # @return String
10
+ # @yieldparam converter [Bridgetown::Converter]
11
+ # @yieldparam index [Integer] index of the conversion step
12
+ # @yieldparam output [String]
13
+ def transform_content(document)
14
+ converters.each_with_index.inject(document.content.to_s) do |content, (converter, index)|
15
+ output = if converter.method(:convert).arity == 1
16
+ converter.convert content
17
+ else
18
+ converter.convert content, document
19
+ end
20
+
21
+ yield converter, index, output if block_given?
22
+
23
+ output.html_safe
24
+ rescue StandardError => e
25
+ Bridgetown.logger.error "Conversion error:",
26
+ "#{converter.class} encountered an error while "\
27
+ "converting `#{document.relative_path}'"
28
+ raise e
29
+ end
30
+ end
31
+
32
+ # Transforms an input document by placing it within the specified layout
33
+ #
34
+ # @param layout [Bridgetown::Layout]
35
+ # @param output [String] the output from document content conversions
36
+ # @param document [Bridgetown::GeneratedPage, Bridgetown::Resource::Base]
37
+ # @return String
38
+ # @yieldparam converter [Bridgetown::Converter]
39
+ # @yieldparam layout_output [String]
40
+ def transform_with_layout(layout, output, document)
41
+ layout_converters = site.matched_converters_for_convertible(layout)
42
+ layout_input = layout.content.dup
43
+
44
+ layout_converters.inject(layout_input) do |content, converter|
45
+ next(content) unless [2, -2].include?(converter.method(:convert).arity) # rubocop:disable Performance/CollectionLiteralInLoop
46
+
47
+ layout.current_document = document
48
+ layout.current_document_output = output
49
+ layout_output = converter.convert content, layout
50
+
51
+ yield converter, layout_output if block_given?
52
+
53
+ layout_output
54
+ rescue StandardError => e
55
+ Bridgetown.logger.error "Conversion error:",
56
+ "#{converter.class} encountered an error while "\
57
+ "converting `#{document.relative_path}'"
58
+ raise e
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,33 @@
1
+ name: Deploy to GitHub pages
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+
14
+ - name: Setup Ruby
15
+ uses: ruby/setup-ruby@v1
16
+ with:
17
+ bundler-cache: true
18
+
19
+ - name: Setup Node
20
+ uses: actions/setup-node@v2
21
+ with:
22
+ node-version: "16"
23
+ cache: "yarn"
24
+ - run: yarn install
25
+
26
+ - name: Build
27
+ run: bin/bridgetown deploy
28
+
29
+ - name: Deploy
30
+ uses: peaceiris/actions-gh-pages@v3
31
+ with:
32
+ github_token: ${{ secrets.GITHUB_TOKEN }}
33
+ publish_dir: ./output
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ `bundle lock --add-platform x86_64-linux`
4
+ copy_file in_templates_dir("gh-pages.yml"), ".github/workflows/gh-pages.yml"
5
+
6
+ # rubocop:disable Layout/LineLength
7
+ say "🎉 A GitHub action to deploy your site to GitHub pages has been configured!"
8
+ say ""
9
+
10
+ say "🛠️ After pushing the action, go to your repository settings and configure GitHub Pages to deploy from the branch `gh-pages`."
11
+ say ""
12
+
13
+ say "You'll likely also need to set `base_path` in your `bridgetown.config.yml` to your repository's name. If you do this you'll need to use the `relative_url` helper for all links and assets in your HTML."
14
+ say "If you're using esbuild for frontend assets, edit `esbuild.config.js` to update `publicPath`."
15
+ say ""
16
+ # rubocop:enable Layout/LineLength
@@ -34,9 +34,10 @@ append_to_file(File.join(javascript_dir, "index.js")) do
34
34
 
35
35
  import controllers from "./controllers/**/*.{js,js.rb}"
36
36
  Object.entries(controllers).forEach(([filename, controller]) => {
37
- if (filename.includes("_controller.")) {
37
+ if (filename.includes("_controller.") || filename.includes("-controller.")) {
38
38
  const identifier = filename.replace("./controllers/", "")
39
- .replace(/_controller\..*$/, "")
39
+ .replace(/[_\-]controller\..*$/, "")
40
+ .replace("_", "-")
40
41
  .replace("/", "--")
41
42
 
42
43
  Stimulus.register(identifier, controller.default)
@@ -0,0 +1,45 @@
1
+ {
2
+ "cleanUrls": true,
3
+ "trailingSlash": false,
4
+ "redirects": [],
5
+ "headers": [
6
+ {
7
+ "source": "/(.*)",
8
+ "headers": [
9
+ {
10
+ "key": "X-Content-Type-Options",
11
+ "value": "nosniff"
12
+ },
13
+ {
14
+ "key": "X-Frame-Options",
15
+ "value": "DENY"
16
+ },
17
+ {
18
+ "key": "X-XSS-Protection",
19
+ "value": "1; mode=block"
20
+ },
21
+ {
22
+ "key": "Referrer-Policy",
23
+ "value": "strict-origin"
24
+ },
25
+ {
26
+ "key": "Permissions-Policy",
27
+ "value": "geolocation=(self), microphone=()"
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ "source": "/feed.xml",
33
+ "headers": [
34
+ {
35
+ "key": "Content-Type",
36
+ "value": "application/rss+xml"
37
+ },
38
+ {
39
+ "key": "Cache-Control",
40
+ "value": "public, max-age=3600"
41
+ }
42
+ ]
43
+ }
44
+ ]
45
+ }
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Builders::VercelUrl < SiteBuilder
4
+ def build
5
+ hook :site, :pre_render do |site|
6
+ next unless ENV["VERCEL_URL"] && ENV["VERCEL_ENV"] != "production"
7
+
8
+ Bridgetown.logger.info("Subbing Vercel URL")
9
+ site.config.update(url: "https://#{ENV["VERCEL_URL"]}")
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ copy_file in_templates_dir("vercel.json"), "vercel.json"
4
+ copy_file in_templates_dir("vercel_url.rb"), "plugins/builders/vercel_url.rb"
@@ -83,16 +83,14 @@ module Bridgetown
83
83
  options.merge!(options[:locals]) if options[:locals]
84
84
  options[:content] = yield if block_given?
85
85
 
86
- partial_segments = partial_name.split("/")
87
- partial_segments.last.sub!(%r!^!, "_")
88
- partial_name = partial_segments.join("/")
89
-
90
- Tilt::ErubiTemplate.new(
91
- site.in_source_dir(site.config[:partials_dir], "#{partial_name}.erb"),
86
+ partial_path = _partial_path(partial_name, "erb")
87
+ tmpl = site.tmp_cache["partial-tmpl:#{partial_path}"] ||= Tilt::ErubiTemplate.new(
88
+ partial_path,
92
89
  outvar: "@_erbout",
93
90
  bufval: "Bridgetown::OutputBuffer.new",
94
91
  engine_class: ERBEngine
95
- ).render(self, options)
92
+ )
93
+ tmpl.render(self, options)
96
94
  end
97
95
  end
98
96
 
@@ -11,13 +11,10 @@ module Bridgetown
11
11
  options.merge!(options[:locals]) if options[:locals]
12
12
  options[:content] = capture(&block) if block
13
13
 
14
- partial_segments = partial_name.split("/")
15
- partial_segments.last.sub!(%r!^!, "_")
16
- partial_name = partial_segments.join("/")
17
-
18
- Tilt::SerbeaTemplate.new(
19
- site.in_source_dir(site.config[:partials_dir], "#{partial_name}.serb")
20
- ).render(self, options)
14
+ partial_path = _partial_path(partial_name, "serb")
15
+ tmpl = site.tmp_cache["partial-tmpl:#{partial_path}"] ||=
16
+ Tilt::SerbeaTemplate.new(partial_path)
17
+ tmpl.render(self, options)
21
18
  end
22
19
  end
23
20
 
@@ -5,6 +5,7 @@ module Bridgetown
5
5
  include LayoutPlaceable
6
6
  include LiquidRenderable
7
7
  include Publishable
8
+ include Transformable
8
9
 
9
10
  attr_writer :dir
10
11
  attr_accessor :site, :paginator, :name, :ext, :basename, :data, :content, :output
@@ -12,7 +13,7 @@ module Bridgetown
12
13
  alias_method :extname, :ext
13
14
 
14
15
  # A set of extensions that are considered HTML or HTML-like so we
15
- # should not alter them, this includes .xhtml through XHTM5.
16
+ # should not alter them
16
17
 
17
18
  HTML_EXTENSIONS = %w(
18
19
  .html
@@ -54,11 +55,11 @@ module Bridgetown
54
55
  output || content || ""
55
56
  end
56
57
 
57
- # Accessor for data properties by Liquid.
58
+ # Accessor for data properties by Liquid
58
59
  #
59
- # property - The String name of the property to retrieve.
60
+ # @param property [String] name of the property to retrieve
60
61
  #
61
- # Returns the String value or nil if the property isn't included.
62
+ # @return [Object]
62
63
  def [](property)
63
64
  data[property]
64
65
  end
@@ -67,7 +68,7 @@ module Bridgetown
67
68
  # upon generation. This is derived from the permalink or, if
68
69
  # permalink is absent, will be '/'
69
70
  #
70
- # Returns the String destination directory.
71
+ # @return [String]
71
72
  def dir
72
73
  if url.end_with?("/")
73
74
  url
@@ -78,6 +79,8 @@ module Bridgetown
78
79
  end
79
80
 
80
81
  # Liquid representation of current page
82
+ #
83
+ # @return [Bridgetown::Drops::GeneratedPageDrop]
81
84
  def to_liquid
82
85
  @liquid_drop ||= Drops::GeneratedPageDrop.new(self)
83
86
  end
@@ -90,7 +93,7 @@ module Bridgetown
90
93
 
91
94
  # The template of the permalink.
92
95
  #
93
- # Returns the template String.
96
+ # @return [String]
94
97
  def template
95
98
  if !html?
96
99
  "/:path/:basename:output_ext"
@@ -103,7 +106,7 @@ module Bridgetown
103
106
 
104
107
  # The generated relative url of this page. e.g. /about.html.
105
108
  #
106
- # Returns the String url.
109
+ # @return [String]
107
110
  def url
108
111
  @url ||= URL.new(
109
112
  template: template,
@@ -123,6 +126,22 @@ module Bridgetown
123
126
  }
124
127
  end
125
128
 
129
+ # Layout associated with this resource
130
+ # This will output a warning if the layout can't be found.
131
+ #
132
+ # @return [Bridgetown::Layout]
133
+ def layout
134
+ return @layout if @layout
135
+ return if no_layout?
136
+
137
+ @layout = site.layouts[data.layout].tap do |layout|
138
+ unless layout
139
+ Bridgetown.logger.warn "Generated Page:", "Layout '#{data.layout}' " \
140
+ "requested via #{relative_path} does not exist."
141
+ end
142
+ end
143
+ end
144
+
126
145
  # Overide this in subclasses for custom initialization behavior
127
146
  def process
128
147
  # no-op by default
@@ -139,21 +158,68 @@ module Bridgetown
139
158
  @relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).delete_prefix("/")
140
159
  end
141
160
 
142
- # FIXME: spinning up a new Renderer object just to get an extension
143
- # seems excessive
144
- #
145
161
  # The output extension of the page.
146
162
  #
147
- # Returns the output extension
163
+ # @return [String]
148
164
  def output_ext
149
- @output_ext ||= Bridgetown::Renderer.new(site, self).output_ext
165
+ @output_ext ||= (permalink_ext || converter_output_ext)
166
+ end
167
+
168
+ def permalink_ext
169
+ page_permalink = permalink
170
+ if page_permalink &&
171
+ !page_permalink.end_with?("/")
172
+ permalink_ext = File.extname(page_permalink)
173
+ permalink_ext unless permalink_ext.empty?
174
+ end
175
+ end
176
+
177
+ def converter_output_ext
178
+ if output_exts.size == 1
179
+ output_exts.last
180
+ else
181
+ output_exts[-2]
182
+ end
183
+ end
184
+
185
+ def output_exts
186
+ @output_exts ||= converters.filter_map do |c|
187
+ c.output_ext(extname)
188
+ end
189
+ end
190
+
191
+ # @return [Array<Bridgetown::Converter>]
192
+ def converters
193
+ @converters ||= site.matched_converters_for_convertible(self)
194
+ end
195
+
196
+ def transform!
197
+ Bridgetown.logger.debug "Transforming:", relative_path
198
+
199
+ trigger_hooks :pre_render
200
+ self.content = transform_content(self)
201
+ place_in_layout? ? place_into_layouts : self.output = content.dup
202
+ trigger_hooks :post_render
203
+
204
+ self
205
+ end
206
+
207
+ def place_into_layouts
208
+ Bridgetown.logger.debug "Placing in Layouts:", relative_path
209
+ rendered_output = content.dup
210
+
211
+ site.validated_layouts_for(self, data.layout).each do |layout|
212
+ rendered_output = transform_with_layout(layout, rendered_output, self)
213
+ end
214
+
215
+ self.output = rendered_output
150
216
  end
151
217
 
152
218
  # Obtain destination path.
153
219
  #
154
- # dest - The String path to the destination dir.
220
+ # @param dest [String] path to the destination dir
155
221
  #
156
- # Returns the destination file path String.
222
+ # @return [String]
157
223
  def destination(dest)
158
224
  path = site.in_dest_dir(dest, URL.unescape_path(url))
159
225
  path = File.join(path, "index") if url.end_with?("/")
@@ -163,9 +229,7 @@ module Bridgetown
163
229
 
164
230
  # Write the generated page file to the destination directory.
165
231
  #
166
- # dest - The String path to the destination dir.
167
- #
168
- # Returns nothing.
232
+ # @param dest [String] path to the destination dir
169
233
  def write(dest)
170
234
  path = destination(dest)
171
235
  FileUtils.mkdir_p(File.dirname(path))
@@ -48,8 +48,6 @@ module Bridgetown
48
48
  Bridgetown::Current.preloaded_configuration ||=
49
49
  self.class.opts[:bridgetown_preloaded_config]
50
50
 
51
- request.public
52
-
53
51
  request.root do
54
52
  output_folder = Bridgetown::Current.preloaded_configuration.destination
55
53
  File.read(File.join(output_folder, "index.html"))
@@ -41,6 +41,24 @@ module Bridgetown
41
41
  end
42
42
 
43
43
  def start!(roda_app)
44
+ if Bridgetown::Current.preloaded_configuration.base_path == "/"
45
+ load_all_routes roda_app
46
+ return
47
+ end
48
+
49
+ # Support custom base_path configurations
50
+ roda_app.request.on(
51
+ Bridgetown::Current.preloaded_configuration.base_path.delete_prefix("/")
52
+ ) do
53
+ load_all_routes roda_app
54
+ end
55
+
56
+ nil
57
+ end
58
+
59
+ def load_all_routes(roda_app)
60
+ roda_app.request.public
61
+
44
62
  if Bridgetown.env.development? &&
45
63
  !Bridgetown::Current.preloaded_configuration.skip_live_reload
46
64
  setup_live_reload roda_app
@@ -50,11 +68,9 @@ module Bridgetown
50
68
  klass.merge roda_app
51
69
  end
52
70
 
53
- if defined?(Bridgetown::Routes::RodaRouter)
54
- Bridgetown::Routes::RodaRouter.start!(roda_app)
55
- end
71
+ return unless defined?(Bridgetown::Routes::RodaRouter)
56
72
 
57
- nil
73
+ Bridgetown::Routes::RodaRouter.start!(roda_app)
58
74
  end
59
75
 
60
76
  def setup_live_reload(app) # rubocop:disable Metrics/AbcSize
@@ -30,7 +30,7 @@ module Bridgetown
30
30
  def initialize(model:)
31
31
  @model = model
32
32
  @site = model.site
33
- @data = front_matter_defaults
33
+ @data = collection.data? ? HashWithDotAccess::Hash.new : front_matter_defaults
34
34
 
35
35
  trigger_hooks :post_init
36
36
  end
@@ -3,6 +3,8 @@
3
3
  module Bridgetown
4
4
  module Resource
5
5
  class Transformer
6
+ include Transformable
7
+
6
8
  # @return [Array<Hash>]
7
9
  attr_reader :conversions
8
10
 
@@ -30,10 +32,18 @@ module Bridgetown
30
32
  permalink_ext || output_ext
31
33
  end
32
34
 
33
- def process!
35
+ def process! # rubocop:disable Metrics/AbcSize
34
36
  Bridgetown.logger.debug "Transforming:", resource.relative_path
35
37
  resource.around_hook :render do
36
- run_conversions
38
+ resource.content = transform_content(resource) do |converter, index, output|
39
+ conversions[index] = {
40
+ type: :content,
41
+ converter: converter,
42
+ output: Bridgetown.env.production? ? nil : output,
43
+ output_ext: conversions[index]&.dig(:output_ext) ||
44
+ converter.output_ext(resource.extname),
45
+ }
46
+ end
37
47
  resource.place_in_layout? ? place_into_layouts : resource.output = resource.content.dup
38
48
  end
39
49
  end
@@ -85,95 +95,21 @@ module Bridgetown
85
95
  .fetch(:output_ext)
86
96
  end
87
97
 
88
- # @return [Array<Bridgetown::Layout>]
89
- def validated_layouts
90
- layout = site.layouts[resource.data.layout]
91
- warn_on_missing_layout layout, resource.data.layout
92
-
93
- layout_list = Set.new([layout])
94
- while layout
95
- layout_name = layout.data.layout
96
- layout = site.layouts[layout_name]
97
- warn_on_missing_layout layout, layout_name
98
-
99
- layout_list << layout
100
- end
101
-
102
- layout_list.to_a.compact
103
- end
104
-
105
- def warn_on_missing_layout(layout, layout_name)
106
- return unless layout.nil? && layout_name
107
-
108
- Bridgetown.logger.warn(
109
- "Build Warning:",
110
- "Layout '#{layout_name}' requested via #{resource.relative_path} does not exist."
111
- )
112
- end
113
-
114
- ### Transformation Actions
115
-
116
- def run_conversions # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
117
- input = resource.content.to_s
118
-
119
- # @param content [String]
120
- # @param converter [Bridgetown::Converter]
121
- resource.content = converters.each_with_index.inject(input) do |content, (converter, index)|
122
- output = if converter.method(:convert).arity == 1
123
- converter.convert content
124
- else
125
- converter.convert content, resource
126
- end
127
- conversions[index] = {
128
- type: :content,
129
- converter: converter,
130
- output: Bridgetown.env.production? ? nil : output,
131
- output_ext: conversions[index]&.dig(:output_ext) ||
132
- converter.output_ext(resource.extname),
133
- }
134
- output.html_safe
135
- rescue StandardError => e
136
- Bridgetown.logger.error "Conversion error:",
137
- "#{converter.class} encountered an error while "\
138
- "converting `#{resource.relative_path}'"
139
- raise e
140
- end
141
- end
142
-
143
98
  def place_into_layouts
144
99
  Bridgetown.logger.debug "Placing in Layouts:", resource.relative_path
145
100
  output = resource.content.dup
146
- validated_layouts.each do |layout|
147
- output = run_layout_conversions layout, output
101
+ site.validated_layouts_for(resource, resource.data.layout).each do |layout|
102
+ output = transform_with_layout(layout, output, resource) do |converter, layout_output|
103
+ conversions << {
104
+ type: :layout,
105
+ layout: layout,
106
+ converter: converter,
107
+ output: Bridgetown.env.production? ? nil : layout_output,
108
+ }
109
+ end
148
110
  end
149
111
  resource.output = output
150
112
  end
151
-
152
- def run_layout_conversions(layout, output)
153
- layout_converters = site.matched_converters_for_convertible(layout)
154
- layout_input = layout.content.dup
155
-
156
- layout_converters.inject(layout_input) do |content, converter|
157
- next(content) unless [2, -2].include?(converter.method(:convert).arity) # rubocop:disable Performance/CollectionLiteralInLoop
158
-
159
- layout.current_document = resource
160
- layout.current_document_output = output
161
- layout_output = converter.convert content, layout
162
-
163
- conversions << {
164
- type: :layout,
165
- layout: layout,
166
- converter: converter,
167
- output: Bridgetown.env.production? ? nil : layout_output,
168
- }
169
- layout_output
170
- rescue StandardError => e
171
- Bridgetown.logger.error "Conversion error:",
172
- "#{converter.class} encountered an error while "\
173
- "converting `#{resource.relative_path}'"
174
- raise e
175
- end
176
- end
177
113
  end
178
114
  end
179
115
  end
@@ -107,5 +107,12 @@ module Bridgetown
107
107
  strict_variables: site.config["liquid"]["strict_variables"],
108
108
  }
109
109
  end
110
+
111
+ def _partial_path(partial_name, ext)
112
+ partial_name = partial_name.split("/").tap { _1.last.prepend("_") }.join("/")
113
+
114
+ # TODO: see if there's a workaround for this to speed up performance
115
+ site.in_source_dir(site.config[:partials_dir], "#{partial_name}.#{ext}")
116
+ end
110
117
  end
111
118
  end
@@ -53,6 +53,7 @@ module Bridgetown
53
53
  @reader = Reader.new(self)
54
54
  @liquid_renderer = LiquidRenderer.new(self)
55
55
 
56
+ Bridgetown::Cache.base_cache["site_tmp"] = {}.with_dot_access
56
57
  ensure_not_in_dest
57
58
 
58
59
  Bridgetown::Current.site = self
@@ -74,6 +75,10 @@ module Bridgetown
74
75
  end
75
76
  end
76
77
 
78
+ def tmp_cache
79
+ Bridgetown::Cache.base_cache["site_tmp"]
80
+ end
81
+
77
82
  def inspect
78
83
  "#<Bridgetown::Site #{metadata.inspect.delete_prefix("{").delete_suffix("}")}>"
79
84
  end
@@ -33,6 +33,12 @@ module Bridgetown
33
33
  return
34
34
  end
35
35
 
36
+ if defined?(ActiveSupport::RubyFeatures) && ActiveSupport::RubyFeatures::CLASS_SUBCLASSES
37
+ ActiveSupport::DescendantsTracker.clear([value.superclass])
38
+ return
39
+ end
40
+
41
+ # TODO: this could probably be refactored to work like the above
36
42
  ActiveSupport::DescendantsTracker.class_variable_get(
37
43
  :@@direct_descendants
38
44
  )[value.superclass]&.reject! { _1 == value }
@@ -457,7 +457,7 @@ module Bridgetown
457
457
  code = <<~JAVASCRIPT
458
458
  let lastmod = 0
459
459
  function startReloadConnection() {
460
- const evtSource = new EventSource("/_bridgetown/live_reload")
460
+ const evtSource = new EventSource("#{site.base_path(strip_slash_only: true)}/_bridgetown/live_reload")
461
461
  evtSource.onmessage = event => {
462
462
  if (event.data == "reloaded!") {
463
463
  location.reload()
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bridgetown
4
- VERSION = "1.0.0.beta1"
4
+ VERSION = "1.0.0"
5
5
  CODE_NAME = "Pearl"
6
6
  end
@@ -92,11 +92,11 @@ module Bridgetown
92
92
  autoload :Publishable, "bridgetown-core/concerns/publishable"
93
93
  autoload :Publisher, "bridgetown-core/publisher"
94
94
  autoload :Reader, "bridgetown-core/reader"
95
- autoload :Renderer, "bridgetown-core/renderer"
96
95
  autoload :RubyTemplateView, "bridgetown-core/ruby_template_view"
97
96
  autoload :LogWriter, "bridgetown-core/log_writer"
98
97
  autoload :Site, "bridgetown-core/site"
99
98
  autoload :StaticFile, "bridgetown-core/static_file"
99
+ autoload :Transformable, "bridgetown-core/concerns/transformable"
100
100
  autoload :URL, "bridgetown-core/url"
101
101
  autoload :Utils, "bridgetown-core/utils"
102
102
  autoload :VERSION, "bridgetown-core/version"
@@ -26,4 +26,4 @@ gem "bridgetown", "~> <%= Bridgetown::VERSION %>"
26
26
 
27
27
  # Puma is a Rack-compatible server used by Bridgetown
28
28
  # (you can optionally limit this to the "development" group)
29
- gem "puma", "~> 5.5"
29
+ gem "puma", "~> 5.6"
@@ -1,11 +1,11 @@
1
1
  <header>
2
- <img src="/images/logo.svg" alt="Logo" />
2
+ <img src="<%= relative_url '/images/logo.svg' %>" alt="Logo" />
3
3
  </header>
4
4
 
5
5
  <nav>
6
6
  <ul>
7
- <li><a href="/">Home</a></li>
8
- <li><a href="/about">About</a></li>
9
- <li><a href="/posts">Posts</a></li>
7
+ <li><a href="<%= relative_url '/' %>">Home</a></li>
8
+ <li><a href="<%= relative_url '/about' %>">About</a></li>
9
+ <li><a href="<%= relative_url '/posts' %>">Posts</a></li>
10
10
  </ul>
11
11
  </nav>
@@ -1,11 +1,11 @@
1
1
  <header>
2
- <img src="/images/logo.svg" alt="Logo" />
2
+ <img src="{{ '/images/logo.svg' | relative_url }}" alt="Logo" />
3
3
  </header>
4
4
 
5
5
  <nav>
6
6
  <ul>
7
- <li><a href="/">Home</a></li>
8
- <li><a href="/about">About</a></li>
9
- <li><a href="/posts">Posts</a></li>
7
+ <li><a href="{{ '/' | relative_url }}">Home</a></li>
8
+ <li><a href="{{ '/about' | relative_url }}">About</a></li>
9
+ <li><a href="{{ '/posts' | relative_url }}">Posts</a></li>
10
10
  </ul>
11
11
  </nav>
@@ -1,11 +1,11 @@
1
1
  <header>
2
- <img src="/images/logo.svg" alt="Logo" />
2
+ <img src="{{ '/images/logo.svg' | relative_url }}" alt="Logo" />
3
3
  </header>
4
4
 
5
5
  <nav>
6
6
  <ul>
7
- <li><a href="/">Home</a></li>
8
- <li><a href="/about">About</a></li>
9
- <li><a href="/posts">Posts</a></li>
7
+ <li><a href="{{ '/' | relative_url }}">Home</a></li>
8
+ <li><a href="{{ '/about' | relative_url }}">About</a></li>
9
+ <li><a href="{{ '/posts' | relative_url }}">Posts</a></li>
10
10
  </ul>
11
11
  </nav>
@@ -19,8 +19,12 @@ url: "" # the base hostname & protocol for your site, e.g. https://example.com
19
19
  permalink: pretty
20
20
 
21
21
  # Other options you might want to investigate:
22
- #
23
- # base_path: "/" # the subpath of your site, e.g. /blog
22
+ #
23
+ # base_path: "/" # the subpath of your site, e.g. /blog. If you set this option,
24
+ # ensure you use the `relative_url` helper for all links and assets in your HTML.
25
+ # If you're using esbuild for frontend assets, edit `esbuild.config.js` to
26
+ # update `publicPath`.
27
+
24
28
  # timezone: America/Los_Angeles
25
29
  # pagination:
26
- # enabled: true
30
+ # enabled: true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bridgetown-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bridgetown Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-13 00:00:00.000000000 Z
11
+ date: 2022-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -418,6 +418,7 @@ files:
418
418
  - lib/bridgetown-core/concerns/site/renderable.rb
419
419
  - lib/bridgetown-core/concerns/site/ssr.rb
420
420
  - lib/bridgetown-core/concerns/site/writable.rb
421
+ - lib/bridgetown-core/concerns/transformable.rb
421
422
  - lib/bridgetown-core/configuration.rb
422
423
  - lib/bridgetown-core/configurations/.keep
423
424
  - lib/bridgetown-core/configurations/bt-postcss.rb
@@ -430,6 +431,8 @@ files:
430
431
  - lib/bridgetown-core/configurations/cypress/cypress_dir/support/commands.js
431
432
  - lib/bridgetown-core/configurations/cypress/cypress_dir/support/index.js
432
433
  - lib/bridgetown-core/configurations/cypress/cypress_tasks
434
+ - lib/bridgetown-core/configurations/gh-pages.rb
435
+ - lib/bridgetown-core/configurations/gh-pages/gh-pages.yml
433
436
  - lib/bridgetown-core/configurations/minitesting.rb
434
437
  - lib/bridgetown-core/configurations/netlify.rb
435
438
  - lib/bridgetown-core/configurations/netlify/netlify.sh
@@ -443,6 +446,9 @@ files:
443
446
  - lib/bridgetown-core/configurations/tailwindcss/postcss.config.js
444
447
  - lib/bridgetown-core/configurations/turbo.rb
445
448
  - lib/bridgetown-core/configurations/turbo/turbo_transitions.js
449
+ - lib/bridgetown-core/configurations/vercel.rb
450
+ - lib/bridgetown-core/configurations/vercel/vercel.json
451
+ - lib/bridgetown-core/configurations/vercel/vercel_url.rb
446
452
  - lib/bridgetown-core/converter.rb
447
453
  - lib/bridgetown-core/converters/erb_templates.rb
448
454
  - lib/bridgetown-core/converters/identity.rb
@@ -505,7 +511,6 @@ files:
505
511
  - lib/bridgetown-core/readers/defaults_reader.rb
506
512
  - lib/bridgetown-core/readers/layout_reader.rb
507
513
  - lib/bridgetown-core/readers/plugin_content_reader.rb
508
- - lib/bridgetown-core/renderer.rb
509
514
  - lib/bridgetown-core/resource/base.rb
510
515
  - lib/bridgetown-core/resource/destination.rb
511
516
  - lib/bridgetown-core/resource/permalink_processor.rb
@@ -602,9 +607,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
602
607
  version: 2.7.0
603
608
  required_rubygems_version: !ruby/object:Gem::Requirement
604
609
  requirements:
605
- - - ">"
610
+ - - ">="
606
611
  - !ruby/object:Gem::Version
607
- version: 1.3.1
612
+ version: '0'
608
613
  requirements: []
609
614
  rubygems_version: 3.1.4
610
615
  signing_key:
@@ -1,169 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bridgetown
4
- # This class handles the output rendering and layout placement of pages and
5
- # documents. For rendering of resources in particular, see Bridgetown::Resource::Transformer
6
- class Renderer
7
- attr_reader :document, :site
8
-
9
- def initialize(site, document)
10
- @site = site
11
- @document = document
12
- end
13
-
14
- # Determine which converters to use based on this document's
15
- # extension.
16
- #
17
- # Returns Array of Converter instances.
18
- def converters
19
- @converters ||= site.converters.select do |converter|
20
- if converter.method(:matches).arity == 1
21
- converter.matches(document.extname)
22
- else
23
- converter.matches(document.extname, document)
24
- end
25
- end.sort
26
- end
27
-
28
- # Determine the extname the outputted file should have
29
- #
30
- # Returns String the output extname including the leading period.
31
- def output_ext
32
- @output_ext ||= (permalink_ext || converter_output_ext)
33
- end
34
-
35
- # Run hooks and render the document
36
- #
37
- # Returns nothing
38
- def run
39
- Bridgetown.logger.debug "Rendering:", document.relative_path
40
-
41
- document.trigger_hooks :pre_render
42
- document.output = render_document
43
- document.trigger_hooks :post_render
44
- end
45
-
46
- # Render the document.
47
- #
48
- # Returns String rendered document output
49
- def render_document
50
- execute_inline_ruby!
51
-
52
- output = document.content
53
- Bridgetown.logger.debug "Rendering Markup:", document.relative_path
54
- output = convert(output.to_s, document)
55
- document.content = output.html_safe
56
-
57
- if document.place_in_layout?
58
- Bridgetown.logger.debug "Rendering Layout:", document.relative_path
59
- output = place_in_layouts(output)
60
- end
61
-
62
- output
63
- end
64
-
65
- def execute_inline_ruby!
66
- return unless site.config.should_execute_inline_ruby?
67
-
68
- Bridgetown::Utils::RubyExec.search_data_for_ruby_code(document)
69
- end
70
-
71
- # Convert the document using the converters which match this renderer's document.
72
- #
73
- # Returns String the converted content.
74
- def convert(content, document)
75
- converters.reduce(content) do |output, converter|
76
- if converter.method(:convert).arity == 1
77
- converter.convert output
78
- else
79
- converter.convert output, document
80
- end
81
- rescue StandardError => e
82
- Bridgetown.logger.error "Conversion error:",
83
- "#{converter.class} encountered an error while "\
84
- "converting `#{document.relative_path}'"
85
- raise e
86
- end
87
- end
88
-
89
- # Render layouts and place document content inside.
90
- #
91
- # Returns String rendered content
92
- def place_in_layouts(content)
93
- output = content.dup
94
- layout = site.layouts[document.data["layout"]]
95
- validate_layout(layout)
96
-
97
- used = Set.new([layout])
98
-
99
- while layout
100
- output = render_layout(output, layout)
101
-
102
- next unless (layout = site.layouts[layout.data["layout"]])
103
- break if used.include?(layout)
104
-
105
- used << layout
106
- end
107
- output
108
- end
109
-
110
- private
111
-
112
- # Checks if the layout specified in the document actually exists
113
- #
114
- # layout - the layout to check
115
- # Returns nothing
116
- def validate_layout(layout)
117
- return unless document.data["layout"].present? &&
118
- layout.nil? &&
119
- !(document.is_a? Bridgetown::Excerpt)
120
-
121
- Bridgetown.logger.warn "Build Warning:", "Layout '#{document.data["layout"]}' requested " \
122
- "in #{document.relative_path} does not exist."
123
- end
124
-
125
- # Render layout content into document.output
126
- #
127
- # Returns String rendered content
128
- def render_layout(output, layout)
129
- layout_converters = site.matched_converters_for_convertible(layout)
130
-
131
- layout_content = layout.content.dup
132
- layout_converters.reduce(layout_content) do |layout_output, converter|
133
- next(layout_output) unless converter.method(:convert).arity == 2
134
-
135
- layout.current_document = document
136
- layout.current_document_output = output
137
- converter.convert layout_output, layout
138
- rescue StandardError => e
139
- Bridgetown.logger.error "Conversion error:",
140
- "#{converter.class} encountered an error while "\
141
- "converting `#{document.relative_path}'"
142
- raise e
143
- end
144
- end
145
-
146
- def permalink_ext
147
- document_permalink = document.permalink
148
- if document_permalink &&
149
- !document_permalink.end_with?("/")
150
- permalink_ext = File.extname(document_permalink)
151
- permalink_ext unless permalink_ext.empty?
152
- end
153
- end
154
-
155
- def converter_output_ext
156
- if output_exts.size == 1
157
- output_exts.last
158
- else
159
- output_exts[-2]
160
- end
161
- end
162
-
163
- def output_exts
164
- @output_exts ||= converters.filter_map do |c|
165
- c.output_ext(document.extname)
166
- end
167
- end
168
- end
169
- end