relaton-render 3.0.0.pre.alpha.4 → 3.0.0.pre.alpha.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee63b0602a2be7f4c00c3d0fee7795387cac5b695037ffec618271b380ce6098
4
- data.tar.gz: 1bd28b75e32a979ba82cedc675851d61c26769010c62823a85180a5c8236a8a5
3
+ metadata.gz: 6e6e4911053aee3915882fcee48c182f8bf0d1ca2c879e7201bb0d19cfd48e4b
4
+ data.tar.gz: 60b845d08886130df02eaef46bfe5811996f208aaab13093fb660221f5f50799
5
5
  SHA512:
6
- metadata.gz: '070696e6d0f15855bb40365c0e5953f05a80ea0fc0b453b2c1b62da371d9bfa0459c9d7e593ba79add4227c4ecc97af247561cd78345d835a5262f9be30ee651'
7
- data.tar.gz: 660e8b5815000dd129e2893f39584d64999eda4d863c704ba9a4ee1e8cda9d68bdefbdfb8675a2aea25309a649709d7fa24458e5682c27c5932344cbe5e8ceed
6
+ metadata.gz: 855419eacf8dc6f71a4c9eaef6b23341328bee50a1a59b0c2138d62420b3295d59176a83d3cac5c52a0c2cb989558ebced170badaf8732f04449fb5a5047cc6d
7
+ data.tar.gz: 38ace39e42d57252a8eb994cc4ec4a82ea56a5bd6476025db679b6b4a42c6c676b77908d6d076f06442e30768bb406104e284daed8e85dd73dfbb8f7c66aa7fc
@@ -29,6 +29,14 @@ module Relaton
29
29
  value&.content.to_s
30
30
  end
31
31
 
32
+ # Localizable values scoped to the render language: the variants
33
+ # declared in that language, or all of them when none matches
34
+ def titles_in_lang(values)
35
+ titles = Array(values)
36
+ in_lang = titles.select { |t| Array(t.language).include?(@i18n.lang) }
37
+ in_lang.empty? ? titles : in_lang
38
+ end
39
+
32
40
  def contributors(role)
33
41
  Array(@model.contributor).select { |c| has_role?(c, role) }
34
42
  end
@@ -68,12 +76,20 @@ module Relaton
68
76
 
69
77
  ""
70
78
  end.reject(&:empty?)
71
- return localized(person.name&.formatted_initials) if parts.empty?
72
- return parts.map { |p| "#{p[0]}." }.join(" ") if initials?
79
+ sep = @style.scheme.name_form.initials_separator.to_s
80
+ return reinitials(localized(person.name&.formatted_initials),
81
+ sep) if parts.empty?
82
+ return parts.map { |p| "#{p[0]}." }.join(sep) if initials?
73
83
 
74
84
  parts.join(" ")
75
85
  end
76
86
 
87
+ # Declared initials are a list in string form; rejoin them with
88
+ # the style's separator
89
+ def reinitials(raw, sep)
90
+ raw.split(/\s+/).reject(&:empty?).join(sep)
91
+ end
92
+
77
93
  def initials?
78
94
  @style.scheme.name_form.initials
79
95
  end
@@ -40,7 +40,8 @@ module Relaton
40
40
  def host_title_text
41
41
  return localized(relation&.description) if host.nil?
42
42
 
43
- Array(host.title).map { |t| localized(t) }.join(" ").strip
43
+ titles_in_lang(host.title).map { |t| localized(t) }
44
+ .join(" ").strip
44
45
  end
45
46
 
46
47
  def host_title
@@ -68,7 +69,9 @@ module Relaton
68
69
 
69
70
  surname = person_surname(person)
70
71
  given = person_given(person)
71
- if first
72
+ if @style.scheme.name_form.inverted_all
73
+ @style.render_name(surname: surname, given: given)
74
+ elsif first
72
75
  [surname, given].reject(&:empty?).join(", ")
73
76
  else
74
77
  [given, surname].reject(&:empty?).join(" ")
@@ -15,19 +15,26 @@ module Relaton
15
15
  end
16
16
 
17
17
  def render
18
+ joined = if (form = @style.templates.creators) && !form.empty?
19
+ ::Relaton::Render::Iso690::Template.new(form).evaluate(
20
+ "names" => Template::Field[true, join(names)],
21
+ )
22
+ else
23
+ join(names)
24
+ end
18
25
  case role_placement
19
26
  when "afterPeriod"
20
27
  # the in-slot trailing space separates the (eds.) marker
21
28
  # from the next element, which follows directly in the
22
29
  # template; a lone editor is unmarked
23
30
  if editors? && creators.size > 1
24
- "#{period(join(names))} (#{role_word}) "
31
+ "#{period(joined)} (#{role_word}) "
25
32
  else
26
- "#{period(join(names))} "
33
+ "#{period(joined)} "
27
34
  end
28
35
  else
29
36
  marker = editors? && creators.size > 1 ? " (#{role_word})" : ''
30
- "#{join(names)}#{marker}"
37
+ "#{joined}#{marker}"
31
38
  end
32
39
  end
33
40
 
@@ -96,7 +103,7 @@ module Relaton
96
103
  def personal_name(person, first:)
97
104
  surname = surname(person).to_s
98
105
  given = given_names(person)
99
- if first && !name_form.given_name_first
106
+ if (first || name_form.inverted_all) && !name_form.given_name_first
100
107
  @style.render_name(surname: surname, given: given)
101
108
  else
102
109
  [given, surname.upcase].reject(&:empty?).join(" ")
@@ -108,9 +115,21 @@ module Relaton
108
115
  end
109
116
 
110
117
  def join(names)
118
+ oxford = @i18n.label("oxford_comma")
119
+ if serial_list? && names.size > 1 && !oxford.empty?
120
+ return "#{names[0..-2].join(', ')}#{oxford} " \
121
+ "#{@i18n.label('and')} #{names.last}"
122
+ end
123
+
111
124
  join_names(names)
112
125
  end
113
126
 
127
+ # Serial list style: every gap takes the serial form, even
128
+ # between two names
129
+ def serial_list?
130
+ @style.scheme.name_form.list_style == "serial"
131
+ end
132
+
114
133
  def editors?
115
134
  !creators.empty? && creators.all? { |c| has_role?(c, "editor") }
116
135
  end
@@ -13,10 +13,17 @@ module Relaton
13
13
  end
14
14
 
15
15
  def render
16
- [places.join("; "), publishers.join("; ")]
16
+ [place_text, publishers.join("; ")]
17
17
  .reject(&:empty?).join(@i18n.punct_fetch("production_sep", ": "))
18
18
  end
19
19
 
20
+ def place_text
21
+ return places.join("; ") unless places.empty?
22
+
23
+ label = @i18n.label("no_place")
24
+ label == "no_place" ? "" : label
25
+ end
26
+
20
27
  private
21
28
 
22
29
  def places
@@ -36,7 +36,8 @@ module Relaton
36
36
  end
37
37
 
38
38
  def series_title
39
- Array(series&.title).map { |t| localized(t) }.join(" ").strip
39
+ titles_in_lang(series&.title).map { |t| localized(t) }
40
+ .join(" ").strip
40
41
  end
41
42
 
42
43
  def number
@@ -33,10 +33,14 @@ module Relaton
33
33
  .include?(Kinds.kind_for(@model.type))
34
34
  end
35
35
 
36
+ # A typed main title wins; an untyped title is main by
37
+ # default, but yields to a typed one
36
38
  def main_title
37
- t = Array(@model.title).find { |x| (x.type || "main") == "main" } ||
38
- Array(@model.title).first
39
- localized(t)
39
+ titles = Array(@model.title)
40
+ mains = titles.select { |x| x.type == "main" }
41
+ mains = titles.select { |x| x.type.nil? } if mains.empty?
42
+ mains = titles if mains.empty?
43
+ localized(titles_in_lang(mains).first)
40
44
  end
41
45
  end
42
46
  end
@@ -35,7 +35,18 @@ module Relaton
35
35
  def element_field(slot)
36
36
  element = Elements.build(slot, @model, style: @style, i18n: @i18n)
37
37
  text = element.render.to_s
38
- Template::Field[element.present? && !text.empty?, text]
38
+ if element.present? && !text.empty?
39
+ return Template::Field[true, text]
40
+ end
41
+
42
+ fallback = @style.fallback_for(item_kind, slot)
43
+ return Template::Field[true, fallback] if fallback
44
+
45
+ Template::Field[false, ""]
46
+ end
47
+
48
+ def item_kind
49
+ Kinds.kind_for(@model.type)
39
50
  end
40
51
 
41
52
  def name_fields
@@ -16,15 +16,19 @@ module Relaton
16
16
  "MRN" => ->(content) { content },
17
17
  }.freeze
18
18
 
19
+ # Flavor-registered kinds, consulted before the built-ins; the
20
+ # registry is process-wide by design
21
+ OVERRIDES = {}
22
+
19
23
  class << self
20
24
  def register(type, kind)
21
- KINDS[type] = kind
25
+ OVERRIDES[type] = kind
22
26
  kind
23
27
  end
24
28
 
25
29
  def render(docidentifier)
26
30
  content = docidentifier.content.to_s
27
- kind = KINDS[docidentifier.type]
31
+ kind = OVERRIDES[docidentifier.type] || KINDS[docidentifier.type]
28
32
  kind ? kind.call(content) : content
29
33
  end
30
34
  end
@@ -43,9 +43,10 @@ module Relaton
43
43
  end
44
44
 
45
45
  def home_docid?(model)
46
- type = @style.scheme.home_docid_type
47
- !type.nil? && !type.empty? &&
48
- Array(model.docidentifier).any? { |d| d.type == type }
46
+ types = Array(@style.scheme.home_docid_type)
47
+ return false if types.empty?
48
+
49
+ Array(model.docidentifier).any? { |d| types.include?(d.type) }
49
50
  end
50
51
 
51
52
  # In-text form: SURNAME, year + disambiguator (name-and-date)
@@ -17,12 +17,27 @@ module Relaton
17
17
  # A completename is rendered, not decomposed; styles that
18
18
  # upcase inverted names may declare the completename treatment
19
19
  attribute :completename_upcase, :boolean, default: -> { false }
20
+ # Every personal name takes the inverted form (surname first),
21
+ # not just the principal creator
22
+ attribute :inverted_all, :boolean, default: -> { false }
23
+ # "serial": the oxford comma appears at every gap of the
24
+ # creator list, including between two names
25
+ attribute :list_style, :string, default: ""
26
+ # The inverted form's surname casing: the name-date convention
27
+ # upcases; small-cap styles keep the declared case
28
+ attribute :surname_upcase, :boolean, default: -> { true }
29
+ # Initials are a list; this separates them ("J. K." vs "J.K.")
30
+ attribute :initials_separator, :string, default: " "
20
31
 
21
32
  key_value do
22
33
  map "initials", to: :initials
23
34
  map "givenNameFirst", to: :given_name_first
24
35
  map "rolePlacement", to: :role_placement
25
36
  map "completenameUpcase", to: :completename_upcase
37
+ map "invertedAll", to: :inverted_all
38
+ map "listStyle", to: :list_style
39
+ map "surnameUpcase", to: :surname_upcase
40
+ map "initialsSeparator", to: :initials_separator
26
41
  end
27
42
  end
28
43
  end
@@ -10,7 +10,7 @@ module Relaton
10
10
  attribute :system, :string, default: "name-date"
11
11
  attribute :name_form, NameForm, default: -> { NameForm.new }
12
12
  attribute :locale, Locale, default: -> { Locale.new }
13
- attribute :home_docid_type, :string
13
+ attribute :home_docid_type, :string, collection: true
14
14
 
15
15
  key_value do
16
16
  map "system", to: :system
@@ -15,6 +15,7 @@ module Relaton
15
15
  attribute :name, :string, default: "{{surname}}, {{givenNames}}"
16
16
  attribute :series, :string, default: ""
17
17
  attribute :uri, :string, default: ""
18
+ attribute :creators, :string, default: ""
18
19
 
19
20
  key_value do
20
21
  map "titleOpen", to: :title_open
@@ -24,6 +25,7 @@ module Relaton
24
25
  map "name", to: :name
25
26
  map "series", to: :series
26
27
  map "uri", to: :uri
28
+ map "creators", to: :creators
27
29
  end
28
30
  end
29
31
  end
@@ -12,6 +12,7 @@ module Relaton
12
12
  attribute :series, :string
13
13
  attribute :title, :string
14
14
  attribute :home, :boolean
15
+ attribute :fallbacks, :hash, default: -> { {} }
15
16
 
16
17
  key_value do
17
18
  map "type", to: :type
@@ -19,6 +20,7 @@ module Relaton
19
20
  map "series", to: :series
20
21
  map "title", to: :title
21
22
  map "home", to: :home
23
+ map "fallbacks", to: :fallbacks
22
24
  end
23
25
  end
24
26
  end
@@ -52,6 +52,15 @@ module Relaton
52
52
  candidates.first&.template || templates.reference
53
53
  end
54
54
 
55
+ def type_template_for(type)
56
+ per_type.find { |t| t.type == type.to_s }
57
+ end
58
+
59
+ # The absent-slot replacement text declared for a type, when any
60
+ def fallback_for(type, slot)
61
+ type_template_for(type)&.fallbacks&.[](slot.to_s)
62
+ end
63
+
55
64
  def title_form_for(type)
56
65
  per_type.lazy.select { |t| t.type == type.to_s }
57
66
  .find { |t| t.title && !t.title.empty? }&.title
@@ -60,8 +69,9 @@ module Relaton
60
69
  # First-creator name form: the style's declared name template with
61
70
  # the surname upcased, per the name-and-date convention.
62
71
  def render_name(surname:, given:)
72
+ shown = scheme.name_form.surname_upcase ? surname.upcase : surname
63
73
  Template.new(templates.name).evaluate(
64
- "surname" => Template::Field[!surname.empty?, surname.upcase],
74
+ "surname" => Template::Field[!shown.empty?, shown],
65
75
  "givennames" => Template::Field[!given.empty?, given],
66
76
  )
67
77
  end
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Render
3
- VERSION = "3.0.0.pre.alpha.4".freeze
3
+ VERSION = "3.0.0.pre.alpha.6".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-render
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre.alpha.4
4
+ version: 3.0.0.pre.alpha.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.