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.
- checksums.yaml +4 -4
- data/Gemfile +15 -2
- data/lib/relaton/render/iso690/element.rb +43 -0
- data/lib/relaton/render/iso690/elements/component_part.rb +50 -0
- data/lib/relaton/render/iso690/elements/creator.rb +129 -0
- data/lib/relaton/render/iso690/elements/edition.rb +47 -0
- data/lib/relaton/render/iso690/elements/identifier.rb +32 -0
- data/lib/relaton/render/iso690/elements/location.rb +27 -0
- data/lib/relaton/render/iso690/elements/medium.rb +27 -0
- data/lib/relaton/render/iso690/elements/numeration.rb +26 -0
- data/lib/relaton/render/iso690/elements/production.rb +36 -0
- data/lib/relaton/render/iso690/elements/pub_date.rb +51 -0
- data/lib/relaton/render/iso690/elements/series.rb +40 -0
- data/lib/relaton/render/iso690/elements/title.rb +30 -0
- data/lib/relaton/render/iso690/elements.rb +40 -0
- data/lib/relaton/render/iso690/fields.rb +53 -0
- data/lib/relaton/render/iso690/i18n/en.yml +13 -0
- data/lib/relaton/render/iso690/i18n/fr.yml +14 -0
- data/lib/relaton/render/iso690/i18n.rb +53 -0
- data/lib/relaton/render/iso690/identifier_kinds.rb +34 -0
- data/lib/relaton/render/iso690/index_renderer.rb +57 -0
- data/lib/relaton/render/iso690/kinds.rb +43 -0
- data/lib/relaton/render/iso690/renderer.rb +52 -0
- data/lib/relaton/render/iso690/style/locale.rb +44 -0
- data/lib/relaton/render/iso690/style/name_form.rb +21 -0
- data/lib/relaton/render/iso690/style/scheme.rb +23 -0
- data/lib/relaton/render/iso690/style/sort_rule.rb +25 -0
- data/lib/relaton/render/iso690/style/template_map.rb +28 -0
- data/lib/relaton/render/iso690/style/type_template.rb +21 -0
- data/lib/relaton/render/iso690/style.rb +76 -0
- data/lib/relaton/render/iso690/styles/author-date.yml +28 -0
- data/lib/relaton/render/iso690/template.rb +72 -0
- data/lib/relaton/render/iso690.rb +22 -0
- data/lib/relaton/render/version.rb +1 -1
- data/lib/relaton-render.rb +3 -7
- data/relaton-render.gemspec +2 -19
- metadata +35 -249
- data/lib/relaton/render/fields/date.rb +0 -48
- data/lib/relaton/render/fields/fields.rb +0 -266
- data/lib/relaton/render/general/citations.rb +0 -178
- data/lib/relaton/render/general/config.yml +0 -129
- data/lib/relaton/render/general/render.rb +0 -316
- data/lib/relaton/render/general/render_classes.rb +0 -132
- data/lib/relaton/render/general/uri.rb +0 -57
- data/lib/relaton/render/i18n/i18n.rb +0 -40
- data/lib/relaton/render/parse/parse.rb +0 -152
- data/lib/relaton/render/parse/parse_contributors.rb +0 -184
- data/lib/relaton/render/parse/parse_extract.rb +0 -200
- data/lib/relaton/render/parse/parse_id.rb +0 -128
- data/lib/relaton/render/template/liquid.rb +0 -48
- data/lib/relaton/render/template/subclasses.rb +0 -123
- data/lib/relaton/render/template/template.rb +0 -228
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d8d567a54651ce75901eeb043077a17b840e9a9d9d00e95d3afcde793bfc6795
|
|
4
|
+
data.tar.gz: 3b6019abeef370c32db6e855238b4500c1be2a785eb726eb6577b6e454588d4b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c75141af4b07759f64a7c12ed491509ddfc2cd88595ea6484587a0bb753e333b633906188bf03e765912a06c4fd6e7a1812e0a886486c3c1b3f8435488f376b6
|
|
7
|
+
data.tar.gz: 2d8b040b077067944c76dd2149af2272bb536811fe228c940d91e5e79c0b42de0f3c4360b9586f0c6a369507eddf01e96246f334b169e4c1e2c5ea1df3507ee5
|
data/Gemfile
CHANGED
|
@@ -3,9 +3,22 @@ Encoding.default_internal = Encoding::UTF_8
|
|
|
3
3
|
|
|
4
4
|
source "https://rubygems.org"
|
|
5
5
|
|
|
6
|
-
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
|
6
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
7
7
|
|
|
8
8
|
gemspec
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
group :development, :test do
|
|
11
|
+
gem "canon"
|
|
12
|
+
gem "relaton", ">= 3.0.0.pre.alpha", "< 4" # the model fixtures; the engine itself is model-agnostic
|
|
13
|
+
gem "debug"
|
|
14
|
+
gem "iso-690-test-suite", github: "relaton/iso-690-test-suite"
|
|
15
|
+
gem "rake", ">= 12.3.3"
|
|
16
|
+
gem "rspec", "~> 3.0"
|
|
17
|
+
gem "simplecov"
|
|
18
|
+
end
|
|
11
19
|
|
|
20
|
+
begin
|
|
21
|
+
eval_gemfile("Gemfile.devel")
|
|
22
|
+
rescue StandardError
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
# Base data element (ISO 690 clause 7). An element wraps typed data
|
|
7
|
+
# taken from the relaton model instance; #present? is the omission
|
|
8
|
+
# predicate, #render the element's formatting method. Punctuation
|
|
9
|
+
# between elements belongs to the kind/style, not the element.
|
|
10
|
+
class Element
|
|
11
|
+
def initialize(model, style:, i18n:)
|
|
12
|
+
@model = model
|
|
13
|
+
@style = style
|
|
14
|
+
@i18n = i18n
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def present?
|
|
18
|
+
false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def render
|
|
22
|
+
nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def localized(value)
|
|
28
|
+
value&.content.to_s
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def contributors(role)
|
|
32
|
+
Array(@model.contributor).select { |c| has_role?(c, role) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def has_role?(contributor, role)
|
|
36
|
+
Array(contributor.role).any? do |r|
|
|
37
|
+
r.is_a?(String) ? r == role : r.type == role
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Component part within a host (ISO 690 clause 7.4): "In: host
|
|
8
|
+
# title, edition of host". Host data comes from the typed
|
|
9
|
+
# partOf relation.
|
|
10
|
+
class ComponentPart < Element
|
|
11
|
+
def present?
|
|
12
|
+
!host_title.empty?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def render
|
|
16
|
+
"#{@i18n.label('in')} " \
|
|
17
|
+
"#{@style.templates.title_open}#{host_title}" \
|
|
18
|
+
"#{@style.templates.title_close}" \
|
|
19
|
+
"#{host_edition}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def relation
|
|
25
|
+
Array(@model.relation).find { |r| r.type == "partOf" }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def host
|
|
29
|
+
relation&.bibitem
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def host_title
|
|
33
|
+
return localized(relation&.description) if host.nil?
|
|
34
|
+
|
|
35
|
+
Array(host.title).map { |t| localized(t) }.join(" ").strip
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def host_edition
|
|
39
|
+
return "" if host.nil?
|
|
40
|
+
|
|
41
|
+
edition = Edition.new(host, style: @style, i18n: @i18n)
|
|
42
|
+
return "" unless edition.present?
|
|
43
|
+
|
|
44
|
+
". #{edition.render}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Name(s) of creator(s) (ISO 690 clause 7.2). The first creator is
|
|
8
|
+
# given inverted per the style's name form (SURNAME, forenames),
|
|
9
|
+
# subsequent creators in direct order (forenames SURNAME); name
|
|
10
|
+
# parts come from the typed model, never decomposed from a
|
|
11
|
+
# rendered string.
|
|
12
|
+
class Creator < Element
|
|
13
|
+
def present?
|
|
14
|
+
!creators.empty?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def render
|
|
18
|
+
"#{join(names)}#{role_suffix}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# In-text (name-and-date) form: the principal creator only
|
|
22
|
+
def in_text
|
|
23
|
+
principal = creators.first or return ""
|
|
24
|
+
person = principal.person or return org_name(principal)
|
|
25
|
+
completename(person) || surname(person)&.upcase || ""
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The principal creator's given names, as the name form declares
|
|
29
|
+
def principal_given
|
|
30
|
+
principal = creators.first or return ""
|
|
31
|
+
person = principal.person or return ""
|
|
32
|
+
complete = completename(person)
|
|
33
|
+
return "" if complete
|
|
34
|
+
|
|
35
|
+
given_names(person)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def creators
|
|
41
|
+
@creators ||= begin
|
|
42
|
+
found = contributors("author")
|
|
43
|
+
found = contributors("editor") if found.empty?
|
|
44
|
+
found
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def names
|
|
49
|
+
creators.each_with_index
|
|
50
|
+
.map do |contributor, index|
|
|
51
|
+
format(contributor,
|
|
52
|
+
first: index.zero?)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def format(contributor, first:)
|
|
57
|
+
person = contributor.person or return org_name(contributor)
|
|
58
|
+
name = completename(person) ||
|
|
59
|
+
personal_name(person, first: first)
|
|
60
|
+
name.empty? ? org_name(contributor) : name
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def personal_name(person, first:)
|
|
64
|
+
surname = surname(person).to_s
|
|
65
|
+
given = given_names(person)
|
|
66
|
+
if first && !name_form.given_name_first
|
|
67
|
+
@style.render_name(surname: surname, given: given)
|
|
68
|
+
else
|
|
69
|
+
[given, surname.upcase].reject(&:empty?).join(" ")
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def name_form
|
|
74
|
+
@style.scheme.name_form
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def join(names)
|
|
78
|
+
case names.size
|
|
79
|
+
when 0 then ""
|
|
80
|
+
when 1 then names.first
|
|
81
|
+
when 2 then names.join(" #{@i18n.label('and')} ")
|
|
82
|
+
else
|
|
83
|
+
"#{names[0..-2].join(', ')}#{@i18n.label('oxford_comma')} " \
|
|
84
|
+
"#{@i18n.label('and')} #{names.last}"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def role_suffix
|
|
89
|
+
return "" unless editors?
|
|
90
|
+
|
|
91
|
+
suffix = creators.one? ? @i18n.label("ed") : @i18n.label("eds")
|
|
92
|
+
" (#{suffix})"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def editors?
|
|
96
|
+
!creators.empty? && creators.all? { |c| has_role?(c, "editor") }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def completename(person)
|
|
100
|
+
value = localized(person.name&.completename)
|
|
101
|
+
value.empty? ? nil : value
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def surname(person)
|
|
105
|
+
value = localized(person.name&.surname)
|
|
106
|
+
value.empty? ? nil : value
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def given_names(person)
|
|
110
|
+
names = Array(person.name&.forename).map { |f| localized(f) }
|
|
111
|
+
.reject(&:empty?)
|
|
112
|
+
return names.map { |n| "#{n[0]}." }.join(" ") if name_form.initials
|
|
113
|
+
|
|
114
|
+
names.join(" ")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def org_name(contributor)
|
|
118
|
+
name = Array(contributor.organization&.name)
|
|
119
|
+
.map { |n| localized(n).upcase }.join(", ")
|
|
120
|
+
abbrev = localized(contributor.organization&.abbreviation)
|
|
121
|
+
return name if name.empty? || abbrev.empty?
|
|
122
|
+
|
|
123
|
+
"#{name} (#{abbrev})"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Edition and version (ISO 690 clause 7.6). The model numbers the
|
|
8
|
+
# edition through Edition#number (falling back to its content).
|
|
9
|
+
class Edition < Element
|
|
10
|
+
def present?
|
|
11
|
+
!number.zero?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render
|
|
15
|
+
"#{ordinalize(number)} #{@i18n.label('edition')}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def number
|
|
21
|
+
raw = @model.edition&.number || @model.edition&.content
|
|
22
|
+
Integer(raw)
|
|
23
|
+
rescue ArgumentError, TypeError
|
|
24
|
+
0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ordinalize(num)
|
|
28
|
+
"#{num}#{ordinal_suffix(num)}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ordinal_suffix(num)
|
|
32
|
+
case num % 100
|
|
33
|
+
when 11, 12, 13 then "th"
|
|
34
|
+
else
|
|
35
|
+
case num % 10
|
|
36
|
+
when 1 then "st"
|
|
37
|
+
when 2 then "nd"
|
|
38
|
+
when 3 then "rd"
|
|
39
|
+
else "th"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Standard and persistent identifiers, rendered by kind
|
|
8
|
+
class Identifier < Element
|
|
9
|
+
INTERNAL_TYPES = %w[metanorma metanorma-ordinal metanorma-objid]
|
|
10
|
+
.freeze
|
|
11
|
+
|
|
12
|
+
def present?
|
|
13
|
+
!identifiers.empty?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def render
|
|
17
|
+
identifiers.map { |d| IdentifierKinds.render(d) }
|
|
18
|
+
.join(@i18n.punct_fetch("identifier_join", ". "))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def identifiers
|
|
24
|
+
Array(@model.docidentifier).reject do |d|
|
|
25
|
+
INTERNAL_TYPES.include?(d.type) || d.content.to_s.strip.empty?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Availability and location (ISO 690 clause 7.12): access location
|
|
8
|
+
# (URI) of the resource
|
|
9
|
+
class Location < Element
|
|
10
|
+
def present?
|
|
11
|
+
!uri.empty?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render
|
|
15
|
+
"#{@i18n.label('available_from')} #{uri}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def uri
|
|
21
|
+
Array(@model.accesslocation).reject(&:empty?).first.to_s
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Medium designation (ISO 690 clause 7.5), bracketed per the
|
|
8
|
+
# standard's worked examples, e.g. "[online]"
|
|
9
|
+
class Medium < Element
|
|
10
|
+
def present?
|
|
11
|
+
!medium.empty?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render
|
|
15
|
+
"[#{medium}]"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def medium
|
|
21
|
+
localized(@model.medium)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Numeration within a series (ISO 690 clause 7.9): report numbers
|
|
8
|
+
class Numeration < Element
|
|
9
|
+
def present?
|
|
10
|
+
!docnumber.to_s.empty?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render
|
|
14
|
+
"#{@i18n.label('report_no')} #{docnumber}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def docnumber
|
|
20
|
+
@model.docnumber
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Production information: place and publisher (ISO 690 clause 7.8).
|
|
8
|
+
# Place comes from the model's typed city; publishers from
|
|
9
|
+
# organization contributors.
|
|
10
|
+
class Production < Element
|
|
11
|
+
def present?
|
|
12
|
+
!places.empty? || !publishers.empty?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def render
|
|
16
|
+
[places.join("; "), publishers.join("; ")]
|
|
17
|
+
.reject(&:empty?).join(@i18n.punct_fetch("production_sep", ": "))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def places
|
|
23
|
+
Array(@model.place).map { |p| p.city.to_s }
|
|
24
|
+
.reject { |c| c.strip.empty? }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def publishers
|
|
28
|
+
contributors("publisher").map do |c|
|
|
29
|
+
Array(c.organization&.name).map { |n| localized(n) }.join(", ")
|
|
30
|
+
end.reject(&:empty?)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Date of publication (ISO 690 clause 7.7). The relaton model
|
|
8
|
+
# provides typed date values (StringDate::Value#to_date); years
|
|
9
|
+
# come from the model, never from string manipulation. A from/to
|
|
10
|
+
# pair renders as a range (closed or open).
|
|
11
|
+
class PubDate < Element
|
|
12
|
+
def present?
|
|
13
|
+
!render.nil?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def render
|
|
17
|
+
range || year&.to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def publication_date
|
|
23
|
+
Array(@model.date).find(&:published) ||
|
|
24
|
+
Array(@model.date).find { |d| d.type.nil? }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def publication_date_value
|
|
28
|
+
d = publication_date or return nil
|
|
29
|
+
d.from || d.at || d.to
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def range
|
|
33
|
+
d = publication_date or return nil
|
|
34
|
+
dash = @i18n.label("date_range")
|
|
35
|
+
if d.from && d.to
|
|
36
|
+
"#{d.from.to_date.year}#{dash}#{d.to.to_date.year}"
|
|
37
|
+
elsif d.from
|
|
38
|
+
"#{d.from.to_date.year}#{dash}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def year
|
|
43
|
+
publication_date_value.to_date.year
|
|
44
|
+
rescue ArgumentError, TypeError, NoMethodError
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Series title and number (ISO 690 clause 7.10)
|
|
8
|
+
class Series < Element
|
|
9
|
+
def present?
|
|
10
|
+
!series_title.empty?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render
|
|
14
|
+
base = "#{@style.templates.title_open}#{series_title}" \
|
|
15
|
+
"#{@style.templates.title_close}"
|
|
16
|
+
if number.empty?
|
|
17
|
+
base
|
|
18
|
+
else
|
|
19
|
+
"#{base}, #{@i18n.label('series_no')} #{number}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def series
|
|
26
|
+
Array(@model.series).first
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def series_title
|
|
30
|
+
Array(series&.title).map { |t| localized(t) }.join(" ").strip
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def number
|
|
34
|
+
series&.number.to_s
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Elements
|
|
7
|
+
# Title of the resource (ISO 690 clause 7.3), emphasised by the
|
|
8
|
+
# style's declared title markers
|
|
9
|
+
class Title < Element
|
|
10
|
+
def present?
|
|
11
|
+
!main_title.empty?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render
|
|
15
|
+
"#{@style.templates.title_open}#{main_title}" \
|
|
16
|
+
"#{@style.templates.title_close}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def main_title
|
|
22
|
+
t = Array(@model.title).find { |x| (x.type || "main") == "main" } ||
|
|
23
|
+
Array(@model.title).first
|
|
24
|
+
localized(t)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
# Element registry (ISO 690 clause 7 vocabulary)
|
|
7
|
+
module Elements
|
|
8
|
+
autoload :Creator, "relaton/render/iso690/elements/creator"
|
|
9
|
+
autoload :Title, "relaton/render/iso690/elements/title"
|
|
10
|
+
autoload :Edition, "relaton/render/iso690/elements/edition"
|
|
11
|
+
autoload :Medium, "relaton/render/iso690/elements/medium"
|
|
12
|
+
autoload :Series, "relaton/render/iso690/elements/series"
|
|
13
|
+
autoload :Production, "relaton/render/iso690/elements/production"
|
|
14
|
+
autoload :PubDate, "relaton/render/iso690/elements/pub_date"
|
|
15
|
+
autoload :Identifier, "relaton/render/iso690/elements/identifier"
|
|
16
|
+
autoload :Location, "relaton/render/iso690/elements/location"
|
|
17
|
+
autoload :Numeration, "relaton/render/iso690/elements/numeration"
|
|
18
|
+
autoload :ComponentPart, "relaton/render/iso690/elements/component_part"
|
|
19
|
+
|
|
20
|
+
CLASSES = {
|
|
21
|
+
creator: Creator,
|
|
22
|
+
title: Title,
|
|
23
|
+
edition: Edition,
|
|
24
|
+
medium: Medium,
|
|
25
|
+
series: Series,
|
|
26
|
+
production: Production,
|
|
27
|
+
date: PubDate,
|
|
28
|
+
identifier: Identifier,
|
|
29
|
+
location: Location,
|
|
30
|
+
numeration: Numeration,
|
|
31
|
+
component_part: ComponentPart,
|
|
32
|
+
}.freeze
|
|
33
|
+
|
|
34
|
+
def self.build(name, model, style:, i18n:)
|
|
35
|
+
CLASSES.fetch(name).new(model, style: style, i18n: i18n)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
# Field resolver: builds the template evaluator's field table from a
|
|
7
|
+
# relaton model instance. Slots resolve to ISO 690 clause 7 data
|
|
8
|
+
# elements, to name-form fields of the principal creator, or to the
|
|
9
|
+
# disambiguator supplied by the citation caller.
|
|
10
|
+
class Fields
|
|
11
|
+
ELEMENT_SLOTS = %i[
|
|
12
|
+
creator title edition medium series production
|
|
13
|
+
date numeration component_part identifier location
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
16
|
+
def initialize(model, style:, i18n:, disambiguator: nil)
|
|
17
|
+
@model = model
|
|
18
|
+
@style = style
|
|
19
|
+
@i18n = i18n
|
|
20
|
+
@disambiguator = disambiguator.to_s
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_h
|
|
24
|
+
table = {}
|
|
25
|
+
ELEMENT_SLOTS.each do |slot|
|
|
26
|
+
key = slot.to_s.delete("_").downcase
|
|
27
|
+
table[key] = element_field(slot)
|
|
28
|
+
end
|
|
29
|
+
table.merge(name_fields)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def element_field(slot)
|
|
35
|
+
element = Elements.build(slot, @model, style: @style, i18n: @i18n)
|
|
36
|
+
text = element.render.to_s
|
|
37
|
+
Template::Field[element.present? && !text.empty?, text]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def name_fields
|
|
41
|
+
creator = Elements.build(:creator, @model, style: @style, i18n: @i18n)
|
|
42
|
+
{
|
|
43
|
+
"surname" => Template::Field[creator.present?, creator.in_text],
|
|
44
|
+
"givennames" => Template::Field[!creator.principal_given.empty?,
|
|
45
|
+
creator.principal_given],
|
|
46
|
+
"disambiguator" => Template::Field[!@disambiguator.empty?,
|
|
47
|
+
@disambiguator],
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|