relaton-render 0.4.2 → 3.0.0.pre.alpha.26
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 +24 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +2 -2
- data/Gemfile +17 -1
- data/README.adoc +13 -258
- data/docs/citation-style-pack.adoc +370 -0
- data/lib/relaton/render/general.rb +305 -0
- data/lib/relaton/render/iso690/element.rb +153 -0
- data/lib/relaton/render/iso690/elements/access.rb +44 -0
- data/lib/relaton/render/iso690/elements/authorizer.rb +30 -0
- data/lib/relaton/render/iso690/elements/citeid.rb +39 -0
- data/lib/relaton/render/iso690/elements/component_part.rb +99 -0
- data/lib/relaton/render/iso690/elements/creator.rb +258 -0
- data/lib/relaton/render/iso690/elements/edition.rb +92 -0
- data/lib/relaton/render/iso690/elements/extent.rb +71 -0
- data/lib/relaton/render/iso690/elements/identifier.rb +46 -0
- data/lib/relaton/render/iso690/elements/location.rb +73 -0
- data/lib/relaton/render/iso690/elements/medium.rb +32 -0
- data/lib/relaton/render/iso690/elements/numeration.rb +26 -0
- data/lib/relaton/render/iso690/elements/production.rb +92 -0
- data/lib/relaton/render/iso690/elements/pub_date.rb +56 -0
- data/lib/relaton/render/iso690/elements/series.rb +66 -0
- data/lib/relaton/render/iso690/elements/size.rb +41 -0
- data/lib/relaton/render/iso690/elements/status.rb +30 -0
- data/lib/relaton/render/iso690/elements/stddoc.rb +40 -0
- data/lib/relaton/render/iso690/elements/title.rb +56 -0
- data/lib/relaton/render/iso690/elements/updated.rb +38 -0
- data/lib/relaton/render/iso690/elements.rb +67 -0
- data/lib/relaton/render/iso690/fields.rb +142 -0
- data/lib/relaton/render/iso690/i18n/en.yml +47 -0
- data/lib/relaton/render/iso690/i18n/fr.yml +14 -0
- data/lib/relaton/render/iso690/i18n/ja.yml +38 -0
- data/lib/relaton/render/iso690/i18n.rb +83 -0
- data/lib/relaton/render/iso690/identifier_kinds.rb +29 -0
- data/lib/relaton/render/iso690/index_renderer.rb +57 -0
- data/lib/relaton/render/iso690/kinds.rb +53 -0
- data/lib/relaton/render/iso690/renderer.rb +148 -0
- data/lib/relaton/render/iso690/rules.rb +36 -0
- data/lib/relaton/render/iso690/style/locale.rb +53 -0
- data/lib/relaton/render/iso690/style/name_form.rb +87 -0
- data/lib/relaton/render/iso690/style/scheme.rb +33 -0
- data/lib/relaton/render/iso690/style/sort_rule.rb +25 -0
- data/lib/relaton/render/iso690/style/template_map.rb +40 -0
- data/lib/relaton/render/iso690/style/type_template.rb +37 -0
- data/lib/relaton/render/iso690/style.rb +222 -0
- data/lib/relaton/render/iso690/styles/apa.yml +45 -0
- data/lib/relaton/render/iso690/styles/author-date.yml +31 -0
- data/lib/relaton/render/iso690/styles/chicago.yml +48 -0
- data/lib/relaton/render/iso690/styles/ieee-sa.yml +45 -0
- data/lib/relaton/render/iso690/styles/lncs.yml +54 -0
- data/lib/relaton/render/iso690/template.rb +248 -0
- data/lib/relaton/render/iso690.rb +27 -0
- data/lib/relaton/render/version.rb +1 -1
- data/lib/relaton-render.rb +11 -5
- data/relaton-render.gemspec +6 -13
- metadata +61 -116
- data/lib/isodoc/i18n.rb +0 -33
- data/lib/isodoc-yaml/i18n-ar.yaml +0 -44
- data/lib/isodoc-yaml/i18n-de.yaml +0 -43
- data/lib/isodoc-yaml/i18n-en.yaml +0 -40
- data/lib/isodoc-yaml/i18n-es.yaml +0 -47
- data/lib/isodoc-yaml/i18n-fr.yaml +0 -48
- data/lib/isodoc-yaml/i18n-ru.yaml +0 -51
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +0 -40
- data/lib/relaton/render/fields/date.rb +0 -45
- data/lib/relaton/render/fields/fields.rb +0 -245
- data/lib/relaton/render/general/citations.rb +0 -96
- data/lib/relaton/render/general/config.yml +0 -79
- data/lib/relaton/render/general/render.rb +0 -185
- data/lib/relaton/render/general/render_classes.rb +0 -129
- data/lib/relaton/render/parse/parse.rb +0 -64
- data/lib/relaton/render/parse/parse_contributors.rb +0 -132
- data/lib/relaton/render/parse/parse_extract.rb +0 -180
- data/lib/relaton/render/template/liquid.rb +0 -15
- data/lib/relaton/render/template/template.rb +0 -188
- data/lib/relaton/render/utils/utils.rb +0 -27
|
@@ -1,129 +0,0 @@
|
|
|
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 internal).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
|
-
|
|
126
|
-
class Internal < General
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
end
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
require "nokogiri"
|
|
2
|
-
require "twitter_cldr"
|
|
3
|
-
require_relative "parse_contributors"
|
|
4
|
-
require_relative "parse_extract"
|
|
5
|
-
|
|
6
|
-
module Relaton
|
|
7
|
-
module Render
|
|
8
|
-
class Parse
|
|
9
|
-
def initialize(options)
|
|
10
|
-
@lang = options[:lang] || "en"
|
|
11
|
-
@script = options[:script] || "Latn"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def extract(doc)
|
|
15
|
-
host = host(doc)
|
|
16
|
-
simple_xml2hash(doc).merge(simple_or_host_xml2hash(doc, host))
|
|
17
|
-
.merge(host_xml2hash(host))
|
|
18
|
-
.merge(series_xml2hash(doc, host))
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def simple_xml2hash(doc)
|
|
22
|
-
creators, role = creatornames(doc)
|
|
23
|
-
{ type: type(doc), title: title(doc), extent_raw: extent(doc),
|
|
24
|
-
size_raw: size(doc),
|
|
25
|
-
standardidentifier: standardidentifier(doc), uri_raw: uri(doc),
|
|
26
|
-
status: status(doc), creators: creators, role_raw: role }
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def simple_or_host_xml2hash(doc, host)
|
|
30
|
-
{ edition_raw: edition(doc, host), edition_num: edition_num(doc, host),
|
|
31
|
-
medium_raw: medium(doc, host),
|
|
32
|
-
place_raw: place(doc, host), publisher_raw: publisher(doc, host),
|
|
33
|
-
publisher_abbrev_raw: publisher_abbrev(doc, host),
|
|
34
|
-
distributor_raw: distributor(doc, host), draft_raw: draft(doc, host),
|
|
35
|
-
access_location: access_location(doc, host),
|
|
36
|
-
date: date(doc, host), date_updated: date_updated(doc, host),
|
|
37
|
-
date_accessed: date_accessed(doc, host) }
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def host_xml2hash(host)
|
|
41
|
-
creators, role = creatornames(host)
|
|
42
|
-
{ host_creators: creators, host_role_raw: role,
|
|
43
|
-
host_title: title(host) }
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def series_xml2hash(doc, host)
|
|
47
|
-
series = series(doc)
|
|
48
|
-
host and series ||= series(host)
|
|
49
|
-
series_xml2hash1(series, doc)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def series_xml2hash1(series, doc)
|
|
53
|
-
return {} unless series
|
|
54
|
-
|
|
55
|
-
{ series_formatted: series_formatted(series, doc),
|
|
56
|
-
series_title: series_title(series, doc),
|
|
57
|
-
series_abbr: series_abbr(series, doc),
|
|
58
|
-
series_run: series_run(series, doc),
|
|
59
|
-
series_num: series_num(series, doc),
|
|
60
|
-
series_partnumber: series_partnumber(series, doc) }
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
module Relaton
|
|
2
|
-
module Render
|
|
3
|
-
class Parse
|
|
4
|
-
def extract_orgname(org)
|
|
5
|
-
org.name&.first&.content
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def extract_personname(person)
|
|
9
|
-
surname = person.name.surname || person.name.completename
|
|
10
|
-
given, middle, initials = given_and_middle_name(person)
|
|
11
|
-
{ surname: surname.content,
|
|
12
|
-
given: given,
|
|
13
|
-
middle: middle,
|
|
14
|
-
initials: initials }
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def given_and_middle_name(person)
|
|
18
|
-
forenames = person.name.forename.map(&:content)
|
|
19
|
-
initials = person.name.initial.map(&:content)
|
|
20
|
-
.map { |x| x.sub(/\.$/, "") }
|
|
21
|
-
forenames.empty? and initials.empty? and return [nil, nil, nil]
|
|
22
|
-
initials.empty? and initials = forenames.map { |x| x[0] }
|
|
23
|
-
[forenames.first, forenames[1..-1], initials]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def extractname(contributor)
|
|
27
|
-
org = contributor.entity if contributor.entity
|
|
28
|
-
.is_a?(RelatonBib::Organization)
|
|
29
|
-
person = contributor.entity if contributor.entity
|
|
30
|
-
.is_a?(RelatonBib::Person)
|
|
31
|
-
return { nonpersonal: extract_orgname(org) } if org
|
|
32
|
-
return extract_personname(person) if person
|
|
33
|
-
|
|
34
|
-
nil
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def contributor_role(contributors)
|
|
38
|
-
return nil unless contributors.length.positive?
|
|
39
|
-
|
|
40
|
-
desc = contributors[0].role.first.description.join("\n")
|
|
41
|
-
type = contributors[0].role.first.type
|
|
42
|
-
desc.empty? ? type : desc
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def creatornames(doc)
|
|
46
|
-
cr = creatornames1(doc)
|
|
47
|
-
cr.empty? and return [nil, nil]
|
|
48
|
-
[cr.map { |x| extractname(x) }, contributor_role(cr)]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def creatornames_roles_allowed
|
|
52
|
-
%w(author performer adapter translator editor publisher distributor)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def creatornames1(doc)
|
|
56
|
-
cr = []
|
|
57
|
-
return [] if doc.nil?
|
|
58
|
-
|
|
59
|
-
creatornames_roles_allowed.each do |r|
|
|
60
|
-
add = pick_contributor(doc, r)
|
|
61
|
-
next if add.nil?
|
|
62
|
-
|
|
63
|
-
cr = add and break
|
|
64
|
-
end
|
|
65
|
-
cr.nil? and cr = doc.contributor
|
|
66
|
-
cr
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def datepick(date)
|
|
70
|
-
return nil if date.nil?
|
|
71
|
-
|
|
72
|
-
on = date.on
|
|
73
|
-
from = date.from
|
|
74
|
-
to = date.to
|
|
75
|
-
return { on: on } if on
|
|
76
|
-
return { from: from, to: to } if from
|
|
77
|
-
|
|
78
|
-
nil
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def date1(date)
|
|
82
|
-
%w(published issued circulated).each do |t|
|
|
83
|
-
ret = date.detect { |x| x.type == t } and
|
|
84
|
-
return ret
|
|
85
|
-
end
|
|
86
|
-
date.first
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def date(doc, host)
|
|
90
|
-
ret = date1(doc.date)
|
|
91
|
-
host and ret ||= date1(host.date)
|
|
92
|
-
datepick(ret)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def date_updated(doc, host)
|
|
96
|
-
ret = doc.date.detect { |x| x.type == "updated" }
|
|
97
|
-
host and ret ||= host.date.detect { |x| x.type == "updated" }
|
|
98
|
-
datepick(ret)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def date_accessed(doc, host)
|
|
102
|
-
ret = doc.date.detect { |x| x.type == "accessed" }
|
|
103
|
-
host and ret ||= host.date.detect { |x| x.type == "accessed" }
|
|
104
|
-
datepick(ret)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def publisher(doc, host)
|
|
108
|
-
x = pick_contributor(doc, "publisher")
|
|
109
|
-
host and x ||= pick_contributor(host, "publisher")
|
|
110
|
-
x.nil? and return nil
|
|
111
|
-
x.map { |c| extractname(c) }
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def publisher_abbrev(doc, host)
|
|
115
|
-
x = pick_contributor(doc, "publisher")
|
|
116
|
-
host and x ||= pick_contributor(host, "publisher")
|
|
117
|
-
x.nil? and return nil
|
|
118
|
-
x.map do |c|
|
|
119
|
-
c.entity.abbreviation&.content ||
|
|
120
|
-
c.entity.name.first&.content
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def distributor(doc, host)
|
|
125
|
-
x = pick_contributor(doc, "distributor")
|
|
126
|
-
host and x ||= pick_contributor(host, "distributor")
|
|
127
|
-
x.nil? and return nil
|
|
128
|
-
x.map { |c| extractname(c) }
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
module Relaton
|
|
2
|
-
module Render
|
|
3
|
-
class Parse
|
|
4
|
-
def host(doc)
|
|
5
|
-
doc.relation.detect { |r| r.type == "includedIn" }&.bibitem
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
# TODO : first is naive choice
|
|
9
|
-
def title(doc)
|
|
10
|
-
return nil if doc.nil? || doc.title.empty?
|
|
11
|
-
|
|
12
|
-
t = doc.title.select { |x| x.title.language&.include? @lang }
|
|
13
|
-
t.empty? and t = doc.title
|
|
14
|
-
t1 = t.select { |x| x.type == "main" }
|
|
15
|
-
t1.empty? and t1 = t
|
|
16
|
-
t1.first&.title&.content
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def medium(doc, host)
|
|
20
|
-
x = doc.medium || host&.medium or return nil
|
|
21
|
-
|
|
22
|
-
%w(content genre form carrier size scale).each_with_object({}) do |i, m|
|
|
23
|
-
m[i] = x.send i
|
|
24
|
-
end.compact
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def size(doc)
|
|
28
|
-
x = doc.size or return nil
|
|
29
|
-
x.size.each_with_object({}) do |v, m|
|
|
30
|
-
m[v.type] ||= []
|
|
31
|
-
m[v.type] << v.value
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def edition(doc, host)
|
|
36
|
-
doc.edition&.content || host&.edition&.content
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def edition_num(doc, host)
|
|
40
|
-
doc.edition&.number || host&.edition&.number
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def place(doc, host)
|
|
44
|
-
x = doc.place
|
|
45
|
-
x.empty? && host and x = host.place
|
|
46
|
-
x.empty? and return x
|
|
47
|
-
x.map(&:name)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def series(doc)
|
|
51
|
-
doc.series.detect { |s| s.type == "main" } ||
|
|
52
|
-
doc.series.detect { |s| s.type.nil? } ||
|
|
53
|
-
doc.series.first
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def series_title(series, _doc)
|
|
57
|
-
return nil if series.nil?
|
|
58
|
-
|
|
59
|
-
series.title.respond_to?(:titles) and
|
|
60
|
-
return series.title.titles.first.title.content
|
|
61
|
-
series.title&.title&.content || series.formattedref&.content
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def series_formatted(series, _doc)
|
|
65
|
-
series.formattedref&.content
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def series_abbr(series, _doc)
|
|
69
|
-
series.abbreviation&.content
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def series_num(series, _doc)
|
|
73
|
-
series.number
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def series_partnumber(series, _doc)
|
|
77
|
-
series.partnumber
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def series_run(series, _doc)
|
|
81
|
-
series.run
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def standardidentifier(doc)
|
|
85
|
-
doc.docidentifier.each_with_object([]) do |id, ret|
|
|
86
|
-
ret << id.id unless standardidentifier_exclude.include? id.type
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def standardidentifier_exclude
|
|
91
|
-
%w(metanorma metanorma-ordinal)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def uri(doc)
|
|
95
|
-
uri = nil
|
|
96
|
-
%w(doi uri src).each do |t|
|
|
97
|
-
uri = doc.link.detect { |u| u.type == t } and break
|
|
98
|
-
end
|
|
99
|
-
uri ||= doc.link.first
|
|
100
|
-
return nil unless uri
|
|
101
|
-
|
|
102
|
-
uri.content.to_s
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def access_location(doc, host)
|
|
106
|
-
x = doc.accesslocation || host&.accesslocation or
|
|
107
|
-
return nil
|
|
108
|
-
x.first
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def included(type)
|
|
112
|
-
["article", "inbook", "incollection", "inproceedings"].include? type
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def type(doc)
|
|
116
|
-
type = doc.type and return type
|
|
117
|
-
doc.relation.any? { |r| r.type == "includedIn" } and return "inbook"
|
|
118
|
-
"book"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def extent1(localities)
|
|
122
|
-
localities.each_with_object({}) do |l, ret|
|
|
123
|
-
ret[(l.type || "page").to_sym] = {
|
|
124
|
-
from: localized_string_or_text(l.reference_from),
|
|
125
|
-
to: localized_string_or_text(l.reference_to),
|
|
126
|
-
}
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def extent(doc)
|
|
131
|
-
doc.extent.each_with_object([]) do |e, acc|
|
|
132
|
-
case e
|
|
133
|
-
when RelatonBib::LocalityStack
|
|
134
|
-
acc << extent1(e.locality)
|
|
135
|
-
when RelatonBib::Locality
|
|
136
|
-
acc << extent1(Array(e))
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def draft(doc, host)
|
|
142
|
-
dr = doc.status&.stage&.value || host&.status&.stage&.value
|
|
143
|
-
|
|
144
|
-
{ iteration: iter_ordinal(doc) || iter_ordinal(host), status: dr }
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def iter_ordinal(doc)
|
|
148
|
-
return nil unless iter = doc&.status&.iteration
|
|
149
|
-
|
|
150
|
-
iter
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def status(doc)
|
|
154
|
-
doc.status&.stage&.value
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
private
|
|
158
|
-
|
|
159
|
-
def blank?(text)
|
|
160
|
-
text.nil? || text.empty?
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
def pick_contributor(doc, role)
|
|
164
|
-
ret = doc.contributor.select do |c|
|
|
165
|
-
c.role.any? { |r| r.type == role }
|
|
166
|
-
end
|
|
167
|
-
ret.empty? ? nil : ret
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def localized_string_or_text(str)
|
|
171
|
-
case str
|
|
172
|
-
when RelatonBib::LocalizedString
|
|
173
|
-
str.content
|
|
174
|
-
when String
|
|
175
|
-
str
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
end
|
|
179
|
-
end
|
|
180
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
module Relaton
|
|
2
|
-
module Render
|
|
3
|
-
module Template
|
|
4
|
-
module CapitalizeFirst
|
|
5
|
-
def capitalize_first(words)
|
|
6
|
-
return nil if words.nil?
|
|
7
|
-
|
|
8
|
-
ret = words.split(/[ _]/)
|
|
9
|
-
ret.first.capitalize! if ret.size.positive?
|
|
10
|
-
ret.join("_")
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
require_relative "../utils/utils"
|
|
2
|
-
require_relative "liquid"
|
|
3
|
-
|
|
4
|
-
module Relaton
|
|
5
|
-
module Render
|
|
6
|
-
module Template
|
|
7
|
-
class General
|
|
8
|
-
def initialize(opt = {})
|
|
9
|
-
@htmlentities = HTMLEntities.new
|
|
10
|
-
customise_liquid
|
|
11
|
-
parse_options(opt)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def parse_options(opt)
|
|
15
|
-
opt = Utils::sym_keys(opt)
|
|
16
|
-
@i18n = opt[:i18n]
|
|
17
|
-
@template_raw = opt[:template].dup
|
|
18
|
-
@template =
|
|
19
|
-
case opt[:template]
|
|
20
|
-
when Hash
|
|
21
|
-
opt[:template].transform_values { |x| template_process(x) }
|
|
22
|
-
when Array then opt[:template].map { |x| template_process(x) }
|
|
23
|
-
else { default: template_process(opt[:template]) }
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def customise_liquid
|
|
28
|
-
::Liquid::Template
|
|
29
|
-
.register_filter(::Relaton::Render::Template::CapitalizeFirst)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# denote start and end of field,
|
|
33
|
-
# so that we can detect empty fields in postprocessing
|
|
34
|
-
FIELD_DELIM = "\u0018".freeze
|
|
35
|
-
|
|
36
|
-
# escape < >
|
|
37
|
-
LT_DELIM = "\u0019".freeze
|
|
38
|
-
GT_DELIM = "\u001a".freeze
|
|
39
|
-
|
|
40
|
-
# use tab internally for non-spacing delimiter
|
|
41
|
-
NON_SPACING_DELIM = "\t".freeze
|
|
42
|
-
|
|
43
|
-
def template_process(template)
|
|
44
|
-
t = template.gsub(/\{\{/, "#{FIELD_DELIM}{{")
|
|
45
|
-
.gsub(/\}\}/, "}}#{FIELD_DELIM}")
|
|
46
|
-
.gsub(/\t/, " ")
|
|
47
|
-
t1 = t.split(/(\{\{.+?\}\})/).map do |n|
|
|
48
|
-
n.include?("{{") ? n : n.gsub(/(?<!\\)\|/, "\t")
|
|
49
|
-
end.join
|
|
50
|
-
::Liquid::Template.parse(t1)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def render(hash)
|
|
54
|
-
t = template_select(hash) or return nil
|
|
55
|
-
|
|
56
|
-
template_clean(t.render(liquid_hash(hash.merge("labels" => @i18n.get))))
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def template_select(_hash)
|
|
60
|
-
@template[:default]
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def template_clean(str)
|
|
64
|
-
str = str.gsub(/</i, LT_DELIM).gsub(/>/i, GT_DELIM)
|
|
65
|
-
str = template_clean1(@htmlentities.decode(str))
|
|
66
|
-
/[[:alnum:]]/.match?(str) or return nil
|
|
67
|
-
str.strip.gsub(/#{LT_DELIM}/o, "<")
|
|
68
|
-
.gsub(/#{GT_DELIM}/o, ">")
|
|
69
|
-
.gsub(/&(?!#\S+?;)/, "&")
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# use tab internally for non-spacing delimiter
|
|
73
|
-
def template_clean1(str)
|
|
74
|
-
str.gsub(/\S*#{FIELD_DELIM}#{FIELD_DELIM}\S*/o, "")
|
|
75
|
-
.gsub(/#{FIELD_DELIM}/o, "")
|
|
76
|
-
.gsub(/([,:;]\s*)+([,:;](\s|$))/, "\\2")
|
|
77
|
-
.gsub(/([,.:;]\s*)+([.](\s|$))/, "\\2")
|
|
78
|
-
.gsub(/([,:;]\s*)+(,(\s|$))/, "\\2")
|
|
79
|
-
.gsub(/(:\s+)(&\s)/, "\\2")
|
|
80
|
-
.gsub(/\s+([,.:;)])/, "\\1")
|
|
81
|
-
.sub(/^\s*[,.:;]\s*/, "")
|
|
82
|
-
.sub(/[,:;]\s*$/, "")
|
|
83
|
-
.gsub(/(?<!\\)_/, " ")
|
|
84
|
-
.gsub(/\\_/, "_")
|
|
85
|
-
.gsub(/#{NON_SPACING_DELIM}/o, "").gsub(/\s+/, " ")
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# need non-breaking spaces in fields: "Updated:_nil" ---
|
|
89
|
-
# we want the "Updated:" deleted,
|
|
90
|
-
# even if it's multiple words, as in French Mise_à_jour.
|
|
91
|
-
def liquid_hash(hash)
|
|
92
|
-
case hash
|
|
93
|
-
when Hash
|
|
94
|
-
hash.map { |k, v| [k.to_s, liquid_hash(v)] }.to_h
|
|
95
|
-
when Array
|
|
96
|
-
hash.map { |v| liquid_hash(v) }
|
|
97
|
-
when String
|
|
98
|
-
hash.empty? ? nil : hash.gsub(/ /, "_")
|
|
99
|
-
else hash
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
class Series < General
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
class Extent < General
|
|
108
|
-
def template_select(hash)
|
|
109
|
-
@template[hash[:type].to_sym]
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
class Size < General
|
|
114
|
-
def template_select(hash)
|
|
115
|
-
@template[hash[:type].to_sym]
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
class Name < General
|
|
120
|
-
def initialize(opt = {})
|
|
121
|
-
@etal_count = opt[:template]["etal_count"]
|
|
122
|
-
opt[:template].delete("etal_count")
|
|
123
|
-
super
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def template_select(names)
|
|
127
|
-
return nil if names.nil? || names.empty?
|
|
128
|
-
|
|
129
|
-
case names[:surname].size
|
|
130
|
-
when 1 then @template[:one]
|
|
131
|
-
when 2 then @template[:two]
|
|
132
|
-
when 3 then @template[:more]
|
|
133
|
-
else template_select_etal(names)
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def template_select_etal(names)
|
|
138
|
-
if @etal_count && names[:surname].size >= @etal_count
|
|
139
|
-
@template[:etal]
|
|
140
|
-
else expand_nametemplate(@template_raw[:more], names[:surname].size)
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
# assumes that template contains, consecutively and not interleaved,
|
|
145
|
-
# ...[0], ...[1], ...[2]
|
|
146
|
-
def expand_nametemplate(template, size)
|
|
147
|
-
t = nametemplate_split(template)
|
|
148
|
-
mid = (1..size - 2).each_with_object([]) do |i, m|
|
|
149
|
-
m << t[1].gsub(/\[1\]/, "[#{i}]")
|
|
150
|
-
end
|
|
151
|
-
template_process(t[0] + mid.join + t[2].gsub(/\[2\]/,
|
|
152
|
-
"[#{size - 1}]"))
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def nametemplate_split(template)
|
|
156
|
-
curr = 0
|
|
157
|
-
prec = ""
|
|
158
|
-
t = template.split(/(\{[{%].+?[}%]\})/)
|
|
159
|
-
.each_with_object(["", "", ""]) do |n, m|
|
|
160
|
-
m, curr, prec = nametemplate_split1(n, m, curr, prec)
|
|
161
|
-
|
|
162
|
-
m
|
|
163
|
-
end
|
|
164
|
-
t[-1] += prec
|
|
165
|
-
t
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def nametemplate_split1(elem, acc, curr, prec)
|
|
169
|
-
if match = /\{[{%].+?\[(\d)\]/.match(elem)
|
|
170
|
-
curr += 1 if match[1].to_i > curr
|
|
171
|
-
acc[curr] += prec
|
|
172
|
-
prec = ""
|
|
173
|
-
acc[curr] += elem
|
|
174
|
-
elsif /\{%\s*endif/.match?(elem)
|
|
175
|
-
acc[curr] += prec
|
|
176
|
-
prec = ""
|
|
177
|
-
acc[curr] += elem
|
|
178
|
-
else prec += elem
|
|
179
|
-
end
|
|
180
|
-
[acc, curr, prec]
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
class AuthorCite < Name
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|