metanorma-iso 3.4.5 → 3.4.7

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +13 -1
  3. data/Makefile +0 -45
  4. data/lib/isodoc/iso/html/html_iso_titlepage.html +6 -0
  5. data/lib/isodoc/iso/html/style-human.css +0 -4
  6. data/lib/isodoc/iso/html/style-human.scss +0 -2
  7. data/lib/isodoc/iso/html/style-iso.css +0 -2
  8. data/lib/isodoc/iso/html/style-iso.scss +0 -2
  9. data/lib/isodoc/iso/html/word_iso_titlepage-dis.html +14 -0
  10. data/lib/isodoc/iso/html/word_iso_titlepage-prf.html +14 -0
  11. data/lib/isodoc/iso/html/word_iso_titlepage.html +14 -0
  12. data/lib/isodoc/iso/i18n-de.yaml +2 -0
  13. data/lib/isodoc/iso/i18n-en.yaml +4 -0
  14. data/lib/isodoc/iso/i18n-fr.yaml +4 -0
  15. data/lib/isodoc/iso/i18n-ru.yaml +4 -0
  16. data/lib/isodoc/iso/i18n-zh-Hans.yaml +2 -0
  17. data/lib/isodoc/iso/iso.amendment.xsl +648 -83
  18. data/lib/isodoc/iso/iso.international-standard.xsl +648 -83
  19. data/lib/isodoc/iso/metadata.rb +15 -1
  20. data/lib/isodoc/iso/presentation_origin.rb +2 -6
  21. data/lib/isodoc/iso/presentation_xml_convert.rb +16 -1
  22. data/lib/isodoc/iso/word_cleanup.rb +1 -2
  23. data/lib/isodoc/iso/word_convert.rb +11 -0
  24. data/lib/metanorma/iso/basicdoc.rng +31 -6
  25. data/lib/metanorma/iso/cleanup_biblio.rb +55 -15
  26. data/lib/metanorma/iso/front.rb +14 -2
  27. data/lib/metanorma/iso/front_id.rb +8 -2
  28. data/lib/metanorma/iso/isodoc.rng +28 -3
  29. data/lib/metanorma/iso/mathml3-common.rng +257 -0
  30. data/lib/metanorma/iso/mathml3-content.rng +1544 -0
  31. data/lib/metanorma/iso/mathml3-presentation.rng +2324 -0
  32. data/lib/metanorma/iso/mathml3-strict-content.rng +205 -0
  33. data/lib/metanorma/iso/mathml3.rng +23 -0
  34. data/lib/metanorma/iso/metanorma-mathml.rng +45 -0
  35. data/lib/metanorma/iso/publisher_identity.rb +36 -0
  36. data/lib/metanorma/iso/relaton-iso.rng +2 -0
  37. data/lib/metanorma/iso/reqt.rng +10 -2
  38. data/lib/metanorma/iso/validate.rb +1 -1
  39. data/lib/metanorma/iso/validate_section.rb +1 -5
  40. data/lib/metanorma/iso/version.rb +1 -1
  41. data/lib/metanorma-iso.rb +1 -0
  42. data/lib/relaton/render/config.yml +9 -9
  43. data/metanorma-iso.gemspec +1 -1
  44. metadata +11 -7
@@ -92,11 +92,13 @@ module IsoDoc
92
92
  subpart: isoxml.at(ns("#{prefix}/@subpart")),
93
93
  amd: isoxml.at(ns("#{prefix}/@amendment")),
94
94
  add: isoxml.at(ns("#{prefix}/@addendum")),
95
+ sup: isoxml.at(ns("#{prefix}/@supplement")),
96
+ ext: isoxml.at(ns("#{prefix}/@extract")),
95
97
  corr: isoxml.at(ns("#{prefix}/@corrigendum")) }
96
98
  end
97
99
 
98
100
  def title_parts(isoxml, lang)
99
- %w(intro main complementary part amd add).each_with_object({}) do |w, m|
101
+ %w(intro main complementary part amd add sup ext).each_with_object({}) do |w, m|
100
102
  m[w.to_sym] = isoxml.at(ns("//bibdata/title[@type='title-#{w}' and " \
101
103
  "@language='#{lang}']"))
102
104
  end
@@ -123,6 +125,12 @@ module IsoDoc
123
125
  tn[:add] and set(:doctitleaddlabel,
124
126
  title_part_prefix(isoxml, "addendum", lang))
125
127
  tp[:add] and set(:doctitleadd, to_xml(tp[:add].children))
128
+ tn[:sup] and set(:doctitlesuplabel,
129
+ title_part_prefix(isoxml, "supplement", lang))
130
+ tp[:sup] and set(:doctitlesup, to_xml(tp[:sup].children))
131
+ tn[:ext] and set(:doctitleextlabel,
132
+ title_part_prefix(isoxml, "extract", lang))
133
+ tp[:ext] and set(:doctitleext, to_xml(tp[:ext].children))
126
134
  main = compose_title(tp, tn, lang)
127
135
  set(:doctitle, main)
128
136
  end
@@ -144,6 +152,12 @@ module IsoDoc
144
152
  tn[:add] and set(:docsubtitleaddlabel,
145
153
  title_part_prefix(isoxml, "addendum", lang))
146
154
  tp[:add] and set(:docsubtitleadd, to_xml(tp[:add].children))
155
+ tn[:sup] and set(:docsubtitlesuplabel,
156
+ title_part_prefix(isoxml, "supplement", lang))
157
+ tp[:sup] and set(:docsubtitlesup, to_xml(tp[:sup].children))
158
+ tn[:ext] and set(:docsubtitleextlabel,
159
+ title_part_prefix(isoxml, "extract", lang))
160
+ tp[:ext] and set(:docsubtitleext, to_xml(tp[:ext].children))
147
161
  tn[:corr] and set(:docsubtitlecorrlabel,
148
162
  title_part_prefix(isoxml, "corrigendum", lang))
149
163
  main = compose_title(tp, tn, lang)
@@ -84,15 +84,11 @@ module IsoDoc
84
84
  insert_biblio_callout(elem)
85
85
  end
86
86
 
87
- # TODO share with metanorma dir
88
- ISO_PUBLISHER_XPATH = <<~XPATH.freeze
89
- ./contributor[role/@type = 'publisher']/organization[abbreviation = 'ISO' or abbreviation = 'IEC' or name = 'International Organization for Standardization' or name = 'International Electrotechnical Commission']
90
- XPATH
91
-
92
87
  def insert_biblio_callout(elem)
93
88
  semx = elem.document.at("//*[@id = '#{elem['source']}']") or return
94
89
  if ref = @bibitem_lookup[semx["bibitemid"]]
95
- ref.at(ns(ISO_PUBLISHER_XPATH)) and return
90
+ Metanorma::Iso::PublisherIdentity
91
+ .iso_iec_publisher?(ref, ns: method(:ns)) and return
96
92
  # is this reference cited with a [n],
97
93
  # even if it has its own SDO identifier?
98
94
  citeas = ref.at(ns("./docidentifier[@type = 'metanorma-ordinal']")) ||
@@ -16,7 +16,11 @@ module IsoDoc
16
16
  end
17
17
 
18
18
  def convert1(docxml, filename, dir)
19
- @iso_class = instance_of?(IsoDoc::Iso::PresentationXMLConvert)
19
+ # ISO-only (not inheriting flavours, and -- unlike instance_of? --
20
+ # not tastes that reuse this class): gate on the document publisher.
21
+ # metanorma/metanorma-oiml#13.
22
+ @iso_class = Metanorma::Iso::PublisherIdentity
23
+ .iso_publisher?(docxml.at(ns("//bibdata")), ns: method(:ns))
20
24
  if amd?(docxml)
21
25
  @oldsuppressheadingnumbers = @suppressheadingnumbers
22
26
  @suppressheadingnumbers = true
@@ -183,6 +187,17 @@ module IsoDoc
183
187
  ret
184
188
  end
185
189
 
190
+ # ISO mandates sequential bibliography numbering. A `.metanorma`
191
+ # docidentifier (e.g. `[ГОСТ 3295-73]`) must not suppress the
192
+ # autonumber the way it does for other flavours.
193
+ # https://github.com/metanorma/metanorma-iso/issues/1530
194
+ def bibliography_bibitem_number_skip(bibitem)
195
+ implicit_reference(bibitem) ||
196
+ bibitem.at(ns(".//docidentifier[@type = 'metanorma-ordinal']")) ||
197
+ bibitem["suppress_identifier"] == "true" ||
198
+ bibitem["hidden"] == "true" || bibitem.parent["hidden"] == "true"
199
+ end
200
+
186
201
  def admonition_delim(elem)
187
202
  if elem.at("./*[not(self::xmlns:name)]")&.name == "p"
188
203
  " &#x2014; "
@@ -181,8 +181,7 @@ module IsoDoc
181
181
  # do not use in IEC, BSI, where Word does not use list to generate
182
182
  # "Annex A"
183
183
  def annex_toc(annexid)
184
- instance_of?(IsoDoc::Iso::WordConvert) ||
185
- instance_of?(WordDISConvert) or return ""
184
+ @iso_publisher or return ""
186
185
  annexid += 1
187
186
  x = "#{@i18n.annex} #{('@'.ord + annexid).chr} "
188
187
  [x, annexid]
@@ -58,6 +58,17 @@ module IsoDoc
58
58
  end
59
59
  end
60
60
 
61
+ # word_cleanup (make_WordToC / annex_toc) runs on the generated Word
62
+ # HTML, which no longer carries <bibdata>; capture the document's
63
+ # ISO-publisher identity here, off the source presentation XML, and
64
+ # propagate it via @iso_publisher. ISO-only (not IEC/BSI, and --
65
+ # unlike instance_of? -- not tastes reusing this class). oiml#13.
66
+ def convert1(docxml, filename, dir)
67
+ @iso_publisher = Metanorma::Iso::PublisherIdentity
68
+ .iso_publisher?(docxml.at(ns("//bibdata")), ns: method(:ns))
69
+ super
70
+ end
71
+
61
72
  def make_body(xml, docxml)
62
73
  body_attr = { lang: "EN-US", link: "blue", vlink: "#954F72" }
63
74
  xml.body(**body_attr) do |body|
@@ -1902,15 +1902,40 @@ or as the string "auto"</a:documentation>
1902
1902
  <a:documentation>Mathematically formatted text</a:documentation>
1903
1903
  <element name="stem">
1904
1904
  <ref name="StemAttributes"/>
1905
- <oneOrMore>
1906
- <choice>
1905
+ <optional>
1906
+ <text>
1907
1907
  <a:documentation>The content of the mathematically formatted text</a:documentation>
1908
- <text/>
1909
- <ref name="AnyElement"/>
1910
- </choice>
1911
- </oneOrMore>
1908
+ </text>
1909
+ </optional>
1910
+ <optional>
1911
+ <ref name="mathml"/>
1912
+ </optional>
1913
+ <optional>
1914
+ <ref name="asciimath"/>
1915
+ </optional>
1916
+ <optional>
1917
+ <ref name="latexmath"/>
1918
+ </optional>
1912
1919
  </element>
1913
1920
  </define>
1921
+ <define name="latexmath">
1922
+ <a:documentation>Encoding of LatexMath</a:documentation>
1923
+ <element name="latexmath">
1924
+ <text/>
1925
+ </element>
1926
+ </define>
1927
+ <define name="asciimath">
1928
+ <a:documentation>Encoding of AsciiMath</a:documentation>
1929
+ <element name="asciimath">
1930
+ <text/>
1931
+ </element>
1932
+ </define>
1933
+ <define name="mathml">
1934
+ <a:documentation>Encoding of MathML: the official W3C MathML 3.0 grammar (namespace
1935
+ http://www.w3.org/1998/Math/MathML), via the metanorma wrapper in
1936
+ grammars/mathml/. See grammars/mathml/README.adoc and basicdoc-models#35.</a:documentation>
1937
+ <externalRef href="metanorma-mathml.rng"/>
1938
+ </define>
1914
1939
  <define name="StemAttributes">
1915
1940
  <attribute name="type">
1916
1941
  <a:documentation>The notation used to mathematically format the text</a:documentation>
@@ -18,7 +18,8 @@ module Metanorma
18
18
  # ISO as a prefix goes first
19
19
  def docidentifier_cleanup(xml)
20
20
  prefix = get_id_prefix(xml)
21
- amd = @amd || xml.at("//bibdata/ext/doctype")&.text == "addendum"
21
+ amd = @amd ||
22
+ %w(addendum supplement extract).include?(xml.at("//bibdata/ext/doctype")&.text)
22
23
  id = xml.at("//bibdata/ext/structuredidentifier/project-number") and
23
24
  id.content =
24
25
  id_prefix(prefix, id, amd:)
@@ -89,8 +90,34 @@ module Metanorma
89
90
 
90
91
  def bibitem_cleanup(xmldoc)
91
92
  super
92
- unpublished_note(xmldoc)
93
- withdrawn_note(xmldoc)
93
+ cutoff = biblio_cutoff_date(xmldoc)
94
+ unpublished_note(xmldoc, cutoff)
95
+ withdrawn_note(xmldoc, cutoff)
96
+ end
97
+
98
+ # The citing document's publication date: reference status annotations
99
+ # (withdrawn/replaced, under-preparation) are rewound to this date, so a
100
+ # reference is not shown with a status change that only happened *after*
101
+ # the citing document was published. metanorma/metanorma-standoc#941.
102
+ def biblio_cutoff_date(xmldoc)
103
+ bd = xmldoc.at("//bibdata") or return nil
104
+ dates = bd.xpath("./date[@type = 'published' or @type = 'issued' or " \
105
+ "@type = 'circulated']/on").map { |d| iso_date(d.text) }
106
+ if (y = bd.at("./copyright/from")&.text)&.match?(/^\d{4}$/)
107
+ dates << Date.new(y.to_i, 12, 31)
108
+ end
109
+ dates.compact.max
110
+ end
111
+
112
+ # Complete a partial ISO date to the end of its period, so a status change
113
+ # anywhere within the citing document's publication year still counts as
114
+ # having occurred by publication.
115
+ def iso_date(str)
116
+ case str.to_s.strip
117
+ when /^(\d{4})$/ then Date.new($1.to_i, 12, 31)
118
+ when /^(\d{4})-(\d{2})/ then Date.new($1.to_i, $2.to_i, -1)
119
+ else Date.parse(str) rescue nil
120
+ end
94
121
  end
95
122
 
96
123
  def bibitem_note_types(bib)
@@ -99,21 +126,21 @@ module Metanorma
99
126
  end.flatten
100
127
  end
101
128
 
102
- def unpublished_note(xmldoc)
129
+ def unpublished_note(xmldoc, cutoff = nil)
103
130
  xmldoc.xpath("//bibitem[not(./ancestor::bibitem)]").each do |b|
104
131
  n = bibitem_note_types(b)
105
- n.include?("Unpublished-Status") or unpublished_note1(b)
132
+ n.include?("Unpublished-Status") or unpublished_note1(b, cutoff)
106
133
  end
107
134
  end
108
135
 
109
- def unpublished_note1(bibitem)
136
+ def unpublished_note1(bibitem, cutoff = nil)
110
137
  unpublished_ref?(bibitem) and return
111
138
  docid = bibitem.at("./docidentifier[@primary = 'true']") ||
112
139
  bibitem.at("./docidentifier[@type = 'ISO' or @type = 'IEC']") ||
113
140
  bibitem.at("./docidentifier")
114
141
  base_pubid, orig = parse_draft_docid(docid, bibitem)
115
142
  insert_unpub_note(bibitem, @i18n.under_preparation
116
- .sub("%", dated_draft_id(orig, base_pubid)))
143
+ .sub("%", dated_draft_id(orig, base_pubid, cutoff)))
117
144
  draft_biblio_docid(orig, base_pubid, docid)
118
145
  end
119
146
 
@@ -131,24 +158,24 @@ module Metanorma
131
158
  docid.children = new
132
159
  end
133
160
 
134
- def dated_draft_id(orig, base_pubid)
161
+ def dated_draft_id(orig, base_pubid, cutoff = nil)
135
162
  ret = orig.dup
136
- ret[:year] = Date.today.year
163
+ ret[:year] = cutoff&.year || Date.today.year
137
164
  base_pubid.create(**ret).to_s
138
165
  end
139
166
 
140
167
  def unpublished_ref?(bibitem)
141
- pub_class(bibitem) > 2 and return true
168
+ PublisherIdentity.iso_iec_publisher?(bibitem) or return true
142
169
  ((s = bibitem.at("./status/stage")) && s.text.match?(/\d/) &&
143
170
  (s.text.to_i < 60)) or return true
144
171
  false
145
172
  end
146
173
 
147
- def withdrawn_note(xmldoc)
174
+ def withdrawn_note(xmldoc, cutoff = nil)
148
175
  xmldoc.xpath("//bibitem").each do |b|
149
176
  n = bibitem_note_types(b)
150
177
  n.include?("Unpublished-Status") and next
151
- withdrawn_ref?(b) or next
178
+ withdrawn_ref?(b, cutoff) or next
152
179
  if id = replacement_standard(b)
153
180
  insert_unpub_note(b, @i18n.cancelled_and_replaced.sub("%", id))
154
181
  else insert_unpub_note(b, @i18n.withdrawn)
@@ -156,10 +183,23 @@ module Metanorma
156
183
  end
157
184
  end
158
185
 
159
- def withdrawn_ref?(bibitem)
160
- pub_class(bibitem) > 2 and return false
186
+ def withdrawn_ref?(bibitem, cutoff = nil)
187
+ PublisherIdentity.iso_iec_publisher?(bibitem) or return false
161
188
  (s = bibitem.at("./status/stage")) && (s.text.to_i == 95) &&
162
- (t = bibitem.at("./status/substage")) && (t.text.to_i == 99)
189
+ (t = bibitem.at("./status/substage")) && (t.text.to_i == 99) or
190
+ return false
191
+ # As-of-date: a withdrawal that only happened after the citing document
192
+ # was published did not apply then. metanorma/metanorma-standoc#941.
193
+ wd = withdrawal_date(bibitem)
194
+ !(cutoff && wd && wd > cutoff)
195
+ end
196
+
197
+ # Date the reference was superseded/withdrawn: the earliest published date
198
+ # of an obsoletedBy/updates successor.
199
+ def withdrawal_date(bibitem)
200
+ bibitem.xpath("./relation[@type = 'obsoletedBy' or @type = 'updates']" \
201
+ "/bibitem/date[@type = 'published' or @type = 'circulated']" \
202
+ "/on").map { |d| iso_date(d.text) }.compact.min
163
203
  end
164
204
 
165
205
  def replacement_standard(biblio)
@@ -79,11 +79,13 @@ module Metanorma
79
79
  end
80
80
 
81
81
  def title_full(node, xml, lang)
82
- title, intro, part, amd, add = title_full_prep(node, lang)
82
+ title, intro, part, amd, add, sup, ext = title_full_prep(node, lang)
83
83
  title = "#{intro} -- #{title}" if intro
84
84
  title = "#{title} -- #{part}" if part
85
85
  title = "#{title} -- #{amd}" if amd
86
86
  title = "#{title} -- #{add}" if add
87
+ title = "#{title} -- #{sup}" if sup
88
+ title = "#{title} -- #{ext}" if ext
87
89
  add_title_xml(xml, title, lang, "main")
88
90
  end
89
91
 
@@ -95,7 +97,11 @@ module Metanorma
95
97
  @amd and amd = node.attr("title-amendment-#{lang}")
96
98
  node.attr("addendum-number") and
97
99
  add = node.attr("title-addendum-#{lang}")
98
- [title, intro, part, amd, add].map { |x| x&.empty? ? nil : x }
100
+ node.attr("supplement-number") and
101
+ sup = node.attr("title-supplement-#{lang}")
102
+ node.attr("extract-number") and
103
+ ext = node.attr("title-extract-#{lang}")
104
+ [title, intro, part, amd, add, sup, ext].map { |x| x&.empty? ? nil : x }
99
105
  end
100
106
 
101
107
  def title(node, xml)
@@ -115,6 +121,12 @@ module Metanorma
115
121
  node.attr("addendum-number") and
116
122
  title_component(node, xml, lang,
117
123
  { name: "addendum", abbr: "add" })
124
+ node.attr("supplement-number") and
125
+ title_component(node, xml, lang,
126
+ { name: "supplement", abbr: "sup" })
127
+ node.attr("extract-number") and
128
+ title_component(node, xml, lang,
129
+ { name: "extract", abbr: "ext" })
118
130
  title_nums(node, xml, lang)
119
131
  end
120
132
 
@@ -28,6 +28,8 @@ module Metanorma
28
28
  def get_typeabbr(node, amd: false)
29
29
  node.attr("amendment-number") and return :amd
30
30
  node.attr("addendum-number") and return :add
31
+ node.attr("supplement-number") and return :sup
32
+ node.attr("extract-number") and return :ext
31
33
  node.attr("corrigendum-number") and return :cor
32
34
  DOCTYPE2HASHID[doctype(node).to_sym]
33
35
  end
@@ -103,7 +105,9 @@ module Metanorma
103
105
  stage = iso_id_stage(node)
104
106
  ret = { number: node.attr("amendment-number") ||
105
107
  node.attr("corrigendum-number") ||
106
- node.attr("addendum-number"),
108
+ node.attr("addendum-number") ||
109
+ node.attr("supplement-number") ||
110
+ node.attr("extract-number"),
107
111
  year: iso_id_year(node),
108
112
  iteration: node.attr("iteration") }
109
113
  iso_id_stage_populate(ret, node, stage)
@@ -144,7 +148,9 @@ module Metanorma
144
148
  def iso_id_params_resolve(params, params2, node, orig_id)
145
149
  if orig_id && (node.attr("amendment-number") ||
146
150
  node.attr("corrigendum-number") ||
147
- node.attr("addendum-number"))
151
+ node.attr("addendum-number") ||
152
+ node.attr("supplement-number") ||
153
+ node.attr("extract-number"))
148
154
  %i(unpublished part).each { |x| params.delete(x) }
149
155
  params2[:base] = orig_id
150
156
  elsif orig_id &&
@@ -213,6 +213,12 @@ Sources are currently only rendered in metanorma-plateau</a:documentation>
213
213
  <define name="ExampleAttributes">
214
214
  <ref name="NumberingAttributes"/>
215
215
  <ref name="BlockAttributes"/>
216
+ <optional>
217
+ <attribute name="collapsible">
218
+ <a:documentation>Render the example as collapsible (HTML5 details/summary)</a:documentation>
219
+ <data type="boolean"/>
220
+ </attribute>
221
+ </optional>
216
222
  </define>
217
223
  <define name="ExampleBody">
218
224
  <optional>
@@ -846,7 +852,7 @@ titlecase, or lowercase</a:documentation>
846
852
  <a:documentation>Width of the figure block in rendering</a:documentation>
847
853
  </attribute>
848
854
  </optional>
849
- <ref name="BlockAttributes"/>
855
+ <ref name="BlockAttributesCore"/>
850
856
  </define>
851
857
  <define name="SourceAttributes" combine="interleave">
852
858
  <ref name="BlockAttributes"/>
@@ -1277,7 +1283,11 @@ That concept may be defined as a term within the current document, or it may be
1277
1283
  <a:documentation>Class of input form</a:documentation>
1278
1284
  </attribute>
1279
1285
  </optional>
1280
- <ref name="BlockAttributes"/>
1286
+ <ref name="BlockAttributesCore">
1287
+ <a:documentation>form declares its own class above, so it uses BlockAttributesCore to
1288
+ avoid duplicating the custom-class slot in BlockAttributes. Treated like
1289
+ figure. See metanorma/metanorma-standoc#1197</a:documentation>
1290
+ </ref>
1281
1291
  <zeroOrMore>
1282
1292
  <!-- Input form contents -->
1283
1293
  <choice>
@@ -2762,7 +2772,11 @@ links within an SVG file, so that the SVG file can hyperlink to anchors within t
2762
2772
  </oneOrMore>
2763
2773
  </element>
2764
2774
  </define>
2765
- <define name="BlockAttributes">
2775
+ <define name="BlockAttributesCore">
2776
+ <a:documentation>Block attributes excluding the custom CSS class. Blocks that already carry
2777
+ their own `class` attribute (e.g. figure, via basicdoc FigureAttributes)
2778
+ include this directly, to avoid a duplicate-attribute collision with the
2779
+ `class` added in BlockAttributes. See metanorma/metanorma-standoc#1197</a:documentation>
2766
2780
  <optional>
2767
2781
  <attribute name="keep-with-next">
2768
2782
  <a:documentation>Keep this block on the same page as the following block in paged media</a:documentation>
@@ -2794,6 +2808,17 @@ to span across both columns</a:documentation>
2794
2808
  </attribute>
2795
2809
  </optional>
2796
2810
  </define>
2811
+ <define name="BlockAttributes">
2812
+ <a:documentation>Universal block attributes, including a custom CSS class (space-separated,
2813
+ appended additively to the block's built-in HTML class, HTML output only).
2814
+ See metanorma/metanorma-standoc#1197</a:documentation>
2815
+ <ref name="BlockAttributesCore"/>
2816
+ <optional>
2817
+ <attribute name="class">
2818
+ <a:documentation>Custom CSS class(es) for the block in HTML output</a:documentation>
2819
+ </attribute>
2820
+ </optional>
2821
+ </define>
2797
2822
  <define name="DisplayDirective">
2798
2823
  <a:documentation>Directive on how to render a block in Presentation XML </a:documentation>
2799
2824
  <optional>