lanyon 0.3.4 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/History.md +23 -0
- data/LICENSE +1 -1
- data/README.md +17 -3
- data/Rakefile +2 -1
- data/lanyon.gemspec +4 -4
- data/lib/lanyon/application.rb +8 -6
- data/lib/lanyon/backports.rb +2 -0
- data/lib/lanyon/router.rb +14 -2
- data/lib/lanyon/version.rb +4 -2
- data/lib/lanyon.rb +4 -1
- data/test/helper.rb +12 -4
- data/test/test_build.rb +6 -3
- data/test/test_configuration.rb +22 -21
- data/test/test_integration.rb +72 -65
- data/test/test_router.rb +60 -20
- metadata +9 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a2f2ed82be1b1a0e4a4ca74b9ef4bf855fd321fbfdab480711e19b506c29e79e
|
4
|
+
data.tar.gz: e8713bd319fb150aa8763f9b977a6d3407cef1f2fe1edef01e712a8d0c5f09e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4acef77523d343f1dcf1b2c13037cf2ca3aafd9c34613daf52aaae6697811a2b571278e52c2b75db653881fe467ddcb54abdbc991aca7ab8fed87a7cbebf946
|
7
|
+
data.tar.gz: 02b0eb0279f08fde9307f01c5190efc3d2197d5b7f6205aea87383811091582a9d85fd11cddd656f33a7ef5de850dd671e9770cb92a062c4af7530116321c7f4
|
data/History.md
CHANGED
@@ -1,6 +1,29 @@
|
|
1
1
|
Release History
|
2
2
|
===============
|
3
3
|
|
4
|
+
## 0.4.3
|
5
|
+
|
6
|
+
* Use Rack::ContentLength middleware to fix missing
|
7
|
+
Content-Length headers for rack 2.1.0 and later
|
8
|
+
* Update development dependencies
|
9
|
+
|
10
|
+
## 0.4.2
|
11
|
+
|
12
|
+
* Avoid deprecation warnings for minitest expectations
|
13
|
+
* Improve code style
|
14
|
+
|
15
|
+
## 0.4.1
|
16
|
+
|
17
|
+
* Drop pessimistic constraint on Jekyll version
|
18
|
+
* Remove Jekyll cache directory after tests
|
19
|
+
* Let "clean" task remove Jekyll cache directory
|
20
|
+
* Add Jekyll cache directory to .gitignore
|
21
|
+
* Add magic comments for frozen string literals
|
22
|
+
|
23
|
+
## 0.4.0
|
24
|
+
|
25
|
+
* Support .html extension stripping
|
26
|
+
|
4
27
|
## 0.3.4
|
5
28
|
|
6
29
|
* Allow Rack 2
|
data/LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c) 2015-
|
3
|
+
Copyright (c) 2015-2022 Marcus Stollsteimer
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -56,7 +56,7 @@ or as Lanyon initialization options in `config.ru`.
|
|
56
56
|
Example:
|
57
57
|
|
58
58
|
``` ruby
|
59
|
-
run Lanyon.application(:
|
59
|
+
run Lanyon.application(destination: "mysite")
|
60
60
|
```
|
61
61
|
|
62
62
|
This will set a custom destination path, overriding the default (`_site`)
|
@@ -70,7 +70,7 @@ Additional Lanyon initialization options:
|
|
70
70
|
(default: false)
|
71
71
|
|
72
72
|
Note that on read-only filesystems a site build will fail,
|
73
|
-
so you must set
|
73
|
+
so you must set `skip_build: true` in these cases.
|
74
74
|
|
75
75
|
### Custum 404 Page
|
76
76
|
|
@@ -83,6 +83,20 @@ This can also be a file generated by Jekyll from e.g. Markdown sources.
|
|
83
83
|
|
84
84
|
- Gem dependencies (runtime): `jekyll`, `rack`
|
85
85
|
|
86
|
+
## How URLs are resolved
|
87
|
+
|
88
|
+
Lanyon maps URLs to corresponding files as follows:
|
89
|
+
|
90
|
+
1. a `path/` with a trailing slash is changed to `path/index.html`,
|
91
|
+
2. then, Lanyon checks for an exactly corresponding file,
|
92
|
+
3. when `path` does not exist but `path/index.html` does,
|
93
|
+
the response will be a redirect to `path/`,
|
94
|
+
4. when neither 2. nor 3. apply, +path.html+ is tried.
|
95
|
+
|
96
|
+
To avoid confusion, it's probably a good idea to have only one
|
97
|
+
of `resource`, `resource/index.html`, and `resource.html` present
|
98
|
+
as file in your site.
|
99
|
+
|
86
100
|
## Reporting Bugs
|
87
101
|
|
88
102
|
Report bugs on the Lanyon home page: <https://github.com/stomar/lanyon/>
|
@@ -93,7 +107,7 @@ Lanyon was inspired by [rack-jekyll][rack-jekyll] and written as a replacement.
|
|
93
107
|
|
94
108
|
## License
|
95
109
|
|
96
|
-
Copyright © 2015-
|
110
|
+
Copyright © 2015-2022 Marcus Stollsteimer
|
97
111
|
|
98
112
|
Lanyon is licensed under the [MIT License][MIT].
|
99
113
|
See also the included `LICENSE` file for more information.
|
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ def gemspec_file
|
|
7
7
|
end
|
8
8
|
|
9
9
|
|
10
|
-
task :
|
10
|
+
task default: [:test]
|
11
11
|
|
12
12
|
Rake::TestTask.new do |t|
|
13
13
|
t.pattern = "test/**/test_*.rb"
|
@@ -25,6 +25,7 @@ end
|
|
25
25
|
desc "Remove generated files"
|
26
26
|
task :clean do
|
27
27
|
FileUtils.rm_rf("demo/_site")
|
28
|
+
FileUtils.rm_rf("demo/.jekyll-cache")
|
28
29
|
FileUtils.rm(Dir.glob("*.gem"))
|
29
30
|
end
|
30
31
|
|
data/lanyon.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
|
|
10
10
|
|
11
11
|
s.summary = "Lanyon serves your Jekyll site as a Rack application."
|
12
12
|
s.description =
|
13
|
-
"Lanyon is a good friend of Jekyll, the static site generator, "
|
13
|
+
"Lanyon is a good friend of Jekyll, the static site generator, " \
|
14
14
|
"and transforms your website into a Rack application."
|
15
15
|
|
16
16
|
s.authors = ["Marcus Stollsteimer"]
|
@@ -21,11 +21,11 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
s.required_ruby_version = ">= 2.0.0"
|
23
23
|
|
24
|
-
s.add_dependency "jekyll", ">= 2.0"
|
24
|
+
s.add_dependency "jekyll", ">= 2.0"
|
25
25
|
s.add_dependency "rack", ">= 1.6", "< 3.0"
|
26
26
|
|
27
|
-
s.add_development_dependency "rake", "~> 11.2"
|
28
27
|
s.add_development_dependency "minitest", "~> 5.8"
|
28
|
+
s.add_development_dependency "rake", "~> 13.0"
|
29
29
|
|
30
30
|
s.require_paths = ["lib"]
|
31
31
|
|
@@ -40,7 +40,7 @@ Gem::Specification.new do |s|
|
|
40
40
|
] +
|
41
41
|
Dir.glob("lib/**/*") +
|
42
42
|
Dir.glob("test/**/*") +
|
43
|
-
Dir.glob("demo/**/*").reject {|f| f
|
43
|
+
Dir.glob("demo/**/*").reject {|f| f.start_with?("demo/_site/") }
|
44
44
|
|
45
45
|
s.extra_rdoc_files = %w[README.md LICENSE History.md]
|
46
46
|
s.rdoc_options = ["--charset=UTF-8", "--main=README.md"]
|
data/lib/lanyon/application.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rack/mime"
|
2
4
|
require "rack/request"
|
3
5
|
require "rack/response"
|
@@ -42,7 +44,7 @@ module Lanyon
|
|
42
44
|
|
43
45
|
def response(filename) # :nodoc:
|
44
46
|
response = Rack::Response.new(File.binread(filename))
|
45
|
-
response["Content-Type"]
|
47
|
+
response["Content-Type"] = media_type(filename)
|
46
48
|
|
47
49
|
response.finish
|
48
50
|
end
|
@@ -61,7 +63,7 @@ module Lanyon
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def html_wrap(title, content) # :nodoc:
|
64
|
-
<<-
|
66
|
+
<<-DOCUMENT.gsub(/^ {6}/, "")
|
65
67
|
<!DOCTYPE html>
|
66
68
|
<html lang="en">
|
67
69
|
<head>
|
@@ -71,7 +73,7 @@ module Lanyon
|
|
71
73
|
#{content}
|
72
74
|
</body>
|
73
75
|
</html>
|
74
|
-
|
76
|
+
DOCUMENT
|
75
77
|
end
|
76
78
|
|
77
79
|
def default_404_body # :nodoc:
|
@@ -95,7 +97,7 @@ module Lanyon
|
|
95
97
|
end
|
96
98
|
|
97
99
|
def redirect_body(to_path) # :nodoc:
|
98
|
-
message = %Q
|
100
|
+
message = %Q(<p>Redirecting to <a href="#{to_path}">#{to_path}</a>.</p>)
|
99
101
|
|
100
102
|
html_wrap("Redirection", message)
|
101
103
|
end
|
@@ -108,9 +110,9 @@ module Lanyon
|
|
108
110
|
|
109
111
|
body = redirect_body(location)
|
110
112
|
headers = {
|
111
|
-
"Location"
|
113
|
+
"Location" => location,
|
112
114
|
"Cache-Control" => "max-age=#{cache_time}, must-revalidate",
|
113
|
-
"Expires"
|
115
|
+
"Expires" => (Time.now + cache_time).httpdate
|
114
116
|
}
|
115
117
|
|
116
118
|
html_response(body, 301, headers)
|
data/lib/lanyon/backports.rb
CHANGED
data/lib/lanyon/router.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rack/utils"
|
2
4
|
|
3
5
|
|
@@ -16,9 +18,17 @@ module Lanyon
|
|
16
18
|
# Returns the full file system path of the file corresponding to
|
17
19
|
# the given URL +path+, or
|
18
20
|
#
|
19
|
-
# - +:
|
20
|
-
# - +:
|
21
|
+
# - +:must_redirect+ if the request must be redirected to +path/+,
|
22
|
+
# - +:not_found+ if no corresponding file exists.
|
23
|
+
#
|
24
|
+
# The return value is found as follows:
|
21
25
|
#
|
26
|
+
# 1. a +path/+ with a trailing slash is changed to +path/index.html+,
|
27
|
+
# 2. then, the method checks for an exactly corresponding file,
|
28
|
+
# 3. when +path+ does not exist but +path/index.html+ does,
|
29
|
+
# a redirect will be indicated,
|
30
|
+
# 4. finally, when no exactly corresponding file or redirect
|
31
|
+
# can be found, +path.html+ is tried.
|
22
32
|
def endpoint(path)
|
23
33
|
normalized = normalize_path_info(path)
|
24
34
|
|
@@ -27,6 +37,8 @@ module Lanyon
|
|
27
37
|
fullpath
|
28
38
|
elsif needs_redirect_to_dir?(fullpath)
|
29
39
|
:must_redirect
|
40
|
+
elsif FileTest.file?(fullpath_html = "#{fullpath}.html")
|
41
|
+
fullpath_html
|
30
42
|
else
|
31
43
|
:not_found
|
32
44
|
end
|
data/lib/lanyon/version.rb
CHANGED
data/lib/lanyon.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# = lanyon.rb
|
2
4
|
#
|
3
5
|
# See Lanyon module for documentation.
|
@@ -49,6 +51,7 @@ module Lanyon
|
|
49
51
|
|
50
52
|
Rack::Builder.new do
|
51
53
|
use Rack::Head
|
54
|
+
use Rack::ContentLength
|
52
55
|
use Rack::ConditionalGet
|
53
56
|
use Rack::ETag, nil, nil
|
54
57
|
|
@@ -68,7 +71,7 @@ module Lanyon
|
|
68
71
|
|
69
72
|
# @private
|
70
73
|
def self.default_options # :nodoc:
|
71
|
-
{ :
|
74
|
+
{ skip_build: false }
|
72
75
|
end
|
73
76
|
|
74
77
|
# @private
|
data/test/helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "minitest/autorun"
|
2
4
|
require "fileutils"
|
3
5
|
require "stringio"
|
@@ -6,7 +8,11 @@ require "rack/mock"
|
|
6
8
|
require "lanyon"
|
7
9
|
|
8
10
|
|
9
|
-
TEST_DIR = File.expand_path(
|
11
|
+
TEST_DIR = File.expand_path(__dir__)
|
12
|
+
|
13
|
+
SOURCE_DIR = File.join(TEST_DIR, "source")
|
14
|
+
CACHE_DIR = File.join(SOURCE_DIR, ".jekyll-cache")
|
15
|
+
|
10
16
|
TEMP_DIR = File.join(TEST_DIR, "tmp")
|
11
17
|
|
12
18
|
|
@@ -24,10 +30,13 @@ def chdir_tempdir
|
|
24
30
|
Dir.chdir(TEMP_DIR)
|
25
31
|
end
|
26
32
|
|
27
|
-
def
|
28
|
-
File.
|
33
|
+
def teardown_cachedir
|
34
|
+
FileUtils.rm_rf(CACHE_DIR) if File.exist?(CACHE_DIR)
|
29
35
|
end
|
30
36
|
|
37
|
+
def sourcedir
|
38
|
+
SOURCE_DIR
|
39
|
+
end
|
31
40
|
|
32
41
|
def silence_output
|
33
42
|
original_stderr, original_stdout = $stderr, $stdout
|
@@ -38,7 +47,6 @@ ensure
|
|
38
47
|
$stderr, $stdout = original_stderr, original_stdout
|
39
48
|
end
|
40
49
|
|
41
|
-
|
42
50
|
def file_must_exist(filename)
|
43
51
|
assert File.exist?(filename),
|
44
52
|
"Expected file `#{filename}' to exist."
|
data/test/test_build.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "helper"
|
2
4
|
|
3
5
|
|
@@ -9,7 +11,7 @@ describe "when creating a Lanyon application" do
|
|
9
11
|
|
10
12
|
destdir = File.join(tempdir, "_site")
|
11
13
|
|
12
|
-
@dir_options = { :
|
14
|
+
@dir_options = { source: sourcedir, destination: destdir }
|
13
15
|
@page = File.join(destdir, "index.html")
|
14
16
|
@no_page = File.join(destdir, "not_a_page.html")
|
15
17
|
|
@@ -21,6 +23,7 @@ describe "when creating a Lanyon application" do
|
|
21
23
|
|
22
24
|
after do
|
23
25
|
teardown_tempdir
|
26
|
+
teardown_cachedir
|
24
27
|
end
|
25
28
|
|
26
29
|
it "builds the site by default, removing old content" do
|
@@ -33,7 +36,7 @@ describe "when creating a Lanyon application" do
|
|
33
36
|
end
|
34
37
|
|
35
38
|
it "does not build the site when :skip_build option is set" do
|
36
|
-
options = {:
|
39
|
+
options = { skip_build: true }.merge(@dir_options)
|
37
40
|
silence_output do
|
38
41
|
Lanyon.application(options)
|
39
42
|
end
|
@@ -43,7 +46,7 @@ describe "when creating a Lanyon application" do
|
|
43
46
|
end
|
44
47
|
|
45
48
|
it "does always build the site with ::build" do
|
46
|
-
options = {:
|
49
|
+
options = { skip_build: true }.merge(@dir_options)
|
47
50
|
silence_output do
|
48
51
|
Lanyon.build(options)
|
49
52
|
end
|
data/test/test_configuration.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "helper"
|
2
4
|
|
3
5
|
|
@@ -23,7 +25,7 @@ describe "when configuring site" do
|
|
23
25
|
|
24
26
|
it "loads the correct default destination" do
|
25
27
|
config = get_jekyll_config
|
26
|
-
config["destination"].must_equal File.join(Dir.pwd, "_site")
|
28
|
+
_(config["destination"]).must_equal File.join(Dir.pwd, "_site")
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
@@ -41,8 +43,8 @@ describe "when configuring site" do
|
|
41
43
|
|
42
44
|
it "loads the configuration from file" do
|
43
45
|
config = get_jekyll_config
|
44
|
-
config.must_include "config_file_opt"
|
45
|
-
config["config_file_opt"].must_equal "ok"
|
46
|
+
_(config).must_include "config_file_opt"
|
47
|
+
_(config["config_file_opt"]).must_equal "ok"
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
@@ -59,28 +61,28 @@ describe "when configuring site" do
|
|
59
61
|
end
|
60
62
|
|
61
63
|
it "loads the configuration from file" do
|
62
|
-
config = get_jekyll_config(:
|
63
|
-
config.must_include "config_file_opt"
|
64
|
-
config["config_file_opt"].must_equal "ok"
|
64
|
+
config = get_jekyll_config(config: "_my_config.yml")
|
65
|
+
_(config).must_include "config_file_opt"
|
66
|
+
_(config["config_file_opt"]).must_equal "ok"
|
65
67
|
end
|
66
68
|
end
|
67
69
|
|
68
70
|
describe "when initialization options are given" do
|
69
71
|
|
70
72
|
it "has the initialization options" do
|
71
|
-
config = get_jekyll_config(:
|
72
|
-
config.must_include "init_opt"
|
73
|
-
config["init_opt"].must_equal "ok"
|
73
|
+
config = get_jekyll_config(init_opt: "ok")
|
74
|
+
_(config).must_include "init_opt"
|
75
|
+
_(config["init_opt"]).must_equal "ok"
|
74
76
|
end
|
75
77
|
|
76
78
|
it "has the correct destination" do
|
77
|
-
config = get_jekyll_config(:
|
78
|
-
config["destination"].must_equal "/project/_site"
|
79
|
+
config = get_jekyll_config(destination: "/project/_site")
|
80
|
+
_(config["destination"]).must_equal "/project/_site"
|
79
81
|
end
|
80
82
|
|
81
83
|
it "does not pass :skip_build on to Jekyll" do
|
82
|
-
config = get_jekyll_config(:
|
83
|
-
config.wont_include "skip_build"
|
84
|
+
config = get_jekyll_config(skip_build: "ok")
|
85
|
+
_(config).wont_include "skip_build"
|
84
86
|
end
|
85
87
|
end
|
86
88
|
|
@@ -99,17 +101,16 @@ describe "when configuring site" do
|
|
99
101
|
end
|
100
102
|
|
101
103
|
it "has all options and initialization options override file options" do
|
102
|
-
config = get_jekyll_config(:
|
103
|
-
|
104
|
-
config.must_include "
|
105
|
-
config.must_include "
|
106
|
-
config.
|
107
|
-
config["common_opt"].must_equal "from init"
|
104
|
+
config = get_jekyll_config(init_opt: "ok", common_opt: "from init")
|
105
|
+
_(config).must_include "init_opt"
|
106
|
+
_(config).must_include "config_file_opt"
|
107
|
+
_(config).must_include "common_opt"
|
108
|
+
_(config["common_opt"]).must_equal "from init"
|
108
109
|
end
|
109
110
|
|
110
111
|
it "has the correct destination" do
|
111
|
-
config = get_jekyll_config(:
|
112
|
-
config["destination"].must_equal "/project/_site_from_init"
|
112
|
+
config = get_jekyll_config(destination: "/project/_site_from_init")
|
113
|
+
_(config["destination"]).must_equal "/project/_site_from_init"
|
113
114
|
end
|
114
115
|
end
|
115
116
|
end
|
data/test/test_integration.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "helper"
|
4
4
|
|
@@ -18,12 +18,13 @@ describe "when handling requests" do
|
|
18
18
|
|
19
19
|
@destdir = File.join(tempdir, "_site")
|
20
20
|
|
21
|
-
app = get_app(:
|
21
|
+
app = get_app(source: sourcedir, destination: @destdir)
|
22
22
|
@request = Rack::MockRequest.new(app)
|
23
23
|
end
|
24
24
|
|
25
25
|
after do
|
26
26
|
teardown_tempdir
|
27
|
+
teardown_cachedir
|
27
28
|
end
|
28
29
|
|
29
30
|
|
@@ -34,23 +35,23 @@ describe "when handling requests" do
|
|
34
35
|
end
|
35
36
|
|
36
37
|
it "returns status 200" do
|
37
|
-
@response.status.must_equal 200
|
38
|
+
_(@response.status).must_equal 200
|
38
39
|
end
|
39
40
|
|
40
41
|
it "returns correct Content-Length header" do
|
41
|
-
@response.original_headers["Content-Length"].must_equal "17"
|
42
|
+
_(@response.original_headers["Content-Length"]).must_equal "17"
|
42
43
|
end
|
43
44
|
|
44
45
|
it "returns correct Content-Type header" do
|
45
|
-
@response.headers["Content-Type"].must_equal "text/html"
|
46
|
+
_(@response.headers["Content-Type"]).must_equal "text/html"
|
46
47
|
end
|
47
48
|
|
48
49
|
it "returns an ETag header" do
|
49
|
-
@response.headers["ETag"].wont_be_nil
|
50
|
+
_(@response.headers["ETag"]).wont_be_nil
|
50
51
|
end
|
51
52
|
|
52
53
|
it "returns correct body" do
|
53
|
-
@response.body.must_match %r{<p>Home Page</p>}
|
54
|
+
_(@response.body).must_match %r{<p>Home Page</p>}
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
@@ -61,21 +62,21 @@ describe "when handling requests" do
|
|
61
62
|
@response = @request.get("/not/a/page")
|
62
63
|
end
|
63
64
|
|
64
|
-
it "returns status
|
65
|
-
@response.status.must_equal 404
|
65
|
+
it "returns status 404" do
|
66
|
+
_(@response.status).must_equal 404
|
66
67
|
end
|
67
68
|
|
68
69
|
it "returns correct Content-Length header" do
|
69
|
-
@response.original_headers["Content-Length"].must_equal "142"
|
70
|
+
_(@response.original_headers["Content-Length"]).must_equal "142"
|
70
71
|
end
|
71
72
|
|
72
73
|
it "returns correct Content-Type header" do
|
73
|
-
@response.headers["Content-Type"].must_equal "text/html"
|
74
|
+
_(@response.headers["Content-Type"]).must_equal "text/html"
|
74
75
|
end
|
75
76
|
|
76
77
|
it "returns correct body" do
|
77
78
|
expected = %r{<!DOCTYPE html>.*<p>404: Not Found</p>}m
|
78
|
-
@response.body.must_match expected
|
79
|
+
_(@response.body).must_match expected
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
@@ -86,7 +87,7 @@ describe "when handling requests" do
|
|
86
87
|
@custom_404 = File.join(sourcedir, "404.html")
|
87
88
|
File.open(@custom_404, "w") {|f| f.print "Custom 404" }
|
88
89
|
|
89
|
-
app = get_app(:
|
90
|
+
app = get_app(source: sourcedir, destination: @destdir)
|
90
91
|
request = Rack::MockRequest.new(app)
|
91
92
|
@response = request.get("/not/a/page")
|
92
93
|
end
|
@@ -96,15 +97,15 @@ describe "when handling requests" do
|
|
96
97
|
end
|
97
98
|
|
98
99
|
it "returns correct Content-Length header" do
|
99
|
-
@response.original_headers["Content-Length"].must_equal "10"
|
100
|
+
_(@response.original_headers["Content-Length"]).must_equal "10"
|
100
101
|
end
|
101
102
|
|
102
103
|
it "returns correct Content-Type header" do
|
103
|
-
@response.headers["Content-Type"].must_equal "text/html"
|
104
|
+
_(@response.headers["Content-Type"]).must_equal "text/html"
|
104
105
|
end
|
105
106
|
|
106
107
|
it "returns correct body" do
|
107
|
-
@response.body.must_equal "Custom 404"
|
108
|
+
_(@response.body).must_equal "Custom 404"
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
@@ -116,19 +117,19 @@ describe "when handling requests" do
|
|
116
117
|
end
|
117
118
|
|
118
119
|
it "returns status 200" do
|
119
|
-
@response.status.must_equal 200
|
120
|
+
_(@response.status).must_equal 200
|
120
121
|
end
|
121
122
|
|
122
123
|
it "returns correct Content-Type header" do
|
123
|
-
@response.headers["Content-Type"].must_equal "text/html"
|
124
|
+
_(@response.headers["Content-Type"]).must_equal "text/html"
|
124
125
|
end
|
125
126
|
|
126
127
|
it "returns correct Content-Length header" do
|
127
|
-
@response.original_headers["Content-Length"].must_equal "19"
|
128
|
+
_(@response.original_headers["Content-Length"]).must_equal "19"
|
128
129
|
end
|
129
130
|
|
130
131
|
it "returns correct body" do
|
131
|
-
@response.body.must_match %r{<p>A Blog Post</p>}
|
132
|
+
_(@response.body).must_match %r{<p>A Blog Post</p>}
|
132
133
|
end
|
133
134
|
end
|
134
135
|
|
@@ -140,12 +141,12 @@ describe "when handling requests" do
|
|
140
141
|
end
|
141
142
|
|
142
143
|
it "returns status 200" do
|
143
|
-
@response.status.must_equal 200
|
144
|
+
_(@response.status).must_equal 200
|
144
145
|
end
|
145
146
|
|
146
147
|
it "returns Content-Type 'application/octet-stream'" do
|
147
148
|
type = @response.headers["Content-Type"]
|
148
|
-
type.must_equal "application/octet-stream"
|
149
|
+
_(type).must_equal "application/octet-stream"
|
149
150
|
end
|
150
151
|
end
|
151
152
|
|
@@ -154,12 +155,12 @@ describe "when handling requests" do
|
|
154
155
|
|
155
156
|
it "returns correct Content-Type for *.css" do
|
156
157
|
type = @request.get("/css/test.css").headers["Content-Type"]
|
157
|
-
type.must_equal "text/css"
|
158
|
+
_(type).must_equal "text/css"
|
158
159
|
end
|
159
160
|
|
160
161
|
it "returns correct Content-Type for *.min.js" do
|
161
162
|
type = @request.get("/js/test.min.js").headers["Content-Type"]
|
162
|
-
type.must_equal "application/javascript"
|
163
|
+
_(type).must_equal "application/javascript"
|
163
164
|
end
|
164
165
|
end
|
165
166
|
|
@@ -167,11 +168,11 @@ describe "when handling requests" do
|
|
167
168
|
describe "when asked for partially matching paths" do
|
168
169
|
|
169
170
|
it "returns status 404 for path 1" do
|
170
|
-
@request.get("/2015/10/05/hello").status.must_equal 404
|
171
|
+
_(@request.get("/2015/10/05/hello").status).must_equal 404
|
171
172
|
end
|
172
173
|
|
173
174
|
it "returns status 404 for path 2" do
|
174
|
-
@request.get("/10/05/hello-world.html").status.must_equal 404
|
175
|
+
_(@request.get("/10/05/hello-world.html").status).must_equal 404
|
175
176
|
end
|
176
177
|
end
|
177
178
|
|
@@ -182,8 +183,8 @@ describe "when handling requests" do
|
|
182
183
|
filename = File.join(@destdir, "/../_site/index.html")
|
183
184
|
assert File.exist?(filename)
|
184
185
|
|
185
|
-
|
186
|
-
|
186
|
+
response = @request.get("/../_site/index.html")
|
187
|
+
_(response.status).must_equal 404
|
187
188
|
end
|
188
189
|
end
|
189
190
|
|
@@ -191,23 +192,24 @@ describe "when handling requests" do
|
|
191
192
|
describe "when a directory is requested" do
|
192
193
|
|
193
194
|
it "redirects to 'directory/' for 'directory' with index.html" do
|
194
|
-
@request.get("/dir-with-index").status.must_equal 301
|
195
|
+
_(@request.get("/dir-with-index").status).must_equal 301
|
195
196
|
end
|
196
197
|
|
197
198
|
it "returns status 200 for 'directory/' with index.html" do
|
198
|
-
@request.get("/dir-with-index/").status.must_equal 200
|
199
|
+
_(@request.get("/dir-with-index/").status).must_equal 200
|
199
200
|
end
|
200
201
|
|
201
202
|
it "returns correct body for 'directory/' with index.html" do
|
202
|
-
@request.get("/dir-with-index/").body
|
203
|
+
response_body = @request.get("/dir-with-index/").body
|
204
|
+
_(response_body).must_match %r{<p>Index of dir-with-index/</p>}
|
203
205
|
end
|
204
206
|
|
205
207
|
it "returns status 404 for 'directory' without index.html" do
|
206
|
-
@request.get("/dir-without-index").status.must_equal 404
|
208
|
+
_(@request.get("/dir-without-index").status).must_equal 404
|
207
209
|
end
|
208
210
|
|
209
211
|
it "returns status 404 for 'directory/' without index.html" do
|
210
|
-
@request.get("/dir-without-index/").status.must_equal 404
|
212
|
+
_(@request.get("/dir-without-index/").status).must_equal 404
|
211
213
|
end
|
212
214
|
end
|
213
215
|
|
@@ -219,20 +221,20 @@ describe "when handling requests" do
|
|
219
221
|
end
|
220
222
|
|
221
223
|
it "returns status 301" do
|
222
|
-
@response.status.must_equal 301
|
224
|
+
_(@response.status).must_equal 301
|
223
225
|
end
|
224
226
|
|
225
227
|
it "returns correct Location header" do
|
226
|
-
@response.headers["Location"].must_equal "/dir-with-index/"
|
228
|
+
_(@response.headers["Location"]).must_equal "/dir-with-index/"
|
227
229
|
end
|
228
230
|
|
229
231
|
it "returns a Cache-Control header" do
|
230
|
-
@response.headers["Cache-Control"].wont_be_nil
|
232
|
+
_(@response.headers["Cache-Control"]).wont_be_nil
|
231
233
|
end
|
232
234
|
|
233
235
|
it "returns correct body" do
|
234
236
|
expected = %r{<!DOCTYPE html>.*<a href="/dir-with-index/">}m
|
235
|
-
@request.get("/dir-with-index").body.must_match expected
|
237
|
+
_(@request.get("/dir-with-index").body).must_match expected
|
236
238
|
end
|
237
239
|
end
|
238
240
|
|
@@ -245,11 +247,11 @@ describe "when handling requests" do
|
|
245
247
|
|
246
248
|
it "returns correct body" do
|
247
249
|
response_body = @response.body.force_encoding("UTF-8")
|
248
|
-
response_body.must_match %r{<p>¡Buenos días!</p>}
|
250
|
+
_(response_body).must_match %r{<p>¡Buenos días!</p>}
|
249
251
|
end
|
250
252
|
|
251
253
|
it "returns the bytesize as Content-Length header" do
|
252
|
-
@response.original_headers["Content-Length"].must_equal "23"
|
254
|
+
_(@response.original_headers["Content-Length"]).must_equal "23"
|
253
255
|
end
|
254
256
|
end
|
255
257
|
|
@@ -262,11 +264,11 @@ describe "when handling requests" do
|
|
262
264
|
|
263
265
|
it "returns correct body" do
|
264
266
|
expected = "File\r\nwith\r\nCRLF\r\nnewlines\r\n"
|
265
|
-
@response.body.must_equal expected
|
267
|
+
_(@response.body).must_equal expected
|
266
268
|
end
|
267
269
|
|
268
270
|
it "returns the bytesize as Content-Length header" do
|
269
|
-
@response.original_headers["Content-Length"].must_equal "28"
|
271
|
+
_(@response.original_headers["Content-Length"]).must_equal "28"
|
270
272
|
end
|
271
273
|
end
|
272
274
|
|
@@ -274,18 +276,18 @@ describe "when handling requests" do
|
|
274
276
|
describe "when URL contains special characters" do
|
275
277
|
|
276
278
|
it "returns status 200 for URL with escapes" do
|
277
|
-
|
278
|
-
|
279
|
+
response = @request.get("%2F2015%2F11%2F05%2Fhello-world.html")
|
280
|
+
_(response.status).must_equal 200
|
279
281
|
end
|
280
282
|
|
281
283
|
it "returns status 200 for resource name with blank" do
|
282
|
-
|
283
|
-
|
284
|
+
response = @request.get("with%20blank.html")
|
285
|
+
_(response.status).must_equal 200
|
284
286
|
end
|
285
287
|
|
286
288
|
it "returns status 200 for resource name with plus" do
|
287
|
-
|
288
|
-
|
289
|
+
response = @request.get("with+plus.html")
|
290
|
+
_(response.status).must_equal 200
|
289
291
|
end
|
290
292
|
end
|
291
293
|
|
@@ -303,20 +305,20 @@ describe "when handling requests" do
|
|
303
305
|
end
|
304
306
|
|
305
307
|
it "returns correct status code for unchanged '/'" do
|
306
|
-
@request.get("/", @correct_etag).status.must_equal 304
|
308
|
+
_(@request.get("/", @correct_etag).status).must_equal 304
|
307
309
|
end
|
308
310
|
|
309
311
|
it "does not return a Content-Length header for unchanged '/'" do
|
310
312
|
response = @request.get("/", @correct_etag)
|
311
|
-
response.original_headers["Content-Length"].must_be_nil
|
313
|
+
_(response.original_headers["Content-Length"]).must_be_nil
|
312
314
|
end
|
313
315
|
|
314
316
|
it "returns correct status code for changed '/'" do
|
315
|
-
@request.get("/", @other_etag).status.must_equal 200
|
317
|
+
_(@request.get("/", @other_etag).status).must_equal 200
|
316
318
|
end
|
317
319
|
|
318
320
|
it "returns correct status code for 404" do
|
319
|
-
@request.get("/not/a/page", @other_etag).status.must_equal 404
|
321
|
+
_(@request.get("/not/a/page", @other_etag).status).must_equal 404
|
320
322
|
end
|
321
323
|
end
|
322
324
|
|
@@ -324,15 +326,15 @@ describe "when handling requests" do
|
|
324
326
|
describe "when handling HEAD requests" do
|
325
327
|
|
326
328
|
it "returns status 200 for '/'" do
|
327
|
-
@request.head("/").status.must_equal 200
|
329
|
+
_(@request.head("/").status).must_equal 200
|
328
330
|
end
|
329
331
|
|
330
332
|
it "returns correct Content-Length header for '/'" do
|
331
|
-
@request.head("/").original_headers["Content-Length"].must_equal "17"
|
333
|
+
_(@request.head("/").original_headers["Content-Length"]).must_equal "17"
|
332
334
|
end
|
333
335
|
|
334
336
|
it "does not return a body" do
|
335
|
-
@request.head("/").body.must_equal ""
|
337
|
+
_(@request.head("/").body).must_equal ""
|
336
338
|
end
|
337
339
|
end
|
338
340
|
|
@@ -340,36 +342,41 @@ describe "when handling requests" do
|
|
340
342
|
describe "when handling OPTIONS requests" do
|
341
343
|
|
342
344
|
it "returns status 200" do
|
343
|
-
@request.options("/").status.must_equal 200
|
345
|
+
_(@request.options("/").status).must_equal 200
|
344
346
|
end
|
345
347
|
|
346
348
|
it "returns correct Allow header" do
|
347
|
-
@request.options("/").original_headers["Allow"]
|
349
|
+
response_allow_header = @request.options("/").original_headers["Allow"]
|
350
|
+
_(response_allow_header).must_equal "GET,HEAD,OPTIONS"
|
348
351
|
end
|
349
352
|
|
350
353
|
it "does not return a body" do
|
351
|
-
@request.options("/").body.must_equal ""
|
354
|
+
_(@request.options("/").body).must_equal ""
|
352
355
|
end
|
353
356
|
|
354
357
|
it "returns 404 for nonexistent resource" do
|
355
|
-
@request.options("/not/a/page").status.must_equal 404
|
356
|
-
@request.options("/not/a/page").body.must_match %r{<p>404: Not Found</p>}
|
358
|
+
_(@request.options("/not/a/page").status).must_equal 404
|
359
|
+
_(@request.options("/not/a/page").body).must_match %r{<p>404: Not Found</p>}
|
357
360
|
end
|
358
361
|
end
|
359
362
|
|
360
363
|
|
361
|
-
describe "when handling POST, PUT, DELETE, and other requests" do
|
364
|
+
describe "when handling POST, PUT, DELETE, and other not allowed requests" do
|
362
365
|
|
363
366
|
it "returns status 405" do
|
364
|
-
@request.post("/").status.must_equal 405
|
365
|
-
@request.put("/").status.must_equal 405
|
366
|
-
@request.delete("/").status.must_equal 405
|
367
|
-
@request.request("OTHER", "/").status.must_equal 405
|
367
|
+
_(@request.post("/").status).must_equal 405
|
368
|
+
_(@request.put("/").status).must_equal 405
|
369
|
+
_(@request.delete("/").status).must_equal 405
|
370
|
+
_(@request.request("OTHER", "/").status).must_equal 405
|
368
371
|
end
|
369
372
|
|
370
373
|
it "returns correct body" do
|
371
374
|
expected = %r{<!DOCTYPE html>.*<p>405: Method Not Allowed</p>}m
|
372
|
-
@request.post("/").body.must_match expected
|
375
|
+
_(@request.post("/").body).must_match expected
|
376
|
+
end
|
377
|
+
|
378
|
+
it "returns correct Content-Length header" do
|
379
|
+
_(@request.post("/").original_headers["Content-Length"]).must_equal "151"
|
373
380
|
end
|
374
381
|
end
|
375
382
|
end
|
data/test/test_router.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "helper"
|
2
4
|
|
3
5
|
|
@@ -17,6 +19,10 @@ describe Lanyon::Router do
|
|
17
19
|
dir-with-index/index.html
|
18
20
|
dir-without-index/page.html
|
19
21
|
dir1/dir2/dir3/index.html
|
22
|
+
foo
|
23
|
+
foo.html
|
24
|
+
bar.html
|
25
|
+
bar/index.html
|
20
26
|
]
|
21
27
|
|
22
28
|
files.each do |path|
|
@@ -37,44 +43,78 @@ describe Lanyon::Router do
|
|
37
43
|
|
38
44
|
it "returns path for '/'" do
|
39
45
|
filename = File.join(@sitedir, "index.html")
|
40
|
-
@router.endpoint("/").must_equal filename
|
46
|
+
_(@router.endpoint("/")).must_equal filename
|
41
47
|
end
|
42
48
|
|
43
49
|
it "returns existing path" do
|
44
50
|
filename = File.join(@sitedir, "page.html")
|
45
|
-
@router.endpoint("/page.html").must_equal filename
|
51
|
+
_(@router.endpoint("/page.html")).must_equal filename
|
46
52
|
end
|
47
53
|
|
48
54
|
it "returns existing path for resource without extension" do
|
49
55
|
filename = File.join(@sitedir, "README")
|
50
|
-
@router.endpoint("/README").must_equal filename
|
56
|
+
_(@router.endpoint("/README")).must_equal filename
|
51
57
|
end
|
52
58
|
|
53
59
|
it "returns :not_found for non-existent path" do
|
54
|
-
@router.endpoint("/not-a-page.html").must_equal :not_found
|
60
|
+
_(@router.endpoint("/not-a-page.html")).must_equal :not_found
|
55
61
|
end
|
56
62
|
|
57
63
|
it "returns :not_found for partially matching paths" do
|
58
|
-
@router.endpoint("/dir1/dir2/").must_equal :not_found
|
59
|
-
@router.endpoint("/dir2/dir3").must_equal :not_found
|
60
|
-
@router.endpoint("ir1/di").must_equal :not_found
|
64
|
+
_(@router.endpoint("/dir1/dir2/")).must_equal :not_found
|
65
|
+
_(@router.endpoint("/dir2/dir3")).must_equal :not_found
|
66
|
+
_(@router.endpoint("ir1/di")).must_equal :not_found
|
61
67
|
end
|
62
68
|
|
63
69
|
it "returns path for '/path/to/dir/' with index" do
|
64
70
|
filename = File.join(@sitedir, "dir-with-index/index.html")
|
65
|
-
@router.endpoint("/dir-with-index/").must_equal filename
|
71
|
+
_(@router.endpoint("/dir-with-index/")).must_equal filename
|
66
72
|
end
|
67
73
|
|
68
74
|
it "returns :must_redirect for '/path/to/dir' with index" do
|
69
|
-
@router.endpoint("/dir-with-index").must_equal :must_redirect
|
75
|
+
_(@router.endpoint("/dir-with-index")).must_equal :must_redirect
|
70
76
|
end
|
71
77
|
|
72
78
|
it "returns :not_found for '/path/to/dir/' without index" do
|
73
|
-
@router.endpoint("/dir-without-index/").must_equal :not_found
|
79
|
+
_(@router.endpoint("/dir-without-index/")).must_equal :not_found
|
74
80
|
end
|
75
81
|
|
76
82
|
it "returns :not_found for '/path/to/dir' without index" do
|
77
|
-
@router.endpoint("/dir-without-index").must_equal :not_found
|
83
|
+
_(@router.endpoint("/dir-without-index")).must_equal :not_found
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
describe "when automatically adding .html extension" do
|
89
|
+
|
90
|
+
it "returns existing path" do
|
91
|
+
filename = File.join(@sitedir, "page.html")
|
92
|
+
_(@router.endpoint("/page")).must_equal filename
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "when both `foo' and `foo.html' exist" do
|
96
|
+
|
97
|
+
it "returns `foo' and not `foo.html' when asked for `foo'" do
|
98
|
+
filename = File.join(@sitedir, "foo")
|
99
|
+
_(@router.endpoint("/foo")).must_equal filename
|
100
|
+
end
|
101
|
+
|
102
|
+
it "can also serve `foo.html'" do
|
103
|
+
filename = File.join(@sitedir, "foo.html")
|
104
|
+
_(@router.endpoint("/foo.html")).must_equal filename
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "when both `bar.html' and `bar/index.html' exist" do
|
109
|
+
|
110
|
+
it "returns :must_redirect and not `bar.html' when asked for `bar'" do
|
111
|
+
_(@router.endpoint("/bar")).must_equal :must_redirect
|
112
|
+
end
|
113
|
+
|
114
|
+
it "can also serve `bar.html'" do
|
115
|
+
filename = File.join(@sitedir, "bar.html")
|
116
|
+
_(@router.endpoint("/bar.html")).must_equal filename
|
117
|
+
end
|
78
118
|
end
|
79
119
|
end
|
80
120
|
|
@@ -83,27 +123,27 @@ describe Lanyon::Router do
|
|
83
123
|
|
84
124
|
it "discards leading '..' for existing path" do
|
85
125
|
filename = File.join(@sitedir, "page.html")
|
86
|
-
@router.endpoint("/../../page.html").must_equal filename
|
126
|
+
_(@router.endpoint("/../../page.html")).must_equal filename
|
87
127
|
end
|
88
128
|
|
89
129
|
it "allows safe directory traversal" do
|
90
130
|
filename = File.join(@sitedir, "index.html")
|
91
|
-
@router.endpoint("/dir1/../").must_equal filename
|
131
|
+
_(@router.endpoint("/dir1/../")).must_equal filename
|
92
132
|
end
|
93
133
|
|
94
134
|
it "returns :not_found for unsafe directory traversal 1" do
|
95
135
|
filename = File.join(@sitedir, "/../_site/page.html")
|
96
136
|
assert File.exist?(filename)
|
97
137
|
|
98
|
-
@router.endpoint("/../_site/page.html").must_equal :not_found
|
138
|
+
_(@router.endpoint("/../_site/page.html")).must_equal :not_found
|
99
139
|
end
|
100
140
|
|
101
141
|
it "returns :not_found for unsafe directory traversal 2" do
|
102
|
-
@router.endpoint("/%2E%2E/_site/").must_equal :not_found
|
142
|
+
_(@router.endpoint("/%2E%2E/_site/")).must_equal :not_found
|
103
143
|
end
|
104
144
|
|
105
145
|
it "returns :not_found for unsafe directory traversal 3" do
|
106
|
-
@router.endpoint("/dir1/../dir1/../../_site/").must_equal :not_found
|
146
|
+
_(@router.endpoint("/dir1/../dir1/../../_site/")).must_equal :not_found
|
107
147
|
end
|
108
148
|
end
|
109
149
|
|
@@ -113,7 +153,7 @@ describe Lanyon::Router do
|
|
113
153
|
describe "when 404.html does not exist" do
|
114
154
|
|
115
155
|
it "returns nil" do
|
116
|
-
@router.custom_404_body.must_be_nil
|
156
|
+
_(@router.custom_404_body).must_be_nil
|
117
157
|
end
|
118
158
|
end
|
119
159
|
|
@@ -129,7 +169,7 @@ describe Lanyon::Router do
|
|
129
169
|
end
|
130
170
|
|
131
171
|
it "returns correct body" do
|
132
|
-
@router.custom_404_body.must_equal "Custom 404"
|
172
|
+
_(@router.custom_404_body).must_equal "Custom 404"
|
133
173
|
end
|
134
174
|
end
|
135
175
|
end
|
@@ -139,14 +179,14 @@ describe Lanyon::Router do
|
|
139
179
|
|
140
180
|
it "strips trailing slash from root" do
|
141
181
|
router = Lanyon::Router.new(@sitedir + "/")
|
142
|
-
router.root.must_equal @sitedir
|
182
|
+
_(router.root).must_equal @sitedir
|
143
183
|
end
|
144
184
|
|
145
185
|
it "does not append a trailing slash to root" do
|
146
186
|
assert !@sitedir.end_with?("/")
|
147
187
|
|
148
188
|
router = Lanyon::Router.new(@sitedir)
|
149
|
-
router.root.must_equal @sitedir
|
189
|
+
_(router.root).must_equal @sitedir
|
150
190
|
end
|
151
191
|
end
|
152
192
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lanyon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcus Stollsteimer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -17,9 +17,6 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '2.0'
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '4.0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,9 +24,6 @@ dependencies:
|
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '2.0'
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '4.0'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: rack
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -51,33 +45,33 @@ dependencies:
|
|
51
45
|
- !ruby/object:Gem::Version
|
52
46
|
version: '3.0'
|
53
47
|
- !ruby/object:Gem::Dependency
|
54
|
-
name:
|
48
|
+
name: minitest
|
55
49
|
requirement: !ruby/object:Gem::Requirement
|
56
50
|
requirements:
|
57
51
|
- - "~>"
|
58
52
|
- !ruby/object:Gem::Version
|
59
|
-
version: '
|
53
|
+
version: '5.8'
|
60
54
|
type: :development
|
61
55
|
prerelease: false
|
62
56
|
version_requirements: !ruby/object:Gem::Requirement
|
63
57
|
requirements:
|
64
58
|
- - "~>"
|
65
59
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
60
|
+
version: '5.8'
|
67
61
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
62
|
+
name: rake
|
69
63
|
requirement: !ruby/object:Gem::Requirement
|
70
64
|
requirements:
|
71
65
|
- - "~>"
|
72
66
|
- !ruby/object:Gem::Version
|
73
|
-
version: '
|
67
|
+
version: '13.0'
|
74
68
|
type: :development
|
75
69
|
prerelease: false
|
76
70
|
version_requirements: !ruby/object:Gem::Requirement
|
77
71
|
requirements:
|
78
72
|
- - "~>"
|
79
73
|
- !ruby/object:Gem::Version
|
80
|
-
version: '
|
74
|
+
version: '13.0'
|
81
75
|
description: Lanyon is a good friend of Jekyll, the static site generator, and transforms
|
82
76
|
your website into a Rack application.
|
83
77
|
email: sto.mar@web.de
|
@@ -146,8 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
140
|
- !ruby/object:Gem::Version
|
147
141
|
version: '0'
|
148
142
|
requirements: []
|
149
|
-
|
150
|
-
rubygems_version: 2.5.1
|
143
|
+
rubygems_version: 3.3.3
|
151
144
|
signing_key:
|
152
145
|
specification_version: 4
|
153
146
|
summary: Lanyon serves your Jekyll site as a Rack application.
|