bridgetown-core 1.0.0.beta1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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