metanorma-iso 2.4.3 → 2.4.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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