infod 0.0.2 → 0.0.3
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 +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/mail.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#watch __FILE__
|
2
|
+
class E
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'tmail'
|
6
|
+
rescue LoadError => e
|
7
|
+
end
|
8
|
+
|
9
|
+
def triplrTmail &f
|
10
|
+
messagePath = ->id{
|
11
|
+
h = id.h # hash
|
12
|
+
'/msg/' + h[0..1] + '/' + h[2] + '/' + id}
|
13
|
+
|
14
|
+
(TMail::Mail.load node).do{|m| # load
|
15
|
+
d = m.message_id; return unless d # parse successful?
|
16
|
+
id = d[1..-2] # message-ID
|
17
|
+
e = messagePath[id] # webized ID
|
18
|
+
yield e, DC+'identifier', id # original ID
|
19
|
+
yield e, DC+'source', self # original file
|
20
|
+
yield e, Type, E[SIOCt + 'MailMessage']
|
21
|
+
yield e, Type, E[SIOC + 'Post']
|
22
|
+
yield e, Date, m.date.iso8601 if m.date
|
23
|
+
yield e, Title, m.subject.to_utf8
|
24
|
+
yield e, SIOC+'name', m.friendly_from.to_utf8
|
25
|
+
yield e, Creator, E['/m/'+m.from[0].to_utf8]
|
26
|
+
m.header['x-original-to'].do{|f|
|
27
|
+
yield e, SIOC+'reply_to', E[URI.escape "mailto:#{f}?References=<#{e}>&In-Reply-To=<#{e}>&Subject=#{m.subject.to_utf8}"] }
|
28
|
+
%w{to cc bcc}.map{|to|
|
29
|
+
m.send(to).do{|to| to.map{|to|
|
30
|
+
yield e, To, E['/m/'+to.to_utf8]}}}
|
31
|
+
%w{in_reply_to references}.map{|ref|
|
32
|
+
m.send(ref).do{|refs| refs.map{|r|
|
33
|
+
yield e, SIOC+'reply_of', E[messagePath[r[1..-2]]]}}}
|
34
|
+
# minimal local markup to use as HTML-literal even if decoupled from specialized view
|
35
|
+
yield e, Content, H([{_: :pre, class: :mail, style: 'white-space: pre-wrap',
|
36
|
+
c: m.concat_message(e.E,0,&f).gsub(/^\s*(>)(>|\s)*\n/,"").lines.to_a.map{|l| # < skip quoted emptylines v tag quoted lines
|
37
|
+
{_: :span, class: ((l.match /(^\s*(>|On[^\n]+(said|wrote))[^\n]*)\n/) ? 'q' : 'u'), c: [ l.chomp, "\n" ]}}},
|
38
|
+
{_: :style, c: "pre.mail .q {background-color:#0018ff;color:#fff}\npre.mail a {background-color: #91acb3;color:#fff}\npre.mail img {max-width:100%}"}])}
|
39
|
+
rescue Exception => e
|
40
|
+
puts e
|
41
|
+
end
|
42
|
+
|
43
|
+
def triplrMailMessage &f
|
44
|
+
insertDocs :triplrTmail, nil, [To,SIOC+'reply_of'], &f
|
45
|
+
end
|
46
|
+
=begin
|
47
|
+
there's another mail library called Mail, as of v2.5.4 takes 50x as long as tmail (apt-get install ruby-tmail)
|
48
|
+
HEAD 200 http://m/m/2013/12/01/?nocache=&triplr=triplrMail curl/7.33.0 5.4003388
|
49
|
+
HEAD 200 http://m/m/2013/12/01/?nocache=&triplr=triplrTmail curl/7.33.0 0.1198720
|
50
|
+
|
51
|
+
almost a copy of above works but identifiers are not wrapped in <> - with caching it might be fast enough..
|
52
|
+
|
53
|
+
=end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
module TMail
|
58
|
+
class Mail
|
59
|
+
def unicode_body
|
60
|
+
unquoted_body.to_utf8
|
61
|
+
end
|
62
|
+
def concat_message i, partCount=0, &f
|
63
|
+
if multipart?
|
64
|
+
parts.map{|part|
|
65
|
+
if part.multipart? # and even more nested parts..
|
66
|
+
part.concat_message i, partCount, &f
|
67
|
+
elsif !attachment?(part) && part.sub_type != 'html'
|
68
|
+
part.unicode_body.hrefs true
|
69
|
+
else # attachment
|
70
|
+
a = i.a('.attache').mk # create container
|
71
|
+
p = a.as(part['content-type']['name'] || (partCount.to_s + '.' + (E::MIME.invert[part.content_type] || '.bin').to_s))
|
72
|
+
p.w part.body if !p.e # write attachment into message container
|
73
|
+
partCount += 1 # display images
|
74
|
+
yield i.uri, E::SIOC+'attachment', p
|
75
|
+
'<a href="'+p.uri+'">'+(part.main_type=='image' ? '<img src="'+p.uri+'">' : '')+p.uri.label+"</a><br>\n"
|
76
|
+
end
|
77
|
+
}.join
|
78
|
+
else # just a part
|
79
|
+
unicode_body.do{|b|
|
80
|
+
if content_type && content_type.match(/html/)
|
81
|
+
(b.split /<body[^>]*>/)[-1].split(/<\/body>/)[0]
|
82
|
+
else
|
83
|
+
b.hrefs true
|
84
|
+
end}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class String; def is_binary_data?; true; end; end
|
data/infod/{Es/man.rb → man.rb}
RENAMED
@@ -54,18 +54,6 @@ class E
|
|
54
54
|
preconv = %w{hu pt tr}.member?(superLang) ? "" : "-k"
|
55
55
|
pageCmd = "zcat #{man} | groff #{preconv} -T html -man -P -D -P #{imagePath}"
|
56
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
57
|
page = Nokogiri::HTML.parse page
|
70
58
|
body = page.css('body')[0]
|
71
59
|
|
@@ -88,9 +76,9 @@ class E
|
|
88
76
|
# HTMLize hyperlinks
|
89
77
|
# markup commands
|
90
78
|
body.xpath('//text()').map{|a|
|
91
|
-
a.replace a.to_s.gsub('>','>').hrefs.gsub /\b([^<>\s(]+)\(/mi, '<b>\1</b>('
|
92
|
-
}
|
93
|
-
|
79
|
+
a.replace a.to_s.gsub('>','>').hrefs.gsub /\b([^<>\s(]+)\(/mi, '<b>\1</b>('}
|
80
|
+
body.css('font').map{|f|f.remove_attribute 'color'}
|
81
|
+
|
94
82
|
qs = r['QUERY_STRING'].do{|q| q.empty? ? '' : '?' + q}
|
95
83
|
# href-ize commands
|
96
84
|
body.css('b').map{|b|
|
@@ -19,14 +19,14 @@ class E
|
|
19
19
|
yield s, Content, m[3].hrefs(true)
|
20
20
|
yield s, Type, E[SIOCt+'InstantMessage']
|
21
21
|
yield s, Type, E[SIOC+'Post']
|
22
|
-
yield s, '
|
23
|
-
|
22
|
+
yield s, SIOC+'link', (m[3].match(/http:\//) ? 'true' : 'false')
|
23
|
+
} rescue nil
|
24
24
|
}
|
25
25
|
end
|
26
26
|
|
27
|
-
def tw g
|
27
|
+
def tw g
|
28
28
|
no.readlines.shuffle.each_slice(22){|s|
|
29
|
-
E['https://twitter.com/search/realtime?q='+s.map{|u|'from:'+u.chomp}.intersperse('+OR+').join].
|
29
|
+
E['https://twitter.com/search/realtime?q='+s.map{|u|'from:'+u.chomp}.intersperse('+OR+').join].insertDocs :triplrTweets, g}
|
30
30
|
end
|
31
31
|
|
32
32
|
def triplrTweets
|
@@ -47,38 +47,29 @@ class E
|
|
47
47
|
}
|
48
48
|
end
|
49
49
|
|
50
|
-
fn 'head/chat',->d,e{
|
51
|
-
t = d.map{|_,r|r[Date]}.flatten.compact.map &:to_time
|
52
|
-
c = d.map{|_,r|r[Content]}.compact.size
|
53
|
-
[{_: :title, c: "#{c} post#{c!=1 && 's'} #{t.min} -> #{t.max}"},
|
54
|
-
(Fn 'head.formats',e)]}
|
55
|
-
|
56
50
|
fn 'view/chat',->d,e{
|
57
|
-
Fn'
|
51
|
+
Fn'baseview/chat',d,e,->{d.map{|u,r|Fn 'itemview/chat',r,e}}}
|
58
52
|
|
59
|
-
fn '
|
60
|
-
|
61
|
-
r[
|
62
|
-
r[
|
63
|
-
[{_: :a, id: line},
|
64
|
-
{_: :a, :class => :date, href: r.url, c: r[Date][0].match(/T([0-9:]{5})/)[1]},
|
53
|
+
fn 'itemview/chat',->r,e{
|
54
|
+
r[Type] && [*r[Type]].map{|t|t.respond_to?(:uri) && t.uri}.include?(SIOCt+'MailMessage') && r[:mail]=true
|
55
|
+
r[Content] && r[Date] && r[Date][0] &&
|
56
|
+
[r[Date][0].match(/T([0-9:]{5})/).do{|m|m[1]},
|
65
57
|
{_: :span, :class => :nick, c: {_: :a, href: r[Atom+'/link/alternate'].do{|a|a[0].uri}||r.url,
|
66
|
-
c: [r[Atom+"/link/image"].do{|p| {_: :img,
|
58
|
+
c: [r[Atom+"/link/image"].do{|p| {_: :img, src: p[0].uri, style: "#{rand(2).zero? ? 'left' : 'right'}: 0"}},
|
67
59
|
{_: :span, c: r[SIOC+'name']||r[Creator]||'#'}]}},' ',
|
68
|
-
{_: :span, :class => :tw,
|
69
|
-
c: [r[
|
70
|
-
|
71
|
-
((r[Title].to_s==r[Content].to_s || r.uri.match(/twitter/)) && '' ||
|
72
|
-
{_: :a, href: r.url, c: r[Title],:class => r[:mail] ? :titleMail : :title}),
|
60
|
+
{_: :span, :class => :tw, # skip redundant title fields
|
61
|
+
c: [((r[Title].to_s == r[Content].to_s || r.uri.match(/twitter/)) && '' ||
|
62
|
+
{_: :a, :class => :title, href: r.url, c: r[Title]}), # skip quoted mail-lines & abbreviate
|
73
63
|
r[:mail] ? (r[Content].map{|c|c.lines.to_a.grep(/^[^&@_]+$/)[0..21]}) : r[Content],
|
74
|
-
]},
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
64
|
+
]},"<br>\n"]}
|
65
|
+
|
66
|
+
F['view/'+SIOCt+'BoardPost']=->d,e{
|
67
|
+
d.map{|u,r|
|
68
|
+
{class: :BoardPost, style: "background-color:#ff4500;color:#fff;float:left;border-radius:.8em;padding:.4em;max-width:42em;margin:.5em",
|
69
|
+
c: F['itemview/chat'][r,e]}}}
|
70
|
+
|
71
|
+
fn 'baseview/chat',->d,e,c{
|
72
|
+
[(H.once e,'chat.head',(H.css '/css/tw'),{_: :style, c: "body {background-color: #{E.c}}\n"}),c.()]}
|
82
73
|
|
83
74
|
F['view/'+SIOCt+'InstantMessage']=F['view/chat']
|
84
75
|
F['view/'+SIOCt+'MicroblogPost']=F['view/chat']
|
data/infod/{K.rb → mime.rb}
RENAMED
@@ -1,37 +1,49 @@
|
|
1
1
|
#watch __FILE__
|
2
2
|
class E
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
# no link-follow
|
5
|
+
def mime
|
6
|
+
@mime ||=
|
7
|
+
(t = ext.downcase.to_sym
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
9
|
+
if node.symlink?
|
10
|
+
"inode/symlink"
|
11
|
+
elsif d?
|
12
|
+
"inode/directory"
|
13
|
+
elsif MIME[t]
|
14
|
+
MIME[t]
|
15
|
+
elsif Rack::Mime::MIME_TYPES[t='.'+t.to_s]
|
16
|
+
Rack::Mime::MIME_TYPES[t]
|
17
|
+
elsif base.index('msg.')==0
|
18
|
+
"message/rfc822"
|
19
|
+
elsif e
|
20
|
+
`file --mime-type -b #{sh}`.chomp
|
21
|
+
else
|
22
|
+
"application/octet-stream"
|
23
|
+
end)
|
24
|
+
end
|
25
|
+
|
26
|
+
# recursively-dereferenced links
|
27
|
+
def mimeP
|
28
|
+
@mime ||=
|
29
|
+
(p = realpath
|
30
|
+
unless p
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
t = ((File.extname p).tail || '').downcase.to_sym
|
34
|
+
if p.directory?
|
35
|
+
"inode/directory"
|
36
|
+
elsif MIME[t]
|
37
|
+
MIME[t]
|
38
|
+
elsif Rack::Mime::MIME_TYPES[t='.'+t.to_s]
|
39
|
+
Rack::Mime::MIME_TYPES[t]
|
40
|
+
elsif (File.basename p).index('msg.')==0
|
41
|
+
"message/rfc822"
|
42
|
+
else
|
43
|
+
`file --mime-type -b #{Shellwords.escape p.to_s}`.chomp
|
44
|
+
end
|
45
|
+
end )
|
46
|
+
end
|
35
47
|
|
36
48
|
MIME={
|
37
49
|
aif: 'audio/aif',
|
@@ -40,6 +52,7 @@ class E
|
|
40
52
|
avi: 'video/avi',
|
41
53
|
e: 'application/json+rdf',
|
42
54
|
coffee: 'text/plain',
|
55
|
+
conf: 'text/plain',
|
43
56
|
css: 'text/css',
|
44
57
|
csv: 'text/comma-separated-values',
|
45
58
|
doc: 'application/word',
|
@@ -70,12 +83,14 @@ class E
|
|
70
83
|
pdf: 'application/pdf',
|
71
84
|
pl: 'application/perl',
|
72
85
|
png: 'image/png',
|
86
|
+
ps: 'application/postscript',
|
73
87
|
py: 'application/python',
|
74
88
|
rb: 'application/ruby',
|
75
89
|
ru: 'application/ruby',
|
76
90
|
rdf: 'application/rdf+xml',
|
77
91
|
rtf: 'text/rtf',
|
78
92
|
ssv: 'text/semicolon-separated-values',
|
93
|
+
tex: 'text/x-tex',
|
79
94
|
textile: 'application/textile',
|
80
95
|
tsv: 'text/tab-separated-values',
|
81
96
|
ttl: 'text/turtle',
|
@@ -87,9 +102,6 @@ class E
|
|
87
102
|
xlsx: 'application/excel',
|
88
103
|
}
|
89
104
|
|
90
|
-
VideoFile = /(avi|flv|mkv|mpg|mp4|wmv)$/i
|
91
|
-
AudioFile = /(aif|wav|flac|mp3|m4a|aac|ogg)$/i
|
92
|
-
|
93
105
|
MIMEsource={
|
94
106
|
'application/atom+xml' => [:triplrFeed],
|
95
107
|
'application/markdown' => [:triplrMarkdown],
|
@@ -97,18 +109,21 @@ class E
|
|
97
109
|
'application/rdf+xml' => [:triplrRDF,:rdfxml],
|
98
110
|
'application/json' => [:triplrJSON],
|
99
111
|
'application/pdf' => [:triplrPDF],
|
112
|
+
'application/postscript'=> [:triplrPS],
|
100
113
|
'application/textile' => [:triplrTextile],
|
101
114
|
'application/uri' => [:triplrUriList],
|
102
115
|
'application/word' => [:triplrWord],
|
103
116
|
'audio/mp4' => [:triplrStdOut,'faad -i',Audio],
|
104
117
|
'audio/mpeg' => [:triplrStdOut,'id3info',Audio,/\((.*?)\)$/],
|
105
118
|
'audio' => [:triplrStdOut,'sndfile-info',Audio],
|
119
|
+
'image' => [:triplrImage],
|
106
120
|
'inode/symlink' => [:triplrSymlink],
|
107
|
-
'message/rfc822' => [:
|
121
|
+
'message/rfc822' => [:triplrMailMessage],
|
108
122
|
'text/ansi' => [:triplrANSI],
|
109
123
|
'text/comma-separated-values'=>[:triplrCSV,/,/],
|
110
124
|
'text/log' => [:triplrIRC],
|
111
125
|
'text/man' => [:triplrMan],
|
126
|
+
'text/n3' => [:triplrRDF, :n3],
|
112
127
|
'text/nfo' => [:triplrHref,'cp437'],
|
113
128
|
'text/ntriples' => [:triplrRDF, :ntriples],
|
114
129
|
'text/plain' => [:triplrHref],
|
@@ -116,6 +131,7 @@ class E
|
|
116
131
|
'text/semicolon-separated-values'=>[:triplrCSV,/;/],
|
117
132
|
'text/tab-separated-values'=>[:triplrCSV,/\t/],
|
118
133
|
'text/turtle' => [:triplrRDF,:turtle],
|
134
|
+
'text/x-tex' => [:triplrTeX],
|
119
135
|
}
|
120
136
|
|
121
137
|
# prefer a view even if requested file exists
|
@@ -124,6 +140,7 @@ class E
|
|
124
140
|
'application/markdown' => true,
|
125
141
|
'application/json+rdf' => true,
|
126
142
|
'application/org' => true,
|
143
|
+
'application/postscript' => true,
|
127
144
|
'application/textile' => true,
|
128
145
|
'application/uri' => true,
|
129
146
|
'application/word' => true,
|
@@ -134,6 +151,14 @@ class E
|
|
134
151
|
'text/man'=>true,
|
135
152
|
'text/nfo'=>true,
|
136
153
|
'text/rtf'=>true,
|
154
|
+
'text/x-tex'=>true,
|
155
|
+
}
|
156
|
+
|
157
|
+
# cache triplr output
|
158
|
+
MIMEcache={
|
159
|
+
'audio' => true,
|
160
|
+
'image' => true,
|
161
|
+
# '' =>
|
137
162
|
}
|
138
163
|
|
139
164
|
%w{c c++ fortran haskell makefile pascal perl php python ruby}.map{|t|
|
@@ -141,25 +166,16 @@ class E
|
|
141
166
|
MIMEcook[m+t] = true
|
142
167
|
}}
|
143
168
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
"rdf" => W3+"1999/02/22-rdf-syntax-ns#",
|
148
|
-
"rdfs" => RDFs,
|
149
|
-
"sioc" => SIOC,
|
150
|
-
"stat" => Stat,
|
151
|
-
}
|
152
|
-
|
153
|
-
# literal to pathname types
|
154
|
-
Literal={}
|
155
|
-
[Purl+'dc/elements/1.1/date',
|
156
|
-
Date,
|
157
|
-
DC+'created',
|
158
|
-
Modified,
|
159
|
-
].map{|f|Literal[f]=true}
|
169
|
+
def render mime, graph, e
|
170
|
+
E[Render+ mime].y graph, e
|
171
|
+
end
|
160
172
|
|
161
|
-
def
|
162
|
-
|
173
|
+
def triplrMIME &b
|
174
|
+
mimeP.do{|mime|
|
175
|
+
yield uri, E::Type, (E MIMEtype+mimeP)
|
176
|
+
(MIMEsource[mimeP]||
|
177
|
+
MIMEsource[mimeP.split(/\//)[0]]).do{|s|
|
178
|
+
send *s,&b }}
|
163
179
|
end
|
164
180
|
|
165
181
|
end
|
data/infod/{N.rb → names.rb}
RENAMED
@@ -1,25 +1,17 @@
|
|
1
1
|
%w{base64 cgi shellwords}.each{|r|require(r)}
|
2
2
|
|
3
|
-
def E e
|
4
|
-
E.new e
|
5
|
-
end
|
6
|
-
|
7
3
|
class E
|
8
4
|
|
9
|
-
|
5
|
+
attr_reader :uri
|
6
|
+
alias_method :url, :uri
|
10
7
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
else
|
15
|
-
self
|
16
|
-
end
|
8
|
+
def env r=nil
|
9
|
+
r ? (@r = r
|
10
|
+
self) : @r
|
17
11
|
end
|
18
|
-
|
19
|
-
attr_reader :uri
|
20
12
|
|
21
|
-
def
|
22
|
-
|
13
|
+
def == u
|
14
|
+
to_s == u.to_s
|
23
15
|
end
|
24
16
|
|
25
17
|
def basename
|
@@ -39,11 +31,10 @@ class E
|
|
39
31
|
def ttl; @ttl||= docBase.a('.ttl') end
|
40
32
|
|
41
33
|
def docBase
|
42
|
-
uri.split(/#/)[0].E.do{|d|
|
43
|
-
d.dirname.as d.bare }
|
34
|
+
!uri.empty? && uri.split(/#/)[0].do{|u|u.E.do{|d| d.dirname.as d.bare }} || E['']
|
44
35
|
end
|
45
36
|
|
46
|
-
#
|
37
|
+
# and w/ URI-lib
|
47
38
|
def docBaseURI
|
48
39
|
u = URI uri
|
49
40
|
s = u.scheme
|
@@ -79,22 +70,27 @@ class E
|
|
79
70
|
end
|
80
71
|
alias_method :dir, :dirname
|
81
72
|
|
82
|
-
#
|
83
|
-
def
|
84
|
-
|
73
|
+
# add hostname to URI if missing
|
74
|
+
def hostURL e
|
75
|
+
host = 'http://'+e['SERVER_NAME']
|
76
|
+
if uri.index('/') == 0
|
77
|
+
host + uri
|
78
|
+
else
|
79
|
+
uri
|
80
|
+
end
|
85
81
|
end
|
86
82
|
|
87
|
-
# local
|
83
|
+
# locator for local data about global URI
|
88
84
|
def localURL e
|
89
85
|
# path
|
90
|
-
if uri.index('/') == 0
|
86
|
+
if uri.index('/') == 0 # already a local path
|
91
87
|
uri
|
92
88
|
# host match
|
93
|
-
elsif uri.index('http://'+e['SERVER_NAME']+'/') == 0
|
89
|
+
elsif e && uri.index('http://'+e['SERVER_NAME']+'/') == 0
|
94
90
|
pathSegment.uri
|
95
91
|
# non-local
|
96
92
|
else
|
97
|
-
|
93
|
+
URIURL + (CGI.escape uri)
|
98
94
|
end
|
99
95
|
end
|
100
96
|
|
@@ -116,6 +112,10 @@ class E
|
|
116
112
|
uri.expand.E
|
117
113
|
end
|
118
114
|
|
115
|
+
def shorten
|
116
|
+
uri.shorten.E
|
117
|
+
end
|
118
|
+
|
119
119
|
def prependURI u
|
120
120
|
E u.to_s + uri
|
121
121
|
end
|
@@ -129,7 +129,7 @@ class E
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def concatURI b
|
132
|
-
u.appendURI b.E.
|
132
|
+
u.appendURI b.E.shortPath
|
133
133
|
end
|
134
134
|
|
135
135
|
alias_method :a, :appendURI
|
@@ -140,6 +140,19 @@ class E
|
|
140
140
|
uri.path?
|
141
141
|
end
|
142
142
|
|
143
|
+
def shortPath
|
144
|
+
@shortPath ||=
|
145
|
+
(if path?
|
146
|
+
if uri.match /^\//
|
147
|
+
uri
|
148
|
+
else
|
149
|
+
'/' + uri.shorten
|
150
|
+
end
|
151
|
+
else
|
152
|
+
'/E/' + uri.h.dive[0..5] + (Base64.urlsafe_encode64 uri)
|
153
|
+
end)
|
154
|
+
end
|
155
|
+
|
143
156
|
# URI -> path
|
144
157
|
def path
|
145
158
|
@path ||=
|
@@ -170,15 +183,21 @@ class E
|
|
170
183
|
end
|
171
184
|
|
172
185
|
# literals to URIs
|
173
|
-
|
186
|
+
# currently used for iso8601 dates mapping to paths, so date-range queries can be done w/ just dir/fs tooling
|
187
|
+
# could also use as a "trie" for autocomplete or sorting strings
|
174
188
|
def E.literal o
|
175
189
|
E['/'].literal o
|
176
190
|
end
|
191
|
+
|
192
|
+
Literal={}
|
193
|
+
[Purl+'dc/elements/1.1/date',
|
194
|
+
Date,DC+'created',DC+'modified',
|
195
|
+
].map{|f|Literal[f]=true}
|
177
196
|
|
178
197
|
def literal o
|
179
198
|
|
180
199
|
# already a URI
|
181
|
-
return
|
200
|
+
return o if o.class == E
|
182
201
|
|
183
202
|
# blob for non-strings
|
184
203
|
return literalBlob o unless o.class == String
|
@@ -196,7 +215,7 @@ class E
|
|
196
215
|
|
197
216
|
# pathname for short literals
|
198
217
|
def literalURI o
|
199
|
-
E "/l/"+
|
218
|
+
E "/l/"+o.gsub(/[\.:\-T+]/,'/')+'/'+o if Literal[uri] && o
|
200
219
|
end
|
201
220
|
|
202
221
|
def literalBlobURI o
|
@@ -225,13 +244,16 @@ class E
|
|
225
244
|
{'uri' => uri}
|
226
245
|
end
|
227
246
|
|
247
|
+
# implementation-specific internal pathnames not on the web
|
248
|
+
F['/E/GET'] = F[E404]
|
249
|
+
|
228
250
|
end
|
229
251
|
|
230
252
|
class Hash
|
231
253
|
def uri
|
232
|
-
self["uri"]
|
254
|
+
self["uri"]||""
|
233
255
|
end
|
234
|
-
|
256
|
+
alias_method :url, :uri
|
235
257
|
def label
|
236
258
|
self[E::Label] || uri.label
|
237
259
|
end
|
@@ -253,18 +275,25 @@ class String
|
|
253
275
|
self[4..-1]
|
254
276
|
end
|
255
277
|
|
256
|
-
# expand qname-style identifier to URI
|
278
|
+
# expand qname/CURIE-style identifier to URI
|
257
279
|
Expand={}
|
258
280
|
def expand
|
259
|
-
# memoize lookups
|
260
281
|
(Expand.has_key? self) ?
|
261
282
|
Expand[self] :
|
262
283
|
(Expand[self] =
|
263
284
|
match(/([^:]+):([^\/].*)/).do{|e|
|
264
|
-
|
285
|
+
( E::Prefix[e[1]] || e[1]+':' )+e[2]} ||
|
265
286
|
self )
|
266
287
|
end
|
267
288
|
|
289
|
+
# shrink URI to qname/CURIE/prefix'd identifier
|
290
|
+
def shorten
|
291
|
+
E::Prefix.map{|p,f|
|
292
|
+
return p + ':' + self[f.size..-1] if (index f) == 0
|
293
|
+
}
|
294
|
+
self
|
295
|
+
end
|
296
|
+
|
268
297
|
def sh
|
269
298
|
Shellwords.escape self
|
270
299
|
end
|
@@ -277,29 +306,33 @@ class String
|
|
277
306
|
# path -> URI || literal
|
278
307
|
def unpath
|
279
308
|
|
280
|
-
# URI
|
309
|
+
# HTTP URI
|
281
310
|
if m = (match /^\/([a-z]+:)\/+(.*)/)
|
282
311
|
(m[1] + '//' + m[2]).E
|
283
312
|
|
284
|
-
#
|
313
|
+
# CURIE
|
314
|
+
elsif m = (match /^\/([^\/:]+:[^\/]+)/)
|
315
|
+
m[1].expand.E
|
316
|
+
|
317
|
+
# opaque URI w/ optional extension
|
318
|
+
elsif match /^\/E\/..\//
|
319
|
+
self[9..-1].match(/([^.]+)(.*)/).do{|c|
|
320
|
+
(Base64.urlsafe_decode64 c[1]) + c[2]
|
321
|
+
}.E
|
322
|
+
|
323
|
+
# String literal
|
285
324
|
elsif match /^\/E\/blob/
|
286
325
|
self.E.r
|
287
326
|
|
288
|
-
# JSON literal
|
327
|
+
# JSON literal
|
289
328
|
elsif match /^\/E\/json/
|
290
329
|
self.E.r true
|
291
330
|
|
292
|
-
#
|
331
|
+
# literal in basename
|
293
332
|
elsif match /^\/l\//
|
294
333
|
File.basename self
|
295
334
|
|
296
|
-
#
|
297
|
-
elsif match /^\/E\/..\//
|
298
|
-
self[9..-1].match(/([^.]+)(.*)/).do{|c|
|
299
|
-
(Base64.urlsafe_decode64 c[1]) + c[2]
|
300
|
-
}.E
|
301
|
-
|
302
|
-
# path
|
335
|
+
# plain path
|
303
336
|
else
|
304
337
|
self.E
|
305
338
|
end
|