infod 0.0.1 → 0.0.2

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.
Files changed (93) hide show
  1. data/infod.rb +2 -3
  2. data/infod/Es.rb +31 -67
  3. data/infod/{W/source.rb → Es/code.rb} +6 -10
  4. data/infod/Es/css.rb +21 -0
  5. data/infod/{W → Es}/csv.rb +0 -0
  6. data/infod/Es/du.rb +16 -0
  7. data/infod/{W → Es}/feed.rb +13 -11
  8. data/infod/Es/filter.rb +75 -0
  9. data/infod/Es/find.rb +20 -0
  10. data/infod/Es/fs.rb +145 -136
  11. data/infod/Es/glob.rb +22 -0
  12. data/infod/Es/grep.rb +61 -0
  13. data/infod/Es/groonga.rb +47 -56
  14. data/infod/Es/html.rb +271 -0
  15. data/infod/Es/image.rb +114 -0
  16. data/infod/Es/in.rb +68 -0
  17. data/infod/Es/index.rb +183 -0
  18. data/infod/{W → Es}/json.rb +28 -4
  19. data/infod/Es/kv.rb +60 -0
  20. data/infod/Es/ls.rb +58 -0
  21. data/infod/Es/mail.rb +87 -0
  22. data/infod/Es/man.rb +112 -0
  23. data/infod/Es/mime.rb +59 -0
  24. data/infod/Es/out.rb +52 -0
  25. data/infod/{W/page.rb → Es/pager.rb} +7 -3
  26. data/infod/Es/pdf.rb +19 -0
  27. data/infod/Es/rdf.rb +35 -0
  28. data/infod/Es/schema.rb +99 -0
  29. data/infod/Es/search.rb +24 -0
  30. data/infod/Es/sh.rb +21 -0
  31. data/infod/{W → Es}/text.rb +26 -14
  32. data/infod/H.rb +15 -29
  33. data/infod/H/audio.rb +19 -0
  34. data/infod/H/blog.rb +15 -0
  35. data/infod/{W → H}/cal.rb +2 -31
  36. data/infod/H/edit.rb +88 -0
  37. data/infod/{W/examine/examine.rb → H/facets.rb} +17 -17
  38. data/infod/{W → H}/forum.rb +1 -0
  39. data/infod/{W/examine/sw.rb → H/hf.rb} +12 -12
  40. data/infod/H/histogram.rb +78 -0
  41. data/infod/H/mail.rb +92 -0
  42. data/infod/{W/chat.rb → H/microblog.rb} +21 -16
  43. data/infod/H/threads.rb +77 -0
  44. data/infod/H/time.rb +131 -0
  45. data/infod/H/who.rb +30 -0
  46. data/infod/{W → H}/wiki.rb +0 -0
  47. data/infod/K.rb +28 -60
  48. data/infod/N.rb +151 -74
  49. data/infod/Rb.rb +3 -3
  50. data/infod/Th.rb +27 -101
  51. data/infod/Th/404.rb +29 -36
  52. data/infod/Th/500.rb +36 -5
  53. data/infod/Th/GET.rb +48 -118
  54. data/infod/Th/POST.rb +31 -11
  55. data/infod/Th/perf.rb +37 -0
  56. data/infod/Th/util.rb +89 -0
  57. data/infod/Y.rb +24 -7
  58. data/infod/infod.rb +2 -3
  59. metadata +92 -64
  60. data/infod/Es/redis.rb +0 -3
  61. data/infod/Es/sqlite.rb +0 -3
  62. data/infod/Th/local.rb +0 -22
  63. data/infod/W.rb +0 -34
  64. data/infod/W/audio.rb +0 -56
  65. data/infod/W/blog.rb +0 -3
  66. data/infod/W/color.rb +0 -28
  67. data/infod/W/core.rb +0 -77
  68. data/infod/W/css.rb +0 -24
  69. data/infod/W/du.rb +0 -35
  70. data/infod/W/edit.rb +0 -8
  71. data/infod/W/examine/exhibit.rb +0 -34
  72. data/infod/W/examine/hist.rb +0 -55
  73. data/infod/W/examine/history.rb +0 -19
  74. data/infod/W/examine/normal.rb +0 -31
  75. data/infod/W/examine/protovis.rb +0 -30
  76. data/infod/W/examine/time/graph.rb +0 -86
  77. data/infod/W/examine/time/line.rb +0 -24
  78. data/infod/W/find.rb +0 -24
  79. data/infod/W/grep.rb +0 -27
  80. data/infod/W/html.rb +0 -143
  81. data/infod/W/image.rb +0 -61
  82. data/infod/W/kv.rb +0 -66
  83. data/infod/W/ls.rb +0 -50
  84. data/infod/W/mail.rb +0 -248
  85. data/infod/W/pdf.rb +0 -16
  86. data/infod/W/post.rb +0 -9
  87. data/infod/W/rdf.rb +0 -32
  88. data/infod/W/schema.rb +0 -172
  89. data/infod/W/search.rb +0 -33
  90. data/infod/W/shell.rb +0 -30
  91. data/infod/W/table.rb +0 -87
  92. data/infod/W/tree.rb +0 -26
  93. data/infod/W/vfs.rb +0 -175
@@ -1,86 +0,0 @@
1
- #watch __FILE__
2
- class E
3
-
4
- F["?"]||={}
5
- F["?"].update({'taft'=>{
6
- 'graph'=>'|',
7
- '|'=>'triplrMozHist',
8
- 'view'=>'page',
9
- 'v'=>'timegraph',
10
- 'arc'=>'referer'}})
11
-
12
- # massage data for timegraph
13
- fn 'filter/timegraph',->e,m,_{
14
-
15
- e['timegraph'] ||= true
16
-
17
- x = e['x'] || Date # x prop
18
- y = e['y'] # y property
19
-
20
- # 2D values
21
- vX = m.map{|_,r|r[x]}.flatten.compact.map(&:to_time).map &:to_f
22
- vY = m.map{|_,r|r[y]}.flatten.compact.map &:to_f
23
- maxX = vX.max
24
- minX = vX.min
25
- maxY = vY.max
26
- minY = vY.min
27
-
28
- # scaling-ratio to normalize values to %
29
- scaleX = 100/((maxX-minX).do{|v|v==0 ? 100 : v}||100)
30
- scaleY = 100/((maxY-minY).do{|v|v==0 ? 100 : v}||100)
31
-
32
- # annotate resources with positioning data
33
- m.map{|u,r|
34
- r['x'] = [*r[x]][0].do{|v|(maxX - v.to_time.to_f)*scaleX} || 0
35
- r['y'] = y.do{|y|[*r[y]][0].do{|v|(maxY - v.to_f)*scaleY} || 0} || rand(100)}
36
- }
37
-
38
- # a linked-timeline view
39
- fn 'view/timegraph',->d,e{
40
- # use standard structure for examine faceted-filtering
41
- i=F['view/timegraph/item']
42
- Fn 'view/timegraph/base',d,e,->{d.map{|u,r|i.(r,e)}}}
43
-
44
- # timegraph container-element
45
- fn 'view/timegraph/base',->d,e,c{
46
- Fn 'filter/timegraph', e.q, d, nil unless e.q['timegraph']==true
47
-
48
- e[:graph] = d
49
- e[:group] = {}
50
- e[:color] = E.c
51
-
52
- [H.css('/css/timegraph'),{class: :timegraph, c: c.()}]}
53
-
54
- # timegraph entry
55
- fn 'view/timegraph/item',->r,x{
56
- # skip resources w/o x-axis field
57
- if r[x.q['x'] || Date]
58
-
59
- labelP = x.q['label'].expand || Creator
60
- label = (r[labelP][0]).do{|l|
61
- l.respond_to?(:uri) ? l.uri : l.to_s}
62
- lc = x[:group][label] ||= E.c
63
-
64
- [{style: "top: #{r['x']}%; left: 0", class: :date, c: r[Date][0]},
65
- {style: "top: #{r['x']}%; left: #{r['y']}%",
66
- c: [{_: :a, href: r.url, c: '#', class: :link},
67
- {_: :a,
68
- title: r[Date][0],
69
- href: '#'+r.uri,
70
- class: :label,
71
- style: "background-color: #{lc}",
72
- c: label,
73
- }]},
74
-
75
- # arc(s)
76
- {_: :svg, c:
77
- r[x.q['arc'].expand].map{|e|
78
- # target resource
79
- x[:graph][e.uri].do{|e|
80
- # arc path
81
- {_: :line, class: :arc, stroke: x[:color], 'stroke-dasharray'=>"2,2",
82
- y1: e['x'].to_s+'%', x1: e['y'].to_s+'%',
83
- y2: r['x'].to_s+'%', x2: r['y'].to_s+'%'}}}}]
84
- end }
85
-
86
- end
@@ -1,24 +0,0 @@
1
- class E
2
-
3
- ## SIMILE Timeline
4
- # http://www.simile-widgets.org/
5
-
6
- # JSON format
7
- fn Render+'application/timeline',->d,e{
8
- {dateTimeFormat: 'iso8601',
9
- events: d.values.map{|r|
10
- r[Date].do{|d|
11
- {description: r.uri,
12
- title: r[Title],
13
- start: [*d][0],
14
- link: r.url,
15
- }}}.compact}.to_json}
16
-
17
- fn 'head/timeline',->d,e{
18
- ['<script>var t="'+e['REQUEST_PATH']+e.q.except('view','?').merge({format: 'application/timeline'}).qs+'"</script>',
19
- (H.js '/js/timeline'),
20
- (H.js 'http://api.simile-widgets.org/timeline/2.3.1/timeline-api')]}
21
-
22
- fn 'view/timeline',->d,e{'<div id="tl" class="timeline-default" style="height: 300px;"></div>'}
23
-
24
- end
data/infod/W/find.rb DELETED
@@ -1,24 +0,0 @@
1
- #watch __FILE__
2
- class E
3
-
4
- fn 'set/find',->e,q,m{
5
- t=q['day'] && q['day'].match(/^\d+$/) && '-ctime -'+q['day']
6
- s=q['size'] && q['size'].match(/^\d+$/) && '-size +'+q['size']+'M'
7
- r=q['q'] && '-iregex ' + ('.*'+q['q']+'.*').sh
8
- `find #{e.sh} #{t} #{s} #{r} | head -n 1024`.lines.map &:pathToURI}
9
-
10
- fn 'graph/find',->e,q,m{
11
- (Fn 'set/find', e,q,m).do{|f|
12
- if f.size < 256
13
- f.map{|r|r.fromStream m,:triplrInode,false}
14
- else
15
- f.map{|r|m[r.uri]=r}
16
- end}}
17
-
18
- fn 'view/find',->i,e{
19
- {_: :form, method: :GET, action: e['REQUEST_PATH'].t, style: 'float: right',
20
- c: [{_: :input, name: :graph, value: :find, type: :hidden},
21
- {_: :input, name: :view, value: :ls, type: :hidden},
22
- {_: :input, name: :q}]}}
23
-
24
- end
data/infod/W/grep.rb DELETED
@@ -1,27 +0,0 @@
1
- #watch __FILE__
2
- class E
3
-
4
- fn 'set/grep',->e,q,m{
5
- `grep -rl#{q.has_key?('i') && 'i'} #{q['q'].sh} #{e.sh}`.lines.map &:pathToURI
6
- }
7
-
8
- fn 'view/grep',->d,e{
9
- w=e.q['q'].scan(/[\w]+/).map(&:downcase).uniq # split/dedupe words
10
- c={}; w.each_with_index{|w,i|c[w]=i} # word index
11
- a=/(#{w.join '|'})/i # OR pattern
12
- p=/#{w.join '.*'}/i # sequential pattern
13
- [H.css('/css/search'),{_: :style, c: c.values.map{|i| # word styles
14
- b = rand(16777216) # random color
15
- f = b > 8388608 ? :black : :white # keep text contrasty
16
- ".w#{i} {background-color: #{'#%06x' % b}; color: #{f}}\n"}},# CSS
17
- d.map{|u,r| l = r.to_s.gsub(/<[^>]*>/,'').lines # plaintextify
18
- g = l.grep p # sequential match first
19
- g = l.grep a if g.empty? # OR match second
20
- !g.empty? && # find anything?
21
- [r.E.do{|e|{_: :a,href: e.url,c: e}},'<br>', # doc link
22
- [g[-1*(g.size.max 3)..-1].map{|l| # show 3 matches per doc
23
- l[0..404].gsub(a){|g| # create exerpt
24
- H({_: :span, class: "w w#{c[g.downcase]}",c: g})} # style exerpt
25
- },"<br>"]]}]}
26
-
27
- end
data/infod/W/html.rb DELETED
@@ -1,143 +0,0 @@
1
- #watch __FILE__
2
-
3
- class Array
4
- def html table=true
5
- map(&:html).join ' '
6
- end
7
- end
8
-
9
- class Object
10
- def html *a
11
- to_s.gsub('<','&lt;').gsub('>','&gt;')
12
- end
13
- end
14
-
15
- class String
16
- def br
17
- gsub(/\n/,"<br>\n")
18
- end
19
- def href name=nil
20
- '<a href="'+self+'">'+(name||(Fn 'abbrURI',self))+'</a>'
21
- end
22
- def html
23
- if match /\A(https?:\/\/)[\S]+\Z/
24
- href
25
- else
26
- self
27
- end
28
- rescue
29
- self
30
- end
31
- end
32
-
33
- class Hash
34
- def html
35
- H({_: :table, class: :html, c:
36
- map{|k,v|
37
- {_: :tr, property: k, c:
38
- [{_: :td,c: (Fn 'abbrURI',k), class: :key},
39
- {_: :td,
40
- c: (case k
41
- when E::Content
42
- {_: :pre, style: "white-space: pre-wrap", c: v}
43
- when 'uri'
44
- u = v.E
45
- {_: :a, id: u, href: u.url, c: v}
46
- else
47
- v.html
48
- end), class: :val}].cr}}.cr})
49
- end
50
- end
51
-
52
- class E
53
- def html name=nil,l=false
54
- (l ? url : uri).href name
55
- end
56
-
57
- def link
58
- html '#',true
59
- end
60
-
61
- fn 'abbrURI',->u{
62
- u.to_s.sub(/(?<scheme>[a-z]+:\/\/)?(?<abbr>.*?)(?<frag>[^#\/]+)$/,
63
- '<span class="abbr"><span class="scheme">\k<scheme></span>\k<abbr></span><span class="frag">\k<frag></span>')
64
- }
65
-
66
- fn 'head',->d,e{
67
- [{_: :title, c: d.attr(Title) || e.uri},
68
- (Fn 'head.formats',e),
69
- (Fn 'head.icon')].cr}
70
-
71
- fn 'head.formats',->e{
72
- F.keys.grep(/^render/).map{|f|
73
- f = f[7..-1]
74
- {_: :link, rel: :meta, type: f, href:'http://' + e['SERVER_NAME'] + e['REQUEST_PATH'] + e.q.merge({'format' => f}).qs}}.cr}
75
-
76
- fn 'head.icon',->{{_: :link, href:'/css/i/favicon.ico', rel: :icon}}
77
-
78
- # domain-specific view
79
- fn 'view',->d,e{( Fn 'view/divine/set',d,e)||
80
- d.values.map{|r|Fn 'view/divine/item',r,e}}
81
-
82
- # no domain-specific view
83
- fn 'view/base',->d,e{[H.css('/css/html'),d.values.map(&:html)]}
84
-
85
- # select view - filesystem hints
86
- fn 'view/divine/set',->d,e{
87
- d.values.map{|e|e.E.base}.do{|b|
88
- s = b.size.to_f
89
- t = 0.42 # threshold
90
- if b.grep(/^msg\./).size / s > t # email
91
- Fn 'view/threads',d,e
92
- elsif b.grep(/(aif|wav|flac|mp3|m4a|aac|ogg)$/i).size / s > t # audio
93
- Fn 'view/audioplayer', d,e
94
- elsif b.grep(/(gif|jpe?g|png)$/i).size / s > t # images
95
- Fn 'view/th', d,e
96
- elsif b.grep(/\.log$/).size / s > t
97
- Fn 'view/chat', d,e
98
- else false
99
- end}}
100
-
101
- Data['view/divine/item'] = "use RDF typeclass hints to choose view for a resource"
102
- fn 'view/divine/item',->r,e{
103
- r.class==Hash && r[Type] && r[Type][0] && r[Type][0].respond_to?(:uri) &&
104
- (t = r[Type][0].uri; !t.empty? && # a RDF type
105
- (F['view/'+t] ||
106
- F['view/'+t.split(/\//)[-2]]).do{|f|
107
- f.({r.uri => r},e)}) ||
108
- [r.html,H.once(e,'css',H.css('/css/html'))] }
109
-
110
- Data['view/select'] = "show a menu of all views available"
111
- fn 'view/select',->d,e{
112
- [{_: :style, c: 'a {min-width:22em;text-align:right}'},
113
- F.keys.grep(/^view\/(?!application)/).map{|v|
114
- [{_: :a, href: e['REQUEST_PATH']+e.q.merge({'view' => v[5..-1]}).qs,c: v},'<br>']}]}
115
- F['view/?'] = F['view/select']
116
-
117
- F['doc/view/multi'] = "display multiple comma-separated <b>views</b>"
118
- fn 'view/multi',->d,e{e.q['views'].split(',').map{|v|Fn'view/'+v,d,e}}
119
-
120
- def triplrBlob
121
- glob.select(&:f).do{|f|f.map{|r|
122
- yield r.uri,Type,E('blob')
123
- yield r.uri,Content,r.r}} end
124
- graphFromStream :triplrBlob
125
-
126
- def triplrHref e=nil
127
- yield uri,Content,read.do{|r|e ? r.force_encoding(e).to_utf8 : r}.hrefs
128
- end
129
-
130
- fn Render+'text/html',->d,e{
131
- v = e.q['view'].to_s
132
- h = F['head/'+v] || F['head']
133
- v = F['view/'+v] || F['view']
134
-
135
- H(e.q.has_key?('un') ? v.(d,e) :
136
- ['<!DOCTYPE html>',
137
- {_: :html,
138
- c: [{_: :head,
139
- c: ['<meta charset="utf-8" />',
140
- h.(d,e)]},
141
- {_: :body, c: v.(d,e)}].cr}].cr)}
142
-
143
- end
data/infod/W/image.rb DELETED
@@ -1,61 +0,0 @@
1
- #watch __FILE__
2
- class E
3
-
4
- def thumb?
5
- mime.match(/^(image|video)/) && # is file an image?
6
- @r.qs.match(/^[0-9]{0,3}x[0-9]{0,3}$/) && # valid dimensions?
7
- base.match(/^[^.]/) # skip "invisible" images
8
- end
9
-
10
- def thumb
11
- E['/E/images/'+
12
- [no.stat.do{|s|
13
- [s.ino,s.mtime]},
14
- @r.qs].h.dive+'.png'].do{|n| n.e ||
15
- (n.dirname.dir
16
- mime.match(/^video/) &&
17
- `ffmpegthumbnailer -s #{@r.qs.match(/[0-9]+/).to_s} -i #{sh} -o #{n.sh}` ||
18
- `gm convert #{sh} -thumbnail "#{@r.qs}" #{n.sh}`)
19
- n.env @r }
20
- end
21
-
22
- fn 'view/img',->i,_{
23
- [i.values.map{|i|
24
- [{_: :a, href: i.url,
25
- c: {_: :img,
26
- style:'float:left;max-width:61.8%',
27
- src: i.url}},
28
- i.html]},
29
- (H.css '/css/img')
30
- ]}
31
-
32
- fn 'view/th',->i,e{
33
- s=e.q['s']||'233'
34
- i.map{|u,i| u.match(/(gif|jpg|png|tiff)$/i) &&
35
- {_: :a, href: i.url+'?view=img',
36
- c: {_: :img, src: i.url+'?'+s+'x'+s}}}}
37
-
38
- F['view/'+MIMEtype+'image/gif'] = F['view/th']
39
- F['view/'+MIMEtype+'image/jpeg']= F['view/th']
40
- F['view/'+MIMEtype+'image/png'] = F['view/th']
41
-
42
- fn 'view/imgs',->m,e{ require 'nokogiri'
43
- h=e.q['h'].do{|h|h.match(/^[0-9]+$/).do{|_|'height:'+h+'px'}}
44
- seen={}
45
- x=->i{i&&i.match(/(jpg|gif|png)$/i)&&i}
46
- [(H.once e,:mu,H.js('/js/mu')),H.js('/js/images'),
47
- m.values.map{|v|
48
- [[*v[Content]].map{|c|
49
- c.class == String &&
50
- (Nokogiri::HTML.parse(c).do{|c|
51
- [c.css('img').map{|i|i['src']}.compact,
52
- c.css( 'a').map{|i|i['href']}.select(&x)]
53
- })},
54
- x.(v.uri),
55
- (v.respond_to?(:values)&&v.values.flatten.map{|v|v.respond_to?(:uri)&&v.uri}.select(&x))
56
- ].flatten.uniq.compact.map{|s|
57
- {s: s,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|
58
- !seen[i[:s]] && (seen[i[:s]]=true; i[:c].())
59
- }]}
60
-
61
- end
data/infod/W/kv.rb DELETED
@@ -1,66 +0,0 @@
1
- class E
2
-
3
- # a simple key/value RDF store on a fs
4
-
5
- # *get*
6
- # (E'http://www.kanzaki.com/ns/music#EnglishHorn')[RDFs+'comment']
7
- # -> ["A double-reed woodwind instrument, larger member of the oboe family."]
8
- #
9
- # *set*
10
- # (E'lement')['level']='trace'
11
- #
12
- # *update*
13
- # (E'lement')['level','trace','abundant']
14
- #
15
- def [] p,o=nil, v=nil
16
- unless o
17
- (s p).listPredicates
18
- else
19
- edit E(p),(o.class == E ? o : E(p).literal(o)),v
20
- end
21
- end
22
-
23
- def []= p,o
24
- self[p,o]
25
- end
26
-
27
- def edit p,o,v=nil
28
- d=(s p).s o # object
29
- if v # edit
30
- if d.e
31
- d.deleteNode # remove
32
- indexEdit p,o,'' # unindex
33
- end
34
- self[p,v] unless v.empty? # add
35
- else
36
- unless d.e
37
- indexEdit p,o,nil # index add
38
- d.dir # create
39
- end
40
- end
41
- touch if e
42
- end
43
-
44
- def triplrFsStore
45
- listPredicates.map{|p|
46
- self[p].map{|o|
47
- yield uri, p.uri, o }}
48
- end
49
-
50
- def deletePredicate p
51
- self[p].each{|o| self[p,o,'']}
52
- end
53
-
54
- # property list
55
- # E -> [E]
56
- def listPredicates
57
- s = u.to_s.size+1
58
- subtree.map{|n|n.uri[s..-1].unpath}
59
- end
60
-
61
- def literalBlob o
62
- u = literalBlobURI o
63
- u.w o,!o.class==String unless u.f
64
- end
65
-
66
- end
data/infod/W/ls.rb DELETED
@@ -1,50 +0,0 @@
1
- #watch __FILE__
2
- class E
3
-
4
- fn 'set/ls',->d,e,m{d.c}
5
-
6
- # filesystem metadata only
7
- fn 'graph/ls',->d,e,m{d.c.map{|c|c.fromStream m, :triplrInode, false}}
8
-
9
- # basic directory view
10
- fn 'view/dir',->i,e{
11
-
12
- # localize URL
13
- h = 'http://' + e['SERVER_NAME'] + '/'
14
- l = -> u {
15
- if u.index(h) == 0
16
- u # already a local link
17
- else
18
- # generate local link
19
- Prefix + u
20
- end}
21
-
22
- # item thumbnail / link
23
- a = -> i { e = i.E
24
- {_: :a, href: l[e.uri],
25
- c: e.uri.match(/(gif|jpe?g|png)$/i) ? {_: :img, src: i.uri+'?233x233'} :
26
- e.uri.sub(/.*\//,'')
27
- }}
28
-
29
- [(H.once e, 'dir', (H.css '/css/ls')),
30
- i.map{|u,r| r[Posix+'dir#child'] ? # directory?
31
- {class: :dir, style: "background-color: #{E.c}", # dir wrapper
32
- c: [{c: [{_: :a, href: l[r.uri]+'?graph=ls&view=ls', c: r.uri.sub( 'http://'+e['SERVER_NAME'],'')}, # link to ls
33
- {_: :a, href: l[r.uri].t, c: '/'}]},
34
- r[Posix+'dir#child'].map{|c|a[c]}]} : # children
35
- a[r]}]} # item
36
-
37
- F['view/'+MIMEtype+'inode/directory']=F['view/dir']
38
-
39
- # tabular rendering
40
- fn 'view/ls',->i,e{
41
- [(H.css '/css/ls'),
42
- {_: :a, class: :up, href: E(e['uri']).parent.url+'?graph=ls&view=ls', c: '&uarr;'},
43
- {class: :ls,
44
- c: (Fn 'view/tab',i,e)},
45
- {_: :a, class: :du, href: e['REQUEST_PATH'].t+'??=du', c: :du, rel: :nofollow},
46
- (Fn 'view/find',i,e),'<br clear=all>',
47
- {_: :a, class: :down, href: e['uri'].E.url.t, c: '&darr;'},
48
- ]}
49
-
50
- end