servel 0.28.0 → 0.33.0

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: 8f15c64ad7143343fa43beea82a7c09813ffda5d38c64cf3933fe5033bb78270
4
- data.tar.gz: 4a37029622423e52a260f26b3dd71a2ac0943e605370364a85e206fd644f6951
3
+ metadata.gz: 36dac91c1fba1bbaa2ab70a7dc39404996216867968c93438f503ccc8dd15631
4
+ data.tar.gz: fedf2fb5c899e69de6715c40b64c4d7c652f6f01c6bec40c99cea1780ce6c16a
5
5
  SHA512:
6
- metadata.gz: bea3930d3199941d249401dfae0f25a27dc03cf43dd39af5914d2ae7ef9af64ce49c73b47099758611e076f96396f30564404451b9f8f58a78fbfaf34b2f2622
7
- data.tar.gz: 0d3f892f937a3046e75a8a61fad8678252a88e7f657ef84da82ee7f46d852492368cc42aa17cda7ac869236a4ae3ae12200f6b48dd8a35c8648afd9460b02b52
6
+ metadata.gz: 6b52f97da999645b081ad452866fb032e841f073dbb9e3be5c28b4501062cca015d131872c237fc14cf5920421a0671ef8114d984c7bc320c4183f407da66cb3
7
+ data.tar.gz: 3d621057dd5499b01a69251a08e3d18c3dab29435fde99313f43484d0ae53ba443ca9aec6c16b71369a8e0a25dd5319bf029104cf7c385bf32913cc4d928cc92
data/app/_gallery.haml CHANGED
@@ -6,9 +6,10 @@
6
6
  #page-back.paginator ◀
7
7
  #page-next.paginator ▶
8
8
  #content
9
- %img#image
10
- %video#video{controls: false, loop: true}
11
- %audio#audio{controls: true}
12
- #text
13
- %a#text-anchor{href: '#'}
14
- #text-content
9
+ #scroller
10
+ %img#image
11
+ %video#video{controls: false, loop: true}
12
+ %audio#audio{controls: true}
13
+ #text
14
+ %a#text-anchor{href: '#'}
15
+ #text-content
data/app/css/common.css CHANGED
@@ -16,6 +16,14 @@ body {
16
16
  user-select: none;
17
17
  }
18
18
 
19
+ .text-selectable {
20
+ -webkit-user-select: text;
21
+ -moz-user-select: text;
22
+ -khtml-user-select: text;
23
+ -ms-user-select: text;
24
+ user-select: text;
25
+ }
26
+
19
27
  a {
20
28
  text-decoration: none;
21
29
  }
data/app/css/gallery.css CHANGED
@@ -1,25 +1,85 @@
1
1
  #gallery {
2
2
  background: #333;
3
3
  display: none;
4
- flex-direction: column;
5
4
  }
6
5
 
7
6
  body.has-gallery.gallery #gallery {
8
7
  display: flex;
9
8
  }
10
9
 
10
+ #controls {
11
+ display: flex;
12
+ }
13
+
14
+ #page-jump-listing {
15
+ flex-grow: 1;
16
+ }
17
+
18
+ .paginator {
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ height: 75px;
23
+
24
+ font-size: 2em;
25
+ font-weight: bold;
26
+ text-align: center;
27
+ background-color: #1f1f1f;
28
+ color: #858585;
29
+
30
+ cursor: pointer;
31
+ }
32
+
33
+ .paginator:hover {
34
+ background-color: #0f0f0f;
35
+ color: #c1c1c1;
36
+ }
37
+
11
38
  #content {
12
39
  display: flex;
13
40
  align-items: center;
14
41
  justify-content: center;
15
42
  flex-grow: 1;
43
+ min-width: 0;
44
+ min-height: 0;
45
+ }
46
+
47
+ #scroller {
48
+ width: 100%;
49
+ max-height: 100%;
50
+ overflow: auto;
51
+ }
52
+
53
+ body.portrait #gallery {
54
+ flex-direction: column;
55
+ }
56
+
57
+ body.portrait .paginator {
58
+ width: 100px;
59
+ }
60
+
61
+ body.portrait #page-jump-listing {
62
+ width: auto;
63
+ }
64
+
65
+ body.landscape #gallery {
66
+ flex-direction: row;
67
+ }
68
+
69
+ body.landscape #controls {
70
+ flex-direction: column;
71
+ flex-shrink: 0;
72
+ width: 100px;
73
+ }
74
+
75
+ body.landscape #page-jump-listing {
76
+ writing-mode: vertical-rl;
77
+ transform: rotate(180deg);
16
78
  }
17
79
 
18
80
  #image, #video, #audio, #text {
19
81
  display: none;
20
- max-width: 100%;
21
82
  margin: 0 auto 0 auto;
22
- padding-top: 75px;
23
83
  }
24
84
 
25
85
  #video:focus, #audio:focus {
@@ -51,36 +111,6 @@ body.has-gallery.gallery #gallery {
51
111
  display: block;
52
112
  }
53
113
 
54
- #controls {
55
- position: fixed;
56
- left: 0;
57
- right: 0;
58
- display: flex;
59
- z-index: 10;
60
- }
61
-
62
- .paginator {
63
- display: flex;
64
- align-items: center;
65
- justify-content: center;
66
- width: 100px;
67
- height: 75px;
68
-
69
- font-size: 2em;
70
- font-weight: bold;
71
- text-align: center;
72
- background-color: #000000;
73
- color: #ffffff;
74
-
75
- opacity: 0.4;
76
- cursor: pointer;
77
- }
78
-
79
- #page-jump-listing {
80
- flex-grow: 1;
81
- width: auto;
82
- }
83
-
84
114
  @media screen and (max-width: 767px) {
85
115
  #gallery.video, #gallery.audio, #gallery.text {
86
116
  padding: 0;
@@ -101,9 +131,3 @@ body.has-gallery.gallery #gallery {
101
131
  display: none;
102
132
  }
103
133
  }
104
-
105
- @media screen and (min-width: 768px) {
106
- .paginator:hover {
107
- opacity: 0.7;
108
- }
109
- }
data/app/js/gallery.js CHANGED
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
 
3
3
  var Gallery = (function() {
4
- var LAYOUT_MODES = ["fit-both", "fit-width", "clamp-width"];
4
+ var LAYOUT_MODES = ["fit-both", "fit-width", "clamp-width", "full-size"];
5
5
 
6
+ var $body;
6
7
  var $gallery;
8
+ var $image;
7
9
  var $video;
8
10
  var $audio;
9
11
  var currentIndex;
@@ -155,15 +157,38 @@ var Gallery = (function() {
155
157
  }
156
158
 
157
159
  function layout() {
158
- var viewportHeight = document.documentElement.clientHeight + "px";
159
- $gallery.style.minHeight = viewportHeight;
160
+ var vw = document.documentElement.clientWidth;
161
+ var vh = document.documentElement.clientHeight;
162
+
163
+ var viewportOrientation = vw > vh ? "landscape" : "portrait";
164
+ $body.classList.remove("landscape", "portrait");
165
+ $body.classList.add(viewportOrientation);
166
+
167
+ $gallery.style.height = vh + "px";
168
+
169
+ var scrollerMaxHeight = viewportOrientation == "landscape" ? vh : vh - 75;
160
170
 
161
171
  var layoutMode = LAYOUT_MODES[layoutModeIndex];
162
- var maxHeight = layoutMode == "fit-both" ? viewportHeight : "none";
163
- var maxWidth = layoutMode == "clamp-width" ? "1000px" : "100%";
164
172
 
165
- $("#image").style.maxWidth = maxWidth;
166
- $("#image").style.maxHeight = maxHeight;
173
+ if(layoutMode == "fit-both") {
174
+ var maxWidth = "100%";
175
+ var maxHeight = (scrollerMaxHeight + "px");
176
+ }
177
+ else if(layoutMode == "fit-width") {
178
+ var maxWidth = "100%";
179
+ var maxHeight = "none";
180
+ }
181
+ else if(layoutMode == "clamp-width") {
182
+ var maxWidth = "1000px";
183
+ var maxHeight = "none";
184
+ }
185
+ else if(layoutMode == "full-size") {
186
+ var maxWidth = "none";
187
+ var maxHeight = "none";
188
+ }
189
+
190
+ $image.style.maxWidth = maxWidth;
191
+ $image.style.maxHeight = maxHeight;
167
192
  $video.style.maxWidth = maxWidth;
168
193
  $video.style.maxHeight = maxHeight;
169
194
  $audio.style.maxWidth = maxWidth;
@@ -181,7 +206,9 @@ var Gallery = (function() {
181
206
  }
182
207
 
183
208
  function init() {
209
+ $body = $("body");
184
210
  $gallery = $("#gallery");
211
+ $image = $("#image");
185
212
  $video = $("#video");
186
213
  $audio = $("#audio");
187
214
 
data/app/js/index.js CHANGED
@@ -19,52 +19,8 @@ var Index = (function() {
19
19
  document.body.classList.add("gallery");
20
20
  }
21
21
 
22
- function jumpScroll() {
23
- if(galleryVisible()) {
24
- jumpListing();
25
- window.scrollTo(0, 0);
26
- }
27
- else {
28
- jumpGallery();
29
- window.scrollTo(0, document.body.scrollHeight);
30
- }
31
- }
32
-
33
- function atTop() {
34
- return window.scrollY == 0;
35
- }
36
-
37
- function bottomScrollDown(event) {
38
- return galleryVisible() && atBottom() && event.deltaY > 0;
39
- }
40
-
41
- function topScrollUp(event) {
42
- return listingVisible() && atTop() && event.deltaY < 0;
43
- }
44
-
45
- function initEvents() {
46
- var scrollSize = 0;
47
-
48
- window.addEventListener("wheel", function(event) {
49
- if(bottomScrollDown(event) || topScrollUp(event)) {
50
- scrollSize += Math.abs(event.deltaY);
51
-
52
- if(scrollSize >= 1500) {
53
- scrollSize = 0;
54
- jumpScroll();
55
- }
56
- }
57
- else {
58
- scrollSize = 0;
59
- }
60
- });
61
- }
62
-
63
22
  function init() {
64
- if((Entries.media().length / Entries.all().length) >= 0.5) jumpGallery();
65
- else jumpListing();
66
-
67
- initEvents();
23
+ jumpListing();
68
24
  }
69
25
 
70
26
  return {
data/app/js/listing.js CHANGED
@@ -27,7 +27,7 @@ var Listing = (function() {
27
27
  function renderRow(file) {
28
28
  return HTMLSafe`
29
29
  <tr>
30
- <td class="name">
30
+ <td class="name text-selectable">
31
31
  <span class="icon">${file.icon}</span>
32
32
  <a href="${file.href}" class="default ${file.class}" data-url="${file.href}" data-type="${file.mediaType}">${file.name}</a>
33
33
  </td>
data/bin/servel CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require "servel"
4
4
 
5
- Servel::CLI.new(ARGV).start
5
+ Servel::CLI.new.start
data/lib/servel.rb CHANGED
@@ -1,20 +1,59 @@
1
1
  require 'rack'
2
2
  require 'rack/handler/puma'
3
+ require 'puma/configuration'
3
4
  require 'hamlit'
4
5
  require 'active_support/all'
5
6
  require 'lru_redux'
7
+ require 'tty-config'
6
8
 
7
9
  require 'thread'
8
10
  require 'pathname'
9
11
  require 'json'
12
+ require 'digest'
10
13
 
11
14
  module Servel
12
- def self.build_app(path_map)
15
+ def self.build_app(listings:, username: nil, password: nil)
16
+ app = build_listings_app(build_path_map(listings))
17
+
18
+ if username && username != ""
19
+ build_authentication_app(app: app, username: username, password: password)
20
+ else
21
+ app
22
+ end
23
+ end
24
+
25
+ def self.build_authentication_app(app:, username:, password:)
26
+ hashed_username = Digest::SHA512.digest(username)
27
+ hashed_password = Digest::SHA512.digest(password)
28
+
29
+ Rack::Auth::Basic.new(app) do |submitted_username, submitted_password|
30
+ hashed_submitted_username = Digest::SHA512.digest(submitted_username)
31
+ hashed_submitted_password = Digest::SHA512.digest(submitted_password)
32
+
33
+ Rack::Utils.secure_compare(
34
+ "#{hashed_username}#{hashed_password}",
35
+ "#{hashed_submitted_username}#{hashed_submitted_password}"
36
+ )
37
+ end
38
+ end
39
+
40
+ def self.build_path_map(listings)
41
+ listings.map do |listing|
42
+ listing = { listing => nil } if listing.is_a?(String)
43
+
44
+ root, url_root = listing.keys.first, listing.values.first || "/"
45
+ [Pathname.new(root).realpath, url_root]
46
+ end.to_h
47
+ end
48
+
49
+ def self.build_listings_app(path_map)
13
50
  url_map = path_map.map { |root, url_root| [url_root, Servel::App.new(root)] }.to_h
14
51
  url_map["/"] = Servel::HomeApp.new(path_map.values) unless url_map.keys.include?("/")
15
52
 
16
53
  Rack::URLMap.new(url_map)
17
54
  end
55
+
56
+
18
57
  end
19
58
 
20
59
  require "servel/version"
@@ -25,4 +64,5 @@ require "servel/haml_context"
25
64
  require "servel/index"
26
65
  require "servel/app"
27
66
  require "servel/home_app"
67
+ require "servel/config_parser"
28
68
  require "servel/cli"
data/lib/servel/cli.rb CHANGED
@@ -1,18 +1,16 @@
1
- class Servel::CLI
2
- def initialize(argv)
3
- @argv = argv
4
- end
5
-
6
- def start
7
- Rack::Handler::Puma.run(Servel.build_app(path_map))
8
- end
9
-
10
- def path_map
11
- @argv.map do |arg|
12
- root, url_root = arg.split(":" , 2)
13
- root = Pathname.new(root).realpath
14
-
15
- [root, url_root || "/"]
16
- end.to_h
17
- end
18
- end
1
+ class Servel::CLI
2
+ ALLOWED_PUMA_OPTIONS = [
3
+ :Host,
4
+ :Port,
5
+ :binds
6
+ ]
7
+
8
+ def initialize
9
+ @config = Servel::ConfigParser.new.config
10
+ end
11
+
12
+ def start
13
+ app = Servel.build_app(**@config.slice(:listings, :username, :password))
14
+ Rack::Handler::Puma.run(app, **@config.slice(*ALLOWED_PUMA_OPTIONS))
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ class Servel::ConfigParser
2
+ attr_reader :config
3
+
4
+ def initialize
5
+ @tty_config = TTY::Config.new
6
+ @tty_config.filename = "servel"
7
+ @tty_config.append_path(Dir.pwd)
8
+ @tty_config.append_path((Pathname.new(Dir.home) + ".servel").to_s)
9
+ @tty_config.append_path(Dir.home)
10
+ @tty_config.env_prefix = "servel"
11
+ @tty_config.autoload_env
12
+ @tty_config.read if @tty_config.exist?
13
+
14
+ @tty_config.append(*parse_argv, to: :listings)
15
+ parse_binds
16
+
17
+ @config = @tty_config.to_h.transform_keys(&:to_sym)
18
+ end
19
+
20
+ def parse_argv
21
+ ARGV.map do |arg|
22
+ root, url_root = arg.split(":" , 2)
23
+ { root => url_root }
24
+ end
25
+ end
26
+
27
+ def parse_binds
28
+ return parse_ssl_bind if @tty_config.fetch(:cert) && @tty_config.fetch(:key)
29
+
30
+ host = @tty_config.fetch(:host)
31
+ port = @tty_config.fetch(:port)
32
+ @tty_config.set(:Host, value: host) if host
33
+ @tty_config.set(:Port, value: port) if port
34
+ end
35
+
36
+ def parse_ssl_bind
37
+ host = @tty_config.fetch(:host, default: ::Puma::ConfigDefault::DefaultTCPHost)
38
+ port = @tty_config.fetch(:port, default: ::Puma::ConfigDefault::DefaultTCPPort)
39
+ key = Pathname.new(@tty_config.fetch(:key)).expand_path
40
+ cert = Pathname.new(@tty_config.fetch(:cert)).expand_path
41
+
42
+ query = URI.encode_www_form(key: key, cert: cert)
43
+ @tty_config.append("ssl://#{host}:#{port}?#{query}", to: :binds)
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module Servel
2
- VERSION = "0.28.0"
2
+ VERSION = "0.33.0"
3
3
  end
data/servel.gemspec CHANGED
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency "hamlit"
29
29
  spec.add_dependency "activesupport"
30
30
  spec.add_dependency "lru_redux"
31
+ spec.add_dependency "tty-config"
31
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: servel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.28.0
4
+ version: 0.33.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brenton "B-Train" Fletcher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-24 00:00:00.000000000 Z
11
+ date: 2021-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: tty-config
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: Serves files and directories over HTTP.
112
126
  email:
113
127
  - i@bloople.net
@@ -143,6 +157,7 @@ files:
143
157
  - lib/servel.rb
144
158
  - lib/servel/app.rb
145
159
  - lib/servel/cli.rb
160
+ - lib/servel/config_parser.rb
146
161
  - lib/servel/entry.rb
147
162
  - lib/servel/entry_factory.rb
148
163
  - lib/servel/haml_context.rb
@@ -170,8 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
185
  - !ruby/object:Gem::Version
171
186
  version: '0'
172
187
  requirements: []
173
- rubyforge_project:
174
- rubygems_version: 2.7.6
188
+ rubygems_version: 3.0.3
175
189
  signing_key:
176
190
  specification_version: 4
177
191
  summary: Serves files and directories over HTTP.