impression 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5a7e55ef9ff6c795a485a4b1e50456949932d923425ad447ada836ef2e69b0c
4
- data.tar.gz: 669f0781d30986542fb09aad0af058107a658281136ace716edfdefc18fefabb
3
+ metadata.gz: aaea11fcf3fcaab1902290a620d9cdb0fa5dfb11ae38c90335f80471629d652f
4
+ data.tar.gz: 9eaebd5c2a28856a568e583399c3ea6db8332e6c2aae6d570639505788203dc1
5
5
  SHA512:
6
- metadata.gz: 1cdbfd6167b1e1717e5a3fda6089c84bb0ed7c6d810b1dac9376a1cd81a38a473c097ba6dd6ecbd07c61145b86b5e10f13c8be02ac69c14c556ba6991f87e4f4
7
- data.tar.gz: cf2e071b60b5ed0aa0ab826d2721c55d15cabb7fa0f63e84d068f76eef9a39db68159d6a651ddf5371976c4703a72a910883e50becdd64ff365d4b955cb93192
6
+ metadata.gz: 145722a3828e039ed1a021c002cc0a551e66f78a300d869203f15d8c3df8c2d532d71d37674a7c11b1d995c39cb138a06040665a785e22581473843d28581a49
7
+ data.tar.gz: 9d179f895f2d819f1c63762099137dda5511614176c9e25df4aef7d735975fbda25167b5f3c3a94788f96c8b37ece7c2f42acc7b54dcaa38054863976f039ccf
@@ -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,8 @@
1
+ ## 0.2 2022-01-13
2
+
3
+ - Implement `FileTree` (#2)
4
+ - Rename `Resource#render` to `Resource#respond`
5
+ - Rewrite resource routing (#1)
6
+ - Implement `Resource`
7
+
8
+ ## 0.1 2021-02-24
data/Gemfile CHANGED
@@ -1,3 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ # %w{polyphony tipi qeweney rubyoshka}.each do |dep|
6
+ # dir = "../#{dep}"
7
+ # gem(dep, path: dir) if File.directory?(dir)
8
+ # end
data/Gemfile.lock CHANGED
@@ -1,53 +1,86 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- impression (0.1)
4
+ impression (0.2)
5
5
  kramdown (~> 2.3.0)
6
6
  kramdown-parser-gfm (~> 1.1.0)
7
- polyphony (~> 0.51.0)
7
+ papercraft (~> 0.12)
8
+ polyphony (~> 0.73.1)
9
+ qeweney (~> 0.15)
8
10
  rouge (~> 3.26.0)
9
- tipi (~> 0.37)
11
+ tipi (~> 0.45)
10
12
 
11
13
  GEM
12
14
  remote: https://rubygems.org/
13
15
  specs:
14
- ansi (1.5.0)
15
- builder (3.2.4)
16
- docile (1.3.5)
16
+ acme-client (2.0.9)
17
+ faraday (>= 0.17, < 2.0.0)
18
+ docile (1.4.0)
17
19
  escape_utils (1.2.1)
18
- http-2 (0.10.2)
19
- http_parser.rb (0.6.0)
20
- json (2.5.1)
21
- kramdown (2.3.0)
20
+ ever (0.1)
21
+ extralite (1.11)
22
+ faraday (1.9.3)
23
+ faraday-em_http (~> 1.0)
24
+ faraday-em_synchrony (~> 1.0)
25
+ faraday-excon (~> 1.1)
26
+ faraday-httpclient (~> 1.0)
27
+ faraday-multipart (~> 1.0)
28
+ faraday-net_http (~> 1.0)
29
+ faraday-net_http_persistent (~> 1.0)
30
+ faraday-patron (~> 1.0)
31
+ faraday-rack (~> 1.0)
32
+ faraday-retry (~> 1.0)
33
+ ruby2_keywords (>= 0.0.4)
34
+ faraday-em_http (1.0.0)
35
+ faraday-em_synchrony (1.0.0)
36
+ faraday-excon (1.1.0)
37
+ faraday-httpclient (1.0.1)
38
+ faraday-multipart (1.0.3)
39
+ multipart-post (>= 1.2, < 3)
40
+ faraday-net_http (1.0.1)
41
+ faraday-net_http_persistent (1.2.0)
42
+ faraday-patron (1.0.0)
43
+ faraday-rack (1.0.0)
44
+ faraday-retry (1.0.3)
45
+ h1p (0.2)
46
+ http-2 (0.11.0)
47
+ json (2.6.1)
48
+ kramdown (2.3.1)
22
49
  rexml
23
50
  kramdown-parser-gfm (1.1.0)
24
51
  kramdown (~> 2.0)
52
+ localhost (1.1.9)
25
53
  minitest (5.11.3)
26
- minitest-reporters (1.4.3)
27
- ansi
28
- builder
29
- minitest (>= 5.0)
30
- ruby-progressbar
31
54
  msgpack (1.4.2)
32
- polyphony (0.51.0)
33
- qeweney (0.5)
55
+ multipart-post (2.1.1)
56
+ papercraft (0.12)
57
+ escape_utils (= 1.2.1)
58
+ kramdown (~> 2.3.0)
59
+ kramdown-parser-gfm (~> 1.1.0)
60
+ rouge (~> 3.26.0)
61
+ polyphony (0.73.1)
62
+ qeweney (0.15)
34
63
  escape_utils (~> 1.2.1)
35
64
  rack (2.2.3)
36
65
  rake (12.3.3)
37
- rexml (3.2.4)
38
- rouge (3.26.0)
39
- ruby-progressbar (1.11.0)
66
+ rexml (3.2.5)
67
+ rouge (3.26.1)
68
+ ruby2_keywords (0.0.5)
40
69
  simplecov (0.17.1)
41
70
  docile (~> 1.1)
42
71
  json (>= 1.8, < 3)
43
72
  simplecov-html (~> 0.10.0)
44
73
  simplecov-html (0.10.2)
45
- tipi (0.37)
46
- http-2 (~> 0.10.0)
47
- http_parser.rb (~> 0.6.0)
74
+ tipi (0.45)
75
+ acme-client (~> 2.0.8)
76
+ ever (~> 0.1)
77
+ extralite (~> 1.2)
78
+ h1p (~> 0.2)
79
+ http-2 (~> 0.11)
80
+ localhost (~> 1.1.4)
48
81
  msgpack (~> 1.4.2)
49
- polyphony (~> 0.51.0)
50
- qeweney (~> 0.5)
82
+ polyphony (~> 0.71)
83
+ qeweney (~> 0.14)
51
84
  rack (>= 2.0.8, < 2.3.0)
52
85
  websocket (~> 1.2.8)
53
86
  websocket (1.2.9)
@@ -58,9 +91,8 @@ PLATFORMS
58
91
  DEPENDENCIES
59
92
  impression!
60
93
  minitest (~> 5.11.3)
61
- minitest-reporters (~> 1.4.2)
62
94
  rake (~> 12.3.3)
63
95
  simplecov (~> 0.17.1)
64
96
 
65
97
  BUNDLED WITH
66
- 2.1.4
98
+ 2.3.3
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/clean"
5
+
6
+ task :default => [:test]
7
+
8
+ task :test do
9
+ exec 'ruby test/run.rb'
10
+ end
@@ -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
+ }
@@ -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.serve('0.0.0.0', 4411, opts) do |req|
17
- app.call(req)
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
@@ -0,0 +1,15 @@
1
+ # This is a tutorial
2
+
3
+ ## I'm an h2
4
+
5
+ ```ruby
6
+ "here's some code"
7
+
8
+ class A
9
+ def b
10
+ [:c, 42, /foo/]
11
+ end
12
+ end
13
+
14
+ p A.new.b
15
+ ```
data/impression.gemspec CHANGED
@@ -19,15 +19,19 @@ Gem::Specification.new do |s|
19
19
 
20
20
  # s.executables = ['impression']
21
21
 
22
- s.add_runtime_dependency 'polyphony', '~>0.51.0'
23
- s.add_runtime_dependency 'tipi', '~>0.37'
22
+ s.add_runtime_dependency 'polyphony', '~>0.73.1'
23
+ s.add_runtime_dependency 'tipi', '~>0.45'
24
+ s.add_runtime_dependency 'qeweney', '~>0.15'
25
+
24
26
  s.add_runtime_dependency 'kramdown', '~>2.3.0'
25
27
  s.add_runtime_dependency 'rouge', '~>3.26.0'
26
28
  s.add_runtime_dependency 'kramdown-parser-gfm', '~>1.1.0'
27
29
 
30
+ # s.add_runtime_dependency 'rb-inotify', '~>0.10.1'
31
+ s.add_runtime_dependency 'papercraft', '~>0.12'
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,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Impression
4
+ class App < Resource
5
+ def initialize(path: '/', **opts)
6
+ super(path: path, **opts)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,89 @@
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 respond(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, kind, path = nil)
38
+ case kind
39
+ when :not_found
40
+ req.respond(nil, ':status' => Qeweney::Status::NOT_FOUND)
41
+ when :file
42
+ req.serve_file(path)
43
+ else
44
+ raise "Invalid path info kind #{kind.inspect}"
45
+ end
46
+ end
47
+
48
+ # Returns the path info for the given relative path.
49
+ #
50
+ # @param path [String] relative path
51
+ # @return [Array] path info (a tuple comprising kind and file path)
52
+ def get_path_info(path)
53
+ @path_info_cache[path] || calculate_path_info(path)
54
+ end
55
+
56
+ # Calculates the path info for the given relative path.
57
+ #
58
+ # @param path [String] relative path
59
+ # @param add_html_ext [bool] whether to add .html extension if not found
60
+ # @return [Array] path info
61
+ def calculate_path_info(path, add_html_ext = true)
62
+ full_path = File.join(@directory, path)
63
+
64
+ stat = File.stat(full_path) rescue nil
65
+ if !stat
66
+ return add_html_ext ?
67
+ calculate_path_info("#{path}.html", false) : [:not_found]
68
+ elsif stat.directory?
69
+ return calculate_directory_path_info(full_path)
70
+ else
71
+ return [:file, full_path]
72
+ end
73
+ end
74
+
75
+ # Calculates the path info for a directory. If an `index.html` file exists,
76
+ # its path info is returned, otherwise a `:not_found` path info is returned.
77
+ #
78
+ # @param path [String] directory path
79
+ # @return [Array] path info
80
+ def calculate_directory_path_info(path)
81
+ index_path = File.join(path, 'index.html')
82
+ if File.file?(index_path)
83
+ [:file, index_path]
84
+ else
85
+ [:not_found]
86
+ end
87
+ end
88
+ end
89
+ 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