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.
- data/infod.rb +2 -3
- data/infod/Es.rb +31 -67
- data/infod/{W/source.rb → Es/code.rb} +6 -10
- data/infod/Es/css.rb +21 -0
- data/infod/{W → Es}/csv.rb +0 -0
- data/infod/Es/du.rb +16 -0
- data/infod/{W → Es}/feed.rb +13 -11
- data/infod/Es/filter.rb +75 -0
- data/infod/Es/find.rb +20 -0
- data/infod/Es/fs.rb +145 -136
- data/infod/Es/glob.rb +22 -0
- data/infod/Es/grep.rb +61 -0
- data/infod/Es/groonga.rb +47 -56
- data/infod/Es/html.rb +271 -0
- data/infod/Es/image.rb +114 -0
- data/infod/Es/in.rb +68 -0
- data/infod/Es/index.rb +183 -0
- data/infod/{W → Es}/json.rb +28 -4
- data/infod/Es/kv.rb +60 -0
- data/infod/Es/ls.rb +58 -0
- data/infod/Es/mail.rb +87 -0
- data/infod/Es/man.rb +112 -0
- data/infod/Es/mime.rb +59 -0
- data/infod/Es/out.rb +52 -0
- data/infod/{W/page.rb → Es/pager.rb} +7 -3
- data/infod/Es/pdf.rb +19 -0
- data/infod/Es/rdf.rb +35 -0
- data/infod/Es/schema.rb +99 -0
- data/infod/Es/search.rb +24 -0
- data/infod/Es/sh.rb +21 -0
- data/infod/{W → Es}/text.rb +26 -14
- data/infod/H.rb +15 -29
- data/infod/H/audio.rb +19 -0
- data/infod/H/blog.rb +15 -0
- data/infod/{W → H}/cal.rb +2 -31
- data/infod/H/edit.rb +88 -0
- data/infod/{W/examine/examine.rb → H/facets.rb} +17 -17
- data/infod/{W → H}/forum.rb +1 -0
- data/infod/{W/examine/sw.rb → H/hf.rb} +12 -12
- data/infod/H/histogram.rb +78 -0
- data/infod/H/mail.rb +92 -0
- data/infod/{W/chat.rb → H/microblog.rb} +21 -16
- data/infod/H/threads.rb +77 -0
- data/infod/H/time.rb +131 -0
- data/infod/H/who.rb +30 -0
- data/infod/{W → H}/wiki.rb +0 -0
- data/infod/K.rb +28 -60
- data/infod/N.rb +151 -74
- data/infod/Rb.rb +3 -3
- data/infod/Th.rb +27 -101
- data/infod/Th/404.rb +29 -36
- data/infod/Th/500.rb +36 -5
- data/infod/Th/GET.rb +48 -118
- data/infod/Th/POST.rb +31 -11
- data/infod/Th/perf.rb +37 -0
- data/infod/Th/util.rb +89 -0
- data/infod/Y.rb +24 -7
- data/infod/infod.rb +2 -3
- metadata +92 -64
- data/infod/Es/redis.rb +0 -3
- data/infod/Es/sqlite.rb +0 -3
- data/infod/Th/local.rb +0 -22
- data/infod/W.rb +0 -34
- data/infod/W/audio.rb +0 -56
- data/infod/W/blog.rb +0 -3
- data/infod/W/color.rb +0 -28
- data/infod/W/core.rb +0 -77
- data/infod/W/css.rb +0 -24
- data/infod/W/du.rb +0 -35
- data/infod/W/edit.rb +0 -8
- data/infod/W/examine/exhibit.rb +0 -34
- data/infod/W/examine/hist.rb +0 -55
- data/infod/W/examine/history.rb +0 -19
- data/infod/W/examine/normal.rb +0 -31
- data/infod/W/examine/protovis.rb +0 -30
- data/infod/W/examine/time/graph.rb +0 -86
- data/infod/W/examine/time/line.rb +0 -24
- data/infod/W/find.rb +0 -24
- data/infod/W/grep.rb +0 -27
- data/infod/W/html.rb +0 -143
- data/infod/W/image.rb +0 -61
- data/infod/W/kv.rb +0 -66
- data/infod/W/ls.rb +0 -50
- data/infod/W/mail.rb +0 -248
- data/infod/W/pdf.rb +0 -16
- data/infod/W/post.rb +0 -9
- data/infod/W/rdf.rb +0 -32
- data/infod/W/schema.rb +0 -172
- data/infod/W/search.rb +0 -33
- data/infod/W/shell.rb +0 -30
- data/infod/W/table.rb +0 -87
- data/infod/W/tree.rb +0 -26
- data/infod/W/vfs.rb +0 -175
data/infod/Es/ls.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
class E
|
3
|
+
|
4
|
+
fn 'view/dir',->i,e{
|
5
|
+
|
6
|
+
# item link + preview
|
7
|
+
a = -> i { i = i.E
|
8
|
+
{_: :a, href: i.localURL(e),
|
9
|
+
c: i.uri.match(/(gif|jpe?g|png)$/i) ? {_: :img, src: i.uri+'?y=scaleImage&px=233'} : i.uri.sub(/.*\//,'')}}
|
10
|
+
|
11
|
+
[(H.once e, 'dir', (H.css '/css/ls')),
|
12
|
+
i.map{|u,r|
|
13
|
+
if r[Posix+'dir#child']
|
14
|
+
url = r.E.localURL e
|
15
|
+
{class: :dir, style: "background-color: #{E.cs}", # dir wrapper
|
16
|
+
c: [{c: [{_: :a, href: url.t+'?view=ls&triplr=id', # link to "ls"
|
17
|
+
c: r.uri.sub( 'http://'+e['SERVER_NAME'],'')},
|
18
|
+
{_: :a, href: url.t, c: '/'}]},
|
19
|
+
r[Posix+'dir#child'].map{|c|a[c]}]}
|
20
|
+
else
|
21
|
+
a[r]
|
22
|
+
end
|
23
|
+
}]}
|
24
|
+
|
25
|
+
F['view/'+MIMEtype+'inode/directory'] = F['view/dir']
|
26
|
+
|
27
|
+
fn 'view/ls',->i,e{
|
28
|
+
dir = e['uri'].E
|
29
|
+
path = dir.pathSegment
|
30
|
+
up = (if !path || path.uri == '/'
|
31
|
+
'/'
|
32
|
+
else
|
33
|
+
dir.parent.url.t+'?view=ls&triplr=id'
|
34
|
+
end)
|
35
|
+
|
36
|
+
[(H.css '/css/ls'),
|
37
|
+
{_: :a, class: :up, href: up, c: '↑'},
|
38
|
+
{class: :ls,
|
39
|
+
c: (Fn 'view/table',i,e)},
|
40
|
+
(Fn 'view/find',i,e),'<br clear=all>',
|
41
|
+
{_: :a, class: :down, href: e['uri'].E.url.t + e.q.except('triplr','view').qs, c: '↓'}]}
|
42
|
+
|
43
|
+
# user-patchable default-handler
|
44
|
+
fn '/GET',->e,r{
|
45
|
+
x = 'index.html'
|
46
|
+
i = [e,e.pathSegment].compact.map{|e|e.as x}.find &:e
|
47
|
+
if i
|
48
|
+
if e.uri[-1] == '/' # inside dir?
|
49
|
+
i.env(r).getFile # show index
|
50
|
+
else # descend to indexed dir
|
51
|
+
[301, {Location: e.uri.t}, []]
|
52
|
+
end
|
53
|
+
else
|
54
|
+
# default handler
|
55
|
+
e.response
|
56
|
+
end}
|
57
|
+
|
58
|
+
end
|
data/infod/Es/mail.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
class E
|
2
|
+
|
3
|
+
# TMail version: 1.2.7.1-4 from:
|
4
|
+
# apt-get install ruby-tmail
|
5
|
+
|
6
|
+
def triplrTmail ; require 'tmail'
|
7
|
+
|
8
|
+
# read message
|
9
|
+
i = -> i {E i[1..-2]} # Message-ID -> E
|
10
|
+
(TMail::Mail.load node).do{|m| # parse
|
11
|
+
d = m.message_id; return unless d # parse successful?
|
12
|
+
e = i[d] # Message resource
|
13
|
+
|
14
|
+
# index previously unseen mail
|
15
|
+
e.e || ( # Message-ID locatable?
|
16
|
+
ln e # create message-id path
|
17
|
+
self.index Creator, m.from[0].E # index From
|
18
|
+
m.to.do{|t|self.index To, t[0].E} # index To
|
19
|
+
|
20
|
+
%w{in_reply_to references}.map{|p| m.send(p).do{|os| os.map{|o|
|
21
|
+
e.index SIOC+'reply_of', i[o]}}}) # index references
|
22
|
+
|
23
|
+
# yield triples
|
24
|
+
yield e.uri, Type, E[SIOCt + 'MailMessage']
|
25
|
+
yield e.uri, Type, E[SIOC + 'Post']
|
26
|
+
yield e.uri, Date, m.date.iso8601 if m.date
|
27
|
+
yield e.uri, Content, m.decentBody
|
28
|
+
[[:subject,Title],
|
29
|
+
[:to,To,true],
|
30
|
+
[:cc,To,true],
|
31
|
+
[:bcc,To,true],
|
32
|
+
[:friendly_from,SIOC+'name'],
|
33
|
+
[:from,Creator,true],
|
34
|
+
[:reply_to,'/mail/reply_to',true],
|
35
|
+
[:in_reply_to,'/parent',true,true],
|
36
|
+
[:in_reply_to,SIOC+'reply_of',true,true],
|
37
|
+
[:references,SIOC+'reply_of',true,true],
|
38
|
+
].each{|a| m.send(a[0]).do{|o| [*o].map{|o|
|
39
|
+
yield e.uri,a[1], # skip empty String values
|
40
|
+
(a[2] ? (a[3] ? i[o] : o.E) : o.to_utf8) unless o.match(/\A[, \n]*\Z/)}}}}
|
41
|
+
|
42
|
+
rescue Exception => e
|
43
|
+
puts [:mail,uri,e].join(' ')
|
44
|
+
end
|
45
|
+
|
46
|
+
alias_method :triplrMail, :triplrTmail
|
47
|
+
|
48
|
+
# pure-ruby mail is only 10x (vs 100x) slower than C-ext based TMail w/ new parser
|
49
|
+
# API is mostly identical, URIs strings arent <>-wrapped
|
50
|
+
# TODO replace this msg with triplrMail if anyone wants it
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
module TMail
|
55
|
+
class Mail
|
56
|
+
def unicode_body
|
57
|
+
unquoted_body.to_utf8
|
58
|
+
end
|
59
|
+
def decentBody
|
60
|
+
unHTML=->t{t.split(/<body[^>]*>/)[-1].split(/<\/body>/)[0]}
|
61
|
+
if multipart?
|
62
|
+
parts.collect{ |part|
|
63
|
+
c = part["content-type"]
|
64
|
+
if part.multipart?
|
65
|
+
part.decentBody
|
66
|
+
elsif header.nil?
|
67
|
+
""
|
68
|
+
elsif !attachment?(part) && c.sub_type != 'html'
|
69
|
+
part.unicode_body.hrefs(true)
|
70
|
+
else
|
71
|
+
(c["name"]||'attach').do{|a|
|
72
|
+
message_id ? (message_id[1..-2]+'/'+a).E.do{|i|
|
73
|
+
i.w part.body if !i.e
|
74
|
+
'<a href='+i.url+'>'+(part.main_type=='image' ? '<img src="'+i.url+'">' : a)+"</a><br>\n"
|
75
|
+
} : ""};end
|
76
|
+
}.join
|
77
|
+
|
78
|
+
else
|
79
|
+
unicode_body.do{|b|content_type&&content_type.match(/html/) ? unHTML.(b) : b.hrefs(true)}
|
80
|
+
end
|
81
|
+
rescue
|
82
|
+
''
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class String; def is_binary_data?; true; end; end
|
data/infod/Es/man.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
class E
|
3
|
+
|
4
|
+
fn '/man/GET',->e,r{
|
5
|
+
manPath = '/usr/share/man'
|
6
|
+
|
7
|
+
# eat selector
|
8
|
+
name = e.pathSegment.uri.sub('/man/','/').tail
|
9
|
+
|
10
|
+
# section requested?
|
11
|
+
section = nil
|
12
|
+
name.match(/^([0-9])(\/|$)/).do{|p|
|
13
|
+
section = p[1]
|
14
|
+
name = p.post_match }
|
15
|
+
|
16
|
+
if !name || name.empty? || name.match(/\//)
|
17
|
+
if section
|
18
|
+
# enumerate section children
|
19
|
+
(H [H.css('/css/man'),{_: :style, c: "a {background-color: #{E.cs}}"},
|
20
|
+
Pathname(manPath+'/man'+section).c.map{|p|
|
21
|
+
n = p.basename.to_s.sub /\.[0-9][a-z]*\...$/,''
|
22
|
+
}.group_by{|e|e[0].match(/[a-zA-Z]/) ? e[0].downcase : '0-9'}.sort.map{|g,m|
|
23
|
+
[{_: :h3, c: g},
|
24
|
+
m.map{|n|[{_: :a, href: '/man/'+section+'/'+n, c: n },' ']}]}
|
25
|
+
]).hR
|
26
|
+
else
|
27
|
+
e.response
|
28
|
+
end
|
29
|
+
else
|
30
|
+
acceptLang = r['HTTP_ACCEPT_LANGUAGE'].do{|a|a.split(/,/)[0]}
|
31
|
+
lang = r.q['lang'] || acceptLang
|
32
|
+
superLang = lang.do{|l| (l.split /[_-]/)[0] }
|
33
|
+
langSH = lang.do{|l| '-L ' + l.sub('-','_').sh }
|
34
|
+
man = `man #{langSH} -w #{section} #{name.sh}`.chomp
|
35
|
+
|
36
|
+
if man.empty?
|
37
|
+
return false
|
38
|
+
else
|
39
|
+
|
40
|
+
roff = man.E
|
41
|
+
htmlBase = roff.dir.to_s.sub(/.*\/share/,'').E
|
42
|
+
html = htmlBase.as roff.bare + '.html'
|
43
|
+
cached = html.e && html.m > (Pathname man).stat.mtime
|
44
|
+
|
45
|
+
if !cached
|
46
|
+
|
47
|
+
locales = Pathname(manPath).c.select{|p|p.basename.to_s.do{|b| !b.match(/^man/) && !b.match(/\./) }}.map{|p|File.basename p}
|
48
|
+
localesAvail = locales.select{|l|
|
49
|
+
File.exist? manPath + '/' + l + '/' + roff.uri.split('/')[-2..-1].join('/')}
|
50
|
+
|
51
|
+
imagePath = htmlBase.d + '/images'
|
52
|
+
FileUtils.mkdir_p imagePath unless File.exist? imagePath
|
53
|
+
|
54
|
+
preconv = %w{hu pt tr}.member?(superLang) ? "" : "-k"
|
55
|
+
pageCmd = "zcat #{man} | groff #{preconv} -T html -man -P -D -P #{imagePath}"
|
56
|
+
page = `#{pageCmd}`#.to_utf8
|
57
|
+
|
58
|
+
[[:name,name],
|
59
|
+
[:acceptLang,acceptLang],
|
60
|
+
[:lang, lang],
|
61
|
+
[:langSH, langSH],
|
62
|
+
[:superLang, superLang],
|
63
|
+
[:roff,man],
|
64
|
+
[:htmlBase,htmlBase.d],
|
65
|
+
[:imagePath,imagePath],
|
66
|
+
[:localizations,localesAvail],
|
67
|
+
[:pageCmd,pageCmd]].map{|p| puts [" "*(13-p[0].size),*p].join ' ' }
|
68
|
+
|
69
|
+
page = Nokogiri::HTML.parse page
|
70
|
+
body = page.css('body')[0]
|
71
|
+
|
72
|
+
# add CSS link
|
73
|
+
body.add_child H H.css('/css/man')
|
74
|
+
body.add_child H[{_: :style, c: "a {background-color:#{E.cs}}"}]
|
75
|
+
|
76
|
+
# add localization links
|
77
|
+
(body.css('h1')[0] ||
|
78
|
+
body.css('p')[0]
|
79
|
+
).add_previous_sibling H localesAvail.map{|l|
|
80
|
+
{_: :a, class: :lang, href: r['REQUEST_PATH']+'?lang='+l, c: l}}
|
81
|
+
|
82
|
+
# webize image paths
|
83
|
+
body.css('img').map{|i|
|
84
|
+
p = (i.attr 'src').unpathFs
|
85
|
+
i.replace H[{_: :img, src: p}]}
|
86
|
+
|
87
|
+
# inspect plaintext
|
88
|
+
# HTMLize hyperlinks
|
89
|
+
# markup commands
|
90
|
+
body.xpath('//text()').map{|a|
|
91
|
+
a.replace a.to_s.gsub('>','>').hrefs.gsub /\b([^<>\s(]+)\(/mi, '<b>\1</b>('
|
92
|
+
}
|
93
|
+
|
94
|
+
qs = r['QUERY_STRING'].do{|q| q.empty? ? '' : '?' + q}
|
95
|
+
# href-ize commands
|
96
|
+
body.css('b').map{|b|
|
97
|
+
b.next.do{|n|
|
98
|
+
n.to_s.match(/\(([0-9])\)(.*)/).do{|section|
|
99
|
+
name, s = b.inner_text, section[1]
|
100
|
+
n.replace section[2]
|
101
|
+
b.replace " <a href='/man/#{s}/#{name}#{qs}'><b>#{name}</b>(#{s})</a>"}}}
|
102
|
+
|
103
|
+
html.w page
|
104
|
+
end
|
105
|
+
|
106
|
+
# response
|
107
|
+
html.env(r).getFile
|
108
|
+
end
|
109
|
+
end
|
110
|
+
}
|
111
|
+
|
112
|
+
end
|
data/infod/Es/mime.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
class E
|
3
|
+
|
4
|
+
# MIME-type, no link-following
|
5
|
+
def mime
|
6
|
+
@mime ||=
|
7
|
+
(t = ext.downcase.to_sym
|
8
|
+
|
9
|
+
if node.symlink?
|
10
|
+
"inode/symlink"
|
11
|
+
|
12
|
+
elsif d?
|
13
|
+
"inode/directory"
|
14
|
+
|
15
|
+
elsif MIME[t]
|
16
|
+
MIME[t]
|
17
|
+
|
18
|
+
elsif Rack::Mime::MIME_TYPES[t='.'+t.to_s]
|
19
|
+
Rack::Mime::MIME_TYPES[t]
|
20
|
+
|
21
|
+
elsif base.index('msg.')==0
|
22
|
+
"message/rfc822"
|
23
|
+
|
24
|
+
elsif e
|
25
|
+
`file --mime-type -b #{sh}`.chomp
|
26
|
+
|
27
|
+
else
|
28
|
+
"application/octet-stream"
|
29
|
+
end)
|
30
|
+
end
|
31
|
+
|
32
|
+
# MIME-type of recursively-dereferenced path
|
33
|
+
def mimeP
|
34
|
+
@mime ||=
|
35
|
+
(p = realpath
|
36
|
+
|
37
|
+
unless p
|
38
|
+
nil
|
39
|
+
else
|
40
|
+
t = ((File.extname p).tail || '').downcase.to_sym
|
41
|
+
|
42
|
+
if p.directory?
|
43
|
+
"inode/directory"
|
44
|
+
|
45
|
+
elsif MIME[t]
|
46
|
+
MIME[t]
|
47
|
+
|
48
|
+
elsif Rack::Mime::MIME_TYPES[t='.'+t.to_s]
|
49
|
+
Rack::Mime::MIME_TYPES[t]
|
50
|
+
|
51
|
+
elsif (File.basename p).index('msg.')==0
|
52
|
+
"message/rfc822"
|
53
|
+
|
54
|
+
else
|
55
|
+
`file --mime-type -b #{Shellwords.escape p.to_s}`.chomp
|
56
|
+
end
|
57
|
+
end )
|
58
|
+
end
|
59
|
+
end
|
data/infod/Es/out.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
class E
|
2
|
+
|
3
|
+
def render mime, graph, e
|
4
|
+
E[Render+ mime].y graph, e
|
5
|
+
end
|
6
|
+
|
7
|
+
fn '/E/GET',->e,r{[301,{Location: '/'},[]]}
|
8
|
+
|
9
|
+
def response
|
10
|
+
|
11
|
+
q = @r.q # query-string
|
12
|
+
g = q['graph'] # graph-function selector
|
13
|
+
|
14
|
+
# empty response graph
|
15
|
+
m = {}
|
16
|
+
|
17
|
+
# identify graph
|
18
|
+
graphID = (F['protograph/' + g] || F['protograph/'])[self,q,m]
|
19
|
+
|
20
|
+
return F[E404][self,@r] if m.empty?
|
21
|
+
|
22
|
+
# identify response
|
23
|
+
@r['ETag'] ||= [graphID, q, @r.format, Watch].h
|
24
|
+
|
25
|
+
maybeSend @r.format, ->{
|
26
|
+
|
27
|
+
# response
|
28
|
+
r = E'/E/req/' + @r['ETag'].dive
|
29
|
+
if r.e # response exists
|
30
|
+
r # cached response
|
31
|
+
else
|
32
|
+
|
33
|
+
# graph
|
34
|
+
c = E '/E/graph/' + graphID.dive
|
35
|
+
if c.e # graph exists
|
36
|
+
m.merge! c.r true
|
37
|
+
else
|
38
|
+
# construct graph
|
39
|
+
(F['graph/' + g] || F['graph/'])[self,q,m]
|
40
|
+
# cache graph
|
41
|
+
c.w m,true
|
42
|
+
end
|
43
|
+
|
44
|
+
# graph sort/filter
|
45
|
+
E.filter q, m, self
|
46
|
+
|
47
|
+
# cache response
|
48
|
+
r.w render @r.format, m, @r
|
49
|
+
end }
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -1,8 +1,12 @@
|
|
1
1
|
#watch __FILE__
|
2
2
|
class E
|
3
3
|
|
4
|
-
fn 'head/page',->d,e{
|
5
|
-
|
4
|
+
fn 'head/page',->d,e{
|
5
|
+
v = e.q['v']
|
6
|
+
unless v == 'page'
|
7
|
+
h = F['head/'+v] || F['head']
|
8
|
+
h[d,e]
|
9
|
+
end}
|
6
10
|
|
7
11
|
fn 'view/page',->d,e{
|
8
12
|
# try daydirs if no pagination data provided
|
@@ -25,6 +29,6 @@ class E
|
|
25
29
|
|
26
30
|
[(H.js '/js/pager'),(H.once e,:mu,(H.js '/js/mu')), # n/p key shortcuts
|
27
31
|
c,(H (F['view/'+e.q['v']]||F['view']).(d,e)), # content
|
28
|
-
'<br clear=all>',c]}
|
32
|
+
'<br clear=all>',{class: :bottom, c: c}]}
|
29
33
|
|
30
34
|
end
|
data/infod/Es/pdf.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class E
|
2
|
+
|
3
|
+
def triplrPDF &f
|
4
|
+
|
5
|
+
text = docBase.a '.txt'
|
6
|
+
unless text.e && text.m > m
|
7
|
+
puts "PDF #{uri}"
|
8
|
+
`pdftotext #{sh}`
|
9
|
+
end
|
10
|
+
|
11
|
+
# metadata
|
12
|
+
triplrStdOut 'pdfinfo', &f
|
13
|
+
|
14
|
+
# body
|
15
|
+
yield uri, Content, `cat #{text.sh}`
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/infod/Es/rdf.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
class E
|
3
|
+
|
4
|
+
def self.renderRDF d,f
|
5
|
+
require 'linkeddata'
|
6
|
+
(RDF::Writer.for f).buffer{|w|
|
7
|
+
d.values.each{|r| r.triples{|s,p,o|
|
8
|
+
s = RDF::URI s
|
9
|
+
p = RDF::URI p
|
10
|
+
o = ([E,Hash].member?(o.class) ? (RDF::URI o.uri) : (RDF::Literal o)) rescue nil
|
11
|
+
(w << (RDF::Statement.new s,p,o) if o ) rescue nil
|
12
|
+
}}}
|
13
|
+
end
|
14
|
+
|
15
|
+
def triplrRDF format=:rdfa, localFile=true ; require 'linkeddata'
|
16
|
+
location = (localFile && f) ? d : uri
|
17
|
+
puts [:RDF,location].join ' '
|
18
|
+
RDF::Reader.open(location, :format => format){|r|
|
19
|
+
r.each_triple{|s,p,o|
|
20
|
+
yield s.to_s, p.to_s, [RDF::Node, RDF::URI].member?(o.class) ? E(o) : o.value.do{|v|v.class == String ? v.to_utf8 : v}}}
|
21
|
+
end
|
22
|
+
|
23
|
+
[['application/ld+json',:jsonld],
|
24
|
+
['application/json+ld',:jsonld],
|
25
|
+
['application/jsonld',:jsonld],
|
26
|
+
['application/rdf+xml',:rdfxml],
|
27
|
+
['application/rdfxml',:rdfxml],
|
28
|
+
['text/ntriples',:ntriples],
|
29
|
+
['text/turtle',:turtle],
|
30
|
+
['text/rdf+n3',:n3],
|
31
|
+
['text/n3',:n3]
|
32
|
+
].map{|mime|
|
33
|
+
F[Render+mime[0]] = ->d,a=nil{E.renderRDF d, mime[1]}}
|
34
|
+
|
35
|
+
end
|