bridgetown-core 1.0.0.alpha10 → 1.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/bin/bridgetown +6 -1
  4. data/bridgetown-core.gemspec +3 -3
  5. data/lib/bridgetown-core/collection.rb +6 -6
  6. data/lib/bridgetown-core/commands/base.rb +18 -18
  7. data/lib/bridgetown-core/commands/build.rb +1 -1
  8. data/lib/bridgetown-core/commands/clean.rb +2 -2
  9. data/lib/bridgetown-core/commands/console.rb +1 -0
  10. data/lib/bridgetown-core/commands/esbuild/esbuild.config.js +27 -0
  11. data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +216 -0
  12. data/lib/bridgetown-core/commands/esbuild/migrate-from-webpack.rb +47 -0
  13. data/lib/bridgetown-core/commands/esbuild/setup.rb +4 -0
  14. data/lib/bridgetown-core/commands/esbuild/update.rb +4 -0
  15. data/lib/bridgetown-core/commands/esbuild.rb +83 -0
  16. data/lib/bridgetown-core/commands/new.rb +80 -10
  17. data/lib/bridgetown-core/commands/webpack/enable-postcss.rb +1 -1
  18. data/lib/bridgetown-core/commands/webpack/update.rb +3 -3
  19. data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +1 -1
  20. data/lib/bridgetown-core/commands/webpack.rb +3 -3
  21. data/lib/bridgetown-core/component.rb +9 -3
  22. data/lib/bridgetown-core/concerns/site/configurable.rb +6 -0
  23. data/lib/bridgetown-core/concerns/site/content.rb +4 -4
  24. data/lib/bridgetown-core/concerns/site/extensible.rb +8 -0
  25. data/lib/bridgetown-core/concerns/site/processable.rb +23 -4
  26. data/lib/bridgetown-core/concerns/site/renderable.rb +27 -16
  27. data/lib/bridgetown-core/concerns/site/ssr.rb +2 -17
  28. data/lib/bridgetown-core/concerns/transformable.rb +62 -0
  29. data/lib/bridgetown-core/configurations/minitesting.rb +1 -1
  30. data/lib/bridgetown-core/configurations/purgecss.rb +2 -1
  31. data/lib/bridgetown-core/configurations/render/render.yaml.erb +3 -0
  32. data/lib/bridgetown-core/configurations/stimulus.rb +41 -12
  33. data/lib/bridgetown-core/configurations/tailwindcss/css_imports.css +5 -0
  34. data/lib/bridgetown-core/configurations/tailwindcss.rb +31 -2
  35. data/lib/bridgetown-core/configurations/turbo/turbo_transitions.js +48 -0
  36. data/lib/bridgetown-core/configurations/turbo.rb +15 -5
  37. data/lib/bridgetown-core/configurations/vercel/vercel.json +45 -0
  38. data/lib/bridgetown-core/configurations/vercel/vercel_url.rb +12 -0
  39. data/lib/bridgetown-core/configurations/vercel.rb +4 -0
  40. data/lib/bridgetown-core/converters/erb_templates.rb +6 -8
  41. data/lib/bridgetown-core/converters/ruby_templates.rb +1 -1
  42. data/lib/bridgetown-core/converters/serbea_templates.rb +5 -8
  43. data/lib/bridgetown-core/drops/drop.rb +1 -1
  44. data/lib/bridgetown-core/drops/resource_drop.rb +28 -5
  45. data/lib/bridgetown-core/errors.rb +21 -0
  46. data/lib/bridgetown-core/generated_page.rb +81 -17
  47. data/lib/bridgetown-core/generators/prototype_generator.rb +3 -3
  48. data/lib/bridgetown-core/helpers.rb +3 -2
  49. data/lib/bridgetown-core/hooks.rb +51 -20
  50. data/lib/bridgetown-core/model/base.rb +24 -1
  51. data/lib/bridgetown-core/model/origin.rb +4 -6
  52. data/lib/bridgetown-core/model/repo_origin.rb +48 -0
  53. data/lib/bridgetown-core/rack/boot.rb +5 -9
  54. data/lib/bridgetown-core/rack/roda.rb +4 -5
  55. data/lib/bridgetown-core/rack/routes.rb +44 -10
  56. data/lib/bridgetown-core/rack/static_indexes.rb +2 -0
  57. data/lib/bridgetown-core/resource/base.rb +3 -1
  58. data/lib/bridgetown-core/resource/transformer.rb +21 -85
  59. data/lib/bridgetown-core/ruby_template_view.rb +11 -0
  60. data/lib/bridgetown-core/site.rb +5 -0
  61. data/lib/bridgetown-core/tags/{webpack_path.rb → asset_path.rb} +7 -9
  62. data/lib/bridgetown-core/tasks/bridgetown_tasks.rake +2 -1
  63. data/lib/bridgetown-core/utils/loaders_manager.rb +6 -0
  64. data/lib/bridgetown-core/utils.rb +88 -30
  65. data/lib/bridgetown-core/version.rb +1 -1
  66. data/lib/bridgetown-core/watcher.rb +74 -70
  67. data/lib/bridgetown-core.rb +2 -1
  68. data/lib/site_template/Gemfile.erb +17 -11
  69. data/lib/site_template/README.md +2 -2
  70. data/lib/site_template/{Rakefile → Rakefile.erb} +15 -0
  71. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.erb +11 -0
  72. data/lib/site_template/TEMPLATES/erb/_components/shared/navbar.rb +5 -0
  73. data/lib/site_template/TEMPLATES/erb/_layouts/default.erb +15 -0
  74. data/lib/site_template/TEMPLATES/erb/_layouts/page.erb +7 -0
  75. data/lib/site_template/TEMPLATES/erb/_layouts/post.erb +7 -0
  76. data/lib/site_template/TEMPLATES/erb/_partials/_footer.erb +3 -0
  77. data/lib/site_template/TEMPLATES/erb/_partials/_head.erb +10 -0
  78. data/lib/site_template/{src → TEMPLATES/liquid}/_components/footer.liquid +0 -0
  79. data/lib/site_template/TEMPLATES/liquid/_components/head.liquid +10 -0
  80. data/lib/site_template/TEMPLATES/liquid/_components/navbar.liquid +11 -0
  81. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/default.liquid +2 -2
  82. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/page.liquid +0 -0
  83. data/lib/site_template/{src → TEMPLATES/liquid}/_layouts/post.liquid +0 -0
  84. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.rb +5 -0
  85. data/lib/site_template/TEMPLATES/serbea/_components/shared/navbar.serb +11 -0
  86. data/lib/site_template/TEMPLATES/serbea/_layouts/default.serb +15 -0
  87. data/lib/site_template/TEMPLATES/serbea/_layouts/page.serb +7 -0
  88. data/lib/site_template/TEMPLATES/serbea/_layouts/post.serb +7 -0
  89. data/lib/site_template/TEMPLATES/serbea/_partials/_footer.serb +3 -0
  90. data/lib/site_template/TEMPLATES/serbea/_partials/_head.serb +10 -0
  91. data/lib/site_template/frontend/javascript/index.js.erb +7 -3
  92. data/lib/site_template/frontend/styles/index.css +71 -6
  93. data/lib/site_template/package.json.erb +24 -9
  94. data/lib/site_template/ruby-version.erb +1 -0
  95. data/lib/site_template/server/roda_app.rb +5 -3
  96. data/lib/site_template/server/routes/hello.rb.sample +1 -1
  97. data/lib/site_template/src/images/logo.svg +91 -0
  98. data/lib/site_template/src/index.md.erb +22 -0
  99. data/lib/site_template/src/posts.md.erb +28 -0
  100. metadata +57 -23
  101. data/lib/bridgetown-core/configurations/swup.rb +0 -37
  102. data/lib/bridgetown-core/renderer.rb +0 -169
  103. data/lib/site_template/frontend/styles/index.scss +0 -17
  104. data/lib/site_template/src/_components/head.liquid +0 -10
  105. data/lib/site_template/src/_components/navbar.liquid +0 -5
  106. data/lib/site_template/src/_layouts/home.liquid +0 -7
  107. data/lib/site_template/src/images/.keep +0 -1
  108. data/lib/site_template/src/index.md +0 -7
  109. data/lib/site_template/src/posts.md +0 -14
@@ -11,15 +11,22 @@ unless File.exist?("postcss.config.js")
11
11
  return
12
12
  end
13
13
 
14
+ say_status :tailwind, "Installing Tailwind CSS..."
15
+
14
16
  confirm = ask "This configuration will ovewrite your existing #{"postcss.config.js".bold.white}. Would you like to continue? [Yn]"
15
17
  return unless confirm.casecmp?("Y")
16
18
 
17
19
  run "yarn add -D tailwindcss"
18
20
  run "npx tailwindcss init"
19
21
 
20
- copy_file in_templates_dir("postcss.config.js"), "postcss.config.js", force: true
22
+ gsub_file "tailwind.config.js", "content: [],", <<~JS.strip
23
+ content: [
24
+ './src/**/*.{html,md,liquid,erb,serb}',
25
+ './frontend/javascript/**/*.js',
26
+ ],
27
+ JS
21
28
 
22
- run "bundle exec bridgetown configure purgecss"
29
+ copy_file in_templates_dir("postcss.config.js"), "postcss.config.js", force: true
23
30
 
24
31
  if File.exist?("frontend/styles/index.css")
25
32
  prepend_to_file "frontend/styles/index.css",
@@ -29,4 +36,26 @@ else
29
36
  say File.read(in_templates_dir("/css_imports.css"))
30
37
  end
31
38
 
39
+ create_file "frontend/styles/jit-refresh.css", "/* #{Time.now.to_i} */"
40
+
41
+ create_builder "tailwind_jit.rb" do
42
+ <<~RUBY
43
+ class Builders::TailwindJit < SiteBuilder
44
+ def build
45
+ hook :site, :pre_reload do |_, paths|
46
+ # Don't trigger refresh if it's a frontend-only change
47
+ next if paths.length == 1 && paths.first.ends_with?("manifest.json")
48
+
49
+ # Save out a comment file to trigger Tailwind's JIT
50
+ refresh_file = site.in_root_dir("frontend", "styles", "jit-refresh.css")
51
+ File.write refresh_file, "/* \#{Time.now.to_i} */"
52
+ throw :halt # don't continue the build, wait for watcher rebuild
53
+ end
54
+ end
55
+ end
56
+ RUBY
57
+ end
58
+
59
+ say_status :tailwind, "Tailwind CSS is now configured."
60
+
32
61
  # rubocop:enable all
@@ -0,0 +1,48 @@
1
+ document.addEventListener("turbo:visit", () => {
2
+ let main = document.querySelector("main");
3
+ if (main.dataset.turboTransition == "false") return;
4
+
5
+ let [movement, scale] = ["15px", "0.99"];
6
+
7
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
8
+ [movement, scale] = ["7px", "1"]
9
+ };
10
+
11
+ main.style.transformOrigin = "50% 0%";
12
+ main.dataset.animatingOut = true;
13
+
14
+ main.animate(
15
+ [
16
+ { opacity: 1, transform: "translateY(0px) scale(1)" },
17
+ { opacity: 0, transform: `translateY(${movement}) scale(${scale})` }
18
+ ],
19
+ { duration: 300, easing: "cubic-bezier(0.45, 0, 0.55, 1)" }
20
+ );
21
+
22
+ Promise.all(main.getAnimations().map(animation => animation.finished)).then(() => {
23
+ if (main.dataset.animatingOut) main.style.visibility = "hidden"
24
+ })
25
+ });
26
+
27
+ document.addEventListener("turbo:load", () => {
28
+ let main = document.querySelector("main");
29
+ if (main.dataset.turboTransition == "false") return;
30
+
31
+ let [movement, scale] = ["-10px", "0.99"];
32
+
33
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
34
+ [movement, scale] = ["-5px", "1"]
35
+ };
36
+
37
+ main.style.visibility = "visible";
38
+ main.style.transformOrigin = "50% 0%";
39
+ delete main.dataset.animatingOut;
40
+
41
+ main.animate(
42
+ [
43
+ { opacity: 0, transform: `translateY(${movement}) scale(${scale})` },
44
+ { opacity: 1, transform: "translateY(0px) scale(1)" }
45
+ ],
46
+ { duration: 150, easing: "cubic-bezier(0.45, 0, 0.55, 1)" }
47
+ )
48
+ })
@@ -1,16 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- say "Installing Turbo...", :green
3
+ say_status :turbo, "Installing Turbo..."
4
4
 
5
5
  run("yarn add @hotwired/turbo")
6
6
 
7
- say 'Adding Turbo to "frontend/javascript/index.js"...', :magenta
7
+ say_status :turbo, 'Adding Turbo to "frontend/javascript/index.js"...', :magenta
8
8
 
9
9
  javascript_import do
10
10
  <<~JS
11
- import Turbo from "@hotwired/turbo"
11
+ import * as Turbo from "@hotwired/turbo"
12
+
13
+ // Uncomment the line below to add transition animations when Turbo navigates.
14
+ // We recommend adding <meta name="turbo-cache-control" content="no-preview" />
15
+ // to your HTML head if you turn on transitions. Use data-turbo-transition="false"
16
+ // on your <main> element for pages where you don't want any transition animation.
17
+ //
18
+ // import "./turbo_transitions.js"
12
19
  JS
13
20
  end
14
21
 
15
- say "Turbo successfully added", :green
16
- say 'For further reading, check out "https://turbo.hotwired.dev/"', :blue
22
+ copy_file in_templates_dir("turbo_transitions.js"), "frontend/javascript/turbo_transitions.js"
23
+
24
+ say_status :turbo, "Turbo successfully added!", :magenta
25
+ say_status :turbo, "Take a look in your index.js file for optional animation setup.", :blue
26
+ say_status :turbo, 'For further reading, check out "https://turbo.hotwired.dev/"', :blue
@@ -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
 
@@ -115,7 +113,7 @@ module Bridgetown
115
113
  erb_view = Bridgetown::ERBView.new(convertible)
116
114
 
117
115
  erb_renderer = Tilt::ErubiTemplate.new(
118
- convertible.relative_path,
116
+ convertible.path,
119
117
  line_start(convertible),
120
118
  outvar: "@_erbout",
121
119
  bufval: "Bridgetown::OutputBuffer.new",
@@ -9,7 +9,7 @@ module Bridgetown
9
9
  def convert(content, convertible)
10
10
  erb_view = Bridgetown::ERBView.new(convertible)
11
11
  erb_view.instance_eval(
12
- content, convertible.relative_path.to_s, line_start(convertible)
12
+ content, convertible.path.to_s, line_start(convertible)
13
13
  ).to_s
14
14
  end
15
15
  end
@@ -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
 
@@ -39,7 +36,7 @@ module Bridgetown
39
36
 
40
37
  serb_view = Bridgetown::SerbeaView.new(convertible)
41
38
 
42
- serb_renderer = Tilt::SerbeaTemplate.new(convertible.relative_path) { content }
39
+ serb_renderer = Tilt::SerbeaTemplate.new(convertible.path) { content }
43
40
 
44
41
  if convertible.is_a?(Bridgetown::Layout)
45
42
  serb_renderer.render(serb_view) do
@@ -110,7 +110,7 @@ module Bridgetown
110
110
  # underlying data hashes and performs a set union to ensure a list
111
111
  # of unique keys for the Drop.
112
112
  #
113
- # Returns an Array of unique keys for content for the Drop.
113
+ # @return [Array<String>]
114
114
  def keys
115
115
  (content_methods |
116
116
  mutations.keys |
@@ -6,7 +6,7 @@ module Bridgetown
6
6
  extend Forwardable
7
7
 
8
8
  NESTED_OBJECT_FIELD_BLACKLIST = %w(
9
- content output excerpt next previous
9
+ content output excerpt next previous next_resource previous_resource
10
10
  ).freeze
11
11
 
12
12
  mutable false
@@ -44,13 +44,15 @@ module Bridgetown
44
44
  cmp
45
45
  end
46
46
 
47
- def previous
48
- @previous ||= @obj.previous_resource.to_liquid
47
+ def next_resource
48
+ @next ||= @obj.next_resource.to_liquid
49
49
  end
50
+ alias_method :next, :next_resource
50
51
 
51
- def next
52
- @next ||= @obj.next_resource.to_liquid
52
+ def previous_resource
53
+ @previous ||= @obj.previous_resource.to_liquid
53
54
  end
55
+ alias_method :previous, :previous_resource
54
56
 
55
57
  # Generate a Hash for use in generating JSON.
56
58
  # This is useful if fields need to be cleared before the JSON can generate.
@@ -79,6 +81,27 @@ module Bridgetown
79
81
  result[key] = doc[key] unless NESTED_OBJECT_FIELD_BLACKLIST.include?(key)
80
82
  end
81
83
  end
84
+
85
+ # Generates a list of keys with user content as their values.
86
+ # This gathers up the Drop methods and keys of the mutations and
87
+ # underlying data hashes and performs a set union to ensure a list
88
+ # of unique keys for the Drop.
89
+ #
90
+ # @return [Array<String>]
91
+ def keys
92
+ keys_to_remove = %w[next_resource previous_resource]
93
+ (content_methods |
94
+ mutations.keys |
95
+ fallback_data.keys).flatten.reject do |key|
96
+ keys_to_remove.include?(key)
97
+ end
98
+ end
99
+
100
+ # Inspect the drop's keys and values through a JSON representation
101
+ # of its keys and values.
102
+ def inspect
103
+ JSON.pretty_generate hash_for_json
104
+ end
82
105
  end
83
106
  end
84
107
  end
@@ -14,5 +14,26 @@ module Bridgetown
14
14
  PostURLError = Class.new(FatalException)
15
15
  InvalidURLError = Class.new(FatalException)
16
16
  InvalidConfigurationError = Class.new(FatalException)
17
+
18
+ def self.print_build_error(exc, trace: false)
19
+ Bridgetown.logger.error "Exception raised:", exc.class.to_s.bold
20
+ Bridgetown.logger.error exc.message.reset_ansi
21
+
22
+ trace_args = ["-t", "--trace"]
23
+ print_trace_msg = true
24
+ traces = if trace || ARGV.find { |arg| trace_args.include?(arg) }
25
+ print_trace_msg = false
26
+ exc.backtrace
27
+ else
28
+ exc.backtrace[0..4]
29
+ end
30
+ traces.each_with_index do |backtrace_line, index|
31
+ Bridgetown.logger.error "#{index + 1}:", backtrace_line.reset_ansi
32
+ end
33
+
34
+ return unless print_trace_msg
35
+
36
+ Bridgetown.logger.warn "Backtrace:", "Use the --trace option for complete information."
37
+ end
17
38
  end
18
39
  end
@@ -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))
@@ -1,21 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Handles Generated Pages
4
- Bridgetown::Hooks.register :generated_pages, :post_init, reloadable: false do |page|
4
+ Bridgetown::Hooks.register_one :generated_pages, :post_init, reloadable: false do |page|
5
5
  if page.class != Bridgetown::PrototypePage && page.data["prototype"].is_a?(Hash)
6
6
  Bridgetown::PrototypeGenerator.add_matching_template(page)
7
7
  end
8
8
  end
9
9
 
10
10
  # Handles Resources
11
- Bridgetown::Hooks.register :resources, :post_read, reloadable: false do |resource|
11
+ Bridgetown::Hooks.register_one :resources, :post_read, reloadable: false do |resource|
12
12
  if resource.data["prototype"].is_a?(Hash)
13
13
  Bridgetown::PrototypeGenerator.add_matching_template(resource)
14
14
  end
15
15
  end
16
16
 
17
17
  # Ensure sites clear out templates before rebuild
18
- Bridgetown::Hooks.register :site, :after_reset, reloadable: false do |_site|
18
+ Bridgetown::Hooks.register_one :site, :after_reset, reloadable: false do |_site|
19
19
  Bridgetown::PrototypeGenerator.matching_templates.clear
20
20
  end
21
21
 
@@ -22,9 +22,10 @@ module Bridgetown
22
22
  @context = Context.new({ site: site })
23
23
  end
24
24
 
25
- def webpack_path(asset_type)
26
- Bridgetown::Utils.parse_webpack_manifest_file(site, asset_type.to_s)
25
+ def asset_path(asset_type)
26
+ Bridgetown::Utils.parse_frontend_manifest_file(site, asset_type.to_s)
27
27
  end
28
+ alias_method :webpack_path, :asset_path
28
29
 
29
30
  def live_reload_dev_js
30
31
  Bridgetown::Utils.live_reload_js(site)