infod 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/infod/{H/time.rb → time.rb}
RENAMED
@@ -1,7 +1,7 @@
|
|
1
1
|
#watch __FILE__
|
2
2
|
|
3
3
|
class Time
|
4
|
-
def html; H({_: :time, datetime: iso8601, c: to_s}) end
|
4
|
+
def html e=nil; H({_: :time, datetime: iso8601, c: to_s}) end
|
5
5
|
end
|
6
6
|
|
7
7
|
class Object
|
@@ -17,14 +17,12 @@ end
|
|
17
17
|
|
18
18
|
class E
|
19
19
|
|
20
|
-
# linked-timeline
|
21
20
|
fn 'view/timegraph',->g,e{
|
22
|
-
i = F['
|
23
|
-
Fn '
|
21
|
+
i = F['itemview/timegraph']
|
22
|
+
Fn 'baseview/timegraph',g,e,->{
|
24
23
|
g.map{|u,r|i.(r,e)}}}
|
25
|
-
|
26
|
-
|
27
|
-
fn 'view/timegraph/base',->d,e,c{
|
24
|
+
|
25
|
+
fn 'baseview/timegraph',->d,e,c{
|
28
26
|
Fn 'filter/timegraph', e.q,d,nil
|
29
27
|
|
30
28
|
e[:graph] = d
|
@@ -36,7 +34,7 @@ class E
|
|
36
34
|
[H.css('/css/timegraph'),{class: :timegraph, style: "height: #{h}em", c: c.()}]}
|
37
35
|
|
38
36
|
# timegraph entry
|
39
|
-
fn '
|
37
|
+
fn 'itemview/timegraph',->r,x{
|
40
38
|
|
41
39
|
# on resources w x-axis field
|
42
40
|
if r[x.q['x'] || Date]
|
@@ -57,8 +55,7 @@ class E
|
|
57
55
|
}]},
|
58
56
|
|
59
57
|
# arc(s)
|
60
|
-
{_: :svg, c:
|
61
|
-
r[arc].do{|a|a.map{|e|
|
58
|
+
{_: :svg, c: r.class==Hash && r[arc].do{|a|a.map{|e|
|
62
59
|
# target resource
|
63
60
|
x[:graph][e.uri].do{|e|
|
64
61
|
# arc path
|
@@ -78,8 +75,8 @@ class E
|
|
78
75
|
y = e['y'] # y property
|
79
76
|
|
80
77
|
# 2D values
|
81
|
-
vX = m.map{|_,r|r[x]}.flatten.compact.map(&:to_time).map &:to_f
|
82
|
-
vY = m.map{|_,r|r[y]}.flatten.compact.map &:to_f
|
78
|
+
vX = m.map{|_,r|r[x] if r.class==Hash}.flatten.compact.map(&:to_time).map &:to_f
|
79
|
+
vY = m.map{|_,r|r[y] if r.class==Hash}.flatten.compact.map &:to_f
|
83
80
|
maxX = vX.max || 0
|
84
81
|
minX = vX.min || 0
|
85
82
|
maxY = vY.max || 0
|
@@ -91,28 +88,11 @@ class E
|
|
91
88
|
|
92
89
|
# annotate resources
|
93
90
|
m.map{|u,r|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
fn Render+'application/timeline',->d,e{
|
101
|
-
{dateTimeFormat: 'iso8601',
|
102
|
-
events: d.values.map{|r|
|
103
|
-
r[Date].do{|d|
|
104
|
-
{description: r.uri,
|
105
|
-
title: r[Title],
|
106
|
-
start: [*d][0],
|
107
|
-
link: r.url,
|
108
|
-
}}}.compact}.to_json}
|
109
|
-
|
110
|
-
fn 'head/timeline',->d,e{
|
111
|
-
['<script>var t="'+e['REQUEST_PATH']+e.q.except('view','?').merge({format: 'application/timeline'}).qs+'"</script>',
|
112
|
-
(H.js '/js/timeline'),
|
113
|
-
(H.js 'http://api.simile-widgets.org/timeline/2.3.1/timeline-api')]}
|
114
|
-
|
115
|
-
fn 'view/timeline',->d,e{'<div id="tl" class="timeline-default" style="height: 300px;"></div>'}
|
91
|
+
if r.class==Hash
|
92
|
+
r['x'] = r[x].class==Array && r[x][0].do{|v|(maxX - v.to_time.to_f)*scaleX} || 0
|
93
|
+
r['y'] = y.do{|y|[*r[y]][0].do{|v|(maxY - v.to_f)*scaleY} || 0} || rand(100)
|
94
|
+
end
|
95
|
+
}}
|
116
96
|
|
117
97
|
# tripleStream -> tripleStream
|
118
98
|
def dateNorm *f
|
data/infod/{H/who.rb → whois.rb}
RENAMED
@@ -1,9 +1,11 @@
|
|
1
1
|
#watch __FILE__
|
2
2
|
class E
|
3
3
|
|
4
|
+
# shorthand-URL endpoints to look-up people in index
|
5
|
+
|
4
6
|
fn '/whois/GET',->e,r{
|
5
|
-
|
6
|
-
|
7
|
+
w = (r.q['p']||'').match(/to$/) ? 'to' : 'from'
|
8
|
+
[302,{Location: '/'+w+'/'+(URI.escape (r.q['q']||''))},[]]}
|
7
9
|
|
8
10
|
fn '/to/GET',->e,r{
|
9
11
|
name = e.pathSegment.uri.sub('/to/','/').tail
|
@@ -12,7 +14,7 @@ class E
|
|
12
14
|
else
|
13
15
|
H({style: 'text-align: center',
|
14
16
|
c: [To.E.rangeP.map(&:uri).grep(/#{name}/).map{|n|
|
15
|
-
{_: :a,href: n.E.url+'?set=indexPO&p=sioc:addressed_to
|
17
|
+
{_: :a,href: n.E.url+'?set=indexPO&p=sioc:addressed_to', c: n}},
|
16
18
|
{_: :style, c: "a {display:block;text-decoration:none}"}]}).hR
|
17
19
|
end}
|
18
20
|
|
@@ -23,7 +25,7 @@ class E
|
|
23
25
|
else
|
24
26
|
H({style: 'text-align: center',
|
25
27
|
c: [Creator.E.rangeP(1e4).map(&:uri).grep(/#{name}/).map{|n|
|
26
|
-
{_: :a,href: n.E.url+'?set=indexPO&p=sioc:has_creator
|
28
|
+
{_: :a,href: n.E.url+'?set=indexPO&p=sioc:has_creator', c: n}},
|
27
29
|
{_: :style, c: "a {display:block;text-decoration:none}"}]}).hR
|
28
30
|
end}
|
29
31
|
|
data/infod/{H/wiki.rb → wiki.rb}
RENAMED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: infod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-01-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rack
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
-
description:
|
62
|
+
description: www-server
|
63
63
|
email: _@whats-your.name
|
64
64
|
executables:
|
65
65
|
- infod
|
@@ -68,67 +68,57 @@ extra_rdoc_files: []
|
|
68
68
|
files:
|
69
69
|
- bin/infod
|
70
70
|
- infod.rb
|
71
|
-
-
|
72
|
-
- infod/
|
73
|
-
- infod/
|
74
|
-
- infod/
|
75
|
-
- infod/
|
76
|
-
- infod/
|
77
|
-
- infod/
|
78
|
-
- infod/
|
79
|
-
- infod/
|
80
|
-
- infod/
|
81
|
-
- infod/
|
82
|
-
- infod/
|
83
|
-
- infod/
|
84
|
-
- infod/
|
85
|
-
- infod/
|
86
|
-
- infod/
|
87
|
-
- infod/H/threads.rb
|
88
|
-
- infod/H/mail.rb
|
89
|
-
- infod/H/blog.rb
|
90
|
-
- infod/H/facets.rb
|
91
|
-
- infod/H/cal.rb
|
92
|
-
- infod/H/who.rb
|
93
|
-
- infod/H/wiki.rb
|
94
|
-
- infod/H/histogram.rb
|
95
|
-
- infod/H/time.rb
|
96
|
-
- infod/K.rb
|
97
|
-
- infod/Rb.rb
|
98
|
-
- infod/Y.rb
|
71
|
+
- infod/audio.rb
|
72
|
+
- infod/fs.rb
|
73
|
+
- infod/whois.rb
|
74
|
+
- infod/csv.rb
|
75
|
+
- infod/grep.rb
|
76
|
+
- infod/microblog.rb
|
77
|
+
- infod/forum.rb
|
78
|
+
- infod/json.rb
|
79
|
+
- infod/graph.rb
|
80
|
+
- infod/sh.rb
|
81
|
+
- infod/PATCH.rb
|
82
|
+
- infod/POST.rb
|
83
|
+
- infod/404.rb
|
84
|
+
- infod/man.rb
|
85
|
+
- infod/GET.rb
|
86
|
+
- infod/constants.rb
|
99
87
|
- infod/infod.rb
|
100
|
-
- infod/
|
101
|
-
- infod/
|
102
|
-
- infod/
|
103
|
-
- infod/
|
104
|
-
- infod/
|
105
|
-
- infod/
|
106
|
-
- infod/
|
107
|
-
- infod/
|
108
|
-
- infod/
|
109
|
-
- infod/
|
110
|
-
- infod/
|
111
|
-
- infod/
|
112
|
-
- infod/
|
113
|
-
- infod/
|
114
|
-
- infod/
|
115
|
-
- infod/
|
116
|
-
- infod/
|
117
|
-
- infod/
|
118
|
-
- infod/
|
119
|
-
- infod/
|
120
|
-
- infod/
|
121
|
-
- infod/
|
122
|
-
- infod/
|
123
|
-
- infod/
|
124
|
-
- infod/
|
125
|
-
- infod/
|
126
|
-
- infod/
|
127
|
-
- infod/
|
128
|
-
- infod/
|
129
|
-
- infod/
|
130
|
-
- infod/
|
131
|
-
- infod/
|
88
|
+
- infod/HTTP.rb
|
89
|
+
- infod/glob.rb
|
90
|
+
- infod/edit.rb
|
91
|
+
- infod/ls.rb
|
92
|
+
- infod/page.rb
|
93
|
+
- infod/html.rb
|
94
|
+
- infod/threads.rb
|
95
|
+
- infod/500.rb
|
96
|
+
- infod/code.rb
|
97
|
+
- infod/text.rb
|
98
|
+
- infod/HEAD.rb
|
99
|
+
- infod/feed.rb
|
100
|
+
- infod/ruby.rb
|
101
|
+
- infod/du.rb
|
102
|
+
- infod/groonga.rb
|
103
|
+
- infod/mail.rb
|
104
|
+
- infod/blog.rb
|
105
|
+
- infod/image.rb
|
106
|
+
- infod/facets.rb
|
107
|
+
- infod/cal.rb
|
108
|
+
- infod/css.rb
|
109
|
+
- infod/postscript.rb
|
110
|
+
- infod/kv.rb
|
111
|
+
- infod/rdf.rb
|
112
|
+
- infod/schema.rb
|
113
|
+
- infod/wiki.rb
|
114
|
+
- infod/search.rb
|
115
|
+
- infod/mime.rb
|
116
|
+
- infod/names.rb
|
117
|
+
- infod/histogram.rb
|
118
|
+
- infod/index.rb
|
119
|
+
- infod/find.rb
|
120
|
+
- infod/time.rb
|
121
|
+
- infod/lambda.rb
|
132
122
|
homepage: http://whats-your.name/www/
|
133
123
|
licenses:
|
134
124
|
- Unlicense
|
@@ -153,5 +143,5 @@ rubyforge_project:
|
|
153
143
|
rubygems_version: 1.8.23
|
154
144
|
signing_key:
|
155
145
|
specification_version: 3
|
156
|
-
summary:
|
146
|
+
summary: www-server
|
157
147
|
test_files: []
|
data/config.ru
DELETED
data/infod/Es.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
%w{
|
2
|
-
code
|
3
|
-
css
|
4
|
-
csv
|
5
|
-
du
|
6
|
-
feed
|
7
|
-
filter
|
8
|
-
find
|
9
|
-
fs
|
10
|
-
glob
|
11
|
-
grep
|
12
|
-
groonga
|
13
|
-
html
|
14
|
-
image
|
15
|
-
in
|
16
|
-
index
|
17
|
-
json
|
18
|
-
kv
|
19
|
-
ls
|
20
|
-
mail
|
21
|
-
man
|
22
|
-
mime
|
23
|
-
out
|
24
|
-
pager
|
25
|
-
pdf
|
26
|
-
rdf
|
27
|
-
schema
|
28
|
-
search
|
29
|
-
sh
|
30
|
-
text
|
31
|
-
}.map{|e|require_relative 'Es/'+e}
|
data/infod/Es/filter.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
class E
|
2
|
-
|
3
|
-
# narrow to specified properties
|
4
|
-
fn 'filter/p',->e,m,_{
|
5
|
-
a=Hash[*e['p'].split(/,/).map(&:expand).map{|p|[p,true]}.flatten]
|
6
|
-
m.values.map{|r|
|
7
|
-
r.delete_if{|p,o|!a[p]}}}
|
8
|
-
|
9
|
-
fn 'filter/frag',->e,m,r{
|
10
|
-
f = [r.uri].concat m['frag']['res']
|
11
|
-
m.keys.map{|u|
|
12
|
-
m.delete u unless f.member? u}}
|
13
|
-
|
14
|
-
fn 'filter/basic',->o,m,_{
|
15
|
-
d=m.values
|
16
|
-
o['match'] && (p=o['matchP'].expand
|
17
|
-
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_s.match o['match']}})
|
18
|
-
o['min'] && (min=o['min'].to_f
|
19
|
-
p=o['minP'].expand
|
20
|
-
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_f >= min }})
|
21
|
-
o['max'] && (max=o['max'].to_f
|
22
|
-
p=o['maxP'].expand
|
23
|
-
d=d.select{|r|r[p].do{|p|(p.class==Array ? p[0] : p).to_f <= max }})
|
24
|
-
o['sort'] && (p=o['sort'].expand
|
25
|
-
_ = d.partition{|r|r[p]}
|
26
|
-
d =_[0].sort_by{|r|r[p]}.concat _[1] rescue d)
|
27
|
-
o['sortN'] && (p=o['sortN'].expand
|
28
|
-
_ = d.partition{|r|r[p]}
|
29
|
-
d =_[0].sort_by{|r|
|
30
|
-
(r[p].class==Array && r[p] || [r[p]])[0].do{|d|
|
31
|
-
d.class==String && d.to_i || d
|
32
|
-
}
|
33
|
-
}.concat _[1])
|
34
|
-
o.has_key?('reverse') && d.reverse!
|
35
|
-
m.clear;d.map{|r|m[r['uri']]=r}}
|
36
|
-
|
37
|
-
fn 'filter/map',->o,m,_{
|
38
|
-
o.except('filter','graph','view').map{|p,n|
|
39
|
-
p=p.expand
|
40
|
-
n=n.expand
|
41
|
-
p!=n &&
|
42
|
-
m.values.map{|r|
|
43
|
-
r[p].do{|o|
|
44
|
-
r[n]=o
|
45
|
-
r.delete p }}}}
|
46
|
-
|
47
|
-
fn 'view/map',->d,e{
|
48
|
-
[H.js('/js/normal'),(H.once e,:mu,(H.js '/js/mu')),
|
49
|
-
'<style>.b {display:inline-block;font-weight:bold;padding-right:.8em;text-align:right;min-width:12em}
|
50
|
-
.exerpt {display:inline-block;max-height:1em;overflow:hidden;max-width:44em;font-size: .9em} </style>',
|
51
|
-
{_: :form, c:
|
52
|
-
[d.values.map(&:keys).flatten.uniq.-(['uri']).do{|ps|
|
53
|
-
ps.map{|p|
|
54
|
-
[{class: :b, c: p},{_: :select, name: p, c:
|
55
|
-
(ps + [Date,Creator,Content,Title]).map{|q|
|
56
|
-
{_: :option, c: q}.
|
57
|
-
update(p==q ? {selected: :selected}:{})}},
|
58
|
-
{class: :exerpt, c: d.values.map{|r|r[p]}.flatten.uniq.html},
|
59
|
-
'<br>']}},
|
60
|
-
{_: :input, type: :hidden, name: :view, value: :tab},
|
61
|
-
{_: :input, type: :hidden, name: :filter, value: :map},
|
62
|
-
{_: :input, type: :submit}
|
63
|
-
]}]}
|
64
|
-
|
65
|
-
def self.filter o,m,r
|
66
|
-
o['filter'].do{|f|f.split(/,/).map{|f|Fn 'filter/'+f,o,m,r}}
|
67
|
-
Fn'filter/basic',o,m,r if o.has_any_key ['reverse','sort','max','min','match']
|
68
|
-
m
|
69
|
-
end
|
70
|
-
|
71
|
-
def E.graphProperties g
|
72
|
-
g.values.select{|v|v.respond_to? :keys}.map(&:keys).flatten.uniq
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
data/infod/Es/glob.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
class E
|
2
|
-
|
3
|
-
# glob :: pattern -> [E]
|
4
|
-
def glob p=""
|
5
|
-
(Pathname.glob d + p).map &:E
|
6
|
-
end
|
7
|
-
|
8
|
-
fn 'set/glob',->d,e=nil,_=nil{
|
9
|
-
[d,d.pathSegment].compact.map(&:glob).flatten[0..3e3]}
|
10
|
-
|
11
|
-
fn 'req/randomFile',->e,r{
|
12
|
-
g = F['set/glob'][e]
|
13
|
-
!g.empty? ? [302, {Location: g.random.uri}, []] : [404]}
|
14
|
-
|
15
|
-
def docs
|
16
|
-
doc = self if e # directly-referenced doc
|
17
|
-
docs = docBase.glob ".{e,html,n3,nt,owl,rdf,ttl}" # basename-sharing docs
|
18
|
-
dir = (d? && uri[-1]=='/' && uri.size>1) ? c : [] # trailing slash descends
|
19
|
-
[doc,docs,dir].flatten.compact
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
data/infod/Es/html.rb
DELETED
@@ -1,271 +0,0 @@
|
|
1
|
-
#watch __FILE__
|
2
|
-
|
3
|
-
def H _
|
4
|
-
# Ruby object-literal syntax as HTML constructors
|
5
|
-
case _
|
6
|
-
when Hash then
|
7
|
-
'<'+(_[:_]||:div).to_s+(_.keys-[:_,:c]).map{|a|
|
8
|
-
' '+a.to_s+'='+"'"+
|
9
|
-
_[a].to_s.hsub({"'"=>'%27',
|
10
|
-
'>'=>'%3E',
|
11
|
-
'<'=>'%3C'})+"'"}.join+'>'+
|
12
|
-
(_[:c] ? (H _[:c]) : '')+
|
13
|
-
(_[:_] == :link ? '' : ('</'+(_[:_]||:div).to_s+'>'))
|
14
|
-
when Array then
|
15
|
-
_.map{|n|H n}.join
|
16
|
-
else
|
17
|
-
_.to_s
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class H
|
22
|
-
|
23
|
-
def H.[] h; H h end
|
24
|
-
|
25
|
-
def H.js a,inline=false
|
26
|
-
p=a+'.js'
|
27
|
-
inline ? {_: :script, c: p.E.r} :
|
28
|
-
{_: :script, type: "text/javascript", src: p}
|
29
|
-
end
|
30
|
-
|
31
|
-
def H.once e,n,*h
|
32
|
-
return if e[n]
|
33
|
-
e[n]=true
|
34
|
-
h
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
class Array
|
39
|
-
def html table=true
|
40
|
-
map(&:html).join ' '
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class Object
|
45
|
-
def html *a
|
46
|
-
name = self.class
|
47
|
-
href = "https://duckduckgo.com/?q=ruby+#{name}"
|
48
|
-
"<a href=#{href}><b>#{name}</b></a>"
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class String
|
53
|
-
def br
|
54
|
-
gsub(/\n/,"<br>\n")
|
55
|
-
end
|
56
|
-
def href name=nil
|
57
|
-
'<a href="'+self+'">'+(name||(Fn 'abbrURI',self))+'</a>'
|
58
|
-
end
|
59
|
-
def html
|
60
|
-
if match /\A(\/|http)[\S]+\Z/
|
61
|
-
href
|
62
|
-
else
|
63
|
-
self
|
64
|
-
end
|
65
|
-
rescue
|
66
|
-
self
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
class Fixnum
|
71
|
-
def html; H({_: :input, type: :number, value: to_s}) end
|
72
|
-
end
|
73
|
-
|
74
|
-
class Float
|
75
|
-
def html; H({_: :input, type: :number, value: to_s}) end
|
76
|
-
end
|
77
|
-
|
78
|
-
class TrueClass
|
79
|
-
def html; H({_: :input, type: :checkbox, title: :True, checked: :checked}) end
|
80
|
-
end
|
81
|
-
|
82
|
-
class FalseClass
|
83
|
-
def html; H({_: :input, type: :checkbox, title: :False}) end
|
84
|
-
end
|
85
|
-
|
86
|
-
class Hash
|
87
|
-
def html
|
88
|
-
H({_: :table, class: :html, c:
|
89
|
-
map{|k,v|
|
90
|
-
{_: :tr, property: k, c:
|
91
|
-
[{_: :td,
|
92
|
-
c: {_: :a, name: k,
|
93
|
-
href: (k == 'uri' ? v : k),
|
94
|
-
c: (Fn 'abbrURI',k)}, class: :key},
|
95
|
-
{_: :td,
|
96
|
-
c: (case k
|
97
|
-
when E::Content
|
98
|
-
{_: :pre, style: "white-space: pre-wrap", c: v}
|
99
|
-
when 'uri'
|
100
|
-
u = v.E
|
101
|
-
{_: :a, id: u, href: u.url, c: v}
|
102
|
-
else
|
103
|
-
v.html
|
104
|
-
end), class: :val}].cr}}.cr})
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
class E
|
109
|
-
def html name=nil,l=false
|
110
|
-
(l ? url : uri).href name
|
111
|
-
end
|
112
|
-
|
113
|
-
def link
|
114
|
-
html '#',true
|
115
|
-
end
|
116
|
-
|
117
|
-
fn 'abbrURI',->u{
|
118
|
-
u.to_s.sub(/(?<scheme>[a-z]+:\/\/)?(?<abbr>.*?)(?<frag>[^#\/]*)$/,
|
119
|
-
'<div class="abbr"><div class="scheme">\k<scheme></div>\k<abbr></div><div class="frag">\k<frag></div>')}
|
120
|
-
|
121
|
-
fn 'head',->d,e{
|
122
|
-
[{_: :title, c: e.uri},
|
123
|
-
(Fn 'head.formats',e),
|
124
|
-
(Fn 'head.icon')].cr}
|
125
|
-
|
126
|
-
fn 'head.formats',->e{
|
127
|
-
formats = %w{text/plain text/n3 application/json+ld}
|
128
|
-
formats.map{|f|
|
129
|
-
{_: :link, rel: :meta, type: f,
|
130
|
-
href:'http://' + e['SERVER_NAME'] + e['REQUEST_PATH'] + e.q.merge({'format' => f}).qs}}.cr}
|
131
|
-
|
132
|
-
fn 'head.icon',->{{_: :link, href:'/css/misc/favicon.ico', rel: :icon}}
|
133
|
-
|
134
|
-
fn 'view/select',->d,e{#(Fn 'view/divine/set',d,e)||
|
135
|
-
(Fn 'view/divine/files',d,e)||
|
136
|
-
d.values.map{|r|Fn 'view/divine/resource',r,e}}
|
137
|
-
|
138
|
-
# default view
|
139
|
-
F['view'] = F['view/select']
|
140
|
-
|
141
|
-
fn 'view/base',->d,e{
|
142
|
-
[H.once(e,'base',H.css('/css/html')),
|
143
|
-
d.values.map(&:html)]}
|
144
|
-
|
145
|
-
# select a view based on RDF-type majority
|
146
|
-
fn 'view/divine/set',->d,e{
|
147
|
-
# we'd be throwing away oddball resources to select one view for all of them
|
148
|
-
# but maybe you have a specific reason to
|
149
|
-
# inbuilt views support calling on set or per-resource basis, via "once" spec of set-wide components
|
150
|
-
# so views are selected per-resource unless you hack here..
|
151
|
-
}
|
152
|
-
|
153
|
-
fn 'view/divine/files',->d,e{
|
154
|
-
d.values.map{|e|e.E.base}.do{|b|
|
155
|
-
s = b.size.to_f # size of set
|
156
|
-
t = 0.42 # threshold, max of 0.5 as file and RDF resource are separate
|
157
|
-
if b.grep(/^msg\./).size / s > t
|
158
|
-
Fn 'view/threads',d,e
|
159
|
-
|
160
|
-
elsif b.grep(AudioFile).size / s > t
|
161
|
-
Fn 'view/audio', d,e
|
162
|
-
|
163
|
-
elsif b.grep(/(gif|jpe?g|png)$/i).size / s > t
|
164
|
-
Fn 'view/th', d,e
|
165
|
-
|
166
|
-
elsif b.grep(/\.log$/).size / s > t
|
167
|
-
Fn 'view/chat', d,e
|
168
|
-
|
169
|
-
else false
|
170
|
-
end}}
|
171
|
-
|
172
|
-
# select a view for a RDF resource
|
173
|
-
fn 'view/divine/resource',->r,e{
|
174
|
-
graph = {r.uri => r}
|
175
|
-
view = F['view/base']
|
176
|
-
# find types, skipping malformed/missing info
|
177
|
-
if r.class == Hash
|
178
|
-
r[Type].do{|types|
|
179
|
-
views = types.map{|t|
|
180
|
-
# discard non-URIs
|
181
|
-
t.uri if t.respond_to? :uri}.
|
182
|
-
compact.map{|t|
|
183
|
-
subtype = t
|
184
|
-
type = subtype.split(/\//)[-2]
|
185
|
-
[F['view/' + subtype],
|
186
|
-
F['view/' + type]]}.flatten.compact
|
187
|
-
view = views[0] unless views.empty?}
|
188
|
-
end
|
189
|
-
view[graph,e]}
|
190
|
-
|
191
|
-
# multiple views (comma-separated)
|
192
|
-
fn 'view/multi',->d,e{
|
193
|
-
e.q['views'].split(',').map{|v|
|
194
|
-
F['view/'+v].do{|f|f[d,e]}}}
|
195
|
-
|
196
|
-
def triplrBlob
|
197
|
-
glob.select(&:f).do{|f|f.map{|r|
|
198
|
-
yield r.uri,Type,E('blob')
|
199
|
-
yield r.uri,Content,r.r}} end
|
200
|
-
|
201
|
-
def triplrHref enc=nil
|
202
|
-
puts "triplrHref #{uri} #{d}"
|
203
|
-
yield uri,Content,(f && read).do{|r|enc ? r.force_encoding(enc).to_utf8 : r}.hrefs
|
204
|
-
end
|
205
|
-
|
206
|
-
fn Render+'text/html',->d,e{
|
207
|
-
v = e.q['view'].to_s
|
208
|
-
h = F['head/'+v] || F['head']
|
209
|
-
v = F['view/'+v] || F['view']
|
210
|
-
H(e.q.has_key?('un') ? v[d,e] :
|
211
|
-
['<!DOCTYPE html>',
|
212
|
-
{_: :html,
|
213
|
-
c: [{_: :head,
|
214
|
-
c: ['<meta charset="utf-8" />',
|
215
|
-
h[d,e]]},
|
216
|
-
{_: :body, c: v[d,e]}].cr}].cr)}
|
217
|
-
|
218
|
-
|
219
|
-
# property-selector toolbar (requires RDFa views)
|
220
|
-
fn 'view/p',->d,e{
|
221
|
-
[H.once(e,'property.toolbar',H.once(e,'p',(H.once e,:mu,H.js('/js/mu')),
|
222
|
-
H.js('/js/p'),
|
223
|
-
H.css('/css/table')),
|
224
|
-
{_: :a, href: '#', c: '-', id: :hideP},
|
225
|
-
{_: :a, href: '#', c: '+', id: :showP},
|
226
|
-
{_: :span, id: 'properties',
|
227
|
-
c: E.graphProperties(d).map{|k|
|
228
|
-
{_: :a, class: :n, href: k, c: k.label+' '}}},
|
229
|
-
{_: :style, id: :pS},
|
230
|
-
{_: :style, id: :lS}),
|
231
|
-
(Fn 'view/'+(e.q['pv']||'table'),d,e)]}
|
232
|
-
|
233
|
-
# table-cell placement on sparse matrix of rows/columns
|
234
|
-
# cal.rb contains an example usage
|
235
|
-
fn 'view/t',->d,e,l=nil,a=nil{
|
236
|
-
[H.once(e,'table',H.css('/css/table')),
|
237
|
-
{_: :table, c:
|
238
|
-
{_: :tbody, c: (Fn 'table/'+(l||e.q['table']),d).do{|t|
|
239
|
-
rx = t.keys.max
|
240
|
-
rm = t.keys.min
|
241
|
-
c = t.values.map(&:keys)
|
242
|
-
cm = c.map(&:min).min
|
243
|
-
cx = c.map(&:max).max
|
244
|
-
(rm..rx).map{|r|
|
245
|
-
{_: :tr, c:
|
246
|
-
t[r].do{|r|
|
247
|
-
(cm..cx).map{|c|
|
248
|
-
r[c].do{|c|
|
249
|
-
{_: :td, class: :cell, c:(Fn 'view/'+(a||e.q['cellview']),c,e)}
|
250
|
-
}||{_: :td}}}}}}}}]}
|
251
|
-
|
252
|
-
fn 'view/table',->i,e{[H.css('/css/table'),(Fn 'table',i.values,e)]}
|
253
|
-
|
254
|
-
fn 'table',->es,q=nil{
|
255
|
-
ks = {} # predicate table
|
256
|
-
es.map{|e|e.respond_to?(:keys) &&
|
257
|
-
e.keys.map{|k|ks[k]=true}}
|
258
|
-
keys = ks.keys
|
259
|
-
keys.empty? ? es.html :
|
260
|
-
H({_: :table,:class => :tab,
|
261
|
-
c: [{_: :tr,
|
262
|
-
c: keys.map{|k|
|
263
|
-
{_: :th, class: :label, property: k,
|
264
|
-
c: q ? {_: :a,
|
265
|
-
href: q['REQUEST_PATH']+q.q.except('reverse').merge({'sort'=>k}).merge(q.q.member?('reverse') ? {} : {'reverse'=>true}).qs,
|
266
|
-
c: (Fn 'abbrURI',k)} : k}}},
|
267
|
-
*es.map{|e|
|
268
|
-
{_: :tr, about: e.uri, c:
|
269
|
-
keys.map{|k| {_: :td, property: k, c: e[k].send(k=='uri' ? :href : :html)} }}}]})}
|
270
|
-
|
271
|
-
end
|