relaton-render 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/rake.yml +15 -0
- data/.hound.yml +5 -0
- data/.rubocop.yml +10 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +25 -0
- data/README.adoc +241 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/rspec +18 -0
- data/bin/setup +8 -0
- data/lib/isodoc/i18n.rb +24 -0
- data/lib/isodoc-yaml/i18n-ar.yaml +2 -0
- data/lib/isodoc-yaml/i18n-de.yaml +2 -0
- data/lib/isodoc-yaml/i18n-en.yaml +22 -0
- data/lib/isodoc-yaml/i18n-es.yaml +2 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +2 -0
- data/lib/isodoc-yaml/i18n-ru.yaml +23 -0
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +2 -0
- data/lib/parse/parse.rb +54 -0
- data/lib/parse/parse_contributors.rb +96 -0
- data/lib/parse/parse_extract.rb +155 -0
- data/lib/relaton/config.yml +67 -0
- data/lib/relaton/render.rb +123 -0
- data/lib/relaton/render_classes.rb +126 -0
- data/lib/relaton/render_fields.rb +151 -0
- data/lib/relaton/version.rb +5 -0
- data/lib/relaton-render.rb +6 -0
- data/lib/template/template.rb +152 -0
- data/lib/utils/utils.rb +27 -0
- data/relaton-render.gemspec +35 -0
- metadata +213 -0
@@ -0,0 +1,155 @@
|
|
1
|
+
class Iso690Parse
|
2
|
+
def title(doc)
|
3
|
+
doc&.at("./title")&.text
|
4
|
+
end
|
5
|
+
|
6
|
+
def medium(doc, host)
|
7
|
+
x = doc.at("./medium") || host&.at("./medium") or return nil
|
8
|
+
|
9
|
+
%w(content genre form carrier size scale).each_with_object([]) do |i, m|
|
10
|
+
m << x.at("./#{i}")&.text
|
11
|
+
end.compact.join(", ")
|
12
|
+
end
|
13
|
+
|
14
|
+
def blank?(text)
|
15
|
+
text.nil? || text.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
def edition(doc, host)
|
19
|
+
x = doc.at("./edition") || host&.at("./edition") or return nil
|
20
|
+
|
21
|
+
x.text
|
22
|
+
end
|
23
|
+
|
24
|
+
def place(doc, host)
|
25
|
+
x = doc.at("./place") || host&.at("./place") or return nil
|
26
|
+
|
27
|
+
x.text
|
28
|
+
end
|
29
|
+
|
30
|
+
def publisher(doc, host)
|
31
|
+
x = doc.at("./contributor[role/@type = 'publisher']/organization/name") ||
|
32
|
+
host&.at("./contributor[role/@type = 'publisher']/organization/name") or
|
33
|
+
return nil
|
34
|
+
x.text
|
35
|
+
end
|
36
|
+
|
37
|
+
def distributor(doc, host)
|
38
|
+
x = doc.at("./contributor[role/@type = 'distributor']/organization/name") ||
|
39
|
+
host&.at("./contributor[role/@type = 'distributor']/organization/name") or
|
40
|
+
return nil
|
41
|
+
x.text
|
42
|
+
end
|
43
|
+
|
44
|
+
def series_title(doc)
|
45
|
+
doc&.at("./title")&.text || doc&.at("./formattedref")&.text
|
46
|
+
end
|
47
|
+
|
48
|
+
def series_abbr(doc)
|
49
|
+
doc&.at("./abbreviation")&.text
|
50
|
+
end
|
51
|
+
|
52
|
+
def series_num(doc)
|
53
|
+
doc&.at("./number")&.text
|
54
|
+
end
|
55
|
+
|
56
|
+
def series_partnumber(doc)
|
57
|
+
doc&.at("./partnumber")&.text
|
58
|
+
end
|
59
|
+
|
60
|
+
def series_run(doc)
|
61
|
+
doc&.at("./run")&.text
|
62
|
+
end
|
63
|
+
|
64
|
+
def standardidentifier(doc)
|
65
|
+
doc.xpath("./docidentifier").each_with_object([]) do |id, ret|
|
66
|
+
ret << id.text unless %w(metanorma metanorma-ordinal).include? id["type"]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def uri(doc)
|
71
|
+
uri = doc.at("./uri[@type = 'doi']") || doc.at("./uri[@type = 'uri']") ||
|
72
|
+
doc.at("./uri[@type = 'src']") || doc.at("./uri")
|
73
|
+
uri&.text
|
74
|
+
end
|
75
|
+
|
76
|
+
def access_location(doc, host)
|
77
|
+
x = doc.at("./accessLocation") || host&.at("./accessLocation") or
|
78
|
+
return nil
|
79
|
+
x.text
|
80
|
+
end
|
81
|
+
|
82
|
+
def included(type)
|
83
|
+
["article", "inbook", "incollection", "inproceedings"].include? type
|
84
|
+
end
|
85
|
+
|
86
|
+
def wrap(text, startdelim = " ", enddelim = ".")
|
87
|
+
return "" if blank?(text)
|
88
|
+
|
89
|
+
"#{startdelim}#{text}#{enddelim}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def type(doc)
|
93
|
+
type = doc.at("./@type") and return type&.text
|
94
|
+
doc.at("./relation[@type = 'includedIn']") and return "inbook"
|
95
|
+
"book"
|
96
|
+
end
|
97
|
+
|
98
|
+
def extent1(localities)
|
99
|
+
localities.each_with_object({}) do |l, ret|
|
100
|
+
ret[(l["type"] || "page").to_sym] = {
|
101
|
+
from: l.at("./referenceFrom")&.text,
|
102
|
+
to: l.at("./referenceTo")&.text,
|
103
|
+
}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def extent0(elem, acc, ret1)
|
108
|
+
case elem.name
|
109
|
+
when "localityStack"
|
110
|
+
acc << ret1
|
111
|
+
ret1 = {}
|
112
|
+
acc << extent1(elem.elements)
|
113
|
+
when "locality" then ret1.merge!(extent1([elem]))
|
114
|
+
when "referenceFrom" then ret1.merge!(extent1([elem.parent]))
|
115
|
+
end
|
116
|
+
[acc, ret1]
|
117
|
+
end
|
118
|
+
|
119
|
+
def extent(doc)
|
120
|
+
ret1 = {}
|
121
|
+
ret = doc.xpath("./extent").each_with_object([]) do |e, acc|
|
122
|
+
e.elements.each do |l|
|
123
|
+
acc, ret1 = extent0(l, acc, ret1)
|
124
|
+
break if l.name == "referenceFrom"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
ret << ret1
|
128
|
+
ret.reject(&:empty?)
|
129
|
+
end
|
130
|
+
|
131
|
+
def draft(doc)
|
132
|
+
dr = doc&.at("./status/stage")&.text
|
133
|
+
|
134
|
+
iterord = iter_ordinal(doc)
|
135
|
+
status = status_print(dr)
|
136
|
+
status = "#{iterord} #{status}" if iterord
|
137
|
+
status
|
138
|
+
end
|
139
|
+
|
140
|
+
def iter_ordinal(isoxml)
|
141
|
+
return nil unless isoxml.at(("./status/iteration"))
|
142
|
+
|
143
|
+
iter = isoxml.at(("./status/iteration"))&.text || "1"
|
144
|
+
iter.to_i.localize.to_rbnf_s("SpelloutRules",
|
145
|
+
"spellout-ordinal").capitalize
|
146
|
+
end
|
147
|
+
|
148
|
+
def status_print(status)
|
149
|
+
status
|
150
|
+
end
|
151
|
+
|
152
|
+
def status(doc)
|
153
|
+
doc&.at("./status/stage")&.text
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
nametemplate:
|
2
|
+
one: "{{surname[0] | upcase }}, {{given[0]}} {{middle[0}}"
|
3
|
+
two: "{{surname[0] | upcase}}, {{given[0]}} {{middle[0]}} {{ labels['and'] }} {{given[1]}} {{middle[1]}} {{surname[1] | upcase}}"
|
4
|
+
more: "{{surname[0] | upcase}}, {{given[0]}} {{middle[0}} , {{given[1]}} {{middle[1]}} {{surname[1] | upcase}} {{ labels['and'] }} {{given[2]}} {{middle[2]}} {{surname[2] | upcase}}"
|
5
|
+
# disabled the following: they should be provided in inheriting calls
|
6
|
+
# etal: "{{surname[0] | upcase}}, {{given[0]}} {{middle[0]}}, {{given[1]}} {{middle[1]}} {{surname[1] | upcase}} <em>et al.</em>"
|
7
|
+
# etal_count: 5
|
8
|
+
seriestemplate: "{% if series_abbr %}{{series_abbr}}{% else %}{{series_title}}{% endif %} ({{series_run}}) {{series_num}}|({{series_partnumber}})"
|
9
|
+
journaltemplate: "<em>{% if series_abbr %}{{series_abbr}}{% else %}{{series_title}}{% endif %}</em> ({{series_run}}) {{ labels['volume'] }}_{{series_num}} {{ labels['part'] }}_{{series_partnumber}}"
|
10
|
+
extenttemplate:
|
11
|
+
book: "{{ volume }}_{{ labels['extent']['volume'] }}, {{ page }}_{{ labels['extent']['page'] }}"
|
12
|
+
booklet: book
|
13
|
+
proceedings: book
|
14
|
+
journal: book
|
15
|
+
standard: book
|
16
|
+
techreport: book
|
17
|
+
inbook: "{{ volume }}: {{ page }}"
|
18
|
+
misc: "{{ labels['extent']['volume'] }}_{{ volume }}, {{ labels['extent']['page'] }}_{{ page }}"
|
19
|
+
# TODO: software extent
|
20
|
+
language: en
|
21
|
+
script: Latn
|
22
|
+
template:
|
23
|
+
book: "{{ creatornames }} ({{role}}) . <em>{{ title }}</em> [{{medium}}] . {{ edition | capitalize }}. ({{ series }}.) {{place}}: {{publisher}}. {{date}}. {{ labels['updated'] | capitalize }}:_{{date_updated}}. {{ standardidentifier | first }}. {{ uri }}. {{ labels['at'] | capitalize}}:_{{ access_location }}. [{{ labels['viewed'] }}:_{{date_accessed}}]. {{extent}}."
|
24
|
+
# TODO: omitted: author ids, subsidiary titles, subsidiary creators, rights metadata, distributor, item attributes, relationships
|
25
|
+
booklet: book
|
26
|
+
manual: book
|
27
|
+
proceedings: book
|
28
|
+
inbook: "{{ creatornames }} ({{role}}) . {{ title }} . {{ labels['in'] | capitalize }}: {{ host_creatornames}} ({{ host_role}}) : <em>{{host_title}}</em> [{{medium}}] . {{ edition | capitalize }}. ({{ series }}.) {{place}}: {{publisher}}. {{date}}. {{extent}}. {{ labels['updated'] | capitalize }}:_{{date_updated}}. {{ standardidentifier | first }}. {{ uri }}. {{ labels['at'] | capitalize}}:_{{ access_location }}. [{{ labels['viewed'] }}:_{{date_accessed}}]."
|
29
|
+
inproceedings: inbook
|
30
|
+
incollection: inbook
|
31
|
+
# TODO: omitted: author ids, additional info for component part, subsidiary titles of host resource, rights metadata, distributor, relationships
|
32
|
+
journal: "<em>{{ title}}</em> [{{medium}}] . {{ edition | capitalize }}. {{place}}: {{publisher}}. {{date}}. {{extent}}. {{ standardidentifier | first }}. {{ uri }}. {{ labels['at'] | capitalize}}:_{{ access_location }}. [{{ labels['viewed'] }}:_{{date_accessed}}]."
|
33
|
+
# TODO subsidiary titles, rights metadata, item attributes, relationships
|
34
|
+
article: "{{ creatornames }} ({{role}}) . {{ title }}. {{ series }} [{{medium}}] . {{ edition | capitalize }}. {{ extent }}. {{place}}: {{publisher}}. {{date}}. {{ labels['updated'] | capitalize }}:_{{date_updated}}. {{ standardidentifier | first }}. {{ uri }}. {{ labels['at'] | capitalize}}:_{{ access_location }}. [{{ labels['viewed'] }}:_{{date_accessed}}]."
|
35
|
+
# TODO: omitted: author ids, subsidiary titles, rights metadata, distributor, item attributes, relationships; newspapers
|
36
|
+
software: "{{ creatornames }} ({{ role}}) . <em>{{ title }}</em> . {{ labels['version'] | capitalize }}_{{ edition_raw }}. {{medium | capitalize}}. {{place}}: {{publisher}}. {{date}}. {{ labels['updated'] | capitalize }}:_{{date_updated}}. {{ standardidentifier | first }}. {{ uri }}. {{ extent}}. [{{ labels['viewed'] }}:_{{date_accessed}}]. "
|
37
|
+
# TODO: omitted: author ids, subsidiary titles, subsidiary creators, copyright, license, distributor, system requirements, relationships
|
38
|
+
electronic resource: software
|
39
|
+
standard: "{{ creatornames }} ({{ role}}) . <em>{{ title }}</em> . {{ labels['in'] | capitalize }}:_{{ series_title }}. {{ medium | capitalize }}. {{ edition | capitalize }}. {{place}}: {{publisher}}. {{date}}. {{ extent }}. {{ standardidentifier | first }}. {{ uri }}. {{ labels['at'] | capitalize}}:_{{ access_location }}. [{{ labels['viewed'] }}:_{{date_accessed}}]."
|
40
|
+
# TODO: omitted: author ids, subsidiary titles, rights metadata, distributor, persistent identifier, item attributes, relationships
|
41
|
+
techreport: standard
|
42
|
+
dataset: "{{ creatornames }} ({{ role }}) . <em>{{ title }}</em> . {{ labels['version'] | capitalize }}_{{ edition_raw }}. {{medium | capitalize }}. {{ labels['in'] | capitalize }}:_{{series}}. {{date}}. {{ labels['updated'] | capitalize }}:_{{date_updated}}. {{ standardidentifier | first }}. {{ uri }}. {{ extent}}. [{{ labels['viewed'] }}:_{{date_accessed}}]. "
|
43
|
+
# TODO: omitted: author ids, system requirements, host archive, copyright, license, data source, distributor, usage instructions, relationships, provenance
|
44
|
+
website: "{{ creatornames }} ({{ role }}) . <em>{{ title }}</em> . {{ labels['version'] | capitalize }}_{{ edition_raw }}. {{medium | capitalize }}. {{ place }}: {{ publisher }}. {{date}}. {{ labels['updated'] | capitalize }}:_{{date_updated}}. {{ standardidentifier | first }}. {{ uri }}. [{{ labels['viewed'] }}:_{{date_accessed}}]. "
|
45
|
+
# TODO: omitted: author ids, page title, system requirements, subsidiary creator, rights metadata, distributor, persistent identifier, archive location, archive date and time, relationships
|
46
|
+
webresource: website
|
47
|
+
# TODO: component part
|
48
|
+
unpublished: "{{ creatornames }} ({{ role }}) . <em>{{ title }}</em> . {{ medium | capitalize }}. {{ date }}. {{ labels['at'] | capitalize}}:_{{ access_location }}. {{ standardidentifier | first }}. {{ uri }}. [{{ labels['viewed'] }}:_{{date_accessed}}]."
|
49
|
+
# TODO: omitted: author ids, subsidiary titles, subsidiary creators, host archive, item attributes, relationships
|
50
|
+
presentation: unpublished
|
51
|
+
thesis: "{{ creatornames }} ({{ role }}) . <em>{{ title }}</em> . {{ medium | capitalize }}. {{ place }}: {{ publisher }}. {{ date }}. {{ labels['at'] | capitalize}}:_{{ access_location }}. {{ standardidentifier | first }}. {{ uri }}. [{{ labels['viewed'] }}:_{{date_accessed}}]."
|
52
|
+
# unsupported types:
|
53
|
+
# map: ""
|
54
|
+
# audiovisual: ""
|
55
|
+
# film: ""
|
56
|
+
# video: ""
|
57
|
+
# broadcast: ""
|
58
|
+
# graphic_work: ""
|
59
|
+
# music: ""
|
60
|
+
# performance: "" (not in Relaton)
|
61
|
+
# patent: ""
|
62
|
+
# archival: ""
|
63
|
+
# social_media: ""
|
64
|
+
# alert: ""
|
65
|
+
# message: ""
|
66
|
+
# conversation: ""
|
67
|
+
# misc: ""
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require_relative "render_classes"
|
2
|
+
require_relative "render_fields"
|
3
|
+
require "yaml"
|
4
|
+
require "liquid"
|
5
|
+
require_relative "../isodoc/i18n"
|
6
|
+
require_relative "../utils/utils"
|
7
|
+
|
8
|
+
module Relaton
|
9
|
+
module Render
|
10
|
+
class General
|
11
|
+
attr_reader :template, :journaltemplate, :seriestemplate, :nametemplate,
|
12
|
+
:extenttemplate, :lang, :script, :edition, :edition_number,
|
13
|
+
:date
|
14
|
+
|
15
|
+
def initialize(opt = {})
|
16
|
+
options = YAML.load_file(File.join(File.dirname(__FILE__),
|
17
|
+
"config.yml"))
|
18
|
+
.merge(Utils::string_keys(opt))
|
19
|
+
@type = self.class.name.downcase.sub(/relaton::render::/, "")
|
20
|
+
root_initalize(options)
|
21
|
+
render_initialize(options)
|
22
|
+
@parse ||= options["parse"]
|
23
|
+
@i18n ||= options["i18n"]
|
24
|
+
end
|
25
|
+
|
26
|
+
def root_initalize(opt)
|
27
|
+
i18n_initialize(opt)
|
28
|
+
@parse = Iso690Parse.new
|
29
|
+
@nametemplate = Iso690NameTemplate
|
30
|
+
.new(template: opt["nametemplate"], i18n: @i18n)
|
31
|
+
@seriestemplate = Iso690SeriesTemplate
|
32
|
+
.new(template: opt["seriestemplate"], i18n: @i18n)
|
33
|
+
@journaltemplate = Iso690SeriesTemplate
|
34
|
+
.new(template: opt["journaltemplate"], i18n: @i18n)
|
35
|
+
@extenttemplate = extentrenderers(opt)
|
36
|
+
end
|
37
|
+
|
38
|
+
def i18n_initialize(opt)
|
39
|
+
@lang = opt["language"]
|
40
|
+
@script = opt["script"]
|
41
|
+
@i18n = i18n(opt["language"], opt["script"])
|
42
|
+
@edition_number = opt["edition_number"] || @i18n.edition_number
|
43
|
+
@edition = opt["edition"] || @i18n.edition
|
44
|
+
@date = opt["date"] || @i18n.date
|
45
|
+
end
|
46
|
+
|
47
|
+
def render_initialize(opt)
|
48
|
+
case opt["template"]
|
49
|
+
when String
|
50
|
+
@template = Iso690Template.new(template: opt["template"],
|
51
|
+
i18n: @i18n)
|
52
|
+
when Hash
|
53
|
+
@render = renderers(opt)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def renderers(opt)
|
58
|
+
template_hash_fill(opt["template"]).each_with_object({}) do |(k, v), m|
|
59
|
+
@type == "general" || @type == k or next
|
60
|
+
m[k] = General.subclass(k)
|
61
|
+
.new(template: v, parse: @parse, i18n: @i18n,
|
62
|
+
language: @lang, script: @script)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def extentrenderers(opt)
|
67
|
+
Iso690ExtentTemplate
|
68
|
+
.new(template: template_hash_fill(opt["extenttemplate"]), i18n: @i18n)
|
69
|
+
end
|
70
|
+
|
71
|
+
def default_template
|
72
|
+
"{{creatornames}}. {{title}}. {{date}}."
|
73
|
+
end
|
74
|
+
|
75
|
+
def i18n(lang = "en", script = "Latn")
|
76
|
+
::IsoDoc::I18n.new(lang, script)
|
77
|
+
end
|
78
|
+
|
79
|
+
def render(bib, embedded: false)
|
80
|
+
docxml = Nokogiri::XML(bib)
|
81
|
+
docxml.remove_namespaces!
|
82
|
+
parse(docxml.root, embedded: embedded)
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse(doc, embedded: false)
|
86
|
+
f = doc.at("./formattedref") and
|
87
|
+
return embedded ? f.children.to_xml : doc.to_xml
|
88
|
+
|
89
|
+
ret = parse1(doc)
|
90
|
+
embedded and return ret
|
91
|
+
"<formattedref>#{ret}</formattedref>"
|
92
|
+
end
|
93
|
+
|
94
|
+
def renderer(doc)
|
95
|
+
unless ret = @template || @render[doc["type"]]&.template
|
96
|
+
raise "No renderer defined for #{doc['type']}"
|
97
|
+
end
|
98
|
+
unless @type == "general" || @type == doc["type"]
|
99
|
+
raise "No renderer defined for #{doc['type']}"
|
100
|
+
end
|
101
|
+
|
102
|
+
ret
|
103
|
+
end
|
104
|
+
|
105
|
+
def parse1(doc)
|
106
|
+
r = renderer(doc)
|
107
|
+
data = @parse.extract(doc)
|
108
|
+
data_liquid = Fields.new(renderer: self).compound_fields_format(data)
|
109
|
+
@i18n.l10n(r.render(data_liquid))
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def template_hash_fill(templates)
|
115
|
+
BIBTYPE.each_with_object({}) do |type, m|
|
116
|
+
template = templates[type] || templates["misc"] || default_template
|
117
|
+
BIBTYPE.include?(template) and template = templates[template]
|
118
|
+
m[type] = template
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Relaton
|
2
|
+
module Render
|
3
|
+
BIBTYPE =
|
4
|
+
%w(article book booklet manual proceedings presentation thesis techreport
|
5
|
+
standard unpublished map electronic_resource audiovisual film video
|
6
|
+
broadcast software graphic_work music patent inbook incollection
|
7
|
+
inproceedings journal website webresource dataset archival social_media
|
8
|
+
alert message conversation misc).freeze
|
9
|
+
|
10
|
+
class General
|
11
|
+
singleton_class.send(:attr_reader, :descendants)
|
12
|
+
@descendants = {}
|
13
|
+
|
14
|
+
def self.inherited(subclass) # rubocop:disable Lint/MissingSuper
|
15
|
+
type = subclass.name.downcase.sub(/relaton::render::/, "")
|
16
|
+
General.descendants[type] = subclass
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.subclass(type)
|
20
|
+
@descendants[type]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Book < General
|
25
|
+
end
|
26
|
+
|
27
|
+
class Journal < General
|
28
|
+
end
|
29
|
+
|
30
|
+
class Booklet < General
|
31
|
+
end
|
32
|
+
|
33
|
+
class Manual < General
|
34
|
+
end
|
35
|
+
|
36
|
+
class Proceedings < General
|
37
|
+
end
|
38
|
+
|
39
|
+
class Presentation < General
|
40
|
+
end
|
41
|
+
|
42
|
+
class Thesis < General
|
43
|
+
end
|
44
|
+
|
45
|
+
class Techreport < General
|
46
|
+
end
|
47
|
+
|
48
|
+
class Standard < General
|
49
|
+
end
|
50
|
+
|
51
|
+
class Unpublished < General
|
52
|
+
end
|
53
|
+
|
54
|
+
class Map < General
|
55
|
+
end
|
56
|
+
|
57
|
+
class Electronic_resource < General
|
58
|
+
end
|
59
|
+
|
60
|
+
class Software < Electronic_resource
|
61
|
+
end
|
62
|
+
|
63
|
+
class Webresource < Electronic_resource
|
64
|
+
end
|
65
|
+
|
66
|
+
class Website < Webresource
|
67
|
+
end
|
68
|
+
|
69
|
+
class Dataset < Electronic_resource
|
70
|
+
end
|
71
|
+
|
72
|
+
class Social_media < Electronic_resource
|
73
|
+
end
|
74
|
+
|
75
|
+
class Alert < Social_media
|
76
|
+
end
|
77
|
+
|
78
|
+
class Message < Social_media
|
79
|
+
end
|
80
|
+
|
81
|
+
class Audiovisual < General
|
82
|
+
end
|
83
|
+
|
84
|
+
class Film < Audiovisual
|
85
|
+
end
|
86
|
+
|
87
|
+
class Video < Audiovisual
|
88
|
+
end
|
89
|
+
|
90
|
+
class Broadcast < Audiovisual
|
91
|
+
end
|
92
|
+
|
93
|
+
class Graphic_work < General
|
94
|
+
end
|
95
|
+
|
96
|
+
class Music < General
|
97
|
+
end
|
98
|
+
|
99
|
+
class Patent < General
|
100
|
+
end
|
101
|
+
|
102
|
+
class Hosted < General
|
103
|
+
end
|
104
|
+
|
105
|
+
class Article < Hosted
|
106
|
+
end
|
107
|
+
|
108
|
+
class InBook < Hosted
|
109
|
+
end
|
110
|
+
|
111
|
+
class InCollection < Hosted
|
112
|
+
end
|
113
|
+
|
114
|
+
class InProceedings < Hosted
|
115
|
+
end
|
116
|
+
|
117
|
+
class Archival < General
|
118
|
+
end
|
119
|
+
|
120
|
+
class Conversation < General
|
121
|
+
end
|
122
|
+
|
123
|
+
class Misc < General
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module Relaton
|
2
|
+
module Render
|
3
|
+
class Fields
|
4
|
+
def initialize(options)
|
5
|
+
@r = options[:renderer]
|
6
|
+
end
|
7
|
+
|
8
|
+
def compound_fields_format(hash)
|
9
|
+
name_fields_format(hash)
|
10
|
+
role_fields_format(hash)
|
11
|
+
date_fields_format(hash)
|
12
|
+
misc_fields_format(hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
def name_fields_format(hash)
|
16
|
+
hash[:creatornames] = nameformat(hash[:creators])
|
17
|
+
hash[:host_creatornames] = nameformat(hash[:host_creators])
|
18
|
+
end
|
19
|
+
|
20
|
+
def role_fields_format(hash)
|
21
|
+
hash[:role] = role_inflect(hash[:creators], hash[:role_raw])
|
22
|
+
hash[:host_role] =
|
23
|
+
role_inflect(hash[:host_creators], hash[:host_role_raw])
|
24
|
+
end
|
25
|
+
|
26
|
+
def misc_fields_format(hash)
|
27
|
+
hash[:series] = seriesformat(hash)
|
28
|
+
hash[:edition] = editionformat(hash[:edition_raw])
|
29
|
+
hash[:extent] = extentformat(hash[:extent_raw], hash)
|
30
|
+
hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def date_fields_format(hash)
|
34
|
+
hash[:date] = dateformat(hash[:date], hash)
|
35
|
+
hash[:date_updated] = dateformat(hash[:date_updated], hash)
|
36
|
+
hash[:date_accessed] = dateformat(hash[:date_accessed], hash)
|
37
|
+
end
|
38
|
+
|
39
|
+
def seriesformat(hash)
|
40
|
+
parts = %i(series_title series_abbr series_num series_partnumber
|
41
|
+
series_run)
|
42
|
+
series_out = parts.each_with_object({}) do |i, m|
|
43
|
+
m[i] = hash[i]
|
44
|
+
end
|
45
|
+
t = hash[:type] == "article" ? @r.journaltemplate : @r.seriestemplate
|
46
|
+
t.render(series_out)
|
47
|
+
end
|
48
|
+
|
49
|
+
def nameformat(names)
|
50
|
+
return names if names.nil?
|
51
|
+
|
52
|
+
parts = %i(surname initials given middle)
|
53
|
+
names_out = names.each_with_object({}) do |n, m|
|
54
|
+
parts.each do |i|
|
55
|
+
m[i] ||= []
|
56
|
+
m[i] << n[i]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
@r.nametemplate.render(names_out)
|
60
|
+
end
|
61
|
+
|
62
|
+
def role_inflect(contribs, role)
|
63
|
+
return nil if role.nil? || contribs.size.zero?
|
64
|
+
|
65
|
+
number = contribs.size > 1 ? "pl" : "sg"
|
66
|
+
@r.i18n.get[role][number] || role
|
67
|
+
end
|
68
|
+
|
69
|
+
def editionformat(edn)
|
70
|
+
return edn unless /^\d+$/.match?(edn)
|
71
|
+
|
72
|
+
num = edn.to_i.localize(@r.lang.to_sym)
|
73
|
+
.to_rbnf_s(*@r.edition_number)
|
74
|
+
@r.edition.sub(/%/, num)
|
75
|
+
end
|
76
|
+
|
77
|
+
def extentformat(extent, hash)
|
78
|
+
extent.map do |e|
|
79
|
+
extent_out = e.merge(type: hash[:type],
|
80
|
+
host_title: hash[:host_title])
|
81
|
+
.transform_values do |v|
|
82
|
+
v.is_a?(Hash) ? range(v) : v
|
83
|
+
end
|
84
|
+
@r.extenttemplate.render(extent_out.merge(orig: e))
|
85
|
+
end.join("; ")
|
86
|
+
end
|
87
|
+
|
88
|
+
def range(hash)
|
89
|
+
if hash[:on] then hash[:on]
|
90
|
+
elsif hash.has_key?(:from) && hash[:from].nil? then nil
|
91
|
+
elsif hash[:from]
|
92
|
+
hash[:to] ? "#{hash[:from]}–#{hash[:to]}" : hash[:from]
|
93
|
+
else hash
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def date_range(hash)
|
98
|
+
if hash[:from]
|
99
|
+
"#{hash[:from]}–#{hash[:to]}"
|
100
|
+
else range(hash)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def dateformat(date, hash)
|
105
|
+
return nil if date.nil?
|
106
|
+
|
107
|
+
%i(from to on).each do |k|
|
108
|
+
date[k] = daterender(date[k], hash)
|
109
|
+
end
|
110
|
+
date_range(date)
|
111
|
+
end
|
112
|
+
|
113
|
+
def daterender(date, _hash)
|
114
|
+
return date if date.nil? || /^\d+$/.match?(date)
|
115
|
+
|
116
|
+
daterender1(date, dategranularity(date), hash)
|
117
|
+
end
|
118
|
+
|
119
|
+
def daterender1(date, format, _hash)
|
120
|
+
datef = dateparse(date, format, @r.lang.to_sym)
|
121
|
+
case @r.date[format]
|
122
|
+
when "to_full_s", "to_long_s", "to_medium_s", "to_short_s"
|
123
|
+
datef.send @r.date[format]
|
124
|
+
else
|
125
|
+
datef.to_additional_s(@r.date[format])
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def dategranularity(date)
|
132
|
+
case date
|
133
|
+
when /^\d+-\d+$/ then "month_year"
|
134
|
+
when /^\d+-\d+-\d+$/ then "day_month_year"
|
135
|
+
else "date_time"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def dateparse(date, format, lang)
|
140
|
+
case format
|
141
|
+
when "date_time" then DateTime.parse(date)
|
142
|
+
.localize(lang, timezone: "Zulu")
|
143
|
+
when "day_month_year" then DateTime.parse(date)
|
144
|
+
.localize(lang, timezone: "Zulu").to_date
|
145
|
+
when "month_year" then Date.parse(date)
|
146
|
+
.localize(lang, timezone: "Zulu").to_date
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|