relaton-render 0.7.0 → 0.7.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 +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
|