metanorma-iso 2.4.3 → 2.4.4

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.
@@ -0,0 +1,102 @@
1
+ require_relative "init"
2
+ require "isodoc"
3
+ require_relative "index"
4
+ require_relative "presentation_xref"
5
+ require_relative "presentation_bibdata"
6
+ require_relative "../../relaton/render/general"
7
+
8
+ module IsoDoc
9
+ module Iso
10
+ class PresentationXMLConvert < IsoDoc::PresentationXMLConvert
11
+ def concept(docxml)
12
+ concept_term(docxml)
13
+ docxml.xpath(ns("//concept")).each do |node|
14
+ concept_render(node, ital: "false", ref: "false",
15
+ linkref: "true", linkmention: "false")
16
+ end
17
+ end
18
+
19
+ def concept_term(docxml)
20
+ docxml.xpath(ns("//term")).each do |f|
21
+ m = {}
22
+ (f.xpath(ns(".//concept")) - f.xpath(ns(".//term//concept")))
23
+ .each { |c| concept_term1(c, m) }
24
+ end
25
+ end
26
+
27
+ def concept_term1(node, seen)
28
+ term = to_xml(node.at(ns("./refterm")))
29
+ if term && seen[term]
30
+ concept_render(node, ital: "false", ref: "false",
31
+ linkref: "true", linkmention: "false")
32
+ else concept_render(node, ital: "true", ref: "true",
33
+ linkref: "true", linkmention: "false")
34
+ end
35
+ seen[term] = true if term
36
+ seen
37
+ end
38
+
39
+ def concept1_ref_content(ref)
40
+ prev = "("
41
+ foll = ")"
42
+ if ref.name == "termref"
43
+ prev, foll = @i18n.term_defined_in.split("%")
44
+ end
45
+ ref.previous = prev
46
+ ref.next = foll
47
+ end
48
+
49
+ def concept1(node)
50
+ node.replace(node&.at(ns("./renderterm"))&.children ||
51
+ node&.at(ns("./refterm"))&.children ||
52
+ node.children)
53
+ end
54
+
55
+ def termdefinition1(elem)
56
+ prefix_domain_to_definition(elem)
57
+ super
58
+ end
59
+
60
+ def prefix_domain_to_definition(elem)
61
+ ((d = elem.at(ns("./domain"))) &&
62
+ (v = elem.at(ns("./definition/verbal-definition"))) &&
63
+ v.elements.first.name == "p") or return
64
+ v.elements.first.children.first.previous =
65
+ "&#x3c;#{to_xml(d.remove.children)}&#x3e; "
66
+ end
67
+
68
+ def insertall_after_here(node, insert, name)
69
+ node.children.each do |n|
70
+ n.name == name or next
71
+ insert.next = n.remove
72
+ insert = n
73
+ end
74
+ insert
75
+ end
76
+
77
+ def termexamples_before_termnotes(node)
78
+ insert = node.at(ns("./definition")) or return
79
+ insert = insertall_after_here(node, insert, "termexample")
80
+ insertall_after_here(node, insert, "termnote")
81
+ end
82
+
83
+ def terms(docxml)
84
+ docxml.xpath(ns("//term[termnote][termexample]")).each do |node|
85
+ termexamples_before_termnotes(node)
86
+ end
87
+ super
88
+ end
89
+
90
+ def related1(node)
91
+ node.remove
92
+ end
93
+
94
+ def termsource_status(status)
95
+ case status
96
+ when "modified", "adapted"
97
+ @i18n.modified
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -3,6 +3,7 @@ require "isodoc"
3
3
  require_relative "index"
4
4
  require_relative "presentation_xref"
5
5
  require_relative "presentation_bibdata"
6
+ require_relative "presentation_terms"
6
7
  require_relative "../../relaton/render/general"
7
8
 
8
9
  module IsoDoc
@@ -86,50 +87,6 @@ module IsoDoc
86
87
  end
87
88
  end
88
89
 
89
- def concept(docxml)
90
- concept_term(docxml)
91
- docxml.xpath(ns("//concept")).each do |node|
92
- concept_render(node, ital: "false", ref: "false",
93
- linkref: "true", linkmention: "false")
94
- end
95
- end
96
-
97
- def concept_term(docxml)
98
- docxml.xpath(ns("//term")).each do |f|
99
- m = {}
100
- (f.xpath(ns(".//concept")) - f.xpath(ns(".//term//concept")))
101
- .each { |c| concept_term1(c, m) }
102
- end
103
- end
104
-
105
- def concept_term1(node, seen)
106
- term = to_xml(node.at(ns("./refterm")))
107
- if term && seen[term]
108
- concept_render(node, ital: "false", ref: "false",
109
- linkref: "true", linkmention: "false")
110
- else concept_render(node, ital: "true", ref: "true",
111
- linkref: "true", linkmention: "false")
112
- end
113
- seen[term] = true if term
114
- seen
115
- end
116
-
117
- def concept1_ref_content(ref)
118
- prev = "("
119
- foll = ")"
120
- if ref.name == "termref"
121
- prev, foll = @i18n.term_defined_in.split("%")
122
- end
123
- ref.previous = prev
124
- ref.next = foll
125
- end
126
-
127
- def concept1(node)
128
- node.replace(node&.at(ns("./renderterm"))&.children ||
129
- node&.at(ns("./refterm"))&.children ||
130
- node.children)
131
- end
132
-
133
90
  # we're assuming terms and clauses in the right place for display,
134
91
  # to cope with multiple terms sections
135
92
  def display_order(docxml)
@@ -145,41 +102,6 @@ module IsoDoc
145
102
  display_order_xpath(docxml, "//indexsect", i)
146
103
  end
147
104
 
148
- def termdefinition1(elem)
149
- prefix_domain_to_definition(elem)
150
- super
151
- end
152
-
153
- def prefix_domain_to_definition(elem)
154
- ((d = elem.at(ns("./domain"))) &&
155
- (v = elem.at(ns("./definition/verbal-definition"))) &&
156
- v.elements.first.name == "p") or return
157
- v.elements.first.children.first.previous =
158
- "&#x3c;#{to_xml(d.remove.children)}&#x3e; "
159
- end
160
-
161
- def insertall_after_here(node, insert, name)
162
- node.children.each do |n|
163
- n.name == name or next
164
- insert.next = n.remove
165
- insert = n
166
- end
167
- insert
168
- end
169
-
170
- def termexamples_before_termnotes(node)
171
- insert = node.at(ns("./definition")) or return
172
- insert = insertall_after_here(node, insert, "termexample")
173
- insertall_after_here(node, insert, "termnote")
174
- end
175
-
176
- def terms(docxml)
177
- docxml.xpath(ns("//term[termnote][termexample]")).each do |node|
178
- termexamples_before_termnotes(node)
179
- end
180
- super
181
- end
182
-
183
105
  def admonition1(elem)
184
106
  super
185
107
  n = elem.at(ns("./name")) or return
@@ -212,10 +134,6 @@ module IsoDoc
212
134
  type
213
135
  end
214
136
 
215
- def related1(node)
216
- node.remove
217
- end
218
-
219
137
  def note1(elem)
220
138
  elem["type"] == "units" and return
221
139
  super
@@ -54,6 +54,7 @@ module Metanorma
54
54
  super
55
55
  @amd = %w(amendment technical-corrigendum).include? doctype(node)
56
56
  @vocab = node.attr("docsubtype") == "vocabulary"
57
+ @validate_years = node.attr("validate-years")
57
58
  end
58
59
 
59
60
  def toc_default
@@ -17,7 +17,7 @@
17
17
  these elements; we just want one namespace for any child grammars
18
18
  of this.
19
19
  -->
20
- <!-- VERSION v1.2.1 -->
20
+ <!-- VERSION v1.2.2 -->
21
21
  <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">
22
22
  <include href="reqt.rng"/>
23
23
  <include href="basicdoc.rng">
@@ -211,6 +211,9 @@
211
211
  <data type="boolean"/>
212
212
  </attribute>
213
213
  </optional>
214
+ <optional>
215
+ <attribute name="style"/>
216
+ </optional>
214
217
  <ref name="CitationType"/>
215
218
  <oneOrMore>
216
219
  <ref name="PureTextElement"/>
@@ -2136,6 +2139,7 @@
2136
2139
  <choice>
2137
2140
  <value>identical</value>
2138
2141
  <value>modified</value>
2142
+ <value>adapted</value>
2139
2143
  <value>restyled</value>
2140
2144
  <value>context-added</value>
2141
2145
  <value>generalisation</value>
@@ -30,6 +30,7 @@ module Metanorma
30
30
  # ISO/IEC DIR 2, 15.5.3, 20.2
31
31
  # does not deal with preceding text marked up
32
32
  def see_xrefs_validate(root)
33
+ @lang == "en" or return
33
34
  root.xpath("//xref").each do |t|
34
35
  preceding = t.at("./preceding-sibling::text()[last()]")
35
36
  next unless !preceding.nil? &&
@@ -45,6 +46,7 @@ module Metanorma
45
46
 
46
47
  # ISO/IEC DIR 2, 15.5.3
47
48
  def see_erefs_validate(root)
49
+ @lang == "en" or return
48
50
  root.xpath("//eref").each do |t|
49
51
  prec = t.at("./preceding-sibling::text()[last()]")
50
52
  next unless !prec.nil? && /\b(see|refer to)\s*\Z/mi.match(prec)
@@ -3,8 +3,9 @@ module Metanorma
3
3
  class Converter < Standoc::Converter
4
4
  # DRG directives 3.7; but anticipated by standoc
5
5
  def subfigure_validate(xmldoc)
6
+ elems = { footnote: "fn", note: "note", key: "dl" }
6
7
  xmldoc.xpath("//figure//figure").each do |f|
7
- { footnote: "fn", note: "note", key: "dl" }.each do |k, v|
8
+ elems.each do |k, v|
8
9
  f.xpath(".//#{v}").each do |n|
9
10
  @log.add("Style", n, "#{k} is not permitted in a subfigure")
10
11
  end
@@ -13,10 +14,10 @@ module Metanorma
13
14
  end
14
15
 
15
16
  def image_name_prefix(xmldoc)
16
- std = xmldoc&.at("//bibdata/ext/structuredidentifier/project-number") or
17
+ std = xmldoc.at("//bibdata/ext/structuredidentifier/project-number") or
17
18
  return
18
- num = xmldoc&.at("//bibdata/docnumber")&.text or return
19
- ed = xmldoc&.at("//bibdata/edition")&.text || "1"
19
+ num = xmldoc.at("//bibdata/docnumber")&.text or return
20
+ ed = xmldoc.at("//bibdata/edition")&.text || "1"
20
21
  prefix = num
21
22
  std["part"] and prefix += "-#{std['part']}"
22
23
  prefix += "_ed#{ed}"
@@ -25,7 +26,7 @@ module Metanorma
25
26
  end
26
27
 
27
28
  def image_name_suffix(xmldoc)
28
- case xmldoc&.at("//bibdata/language")&.text
29
+ case xmldoc.at("//bibdata/language")&.text
29
30
  when "fr" then "_f"
30
31
  when "de" then "_d"
31
32
  when "ru" then "_r"
@@ -60,7 +60,7 @@ module Metanorma
60
60
  case prectext.strip[-1]
61
61
  when ":", "" then list_after_colon_punctuation(list, entries)
62
62
  when "." then entries.each { |li| list_full_sentence(li) }
63
- else style_warning(list, "All lists must be preceded by "\
63
+ else style_warning(list, "All lists must be preceded by " \
64
64
  "colon or full stop", prectext)
65
65
  end
66
66
  end
@@ -80,7 +80,7 @@ module Metanorma
80
80
  def list_semicolon_phrase(elem, last)
81
81
  text = elem.text.strip
82
82
  starts_lowercase?(text) or
83
- style_warning(elem, "List entry of broken up sentence must start "\
83
+ style_warning(elem, "List entry of broken up sentence must start " \
84
84
  "with lowercase letter", text)
85
85
  list_semicolon_phrase_punct(elem, text, last)
86
86
  end
@@ -89,11 +89,11 @@ module Metanorma
89
89
  punct = text.strip.sub(/^.*?(\S)$/m, "\\1")
90
90
  if last
91
91
  punct == "." or
92
- style_warning(elem, "Final list entry of broken up "\
92
+ style_warning(elem, "Final list entry of broken up " \
93
93
  "sentence must end with full stop", text)
94
94
  else
95
95
  punct == ";" or
96
- style_warning(elem, "List entry of broken up sentence must "\
96
+ style_warning(elem, "List entry of broken up sentence must " \
97
97
  "end with semicolon", text)
98
98
  end
99
99
  end
@@ -102,11 +102,11 @@ module Metanorma
102
102
  %w(Cyrl Latn Grek).include?(@script) or return
103
103
  text = elem.text.strip
104
104
  starts_uppercase?(text) or
105
- style_warning(elem, "List entry of separate sentences must start "\
105
+ style_warning(elem, "List entry of separate sentences must start " \
106
106
  "with uppercase letter", text)
107
107
  punct = text.strip.sub(/^.*?(\S)$/m, "\\1")
108
108
  punct == "." or
109
- style_warning(elem, "List entry of separate sentences must "\
109
+ style_warning(elem, "List entry of separate sentences must " \
110
110
  "end with full stop", text)
111
111
  end
112
112
 
@@ -24,6 +24,7 @@ module Metanorma
24
24
  end
25
25
 
26
26
  def requirement_check(text)
27
+ @lang == "en" or return
27
28
  text.split(/\.\s+/).each do |t|
28
29
  return t if requirement_re.match t
29
30
  end
@@ -44,6 +45,7 @@ module Metanorma
44
45
  end
45
46
 
46
47
  def recommendation_check(text)
48
+ @lang == "en" or return
47
49
  text.split(/\.\s+/).each do |t|
48
50
  return t if recommendation_re.match t
49
51
  end
@@ -60,6 +62,7 @@ module Metanorma
60
62
  REGEXP
61
63
 
62
64
  def permission_re
65
+ @lang == "en" or return
63
66
  Regexp.new(self.class::PERMISSION_RE_STR.gsub(/\s/, "")
64
67
  .gsub(/_/, "\\s"), Regexp::IGNORECASE)
65
68
  end
@@ -82,6 +85,7 @@ module Metanorma
82
85
  REGEXP
83
86
 
84
87
  def possibility_re
88
+ @lang == "en" or return
85
89
  Regexp.new(self.class::POSSIBILITY_RE_STR.gsub(/\s/, "")
86
90
  .gsub(/_/, "\\s"), Regexp::IGNORECASE)
87
91
  end
@@ -98,6 +102,26 @@ module Metanorma
98
102
  nil
99
103
  end
100
104
 
105
+ AMBIG_WORDS_RE_STR = <<~REGEXP.freeze
106
+ \\b
107
+ need_to | needs_to | might | could
108
+ \\b
109
+ REGEXP
110
+
111
+ def ambig_words_re
112
+ @lang == "en" or return
113
+ Regexp.new(self.class::AMBIG_WORDS_RE_STR.gsub(/\s/, "")
114
+ .gsub(/_/, "\\s"), Regexp::IGNORECASE)
115
+ end
116
+
117
+ def ambig_words_check(text)
118
+ @lang == "en" or return
119
+ text.split(/\.\s+/).each do |t|
120
+ return t if ambig_words_re.match t
121
+ end
122
+ nil
123
+ end
124
+
101
125
  def style_no_guidance(node, text, docpart)
102
126
  @lang == "en" or return
103
127
  r = requirement_check(text)
@@ -90,32 +90,63 @@ module Metanorma
90
90
  end
91
91
 
92
92
  def style(node, text)
93
- return if @novalid
94
-
93
+ @novalid and return
95
94
  style_number(node, text)
96
95
  style_percent(node, text)
97
96
  style_abbrev(node, text)
98
97
  style_units(node, text)
99
98
  style_punct(node, text)
99
+ style_subscript(node)
100
+ style_ambig_words(node, text)
101
+ end
102
+
103
+ # https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-s-quantity
104
+ def style_subscript(node)
105
+ warning = "may contain nested subscripts (max 3 levels allowed)"
106
+ node.xpath(".//sub[.//sub]").each do |x|
107
+ style_warning(node, warning, x.to_xml)
108
+ end
109
+ node.xpath(".//m:msub[.//m:msub]", "m" => MATHML_NS).each do |x|
110
+ style_warning(node, warning, x.to_xml)
111
+ end
112
+ end
113
+
114
+ # https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-s-need
115
+ # https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-s-might
116
+ def style_ambig_words(node, text)
117
+ r = ambig_words_check(text) and
118
+ style_warning(node, "may contain ambiguous provision", r)
100
119
  end
101
120
 
102
121
  # ISO/IEC DIR 2, 9.1
103
122
  # ISO/IEC DIR 2, Table B.1
104
123
  # https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-n-numbers
105
124
  def style_number(node, text)
106
- style_two_regex_not_prev(
107
- node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)\Z/,
108
- %r{\b(ISO|IEC|IEEE/|(in|January|February|March|April|May|June|August|September|October|November|December)\b)\Z},
109
- "number not broken up in threes"
110
- )
125
+ style_number_grouping(node, text)
111
126
  style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i,
112
127
  "possible decimal point", node, text)
113
128
  @lang == "en" and style_regex(/\b(?<num>billions?)\b/i,
114
129
  "ambiguous number", node, text)
115
- style_regex(/(^|\s)(?<num>-[0-9][0-9,.]*)/i,
130
+ style_regex(/(?:^|\s)(?<num>-[0-9][0-9,.]*)/i,
116
131
  "hyphen instead of minus sign U+2212", node, text)
117
132
  end
118
133
 
134
+ def style_number_grouping(node, text)
135
+ if @validate_years
136
+ style_two_regex_not_prev(
137
+ node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)\Z/,
138
+ %r{\b(ISO|IEC|IEEE|(in|January|February|March|April|May|June|August|September|October|November|December)\b)\Z},
139
+ "number not broken up in threes"
140
+ )
141
+ else
142
+ style_two_regex_not_prev(
143
+ node, text, /^(?<num>-?(?:[0-9]{5,}[,0-9]*|[03-9]\d\d\d|1[0-8]\d\d|2[1-9]\d\d|20[5-9]\d))\Z/,
144
+ %r{\b(ISO|IEC|IEEE|\b)\Z},
145
+ "number not broken up in threes"
146
+ )
147
+ end
148
+ end
149
+
119
150
  # ISO/IEC DIR 2, 9.2.1
120
151
  def style_percent(node, text)
121
152
  style_regex(/\b(?<num>[0-9.,]+%)/,
@@ -169,6 +200,16 @@ module Metanorma
169
200
  "Use 'either x or y, or both'", node, text)
170
201
  style_regex(/\s(?<num>&)\s/i,
171
202
  "Avoid ampersand in ordinary text'", node, text)
203
+ eref_style_punct(node)
204
+ end
205
+
206
+ # https://www.iso.org/ISO-house-style.html#iso-hs-s-text-r-r-ref_unnumbered
207
+ def eref_style_punct(node)
208
+ node.xpath(".//eref[@type='footnote']").each do |e|
209
+ /^\p{P}/.match?(e.next&.text) or next
210
+ style_warning(node, "superscript cross-reference followed by punctuation",
211
+ node.to_xml)
212
+ end
172
213
  end
173
214
 
174
215
  def style_warning(node, msg, text = nil)
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  module ISO
3
- VERSION = "2.4.3".freeze
3
+ VERSION = "2.4.4".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-iso
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.3
4
+ version: 2.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-25 00:00:00.000000000 Z
11
+ date: 2023-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: metanorma-standoc
@@ -352,6 +352,7 @@ files:
352
352
  - lib/isodoc/iso/metadata.rb
353
353
  - lib/isodoc/iso/pdf_convert.rb
354
354
  - lib/isodoc/iso/presentation_bibdata.rb
355
+ - lib/isodoc/iso/presentation_terms.rb
355
356
  - lib/isodoc/iso/presentation_xml_convert.rb
356
357
  - lib/isodoc/iso/presentation_xref.rb
357
358
  - lib/isodoc/iso/sections.rb