relaton-render 3.0.0.pre.alpha.18 → 3.0.0.pre.alpha.20

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: 366d6cbb3430291c42f1c8b836002276120a5f0f8abfc9d3d7a1591b9818d9b9
4
- data.tar.gz: 3e785f025a4d72001ba9e496321c78826b8a689b21a71419f76d59c5ae596ec0
3
+ metadata.gz: f5eb2f65434b6e8671e8050f7c6bab11ebba834e4139563ee32b501cc3a370a4
4
+ data.tar.gz: 918148498a5f6fbba2d4e45102c49b0625a6ab28dc4826376e9649ceb1101e17
5
5
  SHA512:
6
- metadata.gz: 659c808e1247309ee2255bd7932aa55d0b43a95996812af583d454225066a5f0e12829b96765da631c370c6baebb9baf9be067655e87e3c9000a8b737b582859
7
- data.tar.gz: d920c054fdaf325061155b411a5dc9834f8970c900e658b3d0b5d37d655e1ff8541cc360c3872f8fb8dcac26c6eb2de3428862817eaaba243a118f1ba80ae12a
6
+ metadata.gz: 7b1cc9b2c76c9397c32cc3cc3a77b2bc5e455d9d7012f503de94e7937c4174006a39391cfd3fe9ea2190682f8c1bf441a5ddfc2d2c1c15c5b973f9b14722b784
7
+ data.tar.gz: e9ac5313838027bffd9ca98bd2650e067ec4fc5d8bbf1d9dda5b3219b32173afced90b585a4566c8b1fb83b2a337ba4ad94170d4736d21cba1700c97e9364c17
@@ -32,9 +32,24 @@ module Relaton
32
32
  # A flavor names its own CitationStyle instance (name or YAML path)
33
33
  options[:style] and renderer_opts[:style] = options[:style]
34
34
  @renderer = Iso690::Renderer.new(**renderer_opts)
35
+ @renderer_opts = renderer_opts
36
+ @renderers_by_lang = {}
35
37
  warn_general_config if options[:config]
36
38
  end
37
39
 
40
+ # A collection's items may each declare their own language; the
41
+ # renderer localizes by language, so a reference renders in its
42
+ # own language within a document of another (the 1.x plateau
43
+ # per-reference behaviour)
44
+ def renderer_for(lang)
45
+ return @renderer if lang.nil? || lang == @lang
46
+
47
+ @renderers_by_lang[lang] ||= Iso690::Renderer.new(
48
+ **@renderer_opts.merge(lang: lang,
49
+ script: %w(ja ko zh).include?(lang) ? nil : "Latn")
50
+ )
51
+ end
52
+
38
53
  def render(model, embedded: false, **opts)
39
54
  model = to_model(model)
40
55
  text =
@@ -57,15 +72,20 @@ module Relaton
57
72
  items = facade_bibitems(bib) or return nil
58
73
  disambiguators = date_disambiguators(items)
59
74
  items.each_with_object({}).with_index do |(item, m), i|
75
+ renderer = renderer_for(Array(item.language).first)
60
76
  ref = begin
61
- @renderer.render(item, disambiguator: disambiguators[item.id])
77
+ renderer.render(item, disambiguator: disambiguators[item.id])
62
78
  rescue ::Relaton::Render::Unrenderable
63
79
  next
64
80
  end
65
81
  m[item.id] = {
66
82
  id: item.id, ord: i,
83
+ author: renderer.in_text_author(item),
67
84
  formattedref: terminate_reference(ref, item),
68
- citation: citation_renderings(item, ref),
85
+ citation: citation_renderings(item, ref, renderer,
86
+ type: type,
87
+ disambiguator:
88
+ disambiguators[item.id]),
69
89
  }
70
90
  end
71
91
  end
@@ -116,10 +136,14 @@ module Relaton
116
136
  "#{ref}."
117
137
  end
118
138
 
119
- def citation_renderings(item, ref)
120
- short = @renderer.citation(item)
139
+ # The style-keyed capsule ("citation" => { author_date: "..." })
140
+ # is what isodoc's styled erefs consume (their style attribute
141
+ # names the key)
142
+ def citation_renderings(item, ref, renderer, type: "author-date",
143
+ disambiguator: nil)
144
+ short = renderer.citation(item)
121
145
  short = if short.empty?
122
- @renderer.render_short(item, FIRST_DELIM)
146
+ renderer.render_short(item, FIRST_DELIM)
123
147
  else
124
148
  short
125
149
  end
@@ -128,6 +152,11 @@ module Relaton
128
152
  full: ref,
129
153
  default: item.docidentifier.first&.content.to_s,
130
154
  short: short,
155
+ author_date: renderer.author_date_citation(
156
+ item, disambiguator: disambiguator,
157
+ ),
158
+ author: renderer.in_text_author(item),
159
+ title: renderer.title_citation(item),
131
160
  }
132
161
  end
133
162
 
@@ -73,14 +73,37 @@ module Relaton
73
73
  # at the style's et-al threshold the cite truncates
74
74
  # ("Aluffi <em>et al.</em>")
75
75
  def in_text
76
- principal = creators.first or return ""
77
- person = principal.person or return org_name(principal)
78
- raw = surname(person).to_s
79
- surname = name_form.surname_upcase ? raw.upcase : raw
80
- name = completename(person) || surname || ""
76
+ return in_text_etal if in_text_etal?
77
+
78
+ name = creators.first ? in_text_name(creators.first) : ""
81
79
  etal? ? "#{name} <em>et al.</em>" : name
82
80
  end
83
81
 
82
+ # The in-text cite truncates at its own threshold: at
83
+ # inTextEtalCount creators it shows the first
84
+ # inTextEtalDisplay surnames ("Aluffi <em>et al.</em>")
85
+ def in_text_etal
86
+ names = creators.first(name_form.in_text_etal_display)
87
+ .map { |c| in_text_name(c) }
88
+ "#{join(names)} <em>et al.</em>"
89
+ end
90
+
91
+ # The in-text cite names by surname alone (the 1.x
92
+ # authorcitetemplate), never by initials
93
+ def in_text_name(contributor)
94
+ person = contributor.person or return org_name(contributor)
95
+ complete = completename(person)
96
+ return complete unless complete.nil?
97
+
98
+ raw = surname(person).to_s
99
+ name_form.surname_upcase ? raw.upcase : raw
100
+ end
101
+
102
+ def in_text_etal?
103
+ count = name_form.in_text_etal_count
104
+ count.positive? && creators.size >= count
105
+ end
106
+
84
107
  def etal?
85
108
  count = name_form.etal_count
86
109
  count.positive? && creators.size >= count
@@ -11,6 +11,12 @@ module Relaton
11
11
  !main_title.empty?
12
12
  end
13
13
 
14
+ # The citation capsule's plain title (the 1.x citetemplate's
15
+ # "{{ title }}"): the same resolution, no style markers
16
+ def plain
17
+ main_title
18
+ end
19
+
14
20
  def render
15
21
  text = main_title
16
22
  return text if analytic? && @short
@@ -82,6 +82,23 @@ module Relaton
82
82
  elements: @elements).in_text
83
83
  end
84
84
 
85
+ # The author-date in-text capsule ("Aluffi <em>et al.</em>
86
+ # 2022a"): the in-text creator and the disambiguated date
87
+ def author_date_citation(model, disambiguator: nil)
88
+ f = Fields.new(model, style: @style, i18n: @i18n,
89
+ disambiguator: disambiguator,
90
+ elements: @elements).to_h
91
+ [in_text_author(model), f["disambiguateddate"].text]
92
+ .reject(&:empty?).join(" ")
93
+ end
94
+
95
+ # The title citation ("{{ title }}" in the 1.x citetemplate):
96
+ # the title element's plain form, no style markers
97
+ def title_citation(model)
98
+ Elements.build(:title, model, style: @style, i18n: @i18n,
99
+ elements: @elements).plain
100
+ end
101
+
85
102
  # The in-text author key (the principal creator's surname, as
86
103
  # the citation renders it): the batch disambiguation groups by
87
104
  # it
@@ -46,6 +46,13 @@ module Relaton
46
46
  # first etalDisplay names with "et al." (0 disables)
47
47
  attribute :etal_count, :integer, default: 0
48
48
  attribute :etal_display, :integer, default: 0
49
+ # The in-text cite truncates separately from the creator
50
+ # list: at this many creators it shows the first
51
+ # inTextEtalDisplay names with "et al." (0 disables; IEEE
52
+ # cites 3+ as "Aluffi et al." while listing 6 in the
53
+ # bibliography)
54
+ attribute :in_text_etal_count, :integer, default: 0
55
+ attribute :in_text_etal_display, :integer, default: 1
49
56
  # Editor lists carry the role marker ("(Eds.)")
50
57
  attribute :editors_marked, :boolean, default: -> { true }
51
58
 
@@ -65,6 +72,8 @@ module Relaton
65
72
  map "subsequentSurnameUpcase", to: :subsequent_surname_upcase
66
73
  map "etalCount", to: :etal_count
67
74
  map "etalDisplay", to: :etal_display
75
+ map "inTextEtalCount", to: :in_text_etal_count
76
+ map "inTextEtalDisplay", to: :in_text_etal_display
68
77
  map "editorsMarked", to: :editors_marked
69
78
  end
70
79
  end
@@ -9,6 +9,9 @@ scheme:
9
9
  nameForm:
10
10
  initials: false
11
11
  givenNameFirst: false
12
+ # ISO 690 marks an editor list's role ("(éd.)") also when the list
13
+ # holds a single editor; flavors opt out per their own style
14
+ loneEditorMarked: true
12
15
  templates:
13
16
  titleOpen: "_"
14
17
  titleClose: "_"
@@ -102,15 +102,25 @@ module Relaton
102
102
  end
103
103
  end
104
104
 
105
- # A literal bridges two present elements when at least one
106
- # present element stands on each side of it; a leading literal
107
- # (no slot precedes it) attaches to the first slot, emitting
108
- # only when that slot is present
105
+ # A literal is the trailing separator of the element that
106
+ # precedes it: it renders when that element renders and a
107
+ # later element renders, and it is the FIRST literal of its
108
+ # gap (the 1.x segment join — absent elements between two
109
+ # present ones leave the single separator that follows the
110
+ # earlier present element; an absent slot directly before a
111
+ # present one, as "{{date}}{{disambiguator}}, {{access}}",
112
+ # does not swallow it). A leading literal (no slot precedes
113
+ # it) attaches to the first slot, emitting only when that
114
+ # slot is present.
109
115
  def bridged?(index, present)
110
116
  first_slot = @chunks.index { |(kind, _)| kind == :slot }
111
117
  return present.include?(first_slot) if index < first_slot
112
118
 
113
- present.any? { |i| i < index } && present.any? { |i| i > index }
119
+ left = present.select { |i| i < index }.max
120
+ left && present.any? { |i| i > index } &&
121
+ !@chunks[(left + 1)...index].any? do |(kind, _)|
122
+ kind == :text
123
+ end
114
124
  end
115
125
 
116
126
  # A template's paired literal ("({{production}})") closes even
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Render
3
- VERSION = "3.0.0.pre.alpha.18".freeze
3
+ VERSION = "3.0.0.pre.alpha.20".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.18
4
+ version: 3.0.0.pre.alpha.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.