servel 0.20.0 → 0.21.0
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/{lib/servel/templates → app}/_gallery.haml +0 -0
- data/{lib/servel/templates → app}/_listing.haml +0 -0
- data/{lib/servel/templates → app}/css/common.css +0 -15
- data/{lib/servel/templates → app}/css/gallery-text.css +0 -0
- data/{lib/servel/templates → app}/css/gallery.css +0 -0
- data/{lib/servel/templates → app}/css/home.css +0 -0
- data/{lib/servel/templates → app}/css/listing.css +0 -1
- data/{lib/servel/templates → app}/css/normalize.css +0 -0
- data/{lib/servel/templates → app}/home.haml +0 -0
- data/{lib/servel/templates → app}/index.haml +9 -3
- data/app/js/entries.js +111 -0
- data/{lib/servel/templates → app}/js/gallery.js +18 -24
- data/{lib/servel/templates → app}/js/listing.js +23 -45
- data/app/js/natural-orderby.min.js +2 -0
- data/{lib/servel/templates → app}/js/ume.js +0 -0
- data/lib/servel.rb +0 -2
- data/lib/servel/app.rb +1 -11
- data/lib/servel/entry.rb +5 -3
- data/lib/servel/haml_context.rb +1 -1
- data/lib/servel/index.rb +26 -3
- data/lib/servel/version.rb +1 -1
- data/servel.gemspec +0 -1
- metadata +17 -31
- data/lib/servel/entries.rb +0 -68
- data/lib/servel/templates/js/index.js +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2fa8d88495eaaf272edc23d6f8ee35358cdbf85e11339fc46f786cbead036ff9
|
4
|
+
data.tar.gz: dc9d48be2ce10ec35ebe1918f96985cef584bb2871ffaffebbb61ef2ea80a659
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c06b97acc7830e90bda35051313097cf3c414f1f3f4b15e6c2ec1af4be0cc6e665ce9480ace68a20827ad8d140396f9b34630061daa929f289d0c4027f3d2997
|
7
|
+
data.tar.gz: 8d0d2d034cf124464ceb421c110e01750341b9e5aa2bd009963e0bb1ec6262fe8bd24edc97b7bcb4bafaf6b0466879f65caadade8feee8b7a9663f400cb01352
|
File without changes
|
File without changes
|
@@ -23,18 +23,3 @@ a {
|
|
23
23
|
a:hover, a:focus, a:active {
|
24
24
|
text-decoration: underline;
|
25
25
|
}
|
26
|
-
|
27
|
-
#loading {
|
28
|
-
display: flex;
|
29
|
-
align-items: center;
|
30
|
-
justify-content: center;
|
31
|
-
position: fixed;
|
32
|
-
top: 0;
|
33
|
-
right: 0;
|
34
|
-
bottom: 0;
|
35
|
-
left: 0;
|
36
|
-
z-index: 2;
|
37
|
-
background-color: rgba(255, 255, 255, 0.6);
|
38
|
-
font-size: 24px;
|
39
|
-
font-weight: bold;
|
40
|
-
}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -4,6 +4,12 @@
|
|
4
4
|
%meta{charset: 'utf-8'}
|
5
5
|
%title Listing of #{url_root}#{url_path}
|
6
6
|
%meta{name: 'viewport', content: 'width=device-width, height=device-height, user-scalable=no'}
|
7
|
+
|
8
|
+
:javascript
|
9
|
+
window.specialEntries = #{special_entries};
|
10
|
+
window.directoryEntries = #{directory_entries};
|
11
|
+
window.fileEntries = #{file_entries};
|
12
|
+
|
7
13
|
:css
|
8
14
|
#{include('css/normalize.css')}
|
9
15
|
#{include('css/common.css')}
|
@@ -12,11 +18,11 @@
|
|
12
18
|
#{include('css/gallery-text.css')}
|
13
19
|
|
14
20
|
:javascript
|
21
|
+
#{include('js/natural-orderby.min.js')}
|
22
|
+
#{include('js/entries.js')}
|
15
23
|
#{include('js/listing.js')}
|
16
24
|
#{include('js/ume.js')}
|
17
25
|
#{include('js/gallery.js')}
|
18
|
-
#{include('js/index.js')}
|
19
26
|
%body
|
20
27
|
#gallery!= partial('gallery')
|
21
|
-
#listing!= partial('listing', { url_root: url_root, url_path: url_path })
|
22
|
-
#loading Loading...
|
28
|
+
#listing!= partial('listing', { url_root: url_root, url_path: url_path })
|
data/app/js/entries.js
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
var Entries = (function() {
|
4
|
+
//Lists
|
5
|
+
var all;
|
6
|
+
var media;
|
7
|
+
var hasMedia;
|
8
|
+
|
9
|
+
var sortMethod = "name";
|
10
|
+
var sortDirection = "asc";
|
11
|
+
var filterText = "";
|
12
|
+
|
13
|
+
function runFilter(entries) {
|
14
|
+
if(filterText == "") return entries;
|
15
|
+
|
16
|
+
var filteredEntries = [];
|
17
|
+
|
18
|
+
for(var i = 0; i < entries.length; i++) {
|
19
|
+
var entry = entries[i];
|
20
|
+
if(entry.name.toLowerCase().includes(filterText.toLowerCase())) filteredEntries.push(entry);
|
21
|
+
}
|
22
|
+
|
23
|
+
return filteredEntries;
|
24
|
+
}
|
25
|
+
|
26
|
+
function sortByName(entries) {
|
27
|
+
return naturalOrderBy.orderBy(entries, function(entry) {
|
28
|
+
return entry.name.toLowerCase();
|
29
|
+
}, sortDirection);
|
30
|
+
}
|
31
|
+
|
32
|
+
function sortByMtime(a, b) {
|
33
|
+
return b.mtime - a.mtime;
|
34
|
+
}
|
35
|
+
|
36
|
+
function sortBySize(a, b) {
|
37
|
+
return b.size - a.size;
|
38
|
+
}
|
39
|
+
|
40
|
+
function sortByType(a, b) {
|
41
|
+
var aType = a.type.toLowerCase();
|
42
|
+
var bType = b.type.toLowerCase();
|
43
|
+
|
44
|
+
if(aType < bType) return -1;
|
45
|
+
if(aType > bType) return 1;
|
46
|
+
|
47
|
+
return 0;
|
48
|
+
}
|
49
|
+
|
50
|
+
function runSort(entries) {
|
51
|
+
if(sortMethod == "name") return sortByName(entries);
|
52
|
+
|
53
|
+
var sortFunction;
|
54
|
+
if(sortMethod == "mtime") sortFunction = sortByMtime;
|
55
|
+
else if(sortMethod == "size") sortFunction = sortBySize;
|
56
|
+
else if(sortMethod == "type") sortFunction = sortByType;
|
57
|
+
|
58
|
+
entries.sort(sortFunction);
|
59
|
+
if(sortDirection == "desc") entries.reverse();
|
60
|
+
|
61
|
+
return entries;
|
62
|
+
}
|
63
|
+
|
64
|
+
function updateLists() {
|
65
|
+
specialEntries = window.specialEntries.slice();
|
66
|
+
directoryEntries = runSort(runFilter(window.directoryEntries.slice()));
|
67
|
+
fileEntries = runSort(runFilter(window.fileEntries.slice()));
|
68
|
+
|
69
|
+
all = [].concat(specialEntries, directoryEntries, fileEntries);
|
70
|
+
|
71
|
+
media = [];
|
72
|
+
for(var i = 0; i < fileEntries.length; i++) {
|
73
|
+
if(fileEntries[i].media) media.push(fileEntries[i]);
|
74
|
+
}
|
75
|
+
|
76
|
+
hasMedia = media.length > 0;
|
77
|
+
}
|
78
|
+
|
79
|
+
function update() {
|
80
|
+
updateLists();
|
81
|
+
Gallery.onEntriesUpdate();
|
82
|
+
Listing.onEntriesUpdate();
|
83
|
+
}
|
84
|
+
|
85
|
+
function sort(newSortMethod, newSortDirection) {
|
86
|
+
sortMethod = newSortMethod;
|
87
|
+
sortDirection = newSortDirection;
|
88
|
+
update();
|
89
|
+
}
|
90
|
+
|
91
|
+
function filter(newFilterText) {
|
92
|
+
filterText = newFilterText;
|
93
|
+
update();
|
94
|
+
}
|
95
|
+
|
96
|
+
updateLists();
|
97
|
+
|
98
|
+
return {
|
99
|
+
all: function() {
|
100
|
+
return all;
|
101
|
+
},
|
102
|
+
media: function() {
|
103
|
+
return media;
|
104
|
+
},
|
105
|
+
hasMedia: function() {
|
106
|
+
return hasMedia;
|
107
|
+
},
|
108
|
+
filter: filter,
|
109
|
+
sort: sort
|
110
|
+
};
|
111
|
+
})();
|
@@ -3,8 +3,7 @@
|
|
3
3
|
var Gallery = (function() {
|
4
4
|
var $;
|
5
5
|
var $gallery;
|
6
|
-
var
|
7
|
-
var currentIndex = 0;
|
6
|
+
var currentIndex;
|
8
7
|
var layoutItemMax = false;
|
9
8
|
|
10
9
|
function renderText(url) {
|
@@ -29,10 +28,10 @@ var Gallery = (function() {
|
|
29
28
|
function render() {
|
30
29
|
clearContent();
|
31
30
|
|
32
|
-
var entry =
|
31
|
+
var entry = Entries.media()[currentIndex];
|
33
32
|
|
34
33
|
var url = entry.href;
|
35
|
-
var type = entry.
|
34
|
+
var type = entry.mediaType;
|
36
35
|
|
37
36
|
$gallery.classList.add(type);
|
38
37
|
|
@@ -52,7 +51,7 @@ var Gallery = (function() {
|
|
52
51
|
|
53
52
|
function clamp(index) {
|
54
53
|
if(index == null || isNaN(index) || index < 0) return 0;
|
55
|
-
if(index >=
|
54
|
+
if(index >= Entries.media().length) return Entries.media().length - 1;
|
56
55
|
return index;
|
57
56
|
}
|
58
57
|
|
@@ -81,7 +80,7 @@ var Gallery = (function() {
|
|
81
80
|
}
|
82
81
|
|
83
82
|
function jump(url) {
|
84
|
-
var index =
|
83
|
+
var index = Entries.media().findIndex(function(entry) {
|
85
84
|
return entry.href == url;
|
86
85
|
});
|
87
86
|
go(index);
|
@@ -156,10 +155,18 @@ var Gallery = (function() {
|
|
156
155
|
layout();
|
157
156
|
}
|
158
157
|
|
159
|
-
function
|
158
|
+
function onEntriesUpdate() {
|
159
|
+
currentIndex = 0;
|
160
|
+
if(Entries.hasMedia()) render();
|
161
|
+
}
|
162
|
+
|
163
|
+
function init() {
|
164
|
+
$ = document.querySelector.bind(document);
|
165
|
+
$gallery = $("#gallery");
|
166
|
+
|
160
167
|
onEntriesUpdate();
|
161
168
|
|
162
|
-
if(
|
169
|
+
if(Entries.hasMedia()) {
|
163
170
|
$gallery.style.display = "flex";
|
164
171
|
|
165
172
|
initEvents();
|
@@ -167,23 +174,8 @@ var Gallery = (function() {
|
|
167
174
|
}
|
168
175
|
}
|
169
176
|
|
170
|
-
function onEntriesUpdate() {
|
171
|
-
currentIndex = 0;
|
172
|
-
mediaEntries = [];
|
173
|
-
for(var i = 0; i < window.entries.length; i++) {
|
174
|
-
if(window.entries[i].media) mediaEntries.push(window.entries[i]);
|
175
|
-
}
|
176
|
-
|
177
|
-
if(mediaEntries.length > 0) render();
|
178
|
-
}
|
179
|
-
|
180
|
-
window.addEventListener("DOMContentLoaded", function() {
|
181
|
-
$ = document.querySelector.bind(document);
|
182
|
-
$gallery = $("#gallery");
|
183
|
-
});
|
184
|
-
|
185
177
|
return {
|
186
|
-
|
178
|
+
init: init,
|
187
179
|
onEntriesUpdate: onEntriesUpdate,
|
188
180
|
go: go,
|
189
181
|
prev: prev,
|
@@ -193,3 +185,5 @@ var Gallery = (function() {
|
|
193
185
|
jump: jump
|
194
186
|
};
|
195
187
|
})();
|
188
|
+
|
189
|
+
window.addEventListener("DOMContentLoaded", Gallery.init);
|
@@ -3,10 +3,9 @@
|
|
3
3
|
var Listing = (function() {
|
4
4
|
var $;
|
5
5
|
var $container;
|
6
|
-
var filteredEntries = [];
|
7
6
|
var perPage = 99;
|
8
|
-
var currentIndex
|
9
|
-
var moreContent
|
7
|
+
var currentIndex;
|
8
|
+
var moreContent;
|
10
9
|
var scrollDebounce = false;
|
11
10
|
|
12
11
|
function escapeHTML(unsafe) {
|
@@ -31,14 +30,14 @@ var Listing = (function() {
|
|
31
30
|
<tr>
|
32
31
|
<td class="name">
|
33
32
|
<span class="icon">${file.icon}</span>
|
34
|
-
<a href="${file.href}" class="default ${file.class}" data-url="${file.href}" data-type="${file.
|
33
|
+
<a href="${file.href}" class="default ${file.class}" data-url="${file.href}" data-type="${file.mediaType}">${file.name}</a>
|
35
34
|
</td>
|
36
35
|
<td class="new-tab">
|
37
36
|
<a href="${file.href}" class="new-tab ${file.class}" target="_blank">(New tab)</a>
|
38
37
|
</td>
|
39
38
|
<td class="type">${file.type}</td>
|
40
|
-
<td class="size">${file.
|
41
|
-
<td class="modified">${file.
|
39
|
+
<td class="size">${file.sizeText}</td>
|
40
|
+
<td class="modified">${file.mtimeText}</td>
|
42
41
|
</tr>
|
43
42
|
`;
|
44
43
|
}
|
@@ -58,7 +57,7 @@ var Listing = (function() {
|
|
58
57
|
}
|
59
58
|
|
60
59
|
function render() {
|
61
|
-
var currentEntries =
|
60
|
+
var currentEntries = Entries.all().slice(currentIndex, currentIndex + perPage);
|
62
61
|
$container.insertAdjacentHTML("beforeend", renderTable(currentEntries));
|
63
62
|
}
|
64
63
|
|
@@ -69,7 +68,7 @@ var Listing = (function() {
|
|
69
68
|
function onScrolled() {
|
70
69
|
if(atBottom() && moreContent) {
|
71
70
|
currentIndex += perPage;
|
72
|
-
if(currentIndex >=
|
71
|
+
if(currentIndex >= Entries.all().length) moreContent = false;
|
73
72
|
render();
|
74
73
|
}
|
75
74
|
scrollDebounce = false;
|
@@ -85,32 +84,8 @@ var Listing = (function() {
|
|
85
84
|
|
86
85
|
sortable.classList.add("sort-active", "sort-" + sortable.dataset.sortDirection);
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
});
|
91
|
-
}
|
92
|
-
|
93
|
-
function updateFilteredEntries(needle) {
|
94
|
-
if(needle == "") {
|
95
|
-
filteredEntries = window.entries;
|
96
|
-
}
|
97
|
-
else {
|
98
|
-
filteredEntries = [];
|
99
|
-
|
100
|
-
for(var i = 0; i < window.entries.length; i++) {
|
101
|
-
var entry = window.entries[i];
|
102
|
-
if(entry.name.toLowerCase().includes(needle.toLowerCase())) filteredEntries.push(entry);
|
103
|
-
}
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
function applyFilter(needle) {
|
108
|
-
updateFilteredEntries(needle);
|
109
|
-
|
110
|
-
$container.innerHTML = "";
|
111
|
-
currentIndex = 0;
|
112
|
-
moreContent = true;
|
113
|
-
render();
|
87
|
+
Entries.sort(sortable.dataset.sortMethod, sortable.dataset.sortDirection);
|
88
|
+
sortable.scrollIntoView();
|
114
89
|
}
|
115
90
|
|
116
91
|
function initEvents() {
|
@@ -134,28 +109,31 @@ var Listing = (function() {
|
|
134
109
|
e.stopPropagation();
|
135
110
|
|
136
111
|
if(e.keyCode == 13) {
|
137
|
-
|
112
|
+
Entries.filter($("#search").value);
|
138
113
|
}
|
139
114
|
});
|
140
115
|
}
|
141
116
|
|
142
|
-
function onEntriesInit() {
|
143
|
-
onEntriesUpdate();
|
144
|
-
$("#listing").style.display = "block";
|
145
|
-
initEvents();
|
146
|
-
}
|
147
|
-
|
148
117
|
function onEntriesUpdate() {
|
149
|
-
|
118
|
+
$container.innerHTML = "";
|
119
|
+
currentIndex = 0;
|
120
|
+
moreContent = true;
|
121
|
+
render();
|
150
122
|
}
|
151
123
|
|
152
|
-
|
124
|
+
function init() {
|
153
125
|
$ = document.querySelector.bind(document);
|
154
126
|
$container = $("#listing-container");
|
155
|
-
|
127
|
+
|
128
|
+
onEntriesUpdate();
|
129
|
+
|
130
|
+
initEvents();
|
131
|
+
}
|
156
132
|
|
157
133
|
return {
|
158
|
-
|
134
|
+
init: init,
|
159
135
|
onEntriesUpdate: onEntriesUpdate
|
160
136
|
};
|
161
137
|
})();
|
138
|
+
|
139
|
+
window.addEventListener("DOMContentLoaded", Listing.init);
|
@@ -0,0 +1,2 @@
|
|
1
|
+
var naturalOrderBy=function(e){"use strict";var d=function(e,n){return e<n?-1:n<e?1:0},r=/(^0x[\da-fA-F]+$|^([+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?(?!\.\d+)(?=\D|\s|$))|\d+)/g,l=/^\s+|\s+$/g,o=/\s+/g,u=/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/,t=/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[/-]\d{1,4}[/-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,a=/^0+[1-9]{1}[0-9]*$/,y=/[^\x00-\x80]/,m=function(e,n){return e.value===n.value?0:void 0!==e.parsedNumber&&void 0!==n.parsedNumber?d(e.parsedNumber,n.parsedNumber):e.chunks&&n.chunks?function(e,n){for(var r,t,i,o,u=e.length,a=n.length,s=Math.min(u,a),c=0;c<s;c++){var f=e[c],l=n[c];if(f!==l)return""===f!=(""===l)?""===f?-1:1:"number"==typeof f&&"number"==typeof l?d(f,l):"number"==typeof f||"number"==typeof l?"number"==typeof f?-1:1:y.test(f+l)&&f.localeCompare?(i=l,(o=f.localeCompare(i))?o/Math.abs(o):0):(r=f)<(t=l)?-1:t<r?1:0}return s<u||s<a?u<=s?-1:1:0}(e.chunks,n.chunks):(t=n,((r=e).chunks?!t.chunks:t.chunks)?r.chunks?-1:1:(r.isNaN?!t.isNaN:t.isNaN)?r.isNaN?-1:1:(r.isSymbol?!t.isSymbol:t.isSymbol)?r.isSymbol?-1:1:(r.isObject?!t.isObject:t.isObject)?r.isObject?-1:1:(r.isArray?!t.isArray:t.isArray)?r.isArray?-1:1:(r.isFunction?!t.isFunction:t.isFunction)?r.isFunction?-1:1:(r.isNull?!t.isNull:t.isNull)?r.isNull?-1:1:0);var r,t},v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},s=function(r){return"function"==typeof r?r:function(e){if(Array.isArray(e)){var n=Number(r);if(Number.isInteger(n))return e[n]}else if(e&&"object"===(void 0===e?"undefined":v(e))&&"function"!=typeof r)return e[r];return e}},c=function(e){if(0!==e.length){var n=Number(e);if(!Number.isNaN(n))return n}},b=function(e){var n=c(e);return void 0!==n?n:function(e){if(t.test(e)){var n=Date.parse(e);if(!Number.isNaN(n))return n}}(e)},p=function(e){var n;return(n=e,n.replace(r,"\0$1\0").replace(/\0$/,"").replace(/^\0/,"").split("\0")).map(function(e,n,r){return t=e,i=r.length,!u.test(t)||a.test(t)&&1!==i?t.replace(o," ").replace(l,""):c(t)||0;var t,i})},N=function(e){return Number.isNaN(e)||e instanceof Number&&Number.isNaN(e.valueOf())},f=function(){var f=!(0<arguments.length&&void 0!==arguments[0])||arguments[0];return function(e){if("string"==typeof e||e instanceof String||("number"==typeof e||e instanceof Number)&&!N(e)||"boolean"==typeof e||e instanceof Boolean||e instanceof Date){var n=(i=f,"boolean"==typeof(t=e)||t instanceof Boolean?Number(t).toString():"number"==typeof t||t instanceof Number?t.toString():t instanceof Date?t.getTime().toString():"string"==typeof t||t instanceof String?(i?t:t.toLowerCase()).replace(l,""):""),r=b(n);return{parsedNumber:r,chunks:p(r?""+r:n),value:e}}var t,i,o,u,a,s,c;return{isArray:Array.isArray(e),isFunction:(c=e,"function"==typeof c),isNaN:N(e),isNull:(s=e,null===s),isObject:(a=e,!(null===a||"object"!==(void 0===a?"undefined":v(a))||Array.isArray(a)||a instanceof Number||a instanceof String||a instanceof Boolean||a instanceof Date)),isSymbol:(u=e,"symbol"===(void 0===u?"undefined":v(u))),isUndefined:(o=e,void 0===o),value:e}}},g=function(t,e,r){var i=e.length?e.map(s):[function(e){return e}],n=t.map(function(n,e){return{index:e,values:i.map(function(e){return e(n)}).map(f())}});return n.sort(function(e,n){return function(e,n,r){for(var t=e.values,i=n.values,o=t.length,u=r.length,a=0;a<o;a++){var s=a<u?r[a]:null;if(s&&"function"==typeof s){var c=s(t[a].value,i[a].value);if(c)return c}else{var f=m(t[a],i[a]);if(f)return f*("desc"===s?-1:1)}}return 0}(e,n,r)}),n.map(function(e){return n=t,r=e.index,n[r];var n,r})};var i={caseSensitive:!0,order:"asc"};return e.orderBy=function(e,n,r){if(!e||!Array.isArray(e))return[];var t=function(e){if(!e)return[];var n=Array.isArray(e)?[].concat(e):[e];return n.some(function(e){return"string"!=typeof e&&"number"!=typeof e&&"function"!=typeof e})?[]:n}(n),i=function(e){if(!e)return[];var n=Array.isArray(e)?[].concat(e):[e];return n.some(function(e){return"asc"!==e&&"desc"!==e&&"function"!=typeof e})?[]:n}(r);return g(e,t,i)},e.compare=function(e){var n,o,r=(n=e)&&"object"===(void 0===n?"undefined":v(n))?{caseSensitive:"boolean"==typeof n.caseSensitive?n.caseSensitive:i.caseSensitive,order:"asc"===n.order||"desc"===n.order?n.order:i.order}:i;return o=r,function(e,n){var r=f(o.caseSensitive),t=r(e),i=r(n);return m(t,i)*("desc"===o.order?-1:1)}},e}({});
|
2
|
+
//# sourceMappingURL=natural-orderby.min.js.map
|
File without changes
|
data/lib/servel.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'rack/handler/puma'
|
3
3
|
require 'hamlit'
|
4
|
-
require 'naturalsorter'
|
5
4
|
require 'active_support/all'
|
6
5
|
require 'lru_redux'
|
7
6
|
|
@@ -23,7 +22,6 @@ require "servel/instrumentation"
|
|
23
22
|
require "servel/entry"
|
24
23
|
require "servel/entry_factory"
|
25
24
|
require "servel/haml_context"
|
26
|
-
require "servel/entries"
|
27
25
|
require "servel/index"
|
28
26
|
require "servel/app"
|
29
27
|
require "servel/home_app"
|
data/lib/servel/app.rb
CHANGED
@@ -25,13 +25,7 @@ class Servel::App
|
|
25
25
|
|
26
26
|
return [404, {}, []] unless fs_path.exist?
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
if json_request?(request)
|
31
|
-
Servel::Entries.new(url_root: url_root, url_path: url_path, fs_path: fs_path, params: request.params).render
|
32
|
-
else
|
33
|
-
Servel::Index.new(url_root: url_root, url_path: url_path).render
|
34
|
-
end
|
28
|
+
Servel::Index.new(url_root: url_root, url_path: url_path, fs_path: fs_path).render
|
35
29
|
end
|
36
30
|
|
37
31
|
def redirect(location)
|
@@ -44,10 +38,6 @@ class Servel::App
|
|
44
38
|
Rack::Utils.clean_path_info(url_path)
|
45
39
|
end
|
46
40
|
|
47
|
-
def json_request?(request)
|
48
|
-
Rack::Utils.best_q_match(request.get_header("HTTP_ACCEPT"), ['text/html', 'application/json']) == 'application/json'
|
49
|
-
end
|
50
|
-
|
51
41
|
def try_encode(string)
|
52
42
|
return string if string.encoding == UTF_8
|
53
43
|
string.encode(UTF_8)
|
data/lib/servel/entry.rb
CHANGED
@@ -32,11 +32,13 @@ class Servel::Entry
|
|
32
32
|
icon: @icon,
|
33
33
|
href: Rack::Utils.escape_path(@href),
|
34
34
|
class: @listing_classes,
|
35
|
-
|
35
|
+
mediaType: @media_type,
|
36
36
|
name: @name,
|
37
37
|
type: @type,
|
38
|
-
size: @size.
|
39
|
-
|
38
|
+
size: @size.to_i,
|
39
|
+
sizeText: @size.nil? ? "-" : @size,
|
40
|
+
mtime: @mtime.to_i,
|
41
|
+
mtimeText: @mtime.nil? ? "-" : @mtime.strftime("%e %b %Y %l:%M %p"),
|
40
42
|
media: media?
|
41
43
|
}
|
42
44
|
end
|
data/lib/servel/haml_context.rb
CHANGED
data/lib/servel/index.rb
CHANGED
@@ -1,21 +1,44 @@
|
|
1
1
|
class Servel::Index
|
2
2
|
extend Servel::Instrumentation
|
3
|
+
RENDER_CACHE = LruRedux::ThreadSafeCache.new(100)
|
3
4
|
|
4
|
-
def initialize(url_root:, url_path:)
|
5
|
+
def initialize(url_root:, url_path:, fs_path:)
|
5
6
|
@url_root = url_root
|
6
7
|
@url_path = url_path
|
8
|
+
@fs_path = fs_path
|
7
9
|
end
|
8
10
|
|
9
11
|
def render
|
10
|
-
Servel::HamlContext.render('index.haml', locals)
|
12
|
+
RENDER_CACHE.getset(render_cache_key) { Servel::HamlContext.render('index.haml', locals) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def render_cache_key
|
16
|
+
@render_cache_key ||= [@fs_path.to_s, @fs_path.mtime.to_i].join("-")
|
11
17
|
end
|
12
18
|
|
13
19
|
def locals
|
20
|
+
children = @fs_path.children.map { |path| Servel::EntryFactory.for(path) }.compact
|
21
|
+
|
14
22
|
{
|
15
23
|
url_root: @url_root,
|
16
|
-
url_path: @url_path
|
24
|
+
url_path: @url_path,
|
25
|
+
special_entries: special_entries.to_json,
|
26
|
+
directory_entries: children.select(&:directory?).to_json,
|
27
|
+
file_entries: children.select(&:file?).to_json
|
17
28
|
}
|
18
29
|
end
|
19
30
|
|
31
|
+
def special_entries
|
32
|
+
list = []
|
33
|
+
list << Servel::EntryFactory.home("/") if @url_root != ""
|
34
|
+
|
35
|
+
unless @url_path == "/"
|
36
|
+
list << Servel::EntryFactory.top(@url_root == "" ? "/" : @url_root)
|
37
|
+
list << Servel::EntryFactory.parent("../")
|
38
|
+
end
|
39
|
+
|
40
|
+
list
|
41
|
+
end
|
42
|
+
|
20
43
|
instrument :render, :locals
|
21
44
|
end
|
data/lib/servel/version.rb
CHANGED
data/servel.gemspec
CHANGED
@@ -25,7 +25,6 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "rake", "~> 12.0"
|
26
26
|
spec.add_dependency "rack", "~> 2.0"
|
27
27
|
spec.add_dependency "puma"
|
28
|
-
spec.add_dependency "naturalsorter"
|
29
28
|
spec.add_dependency "hamlit"
|
30
29
|
spec.add_dependency "activesupport"
|
31
30
|
spec.add_dependency "lru_redux"
|
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.
|
4
|
+
version: 0.21.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-
|
11
|
+
date: 2018-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: naturalsorter
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: hamlit
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -135,33 +121,33 @@ files:
|
|
135
121
|
- LICENSE.txt
|
136
122
|
- README.md
|
137
123
|
- Rakefile
|
124
|
+
- app/_gallery.haml
|
125
|
+
- app/_listing.haml
|
126
|
+
- app/css/common.css
|
127
|
+
- app/css/gallery-text.css
|
128
|
+
- app/css/gallery.css
|
129
|
+
- app/css/home.css
|
130
|
+
- app/css/listing.css
|
131
|
+
- app/css/normalize.css
|
132
|
+
- app/home.haml
|
133
|
+
- app/index.haml
|
134
|
+
- app/js/entries.js
|
135
|
+
- app/js/gallery.js
|
136
|
+
- app/js/listing.js
|
137
|
+
- app/js/natural-orderby.min.js
|
138
|
+
- app/js/ume.js
|
138
139
|
- bin/console
|
139
140
|
- bin/servel
|
140
141
|
- bin/setup
|
141
142
|
- lib/servel.rb
|
142
143
|
- lib/servel/app.rb
|
143
144
|
- lib/servel/cli.rb
|
144
|
-
- lib/servel/entries.rb
|
145
145
|
- lib/servel/entry.rb
|
146
146
|
- lib/servel/entry_factory.rb
|
147
147
|
- lib/servel/haml_context.rb
|
148
148
|
- lib/servel/home_app.rb
|
149
149
|
- lib/servel/index.rb
|
150
150
|
- lib/servel/instrumentation.rb
|
151
|
-
- lib/servel/templates/_gallery.haml
|
152
|
-
- lib/servel/templates/_listing.haml
|
153
|
-
- lib/servel/templates/css/common.css
|
154
|
-
- lib/servel/templates/css/gallery-text.css
|
155
|
-
- lib/servel/templates/css/gallery.css
|
156
|
-
- lib/servel/templates/css/home.css
|
157
|
-
- lib/servel/templates/css/listing.css
|
158
|
-
- lib/servel/templates/css/normalize.css
|
159
|
-
- lib/servel/templates/home.haml
|
160
|
-
- lib/servel/templates/index.haml
|
161
|
-
- lib/servel/templates/js/gallery.js
|
162
|
-
- lib/servel/templates/js/index.js
|
163
|
-
- lib/servel/templates/js/listing.js
|
164
|
-
- lib/servel/templates/js/ume.js
|
165
151
|
- lib/servel/version.rb
|
166
152
|
- servel.gemspec
|
167
153
|
homepage: http://bloople.net/
|
data/lib/servel/entries.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
class Servel::Entries
|
2
|
-
extend Servel::Instrumentation
|
3
|
-
RENDER_CACHE = LruRedux::ThreadSafeCache.new(100)
|
4
|
-
SORT_METHODS = ["name", "mtime", "size", "type"]
|
5
|
-
SORT_DIRECTIONS = ["asc", "desc"]
|
6
|
-
|
7
|
-
def initialize(url_root:, url_path:, fs_path:, params:)
|
8
|
-
@url_root = url_root
|
9
|
-
@url_path = url_path
|
10
|
-
@fs_path = fs_path
|
11
|
-
@params = params
|
12
|
-
end
|
13
|
-
|
14
|
-
def render
|
15
|
-
RENDER_CACHE.getset(render_cache_key) { [200, {}, [entries.to_json]] }
|
16
|
-
end
|
17
|
-
|
18
|
-
def render_cache_key
|
19
|
-
@render_cache_key ||= [@fs_path.to_s, @fs_path.mtime.to_i, sort_method, sort_direction].join("-")
|
20
|
-
end
|
21
|
-
|
22
|
-
def entries
|
23
|
-
children = @fs_path.children.map { |path| Servel::EntryFactory.for(path) }.compact
|
24
|
-
special_entries + apply_sort(children.select(&:directory?)) + apply_sort(children.select(&:file?))
|
25
|
-
end
|
26
|
-
|
27
|
-
def sort_method
|
28
|
-
param = @params["_servel_sort_method"]
|
29
|
-
param = "name" unless SORT_METHODS.include?(param)
|
30
|
-
param
|
31
|
-
end
|
32
|
-
|
33
|
-
def sort_direction
|
34
|
-
param = @params["_servel_sort_direction"]
|
35
|
-
param = "asc" unless SORT_DIRECTIONS.include?(param)
|
36
|
-
param
|
37
|
-
end
|
38
|
-
|
39
|
-
def special_entries
|
40
|
-
list = []
|
41
|
-
list << Servel::EntryFactory.home("/") if @url_root != ""
|
42
|
-
|
43
|
-
unless @url_path == "/"
|
44
|
-
list << Servel::EntryFactory.top(@url_root == "" ? "/" : @url_root)
|
45
|
-
list << Servel::EntryFactory.parent("../")
|
46
|
-
end
|
47
|
-
|
48
|
-
list
|
49
|
-
end
|
50
|
-
|
51
|
-
def apply_sort(entries)
|
52
|
-
entries = case sort_method
|
53
|
-
when "name"
|
54
|
-
Naturalsorter::Sorter.sort_by_method(entries, :name, true)
|
55
|
-
when "mtime"
|
56
|
-
entries.sort_by { |entry| entry.mtime }
|
57
|
-
when "size"
|
58
|
-
entries.sort_by { |entry| entry.size || 0 }
|
59
|
-
when "type"
|
60
|
-
entries.sort_by { |entry| entry.type }
|
61
|
-
end
|
62
|
-
|
63
|
-
entries.reverse! if sort_direction == "desc"
|
64
|
-
entries
|
65
|
-
end
|
66
|
-
|
67
|
-
instrument :render, :entries, :apply_sort
|
68
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
|
3
|
-
var Index = (function() {
|
4
|
-
var $;
|
5
|
-
var inited = false;
|
6
|
-
|
7
|
-
function entriesURL() {
|
8
|
-
var sortable = $("th.sortable.sort-active");
|
9
|
-
return `${location.pathname}?_servel_sort_method=${sortable.dataset.sortMethod}&_servel_sort_direction=${sortable.dataset.sortDirection}`;
|
10
|
-
}
|
11
|
-
|
12
|
-
function onEntriesLoad(callback) {
|
13
|
-
if(inited) {
|
14
|
-
Gallery.onEntriesUpdate();
|
15
|
-
Listing.onEntriesUpdate();
|
16
|
-
}
|
17
|
-
else {
|
18
|
-
inited = true;
|
19
|
-
Gallery.onEntriesInit();
|
20
|
-
Listing.onEntriesInit();
|
21
|
-
}
|
22
|
-
|
23
|
-
$("#loading").style.display = "none";
|
24
|
-
if(callback) callback();
|
25
|
-
}
|
26
|
-
|
27
|
-
function loadEntries(callback) {
|
28
|
-
$("#loading").style.display = "flex";
|
29
|
-
|
30
|
-
var http = new XMLHttpRequest();
|
31
|
-
http.open("GET", entriesURL());
|
32
|
-
|
33
|
-
http.onreadystatechange = function() {
|
34
|
-
if(http.readyState === 4 && http.status === 200) {
|
35
|
-
window.entries = JSON.parse(http.responseText);
|
36
|
-
setTimeout(function() {
|
37
|
-
onEntriesLoad(callback);
|
38
|
-
}, 0);
|
39
|
-
}
|
40
|
-
};
|
41
|
-
|
42
|
-
http.setRequestHeader("Accept", "application/json");
|
43
|
-
http.send();
|
44
|
-
}
|
45
|
-
|
46
|
-
window.addEventListener("DOMContentLoaded", function() {
|
47
|
-
$ = document.querySelector.bind(document);
|
48
|
-
loadEntries();
|
49
|
-
});
|
50
|
-
|
51
|
-
return {
|
52
|
-
loadEntries: loadEntries
|
53
|
-
};
|
54
|
-
})();
|