ttl2html 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e8fed8c4d3c0b809f8adc74461c5e2b828d84acc
4
+ data.tar.gz: 2e9ce925edcf25a69be8760fbb7a686c06e02562
5
+ SHA512:
6
+ metadata.gz: 8eefe53b68272ea86b272c21d7b2accb3e9acb96063e462fb6b6899e6a5f6def5e94c12c156956e9e7bab0fb0cb835d69167ea97d2f51e49f1f7c60de1c47a00
7
+ data.tar.gz: 9f2f036ca40f225b3674c0ccccdb8798d24b6d7762b8c1b723c1507c166a776cf2682c869148c7b8e8bf3f6e26339d389744652d00101e8abe2de1045827eef6
data/bin/ttl2html ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "getoptlong"
4
+ require "ttl2html"
5
+
6
+ parser = GetoptLong.new
7
+ parser.set_options(
8
+ ['--cleanup', GetoptLong::NO_ARGUMENT],
9
+ ['--config', GetoptLong::REQUIRED_ARGUMENT],
10
+ )
11
+ opt_cleanup = false
12
+ opt_config = "config.yml"
13
+ parser.each_option do |optname, optarg|
14
+ case optname
15
+ when "--cleanup"
16
+ opt_cleanup = true
17
+ when "--config"
18
+ opt_config = optarg
19
+ end
20
+ end
21
+
22
+ ttl2html = TTL2HTML::App.new(opt_config)
23
+ ARGV.each do |file|
24
+ ttl2html.load_turtle(file)
25
+ end
26
+ if opt_cleanup
27
+ ttl2html.cleanup
28
+ else
29
+ ttl2html.output_html_files
30
+ ttl2html.output_turtle_files
31
+ end
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "fileutils"
4
+ require "pathname"
5
+ require "erb"
6
+
7
+ module TTL2HTML
8
+ class Template
9
+ attr_reader :param
10
+ include ERB::Util
11
+ def initialize(template, param = {})
12
+ @template = template
13
+ @param = param
14
+ @template_path = [ Dir.pwd, File.join(Dir.pwd, "templates") ]
15
+ end
16
+ def output_to(file, param = {})
17
+ @param.update(param)
18
+ @param[:output_file] = file
19
+ dir = File.dirname(file)
20
+ FileUtils.mkdir_p(dir) if not File.exist?(dir)
21
+ open(file, "w") do |io|
22
+ io.print to_html(@param)
23
+ end
24
+ end
25
+ def to_html(param)
26
+ param[:content] = to_html_raw(@template, param)
27
+ layout_fname = "layout.html.erb"
28
+ to_html_raw(layout_fname, param)
29
+ end
30
+ def to_html_raw(template, param)
31
+ @param.update(param)
32
+ template = find_template_path(template)
33
+ tmpl = open(template){|io| io.read }
34
+ erb = ERB.new(tmpl, $SAFE, "-")
35
+ erb.filename = template
36
+ erb.result(binding)
37
+ end
38
+
39
+ def find_template_path(fname)
40
+ if @param[:template_dir] and Dir.exist?(@param[:template_dir])
41
+ @template_path.unshift(@param[:template_dir])
42
+ @template_path.uniq!
43
+ end
44
+ @template_path.each do |dir|
45
+ file = File.join(dir, fname)
46
+ return file if File.exist? file
47
+ end
48
+ return nil
49
+ end
50
+
51
+ # helper method:
52
+ def relative_path(dest)
53
+ src = @param[:output_file]
54
+ src = Pathname.new(src).relative_path_from(Pathname.new(@param[:output_dir])) if @param[:output_dir]
55
+ path = Pathname(dest).relative_path_from(Pathname(File.dirname src))
56
+ path = path.to_s + "/" if File.directory? path
57
+ path
58
+ end
59
+ def relative_path_uri(dest_uri, base_uri)
60
+ if dest_uri.start_with? base_uri
61
+ dest = dest_uri.sub(base_uri, "")
62
+ relative_path(dest)
63
+ else
64
+ dest_uri
65
+ end
66
+ end
67
+ def get_title(data)
68
+ if @param[:title_property] and data[@param[:title_property]]
69
+ return get_language_literal(data[@param[:title_property]])
70
+ end
71
+ %w(
72
+ https://www.w3.org/TR/rdf-schema/#label
73
+ http://purl.org/dc/terms/title
74
+ http://purl.org/dc/elements/1.1/title
75
+ http://schema.org/name
76
+ http://www.w3.org/2004/02/skos/core#prefLabel
77
+ ).each do |property|
78
+ return get_language_literal(data[property]) if data[property]
79
+ end
80
+ "no title"
81
+ end
82
+ def get_language_literal(object)
83
+ if object.respond_to? :has_key?
84
+ object.values.first
85
+ else
86
+ object
87
+ end
88
+ end
89
+ def format_property(property, labels = {})
90
+ if labels and labels[property]
91
+ labels[property]
92
+ else
93
+ property.split(/[\/\#]/).last.capitalize
94
+ end
95
+ end
96
+ def format_object(object, data)
97
+ if object =~ /\Ahttps?:\/\//
98
+ rel_path = relative_path_uri(object, param[:base_uri])
99
+ if data[object]
100
+ "<a href=\"#{rel_path}\">#{get_title(param[:data_global][object]) or object}</a>"
101
+ else
102
+ "<a href=\"#{rel_path}\">#{object}</a>"
103
+ end
104
+ elsif object =~ /\A_:/ and param[:data_global][object]
105
+ format_triples(param[:data_global][object])
106
+ else
107
+ object
108
+ end
109
+ end
110
+ def format_triples(triples)
111
+ param_local = @param.merge(data: triples)
112
+ to_html_raw("templates/triples.html.erb", param_local)
113
+ end
114
+ end
115
+ end
@@ -0,0 +1 @@
1
+ TTL2HTML::VERSION = "0.0.1"
data/lib/ttl2html.rb ADDED
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "yaml"
4
+ require "nokogiri"
5
+ require "rdf/turtle"
6
+ require "ruby-progressbar"
7
+
8
+ require "ttl2html/template"
9
+
10
+ module TTL2HTML
11
+ class App
12
+ using ProgressBar::Refinements::Enumerator
13
+ def initialize(config = "config.yml")
14
+ @template = {}
15
+ @config = load_config(config)
16
+ if not @config[:base_uri]
17
+ raise "load_config: base_uri not found"
18
+ end
19
+ @data = {}
20
+ @graph = RDF::Graph.new
21
+ end
22
+
23
+ def load_config(file)
24
+ config = {}
25
+ YAML.load_file(file).each do |k, v|
26
+ config[k.intern] = v
27
+ end
28
+ config
29
+ end
30
+
31
+ def load_turtle(file)
32
+ STDERR.puts "loading #{file}..."
33
+ count = 0
34
+ RDF::Turtle::Reader.open(file) do |reader|
35
+ reader.statements.each do |statement|
36
+ @graph.insert(statement)
37
+ s = statement.subject
38
+ v = statement.predicate
39
+ o = statement.object
40
+ count += 1
41
+ @data[s.to_s] ||= {}
42
+ if o.respond_to?(:has_language?) and o.has_language?
43
+ @data[s.to_s][v.to_s] ||= {}
44
+ @data[s.to_s][v.to_s][o.language] = o.to_s
45
+ else
46
+ @data[s.to_s][v.to_s] ||= []
47
+ @data[s.to_s][v.to_s] << o.to_s
48
+ end
49
+ end
50
+ end
51
+ STDERR.puts "#{count} triples. #{@data.size} subjects."
52
+ @data
53
+ end
54
+ def format_turtle(subject, depth = 1)
55
+ turtle = RDF::Turtle::Writer.new
56
+ result = ""
57
+ if subject.iri?
58
+ result << "<#{subject}>\n#{" "*depth}"
59
+ else
60
+ result << "[\n#{" "*depth}"
61
+ end
62
+ result << @graph.query([subject, nil, nil]).predicates.sort.map do |predicate|
63
+ str = "<#{predicate}> "
64
+ str << @graph.query([subject, predicate, nil]).objects.sort_by do |object|
65
+ if object.resource? and not object.iri? # blank node:
66
+ i@graph.query([object, nil, nil]).statements.sort_by{|e|
67
+ [ e.predicate, e.object ]
68
+ }.map{|e|
69
+ [ e.predicate, e.object ]
70
+ }
71
+ else
72
+ object
73
+ end
74
+ end.map do |object|
75
+ if object.resource? and not object.iri? # blank node:
76
+ format_turtle(object, depth + 1)
77
+ else
78
+ case object
79
+ when RDF::URI
80
+ turtle.format_uri(object)
81
+ else
82
+ turtle.format_literal(object)
83
+ end
84
+ end
85
+ end.join(", ")
86
+ str
87
+ end.join(";\n#{" "*depth}")
88
+ result << " ." if subject.iri?
89
+ result << "\n"
90
+ result << "#{" "*(depth-1)}]" if not subject.iri?
91
+ result
92
+ end
93
+
94
+ def each_data
95
+ @data.each do |uri, v|
96
+ next if not uri.start_with? @config[:base_uri]
97
+ yield uri, v
98
+ end
99
+ end
100
+ def output_html_files
101
+ each_data do |uri, v|
102
+ template = Template.new("default.html.erb", @config)
103
+ param = @config.dup
104
+ param[:uri] = uri
105
+ param[:data] = v
106
+ param[:data_global] = @data
107
+ param[:title] = template.get_title(v)
108
+ if @data.keys.find{|e| e.start_with?(uri + "/") }
109
+ file = uri + "/index.html"
110
+ else
111
+ file = uri + ".html"
112
+ end
113
+ #p uri, param
114
+ file = file.sub(@config[:base_uri], "")
115
+ if @config[:output_dir]
116
+ Dir.mkdir @config[:output_dir] if not File.exist? @config[:output_dir]
117
+ file = File.join(@config[:output_dir], file)
118
+ end
119
+ template.output_to(file, param)
120
+ end
121
+ end
122
+ def output_turtle_files
123
+ each_data do |uri, v|
124
+ file = uri.sub(@config[:base_uri], "")
125
+ file << ".ttl"
126
+ if @config[:output_dir]
127
+ Dir.mkdir @config[:output_dir] if not File.exist? @config[:output_dir]
128
+ file = File.join(@config[:output_dir], file)
129
+ end
130
+ str = format_turtle(RDF::URI.new uri)
131
+ open(file, "w") do |io|
132
+ io.puts str.strip
133
+ end
134
+ end
135
+ end
136
+ def cleanup
137
+ each_data do |uri, v|
138
+ if @data.keys.find{|e| e.start_with?(uri + "/") }
139
+ file = uri + "/index.html"
140
+ else
141
+ file = uri + ".html"
142
+ end
143
+ html_file = file.sub(@config[:base_uri], "")
144
+ html_file = File.join(@config[:output_dir], html_file) if @config[:output_dir]
145
+ File.unlink html_file
146
+ ttl_file = uri.sub(@config[:base_uri], "") + ".ttl"
147
+ ttl_file = File.join(@config[:output_dir], ttl_file) if @config[:output_dir]
148
+ File.unlink ttl_file
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,14 @@
1
+ <div class="jumbotron">
2
+ <div class="container">
3
+ <h1><%=h param[:title] %></h1>
4
+ <p><small><span class="glyphicon glyphicon-link"></span> <a href="<%=h param[:uri] %>"><%=h param[:uri] %></a></small></p>
5
+ </div>
6
+ </div>
7
+ <div class="container">
8
+ <div class="row">
9
+ <div class="col-md-12">
10
+ <h2>詳細情報</h2>
11
+ <%= format_triples(param[:data]) %>
12
+ </div>
13
+ </div>
14
+ </div>
@@ -0,0 +1,34 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
6
+ <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
7
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
8
+ <title><% if param[:title] %><%=h param[:title] %><% end %><% if param[:site_title] %> - <%=h param[:site_title] %><% end %></title>
9
+ <meta name="twitter:card" content="summary">
10
+ <meta name="twitter:title" content="<% if param[:title] %><%=h param[:title] %><% end %><% if param[:site_title] %> - <%=h param[:site_title] %><% end %>">
11
+ </head>
12
+ <body>
13
+ <nav class="navbar navbar-inverse">
14
+ <div class="container">
15
+ <ul class="nav navbar-nav navbar-right">
16
+ <li<%= ' class="active"' if param[:active] == :home %>><a class="navbar-brand" href="/">Home</a></li>
17
+ <li<%= ' class="active"' if param[:active] == :about %>><a href="/about">About</a></li>
18
+ </ul>
19
+ </div>
20
+ </nav>
21
+ <%= param[:content] %>
22
+ <hr>
23
+ <footer>
24
+ <%- if param[:uri] -%>
25
+ <p class="pull-right"><a href="<%=h param[:uri] %>.ttl"><img src="https://www.w3.org/RDF/icons/rdf_flyer.24" alt="RDFデータ"></a></p>
26
+ <%- end -%>
27
+ </footer>
28
+
29
+ <!-- jQuery first, then Popper.js, then Bootstrap JS -->
30
+ <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
31
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
32
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
33
+ </body>
34
+ </html>
@@ -0,0 +1,16 @@
1
+ <dl>
2
+ <% param[:data].each do |k, v| %>
3
+ <dt><%=h format_property(k, param[:labels]) %></dt>
4
+ <% if v.respond_to? :has_key? %>
5
+ <% v.each do |lang, v2| %>
6
+ <dd lang="<%=h lang %>"><%= format_object v2, param[:data] %></dd>
7
+ <% end %>
8
+ <% elsif v.size > 1 %>
9
+ <% v.each do |v2| %>
10
+ <dd><%= format_object v2, param[:data] %></dd>
11
+ <% end %>
12
+ <% else %>
13
+ <dd><%= format_object v.first, param[:data] %></dd>
14
+ <% end %>
15
+ <%- end -%>
16
+ </dl>
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ttl2html
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Masao Takaku
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2010-04-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdf-turtle
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ruby-progressbar
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: capybara
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Static site generator for RDF/Turtle
98
+ email: tmasao@acm.org
99
+ executables:
100
+ - ttl2html
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - bin/ttl2html
105
+ - lib/ttl2html.rb
106
+ - lib/ttl2html/template.rb
107
+ - lib/ttl2html/version.rb
108
+ - templates/default.html.erb
109
+ - templates/layout.html.erb
110
+ - templates/triples.html.erb
111
+ homepage: https://github.org/masao/ttl2html
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.6.13
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: ttl2html
135
+ test_files: []