infod 0.0.3.3 → 0.0.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,7 +33,6 @@ class R
33
33
 
34
34
  rescue Groonga::SyntaxError => x
35
35
  m['#'] = {Type => R[COGS+'Exception'], Title => "invalid expr", Content => CGI.escapeHTML(x.message)}
36
- e['nocache']=true
37
36
  end
38
37
 
39
38
  F['docsID'][m,e]}}
@@ -66,14 +65,14 @@ class R
66
65
 
67
66
  # add
68
67
  def roonga graph="global", m = self.graph
69
- R.groonga.do{|g|
70
- m.map{|u,i|
71
- r = g[u] || g.add(u) # create or load entry
72
- r.uri = u # update data
73
- r.graph = graph.to_s
74
- r.content = i.to_s
75
- r.time = i[R::Date].do{|t|t[0].to_time}
76
- }}
68
+ R.groonga.do{|g|
69
+ m.map{|u,i|
70
+ r = g[u] || g.add(u) # create or load entry
71
+ r.uri = u # update data
72
+ r.graph = graph.to_s
73
+ r.content = i.to_s
74
+ r.time = i[R::Date].do{|t|t[0].to_time}
75
+ }}
77
76
  self
78
77
  end
79
78
 
@@ -40,7 +40,7 @@ end
40
40
  class Array
41
41
  def cr; intersperse "\n" end
42
42
  def head; self[0] end
43
- def html v=nil,g=nil; map{|e|e.html v,g}.join ' ' end
43
+ def html v=nil; map{|e|e.html v}.join ' ' end
44
44
  def h; join.h end
45
45
  def intersperse i
46
46
  inject([]){|a,b|a << b << i}[0..-2]
@@ -63,53 +63,41 @@ class String
63
63
  def abbrURI
64
64
  sub /(?<scheme>[a-z]+:\/\/)?(?<abbr>.*?)(?<frag>[^#\/]+)\/?$/,'<span class="abbr"><span class="scheme">\k<scheme></span>\k<abbr></span><span class="frag">\k<frag></span>'
65
65
  end
66
- def html e=nil,g=nil
66
+ def html e=nil
67
67
  self
68
68
  end
69
69
  end
70
70
 
71
71
  class Fixnum
72
- def html e=nil,g=nil; to_s end
72
+ def html e=nil; to_s end
73
73
  def max i; i > self ? self : i end
74
74
  def min i; i < self ? self : i end
75
75
  end
76
76
 
77
77
  class Float
78
- def html e=nil,g=nil; to_s end
78
+ def html e=nil; to_s end
79
79
  def max i; i > self ? self : i end
80
80
  def min i; i < self ? self : i end
81
81
  end
82
82
 
83
83
  class TrueClass
84
- def html e=nil,g=nil; H({_: :input, type: :checkbox, title: :True, checked: :checked}) end
84
+ def html e=nil; H({_: :input, type: :checkbox, title: :True, checked: :checked}) end
85
85
  end
86
86
 
87
87
  class FalseClass
88
- def html e=nil,g=nil; H({_: :input, type: :checkbox, title: :False}) end
88
+ def html e=nil; H({_: :input, type: :checkbox, title: :False}) end
89
89
  end
90
90
 
91
- IsBnode = /^_:/
92
-
93
91
  class Hash
94
- def html e={'SERVER_NAME'=>'localhost'}, g={}, key=true
92
+ def html e={'SERVER_NAME'=>'localhost'}
95
93
  if keys.size == 1 && has_key?('uri')
96
- if uri.match IsBnode
97
- g[uri].do{|r|
98
- r.html e,g,key } || uri.href
99
- else
100
- uri.href
101
- end
94
+ uri.href
102
95
  else
103
96
  H({_: :table, class: :html, c: map{|k,v|
104
- unless k == 'uri' && (v.match IsBnode)
105
- {_: :tr, property: k, c:
106
- [k == R::Content ? {_: :td, class: :val, colspan: 2, c: v} :
107
- [
108
- ({_: :td, c: [{_: :a, name: k, href: (k == 'uri' ? (v.R.docBase.localURL e)+'?graph=edit' : k), c: k.to_s.abbrURI}], class: :key} if key),
109
- {_: :td, c: k == 'uri' ? v.R.do{|u| {_: :a, id: u, href: u.url, c: v}} : v.html(e,g), class: :val},
110
- ]]}
111
- end
112
- }})
97
+ {_: :tr, property: k, c:
98
+ [k == R::Content ? {_: :td, class: :val, colspan: 2, c: v} :
99
+ [{_: :td, c: [{_: :a, name: k, href: (k == 'uri' ? (v.R.docBase.localURL e)+'?graph=edit&mono' : k), c: k.to_s.abbrURI}], class: :key},
100
+ {_: :td, c: k == 'uri' ? v.R.do{|u| {_: :a, id: u, href: u.url, c: v}} : v.html(e), class: :val}]]}}})
113
101
  end
114
102
  end
115
103
  end
@@ -121,36 +109,26 @@ class R
121
109
  end
122
110
 
123
111
  F['view']=->d,e{
124
- d.values.select{|r|
125
- !r.has_key?('uri') || # URI field missing
126
- !r.uri.match(IsBnode) # blank node
127
- true
128
- }.
129
- sort_by{|r| r[Date].do{|d| d[0].to_s} || ''}.reverse.
130
- map{|r| F['view/select'][r,e,d]}}
131
-
132
- F['view/base']=->d,e,k=true,graph=nil{
133
- [H.once(e,'base',H.css('/css/html')),
134
- d.values.map{|v|v.html e,graph,k}]}
135
-
136
- F['view/select']=->r,e,d=nil{
137
- graph = {r.uri => r}
138
- view = nil
139
- if r.class == Hash
140
- (r[Type].class==Array ? r[Type] : [r[Type]]).do{|types|
141
- views = types.map(&:maybeURI).compact.map{|t|
142
- subtype = t
143
- type = subtype.split(/\//)[-2]
144
- [F['view/' + subtype],
145
- (F['view/' + type] if type)]}.
146
- flatten.compact
147
- view = views[0] unless views.empty?}
148
- end
149
- if !view # default view
150
- F['view/base'][graph,e,true,d]
151
- else
152
- view[graph,e]
153
- end}
112
+ d.values.map{|r|
113
+ graph = {r.uri => r}
114
+ view = nil
115
+ if r.class == Hash
116
+ r[Type].justArray.do{|types|
117
+ views = types.map(&:maybeURI).compact.map{|t|
118
+ subtype = t
119
+ type = subtype.split(/\//)[-2]
120
+ [F['view/' + subtype],
121
+ (F['view/' + type] if type)]}.
122
+ flatten.compact
123
+ view = views[0] unless views.empty?}
124
+ end
125
+ if !view
126
+ F['view/base'][graph,e]
127
+ else
128
+ view[graph,e]
129
+ end}}
130
+
131
+ F['view/base']=->d,e{[H.once(e,'base',H.css('/css/html')),d.values.map{|v|v.html e}]}
154
132
 
155
133
  def triplrBlob
156
134
  glob.select(&:f).do{|f|f.map{|r|
@@ -158,10 +136,10 @@ class R
158
136
  yield r.uri,Content,r.r}} end
159
137
 
160
138
  def triplrHref enc=nil
161
- yield uri,Content,(f && read).do{|r|enc ? r.force_encoding(enc).to_utf8 : r}.hrefs
139
+ yield uri,Content,open(d).read.do{|r|enc ? r.force_encoding(enc).to_utf8 : r}.hrefs if f
162
140
  end
163
141
 
164
- def nokogiri; Nokogiri::HTML.parse read end
142
+ def nokogiri; Nokogiri::HTML.parse (open uri).read end
165
143
 
166
144
  F['HTMLbody'] = -> b {
167
145
  b.to_s.split(/<body[^>]*>/)[-1].to_s.split(/<\/body>/)[0] }
@@ -182,17 +160,6 @@ class R
182
160
  c: {_: :img, src: '/css/misc/cube.png', style: 'height:2em;background-color:white;padding:.54em;border-radius:1em;margin:.2em'}},
183
161
  (H.js '/js/pager'),(H.once e,:mu,(H.js '/js/mu'))]}} # (n)ext (p)rev key binding
184
162
 
185
- def contentURIresolve *f
186
- send(*f){|s,p,o|
187
- yield s, p, p == Content ?
188
- (Nokogiri::HTML.fragment o).do{|o|
189
- o.css('a').map{|a|
190
- if a.has_attribute? 'href'
191
- (a.set_attribute 'href', (URI.join s, (a.attr 'href'))) rescue nil
192
- end}
193
- o.to_s} : o}
194
- end
195
-
196
163
  fn Render+'text/html',->d,e{ u = d['#']||{}
197
164
  titles = d.map{|u,r| r[Title] if r.class==Hash }.flatten.compact
198
165
  view = F['view/'+e.q['view'].to_s] || F['view']
@@ -21,14 +21,14 @@ class R
21
21
  `gm convert #{i.sh} -thumbnail "#{size}x#{size}" #{path.sh}`
22
22
  end
23
23
  end
24
- path.e ? (path.env r).getFile : F[E404][e,r]
24
+ path.e ? (path.env r).fileGET : F[E404][e,r]
25
25
  else
26
26
  F[E404][e,r]
27
27
  end}
28
28
 
29
29
  fn 'view/img',->i,_{
30
30
  [i.values.select{|v|v.class==Hash}.map{|i|
31
- i[Type] && (i[Type].class==Array ? i[Type] : [i[Type]]).map(&:maybeURI).include?(DC+'Image') &&
31
+ i[Type] && i[Type].justArray.map(&:maybeURI).include?(DC+'Image') &&
32
32
  [{_: :a, href: i.url, c: {_: :img, style:'float:left;max-width:61.8%', src: i.url}},
33
33
  i.html]},
34
34
  (H.css '/css/img')]}
@@ -15,7 +15,7 @@ shellwords}.map{|r|require r}
15
15
  %w{
16
16
  constants
17
17
  lambda
18
- mime
18
+ MIME
19
19
  404
20
20
  500
21
21
  grep
@@ -45,6 +45,7 @@ names
45
45
  POST
46
46
  rdf
47
47
  schema
48
+ SPARQL
48
49
  text
49
50
  threads
50
51
  time
@@ -4,7 +4,7 @@ end
4
4
 
5
5
  class NilClass
6
6
  def do; nil end
7
- def html e=nil,g=nil; "" end
7
+ def html e=nil; "" end
8
8
  def R; "".R end
9
9
  end
10
10
 
@@ -21,10 +21,6 @@ def watch f
21
21
 
22
22
  class R
23
23
 
24
- def initialize uri
25
- @uri = uri.to_s
26
- end
27
-
28
24
  def R uri = nil
29
25
  uri ? R.new(uri) : self
30
26
  end
@@ -49,7 +45,7 @@ class R
49
45
  i = i.split /:/
50
46
  yield uri, (f + (i[0].match(g)||[0,i[0]])[1]. # s
51
47
  gsub(/\s/,'_').gsub(/\//,'-').gsub(/[\(\)]+/,'')), # p
52
- i.tail.join(':').strip.do{|v|v.match(/^[0-9\.]+$/) ? v.to_f : v.hrefs}} # o
48
+ i.tail.join(':').strip.do{|v|v.match(/^[0-9\.]+$/) ? v.to_f : v}} # o
53
49
  rescue
54
50
  end
55
51
 
@@ -1,18 +1,33 @@
1
1
  #watch __FILE__
2
2
  class R
3
+ =begin usage
3
4
 
4
- MessagePath = ->id{'/msg/' + id.h[0..2] + '/' + id}
5
+ messages matching an address
6
+ msgs = R['/m/semantic-web@w3.org'].take
7
+
8
+ mirror message-files backing a resource-set
9
+ src = R::DC+'source'
10
+ files = msgs.map{|g| '.' + g.graph.values.find{|r|r.has_key? src}[src].head.R.path}
11
+ `rsync -avRz #{files.join ' '} h:/www/`
12
+
13
+ summary view on directories
14
+ F['/mail/GET'] = -> e,r {
15
+ r.q['view'] ||= 'threads' if e.uri[-1] == '/'
16
+ nil }
17
+
18
+ =end
5
19
 
6
- GREP_DIRS.push /^\/m\/[^\/]+\// # allow grep within a single address
20
+ MessagePath = ->id{'/msg/' + id.h[0..2] + '/' + id}
21
+ GREP_DIRS.push /^\/m\/[^\/]+\// # allow on a single address
7
22
 
8
23
  F['/m/GET'] = -> e,r{
9
- # set overview(summary) view and start a depth-first view of message tree of this address
24
+ # use summary view and start a newest-first tree-range at address
10
25
  if m = e.pathSegment.uri.match(/^\/m\/([^\/]+)$/)
11
- r.q['set'] ||= 'depth'
26
+ r.q['set'] ||= 'depth'
12
27
  r.q['view'] ||= 'threads'
13
- e.response
28
+ e.response
14
29
  else
15
- false
30
+ false
16
31
  end}
17
32
 
18
33
  IndexMail = ->doc, graph, host {
@@ -48,12 +63,16 @@ class R
48
63
  creator = '/m/'+f+'#'+f # author URI
49
64
  yield e, Creator, R[creator] # message -> author
50
65
  yield creator, DC+'identifier', R['mailto:'+f] # author ID
66
+ # reply to
67
+ r2 = m['List-Post'].do{|lp|lp.decoded[8..-2]} || # List-Post
68
+ m.reply_to.do{|t|t[0]} || # Reply-To
69
+ f # From
51
70
  yield e, SIOC+'reply_to', # reply URI
52
- R[URI.escape("mailto:#{m.reply_to.do{|t|t[0]}||f}?References=<#{id}>&In-Reply-To=<#{id}>&Subject=#{m.subject}&")+'#reply']}}
71
+ R[URI.escape("mailto:#{r2}?References=<#{id}>&In-Reply-To=<#{id}>&Subject=#{m.subject}&")+'#reply']}}
53
72
 
54
73
  yield e, Date, m.date.iso8601 if m.date # date
55
74
 
56
- m.subject.do{|s|yield e, Title, s.to_utf8} # subject
75
+ m.subject.do{|s|yield e, Title, s.to_utf8.hrefs} # subject
57
76
 
58
77
  yield e, SIOC+'has_discussion', # thread
59
78
  R[e+'?graph=thread&view=timegraph#discussion'] if m.in_reply_to || m.references
@@ -83,7 +102,7 @@ class R
83
102
  c: p.decoded.to_utf8.hrefs.gsub(/^\s*(&gt;)(&gt;|\s)*\n/,"").lines.to_a.map{|l| # skip quoted*empty lines
84
103
  l.match(/(^\s*(&gt;|On[^\n]+(said|wrote))[^\n]*)\n/) ? # quoted?
85
104
  {_: :span, class: :q, depth: l.scan(/(&gt;)/).size, c: l} : l # wrap quotes
86
- }},(H.css '/css/mail',true)])}
105
+ }},(H.css '/css/mail')])}
87
106
 
88
107
  attache = -> { e.R.a('.attache').mk } # filesystem container for attachments & parts
89
108
 
@@ -106,20 +125,6 @@ class R
106
125
  end
107
126
 
108
127
  F['view/'+MIMEtype+'message/rfc822'] = NullView # hide container-resource in default view
109
- =begin
110
- USAGE(context)
111
-
112
- admin (irb) move messages among filesystems
113
- p = R['/m/semantic-web@w3.org'].take.map{|g|'.' + g.graph.values.find{|r|r.has_key?(R::DC+'source')}[R::DC+'source'][0].R.path}
114
- `rsync -avRz #{p.join ' '} h:/www/`
128
+ F['view/'+MIMEtype+'text/n3'] = NullView
115
129
 
116
- view (rb) default to overview of directory
117
- F['/mail/GET'] = -> e,r {
118
- r.q['view'] ||= 'threads' if e.uri[-1] == '/'
119
- false }
120
-
121
- home (sh) current day-dir in Markdown
122
- echo "[today](/?y=day&view=threads)" > TODAY.md
123
-
124
- =end
125
130
  end
@@ -92,7 +92,7 @@ class R
92
92
  end
93
93
 
94
94
  # response
95
- html.env(r).getFile
95
+ html.env(r).fileGET
96
96
  end
97
97
  end
98
98
  }
@@ -26,9 +26,18 @@ class R
26
26
 
27
27
  def tw g
28
28
  node.readlines.shuffle.each_slice(22){|s|
29
- R['https://twitter.com/search/realtime?q='+s.map{|u|'from:'+u.chomp}.intersperse('+OR+').join].addDocs :triplrTweets, g, nil, FeedArchiver}
29
+ R['https://twitter.com/search/realtime?q='+s.map{|u|'from:'+u.chomp}.intersperse('+OR+').join].addDocs :triplrTweets, g, nil, FeedArchiverJSON}
30
30
  end
31
31
 
32
+ FeedArchiverJSON = -> doc, graph, host {
33
+ doc.roonga host
34
+ graph.map{|u,r|
35
+ r[Date].do{|t| # link doc to date-index
36
+ t = t[0].gsub(/[-T]/,'/').sub /(.00.00|Z)$/, '' # trim normalized timezones and non-unique symbols
37
+ b = (u.sub(/http:\/\//,'.').gsub(/\W/,'..').gsub(FeedStop,'').sub(/\d{12,}/,'')+'.').gsub /\.+/,'.'
38
+ doc.ln R["http://#{host}/news/#{t}#{b}e"]}}
39
+ doc}
40
+
32
41
  def triplrTweets
33
42
  base = 'http://twitter.com'
34
43
  nokogiri.css('div.tweet').map{|t|
@@ -1,4 +1,8 @@
1
1
  class R
2
+ =begin
3
+ name-manipulating functions
4
+ a RDF::URI-identified-resource has an associated filesystem node when using our subclass..
5
+ =end
2
6
 
3
7
  def appendURI u; R uri + u.to_s end
4
8
  def appendSlashURI u; R uri.t + u.to_s end
@@ -8,33 +12,22 @@ class R
8
12
  def children; node.c.map &:R end
9
13
  def container; @u ||= R[f ? dirname + '/.' + (File.basename path) : path] end
10
14
  def d; node.to_s end
11
- def delete; node.deleteNode if e; self end
12
15
  def dirname; node.dirname.do{|d| d.to_s.size <= BaseLen ? '/' : d }.R end
13
16
  def docBase; uri.split(/#/)[0].R.do{|d| d.dirname.as d.bare } end
14
17
  def d?; node.directory? end
15
- def env r=nil;r ? (@r = r; self) : @r end
16
- def exist?; node.exist? end
17
18
  def expand; uri.expand.R end
18
19
  def ext; File.extname(uri).tail||'' end
19
- def file?; node.file? end
20
20
  def frag; uri.frag end
21
- def get; open(uri).read end
22
21
  def glob p=""; (Pathname.glob d + p).map &:R end
23
22
  def hostURL e; host='http://'+e['SERVER_NAME']; (uri.index('/') == 0 ? host : '') + uri end
24
23
  def inside; node.expand_path.to_s.index(FSbase) == 0 end
25
24
  def label; uri.label end
26
- def mk; e || FileUtils.mkdir_p(d); self end
27
- def mtime; node.stat.mtime if e end
28
25
  def node; Pathname.new FSbase + path end
29
26
  def parent; R Pathname.new(uri).parent end
30
27
  def parents; parent.do{|p|p.uri.match(/^[.\/]+$/) ? [p] : [p].concat(p.parents)} end
31
28
  def path; uri.match(/^\//) ? uri : ('/'+uri) end
32
29
  def pathSegment; uri.match(/^([a-z]+:\/\/[^\/]+)?(\/.*)/).do{|p|p[2]&&p[2].R}||nil end
33
- def predicatePath p,s=true; container.as s ? p.R.shorten : p end
34
- def predicates; container.c.map{|c|c.base.expand.R} end
35
30
  def prependURI u; R u.to_s + uri end
36
- def read; f ? readFile : get end
37
- def readFile; File.open(d).read end
38
31
  def realpath; node.realpath rescue Errno::ENOENT end
39
32
  def shorten; uri.shorten.R end
40
33
  def siblings; parent.c end
@@ -42,11 +35,9 @@ class R
42
35
  def == u; to_s == u.to_s end
43
36
  def <=> c; to_s <=> c.to_s end
44
37
  def sh; d.force_encoding('UTF-8').sh end
45
- def to_s; uri end
46
- def to_h; {'uri' => uri} end
47
- def touch; FileUtils.touch node; self end
48
- def writeFile c; File.open(d,'w'){|f|f << c} end
49
38
 
39
+ # shortcuts
40
+
50
41
  alias_method :+, :appendURI
51
42
  alias_method :a, :appendURI
52
43
  alias_method :as, :appendSlashURI
@@ -54,11 +45,9 @@ class R
54
45
  alias_method :bare, :barename
55
46
  alias_method :c, :children
56
47
  alias_method :dir, :dirname
57
- alias_method :e, :exist?
58
- alias_method :f, :file?
59
- alias_method :m, :mtime
60
- alias_method :maybeURI, :uri
61
- alias_method :url, :uri
48
+ alias_method :maybeURI, :to_s
49
+ alias_method :url, :to_s
50
+ alias_method :uri, :to_s
62
51
 
63
52
  def localURL e
64
53
  if uri.index('/') == 0
@@ -1,9 +1,9 @@
1
1
  #watch __FILE__
2
2
  class R
3
3
 
4
- def nt; @nt ||= docBase.a('.nt') end
5
- def n3; @n3 ||= docBase.a('.n3') end
6
- def ttl; @ttl||= docBase.a('.ttl') end
4
+ def nt; docBase.a '.nt' end
5
+ def n3; docBase.a '.n3' end
6
+ def ttl; docBase.a '.ttl' end
7
7
 
8
8
  def self.renderRDF d,f,e
9
9
  (RDF::Writer.for f).buffer{|w|
@@ -23,7 +23,8 @@ class R
23
23
  uri = (local && f) ? d : uri
24
24
  RDF::Reader.open(uri, :format => format){|r|
25
25
  r.each_triple{|s,p,o|
26
- yield s.to_s, p.to_s, [RDF::Node, RDF::URI].member?(o.class) ? R(o) : o.value.do{|v|v.class == String ? v.to_utf8 : v}}}
26
+ yield s.to_s, p.to_s,
27
+ [RDF::Node, RDF::URI].member?(o.class) ? R(o) : o.value.do{|v|v.class == String ? v.to_utf8 : v}}}
27
28
  end
28
29
 
29
30
  [['application/ld+json',:jsonld],