bridgetown-core 1.2.0.beta5 → 1.3.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.
- checksums.yaml +4 -4
- data/bridgetown-core.gemspec +21 -23
- data/lib/bridgetown-core/collection.rb +1 -1
- data/lib/bridgetown-core/commands/new.rb +2 -0
- data/lib/bridgetown-core/commands/plugins.rb +19 -13
- data/lib/bridgetown-core/concerns/front_matter_importer.rb +2 -2
- data/lib/bridgetown-core/configuration/configuration_dsl.rb +6 -2
- data/lib/bridgetown-core/configuration.rb +1 -1
- data/lib/bridgetown-core/configurations/purgecss.rb +1 -1
- data/lib/bridgetown-core/errors.rb +10 -1
- data/lib/bridgetown-core/liquid_renderer/table.rb +3 -1
- data/lib/bridgetown-core/model/repo_origin.rb +2 -2
- data/lib/bridgetown-core/rack/boot.rb +13 -1
- data/lib/bridgetown-core/rack/routes.rb +40 -6
- data/lib/bridgetown-core/readers/layout_reader.rb +2 -2
- data/lib/bridgetown-core/utils/loaders_manager.rb +4 -0
- data/lib/bridgetown-core/utils.rb +18 -0
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/bridgetown-core/watcher.rb +1 -1
- data/lib/bridgetown-core.rb +54 -0
- data/lib/roda/plugins/bridgetown_server.rb +140 -0
- data/lib/site_template/Gemfile.erb +6 -3
- data/lib/site_template/server/roda_app.rb +4 -2
- data/lib/site_template/src/_posts/0000-00-00-welcome-to-bridgetown.md.erb +1 -1
- metadata +8 -39
- data/lib/bridgetown-core/commands/serve/servlet.rb +0 -68
- data/lib/bridgetown-core/commands/serve.rb +0 -253
- data/lib/bridgetown-core/rack/roda.rb +0 -157
- data/lib/roda/plugins/bridgetown_boot.rb +0 -25
@@ -0,0 +1,140 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Roda
|
4
|
+
module RodaPlugins
|
5
|
+
module BridgetownServer
|
6
|
+
SiteContext = Struct.new(:registers) # for use by Liquid-esque URL helpers
|
7
|
+
|
8
|
+
def self.load_dependencies(app) # rubocop:disable Metrics
|
9
|
+
unless Bridgetown::Current.preloaded_configuration
|
10
|
+
raise "You must supply a preloaded configuration before loading the Bridgetown Roda " \
|
11
|
+
"plugin"
|
12
|
+
end
|
13
|
+
|
14
|
+
app.plugin :initializers
|
15
|
+
app.plugin :method_override
|
16
|
+
app.plugin :all_verbs
|
17
|
+
app.plugin :hooks
|
18
|
+
app.plugin :common_logger, Bridgetown::Rack::Logger.new($stdout), method: :info
|
19
|
+
app.plugin :json
|
20
|
+
app.plugin :json_parser
|
21
|
+
app.plugin :indifferent_params
|
22
|
+
app.plugin :cookies
|
23
|
+
app.plugin :streaming
|
24
|
+
app.plugin :public, root: Bridgetown::Current.preloaded_configuration.destination
|
25
|
+
app.plugin :not_found do
|
26
|
+
output_folder = Bridgetown::Current.preloaded_configuration.destination
|
27
|
+
File.read(File.join(output_folder, "404.html"))
|
28
|
+
rescue Errno::ENOENT
|
29
|
+
"404 Not Found"
|
30
|
+
end
|
31
|
+
app.plugin :exception_page
|
32
|
+
app.plugin :error_handler do |e|
|
33
|
+
Bridgetown::Errors.print_build_error(
|
34
|
+
e, logger: Bridgetown::LogAdapter.new(self.class.opts[:common_logger]), server: true
|
35
|
+
)
|
36
|
+
next exception_page(e) if ENV.fetch("RACK_ENV", nil) == "development"
|
37
|
+
|
38
|
+
output_folder = Bridgetown::Current.preloaded_configuration.destination
|
39
|
+
File.read(File.join(output_folder, "500.html"))
|
40
|
+
rescue Errno::ENOENT
|
41
|
+
"500 Internal Server Error"
|
42
|
+
end
|
43
|
+
|
44
|
+
ExceptionPage.class_eval do # rubocop:disable Metrics/BlockLength
|
45
|
+
def self.css
|
46
|
+
<<~CSS
|
47
|
+
html * { padding:0; margin:0; }
|
48
|
+
body * { padding:10px 20px; }
|
49
|
+
body * * { padding:0; }
|
50
|
+
body { font-family: -apple-system, sans-serif; font-size: 90%; }
|
51
|
+
body>div { border-bottom:1px solid #ddd; }
|
52
|
+
code { font-family: ui-monospace, monospace; }
|
53
|
+
h1 { font-weight: bold; margin-block-end: .8em; }
|
54
|
+
h2 { margin-block-end:.8em; }
|
55
|
+
h2 span { font-size:80%; color:#f7f7db; font-weight:normal; }
|
56
|
+
h3 { margin:1em 0 .5em 0; }
|
57
|
+
h4 { margin:0 0 .5em 0; font-weight: normal; }
|
58
|
+
table {
|
59
|
+
border:1px solid #ccc; border-collapse: collapse; background:white; }
|
60
|
+
tbody td, tbody th { vertical-align:top; padding:2px 3px; }
|
61
|
+
thead th {
|
62
|
+
padding:1px 6px 1px 3px; background:#fefefe; text-align:left;
|
63
|
+
font-weight:normal; font-size:11px; border:1px solid #ddd; }
|
64
|
+
tbody th { text-align:right; opacity: 0.7; padding-right:.5em; }
|
65
|
+
table.vars { margin:5px 0 2px 40px; }
|
66
|
+
table.vars td, table.req td { font-family: ui-monospace, monospace; }
|
67
|
+
table td.code { width:100%;}
|
68
|
+
table td.code div { overflow:hidden; }
|
69
|
+
table.source th { color:#666; }
|
70
|
+
table.source td {
|
71
|
+
font-family: ui-monospace, monospace; white-space:pre; border-bottom:1px solid #eee; }
|
72
|
+
ul.traceback { list-style-type:none; }
|
73
|
+
ul.traceback li.frame { margin-bottom:1em; }
|
74
|
+
div.context { margin: 10px 0; }
|
75
|
+
div.context ol {
|
76
|
+
padding-left:30px; margin:0 10px; list-style-position: inside; }
|
77
|
+
div.context ol li {
|
78
|
+
font-family: ui-monospace, monospace; white-space:pre; color:#666; cursor:pointer; }
|
79
|
+
div.context ol.context-line li { color:black; background-color:#f7f7db; }
|
80
|
+
div.context ol.context-line li span { float: right; }
|
81
|
+
div.commands { margin-left: 40px; }
|
82
|
+
div.commands a { color:black; text-decoration:none; }
|
83
|
+
#summary { background: #1D453C; color: white; }
|
84
|
+
#summary h2 { font-weight: normal; color: white; }
|
85
|
+
#summary ul#quicklinks { list-style-type: none; margin-bottom: 2em; }
|
86
|
+
#summary ul#quicklinks li { float: left; padding: 0 1em; }
|
87
|
+
#summary ul#quicklinks>li+li { border-left: 1px #666 solid; }
|
88
|
+
#summary a { color: #f47c3c; }
|
89
|
+
#explanation { background:#eee; }
|
90
|
+
#traceback { background: white; }
|
91
|
+
#requestinfo { background:#f6f6f6; padding-left:120px; }
|
92
|
+
#summary table { border:none; background:transparent; }
|
93
|
+
#requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
|
94
|
+
#requestinfo h3 { margin-bottom:-1em; }
|
95
|
+
.error { background: #ffc; }
|
96
|
+
.specific { color:#cc3300; font-weight:bold; }
|
97
|
+
CSS
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
app.before do
|
102
|
+
if self.class.opts[:bridgetown_site]
|
103
|
+
# The site had previously been initialized via the bridgetown_ssr plugin
|
104
|
+
Bridgetown::Current.sites[self.class.opts[:bridgetown_site].label] =
|
105
|
+
self.class.opts[:bridgetown_site]
|
106
|
+
@context ||= SiteContext.new({ site: self.class.opts[:bridgetown_site] })
|
107
|
+
end
|
108
|
+
Bridgetown::Current.preloaded_configuration ||=
|
109
|
+
self.class.opts[:bridgetown_preloaded_config]
|
110
|
+
|
111
|
+
request.root do
|
112
|
+
output_folder = Bridgetown::Current.preloaded_configuration.destination
|
113
|
+
File.read(File.join(output_folder, "index.html"))
|
114
|
+
rescue StandardError
|
115
|
+
response.status = 500
|
116
|
+
"<p>ERROR: cannot find <code>index.html</code> in the output folder.</p>"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
Roda::RodaRequest.alias_method :_previous_roda_cookies, :cookies
|
122
|
+
|
123
|
+
module RequestMethods
|
124
|
+
# Monkeypatch Roda/Rack's Request object so it returns a hash which allows for
|
125
|
+
# indifferent access
|
126
|
+
def cookies
|
127
|
+
# TODO: maybe replace with a simpler hash that offers an overloaded `[]` method
|
128
|
+
_previous_roda_cookies.with_indifferent_access
|
129
|
+
end
|
130
|
+
|
131
|
+
# Starts up the Bridgetown routing system
|
132
|
+
def bridgetown
|
133
|
+
Bridgetown::Rack::Routes.start!(scope)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
register_plugin :bridgetown_server, BridgetownServer
|
139
|
+
end
|
140
|
+
end
|
@@ -24,10 +24,13 @@ gem "bridgetown", "~> <%= Bridgetown::VERSION %>"
|
|
24
24
|
# Uncomment to add file-based dynamic routing to your project:
|
25
25
|
# gem "bridgetown-routes", "~> <%= Bridgetown::VERSION %>"
|
26
26
|
|
27
|
+
# Puma is the Rack-compatible web server used by Bridgetown
|
28
|
+
# (you can optionally limit this to the "development" group)
|
29
|
+
gem "puma", "< 7"
|
30
|
+
|
27
31
|
# Uncomment to use the Inspectors API to manipulate the output
|
28
32
|
# of your HTML or XML resources:
|
29
33
|
# gem "nokogiri", "~> 1.13"
|
30
34
|
|
31
|
-
#
|
32
|
-
#
|
33
|
-
gem "puma", "~> 5.6"
|
35
|
+
# Or for faster parsing of HTML-only resources via Inspectors, use Nokolexbor:
|
36
|
+
# gem "nokolexbor", "~> 0.4"
|
@@ -2,9 +2,11 @@
|
|
2
2
|
# on the concept of a routing tree. Bridgetown uses it for its development
|
3
3
|
# server, but you can also run it in production for fast, dynamic applications.
|
4
4
|
#
|
5
|
-
# Learn more at:
|
5
|
+
# Learn more at: https://www.bridgetownrb.com/docs/routes
|
6
|
+
|
7
|
+
class RodaApp < Roda
|
8
|
+
plugin :bridgetown_server
|
6
9
|
|
7
|
-
class RodaApp < Bridgetown::Rack::Roda
|
8
10
|
# Some Roda configuration is handled in the `config/initializers.rb` file.
|
9
11
|
# But you can also add additional Roda configuration here if needed.
|
10
12
|
|
@@ -5,7 +5,7 @@ date: <%= Time.now.strftime('%Y-%m-%d %H:%M:%S %z') %>
|
|
5
5
|
categories: updates
|
6
6
|
---
|
7
7
|
|
8
|
-
You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `bridgetown
|
8
|
+
You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `bin/bridgetown start`, which launches a web server and auto-regenerates your site when a file is updated.
|
9
9
|
|
10
10
|
Bridgetown requires blog post files to be named according to the following format:
|
11
11
|
|
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.
|
4
|
+
version: 1.3.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bridgetown Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01
|
11
|
+
date: 2023-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -112,28 +112,28 @@ dependencies:
|
|
112
112
|
requirements:
|
113
113
|
- - "~>"
|
114
114
|
- !ruby/object:Gem::Version
|
115
|
-
version: '
|
115
|
+
version: '2.0'
|
116
116
|
type: :runtime
|
117
117
|
prerelease: false
|
118
118
|
version_requirements: !ruby/object:Gem::Requirement
|
119
119
|
requirements:
|
120
120
|
- - "~>"
|
121
121
|
- !ruby/object:Gem::Version
|
122
|
-
version: '
|
122
|
+
version: '2.0'
|
123
123
|
- !ruby/object:Gem::Dependency
|
124
|
-
name:
|
124
|
+
name: faraday-follow_redirects
|
125
125
|
requirement: !ruby/object:Gem::Requirement
|
126
126
|
requirements:
|
127
127
|
- - "~>"
|
128
128
|
- !ruby/object:Gem::Version
|
129
|
-
version: '
|
129
|
+
version: '0.3'
|
130
130
|
type: :runtime
|
131
131
|
prerelease: false
|
132
132
|
version_requirements: !ruby/object:Gem::Requirement
|
133
133
|
requirements:
|
134
134
|
- - "~>"
|
135
135
|
- !ruby/object:Gem::Version
|
136
|
-
version: '
|
136
|
+
version: '0.3'
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
138
|
name: hash_with_dot_access
|
139
139
|
requirement: !ruby/object:Gem::Requirement
|
@@ -274,20 +274,6 @@ dependencies:
|
|
274
274
|
- - "~>"
|
275
275
|
- !ruby/object:Gem::Version
|
276
276
|
version: '1.0'
|
277
|
-
- !ruby/object:Gem::Dependency
|
278
|
-
name: terminal-table
|
279
|
-
requirement: !ruby/object:Gem::Requirement
|
280
|
-
requirements:
|
281
|
-
- - "~>"
|
282
|
-
- !ruby/object:Gem::Version
|
283
|
-
version: '1.8'
|
284
|
-
type: :runtime
|
285
|
-
prerelease: false
|
286
|
-
version_requirements: !ruby/object:Gem::Requirement
|
287
|
-
requirements:
|
288
|
-
- - "~>"
|
289
|
-
- !ruby/object:Gem::Version
|
290
|
-
version: '1.8'
|
291
277
|
- !ruby/object:Gem::Dependency
|
292
278
|
name: thor
|
293
279
|
requirement: !ruby/object:Gem::Requirement
|
@@ -316,20 +302,6 @@ dependencies:
|
|
316
302
|
- - "~>"
|
317
303
|
- !ruby/object:Gem::Version
|
318
304
|
version: '2.0'
|
319
|
-
- !ruby/object:Gem::Dependency
|
320
|
-
name: webrick
|
321
|
-
requirement: !ruby/object:Gem::Requirement
|
322
|
-
requirements:
|
323
|
-
- - "~>"
|
324
|
-
- !ruby/object:Gem::Version
|
325
|
-
version: '1.7'
|
326
|
-
type: :runtime
|
327
|
-
prerelease: false
|
328
|
-
version_requirements: !ruby/object:Gem::Requirement
|
329
|
-
requirements:
|
330
|
-
- - "~>"
|
331
|
-
- !ruby/object:Gem::Version
|
332
|
-
version: '1.7'
|
333
305
|
- !ruby/object:Gem::Dependency
|
334
306
|
name: zeitwerk
|
335
307
|
requirement: !ruby/object:Gem::Requirement
|
@@ -382,8 +354,6 @@ files:
|
|
382
354
|
- lib/bridgetown-core/commands/new.rb
|
383
355
|
- lib/bridgetown-core/commands/plugins.rb
|
384
356
|
- lib/bridgetown-core/commands/registrations.rb
|
385
|
-
- lib/bridgetown-core/commands/serve.rb
|
386
|
-
- lib/bridgetown-core/commands/serve/servlet.rb
|
387
357
|
- lib/bridgetown-core/commands/start.rb
|
388
358
|
- lib/bridgetown-core/commands/webpack.rb
|
389
359
|
- lib/bridgetown-core/commands/webpack/enable-postcss.rb
|
@@ -501,7 +471,6 @@ files:
|
|
501
471
|
- lib/bridgetown-core/plugin_manager.rb
|
502
472
|
- lib/bridgetown-core/rack/boot.rb
|
503
473
|
- lib/bridgetown-core/rack/logger.rb
|
504
|
-
- lib/bridgetown-core/rack/roda.rb
|
505
474
|
- lib/bridgetown-core/rack/routes.rb
|
506
475
|
- lib/bridgetown-core/rack/static_indexes.rb
|
507
476
|
- lib/bridgetown-core/reader.rb
|
@@ -543,7 +512,7 @@ files:
|
|
543
512
|
- lib/bridgetown-core/version.rb
|
544
513
|
- lib/bridgetown-core/watcher.rb
|
545
514
|
- lib/bridgetown-core/yaml_parser.rb
|
546
|
-
- lib/roda/plugins/
|
515
|
+
- lib/roda/plugins/bridgetown_server.rb
|
547
516
|
- lib/roda/plugins/bridgetown_ssr.rb
|
548
517
|
- lib/roda/plugins/initializers.rb
|
549
518
|
- lib/roda/plugins/method_override.rb
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "webrick"
|
4
|
-
|
5
|
-
module Bridgetown
|
6
|
-
module Commands
|
7
|
-
class Serve
|
8
|
-
class Servlet < WEBrick::HTTPServlet::FileHandler
|
9
|
-
DEFAULTS = {
|
10
|
-
"Cache-Control" => "private, max-age=0, proxy-revalidate, " \
|
11
|
-
"no-store, no-cache, must-revalidate",
|
12
|
-
}.freeze
|
13
|
-
|
14
|
-
def initialize(server, root, callbacks)
|
15
|
-
# So we can access them easily.
|
16
|
-
@bridgetown_opts = server.config[:BridgetownOptions]
|
17
|
-
set_defaults
|
18
|
-
super
|
19
|
-
end
|
20
|
-
|
21
|
-
def search_index_file(req, res)
|
22
|
-
super ||
|
23
|
-
search_file(req, res, ".html") ||
|
24
|
-
search_file(req, res, ".xhtml")
|
25
|
-
end
|
26
|
-
|
27
|
-
# Add the ability to tap file.html the same way that Nginx does on our
|
28
|
-
# Docker images (or on GitHub Pages.) The difference is that we might end
|
29
|
-
# up with a different preference on which comes first.
|
30
|
-
|
31
|
-
def search_file(req, res, basename)
|
32
|
-
# /file.* > /file/index.html > /file.html
|
33
|
-
super ||
|
34
|
-
super(req, res, "#{basename}.html") ||
|
35
|
-
super(req, res, "#{basename}.xhtml")
|
36
|
-
end
|
37
|
-
|
38
|
-
# rubocop:disable Naming/MethodName
|
39
|
-
def do_GET(req, res)
|
40
|
-
rtn = super
|
41
|
-
|
42
|
-
validate_and_ensure_charset(req, res)
|
43
|
-
res.header.merge!(@headers)
|
44
|
-
rtn
|
45
|
-
end
|
46
|
-
# rubocop:enable Naming/MethodName
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def validate_and_ensure_charset(_req, res)
|
51
|
-
key = res.header.keys.grep(%r!content-type!i).first
|
52
|
-
typ = res.header[key]
|
53
|
-
|
54
|
-
return if %r!;\s*charset=!.match?(typ)
|
55
|
-
|
56
|
-
res.header[key] = "#{typ}; charset=#{@bridgetown_opts["encoding"]}"
|
57
|
-
end
|
58
|
-
|
59
|
-
def set_defaults
|
60
|
-
hash_ = @bridgetown_opts.fetch("webrick", {}).fetch("headers", {})
|
61
|
-
DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash|
|
62
|
-
hash[key] = val unless hash.key?(key)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,253 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Bridgetown
|
4
|
-
module Commands
|
5
|
-
class Serve < Thor::Group
|
6
|
-
extend BuildOptions
|
7
|
-
extend Summarizable
|
8
|
-
include ConfigurationOverridable
|
9
|
-
|
10
|
-
Registrations.register do
|
11
|
-
register(Serve, "serve", "serve", Serve.summary)
|
12
|
-
end
|
13
|
-
|
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 :detach,
|
17
|
-
aliases: "-B",
|
18
|
-
type: :boolean,
|
19
|
-
desc: "Run the server in the background"
|
20
|
-
class_option :ssl_cert, desc: "X.509 (SSL) certificate."
|
21
|
-
class_option :ssl_key, desc: "X.509 (SSL) Private Key."
|
22
|
-
class_option :show_dir_listing,
|
23
|
-
type: :boolean,
|
24
|
-
desc: "Show a directory listing instead of loading your index file."
|
25
|
-
class_option :skip_initial_build,
|
26
|
-
type: :boolean,
|
27
|
-
desc: "Skips the initial site build which occurs before the server is started."
|
28
|
-
class_option :watch,
|
29
|
-
type: :boolean,
|
30
|
-
aliases: "-w",
|
31
|
-
default: true,
|
32
|
-
desc: "Watch for changes and rebuild"
|
33
|
-
|
34
|
-
def self.banner
|
35
|
-
"bridgetown serve [options]"
|
36
|
-
end
|
37
|
-
summary "DEPRECATED (Serve your site locally using WEBrick)"
|
38
|
-
|
39
|
-
DIRECTORY_INDEX = %w(
|
40
|
-
index.htm
|
41
|
-
index.html
|
42
|
-
index.rhtml
|
43
|
-
index.xht
|
44
|
-
index.xhtml
|
45
|
-
index.cgi
|
46
|
-
index.xml
|
47
|
-
index.json
|
48
|
-
).freeze
|
49
|
-
|
50
|
-
def serve
|
51
|
-
Bridgetown::Deprecator.deprecation_message(
|
52
|
-
"WEBrick (serve) will be removed in favor of Puma (start) in the next Bridgetown release"
|
53
|
-
)
|
54
|
-
|
55
|
-
@mutex = Mutex.new
|
56
|
-
@run_cond = ConditionVariable.new
|
57
|
-
@running = false
|
58
|
-
|
59
|
-
no_watch = options["watch"] == false
|
60
|
-
|
61
|
-
options = Thor::CoreExt::HashWithIndifferentAccess.new(self.options)
|
62
|
-
options["serving"] = true
|
63
|
-
options["watch"] = true unless no_watch
|
64
|
-
|
65
|
-
config = configuration_with_overrides(options, Bridgetown::Current.preloaded_configuration)
|
66
|
-
if Bridgetown.environment == "development"
|
67
|
-
default_url(config).tap do |url|
|
68
|
-
options["url"] = url
|
69
|
-
config.url = url
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
invoke(Build, [], options)
|
74
|
-
start_server
|
75
|
-
end
|
76
|
-
|
77
|
-
protected
|
78
|
-
|
79
|
-
def start_server
|
80
|
-
destination = Bridgetown::Current.preloaded_configuration.destination
|
81
|
-
setup(destination)
|
82
|
-
|
83
|
-
start_up_webrick(destination)
|
84
|
-
end
|
85
|
-
|
86
|
-
def setup(destination)
|
87
|
-
require_relative "serve/servlet"
|
88
|
-
|
89
|
-
FileUtils.mkdir_p(destination)
|
90
|
-
return unless File.exist?(File.join(destination, "404.html"))
|
91
|
-
|
92
|
-
WEBrick::HTTPResponse.class_eval do
|
93
|
-
def create_error_page
|
94
|
-
@header["Content-Type"] = "text/html; charset=UTF-8"
|
95
|
-
@body = File.read(File.join(@config[:DocumentRoot], "404.html"))
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def webrick_opts(opts)
|
101
|
-
opts = {
|
102
|
-
BridgetownOptions: opts,
|
103
|
-
DoNotReverseLookup: true,
|
104
|
-
MimeTypes: mime_types,
|
105
|
-
DocumentRoot: opts["destination"],
|
106
|
-
StartCallback: start_callback(opts["detach"]),
|
107
|
-
StopCallback: stop_callback(opts["detach"]),
|
108
|
-
BindAddress: opts["host"],
|
109
|
-
Port: opts["port"],
|
110
|
-
DirectoryIndex: DIRECTORY_INDEX,
|
111
|
-
}
|
112
|
-
|
113
|
-
opts[:DirectoryIndex] = [] if opts[:BridgetownOptions]["show_dir_listing"]
|
114
|
-
|
115
|
-
enable_ssl(opts)
|
116
|
-
enable_logging(opts)
|
117
|
-
opts
|
118
|
-
end
|
119
|
-
|
120
|
-
def start_up_webrick(destination)
|
121
|
-
opts = Bridgetown::Current.preloaded_configuration
|
122
|
-
@server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") }
|
123
|
-
@server.mount(opts["base_path"].to_s, Servlet, destination, file_handler_opts)
|
124
|
-
|
125
|
-
Bridgetown.logger.info "Server address:", server_address(@server, opts)
|
126
|
-
launch_browser @server, opts if opts["open_url"]
|
127
|
-
boot_or_detach @server, opts
|
128
|
-
end
|
129
|
-
|
130
|
-
def shutdown
|
131
|
-
@server.shutdown if running?
|
132
|
-
end
|
133
|
-
|
134
|
-
def default_url(config)
|
135
|
-
format_url(
|
136
|
-
config["ssl_cert"] && config["ssl_key"],
|
137
|
-
config["host"] == "127.0.0.1" ? "localhost" : config["host"],
|
138
|
-
config["port"]
|
139
|
-
)
|
140
|
-
end
|
141
|
-
|
142
|
-
def format_url(ssl_enabled, address, port, baseurl = nil)
|
143
|
-
format("%<prefix>s://%<address>s:%<port>i%<baseurl>s",
|
144
|
-
prefix: ssl_enabled ? "https" : "http",
|
145
|
-
address: address,
|
146
|
-
port: port,
|
147
|
-
baseurl: baseurl ? "#{baseurl}/" : "")
|
148
|
-
end
|
149
|
-
|
150
|
-
# Recreate NondisclosureName under utf-8 circumstance
|
151
|
-
def file_handler_opts
|
152
|
-
WEBrick::Config::FileHandler.merge(
|
153
|
-
FancyIndexing: true,
|
154
|
-
NondisclosureName: [
|
155
|
-
".ht*", "~*",
|
156
|
-
]
|
157
|
-
)
|
158
|
-
end
|
159
|
-
|
160
|
-
def server_address(server, options = {})
|
161
|
-
format_url(
|
162
|
-
server.config[:SSLEnable],
|
163
|
-
server.config[:BindAddress],
|
164
|
-
server.config[:Port],
|
165
|
-
options["baseurl"]
|
166
|
-
)
|
167
|
-
end
|
168
|
-
|
169
|
-
# Keep in our area with a thread or detach the server as requested
|
170
|
-
# by the user. This method determines what we do based on what you
|
171
|
-
# ask us to do.
|
172
|
-
def boot_or_detach(server, opts)
|
173
|
-
if opts["detach"]
|
174
|
-
pid = Process.fork do
|
175
|
-
server.start
|
176
|
-
end
|
177
|
-
|
178
|
-
Process.detach(pid)
|
179
|
-
Bridgetown.logger.info "Server detached with pid '#{pid}'.", \
|
180
|
-
"Run `pkill -f bridgetown' or `kill -9 #{pid}' " \
|
181
|
-
"to stop the server."
|
182
|
-
else
|
183
|
-
t = Thread.new { server.start }
|
184
|
-
trap("INT") { server.shutdown }
|
185
|
-
t.join
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
# Make the stack verbose if the user requests it.
|
190
|
-
def enable_logging(opts)
|
191
|
-
opts[:AccessLog] = []
|
192
|
-
level = WEBrick::Log.const_get(opts[:BridgetownOptions]["verbose"] ? :DEBUG : :WARN)
|
193
|
-
opts[:Logger] = WEBrick::Log.new($stdout, level)
|
194
|
-
end
|
195
|
-
|
196
|
-
# Add SSL to the stack if the user triggers --enable-ssl and they
|
197
|
-
# provide both types of certificates commonly needed. Raise if they
|
198
|
-
# forget to add one of the certificates.
|
199
|
-
def enable_ssl(opts)
|
200
|
-
cert, key, src =
|
201
|
-
opts[:BridgetownOptions].values_at("ssl_cert", "ssl_key", "source")
|
202
|
-
|
203
|
-
return if cert.nil? && key.nil?
|
204
|
-
raise "Missing --ssl_cert or --ssl_key. Both are required." unless cert && key
|
205
|
-
|
206
|
-
require "openssl"
|
207
|
-
require "webrick/https"
|
208
|
-
|
209
|
-
opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(read_file(src, cert))
|
210
|
-
begin
|
211
|
-
opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(read_file(src, key))
|
212
|
-
rescue StandardError
|
213
|
-
raise unless defined?(OpenSSL::PKey::EC)
|
214
|
-
|
215
|
-
opts[:SSLPrivateKey] = OpenSSL::PKey::EC.new(read_file(src, key))
|
216
|
-
end
|
217
|
-
opts[:SSLEnable] = true
|
218
|
-
end
|
219
|
-
|
220
|
-
def start_callback(detached)
|
221
|
-
return if detached
|
222
|
-
|
223
|
-
proc do
|
224
|
-
@mutex.synchronize do
|
225
|
-
@running = true
|
226
|
-
Bridgetown.logger.info("Server running…", "press ctrl-c to stop.")
|
227
|
-
@run_cond.broadcast
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def stop_callback(detached)
|
233
|
-
return if detached
|
234
|
-
|
235
|
-
proc do
|
236
|
-
@mutex.synchronize do
|
237
|
-
@running = false
|
238
|
-
@run_cond.broadcast
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
def mime_types
|
244
|
-
file = File.expand_path("../mime.types", __dir__)
|
245
|
-
WEBrick::HTTPUtils.load_mime_types(file)
|
246
|
-
end
|
247
|
-
|
248
|
-
def read_file(source_dir, file_path)
|
249
|
-
File.read(Bridgetown.sanitized_path(source_dir, file_path))
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|