relaton-render 1.2.2 → 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/.github/workflows/rake.yml +6 -1
- data/.github/workflows/release.yml +1 -1
- data/.rubocop.yml +2 -2
- data/Gemfile +15 -2
- data/lib/isodoc-yaml/i18n-ar.yaml +8 -2
- data/lib/isodoc-yaml/i18n-de.yaml +8 -2
- data/lib/isodoc-yaml/i18n-en.yaml +8 -2
- data/lib/isodoc-yaml/i18n-es.yaml +8 -2
- data/lib/isodoc-yaml/i18n-fr.yaml +8 -2
- data/lib/isodoc-yaml/i18n-ja.yaml +13 -7
- data/lib/isodoc-yaml/i18n-ru.yaml +8 -2
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +8 -2
- data/lib/isodoc-yaml/i18n-zh-Hant.yaml +8 -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
|
@@ -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
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Relaton
|
|
6
|
+
module Render
|
|
7
|
+
module Iso690
|
|
8
|
+
# Language-specific labels and typographic punctuation, declared per
|
|
9
|
+
# language in i18n/<lang>.yml. Adding a language adds a YAML
|
|
10
|
+
# declaration — no code. A style instance's localized strings overlay
|
|
11
|
+
# the language pack; language-varying intra-element punctuation
|
|
12
|
+
# (e.g. French " : " production separator) is declared under
|
|
13
|
+
# `punct:`.
|
|
14
|
+
class I18n < Lutaml::Model::Serializable
|
|
15
|
+
attribute :lang, :string, default: "en"
|
|
16
|
+
attribute :labels, :hash, default: {}
|
|
17
|
+
attribute :punct, :hash, default: {}
|
|
18
|
+
|
|
19
|
+
key_value do
|
|
20
|
+
map "lang", to: :lang
|
|
21
|
+
map "labels", to: :labels
|
|
22
|
+
map "punct", to: :punct
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def label(key)
|
|
26
|
+
labels.fetch(key.to_s, key.to_s)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def punct_fetch(key, default)
|
|
30
|
+
punct.fetch(key, default)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Style-instance localized strings win over the language pack.
|
|
34
|
+
def overlay!(locale)
|
|
35
|
+
labels.merge!(locale.label_map)
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class << self
|
|
40
|
+
def load(lang = "en")
|
|
41
|
+
code = lang.to_s.empty? ? "en" : lang
|
|
42
|
+
path = File.join(__dir__, "i18n", "#{code}.yml")
|
|
43
|
+
unless File.file?(path)
|
|
44
|
+
raise ArgumentError, "no i18n declarations for language #{code}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
from_yaml(File.read(path))
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
# Standard and persistent identifiers (ISO 690 clause 7.11): each
|
|
7
|
+
# identifier kind carries its own rendering method. Kinds are keyed by
|
|
8
|
+
# the docidentifier's type attribute — never guessed from content.
|
|
9
|
+
# Flavors register additional kinds (e.g. Pubid::Iala's MRN).
|
|
10
|
+
module IdentifierKinds
|
|
11
|
+
KINDS = {
|
|
12
|
+
"DOI" => ->(content) { "https://doi.org/#{content}" },
|
|
13
|
+
"ISBN" => ->(content) { "ISBN #{content}" },
|
|
14
|
+
"ISSN" => ->(content) { "ISSN #{content}" },
|
|
15
|
+
"URN" => ->(content) { content },
|
|
16
|
+
"MRN" => ->(content) { content },
|
|
17
|
+
}.freeze
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
def register(type, kind)
|
|
21
|
+
KINDS[type] = kind
|
|
22
|
+
kind
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def render(docidentifier)
|
|
26
|
+
content = docidentifier.content.to_s
|
|
27
|
+
kind = KINDS[docidentifier.type]
|
|
28
|
+
kind ? kind.call(content) : content
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
# A bibliographic index: the ordered reference list, laid out per the
|
|
7
|
+
# BibliographicStyle instance. Sorting follows the style's declared
|
|
8
|
+
# sortKey rules (creator, then date); numbering is layout data.
|
|
9
|
+
class IndexRenderer
|
|
10
|
+
def initialize(style: "author-date", lang: "en", script: "Latn")
|
|
11
|
+
@style = Style.load(style)
|
|
12
|
+
@i18n = I18n.load(lang).overlay!(@style.scheme.locale)
|
|
13
|
+
@renderer = Renderer.new(style: style, lang: lang, script: script)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# The reference strings, sorted per the style's sortKey rules.
|
|
17
|
+
def references(models)
|
|
18
|
+
sort_rules = @style.sort_keys
|
|
19
|
+
fields = models.to_h { |m| [m, field_table(m)] }
|
|
20
|
+
models.sort do |a, b|
|
|
21
|
+
fa = fields[a]
|
|
22
|
+
fb = fields[b]
|
|
23
|
+
sort_rules.each do |rule|
|
|
24
|
+
cmp = key_of(fa, rule) <=> key_of(fb, rule)
|
|
25
|
+
next if cmp.zero?
|
|
26
|
+
|
|
27
|
+
break(rule.descending? ? -cmp : cmp)
|
|
28
|
+
end || 0
|
|
29
|
+
end.map { |model| @renderer.render(model) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The laid-out index: numbered entries per the layout rules
|
|
33
|
+
# (arabic by default; "none" renders bare references).
|
|
34
|
+
def render(models, numbering: "arabic")
|
|
35
|
+
refs = references(models)
|
|
36
|
+
return refs if numbering == "none"
|
|
37
|
+
|
|
38
|
+
refs.each_with_index.map { |ref, i| "#{i + 1}. #{ref}" }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def field_table(model)
|
|
44
|
+
Fields.new(model, style: @style, i18n: @i18n).to_h
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def key_of(fields, rule)
|
|
48
|
+
field = fields[rule.attribute.to_s.delete("_").downcase]
|
|
49
|
+
return "" if field.nil?
|
|
50
|
+
|
|
51
|
+
text = field.respond_to?(:text) ? field.text : field.to_s
|
|
52
|
+
text.downcase
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
# The vocabulary mapping from a bibliographic item's wire type value
|
|
7
|
+
# to its ISO 690 clause 8 resource kind (TemplateType). This table is
|
|
8
|
+
# the engine's charter — style instances select perType templates on
|
|
9
|
+
# kinds and never enumerate type synonyms. Unmapped values fall to
|
|
10
|
+
# the report kind (clause 8.11), the runner's fallback.
|
|
11
|
+
module Kinds
|
|
12
|
+
TO_KIND = {
|
|
13
|
+
"book" => "monograph",
|
|
14
|
+
"booklet" => "monograph",
|
|
15
|
+
"manual" => "monograph",
|
|
16
|
+
"proceedings" => "monograph",
|
|
17
|
+
"thesis" => "monograph",
|
|
18
|
+
"standard" => "report",
|
|
19
|
+
"techreport" => "report",
|
|
20
|
+
"report" => "report",
|
|
21
|
+
"patent" => "patent",
|
|
22
|
+
"journal" => "continuing",
|
|
23
|
+
"serial" => "continuing",
|
|
24
|
+
"article-journal" => "continuing",
|
|
25
|
+
"article-magazine" => "continuing",
|
|
26
|
+
"inbook" => "component_part",
|
|
27
|
+
"incollection" => "component_part",
|
|
28
|
+
"inproceedings" => "component_part",
|
|
29
|
+
"website" => "online",
|
|
30
|
+
"webresource" => "online",
|
|
31
|
+
"webpage" => "online",
|
|
32
|
+
"online" => "online",
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
DEFAULT_KIND = "report"
|
|
36
|
+
|
|
37
|
+
def self.kind_for(type)
|
|
38
|
+
TO_KIND.fetch(type.to_s, DEFAULT_KIND)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
# Public API: relaton model in, citation string out. The style
|
|
7
|
+
# instance supplies every rendering decision; this class only wires
|
|
8
|
+
# the template evaluator to the field resolver. No XML, no
|
|
9
|
+
# intermediate hashes.
|
|
10
|
+
class Renderer
|
|
11
|
+
class Unrenderable < StandardError; end
|
|
12
|
+
|
|
13
|
+
DEFAULT_STYLE = "author-date"
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
def render(model, style: DEFAULT_STYLE, lang: "en", script: "Latn")
|
|
17
|
+
new(style: style, lang: lang, script: script).render(model)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def citation(model, disambiguator: nil, style: DEFAULT_STYLE,
|
|
21
|
+
lang: "en", script: "Latn")
|
|
22
|
+
new(style: style, lang: lang, script: script)
|
|
23
|
+
.citation(model, disambiguator: disambiguator)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def initialize(style: DEFAULT_STYLE, lang: "en", script: "Latn")
|
|
28
|
+
@style = Style.load(style)
|
|
29
|
+
@i18n = I18n.load(lang).overlay!(@style.scheme.locale)
|
|
30
|
+
@script = script
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def render(model)
|
|
34
|
+
out = Template.new(@style.template_for(Kinds.kind_for(model.type))).evaluate(
|
|
35
|
+
Fields.new(model, style: @style, i18n: @i18n).to_h,
|
|
36
|
+
)
|
|
37
|
+
raise Unrenderable, "no renderable elements" if out.strip.empty?
|
|
38
|
+
|
|
39
|
+
out
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# In-text form: SURNAME, year + disambiguator (name-and-date)
|
|
43
|
+
def citation(model, disambiguator: nil)
|
|
44
|
+
Template.new(@style.templates.citation).evaluate(
|
|
45
|
+
Fields.new(model, style: @style, i18n: @i18n,
|
|
46
|
+
disambiguator: disambiguator).to_h,
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
class Style
|
|
7
|
+
# LocalizedStrings: per-style overrides of the language pack's
|
|
8
|
+
# connective strings, keyed as in the CitationStyle model.
|
|
9
|
+
class Locale < Lutaml::Model::Serializable
|
|
10
|
+
attribute :conj, :string
|
|
11
|
+
attribute :others, :string
|
|
12
|
+
attribute :no_date, :string
|
|
13
|
+
attribute :no_author, :string
|
|
14
|
+
attribute :in_str, :string
|
|
15
|
+
attribute :at, :string
|
|
16
|
+
attribute :available_at, :string
|
|
17
|
+
|
|
18
|
+
key_value do
|
|
19
|
+
map "and", to: :conj
|
|
20
|
+
map "others", to: :others
|
|
21
|
+
map "noDate", to: :no_date
|
|
22
|
+
map "noAuthor", to: :no_author
|
|
23
|
+
map "in", to: :in_str
|
|
24
|
+
map "at", to: :at
|
|
25
|
+
map "availableAt", to: :available_at
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
LABEL_FOR = {
|
|
29
|
+
"conj" => "and", "others" => "others", "no_date" => "no_date",
|
|
30
|
+
"no_author" => "no_author", "in_str" => "in", "at" => "at",
|
|
31
|
+
"available_at" => "available_from",
|
|
32
|
+
}.freeze
|
|
33
|
+
|
|
34
|
+
def label_map
|
|
35
|
+
LABEL_FOR.filter_map do |attr, label|
|
|
36
|
+
value = public_send(attr)
|
|
37
|
+
[label, value] unless value.nil?
|
|
38
|
+
end.to_h
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
class Style
|
|
7
|
+
# How personal names are formed, as declared by the style's
|
|
8
|
+
# citation scheme (relaton-models NameFormRules).
|
|
9
|
+
class NameForm < Lutaml::Model::Serializable
|
|
10
|
+
attribute :initials, :boolean, default: -> { false }
|
|
11
|
+
attribute :given_name_first, :boolean, default: -> { false }
|
|
12
|
+
|
|
13
|
+
key_value do
|
|
14
|
+
map "initials", to: :initials
|
|
15
|
+
map "givenNameFirst", to: :given_name_first
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
class Style
|
|
7
|
+
# CitationScheme: the citation system, its name form and its
|
|
8
|
+
# localized strings (relaton-models CitationScheme).
|
|
9
|
+
class Scheme < Lutaml::Model::Serializable
|
|
10
|
+
attribute :system, :string, default: "name-date"
|
|
11
|
+
attribute :name_form, NameForm, default: -> { NameForm.new }
|
|
12
|
+
attribute :locale, Locale, default: -> { Locale.new }
|
|
13
|
+
|
|
14
|
+
key_value do
|
|
15
|
+
map "system", to: :system
|
|
16
|
+
map "nameForm", to: :name_form
|
|
17
|
+
map "locale", to: :locale
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
class Style
|
|
7
|
+
# SortRule: one ordering key of a bibliographic index sort
|
|
8
|
+
# (relaton-models SortRule).
|
|
9
|
+
class SortRule < Lutaml::Model::Serializable
|
|
10
|
+
attribute :attribute, :string
|
|
11
|
+
attribute :order, :string
|
|
12
|
+
|
|
13
|
+
key_value do
|
|
14
|
+
map "attribute", to: :attribute
|
|
15
|
+
map "order", to: :order
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def descending?
|
|
19
|
+
order == "descending"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
class Style
|
|
7
|
+
# TemplateMap: citation and reference templates as data, plus the
|
|
8
|
+
# title emphasis markers and the first-creator name form. Slots
|
|
9
|
+
# name ISO 690 clause 7 data elements or name-form fields.
|
|
10
|
+
class TemplateMap < Lutaml::Model::Serializable
|
|
11
|
+
attribute :title_open, :string, default: "_"
|
|
12
|
+
attribute :title_close, :string, default: "_"
|
|
13
|
+
attribute :citation, :string, default: "{{surname}}, {{date}}"
|
|
14
|
+
attribute :reference, :string
|
|
15
|
+
attribute :name, :string, default: "{{surname}}, {{givenNames}}"
|
|
16
|
+
|
|
17
|
+
key_value do
|
|
18
|
+
map "titleOpen", to: :title_open
|
|
19
|
+
map "titleClose", to: :title_close
|
|
20
|
+
map "citation", to: :citation
|
|
21
|
+
map "reference", to: :reference
|
|
22
|
+
map "name", to: :name
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
class Style
|
|
7
|
+
# TypeTemplate: the template variant for one bibliographic item
|
|
8
|
+
# type, selected by data lookup (relaton-models TypeTemplate).
|
|
9
|
+
class TypeTemplate < Lutaml::Model::Serializable
|
|
10
|
+
attribute :type, :string
|
|
11
|
+
attribute :template, :string
|
|
12
|
+
|
|
13
|
+
key_value do
|
|
14
|
+
map "type", to: :type
|
|
15
|
+
map "template", to: :template
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|