relaton-bib 0.4.1 → 0.5.0
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 +4 -4
- data/.gitignore +2 -1
- data/Gemfile.lock +24 -19
- data/README.adoc +185 -136
- data/bin/rspec +29 -0
- data/docs/hash.adoc +130 -20
- data/lib/relaton_bib/bibliographic_item.rb +176 -9
- data/lib/relaton_bib/bibtex_parser.rb +236 -0
- data/lib/relaton_bib/contribution_info.rb +1 -1
- data/lib/relaton_bib/hash_converter.rb +12 -6
- data/lib/relaton_bib/place.rb +37 -0
- data/lib/relaton_bib/series.rb +2 -2
- data/lib/relaton_bib/typed_title_string.rb +1 -1
- data/lib/relaton_bib/version.rb +1 -1
- data/lib/relaton_bib/xml_parser.rb +10 -5
- data/relaton-bib.gemspec +2 -1
- metadata +33 -16
@@ -0,0 +1,236 @@
|
|
1
|
+
require "bibtex"
|
2
|
+
require "iso639"
|
3
|
+
|
4
|
+
module RelatonBib
|
5
|
+
class BibtexParser
|
6
|
+
class << self
|
7
|
+
# @param bibtex [String]
|
8
|
+
# @return [Hash{String=>RelatonBib::BibliographicItem}]
|
9
|
+
def from_bibtex(bibtex)
|
10
|
+
BibTeX.parse(bibtex).reduce({}) do |h, bt|
|
11
|
+
h[bt.key] = BibliographicItem.new(
|
12
|
+
id: bt.key,
|
13
|
+
docid: fetch_docid(bt),
|
14
|
+
fetched: fetch_fetched(bt),
|
15
|
+
type: fetch_type(bt),
|
16
|
+
title: fetch_title(bt),
|
17
|
+
contributor: fetch_contributor(bt),
|
18
|
+
date: fetch_date(bt),
|
19
|
+
place: fetch_place(bt),
|
20
|
+
biblionote: fetch_note(bt),
|
21
|
+
relation: fetch_relation(bt),
|
22
|
+
extent: fetch_extent(bt),
|
23
|
+
edition: bt["edition"]&.to_s,
|
24
|
+
series: fetch_series(bt),
|
25
|
+
link: fetch_link(bt),
|
26
|
+
language: fetch_language(bt),
|
27
|
+
classification: fetch_classification(bt)
|
28
|
+
)
|
29
|
+
h
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# @param bibtex [BibTeX::Entry]
|
36
|
+
# @return [Array<RelatonBib::DocumentIdentifier>]
|
37
|
+
def fetch_docid(bibtex)
|
38
|
+
docid = []
|
39
|
+
docid << DocumentIdentifier.new(id: bibtex.isbn.to_s, type: "isbn") if bibtex["isbn"]
|
40
|
+
docid << DocumentIdentifier.new(id: bibtex.lccn.to_s, type: "lccn") if bibtex["lccn"]
|
41
|
+
docid << DocumentIdentifier.new(id: bibtex.issn.to_s, type: "issn") if bibtex["issn"]
|
42
|
+
docid
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param bibtex [BibTeX::Entry]
|
46
|
+
# @return [String, NilClass]
|
47
|
+
def fetch_fetched(bibtex)
|
48
|
+
Date.parse(bibtex.timestamp.to_s) if bibtex["timestamp"]
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param bibtex [BibTeX::Entry]
|
52
|
+
# @return [String]
|
53
|
+
def fetch_type(bibtex)
|
54
|
+
case bibtex.type
|
55
|
+
when :mastersthesis, :phdthesis then "thesis"
|
56
|
+
when :conference then "inproceedings"
|
57
|
+
when :misc then "standard"
|
58
|
+
else bibtex.type.to_s
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param bibtex [BibTeX::Entry]
|
63
|
+
# @return [Array<Hash>]
|
64
|
+
def fetch_place(bibtex)
|
65
|
+
bibtex["address"] ? [bibtex.address.to_s] : []
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param bibtex [BibTeX::Entry]
|
69
|
+
# @return [Array<Hash>]
|
70
|
+
def fetch_title(bibtex)
|
71
|
+
title = []
|
72
|
+
title << { type: "main", content: bibtex.title.to_s } if bibtex["title"]
|
73
|
+
title << { type: "main", content: bibtex.subtitle.to_s } if bibtex["subtitle"]
|
74
|
+
title
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param bibtex [BibTeX::Entry]
|
78
|
+
# @return [Array<Hash>]
|
79
|
+
def fetch_contributor(bibtex)
|
80
|
+
contributor = []
|
81
|
+
fetch_person(bibtex["author"]).each do |entity|
|
82
|
+
contributor << { entity: entity, role: [{ type: "author" }] }
|
83
|
+
end
|
84
|
+
|
85
|
+
fetch_person(bibtex["editor"]).each do |entity|
|
86
|
+
contributor << { entity: entity, role: [{ type: "editor" }] }
|
87
|
+
end
|
88
|
+
|
89
|
+
if bibtex["publisher"]
|
90
|
+
contributor << { entity: { name: bibtex.publisher.to_s }, role: [{ type: "publisher" }] }
|
91
|
+
end
|
92
|
+
|
93
|
+
if bibtex["institution"]
|
94
|
+
contributor << {
|
95
|
+
entity: { name: bibtex.institution.to_s },
|
96
|
+
role: [{ type: "distributor", description: ["sponsor"] }]
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
if bibtex["organization"]
|
101
|
+
contributor << {
|
102
|
+
entity: { name: bibtex.organization.to_s },
|
103
|
+
role: [{ type: "distributor", description: ["sponsor"] }]
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
if bibtex["school"]
|
108
|
+
contributor << {
|
109
|
+
entity: { name: bibtex.school.to_s },
|
110
|
+
role: [{ type: "distributor", description: ["sponsor"] }]
|
111
|
+
}
|
112
|
+
end
|
113
|
+
contributor
|
114
|
+
end
|
115
|
+
|
116
|
+
# @param bibtex [BibTeX::Entry]
|
117
|
+
# @return [Array<RelatonBib::Person>]
|
118
|
+
def fetch_person(person)
|
119
|
+
return [] unless person
|
120
|
+
|
121
|
+
person.map do |name|
|
122
|
+
parts = name.split ", "
|
123
|
+
surname = LocalizedString.new parts.first
|
124
|
+
fname = parts.size > 1 ? parts[1].split : []
|
125
|
+
forename = fname.map { |fn| LocalizedString.new fn }
|
126
|
+
Person.new name: FullName.new(surname: surname, forename: forename)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# @param bibtex [BibTeX::Entry]
|
131
|
+
# @return [Array<Hash>]
|
132
|
+
def fetch_date(bibtex)
|
133
|
+
date = []
|
134
|
+
if bibtex["year"]
|
135
|
+
on = Date.new(bibtex.year.to_i, bibtex["month_numeric"]&.to_i || 1).to_s
|
136
|
+
date << { type: "published", on: on }
|
137
|
+
end
|
138
|
+
|
139
|
+
if bibtex["urldate"]
|
140
|
+
date << { type: "accessed", on: Date.parse(bibtex.urldate.to_s).to_s }
|
141
|
+
end
|
142
|
+
|
143
|
+
date
|
144
|
+
end
|
145
|
+
|
146
|
+
# @param bibtex [BibTeX::Entry]
|
147
|
+
# @return [Array<RelatonBib::BiblioNote>]
|
148
|
+
def fetch_note(bibtex)
|
149
|
+
note = []
|
150
|
+
note << BiblioNote.new(type: "annote", content: bibtex.annote.to_s) if bibtex["annote"]
|
151
|
+
|
152
|
+
if bibtex["howpublished"]
|
153
|
+
note << BiblioNote.new(type: "howpublished", content: bibtex.howpublished.to_s)
|
154
|
+
end
|
155
|
+
|
156
|
+
note << BiblioNote.new(type: "comment", content: bibtex.comment.to_s) if bibtex["comment"]
|
157
|
+
note << BiblioNote.new(content: bibtex.note.to_s) if bibtex["note"]
|
158
|
+
note << BiblioNote.new(type: "tableOfContents", content: bibtex["content"]) if bibtex["content"]
|
159
|
+
note
|
160
|
+
end
|
161
|
+
|
162
|
+
# @param bibtex [BibTeX::Entry]
|
163
|
+
# @return [Array<Hash>]
|
164
|
+
def fetch_relation(bibtex)
|
165
|
+
return [] unless bibtex["booktitle"]
|
166
|
+
|
167
|
+
title = TypedTitleString.new(type: "main", content: bibtex.booktitle.to_s)
|
168
|
+
[{ type: "partOf", bibitem: BibliographicItem.new(title: [title]) }]
|
169
|
+
end
|
170
|
+
|
171
|
+
# @param bibtex [BibTeX::Entry]
|
172
|
+
# @return [Array<RelatonBib::BibItemLocality>]
|
173
|
+
def fetch_extent(bibtex)
|
174
|
+
extent = []
|
175
|
+
extent << BibItemLocality.new("chapter", bibtex.chapter.to_s) if bibtex["chapter"]
|
176
|
+
|
177
|
+
if bibtex["pages"]
|
178
|
+
from, to = bibtex.pages.to_s.split "-"
|
179
|
+
extent << BibItemLocality.new("page", from, to)
|
180
|
+
end
|
181
|
+
|
182
|
+
extent << BibItemLocality.new("volume", bibtex.volume.to_s) if bibtex["volume"]
|
183
|
+
extent
|
184
|
+
end
|
185
|
+
|
186
|
+
# @param bibtex [BibTeX::Entry]
|
187
|
+
# @return [Array<RelatonBib::Series>]
|
188
|
+
def fetch_series(bibtex)
|
189
|
+
series = []
|
190
|
+
if bibtex["journal"]
|
191
|
+
series << Series.new(
|
192
|
+
type: "journal",
|
193
|
+
title: TypedTitleString.new(content: bibtex.journal.to_s),
|
194
|
+
number: bibtex["number"]&.to_s
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
198
|
+
if bibtex["series"]
|
199
|
+
title = TypedTitleString.new content: bibtex.series.to_s
|
200
|
+
series << Series.new(title: title)
|
201
|
+
end
|
202
|
+
series
|
203
|
+
end
|
204
|
+
|
205
|
+
# @param bibtex [BibTeX::Entry]
|
206
|
+
# @return [Array<RelatonBib::TypedUri>]
|
207
|
+
def fetch_link(bibtex)
|
208
|
+
link = []
|
209
|
+
link << TypedUri.new(type: "src", content: bibtex.url.to_s) if bibtex["url"]
|
210
|
+
link << TypedUri.new(type: "doi", content: bibtex.doi.to_s) if bibtex["doi"]
|
211
|
+
link << TypedUri.new(type: "file", content: bibtex.file2.to_s) if bibtex["file2"]
|
212
|
+
link
|
213
|
+
end
|
214
|
+
|
215
|
+
# @param bibtex [BibTeX::Entry]
|
216
|
+
# @return [Array<String>]
|
217
|
+
def fetch_language(bibtex)
|
218
|
+
return [] unless bibtex["language"]
|
219
|
+
|
220
|
+
[Iso639[bibtex.language.to_s].alpha2]
|
221
|
+
end
|
222
|
+
|
223
|
+
# @param bibtex [BibTeX::Entry]
|
224
|
+
# @return [RelatonBib::Classification, NilClass]
|
225
|
+
def fetch_classification(bibtex)
|
226
|
+
cls = []
|
227
|
+
cls << Classification.new(type: "type", value: bibtex["type"].to_s) if bibtex["type"]
|
228
|
+
cls << Classification.new(type: "keyword", value: bibtex.keywords.to_s) if bibtex["keywords"]
|
229
|
+
if bibtex["mendeley-tags"]
|
230
|
+
cls << Classification.new(type: "mendeley", value: bibtex["mendeley-tags"].to_s)
|
231
|
+
end
|
232
|
+
cls
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -22,7 +22,7 @@ module RelatonBib
|
|
22
22
|
# @param description [Array<String>]
|
23
23
|
def initialize(**args)
|
24
24
|
if args[:type] && !TYPES.include?(args[:type])
|
25
|
-
|
25
|
+
warn %{[relaton-bib] Contributor's type "#{args[:type]}" is invalid.}
|
26
26
|
end
|
27
27
|
|
28
28
|
@type = args[:type]
|
@@ -84,7 +84,9 @@ module RelatonBib
|
|
84
84
|
def place_hash_to_bib(ret)
|
85
85
|
return unless ret[:place]
|
86
86
|
|
87
|
-
ret[:place] = array(ret[:place])
|
87
|
+
ret[:place] = array(ret[:place]).map do |pl|
|
88
|
+
pl.is_a?(String) ? Place.new(name: pl) : Place.new(pl)
|
89
|
+
end
|
88
90
|
end
|
89
91
|
|
90
92
|
def accesslocation_hash_to_bib(ret)
|
@@ -130,10 +132,14 @@ module RelatonBib
|
|
130
132
|
|
131
133
|
ret[:biblionote] = array(ret[:biblionote])
|
132
134
|
(ret[:biblionote])&.each_with_index do |n, i|
|
133
|
-
ret[:biblionote][i] =
|
134
|
-
|
135
|
-
|
136
|
-
|
135
|
+
ret[:biblionote][i] = if n.is_a?(String)
|
136
|
+
BiblioNote.new content: n
|
137
|
+
else
|
138
|
+
BiblioNote.new(
|
139
|
+
content: n[:content], type: n[:type], language: n[:language],
|
140
|
+
script: n[:script], format: n[:format]
|
141
|
+
)
|
142
|
+
end
|
137
143
|
end
|
138
144
|
end
|
139
145
|
|
@@ -308,7 +314,7 @@ module RelatonBib
|
|
308
314
|
# ret[:classification][i] = RelatonBib::Classification.new(c)
|
309
315
|
# end
|
310
316
|
if ret[:classification]
|
311
|
-
ret[:classification] =
|
317
|
+
ret[:classification] = array(ret[:classification]).map { |cls| Classification.new cls }
|
312
318
|
end
|
313
319
|
end
|
314
320
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RelatonBib
|
2
|
+
class Place
|
3
|
+
# @return [String]
|
4
|
+
attr_reader :name
|
5
|
+
|
6
|
+
# @return [String, NilClass]
|
7
|
+
attr_reader :uri, :region
|
8
|
+
|
9
|
+
# @param name [String]
|
10
|
+
# @param uri [String, NilClass]
|
11
|
+
# @param region [String, NilClass]
|
12
|
+
def initialize(name:, uri: nil, region: nil)
|
13
|
+
@name = name
|
14
|
+
@uri = uri
|
15
|
+
@region = region
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param builder [Nologiri::XML::Builder]
|
19
|
+
def to_xml(builder)
|
20
|
+
xml = builder.place name
|
21
|
+
xml[:uri] = uri if uri
|
22
|
+
xml[:region] = region if region
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Hash]
|
26
|
+
def to_hash
|
27
|
+
if uri || region
|
28
|
+
hash = { name: name }
|
29
|
+
hash["uri"] = uri if uri
|
30
|
+
hash["region"] = region if region
|
31
|
+
hash
|
32
|
+
else
|
33
|
+
name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/relaton_bib/series.rb
CHANGED
@@ -55,7 +55,7 @@ module RelatonBib
|
|
55
55
|
end
|
56
56
|
|
57
57
|
if args[:type] && !TYPES.include?(args[:type])
|
58
|
-
|
58
|
+
warn "[relaton-bib] Series type is invalid: #{args[:type]}"
|
59
59
|
end
|
60
60
|
|
61
61
|
@type = args[:type] # if %w[main alt].include? args[:type]
|
@@ -67,7 +67,7 @@ module RelatonBib
|
|
67
67
|
@from = args[:from]
|
68
68
|
@to = args[:to]
|
69
69
|
@number = args[:number]
|
70
|
-
@partnumber
|
70
|
+
@partnumber = args[:partnumber]
|
71
71
|
end
|
72
72
|
# rubocop:enable Metrics/MethodLength
|
73
73
|
|
@@ -17,7 +17,7 @@ module RelatonBib
|
|
17
17
|
# @param script [String]
|
18
18
|
def initialize(**args)
|
19
19
|
if args[:type] && !TITLE_TYPES.include?(args[:type])
|
20
|
-
|
20
|
+
warn %{[relaton-bib] title type "#{args[:type]}" is invalid.}
|
21
21
|
end
|
22
22
|
|
23
23
|
unless args[:title] || args[:content]
|
data/lib/relaton_bib/version.rb
CHANGED
@@ -38,7 +38,7 @@ module RelatonBib
|
|
38
38
|
relation: fetch_relations(bibitem),
|
39
39
|
series: fetch_series(bibitem),
|
40
40
|
medium: fetch_medium(bibitem),
|
41
|
-
place: bibitem
|
41
|
+
place: fetch_place(bibitem),
|
42
42
|
extent: fetch_extent(bibitem),
|
43
43
|
accesslocation: bibitem.xpath("./accesslocation").map(&:text),
|
44
44
|
classification: fetch_classification(bibitem),
|
@@ -56,6 +56,12 @@ module RelatonBib
|
|
56
56
|
RelatonBib::BibliographicItem::Version.new revision_date, draft
|
57
57
|
end
|
58
58
|
|
59
|
+
def fetch_place(item)
|
60
|
+
item.xpath("./place").map do |pl|
|
61
|
+
Place.new(name: pl.text, uri: pl[:uri], region: pl[:region])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
59
65
|
def fetch_note(item)
|
60
66
|
item.xpath("./note").map do |n|
|
61
67
|
BiblioNote.new(
|
@@ -113,10 +119,9 @@ module RelatonBib
|
|
113
119
|
end
|
114
120
|
|
115
121
|
def fetch_classification(item)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
Classification.new type: cls[:type], value: cls.text
|
122
|
+
item.xpath("classification").map do |cls|
|
123
|
+
Classification.new type: cls[:type], value: cls.text
|
124
|
+
end
|
120
125
|
end
|
121
126
|
|
122
127
|
def fetch_validity(item)
|
data/relaton-bib.gemspec
CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
|
25
25
|
|
26
|
-
spec.add_development_dependency "bundler", "~> 2.0"
|
27
26
|
spec.add_development_dependency "debase"
|
28
27
|
spec.add_development_dependency "equivalent-xml", "~> 0.6"
|
29
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
@@ -34,5 +33,7 @@ Gem::Specification.new do |spec|
|
|
34
33
|
spec.add_development_dependency "byebug"
|
35
34
|
|
36
35
|
spec.add_dependency "addressable"
|
36
|
+
spec.add_dependency "bibtex-ruby"
|
37
|
+
spec.add_dependency "iso639"
|
37
38
|
spec.add_dependency "nokogiri"
|
38
39
|
end
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relaton-bib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '2.0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '2.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: debase
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +136,34 @@ dependencies:
|
|
150
136
|
- - ">="
|
151
137
|
- !ruby/object:Gem::Version
|
152
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: bibtex-ruby
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: iso639
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: nokogiri
|
155
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,6 +198,7 @@ files:
|
|
184
198
|
- README.adoc
|
185
199
|
- Rakefile
|
186
200
|
- bin/console
|
201
|
+
- bin/rspec
|
187
202
|
- bin/setup
|
188
203
|
- docs/hash.adoc
|
189
204
|
- lib/relaton_bib.rb
|
@@ -192,6 +207,7 @@ files:
|
|
192
207
|
- lib/relaton_bib/biblio_version.rb
|
193
208
|
- lib/relaton_bib/bibliographic_date.rb
|
194
209
|
- lib/relaton_bib/bibliographic_item.rb
|
210
|
+
- lib/relaton_bib/bibtex_parser.rb
|
195
211
|
- lib/relaton_bib/classification.rb
|
196
212
|
- lib/relaton_bib/contribution_info.rb
|
197
213
|
- lib/relaton_bib/contributor.rb
|
@@ -210,6 +226,7 @@ files:
|
|
210
226
|
- lib/relaton_bib/medium.rb
|
211
227
|
- lib/relaton_bib/organization.rb
|
212
228
|
- lib/relaton_bib/person.rb
|
229
|
+
- lib/relaton_bib/place.rb
|
213
230
|
- lib/relaton_bib/series.rb
|
214
231
|
- lib/relaton_bib/typed_title_string.rb
|
215
232
|
- lib/relaton_bib/typed_uri.rb
|