bridgetown-core 0.12.0 → 0.15.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +3 -1
  3. data/bin/bridgetown +9 -48
  4. data/bridgetown-core.gemspec +10 -5
  5. data/lib/bridgetown-core.rb +20 -4
  6. data/lib/bridgetown-core/cleaner.rb +1 -0
  7. data/lib/bridgetown-core/commands/apply.rb +73 -0
  8. data/lib/bridgetown-core/commands/base.rb +45 -0
  9. data/lib/bridgetown-core/commands/build.rb +91 -86
  10. data/lib/bridgetown-core/commands/clean.rb +30 -29
  11. data/lib/bridgetown-core/commands/concerns/actions.rb +95 -0
  12. data/lib/bridgetown-core/commands/concerns/build_options.rb +76 -0
  13. data/lib/bridgetown-core/commands/concerns/configuration_overridable.rb +18 -0
  14. data/lib/bridgetown-core/commands/concerns/summarizable.rb +13 -0
  15. data/lib/bridgetown-core/commands/console.rb +46 -38
  16. data/lib/bridgetown-core/commands/doctor.rb +125 -135
  17. data/lib/bridgetown-core/commands/new.rb +120 -158
  18. data/lib/bridgetown-core/commands/plugins.rb +206 -0
  19. data/lib/bridgetown-core/commands/registrations.rb +16 -0
  20. data/lib/bridgetown-core/commands/serve.rb +214 -217
  21. data/lib/bridgetown-core/{convertible.rb → concerns/convertible.rb} +2 -2
  22. data/lib/bridgetown-core/concerns/site/configurable.rb +153 -0
  23. data/lib/bridgetown-core/concerns/site/content.rb +111 -0
  24. data/lib/bridgetown-core/concerns/site/extensible.rb +56 -0
  25. data/lib/bridgetown-core/concerns/site/processable.rb +74 -0
  26. data/lib/bridgetown-core/concerns/site/renderable.rb +50 -0
  27. data/lib/bridgetown-core/concerns/site/writable.rb +31 -0
  28. data/lib/bridgetown-core/configuration.rb +98 -108
  29. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +0 -3
  30. data/lib/bridgetown-core/document.rb +1 -1
  31. data/lib/bridgetown-core/drops/bridgetown_drop.rb +6 -1
  32. data/lib/bridgetown-core/drops/site_drop.rb +1 -2
  33. data/lib/bridgetown-core/external.rb +17 -21
  34. data/lib/bridgetown-core/filters.rb +10 -0
  35. data/lib/bridgetown-core/generators/prototype_generator.rb +3 -1
  36. data/lib/bridgetown-core/hooks.rb +62 -62
  37. data/lib/bridgetown-core/layout.rb +10 -4
  38. data/lib/bridgetown-core/liquid_renderer.rb +2 -0
  39. data/lib/bridgetown-core/liquid_renderer/file_system.rb +5 -1
  40. data/lib/bridgetown-core/page.rb +9 -2
  41. data/lib/bridgetown-core/plugin.rb +2 -0
  42. data/lib/bridgetown-core/plugin_manager.rb +68 -14
  43. data/lib/bridgetown-core/reader.rb +5 -0
  44. data/lib/bridgetown-core/readers/data_reader.rb +15 -2
  45. data/lib/bridgetown-core/readers/layout_reader.rb +9 -2
  46. data/lib/bridgetown-core/readers/plugin_content_reader.rb +48 -0
  47. data/lib/bridgetown-core/renderer.rb +51 -32
  48. data/lib/bridgetown-core/site.rb +20 -449
  49. data/lib/bridgetown-core/static_file.rb +1 -5
  50. data/lib/bridgetown-core/tags/include.rb +12 -0
  51. data/lib/bridgetown-core/tags/render_content.rb +27 -16
  52. data/lib/bridgetown-core/tags/with.rb +15 -0
  53. data/lib/bridgetown-core/utils.rb +2 -27
  54. data/lib/bridgetown-core/utils/ruby_exec.rb +66 -0
  55. data/lib/bridgetown-core/version.rb +2 -2
  56. data/lib/bridgetown-core/watcher.rb +21 -10
  57. data/lib/site_template/Gemfile.erb +19 -0
  58. data/lib/site_template/plugins/{.keep → builders/.keep} +0 -0
  59. data/lib/site_template/plugins/site_builder.rb +4 -0
  60. data/lib/site_template/src/_components/footer.html +3 -0
  61. data/lib/site_template/src/_components/head.html +9 -0
  62. data/lib/site_template/src/{_includes → _components}/navbar.html +1 -0
  63. data/lib/site_template/src/_layouts/default.html +3 -3
  64. data/lib/site_template/src/{_components/.keep → favicon.ico} +0 -0
  65. data/lib/site_template/src/posts.md +15 -0
  66. data/lib/site_template/start.js +1 -1
  67. metadata +107 -19
  68. data/lib/bridgetown-core/command.rb +0 -106
  69. data/lib/bridgetown-core/commands/help.rb +0 -34
  70. data/lib/site_template/src/_includes/footer.html +0 -3
  71. data/lib/site_template/src/_includes/head.html +0 -9
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Commands
5
+ module Registrations
6
+ def self.registrations
7
+ @registrations || []
8
+ end
9
+
10
+ def self.register(&block)
11
+ @registrations ||= []
12
+ @registrations.push(block)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,264 +2,261 @@
2
2
 
3
3
  module Bridgetown
4
4
  module Commands
5
- class Serve < Command
6
- # Similar to the pattern in Utils::ThreadEvent except we are maintaining the
7
- # state of @running instead of just signaling an event. We have to maintain this
8
- # state since Serve is just called via class methods instead of an instance
9
- # being created each time.
10
- @mutex = Mutex.new
11
- @run_cond = ConditionVariable.new
12
- @running = false
5
+ class Serve < Thor::Group
6
+ extend BuildOptions
7
+ extend Summarizable
8
+ include ConfigurationOverridable
13
9
 
14
- class << self
15
- COMMAND_OPTIONS = {
16
- "ssl_cert" => ["--ssl-cert [CERT]", "X.509 (SSL) certificate."],
17
- "host" => ["host", "-H", "--host [HOST]", "Host to bind to"],
18
- "open_url" => ["-o", "--open-url", "Launch your site in a browser"],
19
- "detach" => ["-B", "--detach",
20
- "Run the server in the background",],
21
- "ssl_key" => ["--ssl-key [KEY]", "X.509 (SSL) Private Key."],
22
- "port" => ["-P", "--port [PORT]", "Port to listen on"],
23
- "show_dir_listing" => ["--show-dir-listing",
24
- "Show a directory listing instead of loading" \
25
- " your index file.",],
26
- "skip_initial_build" => ["skip_initial_build", "--skip-initial-build",
27
- "Skips the initial site build which occurs before" \
28
- " the server is started.",],
29
- }.freeze
30
-
31
- DIRECTORY_INDEX = %w(
32
- index.htm
33
- index.html
34
- index.rhtml
35
- index.xht
36
- index.xhtml
37
- index.cgi
38
- index.xml
39
- index.json
40
- ).freeze
41
-
42
- attr_reader :mutex, :run_cond, :running
43
- alias_method :running?, :running
44
-
45
- def init_with_program(prog)
46
- prog.command(:serve) do |cmd|
47
- cmd.description "Serve your site locally"
48
- cmd.syntax "serve [options]"
49
- cmd.alias :server
50
- cmd.alias :s
51
-
52
- add_build_options(cmd)
53
- COMMAND_OPTIONS.each do |key, val|
54
- cmd.option key, *val
55
- end
10
+ Registrations.register do
11
+ register(Serve, "serve", "serve", Serve.summary)
12
+ end
56
13
 
57
- cmd.action do |_, opts|
58
- opts["serving"] = true
59
- opts["watch"] = true unless opts.key?("watch")
14
+ class_option :host, aliases: "-H", desc: "Host to bind to"
15
+ class_option :port, aliases: "-P", desc: "Port to listen on"
16
+ class_option :open_url,
17
+ aliases: "-o",
18
+ type: :boolean,
19
+ desc: "Launch your site in a browser"
20
+ class_option :detach,
21
+ aliases: "-B",
22
+ type: :boolean,
23
+ desc: "Run the server in the background"
24
+ class_option :ssl_cert, desc: "X.509 (SSL) certificate."
25
+ class_option :ssl_key, desc: "X.509 (SSL) Private Key."
26
+ class_option :show_dir_listing,
27
+ type: :boolean,
28
+ desc: "Show a directory listing instead of loading your index file."
29
+ class_option :skip_initial_build,
30
+ type: :boolean,
31
+ desc: "Skips the initial site build which occurs before the server is started."
32
+
33
+ def self.banner
34
+ "bridgetown serve [options]"
35
+ end
36
+ summary "Serve your site locally using WEBrick"
60
37
 
61
- # TODO: this prints the configuration file log message out-of-order
62
- config = configuration_from_options(opts)
63
- config["url"] = default_url(config) if Bridgetown.env == "development"
38
+ class << self
39
+ attr_accessor :loaded_config
40
+ end
64
41
 
65
- process_with_graceful_fail(cmd, config, Build, Serve)
66
- end
67
- end
42
+ DIRECTORY_INDEX = %w(
43
+ index.htm
44
+ index.html
45
+ index.rhtml
46
+ index.xht
47
+ index.xhtml
48
+ index.cgi
49
+ index.xml
50
+ index.json
51
+ ).freeze
52
+
53
+ def serve
54
+ @mutex = Mutex.new
55
+ @run_cond = ConditionVariable.new
56
+ @running = false
57
+
58
+ no_watch = options["watch"] == false
59
+
60
+ options = Thor::CoreExt::HashWithIndifferentAccess.new(self.options)
61
+
62
+ options["serving"] = true
63
+ options["watch"] = true unless no_watch
64
+
65
+ # TODO: this prints the configuration file log message out-of-order
66
+ self.class.loaded_config = configuration_with_overrides(options)
67
+ if Bridgetown.environment == "development"
68
+ self.class.loaded_config["url"] = default_url(self.class.loaded_config)
68
69
  end
69
70
 
70
- #
71
-
72
- def process(opts)
73
- opts = configuration_from_options(opts)
74
- destination = opts["destination"]
75
- setup(destination)
76
-
77
- start_up_webrick(opts, destination)
78
- end
71
+ invoke(Build, [], options)
72
+ start_server
73
+ end
79
74
 
80
- def shutdown
81
- @server.shutdown if running?
82
- end
75
+ protected
83
76
 
84
- private
77
+ def start_server
78
+ config = self.class.loaded_config
79
+ destination = config["destination"]
80
+ setup(destination)
85
81
 
86
- # Do a base pre-setup of WEBRick so that everything is in place
87
- # when we get ready to party, checking for an setting up an error page
88
- # and making sure our destination exists.
82
+ start_up_webrick(config, destination)
83
+ end
89
84
 
90
- def setup(destination)
91
- require_relative "serve/servlet"
85
+ def setup(destination)
86
+ require_relative "serve/servlet"
92
87
 
93
- FileUtils.mkdir_p(destination)
94
- if File.exist?(File.join(destination, "404.html"))
95
- WEBrick::HTTPResponse.class_eval do
96
- def create_error_page
97
- @header["Content-Type"] = "text/html; charset=UTF-8"
98
- @body = IO.read(File.join(@config[:DocumentRoot], "404.html"))
99
- end
88
+ FileUtils.mkdir_p(destination)
89
+ if File.exist?(File.join(destination, "404.html"))
90
+ WEBrick::HTTPResponse.class_eval do
91
+ def create_error_page
92
+ @header["Content-Type"] = "text/html; charset=UTF-8"
93
+ @body = IO.read(File.join(@config[:DocumentRoot], "404.html"))
100
94
  end
101
95
  end
102
96
  end
97
+ end
103
98
 
104
- def webrick_opts(opts)
105
- opts = {
106
- BridgetownOptions: opts,
107
- DoNotReverseLookup: true,
108
- MimeTypes: mime_types,
109
- DocumentRoot: opts["destination"],
110
- StartCallback: start_callback(opts["detach"]),
111
- StopCallback: stop_callback(opts["detach"]),
112
- BindAddress: opts["host"],
113
- Port: opts["port"],
114
- DirectoryIndex: DIRECTORY_INDEX,
115
- }
116
-
117
- opts[:DirectoryIndex] = [] if opts[:BridgetownOptions]["show_dir_listing"]
118
-
119
- enable_ssl(opts)
120
- enable_logging(opts)
121
- opts
122
- end
99
+ def webrick_opts(opts)
100
+ opts = {
101
+ BridgetownOptions: opts,
102
+ DoNotReverseLookup: true,
103
+ MimeTypes: mime_types,
104
+ DocumentRoot: opts["destination"],
105
+ StartCallback: start_callback(opts["detach"]),
106
+ StopCallback: stop_callback(opts["detach"]),
107
+ BindAddress: opts["host"],
108
+ Port: opts["port"],
109
+ DirectoryIndex: DIRECTORY_INDEX,
110
+ }
111
+
112
+ opts[:DirectoryIndex] = [] if opts[:BridgetownOptions]["show_dir_listing"]
113
+
114
+ enable_ssl(opts)
115
+ enable_logging(opts)
116
+ opts
117
+ end
123
118
 
124
- def start_up_webrick(opts, destination)
125
- @server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
126
- @server.mount(opts["baseurl"].to_s, Servlet, destination, file_handler_opts)
119
+ def start_up_webrick(opts, destination)
120
+ @server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
121
+ @server.mount(opts["baseurl"].to_s, Servlet, destination, file_handler_opts)
127
122
 
128
- Bridgetown.logger.info "Server address:", server_address(@server, opts)
129
- launch_browser @server, opts if opts["open_url"]
130
- boot_or_detach @server, opts
131
- end
123
+ Bridgetown.logger.info "Server address:", server_address(@server, opts)
124
+ launch_browser @server, opts if opts["open_url"]
125
+ boot_or_detach @server, opts
126
+ end
132
127
 
133
- # Recreate NondisclosureName under utf-8 circumstance
134
- def file_handler_opts
135
- WEBrick::Config::FileHandler.merge(
136
- FancyIndexing: true,
137
- NondisclosureName: [
138
- ".ht*", "~*",
139
- ]
140
- )
141
- end
128
+ def shutdown
129
+ @server.shutdown if running?
130
+ end
142
131
 
143
- def server_address(server, options = {})
144
- format_url(
145
- server.config[:SSLEnable],
146
- server.config[:BindAddress],
147
- server.config[:Port],
148
- options["baseurl"]
149
- )
150
- end
132
+ def default_url(config)
133
+ format_url(
134
+ config["ssl_cert"] && config["ssl_key"],
135
+ config["host"] == "127.0.0.1" ? "localhost" : config["host"],
136
+ config["port"]
137
+ )
138
+ end
151
139
 
152
- def format_url(ssl_enabled, address, port, baseurl = nil)
153
- format("%<prefix>s://%<address>s:%<port>i%<baseurl>s",
154
- prefix: ssl_enabled ? "https" : "http",
155
- address: address,
156
- port: port,
157
- baseurl: baseurl ? "#{baseurl}/" : "")
158
- end
140
+ def format_url(ssl_enabled, address, port, baseurl = nil)
141
+ format("%<prefix>s://%<address>s:%<port>i%<baseurl>s",
142
+ prefix: ssl_enabled ? "https" : "http",
143
+ address: address,
144
+ port: port,
145
+ baseurl: baseurl ? "#{baseurl}/" : "")
146
+ end
159
147
 
160
- def default_url(opts)
161
- config = configuration_from_options(opts)
162
- format_url(
163
- config["ssl_cert"] && config["ssl_key"],
164
- config["host"] == "127.0.0.1" ? "localhost" : config["host"],
165
- config["port"]
166
- )
167
- end
148
+ # Recreate NondisclosureName under utf-8 circumstance
149
+ def file_handler_opts
150
+ WEBrick::Config::FileHandler.merge(
151
+ FancyIndexing: true,
152
+ NondisclosureName: [
153
+ ".ht*", "~*",
154
+ ]
155
+ )
156
+ end
168
157
 
169
- def launch_browser(server, opts)
170
- address = server_address(server, opts)
171
- return system "start", address if Utils::Platforms.windows?
172
- return system "xdg-open", address if Utils::Platforms.linux?
173
- return system "open", address if Utils::Platforms.osx?
158
+ def server_address(server, options = {})
159
+ format_url(
160
+ server.config[:SSLEnable],
161
+ server.config[:BindAddress],
162
+ server.config[:Port],
163
+ options["baseurl"]
164
+ )
165
+ end
174
166
 
175
- Bridgetown.logger.error "Refusing to launch browser; " \
176
- "Platform launcher unknown."
177
- end
167
+ def launch_browser(server, opts)
168
+ address = server_address(server, opts)
169
+ return system "start", address if Utils::Platforms.windows?
170
+ return system "xdg-open", address if Utils::Platforms.linux?
171
+ return system "open", address if Utils::Platforms.osx?
178
172
 
179
- # Keep in our area with a thread or detach the server as requested
180
- # by the user. This method determines what we do based on what you
181
- # ask us to do.
182
- def boot_or_detach(server, opts)
183
- if opts["detach"]
184
- pid = Process.fork do
185
- server.start
186
- end
173
+ Bridgetown.logger.error "Refusing to launch browser; " \
174
+ "Platform launcher unknown."
175
+ end
187
176
 
188
- Process.detach(pid)
189
- Bridgetown.logger.info "Server detached with pid '#{pid}'.", \
190
- "Run `pkill -f bridgetown' or `kill -9 #{pid}'" \
191
- " to stop the server."
192
- else
193
- t = Thread.new { server.start }
194
- trap("INT") { server.shutdown }
195
- t.join
177
+ # Keep in our area with a thread or detach the server as requested
178
+ # by the user. This method determines what we do based on what you
179
+ # ask us to do.
180
+ def boot_or_detach(server, opts)
181
+ if opts["detach"]
182
+ pid = Process.fork do
183
+ server.start
196
184
  end
197
- end
198
185
 
199
- # Make the stack verbose if the user requests it.
200
- def enable_logging(opts)
201
- opts[:AccessLog] = []
202
- level = WEBrick::Log.const_get(opts[:BridgetownOptions]["verbose"] ? :DEBUG : :WARN)
203
- opts[:Logger] = WEBrick::Log.new($stdout, level)
186
+ Process.detach(pid)
187
+ Bridgetown.logger.info "Server detached with pid '#{pid}'.", \
188
+ "Run `pkill -f bridgetown' or `kill -9 #{pid}'" \
189
+ " to stop the server."
190
+ else
191
+ t = Thread.new { server.start }
192
+ trap("INT") { server.shutdown }
193
+ t.join
204
194
  end
195
+ end
205
196
 
206
- # Add SSL to the stack if the user triggers --enable-ssl and they
207
- # provide both types of certificates commonly needed. Raise if they
208
- # forget to add one of the certificates.
209
- def enable_ssl(opts)
210
- cert, key, src =
211
- opts[:BridgetownOptions].values_at("ssl_cert", "ssl_key", "source")
212
-
213
- return if cert.nil? && key.nil?
214
- raise "Missing --ssl_cert or --ssl_key. Both are required." unless cert && key
215
-
216
- require "openssl"
217
- require "webrick/https"
218
-
219
- opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(read_file(src, cert))
220
- begin
221
- opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(read_file(src, key))
222
- rescue StandardError
223
- if defined?(OpenSSL::PKey::EC)
224
- opts[:SSLPrivateKey] = OpenSSL::PKey::EC.new(read_file(src, key))
225
- else
226
- raise
227
- end
197
+ # Make the stack verbose if the user requests it.
198
+ def enable_logging(opts)
199
+ opts[:AccessLog] = []
200
+ level = WEBrick::Log.const_get(opts[:BridgetownOptions]["verbose"] ? :DEBUG : :WARN)
201
+ opts[:Logger] = WEBrick::Log.new($stdout, level)
202
+ end
203
+
204
+ # Add SSL to the stack if the user triggers --enable-ssl and they
205
+ # provide both types of certificates commonly needed. Raise if they
206
+ # forget to add one of the certificates.
207
+ def enable_ssl(opts)
208
+ cert, key, src =
209
+ opts[:BridgetownOptions].values_at("ssl_cert", "ssl_key", "source")
210
+
211
+ return if cert.nil? && key.nil?
212
+ raise "Missing --ssl_cert or --ssl_key. Both are required." unless cert && key
213
+
214
+ require "openssl"
215
+ require "webrick/https"
216
+
217
+ opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(read_file(src, cert))
218
+ begin
219
+ opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(read_file(src, key))
220
+ rescue StandardError
221
+ if defined?(OpenSSL::PKey::EC)
222
+ opts[:SSLPrivateKey] = OpenSSL::PKey::EC.new(read_file(src, key))
223
+ else
224
+ raise
228
225
  end
229
- opts[:SSLEnable] = true
230
226
  end
227
+ opts[:SSLEnable] = true
228
+ end
231
229
 
232
- def start_callback(detached)
233
- unless detached
234
- proc do
235
- mutex.synchronize do
236
- @running = true
237
- Bridgetown.logger.info("Server running…", "press ctrl-c to stop.")
238
- @run_cond.broadcast
239
- end
230
+ def start_callback(detached)
231
+ unless detached
232
+ proc do
233
+ @mutex.synchronize do
234
+ @running = true
235
+ Bridgetown.logger.info("Server running…", "press ctrl-c to stop.")
236
+ @run_cond.broadcast
240
237
  end
241
238
  end
242
239
  end
240
+ end
243
241
 
244
- def stop_callback(detached)
245
- unless detached
246
- proc do
247
- mutex.synchronize do
248
- @running = false
249
- @run_cond.broadcast
250
- end
242
+ def stop_callback(detached)
243
+ unless detached
244
+ proc do
245
+ @mutex.synchronize do
246
+ @running = false
247
+ @run_cond.broadcast
251
248
  end
252
249
  end
253
250
  end
251
+ end
254
252
 
255
- def mime_types
256
- file = File.expand_path("../mime.types", __dir__)
257
- WEBrick::HTTPUtils.load_mime_types(file)
258
- end
253
+ def mime_types
254
+ file = File.expand_path("../mime.types", __dir__)
255
+ WEBrick::HTTPUtils.load_mime_types(file)
256
+ end
259
257
 
260
- def read_file(source_dir, file_path)
261
- File.read(Bridgetown.sanitized_path(source_dir, file_path))
262
- end
258
+ def read_file(source_dir, file_path)
259
+ File.read(Bridgetown.sanitized_path(source_dir, file_path))
263
260
  end
264
261
  end
265
262
  end