relaton-render 1.3.0 → 1.4.0.pre.alpha.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +15 -2
  3. data/lib/relaton/render/iso690/element.rb +43 -0
  4. data/lib/relaton/render/iso690/elements/component_part.rb +50 -0
  5. data/lib/relaton/render/iso690/elements/creator.rb +129 -0
  6. data/lib/relaton/render/iso690/elements/edition.rb +47 -0
  7. data/lib/relaton/render/iso690/elements/identifier.rb +32 -0
  8. data/lib/relaton/render/iso690/elements/location.rb +27 -0
  9. data/lib/relaton/render/iso690/elements/medium.rb +27 -0
  10. data/lib/relaton/render/iso690/elements/numeration.rb +26 -0
  11. data/lib/relaton/render/iso690/elements/production.rb +36 -0
  12. data/lib/relaton/render/iso690/elements/pub_date.rb +51 -0
  13. data/lib/relaton/render/iso690/elements/series.rb +40 -0
  14. data/lib/relaton/render/iso690/elements/title.rb +30 -0
  15. data/lib/relaton/render/iso690/elements.rb +40 -0
  16. data/lib/relaton/render/iso690/fields.rb +53 -0
  17. data/lib/relaton/render/iso690/i18n/en.yml +13 -0
  18. data/lib/relaton/render/iso690/i18n/fr.yml +14 -0
  19. data/lib/relaton/render/iso690/i18n.rb +53 -0
  20. data/lib/relaton/render/iso690/identifier_kinds.rb +34 -0
  21. data/lib/relaton/render/iso690/index_renderer.rb +57 -0
  22. data/lib/relaton/render/iso690/kinds.rb +43 -0
  23. data/lib/relaton/render/iso690/renderer.rb +52 -0
  24. data/lib/relaton/render/iso690/style/locale.rb +44 -0
  25. data/lib/relaton/render/iso690/style/name_form.rb +21 -0
  26. data/lib/relaton/render/iso690/style/scheme.rb +23 -0
  27. data/lib/relaton/render/iso690/style/sort_rule.rb +25 -0
  28. data/lib/relaton/render/iso690/style/template_map.rb +28 -0
  29. data/lib/relaton/render/iso690/style/type_template.rb +21 -0
  30. data/lib/relaton/render/iso690/style.rb +76 -0
  31. data/lib/relaton/render/iso690/styles/author-date.yml +28 -0
  32. data/lib/relaton/render/iso690/template.rb +72 -0
  33. data/lib/relaton/render/iso690.rb +22 -0
  34. data/lib/relaton/render/version.rb +1 -1
  35. data/lib/relaton-render.rb +3 -7
  36. data/relaton-render.gemspec +2 -19
  37. metadata +35 -249
  38. data/lib/relaton/render/fields/date.rb +0 -48
  39. data/lib/relaton/render/fields/fields.rb +0 -266
  40. data/lib/relaton/render/general/citations.rb +0 -178
  41. data/lib/relaton/render/general/config.yml +0 -129
  42. data/lib/relaton/render/general/render.rb +0 -316
  43. data/lib/relaton/render/general/render_classes.rb +0 -132
  44. data/lib/relaton/render/general/uri.rb +0 -57
  45. data/lib/relaton/render/i18n/i18n.rb +0 -40
  46. data/lib/relaton/render/parse/parse.rb +0 -152
  47. data/lib/relaton/render/parse/parse_contributors.rb +0 -184
  48. data/lib/relaton/render/parse/parse_extract.rb +0 -200
  49. data/lib/relaton/render/parse/parse_id.rb +0 -128
  50. data/lib/relaton/render/template/liquid.rb +0 -48
  51. data/lib/relaton/render/template/subclasses.rb +0 -123
  52. data/lib/relaton/render/template/template.rb +0 -228
@@ -1,200 +0,0 @@
1
- module Relaton
2
- module Render
3
- class Parse
4
- def host(doc)
5
- doc.relation&.detect { |r| r.type == "includedIn" }&.bibitem
6
- end
7
-
8
- # TODO : first is naive choice
9
- def title(doc)
10
- doc.nil? || doc.title.nil? || doc.title.empty? and return nil
11
- t = Array(doc.title).select { |x| x.language == @lang }
12
- t.empty? and t = Array(doc.title)
13
- t1 = t.select { |x| x.type == "main" }
14
- t1.empty? and t1 = t
15
- t1.first or return
16
- esc(content(t1.first))
17
- end
18
-
19
- def medium(doc, host)
20
- x = doc.medium || host&.medium or return nil
21
- %w(content genre form carrier size scale).each_with_object({}) do |i, m|
22
- m[i] = x.send i
23
- end.compact
24
- end
25
-
26
- def size(doc)
27
- x = doc.size or return nil
28
- x.value.each_with_object({}) do |v, m|
29
- m[v.type] ||= []
30
- m[v.type] << v.content
31
- end
32
- end
33
-
34
- def edition(doc, host)
35
- ret = content(doc.edition || host&.edition)
36
- ret &&= esc(ret)
37
- ret
38
- end
39
-
40
- def edition_num(doc, host)
41
- doc.edition&.number || host&.edition&.number
42
- end
43
-
44
- def place(doc, host)
45
- x = Array(doc.place)
46
- x.empty? && host and x = Array(host.place)
47
- x.empty? and return x
48
- x.map { |p| place1(p) }
49
- end
50
-
51
- def place1(place)
52
- c = place.city
53
- r = place.region
54
- n = place.country
55
- c.nil? && r.empty? && n.empty? and return place.formatted_place
56
- [c, *r.map(&:content), *n.map(&:content)].compact.join(", ")
57
- end
58
-
59
- def series(doc)
60
- doc.series&.detect { |s| s.type == "main" } ||
61
- doc.series&.detect { |s| s.type.nil? } ||
62
- doc.series&.first
63
- end
64
-
65
- def series_title(series, _doc)
66
- series.nil? and return nil
67
- t = Array(series.title).select { |x| x.language == @lang }
68
- t.empty? and t = Array(series.title)
69
- t1 = t.select { |x| x.type == "main" }
70
- t1.empty? and t1 = t
71
- t1.first.nil? and return nil
72
- content(t1.first)
73
- end
74
-
75
- def series_formatted(series, _doc)
76
- content(series.formattedref)
77
- end
78
-
79
- def series_abbr(series, _doc)
80
- content(series.abbreviation)
81
- end
82
-
83
- def series_num(series, _doc)
84
- series.number&.strip
85
- end
86
-
87
- def series_partnumber(series, _doc)
88
- series.partnumber
89
- end
90
-
91
- def series_run(series, _doc)
92
- series.run
93
- end
94
-
95
- def series_org(series, _doc)
96
- series.organization
97
- end
98
-
99
- def series_place(series, _doc)
100
- p = series.place or return nil
101
- place1(p)
102
- end
103
-
104
- def series_dates(series, _doc)
105
- f = series.from
106
- t = series.to
107
- f || t or return nil
108
- "#{f}–#{t}"
109
- end
110
-
111
- def access_location(doc, host)
112
- x = doc.accesslocation || host&.accesslocation or
113
- return nil
114
- Array(x).first
115
- end
116
-
117
- def included(type)
118
- ["article", "inbook", "incollection", "inproceedings"].include? type
119
- end
120
-
121
- def type(doc)
122
- type = doc.type and return type
123
- doc.relation&.any? { |r| r.type == "includedIn" } and return "inbook"
124
- "book"
125
- end
126
-
127
- def language(doc)
128
- doc.language&.first || @lang
129
- end
130
-
131
- def script(doc)
132
- doc.script&.first || @script
133
- end
134
-
135
- def locale(doc)
136
- # TODO not yet implemented in relaton-bib
137
- # doc.locale&.first
138
- end
139
-
140
- def extent1(localities)
141
- localities.each_with_object({}) do |l, ret|
142
- ret[(l.type || "page").to_sym] = {
143
- from: localized_string_or_text(l.reference_from),
144
- to: localized_string_or_text(l.reference_to),
145
- }
146
- end
147
- end
148
-
149
- def localized_string_or_text(str)
150
- case str
151
- when Relaton::Bib::LocalizedString then content(str)
152
- when String then str
153
- end
154
- end
155
-
156
- def extent(doc)
157
- Array(doc.extent).each_with_object([]) do |e, acc|
158
- case e
159
- when Relaton::Bib::Extent, Relaton::Bib::LocalityStack
160
- if e.locality.any?
161
- a = e.locality.each_with_object([]) do |e1, m|
162
- if e1.is_a?(Relaton::Bib::LocalityStack)
163
- m << extent1(e1.locality)
164
- else
165
- m.empty? and m << {}
166
- m[-1].merge!(extent1(Array(e1)))
167
- end
168
- end
169
- acc << a
170
- else
171
- Array(e.locality_stack).each do |stack|
172
- a = stack.locality.each_with_object([{}]) do |e1, m|
173
- m[-1].merge!(extent1(Array(e1)))
174
- end
175
- acc << a
176
- end
177
- end
178
- when Relaton::Bib::Locality
179
- acc << extent1(Array(e))
180
- end
181
- end
182
- end
183
-
184
- def draft(doc, host)
185
- { iteration: iter_ordinal(doc) || iter_ordinal(host),
186
- status: status(doc) || status(host) }
187
- end
188
-
189
- def iter_ordinal(doc)
190
- iter = doc&.status&.iteration or return nil
191
- iter
192
- end
193
-
194
- def status(doc)
195
- v = doc&.status&.stage&.content
196
- #@i18n.get.dig("stage", v) || v
197
- end
198
- end
199
- end
200
- end
@@ -1,128 +0,0 @@
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
- f = id_extract_by_scope(v, "trademark")
15
- f.empty? and f = id_extract_by_scope(v, nil)
16
- m << f
17
- else m << id_extract_by_scope(v, nil)
18
- end
19
- end.flatten
20
- end
21
-
22
- def id_sort_by_scope(ids)
23
- ids.each_with_object({}) do |i, m|
24
- m[i.type] ||= {}
25
- m[i.type][i.scope] ||= []
26
- m[i.type][i.scope] << i
27
- end
28
- end
29
-
30
- def id_extract_by_scope(idents, key)
31
- if idents.key?(key)
32
- idents[key]
33
- else []
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(Array(doc.docidentifier)), Array(doc.docidentifier)].each do |a|
48
- out = authoritative_identifier_select(a)
49
- out.empty? or break
50
- end
51
- # prevent l10n of identifier contents
52
- out.map(&:content).map { |i| esc(i.strip) }
53
- end
54
-
55
- def authoritative_identifier_select(idents)
56
- out = []
57
- auth_id_allow.each do |p|
58
- out = idents.select do |x|
59
- p.call(x) &&
60
- !authoritative_identifier_exclude.include?(id_type_norm(x))
61
- end
62
- out.empty? or break
63
- end
64
- out
65
- end
66
-
67
- def authoritative_identifier_exclude
68
- %w(METANORMA METANORMA-ORDINAL AUTHOR-DATE TITLE URN ISO-REFERENCE) +
69
- other_identifier_include
70
- end
71
-
72
- def other_identifier(doc)
73
- Array(doc.docidentifier).each_with_object([]) do |id, ret|
74
- type = id_type_norm(id)
75
- other_identifier_include.include? type or next
76
- ret << [type, id.content]
77
- end
78
- end
79
-
80
- def other_identifier_include
81
- %w(ISSN ISBN DOI)
82
- end
83
-
84
- def doi(doc)
85
- out = Array(doc.docidentifier).each_with_object([]) do |id, ret|
86
- type = id.type&.sub(/^(DOI)\..*$/i, "\\1") or next
87
- type.casecmp("doi").zero? or next
88
- ret << id.content
89
- end
90
- out.empty? ? nil : out.map { |i| esc(i.strip) }
91
- end
92
-
93
- def id_type_norm(id)
94
- id.type or return nil
95
- m = /^(ISBN|ISSN)\./i.match(id.type) or return id.type.upcase
96
- m[1].upcase
97
- end
98
-
99
- def biblio_tag(doc)
100
- ret = Array(doc.docidentifier).detect do |id|
101
- id.scope&.downcase == "biblio-tag"
102
- end
103
- ret&.content
104
- end
105
-
106
- def uri(doc)
107
- uri = nil
108
- %w(citation uri src).each do |t|
109
- uri = uri_type_select(doc, t) and break
110
- end
111
- uri ||= Array(doc.source).detect do |u|
112
- u.language == @lang && !u.type&.casecmp("doi")&.zero?
113
- end
114
- uri ||= Array(doc.source).detect { |u| !u.type&.casecmp("doi")&.zero? }
115
- uri or return nil
116
- uri.content.to_s.strip
117
- end
118
-
119
- def uri_type_select(doc, type)
120
- uri = Array(doc.source).detect do |u|
121
- u.type&.downcase == type && u.language == @lang
122
- end and return uri
123
- uri = Array(doc.source).detect { |u| u.type&.downcase == type } and return uri
124
- nil
125
- end
126
- end
127
- end
128
- end
@@ -1,48 +0,0 @@
1
- module Relaton
2
- module Render
3
- module Template
4
- module CustomFilters
5
- def capitalize_first(words)
6
- words.nil? and return nil
7
- # Split while preserving delimiters (spaces/underscores) and extracting XML tags
8
- ret = words.split(/(<[^>]+>|[ _])/).reject(&:empty?)
9
- # Find and capitalize the first element that is not a delimiter or XML tag
10
- ret.each do |element|
11
- element.match?(/^[ _]$/) || element.match?(/^<[^>]+>$/) and next
12
- element.capitalize!
13
- break
14
- end
15
- # Join with empty string since delimiters are preserved
16
- ret.join.sub(/^[ _]+/, "").sub(/[ _]+$/, "")
17
- end
18
-
19
- def selective_upcase(text)
20
- text.nil? and return nil
21
- # Split to extract both +++...+++ sections and XML tags
22
- text.split(/(\+\+\+[^+]+?\+\+\+|<[^<>]+>)/).map do |n|
23
- if m = /^\+\+\+(.+)\+\+\+$/.match(n)
24
- m[1] # Keep content inside +++ unchanged
25
- elsif n.match?(/^<[^>]+>$/)
26
- n # Keep XML tags unchanged
27
- else n.upcase # Upcase everything else
28
- end
29
- end.join
30
- end
31
-
32
- def selective_tag(text, tag)
33
- return nil if text.nil?
34
-
35
- ret = text.split(/(\+\+\+[^+]+?\+\+\+)/)
36
- ret.map do |n|
37
- if m = /^\+\+\+(.+)\+\+\+$/.match(n)
38
- m[1]
39
- else
40
- closetag = tag.sub(/^</, "</")
41
- "#{tag}#{n}#{closetag}"
42
- end
43
- end.join
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,123 +0,0 @@
1
- module Relaton
2
- module Render
3
- module Template
4
- class Series < General
5
- end
6
-
7
- class Extent < General
8
- def template_select(hash)
9
- @template[hash[:type].to_sym]
10
- end
11
- end
12
-
13
- class Size < General
14
- def template_select(hash)
15
- @template[hash[:type].to_sym]
16
- end
17
- end
18
-
19
- class Name < General
20
- def initialize(opt = {})
21
- @etal_count = opt[:template]["etal_count"]
22
- @etal_display = opt[:template]["etal_display"] || @etal_count
23
- opt[:template].delete("etal_count")
24
- opt[:template].delete("etal_display")
25
- super
26
- end
27
-
28
- def template_select(names)
29
- return nil if names.nil? || names.empty?
30
-
31
- case names[:surname].size
32
- when 1 then @template[:one]
33
- when 2 then @template[:two]
34
- when 3 then @template[:more]
35
- else template_select_etal(names)
36
- end
37
- end
38
-
39
- def template_select_etal(names)
40
- if @etal_count && names[:surname].size > @etal_count
41
- expand_nametemplate(@template_raw[:etal], @etal_display)
42
- else
43
- expand_nametemplate(@template_raw[:more], names[:surname].size)
44
- end
45
- end
46
-
47
- # assumes that template contains, consecutively and not interleaved,
48
- # ...[0], ...[1], ...[2]
49
- def expand_nametemplate(template, size)
50
- t = nametemplate_split(template)
51
- mid = (1..size - 2).each_with_object([]) do |i, m|
52
- m << t[1].gsub("[1]", "[#{i}]")
53
- end
54
- t[1] = mid.join
55
- t[2].gsub!(/\[\d+\]/, "[#{size - 1}]")
56
- template_process(combine_nametemplate(t, size))
57
- end
58
-
59
- def combine_nametemplate(parts, size)
60
- case size
61
- when 1 then parts[0] + parts[3]
62
- when 2 then parts[0] + parts[2] + parts[3]
63
- else parts.join
64
- end
65
- end
66
-
67
- def nametemplate_split(template)
68
- curr = 0
69
- prec = ""
70
- @in_name = 0
71
- t = template.split(/(\{[{%][^{]+?[}%]\})/)
72
- .each_with_object([""]) do |n, m|
73
- m, curr, prec = nametemplate_split1(n, m, curr, prec)
74
-
75
- m
76
- end
77
- [t[0], t[1], t[-1], prec]
78
- end
79
-
80
- def nametemplate_split1(elem, acc, curr, prec)
81
- if match = /\{[{%].+?\[(\d)\]/.match(elem)
82
- # we are in a name component
83
- # if an if is started, track the if nesting...
84
- @in_name += 1 if /\{%\s*if/.match?(elem)
85
- if match[1].to_i > curr
86
- curr += 1
87
- acc[curr] ||= ""
88
- end
89
- acc[curr] += prec
90
- prec = ""
91
- acc[curr] += elem
92
- elsif /\{%\s*endif/.match?(elem) && @in_name.positive?
93
- # stick the endif to the currently if-nested name component,
94
- # if we are in one (@in_name.positive?)
95
- @in_name -= 1
96
- acc[curr] += prec
97
- prec = ""
98
- acc[curr] += elem
99
- else prec += elem
100
- end
101
- [acc, curr, prec]
102
- end
103
- end
104
-
105
- class AuthorCite < Name
106
- end
107
-
108
- class Cite < General
109
- def template_select(hash)
110
- if hash[:citestyle].to_sym == :short
111
- @template[hash[:type].to_sym]
112
- else
113
- @template[hash[:citestyle].to_sym]
114
- end
115
- end
116
-
117
- def citation_styles
118
- @template.keys
119
- end
120
- end
121
- end
122
- end
123
- end