metanorma-standoc 3.0.15 → 3.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87e7b185086a1c7a576276d5cb0936fbbee3881e5bd377f64f8d2c4dad977d60
4
- data.tar.gz: d4f2ea5da3139ac765f99db91ea52177ffb584af920ba27d31e264e51fdac3c6
3
+ metadata.gz: d0a69974476cfd73fd74d1072ae10647b54c1c9f55d3cfb3d3cf9151a3f8be12
4
+ data.tar.gz: ed1cb04fdc539fafe18e87c4f7b173e9394644425b3791fa56bca4eb6935cd48
5
5
  SHA512:
6
- metadata.gz: 3b4fc65d63c9f696a3bca40bfd95d9f22da114698fb16291ede3c5d5127c3f29449b41c3e02a0e508e23ddf1c81c5e07d5dcd3b0148dc7f9d0424d3ae1b6ed60
7
- data.tar.gz: 15a940affa34106aee7059457d3be4a270e93d1550acd2c1b152bc4d303ef6aebb95e5ca682155d2068a8a658836e47a4e866ebea91b600ac4254945046f8cf3
6
+ metadata.gz: 2a2306e053d66020cfc017e973c30770eb00db604e12bcdccfdccd303fe2b8ddc2c87d7783067665b666e1db49c6c11044a29ae8420b5d72793c5363a9524d04
7
+ data.tar.gz: eda982b66f7f780b1d8ef7a7d48d5063154446792a5e5f50e5e3bd1470036896bba1d6f8060858a498f01d55a06c4d9f2b4c87fe8cbb67aec2bb1b6fffeee699
@@ -318,9 +318,15 @@ h6:hover > a.anchor,
318
318
  padding: 0;
319
319
  }
320
320
 
321
+ .svg-container {
322
+ width: 100%; /* or any desired width */
323
+ display: block; /* ← removes unwanted inline spacing */
324
+ }
325
+
321
326
  svg {
322
327
  width: 100%;
323
- overflow: visible;
328
+ height: auto; /* ← key to maintaining aspect ratio */
329
+ display: block; /* ← removes unwanted inline spacing */
324
330
  }
325
331
 
326
332
  #standard-band {
@@ -14,36 +14,33 @@ module Metanorma
14
14
  .merge(type: node.attr("type"))))
15
15
  end
16
16
 
17
- def sidebar_attrs(node)
18
- todo_attrs(node).merge(
19
- attr_code(
20
- from: node.attr("from"),
21
- to: node.attr("to") || node.attr("from"),
22
- type: node.attr("type") || nil,
23
- ),
24
- )
25
- end
26
-
27
17
  def sidebar(node)
28
18
  noko do |xml|
29
- xml.review **sidebar_attrs(node) do |r|
19
+ xml.annotation **sidebar_attrs(node) do |r|
30
20
  wrap_in_para(node, r)
31
21
  end
32
22
  end
33
23
  end
34
24
 
35
- def todo_attrs(node)
25
+ def sidebar_attrs(node)
36
26
  date = node.attr("date") || Date.today.iso8601.gsub(/\+.*$/, "")
37
27
  date += "T00:00:00Z" unless date.include?("T")
38
28
  attr_code(id_attr(node)
39
29
  .merge(reviewer: node.attr("reviewer") || node.attr("source") ||
40
30
  "(Unknown)",
41
- date:, type: "todo"))
31
+ from: node.attr("from"),
32
+ to: node.attr("to") || node.attr("from"),
33
+ type: node.attr("type") || "review",
34
+ date:))
35
+ end
36
+
37
+ def todo_attrs(node)
38
+ sidebar_attrs(node).merge(type: "todo")
42
39
  end
43
40
 
44
41
  def todo(node)
45
42
  noko do |xml|
46
- xml.review **todo_attrs(node) do |r|
43
+ xml.annotation **todo_attrs(node) do |r|
47
44
  wrap_in_para(node, r)
48
45
  end
49
46
  end
@@ -160,33 +160,41 @@ module Metanorma
160
160
 
161
161
  def variant_cleanup(xmldoc)
162
162
  variant_space_cleanup(xmldoc)
163
- xmldoc.xpath("//*[variant]").each do |c|
164
- next unless c.children.any? do |n|
165
- n.name != "variant" && (!n.text? || !n.text.gsub(/\s/, "").empty?)
163
+ xmldoc.xpath("//*[lang-variant]").each do |c|
164
+ if only_langvariant_children?(c)
165
+ duplicate_langvariants(c, c.xpath("./lang-variant"))
166
+ else
167
+ c.xpath(".//lang-variant").each { |x| x.name = "span" }
166
168
  end
169
+ end
170
+ end
167
171
 
168
- variant_cleanup1(c)
172
+ def only_langvariant_children?(node)
173
+ node.children.none? do |n|
174
+ n.name != "lang-variant" && (!n.text? || !n.text.strip.empty?)
169
175
  end
170
- xmldoc.xpath("//variantwrap").each { |n| n.name = "variant" }
171
176
  end
172
177
 
173
- def variant_cleanup1(elem)
174
- elem.xpath("./variant").each do |n|
175
- if n.at_xpath("preceding-sibling::node()" \
176
- "[not(self::text()[not(normalize-space())])][1]" \
177
- "[self::variantwrap]")
178
- n.previous_element << n
179
- else
180
- n.replace("<variantwrap/>").first << n
181
- end
178
+ def duplicate_langvariants(container, variants)
179
+ lang_variant_to_node(variants.first, container)
180
+ variants[1..].reverse.each do |node|
181
+ new = container.dup
182
+ lang_variant_to_node(node, new)
183
+ container.next = new
182
184
  end
183
185
  end
184
186
 
185
- def variant_space_cleanup(xmldoc)
186
- xmldoc.xpath("//*[variant]").each do |c|
187
- next if c.next.nil? || c.next.next.nil?
187
+ def lang_variant_to_node(variant, node)
188
+ node.children = variant.children
189
+ node["lang"] = variant["lang"]
190
+ node.delete("script")
191
+ variant["script"] and node["script"] = variant["script"]
192
+ end
188
193
 
189
- if c.next.text? && c.next.next.name == "variant"
194
+ def variant_space_cleanup(xmldoc)
195
+ xmldoc.xpath("//*[lang-variant]").each do |c|
196
+ c.next.nil? || c.next.next.nil? and next
197
+ if c.next.text? && c.next.next.name == "lang-variant"
190
198
  c.next.text.gsub(/\s/, "").empty? and
191
199
  c.next.remove
192
200
  end
@@ -121,7 +121,7 @@ module Metanorma
121
121
  def align_callouts_to_annotations(xmldoc)
122
122
  xmldoc.xpath("//sourcecode").each do |x|
123
123
  callouts = x.xpath("./body/callout")
124
- annotations = x.xpath("./annotation")
124
+ annotations = x.xpath("./callout-annotation")
125
125
  callouts.size == annotations.size and
126
126
  link_callouts_to_annotations(callouts, annotations)
127
127
  end
@@ -129,7 +129,7 @@ module Metanorma
129
129
 
130
130
  def merge_annotations_into_sourcecode(xmldoc)
131
131
  xmldoc.xpath("//sourcecode").each do |x|
132
- while x.next_element&.name == "annotation"
132
+ while x.next_element&.name == "callout-annotation"
133
133
  x.next_element.parent = x
134
134
  end
135
135
  end
@@ -48,8 +48,11 @@ module Metanorma
48
48
  x = xmldoc.dup
49
49
  x.root.add_namespace(nil, xml_namespace)
50
50
  xml = Nokogiri::XML(x.to_xml)
51
+ #require "debug"; binding.b
51
52
  @isodoc ||= isodoc(@lang, @script, @locale)
52
- @isodoc.info(xml, nil)
53
+ # initialise @isodoc.xrefs, for @isodoc.xrefs.info
54
+ @isodoc.bibdata(xml) # do i18n
55
+ #@isodoc.info(xml, nil)
53
56
  @isodoc
54
57
  end
55
58
 
@@ -76,19 +79,6 @@ module Metanorma
76
79
  initial_boilerplate(xmldoc, isodoc)
77
80
  end
78
81
 
79
- # KILL
80
- # escape &lt; &gt; &amp; to &amp;gt; etc,
81
- # for passthrough insertion into boilerplate
82
- def boilerplate_isodoc_values(isodoc)
83
- isodoc.meta.get.each do |k, v|
84
- if v.is_a?(String)
85
- isodoc.meta.set(k, v.gsub("&amp;", "&&&&&&&")
86
- .gsub("&lt;", "&amp;lt;").gsub("&gt;", "&amp;gt;")
87
- .gsub("&&&&&&&", "&amp;amp;"))
88
- end
89
- end
90
- end
91
-
92
82
  def initial_boilerplate(xml, isodoc)
93
83
  xml.at("//boilerplate") and return
94
84
  preface = xml.at("//preface | //sections | //annex | //references") or
@@ -19,6 +19,7 @@ module Metanorma
19
19
  def asciimath2mathml_indiv(elem)
20
20
  elem["type"] = "MathML"
21
21
  expr = @c.decode(elem.text)
22
+ expr.strip.empty? and return
22
23
  ret = asciimath_parse(expr, elem)&.strip
23
24
  ret += "<asciimath>#{@c.encode(expr, :basic)}</asciimath>"
24
25
  elem.children = ret
@@ -35,9 +36,9 @@ module Metanorma
35
36
  <math xmlns='#{MATHML_NS}'><mstyle displaystyle='false'><mn>#{expr}</mn></mstyle></math>
36
37
  MATH
37
38
  else
39
+ expr.strip.empty? and return
38
40
  unitsml = if expr.include?("unitsml")
39
- { unitsml: { xml: true,
40
- multiplier: :space } }
41
+ { unitsml: { xml: true, multiplier: :space } }
41
42
  else {} end
42
43
  Plurimath::Math.parse(expr, "asciimath")
43
44
  .to_mathml(**{ display_style: elem["block"] }.merge(unitsml))
@@ -2,9 +2,9 @@ module Metanorma
2
2
  module Standoc
3
3
  module Cleanup
4
4
  def review_cleanup(xmldoc)
5
- reviews = xmldoc.xpath("//review")
5
+ reviews = xmldoc.xpath("//annotation")
6
6
  reviews.empty? and return
7
- ctr = xmldoc.root.add_child("<review-container/>").first
7
+ ctr = xmldoc.root.add_child("<annotation-container/>").first
8
8
  reviews.each do |r|
9
9
  review_set_location(r)
10
10
  ctr << r
@@ -123,28 +123,28 @@ module Metanorma
123
123
  end
124
124
  end
125
125
 
126
- def terms_subclause_type_tally(node, m, parent)
127
- sym = if (node.at(".//term") && !node.at(".//definitions")) ||
128
- (node.name == "terms" && !node.at(".//term"))
129
- unless m[:parent] == :term # don't count Term > Term twice
126
+ def terms_subclause_type_tally(node, acc, parent)
127
+ hasterm = node.at(".//term")
128
+ sym = if (hasterm && !node.at(".//definitions")) ||
129
+ (node.name == "terms" && !hasterm)
130
+ unless acc[:parent] == :term # don't count Term > Term twice
130
131
  :term
131
132
  end
132
- elsif node.at(".//term") && node.at("./self::*#{SYMnoABBR}") then :tsna
133
- elsif node.at(".//term") && node.at("./self::*#{ABBRnoSYM}") then :tans
134
- elsif node.at(".//term") && node.at("./self::*#{SYMABBR}") then :tsa
135
- elsif node.at(".//term") && node.at("./self::*#{NO_SYMABBR}") then :tnsa
133
+ elsif hasterm && node.at("./self::*#{SYMnoABBR}") then :tsna
134
+ elsif hasterm && node.at("./self::*#{ABBRnoSYM}") then :tans
135
+ elsif hasterm && node.at("./self::*#{SYMABBR}") then :tsa
136
+ elsif hasterm && node.at("./self::*#{NO_SYMABBR}") then :tnsa
136
137
  elsif node.at("./self::*#{SYMnoABBR}") then :sna
137
138
  elsif node.at("./self::*#{ABBRnoSYM}") then :ans
138
139
  elsif node.at("./self::*#{SYMABBR}") then :sa
139
140
  elsif node.at("./self::*#{NO_SYMABBR}") then :nsa
140
141
  elsif node.name == "definitions" # ignore
141
- elsif node == parent && node.at(".//term") &&
142
- node.at(".//definitions")
142
+ elsif node == parent && hasterm && node.at(".//definitions")
143
143
  :termdef
144
144
  else :other
145
145
  end
146
- node == parent and m[:parent] = sym
147
- sym and m[sym] += 1
146
+ node == parent and acc[:parent] = sym
147
+ sym and acc[sym] += 1
148
148
  end
149
149
 
150
150
  def sections_variant_title_cleanup(xml)
@@ -107,7 +107,7 @@ module Metanorma
107
107
  %w(pre sourcecode passthrough metanorma-extension stem).freeze
108
108
 
109
109
  STRIP_LINEBREAK_ELEMENTS =
110
- %w(title name variant-title figure example review admonition
110
+ %w(title name variant-title figure example annotation admonition
111
111
  note li th td dt dd p quote label annotation
112
112
  preferred admitted related deprecates field-of-application
113
113
  usage-info expression pronunciation grammar-value domain
@@ -146,8 +146,8 @@ module Metanorma
146
146
  quote label abstract preferred admitted related deprecates
147
147
  field-of-application usage-info expression pronunciation
148
148
  grammar-value domain definition termnote termexample modification
149
- description newcontent floating-title tab review admonition
150
- annotation).include? elem.name
149
+ description newcontent floating-title tab annotation admonition
150
+ callout-annotation).include? elem.name
151
151
  end
152
152
 
153
153
  def empty_tag_with_text_content?(elem)
@@ -56,7 +56,7 @@ module Metanorma
56
56
  inline_macro Metanorma::Standoc::IdentifierInlineMacro
57
57
  inline_macro Metanorma::Standoc::ConceptInlineMacro
58
58
  inline_macro Metanorma::Standoc::AutonumberInlineMacro
59
- inline_macro Metanorma::Standoc::VariantInlineMacro
59
+ inline_macro Metanorma::Standoc::LangVariantInlineMacro
60
60
  inline_macro Metanorma::Standoc::FootnoteBlockInlineMacro
61
61
  inline_macro Metanorma::Standoc::TermRefInlineMacro
62
62
  inline_macro Metanorma::Standoc::SymbolRefInlineMacro
@@ -30,13 +30,21 @@ module Metanorma
30
30
  end
31
31
 
32
32
  def metadata_version(node, xml)
33
+ draft = metadata_version_value(node)
33
34
  xml.edition node.attr("edition") if node.attr("edition")
34
35
  xml.version do |v|
35
36
  v.revision_date node.attr("revdate") if node.attr("revdate")
36
- v.draft node.attr("draft") if node.attr("draft")
37
+ v.draft draft if draft
37
38
  end
38
39
  end
39
40
 
41
+ def metadata_version_value(node)
42
+ draft = node.attr("version") and return draft
43
+ draft = node.attr("draft") or return nil
44
+ draft.empty? and return nil
45
+ draft
46
+ end
47
+
40
48
  def metadata_status(node, xml)
41
49
  xml.status do |s|
42
50
  s.stage (node.attr("status") || node.attr("docstage") || "published")
@@ -115,7 +115,7 @@ module Metanorma
115
115
 
116
116
  def org_logo(xml, logo)
117
117
  logo and xml.logo do |l|
118
- l.image src: logo
118
+ l.image src: logo, mimetype: image_mimetype(logo)
119
119
  end
120
120
  end
121
121
 
@@ -134,29 +134,40 @@ module Metanorma
134
134
  end
135
135
  end
136
136
 
137
+ def image_mimetype(uri)
138
+ types = if /^data:/.match?(uri) then Vectory::Utils::datauri2mime(uri)
139
+ else MIME::Types.type_for(uri)
140
+ end
141
+ types.first.to_s
142
+ end
143
+
137
144
  def image_attributes(node)
145
+ sourceuri = image_src_uri(node)
146
+ uri = sourceuri
147
+ type = image_mimetype(uri)
148
+ uri = uri.sub(%r{^data:image/\*;}, "data:#{type};")
149
+ image_attributes1(node, uri, sourceuri, type)
150
+ end
151
+
152
+ def image_src_uri(node)
138
153
  nodetarget = node.attr("target") || node.target
139
154
  if Gem.win_platform? && /^[a-zA-Z]:/.match?(nodetarget)
140
155
  nodetarget.prepend("/")
141
156
  end
142
- uri = node.image_uri (nodetarget)
157
+ uri = node.image_uri(nodetarget)
143
158
  if Gem.win_platform? && /^\/[a-zA-Z]:/.match?(uri)
144
159
  uri = uri[1..]
145
160
  end
146
- types = if /^data:/.match?(uri) then Vectory::Utils::datauri2mime(uri)
147
- else MIME::Types.type_for(uri)
148
- end
149
- type = types.first.to_s
150
- uri = uri.sub(%r{^data:image/\*;}, "data:#{type};")
151
- image_attributes1(node, uri, type)
161
+ uri
152
162
  end
153
163
 
154
- def image_attributes1(node, uri, type)
164
+ def image_attributes1(node, uri, sourceuri, type)
165
+ /^data:/.match?(sourceuri) and sourceuri = nil
155
166
  attr_code(id_attr(node)
156
167
  .merge(src: uri, mimetype: type,
157
168
  height: node.attr("height") || "auto",
158
169
  width: node.attr("width") || "auto",
159
- filename: node.attr("filename"),
170
+ filename: node.attr("filename") || sourceuri,
160
171
  title: node.attr("titleattr"),
161
172
  alt: node.alt == node.attr("default-alt") ? nil : node.alt))
162
173
  end
@@ -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.7 -->
3
+ <!-- VERSION v2.0.8 -->
4
4
 
5
5
  <!--
6
6
  ALERT: cannot have root comments, because of https://github.com/metanorma/metanorma/issues/437
@@ -72,6 +72,46 @@ but to `@anchor`, the user-supplied cross-reference</a:documentation>
72
72
  </oneOrMore>
73
73
  </element>
74
74
  </define>
75
+ <define name="review">
76
+ <a:documentation>Generalise BasicDoc element from just review comments, to general annotations;
77
+ the type attribute defaults to `review` for reviews</a:documentation>
78
+ <element name="annotation">
79
+ <ref name="RequiredId"/>
80
+ <ref name="ReviewAttributes"/>
81
+ <oneOrMore>
82
+ <ref name="paragraph">
83
+ <a:documentation>Reviewer comments content</a:documentation>
84
+ </ref>
85
+ </oneOrMore>
86
+ </element>
87
+ </define>
88
+ <define name="ruby_pronunciation">
89
+ <a:documentation>Ruby annotation giving pronunciation of text: change tag from BasicDoc for disambiguation</a:documentation>
90
+ <element name="ruby-pronunciation">
91
+ <attribute name="value">
92
+ <a:documentation>Ruby annotation value</a:documentation>
93
+ </attribute>
94
+ <ref name="LocalizedStringAttributes"/>
95
+ </element>
96
+ </define>
97
+ <define name="ruby_annotation">
98
+ <a:documentation>Ruby annotation giving information other than pronunciation of text: change tag from BasicDoc for disambiguation</a:documentation>
99
+ <element name="ruby-annotation">
100
+ <attribute name="value">
101
+ <a:documentation>Ruby annotation value</a:documentation>
102
+ </attribute>
103
+ <ref name="LocalizedStringAttributes"/>
104
+ </element>
105
+ </define>
106
+ <define name="annotation">
107
+ <a:documentation>Source code annotation, corresponding to a callout</a:documentation>
108
+ <element name="callout-annotation">
109
+ <ref name="RequiredId"/>
110
+ <oneOrMore>
111
+ <ref name="paragraph"/>
112
+ </oneOrMore>
113
+ </element>
114
+ </define>
75
115
  <define name="section-title">
76
116
  <a:documentation>Title(s) of a clause</a:documentation>
77
117
  <element name="title">
@@ -540,7 +580,7 @@ normative or informative references, some split references into sections organiz
540
580
  <ref name="OptionalId"/>
541
581
  <optional>
542
582
  <attribute name="style">
543
- <a:documentation>CSS style: only background-color supported</a:documentation>
583
+ <a:documentation>CSS style: only background-color, color, border supported</a:documentation>
544
584
  </attribute>
545
585
  </optional>
546
586
  </define>
@@ -620,7 +660,7 @@ This is done if the footnote reference is already presented in some other form,
620
660
  <ref name="RequiredId"/>
621
661
  <optional>
622
662
  <attribute name="style">
623
- <a:documentation>CSS style: only background-color supported</a:documentation>
663
+ <a:documentation>CSS style: only background-color, color, border supported</a:documentation>
624
664
  </attribute>
625
665
  </optional>
626
666
  </define>
@@ -700,6 +740,11 @@ titlecase, or lowercase</a:documentation>
700
740
  <a:documentation>Width of the table block in rendering</a:documentation>
701
741
  </attribute>
702
742
  </optional>
743
+ <optional>
744
+ <attribute name="style">
745
+ <a:documentation>CSS style: only background-color, color, border supported</a:documentation>
746
+ </attribute>
747
+ </optional>
703
748
  <ref name="BlockAttributes"/>
704
749
  </define>
705
750
  <define name="FigureAttributes" combine="interleave">
@@ -1417,7 +1462,7 @@ numbers</a:documentation>
1417
1462
  </optional>
1418
1463
  <ref name="DocumentBody"/>
1419
1464
  <optional>
1420
- <ref name="review-container">
1465
+ <ref name="annotation-container">
1421
1466
  <a:documentation>Annotations to the document</a:documentation>
1422
1467
  </ref>
1423
1468
  </optional>
@@ -1461,8 +1506,8 @@ numbers</a:documentation>
1461
1506
  </oneOrMore>
1462
1507
  </element>
1463
1508
  </define>
1464
- <define name="review-container">
1465
- <element name="review-container">
1509
+ <define name="annotation-container">
1510
+ <element name="annotation-container">
1466
1511
  <oneOrMore>
1467
1512
  <ref name="review"/>
1468
1513
  </oneOrMore>
@@ -59,6 +59,7 @@ module Metanorma
59
59
  def ol_attrs(node)
60
60
  attr_code(id_attr(node).merge(keep_attrs(node)
61
61
  .merge(type: olist_style(node.style),
62
+ start: node.attr("start"),
62
63
  "explicit-type": olist_style(node.attributes[1]))))
63
64
  end
64
65
 
@@ -114,7 +115,7 @@ module Metanorma
114
115
  def colist(node)
115
116
  noko do |xml|
116
117
  node.items.each_with_index do |item, i|
117
- xml.annotation **attr_code(id: i + 1) do |xml_li|
118
+ xml.callout_annotation **attr_code(id: i + 1) do |xml_li|
118
119
  xml_li.p { |p| p << item.text }
119
120
  end
120
121
  end
@@ -124,11 +124,6 @@ module Metanorma
124
124
  end
125
125
  end
126
126
 
127
- # KILL
128
- def pass_convert(text)
129
- text.sub(/^pass:\[(.+)$/, "pass-format:metanorma[\\1")
130
- end
131
-
132
127
  # InlineLinkRx = %r((^|link:|#{CG_BLANK}|&lt;|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|([^\s\[\]<]*([^\s,.?!\[\]<\)]))))m
133
128
  #
134
129
  InlineLinkRx = %r((^|(?<![-\\])\blink:(?!\+)|\p{Blank}|&lt;|[<>\(\)\[\];"'])((?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)(?:(\[(|.*?[^\\])\])|([^\s\[\]<]*([^\s,.?!\[\]<\)])))))m
@@ -226,14 +221,17 @@ module Metanorma
226
221
  # pass:[A] => pass-format:metanorma[++A++],
227
222
  # so long as A doesn't already start with ++
228
223
  # ditto pass-format:[A] => pass-format:[++A++]
224
+ # convert any \] in the ++...++ body to ]
229
225
  def pass_convert(text)
230
226
  text
231
- .gsub(/pass-format:([^\[ ]*)\[(?!\+\+)(.+?)(?<!\\)\]/,
232
- "pass-format:\\1[++\\2++]")
227
+ .gsub(/pass-format:([^\[ ]*)\[(?!\+\+)(.+?)(?<!\\)\]/) do |_m|
228
+ "pass-format:#{$1}[++#{$2.gsub(/\\\]/, ']')}++]"
229
+ end
233
230
  .gsub(/pass:\[(?=\+\+)(.+?)(?<!\\)\]/,
234
231
  "pass-format:metanorma[\\1]")
235
- .gsub(/pass:\[(?!\+\+)(.+?)(?<!\\)\]/,
236
- "pass-format:metanorma[++\\1++]")
232
+ .gsub(/pass:\[(?!\+\+)(.+?)(?<!\\)\]/) do |_m|
233
+ "pass-format:metanorma[++#{$1.gsub(/\\\]/, ']')}++]"
234
+ end
237
235
  end
238
236
 
239
237
  def inlinelink(text)
@@ -43,7 +43,7 @@ module Metanorma
43
43
  attrs = " value='#{target}'"
44
44
  x = args[:lang] and attrs += " lang='#{x}'"
45
45
  x = args[:script] and attrs += " script='#{x}'"
46
- "<ruby><#{args[:type]} #{attrs}/>#{out}</ruby>"
46
+ "<ruby><ruby-#{args[:type]} #{attrs}/>#{out}</ruby>"
47
47
  end
48
48
  end
49
49
 
@@ -82,7 +82,7 @@ module Metanorma
82
82
  end
83
83
  end
84
84
 
85
- class VariantInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
85
+ class LangVariantInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
86
86
  use_dsl
87
87
  named :lang
88
88
  parse_content_as :text
@@ -91,9 +91,9 @@ module Metanorma
91
91
  /^(?<lang>[^-]*)(?:-(?<script>.*))?$/ =~ target
92
92
  out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
93
93
  if script
94
- %{<variant lang='#{lang}' script='#{script}'>#{out}</variant>}
94
+ %{<lang-variant lang='#{lang}' script='#{script}'>#{out}</lang-variant>}
95
95
  else
96
- %{<variant lang='#{lang}'>#{out}</variant>}
96
+ %{<lang-variant lang='#{lang}'>#{out}</lang-variant>}
97
97
  end
98
98
  end
99
99
  end
@@ -134,7 +134,6 @@ module Metanorma
134
134
  end
135
135
  end
136
136
 
137
- # inject ZWNJ to prevent Asciidoctor from attempting regex substitutions
138
137
  class PassFormatInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
139
138
  use_dsl
140
139
  named :"pass-format"
@@ -143,29 +142,12 @@ module Metanorma
143
142
  def process(parent, target, attrs)
144
143
  format = target || "metanorma"
145
144
  out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"],
146
- type: :pass, attributes: { 'subs' => [] }).convert
145
+ type: :pass, attributes: { "subs" => [] })
146
+ .convert
147
147
  <<~XML.strip
148
- <passthrough-inline formats="#{format}">#{xml_process(out)}</passthrough-inline>
148
+ <passthrough-inline formats="#{format}">#{out}</passthrough-inline>
149
149
  XML
150
150
  end
151
-
152
- # KILL
153
- # Split content into XML tags (including XML-escaped instances),
154
- # XML escapes, and text segments
155
- # Then only apply ZWNJ to punctuation in text segments
156
- def xml_process(out)
157
- processed_out = ""
158
- segments = out.split(/(<[^>]*>|&lt;[^&]*&gt;|&[^;]*;)/)
159
- segments.each_with_index do |segment, index|
160
- processed_out += if index.even? # Text segment (not a tag or escape)
161
- #segment.gsub(/([[:punct:]])/, "\\1&#x200c;")
162
- segment
163
- else # XML tag or escape
164
- segment
165
- end
166
- end
167
- processed_out
168
- end
169
151
  end
170
152
 
171
153
  class IdentifierInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
@@ -8,6 +8,7 @@ module Metanorma
8
8
  def process(parent, reader, attrs)
9
9
  attrs["name"] = "todo"
10
10
  attrs["caption"] = "TODO"
11
+ # these will be converted from admonition to annotation downstream
11
12
  create_block(parent, :admonition, reader.lines, attrs,
12
13
  content_model: :compound)
13
14
  end
@@ -21,6 +22,7 @@ module Metanorma
21
22
  para.set_attr("name", "todo")
22
23
  para.set_attr("caption", "TODO")
23
24
  para.lines[0].sub!(/^TODO: /, "")
25
+ # these will be converted from admonition to annotation downstream
24
26
  para.context = :admonition
25
27
  end
26
28
  end
@@ -13,6 +13,23 @@ module Metanorma
13
13
  end
14
14
  end
15
15
 
16
+ class ::Hash
17
+ def deep_merge(second)
18
+ merger = proc { |_, v1, v2|
19
+ if ::Hash === v1 && ::Hash === v2
20
+ v1.merge(v2, &merger)
21
+ elsif ::Array === v1 && ::Array === v2
22
+ v2 # overwrite old with new
23
+ elsif [:undefined].include?(v2)
24
+ v1
25
+ else
26
+ v2
27
+ end
28
+ }
29
+ merge(second.to_h, &merger)
30
+ end
31
+ end
32
+
16
33
  def initialize(old, new)
17
34
  @old = load_bibitem(old)
18
35
  @new = load_bibitem(new)
@@ -6,6 +6,7 @@ module Metanorma
6
6
  .merge(id_unnum_attrs(node))
7
7
  .merge(headerrows: node.attr("headerrows"),
8
8
  alt: node.attr("alt"),
9
+ style: node.attr("css-style"),
9
10
  summary: node.attr("summary"),
10
11
  width: node.attr("width"))
11
12
  end
@@ -87,6 +87,8 @@ module Metanorma
87
87
  conv = presentation_xml_converter(EmptyAttr.new)
88
88
  i18n = conv.i18n_init(lang, script, locale, i18nyaml)
89
89
  conv.metadata_init(lang, script, locale, i18n)
90
+ conv.xref_init(lang, script, nil, i18n, {})
91
+ conv.xrefs.klass.meta = conv.meta
90
92
  conv
91
93
  end
92
94
 
@@ -1,11 +1,11 @@
1
1
  require "metanorma/standoc/utils"
2
+ require_relative "validate_image"
2
3
  require_relative "validate_section"
3
4
  require_relative "validate_table"
4
5
  require_relative "validate_term"
5
6
  require_relative "validate_schema"
6
7
  require "nokogiri"
7
8
  require "iev"
8
- require "pngcheck"
9
9
 
10
10
  module Metanorma
11
11
  module Standoc
@@ -14,7 +14,6 @@ module Metanorma
14
14
  @doctype = doc.at("//bibdata/ext/doctype")&.text
15
15
  repeat_id_validate(doc.root) # feeds xref_validate, termsect_validate
16
16
  xref_validate(doc) # feeds nested_asset_validate
17
- nested_asset_validate(doc)
18
17
  section_validate(doc)
19
18
  norm_ref_validate(doc)
20
19
  iev_validate(doc.root)
@@ -25,6 +24,7 @@ module Metanorma
25
24
  table_validate(doc)
26
25
  requirement_validate(doc)
27
26
  image_validate(doc)
27
+ block_validate(doc)
28
28
  math_validate(doc)
29
29
  fatalerrors = @log.abort_messages
30
30
  fatalerrors.empty? or
@@ -98,61 +98,6 @@ module Metanorma
98
98
  @log.add("Style", i, err2)
99
99
  end
100
100
 
101
- def image_validate(doc)
102
- image_exists(doc)
103
- image_toobig(doc)
104
- png_validate(doc)
105
- end
106
-
107
- def image_exists(doc)
108
- doc.xpath("//image").each do |i|
109
- Vectory::Utils::url?(i["src"]) and next
110
- Vectory::Utils::datauri?(i["src"]) and next
111
- expand_path(i["src"]) and next
112
- @log.add("Images", i.parent,
113
- "Image not found: #{i['src']}", severity: 0)
114
- end
115
- end
116
-
117
- def expand_path(loc)
118
- relative_path = File.join(@localdir, loc)
119
- [loc, relative_path].detect do |p|
120
- File.exist?(p) ? p : nil
121
- end
122
- end
123
-
124
- def png_validate(doc)
125
- doc.xpath("//image[@mimetype = 'image/png']").each do |i|
126
- Vectory::Utils::url?(i["src"]) and next
127
- decoded = if Vectory::Utils::datauri?(i["src"])
128
- Vectory::Utils::decode_datauri(i["src"])[:data]
129
- else
130
- path = expand_path(i["src"]) or next
131
- File.binread(path)
132
- end
133
- png_validate1(i, decoded)
134
- end
135
- end
136
-
137
- def png_validate1(img, buffer)
138
- PngCheck.check_buffer(buffer)
139
- rescue PngCheck::CorruptPngError => e
140
- @log.add("Images", img.parent,
141
- "Corrupt PNG image detected: #{e.message}")
142
- end
143
-
144
- TOO_BIG_IMG_ERR = <<~ERR.freeze
145
- Image too large for Data URI encoding: disable Data URI encoding (`:data-uri-image: false`), or set `:data-uri-maxsize: 0`
146
- ERR
147
-
148
- def image_toobig(doc)
149
- @dataurimaxsize.zero? and return
150
- doc.xpath("//image").each do |i|
151
- i["src"].size > @dataurimaxsize and
152
- @log.add("Images", i.parent, TOO_BIG_IMG_ERR, severity: 0)
153
- end
154
- end
155
-
156
101
  def validate(doc)
157
102
  content_validate(doc)
158
103
  schema_validate(formattedstr_strip(doc.dup), schema_location)
@@ -250,6 +195,39 @@ module Metanorma
250
195
  get_anchors_between(from["target"], to_location["target"])
251
196
  .each { |id| @doc_xrefs[id] = from }
252
197
  end
198
+
199
+ def block_validate(doc)
200
+ nested_asset_validate(doc)
201
+ all_empty_block_validate(doc)
202
+ end
203
+
204
+ def all_empty_block_validate(doc)
205
+ %w(note example admonition figure quote pre).each do |tag|
206
+ empty_block_validate(doc, "//#{tag}", nil)
207
+ end
208
+ empty_block_validate(doc, "//sourcecode", "body")
209
+ empty_block_validate(doc, "//formula", "stem")
210
+ empty_block_validate(doc, "//ol", "li")
211
+ empty_block_validate(doc, "//ul", "li")
212
+ empty_block_validate(doc, "//dl", "dt")
213
+ end
214
+
215
+ def empty_block_validate(doc, tag, body)
216
+ # require "debug"; binding.b
217
+ doc.xpath(tag).each do |t|
218
+ body and t = t.at("./#{body}")
219
+ empty_block?(t) or next
220
+ @log.add("Blocks", t, "#{tag.sub(/^\/\//, '')} is empty", severity: 1)
221
+ end
222
+ end
223
+
224
+ def empty_block?(block)
225
+ content = block.children.reject { |n| n.name == "name" }
226
+ content.map do |n|
227
+ %w(image xref eref).include?(n.name) ? n.name : n
228
+ end
229
+ content.map(&:to_s).join.strip.empty?
230
+ end
253
231
  end
254
232
  end
255
233
  end
@@ -0,0 +1,62 @@
1
+ require "pngcheck"
2
+
3
+ module Metanorma
4
+ module Standoc
5
+ module Validate
6
+ def image_validate(doc)
7
+ image_exists(doc)
8
+ image_toobig(doc)
9
+ png_validate(doc)
10
+ end
11
+
12
+ def image_exists(doc)
13
+ doc.xpath("//image").each do |i|
14
+ Vectory::Utils::url?(i["src"]) and next
15
+ Vectory::Utils::datauri?(i["src"]) and next
16
+ expand_path(i["src"]) and next
17
+ @log.add("Images", i.parent,
18
+ "Image not found: #{i['src']}", severity: 0)
19
+ end
20
+ end
21
+
22
+ def expand_path(loc)
23
+ relative_path = File.join(@localdir, loc)
24
+ [loc, relative_path].detect do |p|
25
+ File.exist?(p) ? p : nil
26
+ end
27
+ end
28
+
29
+ def png_validate(doc)
30
+ doc.xpath("//image[@mimetype = 'image/png']").each do |i|
31
+ Vectory::Utils::url?(i["src"]) and next
32
+ decoded = if Vectory::Utils::datauri?(i["src"])
33
+ Vectory::Utils::decode_datauri(i["src"])[:data]
34
+ else
35
+ path = expand_path(i["src"]) or next
36
+ File.binread(path)
37
+ end
38
+ png_validate1(i, decoded)
39
+ end
40
+ end
41
+
42
+ def png_validate1(img, buffer)
43
+ PngCheck.check_buffer(buffer)
44
+ rescue PngCheck::CorruptPngError => e
45
+ @log.add("Images", img.parent,
46
+ "Corrupt PNG image detected: #{e.message}")
47
+ end
48
+
49
+ TOO_BIG_IMG_ERR = <<~ERR.freeze
50
+ Image too large for Data URI encoding: disable Data URI encoding (`:data-uri-image: false`), or set `:data-uri-maxsize: 0`
51
+ ERR
52
+
53
+ def image_toobig(doc)
54
+ @dataurimaxsize.zero? and return
55
+ doc.xpath("//image").each do |i|
56
+ i["src"].size > @dataurimaxsize and
57
+ @log.add("Images", i.parent, TOO_BIG_IMG_ERR, severity: 0)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -12,7 +12,7 @@ module Metanorma
12
12
  def sourcecode_style(root)
13
13
  root.xpath("//sourcecode").each do |x|
14
14
  callouts = x.xpath("./body/callout")
15
- annotations = x.xpath("./annotation")
15
+ annotations = x.xpath("./callout-annotation")
16
16
  callouts_error(x, callouts, annotations)
17
17
  end
18
18
  end
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "3.0.15".freeze
22
+ VERSION = "3.1.1".freeze
23
23
  end
24
24
  end
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_dependency "asciidoctor", "~> 2.0.0"
33
33
  spec.add_dependency "crass", "~> 1.0.0"
34
34
  spec.add_dependency "iev", "~> 0.3.5"
35
- spec.add_dependency "isodoc", "~> 3.1.4"
35
+ spec.add_dependency "isodoc", "~> 3.2.0"
36
36
  spec.add_dependency "metanorma", ">= 1.6.0"
37
37
  spec.add_dependency "metanorma-plugin-glossarist", "~> 0.2.3"
38
38
  spec.add_dependency "metanorma-plugin-lutaml", "~> 0.7.31"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-standoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.15
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-09 00:00:00.000000000 Z
11
+ date: 2025-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 3.1.4
75
+ version: 3.2.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 3.1.4
82
+ version: 3.2.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: metanorma
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -554,6 +554,7 @@ files:
554
554
  - lib/metanorma/standoc/terms.rb
555
555
  - lib/metanorma/standoc/utils.rb
556
556
  - lib/metanorma/standoc/validate.rb
557
+ - lib/metanorma/standoc/validate_image.rb
557
558
  - lib/metanorma/standoc/validate_schema.rb
558
559
  - lib/metanorma/standoc/validate_section.rb
559
560
  - lib/metanorma/standoc/validate_table.rb