relaton-render 3.0.0.pre.alpha.34 → 3.0.0.pre.alpha.35
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/docs/citation-style-pack.adoc +1 -1
- data/lib/relaton/render/iso690/rules/nist.rb +384 -0
- data/lib/relaton/render/iso690/rules.rb +11 -0
- data/lib/relaton/render/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 81c57319ba531b5c63b0adcad897b4abbefac37099990a625993dab5357c7a32
|
|
4
|
+
data.tar.gz: 1316576d47fdfccd9007c5ef98dfa3d40d0ca4ab5dca8a3de4cc822ebccdb657
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 36b05f7515bddf6f44a728174a57f365398c0f28aa55b2e3228ea651eadbf0d8c7a7c02ddd70c2b4375b53df83aa13bb896b6be27298e4d8e675a394aeca3d23
|
|
7
|
+
data.tar.gz: a8d0e79f9349ccd80efb408c04789f791dea1b21e510ab3cfd2ce5cfd65d912ef1a5d6b42047d8ad60cec88c65c0a92e8a3c90981e5bb9739d622837ee02aa1f
|
|
@@ -290,7 +290,7 @@ is a rule to promote:
|
|
|
290
290
|
|Flavor override |Becomes rule
|
|
291
291
|
|
|
292
292
|
|`ItuIdentifier` |**[impl]** promoted: `identifier: itu_identifier`
|
|
293
|
-
|`NistIdentifier`, `NistCreator`, `NistDate`, `SerialDate`, `NistSeries`, `NistComponentPart`, `NistPublisher`, `Draft`
|
|
293
|
+
|`NistIdentifier`, `NistCreator`, `NistDate`, `SerialDate`, `NistSeries`, `NistComponentPart`, `NistPublisher`, `Draft` |**[impl]** promoted: `nist_identifier`, `nist_creator`, `nist_date`, `nist_serial_date`, `nist_series`, `nist_component_part`, `nist_publisher`, `nist_draft`
|
|
294
294
|
|`IeeeIdentifier`, `IeeeComponentPart`, `IeeeAccess`, `IeeeMedium` |**[impl]** promoted: `ieee_identifier`, `ieee_component_part`, `ieee_access`, `ieee_medium`
|
|
295
295
|
|`BipmCreator`, `BipmComponentPart`, `BipmProduction`, `BipmExtent`, `BipmMedium`, `BipmEdition`, `BipmVolume` |the BIPM rule set
|
|
296
296
|
|`IhoEdition`, `IhoCreator` |affiliation-composite creators
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Render
|
|
5
|
+
module Iso690
|
|
6
|
+
module Rules
|
|
7
|
+
# The NIST rule set, moved verbatim from the metanorma-nist
|
|
8
|
+
# flavor's NistElements: the corporate creator forms, the
|
|
9
|
+
# series derivation from nist-long identifiers, the draft
|
|
10
|
+
# stage forms, the identifier order, and the component-part
|
|
11
|
+
# host citation. Select from pack data:
|
|
12
|
+
# rules: { creator: nist_series_publisher, ... }
|
|
13
|
+
module Nist
|
|
14
|
+
NIST_AND_ABBREV =
|
|
15
|
+
["NIST", "National Institute of Standards and Technology"].freeze
|
|
16
|
+
|
|
17
|
+
STAGE_PRINT = {
|
|
18
|
+
"draft-internal" => "Internal Draft",
|
|
19
|
+
"draft-wip" => "Work-in-Progress Draft",
|
|
20
|
+
"draft-prelim" => "Preliminary Draft",
|
|
21
|
+
"draft-public" => "Public Draft",
|
|
22
|
+
"draft-approval" => "Approval Draft",
|
|
23
|
+
"final" => "Final",
|
|
24
|
+
"final-review" => "Under Review",
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
FIPS_PUBLISHER = "U.S. Department of Commerce, Washington, D.C."
|
|
28
|
+
NIST_PUBLISHER = "National Institute of Standards and Technology, " \
|
|
29
|
+
"Gaithersburg, MD"
|
|
30
|
+
|
|
31
|
+
HOST_RELATION_TYPES = %w[partOf includedIn].freeze
|
|
32
|
+
|
|
33
|
+
# The partOf/includedIn host and its publication year: shared
|
|
34
|
+
# by the component part and the host-date fallback of the
|
|
35
|
+
# date element
|
|
36
|
+
module HostDate
|
|
37
|
+
def relation_host
|
|
38
|
+
Array(@model.relation).find do |r|
|
|
39
|
+
HOST_RELATION_TYPES.include?(r.type)
|
|
40
|
+
end&.bibitem
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def host_date_year
|
|
44
|
+
h = relation_host or return ""
|
|
45
|
+
d = Array(h.date).find(&:published) ||
|
|
46
|
+
Array(h.date).find { |x| x.type.nil? } ||
|
|
47
|
+
Array(h.date).find { |x| x.type == "issued" } ||
|
|
48
|
+
Array(h.date).first or return ""
|
|
49
|
+
v = d.at || d.from || d.to or return ""
|
|
50
|
+
begin
|
|
51
|
+
v.to_date.year.to_s
|
|
52
|
+
rescue ArgumentError, TypeError
|
|
53
|
+
v.to_s[/\d{4}/].to_s
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# NIST-aware element base: NIST Standard Reference documents
|
|
59
|
+
# are detected by identifier type or publisher
|
|
60
|
+
class Base < Element
|
|
61
|
+
def present?
|
|
62
|
+
!render.to_s.empty?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def nist?
|
|
68
|
+
return true if Array(@model.docidentifier).any? do |d|
|
|
69
|
+
d.type.to_s.start_with?("NIST")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
Array(@model.contributor).select { |c| has_role?(c, "publisher") }
|
|
73
|
+
.any? do |c|
|
|
74
|
+
org = c.organization or next false
|
|
75
|
+
|
|
76
|
+
Array(org.name).any? { |n| NIST_AND_ABBREV.include?(n.content) } ||
|
|
77
|
+
org.abbreviation&.content == "NIST"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def series_title
|
|
82
|
+
Array(@model.series).first&.title&.first&.content.to_s
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# The series publisher block, parenthesized, after the title
|
|
87
|
+
class NistPublisher < Base
|
|
88
|
+
def render
|
|
89
|
+
if series_title == "NIST Federal Information Processing Standards"
|
|
90
|
+
return " (#{FIPS_PUBLISHER})"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
nist? ? " (#{NIST_PUBLISHER})" : ""
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# The NIST draft form ("Draft (Third Public Draft)")
|
|
98
|
+
class NistDraft < Base
|
|
99
|
+
def render
|
|
100
|
+
stage = @model.status&.stage&.content.to_s
|
|
101
|
+
return "" unless stage.start_with?("draft") && nist?
|
|
102
|
+
|
|
103
|
+
"Draft (#{iteration(stage)} #{STAGE_PRINT.fetch(stage, stage)})"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
private
|
|
107
|
+
|
|
108
|
+
def iteration(stage)
|
|
109
|
+
iter = @model.status&.iteration.to_s
|
|
110
|
+
return "Initial" if iter.empty? || iter == "1"
|
|
111
|
+
return "Final" if iter.casecmp("final").zero?
|
|
112
|
+
|
|
113
|
+
spellout_ordinal(iter.to_i)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# The language packs carry ordinal word labels; beyond
|
|
117
|
+
# their reach the numeric suffix form carries the value
|
|
118
|
+
def spellout_ordinal(num)
|
|
119
|
+
word = @i18n.label("ordinal_word_#{num}")
|
|
120
|
+
return word.capitalize unless word == "ordinal_word_#{num}"
|
|
121
|
+
|
|
122
|
+
"#{num}#{ordinal_suffix(num)}"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def ordinal_suffix(num)
|
|
126
|
+
case num % 100
|
|
127
|
+
when 11, 12, 13 then "th"
|
|
128
|
+
else
|
|
129
|
+
case num % 10
|
|
130
|
+
when 1 then "st"
|
|
131
|
+
when 2 then "nd"
|
|
132
|
+
when 3 then "rd"
|
|
133
|
+
else "th"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# The NIST series form ("NIST Special Publication (SP)
|
|
140
|
+
# 800-116 Rev. 1"). A series carrying a formattedref renders
|
|
141
|
+
# it verbatim; the number joins the partnumber ("800-116.1"),
|
|
142
|
+
# and the edition carries the revision. NIST documents
|
|
143
|
+
# without a series element derive it from the nist-long
|
|
144
|
+
# identifier
|
|
145
|
+
class NistSeries < Base
|
|
146
|
+
def render
|
|
147
|
+
s = Array(@model.series).first
|
|
148
|
+
return derived_series unless s
|
|
149
|
+
|
|
150
|
+
formatted = localized(s.formattedref)
|
|
151
|
+
return formatted unless formatted.empty?
|
|
152
|
+
|
|
153
|
+
title = localized(Array(s.title).first)
|
|
154
|
+
return "" if title.empty?
|
|
155
|
+
|
|
156
|
+
[title, parens(s), number(s)].reject(&:empty?).join(" ")
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
private
|
|
160
|
+
|
|
161
|
+
def derived_series
|
|
162
|
+
long = Array(@model.docidentifier).find do |d|
|
|
163
|
+
d.type == "nist-long"
|
|
164
|
+
end&.content.to_s
|
|
165
|
+
return "" if long.empty?
|
|
166
|
+
|
|
167
|
+
title = long[/\A(NIST [A-Za-z ]+?) \d/, 1] || ""
|
|
168
|
+
return "" if title.empty?
|
|
169
|
+
|
|
170
|
+
[title, parens_derived(long), number_derived(long)]
|
|
171
|
+
.reject(&:empty?).join(" ")
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def parens_derived(long)
|
|
175
|
+
# strip the NIST sigla before the whitespace strip: the
|
|
176
|
+
# 1.x order left a bare "NIST" parenthesized
|
|
177
|
+
abbr = long[/\A[A-Z.]+ /, 0].to_s.sub(/\ANIST /, "").strip
|
|
178
|
+
abbr.empty? ? "" : "(#{abbr})"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def number_derived(long)
|
|
182
|
+
num = long[/\A[NISTa-z. ]*([0-9][0-9A-Za-z.-]*)/, 1].to_s
|
|
183
|
+
num.empty? ? num : with_revision(num)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def parens(s)
|
|
187
|
+
abbr = localized(s.abbreviation).sub(/\ANIST /, "")
|
|
188
|
+
abbr.empty? ? "" : "(#{abbr})"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def number(s)
|
|
192
|
+
num = s.number.to_s
|
|
193
|
+
unless s.partnumber.to_s.empty?
|
|
194
|
+
num = num.empty? ? s.partnumber.to_s : "#{num}.#{s.partnumber}"
|
|
195
|
+
end
|
|
196
|
+
num = @model.docnumber.to_s if num.empty? && nist?
|
|
197
|
+
num.empty? ? num : with_revision(num)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def with_revision(num)
|
|
201
|
+
rev = @model.edition&.content.to_s.sub(/\ARevision /, "")
|
|
202
|
+
rev.empty? ? num : "#{num} Rev. #{rev}"
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
module Relaton
|
|
212
|
+
module Render
|
|
213
|
+
module Iso690
|
|
214
|
+
module Rules
|
|
215
|
+
module Nist
|
|
216
|
+
# The NIST identifier order: the authoritative identifiers
|
|
217
|
+
# (ISO, IEC, ...) before the kind-rendered ISBN/DOI/ISSN
|
|
218
|
+
# group; NIST documents cite the NIST identifier alone (the
|
|
219
|
+
# biblio tag)
|
|
220
|
+
class NistIdentifier < Elements::Identifier
|
|
221
|
+
OTHER_TYPES = %w[ISBN ISSN DOI].freeze
|
|
222
|
+
|
|
223
|
+
def render
|
|
224
|
+
return "" if nist?
|
|
225
|
+
|
|
226
|
+
auth, other = unscoped_ids.partition do |d|
|
|
227
|
+
!OTHER_TYPES.include?(d.type)
|
|
228
|
+
end
|
|
229
|
+
(auth + other).map { |d| render_id(d) }.reject(&:empty?)
|
|
230
|
+
.join(". ")
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
private
|
|
234
|
+
|
|
235
|
+
def nist?
|
|
236
|
+
Array(@model.docidentifier).any? do |d|
|
|
237
|
+
d.type.to_s.start_with?("NIST")
|
|
238
|
+
end || Array(@model.contributor).any? do |c|
|
|
239
|
+
next false unless has_role?(c, "publisher")
|
|
240
|
+
|
|
241
|
+
org = c.organization or next false
|
|
242
|
+
|
|
243
|
+
Array(org.name).any? { |n| NIST_AND_ABBREV.include?(n.content) } ||
|
|
244
|
+
org.abbreviation&.content == "NIST"
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def unscoped_ids
|
|
249
|
+
Array(@model.docidentifier).reject do |d|
|
|
250
|
+
Elements::Identifier::INTERNAL_TYPES.include?(d.type) ||
|
|
251
|
+
!d.scope.to_s.empty? || d.content.to_s.strip.empty?
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# The NIST ISBN and ISSN kinds cite the kind label with a
|
|
256
|
+
# colon
|
|
257
|
+
def render_id(docidentifier)
|
|
258
|
+
return "#{docidentifier.type}: #{docidentifier.content}" if
|
|
259
|
+
%w[ISBN ISSN].include?(docidentifier.type)
|
|
260
|
+
|
|
261
|
+
super
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# The NIST component-part order: the host editors before the
|
|
266
|
+
# host title, the host date after the production
|
|
267
|
+
# ("In: Pellegrini AD, Smith PK (Eds.) <em>The nature of
|
|
268
|
+
# play</em> (New York, NY: Guilford Press), 2005")
|
|
269
|
+
class NistComponentPart < Elements::ComponentPart
|
|
270
|
+
include HostDate
|
|
271
|
+
|
|
272
|
+
def render
|
|
273
|
+
h = relation_host or return ""
|
|
274
|
+
out = +"#{lead}#{host_names(h)}"
|
|
275
|
+
eds = host_editors(h)
|
|
276
|
+
out += " (#{@i18n.label(eds.one? ? "ed" : "eds")})" unless
|
|
277
|
+
eds.empty?
|
|
278
|
+
out += " #{host_title}" unless host_title_text.empty?
|
|
279
|
+
production = host_production_text(h)
|
|
280
|
+
out += " (#{production})" unless production.empty?
|
|
281
|
+
date = host_date_year
|
|
282
|
+
out += ", #{date}" unless date.empty?
|
|
283
|
+
out
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
private
|
|
287
|
+
|
|
288
|
+
def host_editors(h)
|
|
289
|
+
Array(h.contributor).select { |c| has_role?(c, "editor") }
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def host_names(h)
|
|
293
|
+
names = host_editors(h).map { |c|
|
|
294
|
+
person = c.person or next ""
|
|
295
|
+
|
|
296
|
+
[person_surname(person), person_given(person)].reject(&:empty?)
|
|
297
|
+
.join(" ")
|
|
298
|
+
}.reject(&:empty?)
|
|
299
|
+
join_names(names)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def host_production_text(h)
|
|
303
|
+
Elements::Production.new(h, style: @style, i18n: @i18n)
|
|
304
|
+
.render.to_s
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# A component part with no date of its own cites the host's
|
|
309
|
+
class NistDate < Elements::PubDate
|
|
310
|
+
include HostDate
|
|
311
|
+
|
|
312
|
+
def render
|
|
313
|
+
text = super.to_s
|
|
314
|
+
text.empty? ? host_date_year : text
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
# The series-position date segment of the 1.x templates: the
|
|
319
|
+
# date carries its own leading comma ("<series>, 2018
|
|
320
|
+
# (updated November 2018)"), so an absent date removes the
|
|
321
|
+
# comma with it
|
|
322
|
+
class NistSerialDate < Base
|
|
323
|
+
def render
|
|
324
|
+
text = pub_date or return ""
|
|
325
|
+
|
|
326
|
+
", #{text}#{updated_date}"
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
private
|
|
330
|
+
|
|
331
|
+
def pub_date
|
|
332
|
+
t = Elements::PubDate.new(@model, style: @style, i18n: @i18n)
|
|
333
|
+
.render.to_s
|
|
334
|
+
t.empty? ? nil : t
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def updated_date
|
|
338
|
+
Elements::Updated.new(@model, style: @style, i18n: @i18n).render
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# The FIPS creator form: the series names the corporate
|
|
343
|
+
# creator; standards without personal creators cite their
|
|
344
|
+
# publisher's name, monographs cite nothing (their "(n.d.)"
|
|
345
|
+
# comes from the perType fallback)
|
|
346
|
+
class NistCreator < Elements::Creator
|
|
347
|
+
def render
|
|
348
|
+
return fips_creator if fips_series?
|
|
349
|
+
|
|
350
|
+
super
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def plain_render
|
|
354
|
+
return fips_creator if fips_series?
|
|
355
|
+
|
|
356
|
+
super
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
private
|
|
360
|
+
|
|
361
|
+
def fallback_name
|
|
362
|
+
return "" if %w[monograph continuing component_part]
|
|
363
|
+
.include?(Kinds.kind_for(@model.type))
|
|
364
|
+
|
|
365
|
+
publishers = contributors("publisher").filter_map do |c|
|
|
366
|
+
localized(Array(c.organization&.name).first)
|
|
367
|
+
end
|
|
368
|
+
publishers.reject(&:empty?).first.to_s
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def fips_series?
|
|
372
|
+
Array(@model.series).first&.title&.first&.content ==
|
|
373
|
+
"NIST Federal Information Processing Standards"
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def fips_creator
|
|
377
|
+
"National Institute of Standards and Technology"
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
end
|
|
@@ -106,6 +106,9 @@ module Relaton
|
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
# The NIST rule set lives in its own autoloaded section
|
|
110
|
+
autoload :Nist, "relaton/render/iso690/rules/nist"
|
|
111
|
+
|
|
109
112
|
REGISTRY = {
|
|
110
113
|
"status_bare" => BareStatus,
|
|
111
114
|
"itu_identifier" => ItuIdentifier,
|
|
@@ -113,6 +116,14 @@ module Relaton
|
|
|
113
116
|
"ieee_component_part" => IeeeComponentPart,
|
|
114
117
|
"ieee_access" => IeeeAccess,
|
|
115
118
|
"ieee_medium" => IeeeMedium,
|
|
119
|
+
"nist_creator" => Nist::NistCreator,
|
|
120
|
+
"nist_date" => Nist::NistDate,
|
|
121
|
+
"nist_serial_date" => Nist::NistSerialDate,
|
|
122
|
+
"nist_series" => Nist::NistSeries,
|
|
123
|
+
"nist_component_part" => Nist::NistComponentPart,
|
|
124
|
+
"nist_identifier" => Nist::NistIdentifier,
|
|
125
|
+
"nist_publisher" => Nist::NistPublisher,
|
|
126
|
+
"nist_draft" => Nist::NistDraft,
|
|
116
127
|
}.freeze
|
|
117
128
|
|
|
118
129
|
class << self
|
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
|
+
version: 3.0.0.pre.alpha.35
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -148,6 +148,7 @@ files:
|
|
|
148
148
|
- lib/relaton/render/iso690/kinds.rb
|
|
149
149
|
- lib/relaton/render/iso690/renderer.rb
|
|
150
150
|
- lib/relaton/render/iso690/rules.rb
|
|
151
|
+
- lib/relaton/render/iso690/rules/nist.rb
|
|
151
152
|
- lib/relaton/render/iso690/style.rb
|
|
152
153
|
- lib/relaton/render/iso690/style/locale.rb
|
|
153
154
|
- lib/relaton/render/iso690/style/name_form.rb
|