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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51ae7431472a2a411d6fbb2e0d68e7a8b32c647cf839886c347e34000576a11c
4
- data.tar.gz: 5ede0d93ad108c2add767f4b9a5cec9b483ee9a1b6dd2db60ef51ee2959e65ab
3
+ metadata.gz: a61037d7e9fc1193d54cb03fd7155a09431a30710990c50366112558b86d8210
4
+ data.tar.gz: 7fe54372399bb332f686af101b9f6e36140497e89073cdf02f5e2bb0afec3183
5
5
  SHA512:
6
- metadata.gz: 0a2c1ff06584f6dddaedd7fab2d58467f3f4e54330107ff300529f26094f67331d09a19838743185af859c9d1deadbe4219ecec1e562f23bd320d87d4359bc1d
7
- data.tar.gz: 2da0c615b6cb5a610d9d4d14c892d22131eb3317595b5b2e131baf7d8f985cb0a8fc76a66f22ab550fc83b37005d9b29c6817ded7bc0b0b50ef3519a1c6ea769
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
@@ -14,6 +14,7 @@ date_formats:
14
14
  date_time: to_long_s
15
15
  ordinal_keys: []
16
16
  OrdinalRules: digits-ordinal
17
+ SpelloutRules: spellout-ordinal
17
18
  edition_ordinal: "第{{ var1 | ordinal_num: '', '' }}版"
18
19
  edition: 版
19
20
  draft: "草案%"
@@ -108,22 +108,23 @@ module Relaton
108
108
  end
109
109
 
110
110
  def render(bib, embedded: false)
111
- if bib.is_a?(String) && Nokogiri::XML(bib).errors.empty?
112
- bib = RelatonBib::XMLParser.from_xml bib
113
- end
114
- parse(bib, embedded: embedded)
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 fmtref(doc)
118
- "<formattedref>#{doc}</formattedref>"
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 parse(doc, embedded: false)
122
- f = doc.formattedref and
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 parse1(doc)
139
+ def render1(doc)
139
140
  r = doc.relation.select { |x| x.type == "hasRepresentation" }
140
- .map { |x| @i18n.also_pub_as + parse_single_bibitem(x.bibitem) }
141
- out = [parse_single_bibitem(doc)] + r
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 parse_single_bibitem(doc)
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
- valid_parse(@i18n.l10n(r.render(data_liquid)))
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
- res = access_url(url_string)
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(url_string)
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
- return nil unless contributors.length.positive?
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 [] if doc.nil?
84
-
82
+ doc.nil? and return []
85
83
  creatornames_roles_allowed.each do |r|
86
84
  add = pick_contributor(doc, r)
87
- next if add.nil?
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
- return nil if date.nil?
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 } if on
102
- return { from: from, to: to } if from
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
- place.city.nil? && place.region.empty? && place.country.empty? and
51
- return place.name
52
- ret = [place.city] + place.region.map(&:name) +
53
- place.country.map(&:name)
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
- return nil unless iter = doc&.status&.iteration
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
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Render
3
- VERSION = "0.7.0".freeze
3
+ VERSION = "0.7.1".freeze
4
4
  end
5
5
  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.0
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-19 00:00:00.000000000 Z
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