relaton-render 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.adoc +5 -0
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
- data/lib/relaton/render/general/render.rb +32 -20
- data/lib/relaton/render/parse/parse.rb +7 -0
- data/lib/relaton/render/parse/parse_contributors.rb +13 -11
- data/lib/relaton/render/parse/parse_extract.rb +13 -89
- data/lib/relaton/render/parse/parse_id.rb +119 -0
- data/lib/relaton/render/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a61037d7e9fc1193d54cb03fd7155a09431a30710990c50366112558b86d8210
|
4
|
+
data.tar.gz: 7fe54372399bb332f686af101b9f6e36140497e89073cdf02f5e2bb0afec3183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f39ff4adacad120c2b2661d89ff59593b7fb41b4cbee209171ebbb92bf188bb52f36f0e8a8f7c62323cfb834bd2d296a7ce2b94bc8217e86838927c189c2794
|
7
|
+
data.tar.gz: 655a9918e4559a77dbcb94bcef62037b1e13ae81aea2472e1d8fd62941ff312abdf2394b9a7dec3528faf083e0079b3111d4aec21e4e935a688807a3b348cedd
|
data/README.adoc
CHANGED
@@ -90,6 +90,11 @@ if called with `type: "author-date"`.
|
|
90
90
|
The author and date are differentiated so that consumers can separate them in citations -- e.g. "Jones (1996) claims",
|
91
91
|
"(Jones 1996, 1997)".
|
92
92
|
|
93
|
+
=== Parsing single reference
|
94
|
+
|
95
|
+
Given an Relaton bibitem object (or equivalent Relaton XML), `parse(input)` will output the hash of fields that is passed into the
|
96
|
+
Liquid templates described below for rendering: it is the hash of bibliographic fields extracted by the gem.
|
97
|
+
|
93
98
|
== Configuration
|
94
99
|
|
95
100
|
=== Templates
|
@@ -108,22 +108,23 @@ module Relaton
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def render(bib, embedded: false)
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
111
|
+
bib = xml2relaton(bib)
|
112
|
+
f = bib.formattedref and
|
113
|
+
return embedded ? f.content : fmtref(f.content)
|
114
|
+
ret = render1(bib) or return nil
|
115
|
+
embedded and return ret
|
116
|
+
fmtref(ret)
|
115
117
|
end
|
116
118
|
|
117
|
-
def
|
118
|
-
|
119
|
+
def xml2relaton(bib)
|
120
|
+
bib.is_a?(Nokogiri::XML::Element) and
|
121
|
+
bib = bib.to_xml
|
122
|
+
bib.is_a?(String) && Nokogiri::XML(bib).errors.empty? and
|
123
|
+
bib = RelatonBib::XMLParser.from_xml(bib) or bib
|
119
124
|
end
|
120
125
|
|
121
|
-
def
|
122
|
-
|
123
|
-
return embedded ? f.content : fmtref(f.content)
|
124
|
-
ret = parse1(doc) or return nil
|
125
|
-
embedded and return ret
|
126
|
-
fmtref(ret)
|
126
|
+
def fmtref(doc)
|
127
|
+
"<formattedref>#{doc}</formattedref>"
|
127
128
|
end
|
128
129
|
|
129
130
|
def renderer(type)
|
@@ -135,20 +136,30 @@ module Relaton
|
|
135
136
|
ret
|
136
137
|
end
|
137
138
|
|
138
|
-
def
|
139
|
+
def render1(doc)
|
139
140
|
r = doc.relation.select { |x| x.type == "hasRepresentation" }
|
140
|
-
.map { |x| @i18n.also_pub_as +
|
141
|
-
out = [
|
141
|
+
.map { |x| @i18n.also_pub_as + render_single_bibitem(x.bibitem) }
|
142
|
+
out = [render_single_bibitem(doc)] + r
|
142
143
|
@i18n.l10n(out.join(". ").gsub(".. ", ". "))
|
143
144
|
end
|
144
145
|
|
145
|
-
def
|
146
|
+
def render_single_bibitem(doc)
|
147
|
+
data_liquid, r = parse(doc)
|
148
|
+
liquid(data_liquid, r)
|
149
|
+
end
|
150
|
+
|
151
|
+
def liquid(data_liquid, renderer)
|
152
|
+
valid_parse(@i18n.l10n(renderer.render(data_liquid)))
|
153
|
+
end
|
154
|
+
|
155
|
+
def parse(doc)
|
156
|
+
doc = xml2relaton(doc)
|
146
157
|
r = renderer(doc.type || "misc")
|
147
158
|
data = @parse.extract(doc)
|
148
159
|
enhance_data(data, r.template_raw)
|
149
160
|
data_liquid = @fieldsklass.new(renderer: self)
|
150
161
|
.compound_fields_format(data)
|
151
|
-
|
162
|
+
[data_liquid, r]
|
152
163
|
end
|
153
164
|
|
154
165
|
def valid_parse(ret)
|
@@ -214,15 +225,16 @@ module Relaton
|
|
214
225
|
end
|
215
226
|
|
216
227
|
def url_exist?(url_string)
|
217
|
-
|
228
|
+
url = URI.parse(url_string)
|
229
|
+
url.host or return true # allow file URLs
|
230
|
+
res = access_url(url)
|
218
231
|
res.is_a?(Net::HTTPRedirection) and return url_exist?(res["location"])
|
219
232
|
res.code[0] != "4"
|
220
233
|
rescue Errno::ENOENT, SocketError
|
221
234
|
false # false if can't find the server
|
222
235
|
end
|
223
236
|
|
224
|
-
def access_url(
|
225
|
-
url = URI.parse(url_string)
|
237
|
+
def access_url(url)
|
226
238
|
req = Net::HTTP.new(url.host, url.port)
|
227
239
|
req.use_ssl = (url.scheme == "https")
|
228
240
|
path = url.path or return false
|
@@ -2,6 +2,7 @@ require "nokogiri"
|
|
2
2
|
require "twitter_cldr"
|
3
3
|
require_relative "parse_contributors"
|
4
4
|
require_relative "parse_extract"
|
5
|
+
require_relative "parse_id"
|
5
6
|
|
6
7
|
module Relaton
|
7
8
|
module Render
|
@@ -65,6 +66,12 @@ module Relaton
|
|
65
66
|
series_org: series_org(series, doc),
|
66
67
|
series_dates: series_dates(series, doc) }
|
67
68
|
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def blank?(text)
|
73
|
+
text.nil? || text.empty?
|
74
|
+
end
|
68
75
|
end
|
69
76
|
end
|
70
77
|
end
|
@@ -61,8 +61,7 @@ module Relaton
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def contributor_role(contributors)
|
64
|
-
|
65
|
-
|
64
|
+
contributors.length.positive? or return nil
|
66
65
|
desc = contributors[0].role.first.description.join("\n")
|
67
66
|
type = contributors[0].role.first.type
|
68
67
|
desc.empty? ? type : desc
|
@@ -80,12 +79,10 @@ module Relaton
|
|
80
79
|
|
81
80
|
def creatornames1(doc)
|
82
81
|
cr = []
|
83
|
-
return []
|
84
|
-
|
82
|
+
doc.nil? and return []
|
85
83
|
creatornames_roles_allowed.each do |r|
|
86
84
|
add = pick_contributor(doc, r)
|
87
|
-
|
88
|
-
|
85
|
+
add.nil? and next
|
89
86
|
cr = add and break
|
90
87
|
end
|
91
88
|
cr.nil? and cr = doc.contributor
|
@@ -93,14 +90,12 @@ module Relaton
|
|
93
90
|
end
|
94
91
|
|
95
92
|
def datepick(date)
|
96
|
-
|
97
|
-
|
93
|
+
date.nil? and return nil
|
98
94
|
on = date.on
|
99
95
|
from = date.from
|
100
96
|
to = date.to
|
101
|
-
return { on: on }
|
102
|
-
return { from: from, to: to }
|
103
|
-
|
97
|
+
on and return { on: on }
|
98
|
+
from and return { from: from, to: to }
|
104
99
|
nil
|
105
100
|
end
|
106
101
|
|
@@ -165,6 +160,13 @@ module Relaton
|
|
165
160
|
x.nil? and return nil
|
166
161
|
x.map { |c| extractname(c) }
|
167
162
|
end
|
163
|
+
|
164
|
+
def pick_contributor(doc, role)
|
165
|
+
ret = doc.contributor.select do |c|
|
166
|
+
c.role.any? { |r| r.type == role }
|
167
|
+
end
|
168
|
+
ret.empty? ? nil : ret
|
169
|
+
end
|
168
170
|
end
|
169
171
|
end
|
170
172
|
end
|
@@ -17,7 +17,6 @@ module Relaton
|
|
17
17
|
|
18
18
|
def medium(doc, host)
|
19
19
|
x = doc.medium || host&.medium or return nil
|
20
|
-
|
21
20
|
%w(content genre form carrier size scale).each_with_object({}) do |i, m|
|
22
21
|
m[i] = x.send i
|
23
22
|
end.compact
|
@@ -47,10 +46,11 @@ module Relaton
|
|
47
46
|
end
|
48
47
|
|
49
48
|
def place1(place)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
c = place.city
|
50
|
+
r = place.region
|
51
|
+
n = place.country
|
52
|
+
c.nil? && r.empty? && n.empty? and return place.name
|
53
|
+
ret = [c] + r.map(&:name) + n.map(&:name)
|
54
54
|
@i18n.l10n(ret.compact.join(", "))
|
55
55
|
end
|
56
56
|
|
@@ -105,68 +105,6 @@ module Relaton
|
|
105
105
|
"#{f}–#{t}"
|
106
106
|
end
|
107
107
|
|
108
|
-
def authoritative_identifier(doc)
|
109
|
-
out = doc.docidentifier.each_with_object([]) do |id, ret|
|
110
|
-
id.primary && !authoritative_identifier_exclude.include?(id.type) and
|
111
|
-
ret << id.id
|
112
|
-
end
|
113
|
-
out.empty? and out = doc.docidentifier.each_with_object([]) do |id, ret|
|
114
|
-
authoritative_identifier_exclude.include?(id_type_norm(id)) or
|
115
|
-
ret << id.id
|
116
|
-
end
|
117
|
-
out
|
118
|
-
end
|
119
|
-
|
120
|
-
def authoritative_identifier_exclude
|
121
|
-
%w(metanorma metanorma-ordinal) + other_identifier_include
|
122
|
-
end
|
123
|
-
|
124
|
-
def other_identifier(doc)
|
125
|
-
doc.docidentifier.each_with_object([]) do |id, ret|
|
126
|
-
type = id_type_norm(id)
|
127
|
-
other_identifier_include.include? type or next
|
128
|
-
ret << @i18n.l10n("#{type}: #{id.id}")
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
def other_identifier_include
|
133
|
-
%w(ISSN ISBN DOI)
|
134
|
-
end
|
135
|
-
|
136
|
-
def doi(doc)
|
137
|
-
out = doc.docidentifier.each_with_object([]) do |id, ret|
|
138
|
-
type = id.type&.sub(/^(DOI)\..*$/i, "\\1") or next
|
139
|
-
type.casecmp("doi").zero? or next
|
140
|
-
ret << id.id
|
141
|
-
end
|
142
|
-
out.empty? ? nil : out
|
143
|
-
end
|
144
|
-
|
145
|
-
def id_type_norm(id)
|
146
|
-
id.type&.sub(/^(ISBN|ISSN)\..*$/i) { $1.upcase }
|
147
|
-
end
|
148
|
-
|
149
|
-
def uri(doc)
|
150
|
-
uri = nil
|
151
|
-
%w(citation uri src).each do |t|
|
152
|
-
uri = uri_type_select(doc, t) and break
|
153
|
-
end
|
154
|
-
uri ||= doc.link.detect do |u|
|
155
|
-
u.language == @lang && !u.type&.casecmp("doi")&.zero?
|
156
|
-
end
|
157
|
-
uri ||= doc.link.detect { |u| !u.type&.casecmp("doi")&.zero? }
|
158
|
-
uri or return nil
|
159
|
-
uri.content.to_s.strip
|
160
|
-
end
|
161
|
-
|
162
|
-
def uri_type_select(doc, type)
|
163
|
-
uri = doc.link.detect do |u|
|
164
|
-
u.type&.downcase == type && u.language == @lang
|
165
|
-
end and return uri
|
166
|
-
uri = doc.link.detect { |u| u.type&.downcase == type } and return uri
|
167
|
-
nil
|
168
|
-
end
|
169
|
-
|
170
108
|
def access_location(doc, host)
|
171
109
|
x = doc.accesslocation || host&.accesslocation or
|
172
110
|
return nil
|
@@ -192,6 +130,13 @@ module Relaton
|
|
192
130
|
end
|
193
131
|
end
|
194
132
|
|
133
|
+
def localized_string_or_text(str)
|
134
|
+
case str
|
135
|
+
when RelatonBib::LocalizedString then content(str)
|
136
|
+
when String then str
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
195
140
|
def extent(doc)
|
196
141
|
doc.extent.each_with_object([]) do |e, acc|
|
197
142
|
case e
|
@@ -209,34 +154,13 @@ module Relaton
|
|
209
154
|
end
|
210
155
|
|
211
156
|
def iter_ordinal(doc)
|
212
|
-
|
213
|
-
|
157
|
+
iter = doc&.status&.iteration or return nil
|
214
158
|
iter
|
215
159
|
end
|
216
160
|
|
217
161
|
def status(doc)
|
218
162
|
doc&.status&.stage&.value
|
219
163
|
end
|
220
|
-
|
221
|
-
private
|
222
|
-
|
223
|
-
def blank?(text)
|
224
|
-
text.nil? || text.empty?
|
225
|
-
end
|
226
|
-
|
227
|
-
def pick_contributor(doc, role)
|
228
|
-
ret = doc.contributor.select do |c|
|
229
|
-
c.role.any? { |r| r.type == role }
|
230
|
-
end
|
231
|
-
ret.empty? ? nil : ret
|
232
|
-
end
|
233
|
-
|
234
|
-
def localized_string_or_text(str)
|
235
|
-
case str
|
236
|
-
when RelatonBib::LocalizedString then content(str)
|
237
|
-
when String then str
|
238
|
-
end
|
239
|
-
end
|
240
164
|
end
|
241
165
|
end
|
242
166
|
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Relaton
|
2
|
+
module Render
|
3
|
+
class Parse
|
4
|
+
# filter applied across full list of auth_id
|
5
|
+
def auth_id_filter(ids)
|
6
|
+
id_scope_filter(ids)
|
7
|
+
end
|
8
|
+
|
9
|
+
def id_scope_filter(ids)
|
10
|
+
ids.detect(&:scope) or return ids
|
11
|
+
id_sort_by_scope(ids).each_with_object([]) do |(k, v), m|
|
12
|
+
case k
|
13
|
+
when "IEEE"
|
14
|
+
m << id_extract_by_scope(v, "trademark")
|
15
|
+
else
|
16
|
+
m << id_extract_by_scope(v, nil)
|
17
|
+
end
|
18
|
+
end.flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
def id_sort_by_scope(ids)
|
22
|
+
ids.each_with_object({}) do |i, m|
|
23
|
+
m[i.type] ||= {}
|
24
|
+
m[i.type][i.scope] ||= []
|
25
|
+
m[i.type][i.scope] << i
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def id_extract_by_scope(idents, key)
|
30
|
+
if idents.key?(key) && idents.keys.size > 1
|
31
|
+
idents[key]
|
32
|
+
else
|
33
|
+
idents.each_with_object([]) { |(_, v), m| m << v }.flatten
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# list of successive filters on individual auth_id instances
|
38
|
+
def auth_id_allow
|
39
|
+
[->(x) { x.language == @lang && x.primary },
|
40
|
+
->(x) { x.primary },
|
41
|
+
->(x) { x.language == @lang },
|
42
|
+
->(_x) { true }]
|
43
|
+
end
|
44
|
+
|
45
|
+
def authoritative_identifier(doc)
|
46
|
+
out = []
|
47
|
+
[auth_id_filter(doc.docidentifier), doc.docidentifier].each do |a|
|
48
|
+
out = authoritative_identifier_select(a)
|
49
|
+
out.empty? or break
|
50
|
+
end
|
51
|
+
out.map(&:id)
|
52
|
+
end
|
53
|
+
|
54
|
+
def authoritative_identifier_select(idents)
|
55
|
+
out = []
|
56
|
+
auth_id_allow.each do |p|
|
57
|
+
out = idents.select do |x|
|
58
|
+
p.call(x) &&
|
59
|
+
!authoritative_identifier_exclude.include?(id_type_norm(x))
|
60
|
+
end
|
61
|
+
out.empty? or break
|
62
|
+
end
|
63
|
+
out
|
64
|
+
end
|
65
|
+
|
66
|
+
def authoritative_identifier_exclude
|
67
|
+
%w(METANORMA METANORMA-ORDINAL) + other_identifier_include
|
68
|
+
end
|
69
|
+
|
70
|
+
def other_identifier(doc)
|
71
|
+
doc.docidentifier.each_with_object([]) do |id, ret|
|
72
|
+
type = id_type_norm(id)
|
73
|
+
other_identifier_include.include? type or next
|
74
|
+
ret << @i18n.l10n("#{type}: #{id.id}")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def other_identifier_include
|
79
|
+
%w(ISSN ISBN DOI)
|
80
|
+
end
|
81
|
+
|
82
|
+
def doi(doc)
|
83
|
+
out = doc.docidentifier.each_with_object([]) do |id, ret|
|
84
|
+
type = id.type&.sub(/^(DOI)\..*$/i, "\\1") or next
|
85
|
+
type.casecmp("doi").zero? or next
|
86
|
+
ret << id.id
|
87
|
+
end
|
88
|
+
out.empty? ? nil : out
|
89
|
+
end
|
90
|
+
|
91
|
+
def id_type_norm(id)
|
92
|
+
id.type or return nil
|
93
|
+
m = /^(ISBN|ISSN)\./i.match(id.type) or return id.type.upcase
|
94
|
+
m[1].upcase
|
95
|
+
end
|
96
|
+
|
97
|
+
def uri(doc)
|
98
|
+
uri = nil
|
99
|
+
%w(citation uri src).each do |t|
|
100
|
+
uri = uri_type_select(doc, t) and break
|
101
|
+
end
|
102
|
+
uri ||= doc.link.detect do |u|
|
103
|
+
u.language == @lang && !u.type&.casecmp("doi")&.zero?
|
104
|
+
end
|
105
|
+
uri ||= doc.link.detect { |u| !u.type&.casecmp("doi")&.zero? }
|
106
|
+
uri or return nil
|
107
|
+
uri.content.to_s.strip
|
108
|
+
end
|
109
|
+
|
110
|
+
def uri_type_select(doc, type)
|
111
|
+
uri = doc.link.detect do |u|
|
112
|
+
u.type&.downcase == type && u.language == @lang
|
113
|
+
end and return uri
|
114
|
+
uri = doc.link.detect { |u| u.type&.downcase == type } and return uri
|
115
|
+
nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relaton-render
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02
|
11
|
+
date: 2024-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -216,6 +216,7 @@ files:
|
|
216
216
|
- lib/relaton/render/parse/parse.rb
|
217
217
|
- lib/relaton/render/parse/parse_contributors.rb
|
218
218
|
- lib/relaton/render/parse/parse_extract.rb
|
219
|
+
- lib/relaton/render/parse/parse_id.rb
|
219
220
|
- lib/relaton/render/template/liquid.rb
|
220
221
|
- lib/relaton/render/template/template.rb
|
221
222
|
- lib/relaton/render/utils/utils.rb
|