jekyll 4.2.1 → 4.2.2
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/.rubocop.yml +350 -350
- data/LICENSE +21 -21
- data/README.markdown +86 -86
- data/exe/jekyll +57 -57
- data/lib/blank_template/_config.yml +3 -3
- data/lib/blank_template/_layouts/default.html +12 -12
- data/lib/blank_template/_sass/main.scss +9 -9
- data/lib/blank_template/assets/css/main.scss +4 -4
- data/lib/blank_template/index.md +8 -8
- data/lib/jekyll/cache.rb +190 -190
- data/lib/jekyll/cleaner.rb +111 -111
- data/lib/jekyll/collection.rb +309 -309
- data/lib/jekyll/command.rb +105 -105
- data/lib/jekyll/commands/build.rb +93 -93
- data/lib/jekyll/commands/clean.rb +45 -45
- data/lib/jekyll/commands/doctor.rb +177 -177
- data/lib/jekyll/commands/help.rb +34 -34
- data/lib/jekyll/commands/new.rb +172 -169
- data/lib/jekyll/commands/new_theme.rb +40 -40
- data/lib/jekyll/commands/serve/live_reload_reactor.rb +122 -122
- data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
- data/lib/jekyll/commands/serve/servlet.rb +202 -202
- data/lib/jekyll/commands/serve/websockets.rb +81 -81
- data/lib/jekyll/commands/serve.rb +362 -362
- data/lib/jekyll/configuration.rb +313 -313
- data/lib/jekyll/converter.rb +54 -54
- data/lib/jekyll/converters/identity.rb +41 -41
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +199 -199
- data/lib/jekyll/converters/markdown.rb +113 -113
- data/lib/jekyll/converters/smartypants.rb +70 -70
- data/lib/jekyll/convertible.rb +257 -257
- data/lib/jekyll/deprecator.rb +50 -50
- data/lib/jekyll/document.rb +544 -544
- data/lib/jekyll/drops/collection_drop.rb +20 -20
- data/lib/jekyll/drops/document_drop.rb +70 -70
- data/lib/jekyll/drops/drop.rb +293 -293
- data/lib/jekyll/drops/excerpt_drop.rb +19 -19
- data/lib/jekyll/drops/jekyll_drop.rb +32 -32
- data/lib/jekyll/drops/site_drop.rb +66 -66
- data/lib/jekyll/drops/static_file_drop.rb +14 -14
- data/lib/jekyll/drops/unified_payload_drop.rb +26 -26
- data/lib/jekyll/drops/url_drop.rb +140 -140
- data/lib/jekyll/entry_filter.rb +121 -121
- data/lib/jekyll/errors.rb +20 -20
- data/lib/jekyll/excerpt.rb +201 -201
- data/lib/jekyll/external.rb +79 -79
- data/lib/jekyll/filters/date_filters.rb +110 -110
- data/lib/jekyll/filters/grouping_filters.rb +64 -64
- data/lib/jekyll/filters/url_filters.rb +98 -98
- data/lib/jekyll/filters.rb +535 -535
- data/lib/jekyll/frontmatter_defaults.rb +240 -240
- data/lib/jekyll/generator.rb +5 -5
- data/lib/jekyll/hooks.rb +107 -107
- data/lib/jekyll/inclusion.rb +32 -32
- data/lib/jekyll/layout.rb +67 -67
- data/lib/jekyll/liquid_extensions.rb +22 -22
- data/lib/jekyll/liquid_renderer/file.rb +77 -77
- data/lib/jekyll/liquid_renderer/table.rb +55 -55
- data/lib/jekyll/liquid_renderer.rb +80 -80
- data/lib/jekyll/log_adapter.rb +151 -151
- data/lib/jekyll/mime.types +866 -866
- data/lib/jekyll/page.rb +217 -217
- data/lib/jekyll/page_excerpt.rb +25 -25
- data/lib/jekyll/page_without_a_file.rb +14 -14
- data/lib/jekyll/path_manager.rb +74 -74
- data/lib/jekyll/plugin.rb +92 -92
- data/lib/jekyll/plugin_manager.rb +115 -115
- data/lib/jekyll/profiler.rb +58 -58
- data/lib/jekyll/publisher.rb +23 -23
- data/lib/jekyll/reader.rb +192 -192
- data/lib/jekyll/readers/collection_reader.rb +23 -23
- data/lib/jekyll/readers/data_reader.rb +79 -79
- data/lib/jekyll/readers/layout_reader.rb +62 -62
- data/lib/jekyll/readers/page_reader.rb +25 -25
- data/lib/jekyll/readers/post_reader.rb +85 -85
- data/lib/jekyll/readers/static_file_reader.rb +25 -25
- data/lib/jekyll/readers/theme_assets_reader.rb +52 -52
- data/lib/jekyll/regenerator.rb +195 -195
- data/lib/jekyll/related_posts.rb +52 -52
- data/lib/jekyll/renderer.rb +265 -265
- data/lib/jekyll/site.rb +551 -551
- data/lib/jekyll/static_file.rb +208 -208
- data/lib/jekyll/stevenson.rb +60 -60
- data/lib/jekyll/tags/highlight.rb +110 -110
- data/lib/jekyll/tags/include.rb +275 -275
- data/lib/jekyll/tags/link.rb +42 -42
- data/lib/jekyll/tags/post_url.rb +106 -106
- data/lib/jekyll/theme.rb +86 -86
- data/lib/jekyll/theme_builder.rb +121 -121
- data/lib/jekyll/url.rb +167 -167
- data/lib/jekyll/utils/ansi.rb +57 -57
- data/lib/jekyll/utils/exec.rb +26 -26
- data/lib/jekyll/utils/internet.rb +37 -37
- data/lib/jekyll/utils/platforms.rb +67 -67
- data/lib/jekyll/utils/thread_event.rb +31 -31
- data/lib/jekyll/utils/win_tz.rb +75 -75
- data/lib/jekyll/utils.rb +367 -367
- data/lib/jekyll/version.rb +5 -5
- data/lib/jekyll.rb +195 -195
- data/lib/site_template/.gitignore +5 -5
- data/lib/site_template/404.html +25 -25
- data/lib/site_template/_config.yml +55 -55
- data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
- data/lib/site_template/about.markdown +18 -18
- data/lib/site_template/index.markdown +6 -6
- data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
- data/lib/theme_template/Gemfile +4 -4
- data/lib/theme_template/LICENSE.txt.erb +21 -21
- data/lib/theme_template/README.md.erb +52 -52
- data/lib/theme_template/_layouts/default.html +1 -1
- data/lib/theme_template/_layouts/page.html +5 -5
- data/lib/theme_template/_layouts/post.html +5 -5
- data/lib/theme_template/example/_config.yml.erb +1 -1
- data/lib/theme_template/example/_post.md +12 -12
- data/lib/theme_template/example/index.html +14 -14
- data/lib/theme_template/example/style.scss +7 -7
- data/lib/theme_template/gitignore.erb +6 -6
- data/lib/theme_template/theme.gemspec.erb +16 -16
- data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
- data/rubocop/jekyll/no_p_allowed.rb +23 -23
- data/rubocop/jekyll/no_puts_allowed.rb +23 -23
- data/rubocop/jekyll.rb +5 -5
- metadata +3 -3
|
@@ -1,202 +1,202 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "webrick"
|
|
4
|
-
|
|
5
|
-
module Jekyll
|
|
6
|
-
module Commands
|
|
7
|
-
class Serve
|
|
8
|
-
# This class is used to determine if the Servlet should modify a served file
|
|
9
|
-
# to insert the LiveReload script tags
|
|
10
|
-
class SkipAnalyzer
|
|
11
|
-
BAD_USER_AGENTS = [%r!MSIE!].freeze
|
|
12
|
-
|
|
13
|
-
def self.skip_processing?(request, response, options)
|
|
14
|
-
new(request, response, options).skip_processing?
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def initialize(request, response, options)
|
|
18
|
-
@options = options
|
|
19
|
-
@request = request
|
|
20
|
-
@response = response
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def skip_processing?
|
|
24
|
-
!html? || chunked? || inline? || bad_browser?
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def chunked?
|
|
28
|
-
@response["Transfer-Encoding"] == "chunked"
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def inline?
|
|
32
|
-
@response["Content-Disposition"].to_s.start_with?("inline")
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def bad_browser?
|
|
36
|
-
BAD_USER_AGENTS.any? { |pattern| pattern.match?(@request["User-Agent"]) }
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def html?
|
|
40
|
-
@response["Content-Type"].to_s.include?("text/html")
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# This class inserts the LiveReload script tags into HTML as it is served
|
|
45
|
-
class BodyProcessor
|
|
46
|
-
HEAD_TAG_REGEX = %r!<head>|<head[^(er)][^<]*>!.freeze
|
|
47
|
-
|
|
48
|
-
attr_reader :content_length, :new_body, :livereload_added
|
|
49
|
-
|
|
50
|
-
def initialize(body, options)
|
|
51
|
-
@body = body
|
|
52
|
-
@options = options
|
|
53
|
-
@processed = false
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def processed?
|
|
57
|
-
@processed
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# rubocop:disable Metrics/MethodLength
|
|
61
|
-
def process!
|
|
62
|
-
@new_body = []
|
|
63
|
-
# @body will usually be a File object but Strings occur in rare cases
|
|
64
|
-
if @body.respond_to?(:each)
|
|
65
|
-
begin
|
|
66
|
-
@body.each { |line| @new_body << line.to_s }
|
|
67
|
-
ensure
|
|
68
|
-
@body.close
|
|
69
|
-
end
|
|
70
|
-
else
|
|
71
|
-
@new_body = @body.lines
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
@content_length = 0
|
|
75
|
-
@livereload_added = false
|
|
76
|
-
|
|
77
|
-
@new_body.each do |line|
|
|
78
|
-
if !@livereload_added && line["<head"]
|
|
79
|
-
line.gsub!(HEAD_TAG_REGEX) do |match|
|
|
80
|
-
%(#{match}#{template.result(binding)})
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
@livereload_added = true
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
@content_length += line.bytesize
|
|
87
|
-
@processed = true
|
|
88
|
-
end
|
|
89
|
-
@new_body = @new_body.join
|
|
90
|
-
end
|
|
91
|
-
# rubocop:enable Metrics/MethodLength
|
|
92
|
-
|
|
93
|
-
def template
|
|
94
|
-
# Unclear what "snipver" does. Doc at
|
|
95
|
-
# https://github.com/livereload/livereload-js states that the recommended
|
|
96
|
-
# setting is 1.
|
|
97
|
-
|
|
98
|
-
# Complicated JavaScript to ensure that livereload.js is loaded from the
|
|
99
|
-
# same origin as the page. Mostly useful for dealing with the browser's
|
|
100
|
-
# distinction between 'localhost' and 127.0.0.1
|
|
101
|
-
@template ||= ERB.new(<<~TEMPLATE)
|
|
102
|
-
<script>
|
|
103
|
-
document.write(
|
|
104
|
-
'<script src="http://' +
|
|
105
|
-
(location.host || 'localhost').split(':')[0] +
|
|
106
|
-
':<%=@options["livereload_port"] %>/livereload.js?snipver=1<%= livereload_args %>"' +
|
|
107
|
-
'></' +
|
|
108
|
-
'script>');
|
|
109
|
-
</script>
|
|
110
|
-
TEMPLATE
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def livereload_args
|
|
114
|
-
# XHTML standard requires ampersands to be encoded as entities when in
|
|
115
|
-
# attributes. See http://stackoverflow.com/a/2190292
|
|
116
|
-
src = ""
|
|
117
|
-
if @options["livereload_min_delay"]
|
|
118
|
-
src += "&mindelay=#{@options["livereload_min_delay"]}"
|
|
119
|
-
end
|
|
120
|
-
if @options["livereload_max_delay"]
|
|
121
|
-
src += "&maxdelay=#{@options["livereload_max_delay"]}"
|
|
122
|
-
end
|
|
123
|
-
src += "&port=#{@options["livereload_port"]}" if @options["livereload_port"]
|
|
124
|
-
src
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
class Servlet < WEBrick::HTTPServlet::FileHandler
|
|
129
|
-
DEFAULTS = {
|
|
130
|
-
"Cache-Control" => "private, max-age=0, proxy-revalidate, " \
|
|
131
|
-
"no-store, no-cache, must-revalidate",
|
|
132
|
-
}.freeze
|
|
133
|
-
|
|
134
|
-
def initialize(server, root, callbacks)
|
|
135
|
-
# So we can access them easily.
|
|
136
|
-
@jekyll_opts = server.config[:JekyllOptions]
|
|
137
|
-
set_defaults
|
|
138
|
-
super
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def search_index_file(req, res)
|
|
142
|
-
super ||
|
|
143
|
-
search_file(req, res, ".html") ||
|
|
144
|
-
search_file(req, res, ".xhtml")
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# Add the ability to tap file.html the same way that Nginx does on our
|
|
148
|
-
# Docker images (or on GitHub Pages.) The difference is that we might end
|
|
149
|
-
# up with a different preference on which comes first.
|
|
150
|
-
|
|
151
|
-
def search_file(req, res, basename)
|
|
152
|
-
# /file.* > /file/index.html > /file.html
|
|
153
|
-
super ||
|
|
154
|
-
super(req, res, "#{basename}.html") ||
|
|
155
|
-
super(req, res, "#{basename}.xhtml")
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# rubocop:disable Naming/MethodName
|
|
159
|
-
def do_GET(req, res)
|
|
160
|
-
rtn = super
|
|
161
|
-
|
|
162
|
-
if @jekyll_opts["livereload"]
|
|
163
|
-
return rtn if SkipAnalyzer.skip_processing?(req, res, @jekyll_opts)
|
|
164
|
-
|
|
165
|
-
processor = BodyProcessor.new(res.body, @jekyll_opts)
|
|
166
|
-
processor.process!
|
|
167
|
-
res.body = processor.new_body
|
|
168
|
-
res.content_length = processor.content_length.to_s
|
|
169
|
-
|
|
170
|
-
if processor.livereload_added
|
|
171
|
-
# Add a header to indicate that the page content has been modified
|
|
172
|
-
res["X-Rack-LiveReload"] = "1"
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
validate_and_ensure_charset(req, res)
|
|
177
|
-
res.header.merge!(@headers)
|
|
178
|
-
rtn
|
|
179
|
-
end
|
|
180
|
-
# rubocop:enable Naming/MethodName
|
|
181
|
-
|
|
182
|
-
private
|
|
183
|
-
|
|
184
|
-
def validate_and_ensure_charset(_req, res)
|
|
185
|
-
key = res.header.keys.grep(%r!content-type!i).first
|
|
186
|
-
typ = res.header[key]
|
|
187
|
-
|
|
188
|
-
unless %r!;\s*charset=!.match?(typ)
|
|
189
|
-
res.header[key] = "#{typ}; charset=#{@jekyll_opts["encoding"]}"
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
def set_defaults
|
|
194
|
-
hash_ = @jekyll_opts.fetch("webrick", {}).fetch("headers", {})
|
|
195
|
-
DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash|
|
|
196
|
-
hash[key] = val unless hash.key?(key)
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "webrick"
|
|
4
|
+
|
|
5
|
+
module Jekyll
|
|
6
|
+
module Commands
|
|
7
|
+
class Serve
|
|
8
|
+
# This class is used to determine if the Servlet should modify a served file
|
|
9
|
+
# to insert the LiveReload script tags
|
|
10
|
+
class SkipAnalyzer
|
|
11
|
+
BAD_USER_AGENTS = [%r!MSIE!].freeze
|
|
12
|
+
|
|
13
|
+
def self.skip_processing?(request, response, options)
|
|
14
|
+
new(request, response, options).skip_processing?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def initialize(request, response, options)
|
|
18
|
+
@options = options
|
|
19
|
+
@request = request
|
|
20
|
+
@response = response
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def skip_processing?
|
|
24
|
+
!html? || chunked? || inline? || bad_browser?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def chunked?
|
|
28
|
+
@response["Transfer-Encoding"] == "chunked"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def inline?
|
|
32
|
+
@response["Content-Disposition"].to_s.start_with?("inline")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def bad_browser?
|
|
36
|
+
BAD_USER_AGENTS.any? { |pattern| pattern.match?(@request["User-Agent"]) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def html?
|
|
40
|
+
@response["Content-Type"].to_s.include?("text/html")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# This class inserts the LiveReload script tags into HTML as it is served
|
|
45
|
+
class BodyProcessor
|
|
46
|
+
HEAD_TAG_REGEX = %r!<head>|<head[^(er)][^<]*>!.freeze
|
|
47
|
+
|
|
48
|
+
attr_reader :content_length, :new_body, :livereload_added
|
|
49
|
+
|
|
50
|
+
def initialize(body, options)
|
|
51
|
+
@body = body
|
|
52
|
+
@options = options
|
|
53
|
+
@processed = false
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def processed?
|
|
57
|
+
@processed
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# rubocop:disable Metrics/MethodLength
|
|
61
|
+
def process!
|
|
62
|
+
@new_body = []
|
|
63
|
+
# @body will usually be a File object but Strings occur in rare cases
|
|
64
|
+
if @body.respond_to?(:each)
|
|
65
|
+
begin
|
|
66
|
+
@body.each { |line| @new_body << line.to_s }
|
|
67
|
+
ensure
|
|
68
|
+
@body.close
|
|
69
|
+
end
|
|
70
|
+
else
|
|
71
|
+
@new_body = @body.lines
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
@content_length = 0
|
|
75
|
+
@livereload_added = false
|
|
76
|
+
|
|
77
|
+
@new_body.each do |line|
|
|
78
|
+
if !@livereload_added && line["<head"]
|
|
79
|
+
line.gsub!(HEAD_TAG_REGEX) do |match|
|
|
80
|
+
%(#{match}#{template.result(binding)})
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
@livereload_added = true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
@content_length += line.bytesize
|
|
87
|
+
@processed = true
|
|
88
|
+
end
|
|
89
|
+
@new_body = @new_body.join
|
|
90
|
+
end
|
|
91
|
+
# rubocop:enable Metrics/MethodLength
|
|
92
|
+
|
|
93
|
+
def template
|
|
94
|
+
# Unclear what "snipver" does. Doc at
|
|
95
|
+
# https://github.com/livereload/livereload-js states that the recommended
|
|
96
|
+
# setting is 1.
|
|
97
|
+
|
|
98
|
+
# Complicated JavaScript to ensure that livereload.js is loaded from the
|
|
99
|
+
# same origin as the page. Mostly useful for dealing with the browser's
|
|
100
|
+
# distinction between 'localhost' and 127.0.0.1
|
|
101
|
+
@template ||= ERB.new(<<~TEMPLATE)
|
|
102
|
+
<script>
|
|
103
|
+
document.write(
|
|
104
|
+
'<script src="http://' +
|
|
105
|
+
(location.host || 'localhost').split(':')[0] +
|
|
106
|
+
':<%=@options["livereload_port"] %>/livereload.js?snipver=1<%= livereload_args %>"' +
|
|
107
|
+
'></' +
|
|
108
|
+
'script>');
|
|
109
|
+
</script>
|
|
110
|
+
TEMPLATE
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def livereload_args
|
|
114
|
+
# XHTML standard requires ampersands to be encoded as entities when in
|
|
115
|
+
# attributes. See http://stackoverflow.com/a/2190292
|
|
116
|
+
src = ""
|
|
117
|
+
if @options["livereload_min_delay"]
|
|
118
|
+
src += "&mindelay=#{@options["livereload_min_delay"]}"
|
|
119
|
+
end
|
|
120
|
+
if @options["livereload_max_delay"]
|
|
121
|
+
src += "&maxdelay=#{@options["livereload_max_delay"]}"
|
|
122
|
+
end
|
|
123
|
+
src += "&port=#{@options["livereload_port"]}" if @options["livereload_port"]
|
|
124
|
+
src
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
class Servlet < WEBrick::HTTPServlet::FileHandler
|
|
129
|
+
DEFAULTS = {
|
|
130
|
+
"Cache-Control" => "private, max-age=0, proxy-revalidate, " \
|
|
131
|
+
"no-store, no-cache, must-revalidate",
|
|
132
|
+
}.freeze
|
|
133
|
+
|
|
134
|
+
def initialize(server, root, callbacks)
|
|
135
|
+
# So we can access them easily.
|
|
136
|
+
@jekyll_opts = server.config[:JekyllOptions]
|
|
137
|
+
set_defaults
|
|
138
|
+
super
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def search_index_file(req, res)
|
|
142
|
+
super ||
|
|
143
|
+
search_file(req, res, ".html") ||
|
|
144
|
+
search_file(req, res, ".xhtml")
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Add the ability to tap file.html the same way that Nginx does on our
|
|
148
|
+
# Docker images (or on GitHub Pages.) The difference is that we might end
|
|
149
|
+
# up with a different preference on which comes first.
|
|
150
|
+
|
|
151
|
+
def search_file(req, res, basename)
|
|
152
|
+
# /file.* > /file/index.html > /file.html
|
|
153
|
+
super ||
|
|
154
|
+
super(req, res, "#{basename}.html") ||
|
|
155
|
+
super(req, res, "#{basename}.xhtml")
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# rubocop:disable Naming/MethodName
|
|
159
|
+
def do_GET(req, res)
|
|
160
|
+
rtn = super
|
|
161
|
+
|
|
162
|
+
if @jekyll_opts["livereload"]
|
|
163
|
+
return rtn if SkipAnalyzer.skip_processing?(req, res, @jekyll_opts)
|
|
164
|
+
|
|
165
|
+
processor = BodyProcessor.new(res.body, @jekyll_opts)
|
|
166
|
+
processor.process!
|
|
167
|
+
res.body = processor.new_body
|
|
168
|
+
res.content_length = processor.content_length.to_s
|
|
169
|
+
|
|
170
|
+
if processor.livereload_added
|
|
171
|
+
# Add a header to indicate that the page content has been modified
|
|
172
|
+
res["X-Rack-LiveReload"] = "1"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
validate_and_ensure_charset(req, res)
|
|
177
|
+
res.header.merge!(@headers)
|
|
178
|
+
rtn
|
|
179
|
+
end
|
|
180
|
+
# rubocop:enable Naming/MethodName
|
|
181
|
+
|
|
182
|
+
private
|
|
183
|
+
|
|
184
|
+
def validate_and_ensure_charset(_req, res)
|
|
185
|
+
key = res.header.keys.grep(%r!content-type!i).first
|
|
186
|
+
typ = res.header[key]
|
|
187
|
+
|
|
188
|
+
unless %r!;\s*charset=!.match?(typ)
|
|
189
|
+
res.header[key] = "#{typ}; charset=#{@jekyll_opts["encoding"]}"
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def set_defaults
|
|
194
|
+
hash_ = @jekyll_opts.fetch("webrick", {}).fetch("headers", {})
|
|
195
|
+
DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash|
|
|
196
|
+
hash[key] = val unless hash.key?(key)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "http/parser"
|
|
4
|
-
|
|
5
|
-
module Jekyll
|
|
6
|
-
module Commands
|
|
7
|
-
class Serve
|
|
8
|
-
# The LiveReload protocol requires the server to serve livereload.js over HTTP
|
|
9
|
-
# despite the fact that the protocol itself uses WebSockets. This custom connection
|
|
10
|
-
# class addresses the dual protocols that the server needs to understand.
|
|
11
|
-
class HttpAwareConnection < EventMachine::WebSocket::Connection
|
|
12
|
-
attr_reader :reload_body, :reload_size
|
|
13
|
-
|
|
14
|
-
def initialize(_opts)
|
|
15
|
-
# If EventMachine SSL support on Windows ever gets better, the code below will
|
|
16
|
-
# set up the reactor to handle SSL
|
|
17
|
-
#
|
|
18
|
-
# @ssl_enabled = opts["ssl_cert"] && opts["ssl_key"]
|
|
19
|
-
# if @ssl_enabled
|
|
20
|
-
# em_opts[:tls_options] = {
|
|
21
|
-
# :private_key_file => Jekyll.sanitized_path(opts["source"], opts["ssl_key"]),
|
|
22
|
-
# :cert_chain_file => Jekyll.sanitized_path(opts["source"], opts["ssl_cert"])
|
|
23
|
-
# }
|
|
24
|
-
# em_opts[:secure] = true
|
|
25
|
-
# end
|
|
26
|
-
|
|
27
|
-
# This is too noisy even for --verbose, but uncomment if you need it for
|
|
28
|
-
# a specific WebSockets issue. Adding ?LR-verbose=true onto the URL will
|
|
29
|
-
# enable logging on the client side.
|
|
30
|
-
# em_opts[:debug] = true
|
|
31
|
-
|
|
32
|
-
em_opts = {}
|
|
33
|
-
super(em_opts)
|
|
34
|
-
|
|
35
|
-
reload_file = File.join(Serve.singleton_class::LIVERELOAD_DIR, "livereload.js")
|
|
36
|
-
|
|
37
|
-
@reload_body = File.read(reload_file)
|
|
38
|
-
@reload_size = @reload_body.bytesize
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# rubocop:disable Metrics/MethodLength
|
|
42
|
-
def dispatch(data)
|
|
43
|
-
parser = Http::Parser.new
|
|
44
|
-
parser << data
|
|
45
|
-
|
|
46
|
-
# WebSockets requests will have a Connection: Upgrade header
|
|
47
|
-
if parser.http_method != "GET" || parser.upgrade?
|
|
48
|
-
super
|
|
49
|
-
elsif parser.request_url.start_with?("/livereload.js")
|
|
50
|
-
headers = [
|
|
51
|
-
"HTTP/1.1 200 OK",
|
|
52
|
-
"Content-Type: application/javascript",
|
|
53
|
-
"Content-Length: #{reload_size}",
|
|
54
|
-
"",
|
|
55
|
-
"",
|
|
56
|
-
].join("\r\n")
|
|
57
|
-
send_data(headers)
|
|
58
|
-
|
|
59
|
-
# stream_file_data would free us from keeping livereload.js in memory
|
|
60
|
-
# but JRuby blocks on that call and never returns
|
|
61
|
-
send_data(reload_body)
|
|
62
|
-
close_connection_after_writing
|
|
63
|
-
else
|
|
64
|
-
body = "This port only serves livereload.js over HTTP.\n"
|
|
65
|
-
headers = [
|
|
66
|
-
"HTTP/1.1 400 Bad Request",
|
|
67
|
-
"Content-Type: text/plain",
|
|
68
|
-
"Content-Length: #{body.bytesize}",
|
|
69
|
-
"",
|
|
70
|
-
"",
|
|
71
|
-
].join("\r\n")
|
|
72
|
-
send_data(headers)
|
|
73
|
-
send_data(body)
|
|
74
|
-
close_connection_after_writing
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
# rubocop:enable Metrics/MethodLength
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "http/parser"
|
|
4
|
+
|
|
5
|
+
module Jekyll
|
|
6
|
+
module Commands
|
|
7
|
+
class Serve
|
|
8
|
+
# The LiveReload protocol requires the server to serve livereload.js over HTTP
|
|
9
|
+
# despite the fact that the protocol itself uses WebSockets. This custom connection
|
|
10
|
+
# class addresses the dual protocols that the server needs to understand.
|
|
11
|
+
class HttpAwareConnection < EventMachine::WebSocket::Connection
|
|
12
|
+
attr_reader :reload_body, :reload_size
|
|
13
|
+
|
|
14
|
+
def initialize(_opts)
|
|
15
|
+
# If EventMachine SSL support on Windows ever gets better, the code below will
|
|
16
|
+
# set up the reactor to handle SSL
|
|
17
|
+
#
|
|
18
|
+
# @ssl_enabled = opts["ssl_cert"] && opts["ssl_key"]
|
|
19
|
+
# if @ssl_enabled
|
|
20
|
+
# em_opts[:tls_options] = {
|
|
21
|
+
# :private_key_file => Jekyll.sanitized_path(opts["source"], opts["ssl_key"]),
|
|
22
|
+
# :cert_chain_file => Jekyll.sanitized_path(opts["source"], opts["ssl_cert"])
|
|
23
|
+
# }
|
|
24
|
+
# em_opts[:secure] = true
|
|
25
|
+
# end
|
|
26
|
+
|
|
27
|
+
# This is too noisy even for --verbose, but uncomment if you need it for
|
|
28
|
+
# a specific WebSockets issue. Adding ?LR-verbose=true onto the URL will
|
|
29
|
+
# enable logging on the client side.
|
|
30
|
+
# em_opts[:debug] = true
|
|
31
|
+
|
|
32
|
+
em_opts = {}
|
|
33
|
+
super(em_opts)
|
|
34
|
+
|
|
35
|
+
reload_file = File.join(Serve.singleton_class::LIVERELOAD_DIR, "livereload.js")
|
|
36
|
+
|
|
37
|
+
@reload_body = File.read(reload_file)
|
|
38
|
+
@reload_size = @reload_body.bytesize
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# rubocop:disable Metrics/MethodLength
|
|
42
|
+
def dispatch(data)
|
|
43
|
+
parser = Http::Parser.new
|
|
44
|
+
parser << data
|
|
45
|
+
|
|
46
|
+
# WebSockets requests will have a Connection: Upgrade header
|
|
47
|
+
if parser.http_method != "GET" || parser.upgrade?
|
|
48
|
+
super
|
|
49
|
+
elsif parser.request_url.start_with?("/livereload.js")
|
|
50
|
+
headers = [
|
|
51
|
+
"HTTP/1.1 200 OK",
|
|
52
|
+
"Content-Type: application/javascript",
|
|
53
|
+
"Content-Length: #{reload_size}",
|
|
54
|
+
"",
|
|
55
|
+
"",
|
|
56
|
+
].join("\r\n")
|
|
57
|
+
send_data(headers)
|
|
58
|
+
|
|
59
|
+
# stream_file_data would free us from keeping livereload.js in memory
|
|
60
|
+
# but JRuby blocks on that call and never returns
|
|
61
|
+
send_data(reload_body)
|
|
62
|
+
close_connection_after_writing
|
|
63
|
+
else
|
|
64
|
+
body = "This port only serves livereload.js over HTTP.\n"
|
|
65
|
+
headers = [
|
|
66
|
+
"HTTP/1.1 400 Bad Request",
|
|
67
|
+
"Content-Type: text/plain",
|
|
68
|
+
"Content-Length: #{body.bytesize}",
|
|
69
|
+
"",
|
|
70
|
+
"",
|
|
71
|
+
].join("\r\n")
|
|
72
|
+
send_data(headers)
|
|
73
|
+
send_data(body)
|
|
74
|
+
close_connection_after_writing
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
# rubocop:enable Metrics/MethodLength
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|