ttl2html 0.0.1

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.
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: []