metanorma-iso 3.4.8 → 3.4.9

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -0
  3. data/lib/isodoc/iso/html/style-human.css +5 -0
  4. data/lib/isodoc/iso/html/style-iso.css +5 -0
  5. data/lib/isodoc/iso/iso.amendment.xsl +113 -66
  6. data/lib/isodoc/iso/iso.international-standard.xsl +113 -66
  7. data/lib/isodoc/iso/presentation_xml_convert.rb +16 -0
  8. data/lib/metanorma/iso/basicdoc.rng +1 -1
  9. data/lib/metanorma/iso/cleanup_biblio.rb +28 -24
  10. data/lib/metanorma/iso/front_id.rb +4 -0
  11. data/lib/metanorma/iso/{mathml3-content.rng → mathml4-content.rng} +104 -80
  12. data/lib/metanorma/iso/mathml4-core.rng +1041 -0
  13. data/lib/metanorma/iso/{mathml3-presentation.rng → mathml4-presentation.rng} +184 -1060
  14. data/lib/metanorma/iso/{mathml3-strict-content.rng → mathml4-strict-content.rng} +92 -8
  15. data/lib/metanorma/iso/mathml4.rng +30 -0
  16. data/lib/metanorma/iso/metanorma-mathml.rng +22 -8
  17. data/lib/metanorma/iso/processor.rb +32 -2
  18. data/lib/metanorma/iso/sts/transformer/back_transformer.rb +85 -0
  19. data/lib/metanorma/iso/sts/transformer/base.rb +118 -0
  20. data/lib/metanorma/iso/sts/transformer/block_dispatcher.rb +109 -0
  21. data/lib/metanorma/iso/sts/transformer/body_transformer.rb +39 -0
  22. data/lib/metanorma/iso/sts/transformer/content_text.rb +40 -0
  23. data/lib/metanorma/iso/sts/transformer/context.rb +64 -0
  24. data/lib/metanorma/iso/sts/transformer/def_list_transformer.rb +57 -0
  25. data/lib/metanorma/iso/sts/transformer/document_transformer.rb +30 -0
  26. data/lib/metanorma/iso/sts/transformer/example_transformer.rb +41 -0
  27. data/lib/metanorma/iso/sts/transformer/figure_transformer.rb +44 -0
  28. data/lib/metanorma/iso/sts/transformer/footnote_collector.rb +82 -0
  29. data/lib/metanorma/iso/sts/transformer/formula_transformer.rb +38 -0
  30. data/lib/metanorma/iso/sts/transformer/front_transformer.rb +56 -0
  31. data/lib/metanorma/iso/sts/transformer/id_generator.rb +181 -0
  32. data/lib/metanorma/iso/sts/transformer/inline_transformer.rb +293 -0
  33. data/lib/metanorma/iso/sts/transformer/iso_meta_transformer.rb +374 -0
  34. data/lib/metanorma/iso/sts/transformer/list_transformer.rb +65 -0
  35. data/lib/metanorma/iso/sts/transformer/nbsp_processor.rb +43 -0
  36. data/lib/metanorma/iso/sts/transformer/note_transformer.rb +43 -0
  37. data/lib/metanorma/iso/sts/transformer/paragraph_transformer.rb +28 -0
  38. data/lib/metanorma/iso/sts/transformer/quote_transformer.rb +17 -0
  39. data/lib/metanorma/iso/sts/transformer/reference_transformer.rb +136 -0
  40. data/lib/metanorma/iso/sts/transformer/section_transformer.rb +102 -0
  41. data/lib/metanorma/iso/sts/transformer/sourcecode_transformer.rb +18 -0
  42. data/lib/metanorma/iso/sts/transformer/standard.rb +33 -0
  43. data/lib/metanorma/iso/sts/transformer/table_transformer.rb +99 -0
  44. data/lib/metanorma/iso/sts/transformer/term_transformer.rb +227 -0
  45. data/lib/metanorma/iso/sts/transformer.rb +52 -0
  46. data/lib/metanorma/iso/sts.rb +38 -0
  47. data/lib/metanorma/iso/version.rb +1 -1
  48. data/lib/metanorma-iso.rb +1 -0
  49. data/metanorma-iso.gemspec +2 -0
  50. metadata +63 -7
  51. data/.hound.yml +0 -5
  52. data/lib/metanorma/iso/mathml3-common.rng +0 -257
  53. data/lib/metanorma/iso/mathml3.rng +0 -23
@@ -0,0 +1,293 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Iso
5
+ module Sts
6
+ class Transformer::InlineTransformer < Transformer::Base
7
+ include Transformer::ContentText
8
+
9
+ def transform_inline(node)
10
+ case node
11
+ when String
12
+ [:content, node]
13
+ when Metanorma::Document::Components::Inline::EmRawElement
14
+ [:italic, transform_italic(node)]
15
+ when Metanorma::Document::Components::Inline::StrongRawElement
16
+ [:bold, transform_bold(node)]
17
+ when Metanorma::Document::Components::Inline::SubElement
18
+ [:sub, transform_sub(node)]
19
+ when Metanorma::Document::Components::Inline::SupElement
20
+ [:sup, transform_sup(node)]
21
+ when Metanorma::Document::Components::Inline::TtElement
22
+ [:monospace, transform_monospace(node)]
23
+ when Metanorma::Document::Components::Inline::SmallCapElement
24
+ [:sc, transform_smallcap(node)]
25
+ when Metanorma::Document::Components::Inline::XrefElement
26
+ [:xref, transform_xref(node)]
27
+ when Metanorma::Document::Components::Inline::ErefElement
28
+ [:std, transform_eref(node)]
29
+ when Metanorma::Document::Components::Inline::FnElement
30
+ [:xref, transform_fn(node)]
31
+ when Metanorma::Document::Components::Inline::LinkElement
32
+ [:ext_link, transform_link(node)]
33
+ when Metanorma::Document::Components::Inline::BrElement
34
+ [:break, transform_br(node)]
35
+ when Metanorma::Document::Components::Inline::StemInlineElement
36
+ [:inline_formula, transform_stem(node)]
37
+ when Metanorma::Document::Components::Inline::ConceptElement
38
+ nil
39
+ when Metanorma::Document::Components::Inline::SpanElement
40
+ [:styled_content, transform_span(node)]
41
+ when Metanorma::Document::Components::Inline::Bcp14Element
42
+ [:bold, transform_bcp14(node)]
43
+ end
44
+ end
45
+
46
+ def apply_inline_content(source, target)
47
+ source.each_mixed_content do |node|
48
+ result = transform_inline(node)
49
+ next unless result
50
+
51
+ type, value = result
52
+ if type == :content
53
+ target.content value
54
+ else
55
+ target.send(type, value)
56
+ end
57
+ end
58
+ target
59
+ end
60
+
61
+ def apply_term_inline_content(source, target)
62
+ text = extract_text(source)
63
+ target.content = [text] if text && !text.empty?
64
+ target
65
+ end
66
+
67
+ def apply_tbx_content(source, target, text_attr: :value)
68
+ source.each_mixed_content do |node|
69
+ result = transform_tbx_inline(node)
70
+ next unless result
71
+
72
+ type, value = result
73
+ if type == :content
74
+ target.send(text_attr, value)
75
+ else
76
+ target.send(type, value)
77
+ end
78
+ end
79
+ target
80
+ end
81
+
82
+ def transform_tbx_inline(node)
83
+ case node
84
+ when String
85
+ [:content, node]
86
+ when Metanorma::Document::Components::Inline::EmRawElement
87
+ [:italic, build_tbx_italic(node)]
88
+ when Metanorma::Document::Components::Inline::StrongRawElement
89
+ [:bold, build_tbx_bold(node)]
90
+ when Metanorma::Document::Components::Inline::SubElement
91
+ [:sub, transform_sub(node)]
92
+ when Metanorma::Document::Components::Inline::SupElement
93
+ [:sup, transform_sup(node)]
94
+ when Metanorma::Document::Components::Inline::XrefElement
95
+ [:xref, transform_xref(node)]
96
+ when Metanorma::Document::Components::Inline::ErefElement
97
+ [:std, transform_eref(node)]
98
+ when Metanorma::Document::Components::Inline::FnElement
99
+ [:xref, transform_fn(node)]
100
+ when Metanorma::Document::Components::Inline::LinkElement
101
+ [:ext_link, transform_link(node)]
102
+ when Metanorma::Document::Components::Inline::StemInlineElement
103
+ [:inline_formula, transform_stem(node)]
104
+ when Metanorma::Document::Components::Inline::TtElement
105
+ [:monospace, transform_monospace(node)]
106
+ end
107
+ end
108
+
109
+ def build_tbx_italic(node)
110
+ ::Sts::TbxIsoTml::Italic.new do |i|
111
+ apply_inline_content(node, i)
112
+ end
113
+ end
114
+
115
+ def build_tbx_bold(node)
116
+ ::Sts::TbxIsoTml::Bold.new do |b|
117
+ apply_inline_content(node, b)
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ def transform_bold(node)
124
+ ::Sts::IsoSts::Bold.new do |b|
125
+ apply_inline_content(node, b)
126
+ end
127
+ end
128
+
129
+ def transform_italic(node)
130
+ ::Sts::IsoSts::Italic.new do |i|
131
+ apply_inline_content(node, i)
132
+ end
133
+ end
134
+
135
+ def transform_sub(node)
136
+ ::Sts::NisoSts::Sub.new do |s|
137
+ s.content node.content if node.content
138
+ end
139
+ end
140
+
141
+ def transform_sup(node)
142
+ ::Sts::NisoSts::Sup.new do |s|
143
+ apply_inline_content(node, s)
144
+ end
145
+ end
146
+
147
+ def transform_monospace(node)
148
+ content = node.content || extract_text(node)
149
+ ::Sts::NisoSts::Monospace.new do |m|
150
+ m.content content if content
151
+ end
152
+ end
153
+
154
+ def transform_smallcap(node)
155
+ content = node.content || extract_text(node)
156
+ ::Sts::NisoSts::Sc.new do |s|
157
+ s.content content if content
158
+ end
159
+ end
160
+
161
+ def transform_xref(node)
162
+ rid = remap_id(node.target)
163
+ xref = ::Sts::TbxIsoTml::Xref.new
164
+ xref.rid = rid
165
+ xref.ref_type = ref_type_for(node.target)
166
+ text = extract_text(node)
167
+ xref.value = text if text && !text.empty?
168
+ xref
169
+ end
170
+
171
+ def transform_eref(node)
172
+ node.bibitemid
173
+ citeas = node.citeas
174
+
175
+ std = ::Sts::IsoSts::Std.new
176
+ std.std_id = citeas
177
+ std.type = "dated"
178
+
179
+ std_ref = ::Sts::IsoSts::StdRef.new
180
+ ref_text = citeas.to_s
181
+ if node.locality_stack && !node.locality_stack.empty?
182
+ localities = node.locality_stack.map do |ls|
183
+ Array(ls.bib_locality).map do |loc|
184
+ if loc.reference_from
185
+ "#{loc.type} #{loc.reference_from}"
186
+ else
187
+ loc.type.to_s
188
+ end
189
+ end
190
+ end.flatten.join(", ")
191
+ ref_text = "#{ref_text}, #{localities}" unless localities.empty?
192
+ end
193
+ std_ref.content = [ref_text]
194
+ std.std_ref std_ref
195
+ std
196
+ end
197
+
198
+ def transform_fn(node)
199
+ text = extract_fn_text(node)
200
+ fn_paragraphs = build_fn_paragraphs(node)
201
+ entry = @context.footnote_collector.register(text,
202
+ paragraphs: fn_paragraphs)
203
+
204
+ xref = ::Sts::TbxIsoTml::Xref.new
205
+ xref.rid = entry[:id]
206
+ xref.ref_type = "fn"
207
+ xref.value = "<sup>#{entry[:number]})</sup>"
208
+ xref
209
+ end
210
+
211
+ def build_fn_paragraphs(node)
212
+ paras = []
213
+ return paras unless node.p && !node.p.empty?
214
+
215
+ node.p.each do |para|
216
+ fn_para = ::Sts::IsoSts::Paragraph.new
217
+ apply_inline_content(para, fn_para)
218
+ paras << fn_para
219
+ end
220
+ paras
221
+ end
222
+
223
+ def extract_fn_text(node)
224
+ parts = []
225
+ if node.p && !node.p.empty?
226
+ node.p.each do |para|
227
+ text = extract_text(para)
228
+ parts << text if text && !text.empty?
229
+ end
230
+ end
231
+ parts.join(" ")
232
+ end
233
+
234
+ def transform_link(node)
235
+ link = ::Sts::NisoSts::ExtLink.new
236
+ link.xlink_href = node.target if node.target
237
+ text = extract_text(node)
238
+ link.content = [text] if text && !text.empty?
239
+ link
240
+ end
241
+
242
+ def transform_br(_node)
243
+ ::Sts::IsoSts::Break.new
244
+ end
245
+
246
+ def transform_stem(node)
247
+ formula = ::Sts::IsoSts::InlineFormula.new
248
+ if node.content
249
+ formula.content = [node.content]
250
+ end
251
+ formula
252
+ end
253
+
254
+ def transform_span(node)
255
+ styled = ::Sts::IsoSts::StyledContent.new
256
+ styled.style_type = node.style if node.style
257
+ apply_inline_content(node, styled)
258
+ styled
259
+ end
260
+
261
+ def transform_bcp14(node)
262
+ content = extract_text(node)
263
+ ::Sts::IsoSts::Bold.new do |b|
264
+ b.content content if content
265
+ end
266
+ end
267
+
268
+ def ref_type_for(target)
269
+ return "sec" unless target
270
+
271
+ case target
272
+ when /^term_/
273
+ "term-sec"
274
+ when /^tab_/
275
+ "table"
276
+ when /^fig_/
277
+ "fig"
278
+ when /^formula_/
279
+ "disp-formula"
280
+ when /^fn_/
281
+ "fn"
282
+ when /^biblref_/, /^sec_bibl/
283
+ "bibr"
284
+ when /^app_/, /^sec_[A-Z]/
285
+ "app"
286
+ else
287
+ "sec"
288
+ end
289
+ end
290
+ end
291
+ end
292
+ end
293
+ end
@@ -0,0 +1,374 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Iso
5
+ module Sts
6
+ class Transformer::IsoMetaTransformer < Transformer::Base
7
+ include Transformer::ContentText
8
+
9
+ DOC_TYPE_MAP = {
10
+ "international-standard" => "IS",
11
+ "technical-specification" => "TS",
12
+ "technical-report" => "TR",
13
+ "publicly-available-specification" => "PAS",
14
+ "international-workshop-agreement" => "IWA",
15
+ "guide" => "GUIDE",
16
+ "amendment" => "Amd",
17
+ "technical-corrigendum" => "TCor",
18
+ "committee-document" => "CD",
19
+ "recommendation" => "R",
20
+ }.freeze
21
+
22
+ def transform(bibdata)
23
+ build_ordered(::Sts::IsoSts::IsoMeta) do |m|
24
+ title_wraps_for(bibdata).each { |tw| m.title_wrap tw }
25
+ m.doc_ident doc_ident_for(bibdata)
26
+ m.std_ident std_ident_for(bibdata)
27
+ std_refs_for(bibdata).each { |sr| m.std_ref sr }
28
+ m.doc_ref doc_ref_for(bibdata)
29
+ release_dates_for(bibdata).each { |rd| m.release_date rd }
30
+ m.comm_ref comm_ref_for(bibdata)
31
+ if (sec = secretariat_for(bibdata))
32
+ m.secretariat sec
33
+ end
34
+ ics_codes_for(bibdata).each { |i| m.ics i }
35
+ permissions_for(bibdata).each { |p| m.permissions p }
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def title_wraps_for(bibdata)
42
+ wraps = []
43
+
44
+ languages_for(bibdata).each do |lang|
45
+ title = title_for_language(bibdata, lang)
46
+ next unless title
47
+
48
+ tw = build_ordered(::Sts::IsoSts::TitleWrap)
49
+ tw.xml_lang = lang
50
+
51
+ intro_text = title_intro_text(title)
52
+ tw.intro = ::Sts::IsoSts::TitleIntro.new(content: [intro_text]) if intro_text
53
+
54
+ main_text = title_main_text(title)
55
+ tw.main = ::Sts::IsoSts::TitleMain.new(content: [main_text]) if main_text
56
+
57
+ compl_text = title_compl_text(title)
58
+ tw.compl = ::Sts::IsoSts::TitleCompl.new(content: [compl_text]) if compl_text
59
+
60
+ full_text = [intro_text, main_text, compl_text].compact.join(" — ")
61
+ tw.full = ::Sts::IsoSts::TitleFull.new(content: [full_text]) if full_text
62
+
63
+ wraps << tw
64
+ end
65
+
66
+ wraps
67
+ end
68
+
69
+ def title_for_language(bibdata, lang)
70
+ titles = bibdata.titles
71
+ titles = titles.items if titles.is_a?(Lutaml::Model::Collection)
72
+ Array(titles).find do |t|
73
+ t_lang = t.language || t.lang
74
+ t_lang == lang
75
+ end
76
+ end
77
+
78
+ def title_intro_text(title)
79
+ ti = title.title_intro
80
+ extract_text_value(ti) if ti
81
+ end
82
+
83
+ def title_main_text(title)
84
+ tm = title.title_main
85
+ if tm
86
+ extract_text_value(tm)
87
+ elsif title.content
88
+ extract_text_value(title)
89
+ end
90
+ end
91
+
92
+ def title_compl_text(title)
93
+ tp = title.title_part
94
+ extract_text_value(tp) if tp
95
+ end
96
+
97
+ def doc_ident_for(bibdata)
98
+ di = ::Sts::IsoSts::DocumentIdentification.new
99
+ di.sdo = ::Sts::NisoSts::Sdo.new(content: [publisher_for(bibdata)])
100
+
101
+ ext = bibdata.ext
102
+ if ext&.structuredidentifier
103
+ si = ext.structuredidentifier
104
+ proj_num = extract_text_value(si.project_number || si)
105
+ di.proj_id = ::Sts::NisoSts::ProjId.new(content: [proj_num]) if proj_num && !proj_num.empty?
106
+ end
107
+
108
+ lang = primary_language(bibdata)
109
+ di.language = ::Sts::IsoSts::Language.new(content: [lang]) if lang
110
+
111
+ release_ver = release_version_for(bibdata)
112
+ di.release_version = ::Sts::NisoSts::ReleaseVersion.new(content: [release_ver]) if release_ver
113
+
114
+ di
115
+ end
116
+
117
+ def std_ident_for(bibdata)
118
+ si = ::Sts::IsoSts::StandardIdentification.new
119
+ si.originator = ::Sts::NisoSts::Originator.new(content: [publisher_for(bibdata)])
120
+
121
+ doctype_abbrev = doctype_abbreviation(bibdata)
122
+ si.doc_type = ::Sts::NisoSts::DocType.new(content: [doctype_abbrev]) if doctype_abbrev
123
+
124
+ if bibdata.docnumber
125
+ si.doc_number = ::Sts::NisoSts::DocNumber.new(content: [bibdata.docnumber])
126
+ end
127
+
128
+ ext = bibdata.ext
129
+ if ext&.structuredidentifier
130
+ si_struct = ext.structuredidentifier
131
+ if si_struct.partnumber
132
+ si.part_number = ::Sts::NisoSts::PartNumber.new(content: [si_struct.partnumber.to_s])
133
+ end
134
+ end
135
+
136
+ if bibdata.edition && !bibdata.edition.empty?
137
+ edition_val = bibdata.edition.is_a?(Array) ? bibdata.edition.first : bibdata.edition
138
+ edition_text = extract_text_value(edition_val) || edition_val.to_s
139
+ si.edition = ::Sts::IsoSts::Edition.new(content: [edition_text]) if edition_text && !edition_text.empty?
140
+ end
141
+
142
+ if bibdata.version
143
+ ver = bibdata.version
144
+ ver_text = ver.revision_date || "1"
145
+ si.version = ::Sts::NisoSts::Version.new(content: [ver_text.to_s])
146
+ end
147
+
148
+ si
149
+ end
150
+
151
+ def std_refs_for(bibdata)
152
+ refs = []
153
+
154
+ identifiers = doc_identifiers(bibdata)
155
+ primary_id = identifiers.first
156
+ return refs unless primary_id
157
+
158
+ ref_text = extract_text_value(primary_id) || primary_id.to_s
159
+ if ref_text && !ref_text.empty?
160
+ sr = ::Sts::IsoSts::StdRef.new
161
+ sr.type = "dated"
162
+ sr.content = [ref_text]
163
+ refs << sr
164
+
165
+ undated = undated_ref(ref_text)
166
+ if undated != ref_text
167
+ sr2 = ::Sts::IsoSts::StdRef.new
168
+ sr2.type = "undated"
169
+ sr2.content = [undated]
170
+ refs << sr2
171
+ end
172
+ end
173
+
174
+ refs
175
+ end
176
+
177
+ def doc_ref_for(bibdata)
178
+ pub = publisher_for(bibdata)
179
+ num = bibdata.docnumber
180
+ return nil unless pub && num
181
+
182
+ lang = primary_language(bibdata)
183
+ ref_text = "#{pub} #{num}"
184
+ ref_text += " (#{lang})" if lang && lang != "en"
185
+
186
+ ::Sts::IsoSts::DocRef.new(content: [ref_text])
187
+ end
188
+
189
+ def release_dates_for(bibdata)
190
+ dates = []
191
+ return dates unless bibdata.date
192
+
193
+ Array(bibdata.date).each do |d|
194
+ next unless d.type == "released"
195
+
196
+ date_val = d.on&.content || extract_text_value(d)
197
+ if date_val
198
+ rd = ::Sts::IsoSts::ReleaseDate.new
199
+ rd.content = [date_val.to_s]
200
+ dates << rd
201
+ end
202
+ end
203
+
204
+ dates
205
+ end
206
+
207
+ def comm_ref_for(bibdata)
208
+ eg = bibdata.ext&.editorial_group
209
+ return nil unless eg
210
+
211
+ parts = []
212
+ tc = eg.technical_committee
213
+ if tc
214
+ if tc.is_a?(Hash)
215
+ parts << "ISO/#{tc['type']} #{tc['number']}"
216
+ elsif tc.number
217
+ parts << extract_text_value(tc)
218
+ end
219
+ end
220
+
221
+ return nil if parts.empty?
222
+
223
+ ::Sts::IsoSts::CommRef.new(content: [parts.join("/")])
224
+ end
225
+
226
+ def secretariat_for(bibdata)
227
+ eg = bibdata.ext&.editorial_group
228
+ return nil unless eg
229
+
230
+ sec = eg.secretariat
231
+ return nil unless sec
232
+
233
+ ::Sts::IsoSts::Secretariat.new(content: [sec.to_s])
234
+ end
235
+
236
+ def ics_codes_for(bibdata)
237
+ ics_list = bibdata.ext&.ics
238
+ return [] unless ics_list
239
+
240
+ Array(ics_list).filter_map do |ics|
241
+ code = ics.code
242
+ next unless code
243
+
244
+ i = ::Sts::NisoSts::Ics.new
245
+ i.ics_code = ::Sts::NisoSts::IcsCode.new(content: [code.to_s])
246
+ i
247
+ end
248
+ end
249
+
250
+ def permissions_for(bibdata)
251
+ perms = []
252
+ return perms unless bibdata.copyright
253
+
254
+ Array(bibdata.copyright).each do |cr|
255
+ perm = build_ordered(::Sts::IsoSts::Permissions) do |p|
256
+ p.copyright_statement = ::Sts::IsoSts::CopyrightStatement.new(
257
+ content: ["All rights reserved"],
258
+ )
259
+
260
+ if cr.from
261
+ p.copyright_year = ::Sts::IsoSts::CopyrightYear.new(
262
+ content: [cr.from.to_s],
263
+ )
264
+ end
265
+
266
+ if cr.owner
267
+ owners = cr.owner.is_a?(Array) ? cr.owner : [cr.owner]
268
+ owners.each do |owner|
269
+ name = owner.organization || owner
270
+ name_text = if name.name
271
+ extract_text_value(name.name) || name.name.to_s
272
+ elsif name.abbreviation
273
+ extract_text_value(name.abbreviation) || name.abbreviation.to_s
274
+ else
275
+ name.to_s
276
+ end
277
+ next if name_text.empty?
278
+
279
+ p.copyright_holder = ::Sts::IsoSts::CopyrightHolder.new(
280
+ content: [name_text],
281
+ )
282
+ end
283
+ end
284
+ end
285
+
286
+ perms << perm
287
+ end
288
+
289
+ perms
290
+ end
291
+
292
+ def publisher_for(bibdata)
293
+ return "ISO" unless bibdata.contributor
294
+
295
+ publisher = Array(bibdata.contributor).find do |c|
296
+ roles = c.role
297
+ roles = [roles] unless roles.is_a?(Array)
298
+ roles&.any? do |r|
299
+ rtype = r.type || r
300
+ rtype.to_s.include?("publisher")
301
+ end
302
+ end
303
+
304
+ return "ISO" unless publisher
305
+
306
+ org = publisher.organization || publisher
307
+ abbr = org.abbreviation
308
+ abbr_text = extract_text_value(abbr) || abbr.to_s
309
+ abbr_text.empty? ? "ISO" : abbr_text
310
+ end
311
+
312
+ def doctype_abbreviation(bibdata)
313
+ dt = bibdata.ext&.doctype
314
+ return nil unless dt
315
+
316
+ dt = Array(dt).first if dt.is_a?(Array)
317
+
318
+ value = dt.is_a?(String) ? dt : (dt.value || dt.abbreviation || dt.to_s)
319
+
320
+ DOC_TYPE_MAP[value] || value
321
+ end
322
+
323
+ def release_version_for(bibdata)
324
+ status = bibdata.status
325
+ return nil unless status
326
+
327
+ stage = status.stage
328
+ return nil unless stage
329
+
330
+ stage_val = extract_text_value(stage) || stage.to_s
331
+
332
+ stage_abbrev = status.stage_abbreviation
333
+ abbrev = extract_text_value(stage_abbrev) if stage_abbrev
334
+
335
+ case stage_val
336
+ when "60" then "IS"
337
+ when "50" then "FDIS"
338
+ when "40" then "DIS"
339
+ when "30" then "CD"
340
+ when "20" then "WD"
341
+ else abbrev || nil
342
+ end
343
+ end
344
+
345
+ def languages_for(bibdata)
346
+ langs = []
347
+ if bibdata.language
348
+ Array(bibdata.language).each do |l|
349
+ langs << (l.is_a?(String) ? l : (l.value || l.to_s))
350
+ end
351
+ end
352
+ langs.empty? ? ["en"] : langs
353
+ end
354
+
355
+ def primary_language(bibdata)
356
+ languages_for(bibdata).first
357
+ end
358
+
359
+ def doc_identifiers(bibdata)
360
+ return [] unless bibdata.doc_identifier
361
+
362
+ Array(bibdata.doc_identifier).select do |di|
363
+ type = di.type
364
+ !type || type == "ISO" || type == "std" || type == "URN"
365
+ end
366
+ end
367
+
368
+ def undated_ref(ref)
369
+ ref.sub(/:\d{4}$/, "")
370
+ end
371
+ end
372
+ end
373
+ end
374
+ end