infod 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/infod.rb +52 -12
  2. data/infod/{Th/404.rb → 404.rb} +4 -16
  3. data/infod/500.rb +53 -0
  4. data/infod/GET.rb +104 -0
  5. data/infod/HEAD.rb +23 -0
  6. data/infod/HTTP.rb +105 -0
  7. data/infod/{Th/PATCH.rb → PATCH.rb} +0 -0
  8. data/infod/POST.rb +34 -0
  9. data/infod/audio.rb +30 -0
  10. data/infod/blog.rb +34 -0
  11. data/infod/cal.rb +72 -0
  12. data/infod/{Es/code.rb → code.rb} +7 -4
  13. data/infod/constants.rb +55 -0
  14. data/infod/{Es/css.rb → css.rb} +0 -0
  15. data/infod/{Es/csv.rb → csv.rb} +0 -0
  16. data/infod/{Es/du.rb → du.rb} +0 -0
  17. data/infod/edit.rb +73 -0
  18. data/infod/{H/facets.rb → facets.rb} +20 -11
  19. data/infod/{Es/feed.rb → feed.rb} +17 -16
  20. data/infod/{Es/find.rb → find.rb} +2 -3
  21. data/infod/forum.rb +13 -0
  22. data/infod/{Es/fs.rb → fs.rb} +5 -2
  23. data/infod/glob.rb +26 -0
  24. data/infod/graph.rb +123 -0
  25. data/infod/{Es/grep.rb → grep.rb} +2 -2
  26. data/infod/{Es/groonga.rb → groonga.rb} +41 -33
  27. data/infod/{H/histogram.rb → histogram.rb} +23 -16
  28. data/infod/html.rb +231 -0
  29. data/infod/{Es/image.rb → image.rb} +16 -26
  30. data/infod/{Es/index.rb → index.rb} +38 -25
  31. data/infod/infod.rb +52 -12
  32. data/infod/json.rb +38 -0
  33. data/infod/{Es/kv.rb → kv.rb} +3 -9
  34. data/infod/{Y.rb → lambda.rb} +18 -1
  35. data/infod/ls.rb +49 -0
  36. data/infod/mail.rb +90 -0
  37. data/infod/{Es/man.rb → man.rb} +3 -15
  38. data/infod/{H/microblog.rb → microblog.rb} +22 -31
  39. data/infod/{K.rb → mime.rb} +68 -52
  40. data/infod/{N.rb → names.rb} +78 -45
  41. data/infod/page.rb +13 -0
  42. data/infod/postscript.rb +26 -0
  43. data/infod/rdf.rb +51 -0
  44. data/infod/{Rb.rb → ruby.rb} +18 -33
  45. data/infod/{Es/schema.rb → schema.rb} +22 -7
  46. data/infod/{Es/search.rb → search.rb} +5 -11
  47. data/infod/{Es/sh.rb → sh.rb} +0 -0
  48. data/infod/{Es/text.rb → text.rb} +33 -29
  49. data/infod/{H/threads.rb → threads.rb} +17 -27
  50. data/infod/{H/time.rb → time.rb} +14 -34
  51. data/infod/{H/who.rb → whois.rb} +6 -4
  52. data/infod/{H/wiki.rb → wiki.rb} +0 -0
  53. metadata +54 -64
  54. data/config.ru +0 -3
  55. data/infod/Es.rb +0 -31
  56. data/infod/Es/filter.rb +0 -75
  57. data/infod/Es/glob.rb +0 -22
  58. data/infod/Es/html.rb +0 -271
  59. data/infod/Es/in.rb +0 -68
  60. data/infod/Es/json.rb +0 -68
  61. data/infod/Es/ls.rb +0 -58
  62. data/infod/Es/mail.rb +0 -87
  63. data/infod/Es/mime.rb +0 -59
  64. data/infod/Es/out.rb +0 -52
  65. data/infod/Es/pager.rb +0 -34
  66. data/infod/Es/pdf.rb +0 -19
  67. data/infod/Es/rdf.rb +0 -35
  68. data/infod/H.rb +0 -15
  69. data/infod/H/audio.rb +0 -19
  70. data/infod/H/blog.rb +0 -15
  71. data/infod/H/cal.rb +0 -81
  72. data/infod/H/edit.rb +0 -88
  73. data/infod/H/forum.rb +0 -4
  74. data/infod/H/hf.rb +0 -114
  75. data/infod/H/mail.rb +0 -92
  76. data/infod/Th.rb +0 -36
  77. data/infod/Th/500.rb +0 -41
  78. data/infod/Th/GET.rb +0 -62
  79. data/infod/Th/HEAD.rb +0 -5
  80. data/infod/Th/POST.rb +0 -39
  81. data/infod/Th/perf.rb +0 -37
  82. data/infod/Th/uid.rb +0 -24
  83. 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
- [{_: :a, href: i.url,
43
- c: {_: :img,
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+'?triplr=triplrImage&view=img',
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 selector-based search
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 input type-normalization
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['prev'] = {'uri' => 'prev', 'url' => desc.url,'d' => 'desc'}
45
- m['next'] = {'uri' => 'next', 'url' => asc.url, 'd' => 'asc'}
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
- a,b = s[0], s.size > 1 && s.pop
61
- desc,asc = r['d'] && r['d']=='asc' && [a,b]||[b,a]
62
- # insert pointers in response-graph
63
- m['prev']={'uri' => 'prev','url' => d.url,'d' => 'desc','offset' => desc.uri} if desc
64
- m['next']={'uri' => 'next','url' => d.url,'d' => 'asc', 'offset' => asc.uri} if asc
65
- s }}
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
- F['set/indexPO'] = F['set/index']
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 n=8,d=:desc,s=nil,o=nil
87
- pIndex.subtree(n,d,s).map &:ro
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&view=page&v=linkPO&c=12', c: p}}}]).hR}
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/o index-traversal pointers
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
- d.map{|u,r| {c: {_: :a, href: r.url+'?set=indexPO&p=' + (URI.escape p) + '&view=page&views=timegraph,mail&v=multi&c=8', c: u}}}]}
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
- # the table of elements
3
-
4
- # Es infrastructure
5
- # H HTML
6
- # K constants
7
- # N naming
8
- # Rb Ruby native-types
9
- # Th HTTP
10
- # Y lambdas
11
-
12
- %w{Y K Rb N Es H Th}.map{|e| require 'infod/' + e}
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
@@ -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 resource
31
- # puts "link #{o} #{t}"
32
- o.ln t
30
+ o.ln t # hard link
33
31
  elsif o.e
34
- # symlink resource
35
- # puts "symlink #{o} #{t}"
36
- o.ln_s t
32
+ o.ln_s t # symbolic link
37
33
  else
38
- # name resource
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
@@ -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: '&uarr;'},
31
+ {class: :ls, c: (Fn 'view/table',i,e)},'<br clear=all>',
32
+ {_: :a, class: :down, href: e['uri'].E.url.t, c: '&darr;'}]}
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