metanorma-ieee 1.4.7 → 1.4.8

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.
@@ -103,7 +103,7 @@ module IsoDoc
103
103
  <semx element='related' source='#{adm['source']}' type='equivalent'><fmt-preferred>#{to_xml(adm)}</p></semx></fmt-preferred>
104
104
  TERM
105
105
  out.parent.next = <<~TERM
106
- <term><fmt-preferred>#{to_xml(adm)}</fmt-preferred>
106
+ <term #{add_id_text}><fmt-preferred>#{to_xml(adm)}</fmt-preferred>
107
107
  <fmt-related>
108
108
  <semx element="related" source="#{pref['source']}" type="see"><fmt-preferred>#{to_xml(pref)}</fmt-preferred></semx>
109
109
  </fmt-related>
@@ -82,15 +82,15 @@ module IsoDoc
82
82
  true
83
83
  end
84
84
 
85
- def creatornames(bibitem)
85
+ def creatornames(bib)
86
86
  ::Relaton::Render::Ieee::General
87
87
  .new(language: @lang, i18nhash: @i18n.get,
88
- # template: { (bibitem["type"] || "misc").to_sym =>
88
+ # template: { (bib["type"] || "misc").to_sym =>
89
89
  # "{{ creatornames }}" },
90
90
  template: "{{ creatornames }}",
91
- extenttemplate: { (bibitem["type"] || "misc").to_sym => "{{page}}" },
92
- sizetemplate: { (bibitem["type"] || "misc").to_sym => "{{data}}" })
93
- .render1(RelatonBib::XMLParser.from_xml(bibitem.to_xml))
91
+ extenttemplate: { (bib["type"] || "misc").to_sym => "{{page}}" },
92
+ sizetemplate: { (bib["type"] || "misc").to_sym => "{{data}}" })
93
+ .render1(RelatonBib::XMLParser.from_xml(bib.to_xml))
94
94
  end
95
95
 
96
96
  def bibliography_bibitem_number1(bibitem, idx, normative)
@@ -119,7 +119,8 @@ module IsoDoc
119
119
  def availability_note(bib)
120
120
  note = bib.at(ns("./note[@type = 'Availability']")) or return ""
121
121
  id = UUIDTools::UUID.random_create.to_s
122
- "<fn id='_#{id}' reference='#{id}'><p>#{note.content}</p></fn>"
122
+ @new_ids[id] = nil
123
+ "<fn id='#{id}' reference='#{id}'><p>#{note.content}</p></fn>"
123
124
  end
124
125
 
125
126
  def omit_docid_prefix(prefix)
@@ -128,8 +129,7 @@ module IsoDoc
128
129
  end
129
130
 
130
131
  def bracket_if_num(num)
131
- return nil if num.nil?
132
-
132
+ num.nil? and return nil
133
133
  num = num.text.sub(/^\[/, "").sub(/\]$/, "")
134
134
  return "[#{num}]" if /^B?\d+$/.match?(num)
135
135
 
@@ -63,7 +63,7 @@ module IsoDoc
63
63
  def termcontainers(docxml)
64
64
  super
65
65
  docxml.xpath(ns("//term[not(./fmt-definition)]")).each do |t|
66
- t << "<fmt-definition></fmt-definition>"
66
+ t << "<fmt-definition #{add_id_text}></fmt-definition>"
67
67
  end
68
68
  end
69
69
 
@@ -73,12 +73,11 @@ module IsoDoc
73
73
 
74
74
  def collapse_term1(term)
75
75
  ret = collapse_term_template(
76
- pref: term.at(ns("./fmt-preferred")),
76
+ pref: term.at(ns("./fmt-preferred"))&.remove,
77
77
  def: term.at(ns("./fmt-definition")),
78
78
  rels: term.at(ns("./fmt-related"))&.remove,
79
79
  source: term.at(ns("./fmt-termsource"))&.remove,
80
80
  )
81
- term.at(ns("./fmt-preferred"))&.remove
82
81
  term.at(ns("./fmt-admitted"))&.remove
83
82
  ins = term.at(ns("./fmt-definition")) and
84
83
  ins.children = ret
@@ -86,24 +85,28 @@ module IsoDoc
86
85
 
87
86
  def collapse_term_related(rels)
88
87
  rels or return
88
+ collapse_term_related1(rels)
89
+ ret = rels.xpath(ns("./p")).map do |x|
90
+ to_xml(x.children).strip
91
+ end.join(". ")
92
+ ret += "." unless ret.empty?
93
+ ret
94
+ end
95
+
96
+ def collapse_term_related1(rels)
89
97
  rels.xpath(ns("./p")).each do |p|
90
98
  orig = p.at(ns(".//semx[@element = 'related']"))
91
99
  reln = "<em>#{@i18n.relatedterms[orig['type']]}:</em> "
92
100
  p.add_first_child reln
93
101
  p.xpath(ns(".//semx[@element = 'related']")).each do |r|
94
- r.at(ns("./fmt-preferred")) or r.add_first_child "**RELATED TERM NOT FOUND**"
102
+ r.at(ns("./fmt-preferred")) or
103
+ r.add_first_child "**RELATED TERM NOT FOUND**"
95
104
  end
96
105
  end
97
- ret = rels.xpath(ns("./p")).map do |x|
98
- to_xml(x.children).strip
99
- end.join(". ")
100
- ret += "." unless ret.empty?
101
- ret
102
106
  end
103
107
 
104
108
  def collapse_term_template(opt)
105
109
  defn, multiblock = collapse_unwrap_definition(opt[:def])
106
- #src = nil
107
110
  opt[:source] and src = "(#{to_xml(opt[:source].remove.children).strip})"
108
111
  t = collapse_term_pref(opt)
109
112
  tail = "#{collapse_term_related(opt[:rels])} #{src}"
@@ -171,9 +171,6 @@ module IsoDoc
171
171
 
172
172
  def ol_numbering1(elem, idx)
173
173
  elem["type"] = ol_depth_rotate(elem, idx).to_s
174
- elem.xpath(ns("./li")).each do |li|
175
- li["id"] ||= "_#{UUIDTools::UUID.random_create}"
176
- end
177
174
  end
178
175
 
179
176
  # overrides IsoDoc:: XrefGen::OlTypeProvider: we trigger
@@ -1,51 +1,10 @@
1
1
  require_relative "cleanup_ref"
2
+ require_relative "cleanup_boilerplate"
2
3
  require_relative "term_lookup_cleanup"
3
4
 
4
5
  module Metanorma
5
6
  module Ieee
6
7
  class Converter < Standoc::Converter
7
- def initial_boilerplate(xml, isodoc)
8
- intro_boilerplate(xml, isodoc)
9
- super if @document_scheme == "ieee-sa-2021"
10
- xml.at("//boilerplate") or return
11
- initial_note(xml)
12
- word_usage(xml)
13
- participants(xml)
14
- footnote_boilerplate_renumber(xml)
15
- end
16
-
17
- def footnote_boilerplate_renumber(xml)
18
- xml.xpath("//boilerplate//fn").each_with_index do |f, i|
19
- f["reference"] = "_boilerplate_#{i + 1}"
20
- end
21
- end
22
-
23
- def intro_boilerplate(xml, isodoc)
24
- intro = xml.at("//introduction/title") or return
25
- template = <<~ADM
26
- This introduction is not part of P{{ docnumeric }}{% if draft %}/D{{ draft }}{% endif %}, {{ full_doctitle }}
27
- ADM
28
- adm = isodoc.populate_template(template)
29
- intro.next = "<admonition>#{adm}</admonition>"
30
- end
31
-
32
- def initial_note(xml)
33
- n = xml.at("//boilerplate//note[@anchor = 'boilerplate_front']")
34
- s = xml.at("//sections")
35
- (n && s) or return
36
- s.children.empty? and s << " "
37
- s.children.first.previous = n.remove
38
- end
39
-
40
- def word_usage(xml)
41
- @document_scheme == "ieee-sa-2021" or return
42
- n = xml.at("//boilerplate//clause[@anchor = 'boilerplate_word_usage']")
43
- &.remove
44
- s = xml.at("//clause[@type = 'overview']")
45
- (n && s) or return
46
- s << n
47
- end
48
-
49
8
  def obligations_cleanup_norm(xml)
50
9
  super
51
10
  xml.xpath("//sections/clause").each do |r|
@@ -94,6 +53,7 @@ module Metanorma
94
53
  ins = n.at("./p[last()]")
95
54
  ins << "<fn reference='_boilerplate_cleanup1'>" \
96
55
  "<p>#{@i18n.note_inform_fn}</p></fn>"
56
+ add_id(ins.last_element_child)
97
57
  end
98
58
 
99
59
  def table_footnote_renumber1(fnote, idx, seen)
@@ -135,7 +95,7 @@ module Metanorma
135
95
 
136
96
  def boilerplate_isodoc(xmldoc)
137
97
  x = xmldoc.dup
138
- x.root.add_namespace(nil, self.class::XML_NAMESPACE)
98
+ x.root.add_namespace(nil, xml_namespace)
139
99
  xml = Nokogiri::XML(x.to_xml)
140
100
  i = isodoc(@lang, @script, @locale)
141
101
  i.bibdata_i18n(xml.at("//xmlns:bibdata"))
@@ -143,75 +103,6 @@ module Metanorma
143
103
  i
144
104
  end
145
105
 
146
- PARTICIPANT_BOILERPLATE_LOCATIONS =
147
- { "boilerplate-participants-wg": "working group",
148
- "boilerplate-participants-bg": "balloting group",
149
- "boilerplate-participants-sb": "standards board",
150
- "boilerplate-participants-blank": nil }.freeze
151
-
152
- def participants(xml)
153
- @document_scheme == "ieee-sa-2021" or return
154
- PARTICIPANT_BOILERPLATE_LOCATIONS.each do |k, v|
155
- populate_participants(xml, k.to_s, v)
156
- end
157
- p = xml.at(".//p[@type = 'emeritus_sign']")
158
- ul = xml.at("//clause[@anchor = 'boilerplate-participants-sb']//ul")
159
- p && ul and ul.next = p
160
- xml.at("//sections//clause[@type = 'participants']")&.remove
161
- end
162
-
163
- def populate_participants(xml, target, subtitle)
164
- t = xml.at("//clause[@anchor = '#{target}']/membership") or return
165
- s = xml.xpath("//clause[@type = 'participants']/clause").detect do |x|
166
- n = x.at("./title") and n.text.strip.downcase == subtitle
167
- end
168
- t.replace(populate_participants1(s || t))
169
- end
170
-
171
- def populate_participants1(clause)
172
- participants_dl_to_ul(clause)
173
- clause.xpath(".//ul | .//ol").each do |ul|
174
- ul.name = "ul"
175
- ul.xpath("./li").each { |li| populate_participants2(li) }
176
- ul.xpath(".//p[normalize-space() = '']").each(&:remove)
177
- end
178
- clause.at("./title")&.remove
179
- clause.children.to_xml
180
- end
181
-
182
- def participants_dl_to_ul(clause)
183
- clause.xpath(".//dl").each do |dl|
184
- dl.ancestors("dl, ul, ol").empty? or next
185
- dl.name = "ul"
186
- dl.xpath("./dt").each(&:remove)
187
- dl.xpath("./dd").each { |li| li.name = "li" }
188
- end
189
- end
190
-
191
- def populate_participants2(list)
192
- curr = list
193
- p = curr.at("./p[text() != '']") and curr = p
194
- if dl = curr.at("./dl")
195
- ret = extract_participants(dl)
196
- dl.children = ret.keys.map do |k|
197
- "<dt>#{k}</dt><dd><p>#{ret[k]}</p></dd>"
198
- end.join
199
- else list.children = "<dl><dt>name</dt><dd><p>#{curr.children.to_xml}" \
200
- "</p></dd><dt>role</dt><dd><p>member</p></dd></dl>"
201
- end
202
- end
203
-
204
- def extract_participants(dlist)
205
- key = ""
206
- map = dlist.xpath("./dt | ./dd").each_with_object({}) do |dtd, m|
207
- (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) or
208
- m[key.strip.downcase] = text_from_paras(dtd)
209
- end
210
- map["company"] &&= "<span class='organization'>#{map['company']}</span>"
211
- map["role"] ||= "member"
212
- map
213
- end
214
-
215
106
  def text_from_paras(node)
216
107
  r = node.at("./p") and node = r
217
108
  node.children.to_xml.strip
@@ -0,0 +1,119 @@
1
+ module Metanorma
2
+ module Ieee
3
+ class Converter < Standoc::Converter
4
+ def initial_boilerplate(xml, isodoc)
5
+ intro_boilerplate(xml, isodoc)
6
+ super if @document_scheme == "ieee-sa-2021"
7
+ xml.at("//boilerplate") or return
8
+ initial_note(xml)
9
+ word_usage(xml)
10
+ participants(xml)
11
+ footnote_boilerplate_renumber(xml)
12
+ end
13
+
14
+ def footnote_boilerplate_renumber(xml)
15
+ xml.xpath("//boilerplate//fn").each_with_index do |f, i|
16
+ f["reference"] = "_boilerplate_#{i + 1}"
17
+ end
18
+ end
19
+
20
+ def intro_boilerplate(xml, isodoc)
21
+ intro = xml.at("//introduction/title") or return
22
+ template = <<~ADM
23
+ This introduction is not part of P{{ docnumeric }}{% if draft %}/D{{ draft }}{% endif %}, {{ full_doctitle }}
24
+ ADM
25
+ adm = isodoc.populate_template(template)
26
+ intro.next = "<admonition>#{adm}</admonition>"
27
+ add_id(intro.next)
28
+ end
29
+
30
+ def initial_note(xml)
31
+ n = xml.at("//boilerplate//note[@anchor = 'boilerplate_front']")
32
+ s = xml.at("//sections")
33
+ (n && s) or return
34
+ s.children.empty? and s << " "
35
+ s.children.first.previous = n.remove
36
+ end
37
+
38
+ def word_usage(xml)
39
+ @document_scheme == "ieee-sa-2021" or return
40
+ n = xml.at("//boilerplate//clause[@anchor = 'boilerplate_word_usage']")
41
+ &.remove
42
+ s = xml.at("//clause[@type = 'overview']")
43
+ (n && s) or return
44
+ s << n
45
+ end
46
+
47
+ PARTICIPANT_BOILERPLATE_LOCATIONS =
48
+ { "boilerplate-participants-wg": "working group",
49
+ "boilerplate-participants-bg": "balloting group",
50
+ "boilerplate-participants-sb": "standards board",
51
+ "boilerplate-participants-blank": nil }.freeze
52
+
53
+ def participants(xml)
54
+ @document_scheme == "ieee-sa-2021" or return
55
+ PARTICIPANT_BOILERPLATE_LOCATIONS.each do |k, v|
56
+ populate_participants(xml, k.to_s, v)
57
+ end
58
+ p = xml.at(".//p[@type = 'emeritus_sign']")
59
+ ul = xml.at("//clause[@anchor = 'boilerplate-participants-sb']//ul")
60
+ p && ul and ul.next = p
61
+ xml.at("//sections//clause[@type = 'participants']")&.remove
62
+ end
63
+
64
+ def populate_participants(xml, target, subtitle)
65
+ t = xml.at("//clause[@anchor = '#{target}']/membership") or return
66
+ s = xml.xpath("//clause[@type = 'participants']/clause").detect do |x|
67
+ n = x.at("./title") and n.text.strip.downcase == subtitle
68
+ end
69
+ t.replace(populate_participants1(s || t))
70
+ end
71
+
72
+ def populate_participants1(clause)
73
+ participants_dl_to_ul(clause)
74
+ clause.xpath(".//ul | .//ol").each do |ul|
75
+ ul.name = "ul"
76
+ ul.xpath("./li").each { |li| populate_participants2(li) }
77
+ ul.xpath(".//p[normalize-space() = '']").each(&:remove)
78
+ end
79
+ clause.at("./title")&.remove
80
+ clause.children.to_xml
81
+ end
82
+
83
+ def participants_dl_to_ul(clause)
84
+ clause.xpath(".//dl").each do |dl|
85
+ dl.ancestors("dl, ul, ol").empty? or next
86
+ dl.name = "ul"
87
+ dl.xpath("./dt").each(&:remove)
88
+ dl.xpath("./dd").each { |li| li.name = "li" }
89
+ end
90
+ end
91
+
92
+ def populate_participants2(list)
93
+ add_id(list)
94
+ curr = list
95
+ p = curr.at("./p[text() != '']") and curr = p
96
+ if dl = curr.at("./dl")
97
+ ret = extract_participants(dl)
98
+ dl.children = ret.keys.map do |k|
99
+ "<dt>#{k}</dt><dd #{add_id_text}><p>#{ret[k]}</p></dd>"
100
+ end.join
101
+ else list.children =
102
+ "<dl><dt>name</dt><dd #{add_id_text}><p>#{curr.children.to_xml}" \
103
+ "</p></dd><dt>role</dt><dd #{add_id_text}><p>member</p></dd></dl>"
104
+ end
105
+ end
106
+
107
+ def extract_participants(dlist)
108
+ key = ""
109
+ map = dlist.xpath("./dt | ./dd").each_with_object({}) do |dtd, m|
110
+ (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) or
111
+ m[key.strip.downcase] = text_from_paras(dtd)
112
+ end
113
+ map["company"] &&= "<span class='organization'>#{map['company']}</span>"
114
+ map["role"] ||= "member"
115
+ map
116
+ end
117
+ end
118
+ end
119
+ end
@@ -44,7 +44,7 @@ module Metanorma
44
44
  when "standard", "techreport" then id
45
45
  else
46
46
  bib1 = bib.dup
47
- bib1.add_namespace(nil, self.class::XML_NAMESPACE)
47
+ bib1.add_namespace(nil, xml_namespace)
48
48
  n = @i.creatornames(bib1)
49
49
  n.nil? && bib["type"].nil? and n = id
50
50
  n
@@ -9,9 +9,6 @@ require_relative "validate"
9
9
  module Metanorma
10
10
  module Ieee
11
11
  class Converter < Standoc::Converter
12
- XML_ROOT_TAG = "ieee-standard".freeze
13
- XML_NAMESPACE = "https://www.metanorma.org/ns/ieee".freeze
14
-
15
12
  register_for "ieee"
16
13
 
17
14
  def init(node)
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
3
- <!-- VERSION v2.0.6 -->
3
+ <!-- VERSION v2.0.7 -->
4
4
 
5
5
  <!--
6
6
  ALERT: cannot have root comments, because of https://github.com/metanorma/metanorma/issues/437
@@ -76,6 +76,7 @@ but to `@anchor`, the user-supplied cross-reference</a:documentation>
76
76
  <a:documentation>Title(s) of a clause</a:documentation>
77
77
  <element name="title">
78
78
  <a:documentation>Title proper for a clause</a:documentation>
79
+ <ref name="RequiredId"/>
79
80
  <zeroOrMore>
80
81
  <ref name="TextElement"/>
81
82
  </zeroOrMore>
@@ -83,10 +84,19 @@ but to `@anchor`, the user-supplied cross-reference</a:documentation>
83
84
  <zeroOrMore>
84
85
  <element name="variant-title">
85
86
  <a:documentation>Alternate title for a clause</a:documentation>
87
+ <ref name="RequiredId"/>
86
88
  <ref name="TypedTitleString"/>
87
89
  </element>
88
90
  </zeroOrMore>
89
91
  </define>
92
+ <define name="tname">
93
+ <element name="name">
94
+ <ref name="RequiredId"/>
95
+ <oneOrMore>
96
+ <ref name="NestedTextElement"/>
97
+ </oneOrMore>
98
+ </element>
99
+ </define>
90
100
  <define name="UlBody">
91
101
  <optional>
92
102
  <ref name="tname">
@@ -475,6 +485,7 @@ normative or informative references, some split references into sections organiz
475
485
  <!-- exclude figures? -->
476
486
  <define name="dd">
477
487
  <element name="dd">
488
+ <ref name="OptionalId"/>
478
489
  <zeroOrMore>
479
490
  <!-- exclude figures? -->
480
491
  <ref name="BasicBlock"/>
@@ -526,6 +537,7 @@ normative or informative references, some split references into sections organiz
526
537
  </choice>
527
538
  </define>
528
539
  <define name="TrAttributes">
540
+ <ref name="OptionalId"/>
529
541
  <optional>
530
542
  <attribute name="style">
531
543
  <a:documentation>CSS style: only background-color supported</a:documentation>
@@ -595,6 +607,7 @@ gives an explicit page orientation</a:documentation>
595
607
  </include>
596
608
  <!-- end overrides -->
597
609
  <define name="FnAttributes" combine="interleave">
610
+ <ref name="RequiredId"/>
598
611
  <optional>
599
612
  <attribute name="hiddenref">
600
613
  <a:documentation>If true, number the footnote as normal, but suppress display of the footnote reference in the document body.
@@ -604,6 +617,7 @@ This is done if the footnote reference is already presented in some other form,
604
617
  </optional>
605
618
  </define>
606
619
  <define name="TdAttributes" combine="interleave">
620
+ <ref name="RequiredId"/>
607
621
  <optional>
608
622
  <attribute name="style">
609
623
  <a:documentation>CSS style: only background-color supported</a:documentation>
@@ -1821,7 +1835,7 @@ used in document amendments</a:documentation>
1821
1835
  </element>
1822
1836
  </define>
1823
1837
  <define name="TermAttributes">
1824
- <ref name="OptionalId"/>
1838
+ <ref name="RequiredId"/>
1825
1839
  <ref name="LocalizedStringAttributes"/>
1826
1840
  <ref name="BlockAttributes"/>
1827
1841
  </define>
@@ -2164,6 +2178,7 @@ used in document amendments</a:documentation>
2164
2178
  <define name="termdefinition">
2165
2179
  <a:documentation>The definition of a term applied in the current document</a:documentation>
2166
2180
  <element name="definition">
2181
+ <ref name="RequiredId"/>
2167
2182
  <optional>
2168
2183
  <attribute name="type">
2169
2184
  <a:documentation>Type of definition, used to differentiate it from other definitions of the same term if present</a:documentation>
@@ -2185,6 +2200,7 @@ used in document amendments</a:documentation>
2185
2200
  </define>
2186
2201
  <define name="verbaldefinition">
2187
2202
  <element name="verbal-definition">
2203
+ <ref name="RequiredId"/>
2188
2204
  <oneOrMore>
2189
2205
  <choice>
2190
2206
  <a:documentation>Content of the verbal representation of the term</a:documentation>
@@ -2205,6 +2221,7 @@ used in document amendments</a:documentation>
2205
2221
  <define name="nonverbalrep">
2206
2222
  <a:documentation>Non-verbal representation of the term</a:documentation>
2207
2223
  <element name="non-verbal-representation">
2224
+ <ref name="RequiredId"/>
2208
2225
  <oneOrMore>
2209
2226
  <choice>
2210
2227
  <a:documentation>Content of the non-verbal representation of the term</a:documentation>
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  module Ieee
3
- VERSION = "1.4.7".freeze
3
+ VERSION = "1.4.8".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-ieee
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.7
4
+ version: 1.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-05-26 00:00:00.000000000 Z
11
+ date: 2025-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: metanorma-standoc
@@ -332,6 +332,7 @@ files:
332
332
  - lib/metanorma/ieee/boilerplate.adoc
333
333
  - lib/metanorma/ieee/boilerplate_wp.adoc
334
334
  - lib/metanorma/ieee/cleanup.rb
335
+ - lib/metanorma/ieee/cleanup_boilerplate.rb
335
336
  - lib/metanorma/ieee/cleanup_ref.rb
336
337
  - lib/metanorma/ieee/converter.rb
337
338
  - lib/metanorma/ieee/front.rb