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.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +350 -350
  3. data/LICENSE +21 -21
  4. data/README.markdown +86 -86
  5. data/exe/jekyll +57 -57
  6. data/lib/blank_template/_config.yml +3 -3
  7. data/lib/blank_template/_layouts/default.html +12 -12
  8. data/lib/blank_template/_sass/main.scss +9 -9
  9. data/lib/blank_template/assets/css/main.scss +4 -4
  10. data/lib/blank_template/index.md +8 -8
  11. data/lib/jekyll/cache.rb +190 -190
  12. data/lib/jekyll/cleaner.rb +111 -111
  13. data/lib/jekyll/collection.rb +309 -309
  14. data/lib/jekyll/command.rb +105 -105
  15. data/lib/jekyll/commands/build.rb +93 -93
  16. data/lib/jekyll/commands/clean.rb +45 -45
  17. data/lib/jekyll/commands/doctor.rb +177 -177
  18. data/lib/jekyll/commands/help.rb +34 -34
  19. data/lib/jekyll/commands/new.rb +172 -169
  20. data/lib/jekyll/commands/new_theme.rb +40 -40
  21. data/lib/jekyll/commands/serve/live_reload_reactor.rb +122 -122
  22. data/lib/jekyll/commands/serve/livereload_assets/livereload.js +1183 -1183
  23. data/lib/jekyll/commands/serve/servlet.rb +202 -202
  24. data/lib/jekyll/commands/serve/websockets.rb +81 -81
  25. data/lib/jekyll/commands/serve.rb +362 -362
  26. data/lib/jekyll/configuration.rb +313 -313
  27. data/lib/jekyll/converter.rb +54 -54
  28. data/lib/jekyll/converters/identity.rb +41 -41
  29. data/lib/jekyll/converters/markdown/kramdown_parser.rb +199 -199
  30. data/lib/jekyll/converters/markdown.rb +113 -113
  31. data/lib/jekyll/converters/smartypants.rb +70 -70
  32. data/lib/jekyll/convertible.rb +257 -257
  33. data/lib/jekyll/deprecator.rb +50 -50
  34. data/lib/jekyll/document.rb +544 -544
  35. data/lib/jekyll/drops/collection_drop.rb +20 -20
  36. data/lib/jekyll/drops/document_drop.rb +70 -70
  37. data/lib/jekyll/drops/drop.rb +293 -293
  38. data/lib/jekyll/drops/excerpt_drop.rb +19 -19
  39. data/lib/jekyll/drops/jekyll_drop.rb +32 -32
  40. data/lib/jekyll/drops/site_drop.rb +66 -66
  41. data/lib/jekyll/drops/static_file_drop.rb +14 -14
  42. data/lib/jekyll/drops/unified_payload_drop.rb +26 -26
  43. data/lib/jekyll/drops/url_drop.rb +140 -140
  44. data/lib/jekyll/entry_filter.rb +121 -121
  45. data/lib/jekyll/errors.rb +20 -20
  46. data/lib/jekyll/excerpt.rb +201 -201
  47. data/lib/jekyll/external.rb +79 -79
  48. data/lib/jekyll/filters/date_filters.rb +110 -110
  49. data/lib/jekyll/filters/grouping_filters.rb +64 -64
  50. data/lib/jekyll/filters/url_filters.rb +98 -98
  51. data/lib/jekyll/filters.rb +535 -535
  52. data/lib/jekyll/frontmatter_defaults.rb +240 -240
  53. data/lib/jekyll/generator.rb +5 -5
  54. data/lib/jekyll/hooks.rb +107 -107
  55. data/lib/jekyll/inclusion.rb +32 -32
  56. data/lib/jekyll/layout.rb +67 -67
  57. data/lib/jekyll/liquid_extensions.rb +22 -22
  58. data/lib/jekyll/liquid_renderer/file.rb +77 -77
  59. data/lib/jekyll/liquid_renderer/table.rb +55 -55
  60. data/lib/jekyll/liquid_renderer.rb +80 -80
  61. data/lib/jekyll/log_adapter.rb +151 -151
  62. data/lib/jekyll/mime.types +866 -866
  63. data/lib/jekyll/page.rb +217 -217
  64. data/lib/jekyll/page_excerpt.rb +25 -25
  65. data/lib/jekyll/page_without_a_file.rb +14 -14
  66. data/lib/jekyll/path_manager.rb +74 -74
  67. data/lib/jekyll/plugin.rb +92 -92
  68. data/lib/jekyll/plugin_manager.rb +115 -115
  69. data/lib/jekyll/profiler.rb +58 -58
  70. data/lib/jekyll/publisher.rb +23 -23
  71. data/lib/jekyll/reader.rb +192 -192
  72. data/lib/jekyll/readers/collection_reader.rb +23 -23
  73. data/lib/jekyll/readers/data_reader.rb +79 -79
  74. data/lib/jekyll/readers/layout_reader.rb +62 -62
  75. data/lib/jekyll/readers/page_reader.rb +25 -25
  76. data/lib/jekyll/readers/post_reader.rb +85 -85
  77. data/lib/jekyll/readers/static_file_reader.rb +25 -25
  78. data/lib/jekyll/readers/theme_assets_reader.rb +52 -52
  79. data/lib/jekyll/regenerator.rb +195 -195
  80. data/lib/jekyll/related_posts.rb +52 -52
  81. data/lib/jekyll/renderer.rb +265 -265
  82. data/lib/jekyll/site.rb +551 -551
  83. data/lib/jekyll/static_file.rb +208 -208
  84. data/lib/jekyll/stevenson.rb +60 -60
  85. data/lib/jekyll/tags/highlight.rb +110 -110
  86. data/lib/jekyll/tags/include.rb +275 -275
  87. data/lib/jekyll/tags/link.rb +42 -42
  88. data/lib/jekyll/tags/post_url.rb +106 -106
  89. data/lib/jekyll/theme.rb +86 -86
  90. data/lib/jekyll/theme_builder.rb +121 -121
  91. data/lib/jekyll/url.rb +167 -167
  92. data/lib/jekyll/utils/ansi.rb +57 -57
  93. data/lib/jekyll/utils/exec.rb +26 -26
  94. data/lib/jekyll/utils/internet.rb +37 -37
  95. data/lib/jekyll/utils/platforms.rb +67 -67
  96. data/lib/jekyll/utils/thread_event.rb +31 -31
  97. data/lib/jekyll/utils/win_tz.rb +75 -75
  98. data/lib/jekyll/utils.rb +367 -367
  99. data/lib/jekyll/version.rb +5 -5
  100. data/lib/jekyll.rb +195 -195
  101. data/lib/site_template/.gitignore +5 -5
  102. data/lib/site_template/404.html +25 -25
  103. data/lib/site_template/_config.yml +55 -55
  104. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +29 -29
  105. data/lib/site_template/about.markdown +18 -18
  106. data/lib/site_template/index.markdown +6 -6
  107. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -74
  108. data/lib/theme_template/Gemfile +4 -4
  109. data/lib/theme_template/LICENSE.txt.erb +21 -21
  110. data/lib/theme_template/README.md.erb +52 -52
  111. data/lib/theme_template/_layouts/default.html +1 -1
  112. data/lib/theme_template/_layouts/page.html +5 -5
  113. data/lib/theme_template/_layouts/post.html +5 -5
  114. data/lib/theme_template/example/_config.yml.erb +1 -1
  115. data/lib/theme_template/example/_post.md +12 -12
  116. data/lib/theme_template/example/index.html +14 -14
  117. data/lib/theme_template/example/style.scss +7 -7
  118. data/lib/theme_template/gitignore.erb +6 -6
  119. data/lib/theme_template/theme.gemspec.erb +16 -16
  120. data/rubocop/jekyll/assert_equal_literal_actual.rb +149 -149
  121. data/rubocop/jekyll/no_p_allowed.rb +23 -23
  122. data/rubocop/jekyll/no_puts_allowed.rb +23 -23
  123. data/rubocop/jekyll.rb +5 -5
  124. 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 += "&amp;mindelay=#{@options["livereload_min_delay"]}"
119
- end
120
- if @options["livereload_max_delay"]
121
- src += "&amp;maxdelay=#{@options["livereload_max_delay"]}"
122
- end
123
- src += "&amp;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 += "&amp;mindelay=#{@options["livereload_min_delay"]}"
119
+ end
120
+ if @options["livereload_max_delay"]
121
+ src += "&amp;maxdelay=#{@options["livereload_max_delay"]}"
122
+ end
123
+ src += "&amp;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