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
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
require_relative "render_classes"
|
|
2
|
-
require_relative "citations"
|
|
3
|
-
require_relative "uri"
|
|
4
|
-
require "yaml"
|
|
5
|
-
require "liquid"
|
|
6
|
-
require "date"
|
|
7
|
-
require "relaton/bib"
|
|
8
|
-
require "metanorma-utils"
|
|
9
|
-
require_relative "../template/template"
|
|
10
|
-
require_relative "../../../isodoc/i18n"
|
|
11
|
-
|
|
12
|
-
module Relaton
|
|
13
|
-
module Render
|
|
14
|
-
class General
|
|
15
|
-
Hash.include ::Metanorma::Utils::Hash
|
|
16
|
-
Array.include ::Metanorma::Utils::Array
|
|
17
|
-
|
|
18
|
-
attr_reader :template, :journaltemplate, :seriestemplate, :nametemplate,
|
|
19
|
-
:authorcitetemplate, :extenttemplate, :sizetemplate,
|
|
20
|
-
:citetemplate, :citeshorttemplate, :lang, :script, :i18n,
|
|
21
|
-
:edition, :date, :fieldsklass, :dateklass, :config
|
|
22
|
-
|
|
23
|
-
def initialize(opt = {})
|
|
24
|
-
options = init_options(opt)
|
|
25
|
-
@type = self.class.name.downcase.split("::").last
|
|
26
|
-
klass_initialize(options)
|
|
27
|
-
root_initalize(options)
|
|
28
|
-
render_initialize(options)
|
|
29
|
-
@parse ||= options["parse"]
|
|
30
|
-
init_misc
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def init_options(opt)
|
|
34
|
-
opt = opt.stringify_all_keys
|
|
35
|
-
@override_file ||= opt["config"]
|
|
36
|
-
@config = config_override(read_config)
|
|
37
|
-
@config.merge(opt)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def init_misc
|
|
41
|
-
@semaphore = Mutex.new
|
|
42
|
-
@urlcache = {}
|
|
43
|
-
@url_warned = {}
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def read_config
|
|
47
|
-
YAML.load_file(File.join(File.dirname(__FILE__), "config.yml"))
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def config_override(ret)
|
|
51
|
-
new = {}
|
|
52
|
-
@override_file and new = YAML.load_file(@override_file)
|
|
53
|
-
ret.deep_merge(new)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def klass_initialize(options)
|
|
57
|
-
@nametemplateklass = Relaton::Render::Template::Name
|
|
58
|
-
@authorcitetemplateklass = Relaton::Render::Template::AuthorCite
|
|
59
|
-
@citetemplateklass = Relaton::Render::Template::Cite
|
|
60
|
-
@citeshorttemplateklass = Relaton::Render::Template::Cite
|
|
61
|
-
@seriestemplateklass = Relaton::Render::Template::Series
|
|
62
|
-
@extenttemplateklass = Relaton::Render::Template::Extent
|
|
63
|
-
@sizetemplateklass = Relaton::Render::Template::Size
|
|
64
|
-
@generaltemplateklass = Relaton::Render::Template::General
|
|
65
|
-
@fieldsklass = Relaton::Render::Fields
|
|
66
|
-
@dateklass = Relaton::Render::Date
|
|
67
|
-
@parseklass = Relaton::Render::Parse
|
|
68
|
-
@i18nklass = options["i18nklass"] || Relaton::Render::I18n
|
|
69
|
-
@citeklass = Relaton::Render::Citations
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def root_initalize(opt)
|
|
73
|
-
i18n_initialize(opt)
|
|
74
|
-
@parse = @parseklass.new(lang: @lang, script: @script, i18n: @i18n)
|
|
75
|
-
@nametemplate = @nametemplateklass
|
|
76
|
-
.new(template: opt["nametemplate"], i18n: @i18n)
|
|
77
|
-
@citetemplate, @citeshorttemplate = citerenderers(opt)
|
|
78
|
-
@authorcitetemplate = @authorcitetemplateklass
|
|
79
|
-
&.new(template: opt["authorcitetemplate"], i18n: @i18n)
|
|
80
|
-
@seriestemplate = @seriestemplateklass
|
|
81
|
-
.new(template: opt["seriestemplate"], i18n: @i18n)
|
|
82
|
-
@journaltemplate = @seriestemplateklass
|
|
83
|
-
.new(template: opt["journaltemplate"], i18n: @i18n)
|
|
84
|
-
@extenttemplate = extentrenderers(opt)
|
|
85
|
-
@sizetemplate = sizerenderers(opt)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def i18n_initialize(opt)
|
|
89
|
-
@lang = opt["language"]
|
|
90
|
-
@script = opt["script"]
|
|
91
|
-
@locale = opt["locale"]
|
|
92
|
-
default_i18n = opt["i18n"] ||
|
|
93
|
-
i18n_klass(language: @lang, script: @script, locale: @locale,
|
|
94
|
-
i18nhash: opt["i18nhash"])
|
|
95
|
-
@i18n = @i18nklass.new(opt.merge({ "i18n" => default_i18n }))
|
|
96
|
-
i18n_default_strs(opt)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# avoid using these, they are document-set not citation-specific
|
|
100
|
-
def i18n_default_strs(opt)
|
|
101
|
-
@edition = opt["edition"] || @i18n.select(nil).edition
|
|
102
|
-
@date = opt["date"] || @i18n.select(nil).get["date_formats"] ||
|
|
103
|
-
{ "month_year" => "yMMMM", "day_month_year" => "to_long_s",
|
|
104
|
-
"date_time" => "to_long_s" }
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def render_initialize(opt)
|
|
108
|
-
case opt["template"]
|
|
109
|
-
when String
|
|
110
|
-
@template = @generaltemplateklass
|
|
111
|
-
.new(template: opt["template"], i18n: @i18n)
|
|
112
|
-
when Hash
|
|
113
|
-
@render = renderers(opt)
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def renderers(opt)
|
|
118
|
-
template_hash_fill(opt["template"]).each_with_object({}) do |(k, v), m|
|
|
119
|
-
@type == "general" || @type == k or next
|
|
120
|
-
m[k] = self.class.subclass(k)
|
|
121
|
-
.new(template: v, parse: @parse, i18n_multi: @i18n.config,
|
|
122
|
-
language: @lang, script: @script, i18nklass: @i18nklass)
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def extentrenderers(opt)
|
|
127
|
-
@extenttemplateklass
|
|
128
|
-
.new(template: template_hash_fill(opt["extenttemplate"]), i18n: @i18n)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def sizerenderers(opt)
|
|
132
|
-
@sizetemplateklass
|
|
133
|
-
.new(template: template_hash_fill(opt["sizetemplate"]), i18n: @i18n)
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def citerenderers(opt)
|
|
137
|
-
s = opt["citetemplate"]["short"]
|
|
138
|
-
r = opt["citetemplate"].reject { |k, _| k == "short" }
|
|
139
|
-
short = @citetemplateklass
|
|
140
|
-
&.new(template: template_hash_fill(s), i18n: @i18n)
|
|
141
|
-
ret = @citetemplateklass
|
|
142
|
-
&.new(template: r, i18n: @i18n)
|
|
143
|
-
[ret, short]
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def default_template
|
|
147
|
-
"{{creatornames}}. {{title}}. {{disambiguated_date}}."
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def i18n_klass(language: "en", script: "Latn", locale: nil, i18nhash: nil)
|
|
151
|
-
::IsoDoc::RelatonRenderI18n.new(language, script, locale: locale,
|
|
152
|
-
i18nhash: i18nhash)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def render(bib, embedded: false, terminator: true)
|
|
156
|
-
bib = xml2relaton(bib)
|
|
157
|
-
f = bib.formattedref and
|
|
158
|
-
return embedded ? f.content : fmtref(f.content)
|
|
159
|
-
ret = render1(bib, terminator) or return nil
|
|
160
|
-
embedded and return ret
|
|
161
|
-
fmtref(ret)
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def xml2relaton(bib)
|
|
165
|
-
bib.is_a?(Relaton::Bib::ItemData) and return bib
|
|
166
|
-
xml = xml_string2noko(bib)
|
|
167
|
-
bib = xml.to_xml(encoding: "UTF-8", indent: 0,
|
|
168
|
-
save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)
|
|
169
|
-
.gsub(/ xmlns="[^"]*"/, "")
|
|
170
|
-
Relaton::Bib::Bibitem.from_xml(bib)
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
def xml_string2noko(bib)
|
|
174
|
-
case bib
|
|
175
|
-
when String
|
|
176
|
-
xml = Nokogiri::XML(bib)
|
|
177
|
-
xml.errors.empty? or return bib
|
|
178
|
-
xml.root
|
|
179
|
-
when Nokogiri::XML::Element
|
|
180
|
-
bib
|
|
181
|
-
when Nokogiri::XML::Document
|
|
182
|
-
bib.root
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def fmtref(doc)
|
|
187
|
-
"<formattedref>#{doc}</formattedref>"
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def renderer(type)
|
|
191
|
-
ret = @template || @render[type]&.template or
|
|
192
|
-
raise "No renderer defined for #{type}"
|
|
193
|
-
@type == "general" || @type == type or
|
|
194
|
-
raise "No renderer defined for #{type}"
|
|
195
|
-
ret
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
# <esc> in field can get capitalised in filters
|
|
199
|
-
def esc_cleanup(text)
|
|
200
|
-
text.gsub(/<esc>/i, "<esc>").gsub(/<\/esc>/i, "</esc>")
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
def render1(doc, terminator)
|
|
204
|
-
obj, str = render_single_bibitem(doc)
|
|
205
|
-
out = [str] + also_pub_as(doc)
|
|
206
|
-
ret1 = out.join(@i18n.select(obj).get["punct"]["biblio-field-delimiter"] || ". ")
|
|
207
|
-
ret = @i18n.select(obj).l10n(esc_cleanup(ret1)
|
|
208
|
-
.gsub(".</esc>.", ".</esc>").gsub(".. ", ". "))
|
|
209
|
-
final = @i18n.select(obj).get["punct"]["biblio-terminator"] || "."
|
|
210
|
-
terminator && !ret.end_with?(final) && !ret.empty? and ret += final
|
|
211
|
-
ret
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def also_pub_as(doc)
|
|
215
|
-
r = Array(doc.relation).select { |x| x.type == "hasRepresentation" }
|
|
216
|
-
r.map do |x|
|
|
217
|
-
_, out = render_single_bibitem(x.bibitem)
|
|
218
|
-
@i18n.select(nil).also_pub_as + out
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def render_single_bibitem(doc)
|
|
223
|
-
data_liquid, r = parse(doc)
|
|
224
|
-
out = liquid(data_liquid, r)
|
|
225
|
-
[data_liquid, out]
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
def liquid(data_liquid, renderer)
|
|
229
|
-
valid_parse(renderer.render(data_liquid, data_liquid))
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def parse(doc)
|
|
233
|
-
doc = xml2relaton(doc)
|
|
234
|
-
r = renderer(doc.type || "misc")
|
|
235
|
-
data = @parse.extract(doc)
|
|
236
|
-
enhance_data(data, r.template_raw)
|
|
237
|
-
data_liquid = @fieldsklass.new(renderer: self)
|
|
238
|
-
.compound_fields_format(data)
|
|
239
|
-
[data_liquid, r]
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
def valid_parse(ret)
|
|
243
|
-
@i18n.select(nil).get["no_date"] == ret and return nil
|
|
244
|
-
ret&.gsub(/\+\+\+(.+?)\+\+\+/, '\1')
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
# expect array of Relaton objects, in sorted order
|
|
248
|
-
# enhance_data is skipped here, and is done in batch inside Citations
|
|
249
|
-
def render_all(bib, type: "author-date")
|
|
250
|
-
bib = sanitise_citations_input(bib) or return
|
|
251
|
-
@citeklass.new(type: type, renderer: citation_renderers,
|
|
252
|
-
i18n: @i18n, lang: @lang, script: @script)
|
|
253
|
-
.render(citations1(bib))
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
def citation_renderers
|
|
257
|
-
{ default: self }
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
def sanitise_citations_input(bib)
|
|
261
|
-
bib.is_a?(Array) and return bib
|
|
262
|
-
bib.is_a?(String) and return sanitise_citations_input_string(bib)
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
def sanitise_citations_input_string(bib)
|
|
266
|
-
p = Nokogiri::XML(bib) or return
|
|
267
|
-
(p.errors.empty? && p.root.at("./bibitem")) or return nil
|
|
268
|
-
p.root.xpath("./bibitem").each_with_object([]) do |b, m|
|
|
269
|
-
m << Relaton::Bib::Bibitem.from_xml(b.to_xml)
|
|
270
|
-
end
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
def citations1(bib)
|
|
274
|
-
bib.each_with_object([]).with_index do |(b, m), i|
|
|
275
|
-
data_liquid = @fieldsklass.new(renderer: self)
|
|
276
|
-
.compound_fields_format(@parse.extract(b))
|
|
277
|
-
m << { author: data_liquid[:authorcite], date: data_liquid[:date],
|
|
278
|
-
ord: i, id: b.id, data: data_liquid, type: b.type }
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
# add to liquid data based on template
|
|
283
|
-
def enhance_data(_data, template)
|
|
284
|
-
template.is_a?(String) or return
|
|
285
|
-
# add_date_accessed(data, template)
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
# functionality removed: date needs to be given explicitly
|
|
289
|
-
def add_date_accessed(data, template)
|
|
290
|
-
(/\{\{\s*date_accessed\s*\}\}/.match?(template) &&
|
|
291
|
-
/\{\{\s*uri\s*\}\}/.match?(template) &&
|
|
292
|
-
data[:uri_raw] && !data[:date_accessed]) or return
|
|
293
|
-
if url_exist?(data[:uri_raw])
|
|
294
|
-
data[:date_accessed] = { on: ::Date.today.to_s }
|
|
295
|
-
else url_warn(data[:uri_raw])
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
def url_warn(uri)
|
|
300
|
-
@url_warned[uri] and return
|
|
301
|
-
warn "BIBLIOGRAPHY WARNING: cannot access #{uri}"
|
|
302
|
-
@url_warned[uri] = true
|
|
303
|
-
end
|
|
304
|
-
|
|
305
|
-
private
|
|
306
|
-
|
|
307
|
-
def template_hash_fill(templates)
|
|
308
|
-
BIBTYPE.each_with_object({}) do |type, m|
|
|
309
|
-
template = templates[type] || templates["misc"] || default_template
|
|
310
|
-
BIBTYPE.include?(template) and template = templates[template]
|
|
311
|
-
m[type] = template
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
end
|
|
@@ -1,132 +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
|
-
# Always look up from the root General class, not from subclasses
|
|
21
|
-
base = self
|
|
22
|
-
base = base.superclass while base.superclass != Object && base.superclass.name =~ /Relaton::Render/
|
|
23
|
-
base.instance_variable_get(:@descendants)&.[](type)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
class Book < General
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
class Journal < General
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
class Booklet < General
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
class Manual < General
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
class Proceedings < General
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
class Presentation < General
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
class Thesis < General
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
class Techreport < General
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
class Standard < General
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
class Unpublished < General
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
class Map < General
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
class Electronic_resource < General
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
class Software < Electronic_resource
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
class Webresource < Electronic_resource
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
class Website < Webresource
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
class Dataset < Electronic_resource
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
class Social_media < Electronic_resource
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
class Alert < Social_media
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
class Message < Social_media
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
class Audiovisual < General
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
class Film < Audiovisual
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
class Video < Audiovisual
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
class Broadcast < Audiovisual
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
class Graphic_work < General
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
class Music < General
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
class Patent < General
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
class Hosted < General
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
class Article < Hosted
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
class InBook < Hosted
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
class InCollection < Hosted
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
class InProceedings < Hosted
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
class Archival < General
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
class Conversation < General
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
class Misc < General
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
class Internal < General
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
require "concurrent"
|
|
2
|
-
require "net/http"
|
|
3
|
-
require "uri"
|
|
4
|
-
|
|
5
|
-
module Relaton
|
|
6
|
-
module Render
|
|
7
|
-
class General
|
|
8
|
-
def url_exist?(url_string)
|
|
9
|
-
return true # temporarily disabling validation of URIs
|
|
10
|
-
url = URI.parse(url_string)
|
|
11
|
-
url.host or return true # allow file URLs
|
|
12
|
-
res = access_url(url) or return false
|
|
13
|
-
res.is_a?(Net::HTTPRedirection) and return url_exist?(res["location"])
|
|
14
|
-
res.code[0] != "4"
|
|
15
|
-
rescue Errno::ENOENT, SocketError
|
|
16
|
-
false # false if can't find the server
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def access_url(url)
|
|
20
|
-
path = url.path or return false
|
|
21
|
-
path.empty? and path = "/"
|
|
22
|
-
url_head(url, path)
|
|
23
|
-
rescue StandardError => e
|
|
24
|
-
warn e
|
|
25
|
-
false
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def url_head(url, path)
|
|
29
|
-
ret = nil
|
|
30
|
-
@semaphore.synchronize { ret = @urlcache[url.to_s] }
|
|
31
|
-
ret and return ret
|
|
32
|
-
ret = Net::HTTP.start(url.host, url.port,
|
|
33
|
-
read_timeout: 2, open_timeout: 2,
|
|
34
|
-
use_ssl: url.scheme == "https") do |http|
|
|
35
|
-
http.request_head(path)
|
|
36
|
-
end
|
|
37
|
-
@semaphore.synchronize { @urlcache[url.to_s] = ret }
|
|
38
|
-
ret
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def urls_exist_concurrent(urls)
|
|
42
|
-
responses = Concurrent::Array.new
|
|
43
|
-
thread_pool = Concurrent::FixedThreadPool.new(5)
|
|
44
|
-
urls.each do |u|
|
|
45
|
-
thread_pool.post { responses << url_exist_async?(u) }
|
|
46
|
-
end
|
|
47
|
-
thread_pool.shutdown
|
|
48
|
-
thread_pool.wait_for_termination
|
|
49
|
-
responses.each_with_object({}) { |n, m| m[n[:url]] = n[:status] }
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def url_exist_async?(url_string)
|
|
53
|
-
{ url: url_string, status: url_exist?(url_string) }
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
module Relaton
|
|
2
|
-
module Render
|
|
3
|
-
class I18n
|
|
4
|
-
# @i18n is a hash of IsoDoc::I18n objects, selected from according to
|
|
5
|
-
# attributes of the parsed Relaton object
|
|
6
|
-
def initialize(opt)
|
|
7
|
-
if opt["i18n_multi"]
|
|
8
|
-
@i18n = opt["i18n_multi"]
|
|
9
|
-
elsif opt["i18n"]
|
|
10
|
-
@i18n = { "" => opt["i18n"] }
|
|
11
|
-
else
|
|
12
|
-
raise error "Bad configuration, Relaton::Render::I18n"
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# obj is the biblio hash, extracted by Relaton::Render::Fields
|
|
17
|
-
# There must always be a default selection, for obj = nil,
|
|
18
|
-
# being the document language setting. If select is applied on obj,
|
|
19
|
-
# the i18n selected is appropriate to the citation specifically,
|
|
20
|
-
# and potentially to the field specificaly
|
|
21
|
-
def select(obj)
|
|
22
|
-
if obj.nil? then select_default
|
|
23
|
-
else select_obj(obj)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def select_default
|
|
28
|
-
@i18n[""]
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def select_obj(_obj)
|
|
32
|
-
@i18n[""]
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def config
|
|
36
|
-
@i18n
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
require "nokogiri"
|
|
2
|
-
require "twitter_cldr"
|
|
3
|
-
require_relative "parse_contributors"
|
|
4
|
-
require_relative "parse_extract"
|
|
5
|
-
require_relative "parse_id"
|
|
6
|
-
|
|
7
|
-
module Relaton
|
|
8
|
-
module Render
|
|
9
|
-
class Parse
|
|
10
|
-
def initialize(options)
|
|
11
|
-
@lang = options[:lang] || "en"
|
|
12
|
-
@script = options[:script] || "Latn"
|
|
13
|
-
@i18n = options[:i18n]
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def extract(doc)
|
|
17
|
-
host = host(doc)
|
|
18
|
-
ret = simple_xml2hash(doc).merge(simple_or_host_xml2hash(doc, host))
|
|
19
|
-
.merge(host_xml2hash(host))
|
|
20
|
-
.merge(series_xml2hash(doc, host))
|
|
21
|
-
ret
|
|
22
|
-
#i18n(ret)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def simple_xml2hash(doc)
|
|
26
|
-
creators, role = creatornames(doc)
|
|
27
|
-
{ type: type(doc), title: title(doc), extent_raw: extent(doc),
|
|
28
|
-
size_raw: size(doc), uri_raw: uri(doc), doi: doi(doc),
|
|
29
|
-
authoritative_identifier: authoritative_identifier(doc),
|
|
30
|
-
other_identifier_raw: other_identifier(doc), biblio_tag: biblio_tag(doc),
|
|
31
|
-
status_raw: status(doc), creators: creators, role_raw: role,
|
|
32
|
-
language: language(doc), script: script(doc), locale: locale(doc) }
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def simple_or_host_xml2hash(doc, host)
|
|
36
|
-
{ edition_raw: edition(doc, host), edition_num: edition_num(doc, host),
|
|
37
|
-
medium_raw: medium(doc, host), draft_raw: draft(doc, host),
|
|
38
|
-
place_raw: place(doc, host), publisher_raw: publisher(doc, host),
|
|
39
|
-
publisher_abbrev_raw: publisher_abbrev(doc, host),
|
|
40
|
-
authorizer_raw: authorizer(doc, host),
|
|
41
|
-
distributor_raw: distributor(doc, host),
|
|
42
|
-
access_location: access_location(doc, host),
|
|
43
|
-
date: date(doc, host), date_updated: date_updated(doc, host),
|
|
44
|
-
date_accessed: date_accessed(doc, host) }
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def host_xml2hash(host)
|
|
48
|
-
creators, role = creatornames(host)
|
|
49
|
-
{ host_creators: creators, host_role_raw: role,
|
|
50
|
-
host_title: title(host) }
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def series_xml2hash(doc, host)
|
|
54
|
-
series = series(doc)
|
|
55
|
-
host and series ||= series(host)
|
|
56
|
-
series_xml2hash1(series, doc)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def series_xml2hash1(series, doc)
|
|
60
|
-
series or return {}
|
|
61
|
-
ret = { series_formatted: series_formatted(series, doc),
|
|
62
|
-
series_title: series_title(series, doc),
|
|
63
|
-
series_abbr: series_abbr(series, doc),
|
|
64
|
-
series_run: series_run(series, doc),
|
|
65
|
-
series_num: series_num(series, doc),
|
|
66
|
-
series_partnumber: series_partnumber(series, doc),
|
|
67
|
-
series_place: series_place(series, doc),
|
|
68
|
-
series_org: series_org(series, doc),
|
|
69
|
-
series_dates: series_dates(series, doc) }
|
|
70
|
-
ret.each do |k, v|
|
|
71
|
-
%i(series_num series_dates).include?(k) and next
|
|
72
|
-
ret[k] = esc(v)
|
|
73
|
-
end
|
|
74
|
-
ret
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
#KILL
|
|
78
|
-
def other_identifier_i18n(hash)
|
|
79
|
-
#ret << "#{type}: #{esc id.id}"
|
|
80
|
-
hash[:other_identifier]&.map! do |i|
|
|
81
|
-
i.include?("<esc>") ? @i18n.select(hash).l10n(i) : i
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
ALLOWED_INLINE_TAGS = %w[
|
|
86
|
-
em eref strong stem sub sup tt underline keyword ruby
|
|
87
|
-
strike smallcap xref br link hr pagebreak bookmark
|
|
88
|
-
image index index-xref concept add del span erefstack
|
|
89
|
-
date fn
|
|
90
|
-
].freeze
|
|
91
|
-
|
|
92
|
-
private
|
|
93
|
-
|
|
94
|
-
def blank?(text)
|
|
95
|
-
text.nil? || text.empty?
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def esc(text)
|
|
99
|
-
blank?(text) and return text
|
|
100
|
-
"<esc>#{text}</esc>"
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Strip any tag not in ALLOWED_INLINE_TAGS, in both literal (<tag>) and
|
|
104
|
-
# entity-encoded (<tag>) forms. Used to defend Liquid template
|
|
105
|
-
# output against embedded structural markup (most commonly <title>) in
|
|
106
|
-
# bibliographic text fields, where relaton-bib may surface either form
|
|
107
|
-
# depending on lutaml-model serialisation behaviour.
|
|
108
|
-
#
|
|
109
|
-
# Authors embed inline markup either literally (<em>foo</em>) or
|
|
110
|
-
# entity-encoded (<em>foo</em>); both are intended as
|
|
111
|
-
# markup, and downstream template rendering decodes entities anyway
|
|
112
|
-
# (see HTMLEntities.decode in template.rb), so we normalise the
|
|
113
|
-
# encoded form to literal up front and let a single Nokogiri-fragment
|
|
114
|
-
# walk handle both. Elements whose name is in the allow-list are
|
|
115
|
-
# preserved verbatim with their entire subtree, so wrappers that
|
|
116
|
-
# legitimately carry block content (notably <fn><p>…</p></fn>)
|
|
117
|
-
# round-trip intact rather than being shredded one tag at a time.
|
|
118
|
-
# Disallowed elements are unwrapped (tag dropped, children kept),
|
|
119
|
-
# recursing first so allowed wrappers nested inside disallowed
|
|
120
|
-
# wrappers still survive. Nokogiri re-escapes any genuine `<` left in
|
|
121
|
-
# text positions on serialisation, so plain prose like "5 < 10" is
|
|
122
|
-
# preserved correctly.
|
|
123
|
-
def sanitise_inline_markup(str)
|
|
124
|
-
blank?(str) and return str
|
|
125
|
-
normalised = str.gsub("<", "<").gsub(">", ">")
|
|
126
|
-
frag = Nokogiri::XML.fragment(normalised)
|
|
127
|
-
unwrap_disallowed(frag)
|
|
128
|
-
save_opts = Nokogiri::XML::Node::SaveOptions::AS_XML |
|
|
129
|
-
Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
|
130
|
-
frag.to_xml(encoding: "UTF-8", save_with: save_opts)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def unwrap_disallowed(node)
|
|
134
|
-
node.children.to_a.each do |child|
|
|
135
|
-
next unless child.element?
|
|
136
|
-
next if ALLOWED_INLINE_TAGS.include?(child.name)
|
|
137
|
-
|
|
138
|
-
unwrap_disallowed(child)
|
|
139
|
-
child.replace(child.children)
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def wrap_in_esc(obj)
|
|
144
|
-
case obj
|
|
145
|
-
when String then esc(obj)
|
|
146
|
-
when Array then obj.map { |e| wrap_in_esc(e) }
|
|
147
|
-
else obj
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|