infod 0.0.2 → 0.0.3
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.
- data/infod.rb +52 -12
- data/infod/{Th/404.rb → 404.rb} +4 -16
- data/infod/500.rb +53 -0
- data/infod/GET.rb +104 -0
- data/infod/HEAD.rb +23 -0
- data/infod/HTTP.rb +105 -0
- data/infod/{Th/PATCH.rb → PATCH.rb} +0 -0
- data/infod/POST.rb +34 -0
- data/infod/audio.rb +30 -0
- data/infod/blog.rb +34 -0
- data/infod/cal.rb +72 -0
- data/infod/{Es/code.rb → code.rb} +7 -4
- data/infod/constants.rb +55 -0
- data/infod/{Es/css.rb → css.rb} +0 -0
- data/infod/{Es/csv.rb → csv.rb} +0 -0
- data/infod/{Es/du.rb → du.rb} +0 -0
- data/infod/edit.rb +73 -0
- data/infod/{H/facets.rb → facets.rb} +20 -11
- data/infod/{Es/feed.rb → feed.rb} +17 -16
- data/infod/{Es/find.rb → find.rb} +2 -3
- data/infod/forum.rb +13 -0
- data/infod/{Es/fs.rb → fs.rb} +5 -2
- data/infod/glob.rb +26 -0
- data/infod/graph.rb +123 -0
- data/infod/{Es/grep.rb → grep.rb} +2 -2
- data/infod/{Es/groonga.rb → groonga.rb} +41 -33
- data/infod/{H/histogram.rb → histogram.rb} +23 -16
- data/infod/html.rb +231 -0
- data/infod/{Es/image.rb → image.rb} +16 -26
- data/infod/{Es/index.rb → index.rb} +38 -25
- data/infod/infod.rb +52 -12
- data/infod/json.rb +38 -0
- data/infod/{Es/kv.rb → kv.rb} +3 -9
- data/infod/{Y.rb → lambda.rb} +18 -1
- data/infod/ls.rb +49 -0
- data/infod/mail.rb +90 -0
- data/infod/{Es/man.rb → man.rb} +3 -15
- data/infod/{H/microblog.rb → microblog.rb} +22 -31
- data/infod/{K.rb → mime.rb} +68 -52
- data/infod/{N.rb → names.rb} +78 -45
- data/infod/page.rb +13 -0
- data/infod/postscript.rb +26 -0
- data/infod/rdf.rb +51 -0
- data/infod/{Rb.rb → ruby.rb} +18 -33
- data/infod/{Es/schema.rb → schema.rb} +22 -7
- data/infod/{Es/search.rb → search.rb} +5 -11
- data/infod/{Es/sh.rb → sh.rb} +0 -0
- data/infod/{Es/text.rb → text.rb} +33 -29
- data/infod/{H/threads.rb → threads.rb} +17 -27
- data/infod/{H/time.rb → time.rb} +14 -34
- data/infod/{H/who.rb → whois.rb} +6 -4
- data/infod/{H/wiki.rb → wiki.rb} +0 -0
- metadata +54 -64
- data/config.ru +0 -3
- data/infod/Es.rb +0 -31
- data/infod/Es/filter.rb +0 -75
- data/infod/Es/glob.rb +0 -22
- data/infod/Es/html.rb +0 -271
- data/infod/Es/in.rb +0 -68
- data/infod/Es/json.rb +0 -68
- data/infod/Es/ls.rb +0 -58
- data/infod/Es/mail.rb +0 -87
- data/infod/Es/mime.rb +0 -59
- data/infod/Es/out.rb +0 -52
- data/infod/Es/pager.rb +0 -34
- data/infod/Es/pdf.rb +0 -19
- data/infod/Es/rdf.rb +0 -35
- data/infod/H.rb +0 -15
- data/infod/H/audio.rb +0 -19
- data/infod/H/blog.rb +0 -15
- data/infod/H/cal.rb +0 -81
- data/infod/H/edit.rb +0 -88
- data/infod/H/forum.rb +0 -4
- data/infod/H/hf.rb +0 -114
- data/infod/H/mail.rb +0 -92
- data/infod/Th.rb +0 -36
- data/infod/Th/500.rb +0 -41
- data/infod/Th/GET.rb +0 -62
- data/infod/Th/HEAD.rb +0 -5
- data/infod/Th/POST.rb +0 -39
- data/infod/Th/perf.rb +0 -37
- data/infod/Th/uid.rb +0 -24
- data/infod/Th/util.rb +0 -89
@@ -2,20 +2,9 @@
|
|
2
2
|
class E
|
3
3
|
|
4
4
|
def triplrImage &f
|
5
|
+
yield uri,Type,E[DC+'Image']
|
5
6
|
triplrStdOut 'exiftool', EXIF, &f
|
6
7
|
end
|
7
|
-
|
8
|
-
# export EXIF to RDF-in-JSON (recursive)
|
9
|
-
def exif
|
10
|
-
take.map{|g|
|
11
|
-
if g.uri.match /(jpe?g|gif|png)$/i
|
12
|
-
e = g.ef
|
13
|
-
if !e.e || e.m < g.m
|
14
|
-
g.ef.w g.fromStream({},:triplrImage), true
|
15
|
-
puts "EXIF #{g} #{g.ef.size} bytes"
|
16
|
-
end
|
17
|
-
end}
|
18
|
-
end
|
19
8
|
|
20
9
|
fn 'req/scaleImage',->e,r{
|
21
10
|
i = [e,e.pathSegment].compact.find(&:f)
|
@@ -38,17 +27,15 @@ class E
|
|
38
27
|
end}
|
39
28
|
|
40
29
|
fn 'view/img',->i,_{
|
41
|
-
[i.values.map{|i|
|
42
|
-
[
|
43
|
-
|
44
|
-
style:'float:left;max-width:61.8%',
|
45
|
-
src: i.url}},
|
30
|
+
[i.values.select{|v|v.class==Hash}.map{|i|
|
31
|
+
i[Type] && (i[Type].class==Array ? i[Type] : [i[Type]]).map{|t|t.respond_to?(:uri) && t.uri}.include?(DC+'Image') &&
|
32
|
+
[{_: :a, href: i.url, c: {_: :img, style:'float:left;max-width:61.8%', src: i.url}},
|
46
33
|
i.html]},
|
47
34
|
(H.css '/css/img')]}
|
48
35
|
|
49
36
|
fn 'view/th',->i,e{
|
50
|
-
i.map{|u,i| u.match(/(gif|jpe?g|png|tiff)$/i) &&
|
51
|
-
{_: :a, href: i.url+'?
|
37
|
+
i.map{|u,i| u && u.match(/(gif|jpe?g|png|tiff)$/i) &&
|
38
|
+
{_: :a, href: i.url+'?view=img',
|
52
39
|
c: {_: :img, src: i.url+'?y=scaleImage&px=233'}}}}
|
53
40
|
|
54
41
|
F['view/'+MIMEtype+'image/gif'] = F['view/th']
|
@@ -56,40 +43,43 @@ class E
|
|
56
43
|
F['view/'+MIMEtype+'image/png'] = F['view/th']
|
57
44
|
|
58
45
|
# display just the images found in content
|
59
|
-
fn 'view/imgs',->m,e{
|
46
|
+
fn 'view/imgs',->m, e { seen = {}
|
60
47
|
|
61
|
-
# height argument
|
48
|
+
# optional height argument
|
62
49
|
h = e.q['h'].do{|h|
|
63
|
-
h.match(/^[0-9]+$/).do{|_|'height:'+h+'px'}}
|
64
|
-
|
65
|
-
# visited images
|
66
|
-
seen={}
|
50
|
+
h.match(/^[0-9]+$/).do{|_|'height:'+h+'px'}}||''
|
67
51
|
|
68
52
|
# extension-based filter
|
69
53
|
x=->i{i&&i.match(/(jpe?g|gif|png)$/i)&&i}
|
70
54
|
|
71
55
|
[(H.once e,:mu,H.js('/js/mu')),H.js('/js/images'),
|
72
56
|
m.values.map{|v|
|
73
|
-
# CSS
|
57
|
+
# CSS-selector search inside content
|
74
58
|
[[*v[Content]].map{|c| c.class == String &&
|
75
59
|
(Nokogiri::HTML.parse(c).do{|c|
|
60
|
+
|
76
61
|
[# <img> elements
|
77
62
|
c.css('img').map{|i|i['src']}.compact,
|
63
|
+
|
78
64
|
# <a> elements with image extensions
|
79
65
|
c.css('a').map{|i|i['href']}.select(&x)]
|
80
66
|
})},
|
67
|
+
|
81
68
|
# check subject URI for image extension
|
82
69
|
x.(v.uri),
|
70
|
+
|
83
71
|
# check object URIs for image extension
|
84
72
|
(v.respond_to?(:values) &&
|
85
73
|
v.values.flatten.map{|v|
|
86
74
|
v.respond_to?(:uri) && v.uri
|
87
75
|
}.select(&x))
|
76
|
+
|
88
77
|
].flatten.uniq.compact.map{|s|
|
89
78
|
# view
|
90
79
|
{uri: s,
|
91
80
|
# img and link to containing resource
|
92
81
|
c: ->{"<a href='#{v.uri.to_s.do{|u|u.path? ? u : u.E.url}}'><img style='float:left;#{h}' src='#{s}'></a>"}}}}.flatten.map{|i|
|
82
|
+
|
93
83
|
# show and mark as seen
|
94
84
|
!seen[i[:uri]] &&
|
95
85
|
(seen[i[:uri]] = true
|
@@ -4,13 +4,13 @@ class E
|
|
4
4
|
# POSIX-fs based index of triples
|
5
5
|
#
|
6
6
|
|
7
|
-
# index a triple
|
7
|
+
# index a triple
|
8
8
|
def index p,o
|
9
9
|
p = p.E
|
10
10
|
indexEdit p, (o.class == E ? o : p.literal(o)), nil
|
11
11
|
end
|
12
12
|
|
13
|
-
# index a triple - no
|
13
|
+
# index a triple - no type-normalization
|
14
14
|
def indexEdit p,o,a
|
15
15
|
return if @noIndex
|
16
16
|
p.pIndex.noIndex[o,self,a]
|
@@ -22,6 +22,7 @@ class E
|
|
22
22
|
|
23
23
|
# reachable graph along named predicate
|
24
24
|
def walk p, g={}, v={}
|
25
|
+
# puts "walk #{uri}"
|
25
26
|
graph g # cumulative graph
|
26
27
|
v[uri] = true # visited mark
|
27
28
|
|
@@ -38,16 +39,19 @@ class E
|
|
38
39
|
fn 'set/subtree',->d,r,m{
|
39
40
|
c =(r['c'].do{|c|c.to_i + 1} || 3).max(100) # one extra for start of next-page
|
40
41
|
o = r['d'] =~ /^a/ ? :asc : :desc # direction
|
42
|
+
|
41
43
|
('/'.E.take c, o, d.uri).do{|s| # take subtree
|
42
44
|
desc, asc = o == :desc ? # orient pagination hints
|
43
45
|
[s.pop, s[0]] : [s[0], s.pop]
|
44
|
-
m['
|
45
|
-
|
46
|
+
u = m['#']
|
47
|
+
u[Type] = E[HTTP+'Response']
|
48
|
+
u[Prev] = {'uri' => desc.url + {'d' => 'desc'}.qs} if desc
|
49
|
+
u[Next] = {'uri' => asc.url + {'d' => 'asc'}.qs} if asc
|
46
50
|
s }}
|
47
51
|
|
48
52
|
# subtree traverse index on p+o cursor
|
49
53
|
fn 'set/index',->d,r,m,f=:rangePO{
|
50
|
-
top = (f == :rangeP ? d : r['p']).expand.E
|
54
|
+
top = (f == :rangeP ? d : (r['p'] || '/')).expand.E
|
51
55
|
count = r['c'] &&
|
52
56
|
r['c'].to_i.max(1000)+1 || 22
|
53
57
|
dir = r['d'] &&
|
@@ -56,20 +60,25 @@ class E
|
|
56
60
|
:desc
|
57
61
|
|
58
62
|
(top.send f, count, dir, r['offset'],(d if f == :rangePO)).do{|s|
|
59
|
-
# pagination pointers
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
# orient pagination pointers
|
64
|
+
ascending = r['d'].do{|d| d == 'asc' }
|
65
|
+
first, last = s[0], s.size > 1 && s.pop
|
66
|
+
desc, asc = ascending && [first,last] || [last,first]
|
67
|
+
|
68
|
+
# response description
|
69
|
+
u = m['#']
|
70
|
+
u[RDFs+'member'] = s
|
71
|
+
u[Prev] = {'uri' => d.url + {'d' => 'desc','offset' => desc.uri}.qs} if desc
|
72
|
+
u[Next] = {'uri' => d.url + {'d' => 'asc', 'offset' => asc.uri}.qs} if asc
|
73
|
+
|
74
|
+
s.map(&:docs).flatten.uniq }}
|
66
75
|
|
67
76
|
fn 'set/indexP',->d,r,m{Fn 'set/index',d,r,m,:rangeP}
|
68
|
-
|
77
|
+
F['set/indexPO'] = F['set/index']
|
69
78
|
|
70
79
|
# predicate index
|
71
80
|
def pIndex
|
72
|
-
prependURI '/index/'
|
81
|
+
shorten.prependURI '/index/'
|
73
82
|
end
|
74
83
|
|
75
84
|
# predicate-object index
|
@@ -83,8 +92,8 @@ class E
|
|
83
92
|
end
|
84
93
|
|
85
94
|
# range query - predicate
|
86
|
-
def rangeP
|
87
|
-
pIndex.subtree(
|
95
|
+
def rangeP size=8, dir=:desc, offset=nil, object=nil
|
96
|
+
pIndex.subtree(size,dir,offset).map &:ro
|
88
97
|
end
|
89
98
|
|
90
99
|
# range query - predicate-object
|
@@ -102,23 +111,25 @@ class E
|
|
102
111
|
no.take(*a).map &:E
|
103
112
|
end
|
104
113
|
|
105
|
-
# random leaf
|
106
114
|
def randomLeaf
|
107
115
|
c.empty? && self || c.r.randomLeaf
|
108
116
|
end
|
109
117
|
|
118
|
+
def E.graphProperties g
|
119
|
+
g.values.select{|v|v.respond_to? :keys}.map(&:keys).flatten.uniq
|
120
|
+
end
|
121
|
+
|
110
122
|
fn 'set/randomLeaf',->d,e,m{[d.randomLeaf]}
|
111
123
|
fn 'req/randomLeaf',->e,r{[302, {Location: e.randomLeaf.uri},[]]}
|
112
124
|
|
113
|
-
|
114
125
|
# enumerate unique predicates in index
|
115
126
|
fn '/index/GET',->e,r{
|
116
127
|
e.pathSegment.uri.match(/^\/index$/) &&
|
117
128
|
(H [{_: :style, c: "a {font-size:3em;display:block}
|
118
129
|
a:hover {background-color:#00f}"},
|
119
|
-
'/index'.E.take.map{|e|e.uri[6..-1].unpath.do{|p|{_: :a, href: '/@'+URI.escape(p.uri)+'?set=indexP&
|
130
|
+
'/index'.E.take.map{|e|e.uri[6..-1].unpath.do{|p|{_: :a, href: '/@'+URI.escape(p.uri)+'?set=indexP&c=12', c: p}}}]).hR}
|
120
131
|
|
121
|
-
# p
|
132
|
+
# p+o index-traversal pointers
|
122
133
|
fn 'view/linkPO',->d,e{
|
123
134
|
p = e['uri']
|
124
135
|
[(H.css '/css/index'),(H.js '/js/search'),{_: :b, c: p},
|
@@ -126,7 +137,10 @@ a:hover {background-color:#00f}"},
|
|
126
137
|
%w{sioc:has_creator sioc:addressed_to}.member?(p).do{|_|
|
127
138
|
{_: :form, action: '/whois',c: [{_: :input, type: :hidden, name: :p, value: p},{_: :input, name: :q}]}
|
128
139
|
},
|
129
|
-
|
140
|
+
# set members
|
141
|
+
d['#'][RDFs+'member'].do{|m|
|
142
|
+
m.map{|r|
|
143
|
+
{c: {_: :a, href: r.url+'?set=indexPO&p=' + (URI.escape p) + '&c=8', c: r.uri}}}}]}
|
130
144
|
|
131
145
|
end
|
132
146
|
|
@@ -137,7 +151,7 @@ class Pathname
|
|
137
151
|
def take count=1000, direction=:desc, offset=nil
|
138
152
|
|
139
153
|
# construct offset-path
|
140
|
-
offset = to_s + offset.gsub(/\/+/,'/').E.path if offset
|
154
|
+
offset = (to_s + offset).gsub(/\/+/,'/').E.path if offset
|
141
155
|
|
142
156
|
# in-range indicator
|
143
157
|
ok = false
|
@@ -151,7 +165,7 @@ class Pathname
|
|
151
165
|
|
152
166
|
# visitation function
|
153
167
|
visit=->nodes{
|
154
|
-
|
168
|
+
|
155
169
|
# sort nodes in asc or desc order
|
156
170
|
nodes.sort_by(&:to_s).send(v).each{|n|
|
157
171
|
ns = n.to_s
|
@@ -174,8 +188,7 @@ class Pathname
|
|
174
188
|
ok = true # iterator is now within range
|
175
189
|
end )}}
|
176
190
|
|
177
|
-
visit.(c) # start
|
178
|
-
|
191
|
+
visit.(c) # start
|
179
192
|
# result set
|
180
193
|
set
|
181
194
|
end
|
data/infod/infod.rb
CHANGED
@@ -1,12 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
%w{
|
2
|
+
constants
|
3
|
+
lambda
|
4
|
+
mime
|
5
|
+
404
|
6
|
+
500
|
7
|
+
audio
|
8
|
+
blog
|
9
|
+
cal
|
10
|
+
code
|
11
|
+
css
|
12
|
+
csv
|
13
|
+
du
|
14
|
+
edit
|
15
|
+
facets
|
16
|
+
feed
|
17
|
+
find
|
18
|
+
forum
|
19
|
+
fs
|
20
|
+
GET
|
21
|
+
glob
|
22
|
+
graph
|
23
|
+
grep
|
24
|
+
groonga
|
25
|
+
HEAD
|
26
|
+
histogram
|
27
|
+
html
|
28
|
+
HTTP
|
29
|
+
image
|
30
|
+
index
|
31
|
+
json
|
32
|
+
kv
|
33
|
+
ls
|
34
|
+
mail
|
35
|
+
man
|
36
|
+
microblog
|
37
|
+
names
|
38
|
+
page
|
39
|
+
PATCH
|
40
|
+
POST
|
41
|
+
postscript
|
42
|
+
rdf
|
43
|
+
ruby
|
44
|
+
schema
|
45
|
+
search
|
46
|
+
sh
|
47
|
+
text
|
48
|
+
threads
|
49
|
+
time
|
50
|
+
whois
|
51
|
+
wiki
|
52
|
+
}.map{|e|require_relative e}
|
data/infod/json.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
def graph g
|
4
|
+
g.merge!({uri=>self})
|
5
|
+
end
|
6
|
+
|
7
|
+
def mergeGraph g
|
8
|
+
g.triples{|s,p,o|
|
9
|
+
self[s] = {'uri' => s} unless self[s].class == Hash
|
10
|
+
self[s][p] ||= []
|
11
|
+
self[s][p].push o unless self[s][p].member? o } if g
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
# self -> tripleStream
|
16
|
+
def triples &f
|
17
|
+
map{|s,r|
|
18
|
+
r.map{|p,o|
|
19
|
+
o.class == Array ? o.each{|o| yield s,p,o} : yield(s,p,o) unless p=='uri'} if r.class == Hash
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class E
|
26
|
+
|
27
|
+
def triplrJSON
|
28
|
+
yield uri, '/application/json', (JSON.parse read) if e
|
29
|
+
rescue Exception => e
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_json *a
|
33
|
+
to_h.to_json *a
|
34
|
+
end
|
35
|
+
|
36
|
+
fn Render+'application/json',->d,_=nil{[d].to_json}
|
37
|
+
|
38
|
+
end
|
data/infod/{Es/kv.rb → kv.rb}
RENAMED
@@ -27,17 +27,11 @@ class E
|
|
27
27
|
unless t.e # triple exists?
|
28
28
|
indexEdit p,o,nil # index triple
|
29
29
|
if o.f # add triple
|
30
|
-
# link
|
31
|
-
# puts "link #{o} #{t}"
|
32
|
-
o.ln t
|
30
|
+
o.ln t # hard link
|
33
31
|
elsif o.e
|
34
|
-
#
|
35
|
-
# puts "symlink #{o} #{t}"
|
36
|
-
o.ln_s t
|
32
|
+
o.ln_s t # symbolic link
|
37
33
|
else
|
38
|
-
#
|
39
|
-
puts "origin missing #{t} , adding URI ref"
|
40
|
-
t.mk
|
34
|
+
t.mk # dir entry
|
41
35
|
end
|
42
36
|
end
|
43
37
|
end
|
data/infod/{Y.rb → lambda.rb}
RENAMED
@@ -5,6 +5,20 @@ def watch f
|
|
5
5
|
|
6
6
|
class E
|
7
7
|
|
8
|
+
def initialize uri
|
9
|
+
@uri = uri.to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
def E arg=nil
|
13
|
+
if arg
|
14
|
+
E.new arg
|
15
|
+
else
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def E.[] u; u.E end
|
21
|
+
|
8
22
|
F={}
|
9
23
|
Watch={}
|
10
24
|
|
@@ -29,6 +43,9 @@ def fn u,y
|
|
29
43
|
end
|
30
44
|
|
31
45
|
def Fn a,*g
|
32
|
-
puts "missing #{a} from #{caller[0]}" unless E::F[a]
|
33
46
|
E::F[a][*g]
|
34
47
|
end
|
48
|
+
|
49
|
+
def E e
|
50
|
+
E.new e
|
51
|
+
end
|
data/infod/ls.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
class E
|
3
|
+
|
4
|
+
fn 'view/dir',->i,e{
|
5
|
+
a = -> i { i = i.E
|
6
|
+
{_: :a, href: i.localURL(e), c: i.uri.match(/(gif|jpe?g|png)$/i) ? {_: :img, src: i.uri+'?y=scaleImage&px=233'} : i.uri.sub(/.*\//,'')}}
|
7
|
+
|
8
|
+
[(H.once e, 'dir', (H.css '/css/ls')),
|
9
|
+
i.map{|u,r|
|
10
|
+
url = r.E.localURL e
|
11
|
+
{class: :dir, style: "background-color: #{E.cs}", # dir wrapper
|
12
|
+
c: [{c: [{_: :a, href: url.t + '?view=ls', c: r.uri.sub('http://'+e['SERVER_NAME'],'')},
|
13
|
+
{_: :a, href: url.t, c: '/'}]},
|
14
|
+
r[Posix+'dir#child'].do{|c|c.map{|c|a[c]}}]}}]}
|
15
|
+
|
16
|
+
F['view/'+MIMEtype+'inode/directory'] = F['view/dir']
|
17
|
+
|
18
|
+
fn 'view/ls',->i,e{
|
19
|
+
dir = e['uri'].E
|
20
|
+
path = dir.pathSegment
|
21
|
+
up = (!path || path.uri == '/') ? '/' : dir.parent.url
|
22
|
+
i = i.dup
|
23
|
+
i.delete_if{|u,r|!r[Stat+'ftype']}
|
24
|
+
f = {}
|
25
|
+
['uri', Posix+'dir#child', Stat+'ftype', Stat+'mtime', Stat+'size'].map{|p|f[p] = true}
|
26
|
+
i.values.map{|r|
|
27
|
+
r.class==Hash &&
|
28
|
+
r.delete_if{|p,o|!f[p]}}
|
29
|
+
[(H.css '/css/ls'),
|
30
|
+
{_: :a, class: :up, href: up+'?view=ls', c: '↑'},
|
31
|
+
{class: :ls, c: (Fn 'view/table',i,e)},'<br clear=all>',
|
32
|
+
{_: :a, class: :down, href: e['uri'].E.url.t, c: '↓'}]}
|
33
|
+
|
34
|
+
# user-patchable default-handler
|
35
|
+
fn '/GET',->e,r{
|
36
|
+
x = 'index.html'
|
37
|
+
i = [e,e.pathSegment].compact.map{|e|e.as x}.find &:e
|
38
|
+
if i
|
39
|
+
if e.uri[-1] == '/' # inside dir?
|
40
|
+
i.env(r).getFile # show index
|
41
|
+
else # descend to indexed dir
|
42
|
+
[301, {Location: e.uri.t}, []]
|
43
|
+
end
|
44
|
+
else
|
45
|
+
# default handler
|
46
|
+
e.response
|
47
|
+
end}
|
48
|
+
|
49
|
+
end
|