impression 0.1 → 0.5
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/.github/FUNDING.yml +1 -0
- data/.github/workflows/test.yml +32 -0
- data/CHANGELOG.md +23 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +63 -32
- data/README.md +44 -2
- data/Rakefile +10 -0
- data/examples/markdown/_assets/style.css +98 -0
- data/examples/markdown/app.rb +11 -5
- data/examples/markdown/docs/tutorial.md +15 -0
- data/impression.gemspec +11 -7
- data/lib/impression/app.rb +9 -0
- data/lib/impression/file_tree.rb +124 -0
- data/lib/impression/file_watcher.rb +50 -0
- data/lib/impression/jamstack.rb +179 -0
- data/lib/impression/request_extensions/responses.rb +48 -0
- data/lib/impression/request_extensions/routing.rb +52 -0
- data/lib/impression/request_extensions.rb +8 -2
- data/lib/impression/resource.rb +168 -0
- data/lib/impression/version.rb +1 -1
- data/lib/impression.rb +8 -0
- data/test/helper.rb +94 -0
- data/test/jamstack/_layouts/article.rb +9 -0
- data/test/jamstack/_layouts/default.rb +12 -0
- data/test/jamstack/articles/2008-06-14-manu.md +6 -0
- data/test/jamstack/articles/2009-06-12-noatche.md +6 -0
- data/test/jamstack/articles/a.md +6 -0
- data/test/jamstack/assets/js/a.js +1 -0
- data/test/jamstack/bar.html +1 -0
- data/test/jamstack/baz/index.md +7 -0
- data/test/jamstack/foo.rb +7 -0
- data/test/jamstack/foobar.rb +10 -0
- data/test/jamstack/index.md +4 -0
- data/test/run.rb +5 -0
- data/test/static/bar/index.html +1 -0
- data/test/static/foo.html +1 -0
- data/test/static/index.html +1 -0
- data/test/static/js/a.js +1 -0
- data/test/test_app.rb +52 -0
- data/test/test_file_tree.rb +116 -0
- data/test/test_file_watcher.rb +57 -0
- data/test/test_jamstack.rb +263 -0
- data/test/test_resource.rb +201 -0
- metadata +57 -35
- data/lib/impression/pages.rb +0 -120
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8db17f3627f0b8de2ed13a81effd9689f8a292b0861104c276d343bf5ec23e8f
|
|
4
|
+
data.tar.gz: 79cc272aed0503e1514723815f7019002c780a890995ef7c6f2d4718d9704000
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 46112700200e6018c10b9a84b3a90184ce590e0da7369096a787467af4c84aba6578c043c1c9ad520cfa6da83638492def2c53b8cc9d51407d74695e3c12af4f
|
|
7
|
+
data.tar.gz: 94b1e171d6161bdd452ce27a6ee5effde4c9a1fdb2fd0247b72449fcb7048a8c1800dc616c6e291d56ea639dcec8a4d2d2dad5e9aa6865ccc0cb96cac4525688
|
data/.github/FUNDING.yml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
github: ciconia
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
build:
|
|
7
|
+
strategy:
|
|
8
|
+
fail-fast: false
|
|
9
|
+
matrix:
|
|
10
|
+
os: [ubuntu-latest, macos-latest]
|
|
11
|
+
ruby: ['2.7', '3.0', '3.1', 'head']
|
|
12
|
+
|
|
13
|
+
name: >-
|
|
14
|
+
${{matrix.os}}, ${{matrix.ruby}}
|
|
15
|
+
|
|
16
|
+
runs-on: ${{matrix.os}}
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
POLYPHONY_USE_LIBEV: "1"
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Setup machine
|
|
23
|
+
uses: actions/checkout@v1
|
|
24
|
+
- name: Setup Ruby and install deps
|
|
25
|
+
uses: ruby/setup-ruby@v1
|
|
26
|
+
with:
|
|
27
|
+
ruby-version: ${{matrix.ruby}}
|
|
28
|
+
bundler-cache: true # 'bundle install' and cache
|
|
29
|
+
cache-version: 1
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: bundle exec rake test
|
data/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 0.5 2022-01-20
|
|
2
|
+
|
|
3
|
+
- Pass resource and request to rendered templates (#8)
|
|
4
|
+
- Implement Jamstack#page_list method (#7)
|
|
5
|
+
|
|
6
|
+
# 0.4 2022-01-19
|
|
7
|
+
|
|
8
|
+
- Remove deprecated Pages code (#6)
|
|
9
|
+
|
|
10
|
+
# 0.3 2022-01-19
|
|
11
|
+
|
|
12
|
+
- Implement basic Jamstack resource (#5)
|
|
13
|
+
- Add support for stock callable responses (#4)
|
|
14
|
+
- Make resource callable, rename `#respond` to `#callable` (#3)
|
|
15
|
+
|
|
16
|
+
## 0.2 2022-01-13
|
|
17
|
+
|
|
18
|
+
- Implement `FileTree` (#2)
|
|
19
|
+
- Rename `Resource#render` to `Resource#respond`
|
|
20
|
+
- Rewrite resource routing (#1)
|
|
21
|
+
- Implement `Resource`
|
|
22
|
+
|
|
23
|
+
## 0.1 2021-02-24
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,66 +1,97 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
impression (0.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
polyphony (~> 0.
|
|
8
|
-
|
|
9
|
-
tipi (~> 0.
|
|
4
|
+
impression (0.5)
|
|
5
|
+
modulation (~> 1.1)
|
|
6
|
+
papercraft (~> 0.14)
|
|
7
|
+
polyphony (~> 0.73.1)
|
|
8
|
+
qeweney (~> 0.15)
|
|
9
|
+
tipi (~> 0.45)
|
|
10
10
|
|
|
11
11
|
GEM
|
|
12
12
|
remote: https://rubygems.org/
|
|
13
13
|
specs:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
docile (1.
|
|
14
|
+
acme-client (2.0.9)
|
|
15
|
+
faraday (>= 0.17, < 2.0.0)
|
|
16
|
+
docile (1.4.0)
|
|
17
17
|
escape_utils (1.2.1)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
ever (0.1)
|
|
19
|
+
extralite (1.11)
|
|
20
|
+
faraday (1.9.3)
|
|
21
|
+
faraday-em_http (~> 1.0)
|
|
22
|
+
faraday-em_synchrony (~> 1.0)
|
|
23
|
+
faraday-excon (~> 1.1)
|
|
24
|
+
faraday-httpclient (~> 1.0)
|
|
25
|
+
faraday-multipart (~> 1.0)
|
|
26
|
+
faraday-net_http (~> 1.0)
|
|
27
|
+
faraday-net_http_persistent (~> 1.0)
|
|
28
|
+
faraday-patron (~> 1.0)
|
|
29
|
+
faraday-rack (~> 1.0)
|
|
30
|
+
faraday-retry (~> 1.0)
|
|
31
|
+
ruby2_keywords (>= 0.0.4)
|
|
32
|
+
faraday-em_http (1.0.0)
|
|
33
|
+
faraday-em_synchrony (1.0.0)
|
|
34
|
+
faraday-excon (1.1.0)
|
|
35
|
+
faraday-httpclient (1.0.1)
|
|
36
|
+
faraday-multipart (1.0.3)
|
|
37
|
+
multipart-post (>= 1.2, < 3)
|
|
38
|
+
faraday-net_http (1.0.1)
|
|
39
|
+
faraday-net_http_persistent (1.2.0)
|
|
40
|
+
faraday-patron (1.0.0)
|
|
41
|
+
faraday-rack (1.0.0)
|
|
42
|
+
faraday-retry (1.0.3)
|
|
43
|
+
h1p (0.2)
|
|
44
|
+
http-2 (0.11.0)
|
|
45
|
+
json (2.6.1)
|
|
46
|
+
kramdown (2.3.1)
|
|
22
47
|
rexml
|
|
23
48
|
kramdown-parser-gfm (1.1.0)
|
|
24
49
|
kramdown (~> 2.0)
|
|
50
|
+
localhost (1.1.9)
|
|
25
51
|
minitest (5.11.3)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
52
|
+
modulation (1.1)
|
|
53
|
+
msgpack (1.4.3)
|
|
54
|
+
multipart-post (2.1.1)
|
|
55
|
+
papercraft (0.14)
|
|
56
|
+
escape_utils (= 1.2.1)
|
|
57
|
+
kramdown (~> 2.3.0)
|
|
58
|
+
kramdown-parser-gfm (~> 1.1.0)
|
|
59
|
+
rouge (~> 3.26.0)
|
|
60
|
+
polyphony (0.73.1)
|
|
61
|
+
qeweney (0.15)
|
|
34
62
|
escape_utils (~> 1.2.1)
|
|
35
63
|
rack (2.2.3)
|
|
36
64
|
rake (12.3.3)
|
|
37
|
-
rexml (3.2.
|
|
38
|
-
rouge (3.26.
|
|
39
|
-
|
|
65
|
+
rexml (3.2.5)
|
|
66
|
+
rouge (3.26.1)
|
|
67
|
+
ruby2_keywords (0.0.5)
|
|
40
68
|
simplecov (0.17.1)
|
|
41
69
|
docile (~> 1.1)
|
|
42
70
|
json (>= 1.8, < 3)
|
|
43
71
|
simplecov-html (~> 0.10.0)
|
|
44
72
|
simplecov-html (0.10.2)
|
|
45
|
-
tipi (0.
|
|
46
|
-
|
|
47
|
-
|
|
73
|
+
tipi (0.45)
|
|
74
|
+
acme-client (~> 2.0.8)
|
|
75
|
+
ever (~> 0.1)
|
|
76
|
+
extralite (~> 1.2)
|
|
77
|
+
h1p (~> 0.2)
|
|
78
|
+
http-2 (~> 0.11)
|
|
79
|
+
localhost (~> 1.1.4)
|
|
48
80
|
msgpack (~> 1.4.2)
|
|
49
|
-
polyphony (~> 0.
|
|
50
|
-
qeweney (~> 0.
|
|
81
|
+
polyphony (~> 0.71)
|
|
82
|
+
qeweney (~> 0.14)
|
|
51
83
|
rack (>= 2.0.8, < 2.3.0)
|
|
52
84
|
websocket (~> 1.2.8)
|
|
53
85
|
websocket (1.2.9)
|
|
54
86
|
|
|
55
87
|
PLATFORMS
|
|
56
|
-
|
|
88
|
+
x86_64-linux
|
|
57
89
|
|
|
58
90
|
DEPENDENCIES
|
|
59
91
|
impression!
|
|
60
92
|
minitest (~> 5.11.3)
|
|
61
|
-
minitest-reporters (~> 1.4.2)
|
|
62
93
|
rake (~> 12.3.3)
|
|
63
94
|
simplecov (~> 0.17.1)
|
|
64
95
|
|
|
65
96
|
BUNDLED WITH
|
|
66
|
-
2.
|
|
97
|
+
2.3.3
|
data/README.md
CHANGED
|
@@ -1,2 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
Impression
|
|
3
|
+
</h1>
|
|
4
|
+
|
|
5
|
+
<h4 align="center">A modern web framework for Ruby</h4>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="http://rubygems.org/gems/impression">
|
|
9
|
+
<img src="https://badge.fury.io/rb/impression.svg" alt="Ruby gem">
|
|
10
|
+
</a>
|
|
11
|
+
<a href="https://github.com/digital-fabric/impression/actions?query=workflow%3ATests">
|
|
12
|
+
<img src="https://github.com/digital-fabric/impression/workflows/Tests/badge.svg" alt="Tests">
|
|
13
|
+
</a>
|
|
14
|
+
<a href="https://github.com/digital-fabric/impression/blob/master/LICENSE">
|
|
15
|
+
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License">
|
|
16
|
+
</a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
## What is Impression
|
|
20
|
+
|
|
21
|
+
> Impression is still in a very early stage of development. Things might not
|
|
22
|
+
> correctly, or not at all.
|
|
23
|
+
|
|
24
|
+
Impression is a modern web framework for Ruby. Unlike other web framework,
|
|
25
|
+
Impression does not impose any rigid structure or paradigm, but instead provides
|
|
26
|
+
a set of tools letting you build any kind of web app, by freely mixing different
|
|
27
|
+
kinds of web resources, be they static files, structured templates, Jamstack
|
|
28
|
+
sites, or dynamic APIs.
|
|
29
|
+
|
|
30
|
+
In Impression, resources can be composed into a hierarchical tree, allowing
|
|
31
|
+
combining of multiple web apps, or web subsystems, into a single URL hierarchy.
|
|
32
|
+
|
|
33
|
+
Impression is made for running on top of
|
|
34
|
+
[Tipi](https://github.com/digital-fabric/tipi), a new all-in-one web server for
|
|
35
|
+
Ruby.
|
|
36
|
+
|
|
37
|
+
## I want to know more
|
|
38
|
+
|
|
39
|
+
Further documentation is coming real soon (TM)...
|
|
40
|
+
|
|
41
|
+
## Contributing
|
|
42
|
+
|
|
43
|
+
Contributions in the form of issues, PRs or comments will be greatly
|
|
44
|
+
appreciated!
|
data/Rakefile
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
* {
|
|
2
|
+
border: 0;
|
|
3
|
+
font: inherit;
|
|
4
|
+
font-size: 100%;
|
|
5
|
+
vertical-align: baseline;
|
|
6
|
+
margin: 0;
|
|
7
|
+
padding: 0;
|
|
8
|
+
color: black;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
body {
|
|
12
|
+
font: normal 14px monospace;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
h1, h2 {
|
|
16
|
+
font-weight: bold;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
header {
|
|
20
|
+
margin-bottom: 20px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
a {
|
|
24
|
+
color: -webkit-link;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
li {
|
|
28
|
+
margin-left: 40px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
em {
|
|
32
|
+
font-style: italic;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
strong {
|
|
36
|
+
font-weight: bold;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
p, ul, ol {
|
|
40
|
+
margin: 20px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
pre {
|
|
44
|
+
margin-bottom: 20px;
|
|
45
|
+
padding: 20px 5px;
|
|
46
|
+
overflow-x: visible;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
pre code {
|
|
50
|
+
word-wrap: no;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
hr {
|
|
54
|
+
display: block;
|
|
55
|
+
margin-top: 0.5em;
|
|
56
|
+
margin-bottom: 0.5em;
|
|
57
|
+
margin-left: auto;
|
|
58
|
+
margin-right: auto;
|
|
59
|
+
border-style: inset;
|
|
60
|
+
border-width: 1px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#nav {
|
|
64
|
+
padding: 20px 5px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
#nav, #content, footer {
|
|
68
|
+
margin: 0 20px;
|
|
69
|
+
max-width: 580px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#nav h1 {
|
|
73
|
+
margin-bottom: 20px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
iframe {
|
|
77
|
+
margin: 20px;
|
|
78
|
+
max-width: 530px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#content img {
|
|
82
|
+
max-width: 100%;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#title {
|
|
86
|
+
margin-top: 40px;
|
|
87
|
+
font-weight: bold;
|
|
88
|
+
text-align: center;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#date {
|
|
92
|
+
display: block;
|
|
93
|
+
text-align: right;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
#webring {
|
|
97
|
+
padding-bottom: 10px;
|
|
98
|
+
}
|
data/examples/markdown/app.rb
CHANGED
|
@@ -11,13 +11,19 @@ opts = {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
puts "pid: #{Process.pid}"
|
|
14
|
-
puts 'Listening on port 4411...'
|
|
15
14
|
|
|
16
|
-
Tipi.
|
|
17
|
-
|
|
15
|
+
Tipi.full_service do |req|
|
|
16
|
+
req.route do
|
|
17
|
+
if req.host != 'noteflakes.com'
|
|
18
|
+
req.respond(nil, ':status' => Qeweney::Status::SERVICE_UNAVAILABLE)
|
|
19
|
+
stop_routing
|
|
20
|
+
end
|
|
21
|
+
req.on('assets') { req.serve_file(req.route_relative_path, base_path: File.join(__dir__, '_assets')) }
|
|
22
|
+
req.default { app.call(req) }
|
|
23
|
+
end
|
|
18
24
|
rescue Exception => e
|
|
19
|
-
p e
|
|
20
|
-
puts e.backtrace.join("\n")
|
|
25
|
+
p [req.path, e]
|
|
26
|
+
# puts e.backtrace.join("\n")
|
|
21
27
|
status = e.respond_to?(:http_status) ? e.http_status : 500
|
|
22
28
|
req.respond(e.inspect, ':status' => status)
|
|
23
29
|
end
|
data/impression.gemspec
CHANGED
|
@@ -10,7 +10,10 @@ Gem::Specification.new do |s|
|
|
|
10
10
|
s.files = `git ls-files`.split
|
|
11
11
|
s.homepage = 'http://github.com/digital-fabric/impression'
|
|
12
12
|
s.metadata = {
|
|
13
|
-
"source_code_uri" => "https://github.com/digital-fabric/impression"
|
|
13
|
+
"source_code_uri" => "https://github.com/digital-fabric/impression",
|
|
14
|
+
"documentation_uri" => "https://www.rubydoc.info/gems/impression",
|
|
15
|
+
"homepage_uri" => "https://github.com/digital-fabric/impression",
|
|
16
|
+
"changelog_uri" => "https://github.com/digital-fabric/impression/blob/master/CHANGELOG.md"
|
|
14
17
|
}
|
|
15
18
|
s.rdoc_options = ["--title", "impression", "--main", "README.md"]
|
|
16
19
|
s.extra_rdoc_files = ["README.md"]
|
|
@@ -19,15 +22,16 @@ Gem::Specification.new do |s|
|
|
|
19
22
|
|
|
20
23
|
# s.executables = ['impression']
|
|
21
24
|
|
|
22
|
-
s.add_runtime_dependency 'polyphony', '~>0.
|
|
23
|
-
s.add_runtime_dependency 'tipi', '~>0.
|
|
24
|
-
s.add_runtime_dependency '
|
|
25
|
-
|
|
26
|
-
s.add_runtime_dependency '
|
|
25
|
+
s.add_runtime_dependency 'polyphony', '~>0.73.1'
|
|
26
|
+
s.add_runtime_dependency 'tipi', '~>0.45'
|
|
27
|
+
s.add_runtime_dependency 'qeweney', '~>0.15'
|
|
28
|
+
|
|
29
|
+
# s.add_runtime_dependency 'rb-inotify', '~>0.10.1'
|
|
30
|
+
s.add_runtime_dependency 'papercraft', '~>0.14'
|
|
31
|
+
s.add_runtime_dependency 'modulation', '~>1.1'
|
|
27
32
|
|
|
28
33
|
|
|
29
34
|
s.add_development_dependency 'rake', '~>12.3.3'
|
|
30
35
|
s.add_development_dependency 'minitest', '~>5.11.3'
|
|
31
|
-
s.add_development_dependency 'minitest-reporters', '~>1.4.2'
|
|
32
36
|
s.add_development_dependency 'simplecov', '~>0.17.1'
|
|
33
37
|
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require_relative './resource'
|
|
5
|
+
|
|
6
|
+
module Impression
|
|
7
|
+
|
|
8
|
+
# `FileTree` implements a resource that maps to a static file hierarchy.
|
|
9
|
+
class FileTree < Resource
|
|
10
|
+
|
|
11
|
+
# Initializes a `FileTree` resource.
|
|
12
|
+
#
|
|
13
|
+
# @param directory [String] static directory path
|
|
14
|
+
# @return [void]
|
|
15
|
+
def initialize(directory:, **props)
|
|
16
|
+
super(**props)
|
|
17
|
+
@directory = directory
|
|
18
|
+
@path_info_cache = {}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Responds to a request.
|
|
22
|
+
#
|
|
23
|
+
# @param req [Qeweney::Request] request
|
|
24
|
+
# @return [void]
|
|
25
|
+
def call(req)
|
|
26
|
+
path_info = get_path_info(req.resource_relative_path)
|
|
27
|
+
render_from_path_info(req, path_info)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# Renders a response from the given response kind and path.
|
|
33
|
+
#
|
|
34
|
+
# @param req [Qeweney::Request] request
|
|
35
|
+
# @param kind [Symbol] path kind (`:not_found` or `:file`)
|
|
36
|
+
# @param path [String, nil] file path
|
|
37
|
+
def render_from_path_info(req, path_info)
|
|
38
|
+
case path_info[:kind]
|
|
39
|
+
when :not_found
|
|
40
|
+
req.respond(nil, ':status' => Qeweney::Status::NOT_FOUND)
|
|
41
|
+
when :file
|
|
42
|
+
render_file(req, path_info)
|
|
43
|
+
else
|
|
44
|
+
raise "Invalid path info kind #{kind.inspect}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# Renders a file response for the given request and the given path info.
|
|
51
|
+
#
|
|
52
|
+
# @param req [Qeweney::Request] request
|
|
53
|
+
# @param path_info [Hash] path info
|
|
54
|
+
# @return [void]
|
|
55
|
+
def render_file(req, path_info)
|
|
56
|
+
req.serve_file(path_info[:path])
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Returns the path info for the given relative path.
|
|
60
|
+
#
|
|
61
|
+
# @param path [String] relative path
|
|
62
|
+
# @return [Hash] path info
|
|
63
|
+
def get_path_info(path)
|
|
64
|
+
@path_info_cache[path] ||= calculate_path_info(path)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Calculates the path info for the given relative path.
|
|
68
|
+
#
|
|
69
|
+
# @param path [String] relative path
|
|
70
|
+
# @param add_ext [bool] whether to add .html extension if not found
|
|
71
|
+
# @return [Hash] path info
|
|
72
|
+
def calculate_path_info(path)
|
|
73
|
+
full_path = File.join(@directory, path)
|
|
74
|
+
|
|
75
|
+
path_info(full_path) || search_path_info_with_extension(full_path) || { kind: :not_found }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Returns the path info for the given path. If the path refers to a file,
|
|
79
|
+
# returns a hash containing the file information. If the path refers to a
|
|
80
|
+
# directory, performs a search for an index file using #directory_path_info.
|
|
81
|
+
# Otherwise, returns nil.
|
|
82
|
+
#
|
|
83
|
+
# @param path [String] path
|
|
84
|
+
# @return [Hash, nil] path info
|
|
85
|
+
def path_info(path)
|
|
86
|
+
stat = File.stat(path) rescue nil
|
|
87
|
+
if !stat
|
|
88
|
+
nil
|
|
89
|
+
elsif stat.directory?
|
|
90
|
+
return directory_path_info(path)
|
|
91
|
+
else
|
|
92
|
+
return { kind: :file, path: path, ext: File.extname(path) }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Calculates the path info for a directory. If an index file exists, its
|
|
97
|
+
# path info is returned, otherwise, returns nil.
|
|
98
|
+
#
|
|
99
|
+
# @param path [String] directory path
|
|
100
|
+
# @return [Hash, nil] path info
|
|
101
|
+
def directory_path_info(path)
|
|
102
|
+
search_path_info_with_extension(File.join(path, 'index'))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Returns the supported path extensions for paths without extension.
|
|
106
|
+
#
|
|
107
|
+
# @return [Array] supported extensions
|
|
108
|
+
def supported_path_extensions
|
|
109
|
+
[:html]
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Searches for files with extensions for the given path.
|
|
113
|
+
#
|
|
114
|
+
# @param path [String] path
|
|
115
|
+
# @return [Hash, nil] path info
|
|
116
|
+
def search_path_info_with_extension(path)
|
|
117
|
+
supported_path_extensions.each do |ext|
|
|
118
|
+
info = path_info("#{path}.#{ext}")
|
|
119
|
+
return info if info
|
|
120
|
+
end
|
|
121
|
+
nil
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rb-inotify'
|
|
4
|
+
|
|
5
|
+
module Impression
|
|
6
|
+
class FileWatcher
|
|
7
|
+
def initialize(spec)
|
|
8
|
+
@notifier = INotify::Notifier.new
|
|
9
|
+
@buffer = []
|
|
10
|
+
setup(spec)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def setup(spec)
|
|
14
|
+
if File.file?(spec)
|
|
15
|
+
setup_single_file(spec)
|
|
16
|
+
elsif File.directory?(spec)
|
|
17
|
+
setup_directory(spec)
|
|
18
|
+
else
|
|
19
|
+
dir = File.dir_name(spec)
|
|
20
|
+
filename = File.basename(spec)
|
|
21
|
+
if dir =~ /\/\*\*$/
|
|
22
|
+
dir = File.dir_name(dir)
|
|
23
|
+
filename = "**/#{filename}"
|
|
24
|
+
end
|
|
25
|
+
setup_directory(dir, filename)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def setup_directory(dir)
|
|
30
|
+
@notifier.watch(dir, :moved_to, :create, :move, :attrib, :modify, :delete) do |event|
|
|
31
|
+
kind = event.flags.first
|
|
32
|
+
|
|
33
|
+
@buffer << [kind, event.absolute_name]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def each(&block)
|
|
38
|
+
@receiver = Fiber.current
|
|
39
|
+
io = @notifier.to_io
|
|
40
|
+
loop do
|
|
41
|
+
io.wait_readable
|
|
42
|
+
@notifier.process
|
|
43
|
+
next if @buffer.empty?
|
|
44
|
+
|
|
45
|
+
@buffer.each(&block)
|
|
46
|
+
@buffer.clear
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|