impression 0.1 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|