metanorma-iso 1.7.4 → 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +3 -13
  3. data/.hound.yml +3 -1
  4. data/.rubocop.yml +3 -7
  5. data/lib/asciidoctor/iso/base.rb +14 -11
  6. data/lib/asciidoctor/iso/biblio.rng +1 -0
  7. data/lib/asciidoctor/iso/cleanup.rb +40 -24
  8. data/lib/asciidoctor/iso/front.rb +28 -16
  9. data/lib/asciidoctor/iso/front_id.rb +66 -50
  10. data/lib/asciidoctor/iso/isodoc.rng +321 -4
  11. data/lib/asciidoctor/iso/isostandard-amd.rng +3 -0
  12. data/lib/asciidoctor/iso/isostandard.rng +12 -0
  13. data/lib/asciidoctor/iso/section.rb +2 -1
  14. data/lib/asciidoctor/iso/validate.rb +22 -110
  15. data/lib/asciidoctor/iso/validate_image.rb +97 -0
  16. data/lib/asciidoctor/iso/validate_requirements.rb +26 -20
  17. data/lib/asciidoctor/iso/validate_section.rb +55 -29
  18. data/lib/asciidoctor/iso/validate_style.rb +36 -24
  19. data/lib/asciidoctor/iso/validate_title.rb +2 -4
  20. data/lib/isodoc/iso/base_convert.rb +8 -2
  21. data/lib/isodoc/iso/html/style-human.css +7 -0
  22. data/lib/isodoc/iso/html/style-iso.css +7 -0
  23. data/lib/isodoc/iso/html_convert.rb +0 -1
  24. data/lib/isodoc/iso/iso.amendment.xsl +680 -198
  25. data/lib/isodoc/iso/iso.international-standard.xsl +680 -198
  26. data/lib/isodoc/iso/metadata.rb +1 -0
  27. data/lib/isodoc/iso/presentation_xml_convert.rb +44 -33
  28. data/lib/isodoc/iso/sts_convert.rb +10 -13
  29. data/lib/isodoc/iso/word_convert.rb +0 -1
  30. data/lib/isodoc/iso/xref.rb +52 -34
  31. data/lib/metanorma/iso/processor.rb +1 -0
  32. data/lib/metanorma/iso/version.rb +1 -1
  33. data/metanorma-iso.gemspec +7 -7
  34. data/spec/asciidoctor/base_spec.rb +426 -305
  35. data/spec/asciidoctor/blocks_spec.rb +96 -34
  36. data/spec/asciidoctor/cleanup_spec.rb +383 -25
  37. data/spec/asciidoctor/section_spec.rb +0 -14
  38. data/spec/asciidoctor/validate_spec.rb +218 -83
  39. data/spec/isodoc/postproc_spec.rb +481 -438
  40. data/spec/spec_helper.rb +16 -15
  41. metadata +46 -46
  42. data/lib/isodoc/iso/html/scripts.html +0 -178
@@ -0,0 +1,97 @@
1
+ module Asciidoctor
2
+ module ISO
3
+ class Converter < Standoc::Converter
4
+ # DRG directives 3.7; but anticipated by standoc
5
+ def subfigure_validate(xmldoc)
6
+ xmldoc.xpath("//figure//figure").each do |f|
7
+ { footnote: "fn", note: "note", key: "dl" }.each do |k, v|
8
+ f.xpath(".//#{v}").each do |n|
9
+ @log.add("Style", n, "#{k} is not permitted in a subfigure")
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ def image_name_prefix(xmldoc)
16
+ std = xmldoc&.at("//bibdata/ext/structuredidentifier/project-number") or
17
+ return
18
+ num = xmldoc&.at("//bibdata/docnumber")&.text or return
19
+ ed = xmldoc&.at("//bibdata/edition")&.text || "1"
20
+ prefix = num
21
+ std["part"] and prefix += "-#{std['part']}"
22
+ prefix += "_ed#{ed}"
23
+ amd = std["amendment"] and prefix += "amd#{amd}"
24
+ prefix
25
+ end
26
+
27
+ def image_name_suffix(xmldoc)
28
+ case xmldoc&.at("//bibdata/language")&.text
29
+ when "fr" then "_f"
30
+ when "de" then "_d"
31
+ when "ru" then "_r"
32
+ when "es" then "_s"
33
+ when "ar" then "_a"
34
+ when "en" then "_e"
35
+ else
36
+ "_e"
37
+ end
38
+ end
39
+
40
+ def disjunct_error(img, cond1, cond2, msg1, msg2)
41
+ cond1 && !cond2 and
42
+ @log.add("Style", img, "image name #{img['src']} #{msg1}")
43
+ !cond1 && cond2 and
44
+ @log.add("Style", img, "image name #{img['src']} #{msg2}")
45
+ end
46
+
47
+ def image_name_parse(img, prefix)
48
+ m = %r[(SL)?#{prefix}fig(?<tab>Tab)?(?<annex>[A-Z])?(Text)?(?<num>\d+)
49
+ (?<subfig>[a-z])?(?<key>_key\d+)?(?<lang>_[a-z])?$]x
50
+ .match(File.basename(img["src"], ".*"))
51
+ m.nil? and
52
+ @log.add("Style", img,
53
+ "image name #{img['src']} does not match DRG requirements")
54
+ m
55
+ end
56
+
57
+ def image_name_validate1(i, prefix)
58
+ m = image_name_parse(i, prefix) or return
59
+ warn i["src"]
60
+ disjunct_error(i, i.at("./ancestor::table"), !m[:tab].nil?,
61
+ "is under a table but is not so labelled",
62
+ "is labelled as under a table but is not")
63
+ disjunct_error(i, i.at("./ancestor::annex"), !m[:annex].nil?,
64
+ "is under an annex but is not so labelled",
65
+ "is labelled as under an annex but is not")
66
+ disjunct_error(i, i.xpath("./ancestor::figure").size > 1, !m[:subfig].nil?,
67
+ "does not have a subfigure letter but is a subfigure",
68
+ "has a subfigure letter but is not a subfigure")
69
+ lang = image_name_suffix(i.document.root)
70
+ (m[:lang] || "_e") == lang or
71
+ @log.add("Style", i,
72
+ "image name #{i['src']} expected to have suffix #{lang}")
73
+ end
74
+
75
+ # DRG directives 3.2
76
+ def image_name_validate(xmldoc)
77
+ prefix = image_name_prefix(xmldoc) or return
78
+ xmldoc.xpath("//image").each do |i|
79
+ next if i["src"].start_with?("data:")
80
+
81
+ if /^ISO_\d+_/.match?(File.basename(i["src"]))
82
+ elsif /^(SL)?#{prefix}fig/.match?(File.basename(i["src"]))
83
+ image_name_validate1(i, prefix)
84
+ else
85
+ @log.add("Style", i,
86
+ "image name #{i['src']} does not match DRG requirements: expect #{prefix}fig")
87
+ end
88
+ end
89
+ end
90
+
91
+ def figure_validate(xmldoc)
92
+ image_name_validate(xmldoc)
93
+ subfigure_validate(xmldoc)
94
+ end
95
+ end
96
+ end
97
+ end
@@ -1,6 +1,4 @@
1
1
  require "metanorma-standoc"
2
- require "nokogiri"
3
- require "pp"
4
2
 
5
3
  module Asciidoctor
6
4
  module ISO
@@ -19,13 +17,15 @@ module Asciidoctor
19
17
  [.,:;]_do_not )
20
18
  \\b
21
19
  REGEXP
22
- REQUIREMENT_RE =
23
- Regexp.new(REQUIREMENT_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
24
- Regexp::IGNORECASE)
20
+
21
+ def requirement_re
22
+ Regexp.new(self.class::REQUIREMENT_RE_STR.gsub(/\s/, "")
23
+ .gsub(/_/, "\\s"), Regexp::IGNORECASE)
24
+ end
25
25
 
26
26
  def requirement_check(text)
27
27
  text.split(/\.\s+/).each do |t|
28
- return t if REQUIREMENT_RE.match t
28
+ return t if requirement_re.match t
29
29
  end
30
30
  nil
31
31
  end
@@ -37,13 +37,15 @@ module Asciidoctor
37
37
  it_is_(not_)?recommended_that
38
38
  \\b
39
39
  REGEXP
40
- RECOMMENDATION_RE =
41
- Regexp.new(RECOMMENDATION_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
42
- Regexp::IGNORECASE)
40
+
41
+ def recommendation_re
42
+ Regexp.new(self.class::RECOMMENDATION_RE_STR.gsub(/\s/, "")
43
+ .gsub(/_/, "\\s"), Regexp::IGNORECASE)
44
+ end
43
45
 
44
46
  def recommendation_check(text)
45
47
  text.split(/\.\s+/).each do |t|
46
- return t if RECOMMENDATION_RE.match t
48
+ return t if recommendation_re.match t
47
49
  end
48
50
  nil
49
51
  end
@@ -56,13 +58,15 @@ module Asciidoctor
56
58
  no\\b[^.,]+\\b(is|are)_required
57
59
  \\b
58
60
  REGEXP
59
- PERMISSION_RE =
60
- Regexp.new(PERMISSION_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
61
- Regexp::IGNORECASE)
61
+
62
+ def permission_re
63
+ Regexp.new(self.class::PERMISSION_RE_STR.gsub(/\s/, "")
64
+ .gsub(/_/, "\\s"), Regexp::IGNORECASE)
65
+ end
62
66
 
63
67
  def permission_check(text)
64
68
  text.split(/\.\s+/).each do |t|
65
- return t if PERMISSION_RE.match t
69
+ return t if permission_re.match t
66
70
  end
67
71
  nil
68
72
  end
@@ -76,18 +80,20 @@ module Asciidoctor
76
80
  it_is_not_possible_to
77
81
  \\b
78
82
  REGEXP
79
- POSSIBILITY_RE =
80
- Regexp.new(POSSIBILITY_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
81
- Regexp::IGNORECASE)
82
83
 
83
- def possibility(text)
84
- text.split(/\.\s+/).each { |t| return t if POSSIBILITY_RE.match t }
84
+ def possibility_re
85
+ Regexp.new(self.class::POSSIBILITY_RE_STR.gsub(/\s/, "")
86
+ .gsub(/_/, "\\s"), Regexp::IGNORECASE)
87
+ end
88
+
89
+ def possibility_check(text)
90
+ text.split(/\.\s+/).each { |t| return t if possibility_re.match t }
85
91
  nil
86
92
  end
87
93
 
88
94
  def external_constraint(text)
89
95
  text.split(/\.\s+/).each do |t|
90
- return t if /\b(must)\b/xi.match t
96
+ return t if /\b(must)\b/xi.match? t
91
97
  end
92
98
  nil
93
99
  end
@@ -50,10 +50,11 @@ module Asciidoctor
50
50
  end
51
51
 
52
52
  def seqcheck(names, msg, accepted)
53
- n = names.shift
53
+ n = names.shift
54
54
  return [] if n.nil?
55
+
55
56
  test = accepted.map { |a| n.at(a) }
56
- if test.all? { |a| a.nil? }
57
+ if test.all?(&:nil?)
57
58
  @log.add("Style", nil, msg)
58
59
  end
59
60
  names
@@ -74,57 +75,65 @@ module Asciidoctor
74
75
  [
75
76
  {
76
77
  msg: "Initial section must be (content) Foreword",
77
- val: ["./self::foreword"]
78
+ val: ["./self::foreword"],
78
79
  },
79
80
  {
80
81
  msg: "Prefatory material must be followed by (clause) Scope",
81
- val: ["./self::introduction", "./self::clause[@type = 'scope']" ]
82
+ val: ["./self::introduction", "./self::clause[@type = 'scope']"],
82
83
  },
83
84
  {
84
85
  msg: "Prefatory material must be followed by (clause) Scope",
85
- val: ["./self::clause[@type = 'scope']" ]
86
+ val: ["./self::clause[@type = 'scope']"],
86
87
  },
87
88
  {
88
89
  msg: "Normative References must be followed by "\
89
90
  "Terms and Definitions",
90
- val: ["./self::terms | .//terms"]
91
+ val: ["./self::terms | .//terms"],
91
92
  },
92
- ].freeze
93
+ ].freeze
93
94
 
94
95
  SECTIONS_XPATH =
95
96
  "//foreword | //introduction | //sections/terms | .//annex | "\
96
- "//sections/definitions | //sections/clause | //references[not(parent::clause)] | "\
97
+ "//sections/definitions | //sections/clause | "\
98
+ "//references[not(parent::clause)] | "\
97
99
  "//clause[descendant::references][not(parent::clause)]".freeze
98
100
 
99
101
  def sections_sequence_validate(root)
102
+ vocab = root&.at("//bibdata/ext/subdoctype")&.text == "vocabulary"
100
103
  names = root.xpath(SECTIONS_XPATH)
101
- names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
104
+ names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
102
105
  n = names[0]
103
- names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
106
+ names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
104
107
  if n&.at("./self::introduction")
105
- names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
108
+ names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
106
109
  end
107
- names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
110
+ names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
108
111
  n = names.shift
109
112
  if n&.at("./self::definitions")
110
113
  n = names.shift
111
114
  end
112
115
  if n.nil? || n.name != "clause"
113
- @log.add("Style", nil, "Document must contain at least one clause")
116
+ @log.add("Style", n, "Document must contain at least one clause")
114
117
  end
115
118
  n&.at("./self::clause") ||
116
- @log.add("Style", nil, "Document must contain clause after "\
119
+ @log.add("Style", n, "Document must contain clause after "\
117
120
  "Terms and Definitions")
118
121
  n&.at("./self::clause[@type = 'scope']") &&
119
- @log.add("Style", nil, "Scope must occur before Terms and Definitions")
120
- n = names.shift
121
- while n&.name == "clause"
122
+ @log.add("Style", n, "Scope must occur before Terms and Definitions")
123
+ n = names.shift
124
+ while n&.name == "clause" || (vocab && n&.name == "terms")
122
125
  n&.at("./self::clause[@type = 'scope']")
123
- @log.add("Style", nil, "Scope must occur before Terms and Definitions")
124
- n = names.shift
126
+ @log.add("Style", n, "Scope must occur before Terms and Definitions")
127
+ n = names.shift
125
128
  end
126
- unless %w(annex references).include? n&.name
127
- @log.add("Style", nil, "Only annexes and references can follow clauses")
129
+ if vocab
130
+ unless %w(annex references terms).include? n&.name
131
+ @log.add("Style", n, "Only terms, annexes and references can follow clauses")
132
+ end
133
+ else
134
+ unless %w(annex references).include? n&.name
135
+ @log.add("Style", n, "Only annexes and references can follow clauses")
136
+ end
128
137
  end
129
138
  while n&.name == "annex"
130
139
  n = names.shift
@@ -138,13 +147,14 @@ module Asciidoctor
138
147
  "Normative References")
139
148
  n = names&.shift
140
149
  n&.at("./self::references[@normative = 'false']") ||
141
- @log.add("Style", nil, "Final section must be (references) Bibliography")
150
+ @log.add("Style", n, "Final section must be (references) Bibliography")
142
151
  names.empty? ||
143
- @log.add("Style", nil, "There are sections after the final Bibliography")
152
+ @log.add("Style", n, "There are sections after the final Bibliography")
144
153
  end
145
154
 
146
155
  def style_warning(node, msg, text = nil)
147
156
  return if @novalid
157
+
148
158
  w = msg
149
159
  w += ": #{text}" if text
150
160
  @log.add("Style", node, w)
@@ -165,15 +175,18 @@ module Asciidoctor
165
175
 
166
176
  def tech_report_style(root)
167
177
  root.at("//bibdata/ext/doctype")&.text == "technical-report" or return
168
- root.xpath("//sections/clause[not(@type = 'scope')] | //annex").each do |s|
169
- r = requirement_check(extract_text(s))
170
- style_warning(s, "Technical Report clause may contain requirement", r) if r
178
+ root.xpath("//sections/clause[not(@type = 'scope')] | //annex")
179
+ .each do |s|
180
+ r = requirement_check(extract_text(s)) and
181
+ style_warning(s,
182
+ "Technical Report clause may contain requirement", r)
171
183
  end
172
184
  end
173
185
 
174
186
  ASSETS_TO_STYLE =
175
- "//termsource | //formula | //termnote | //p[not(ancestor::boilerplate)] | "\
176
- "//li[not(p)] | //dt | //dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
187
+ "//termsource | //formula | //termnote | "\
188
+ "//p[not(ancestor::boilerplate)] | //li[not(p)] | //dt | "\
189
+ "//dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
177
190
 
178
191
  NORM_BIBITEMS =
179
192
  "//references[@normative = 'true']/bibitem".freeze
@@ -198,10 +211,23 @@ module Asciidoctor
198
211
  end
199
212
 
200
213
  def subclause_validate(root)
201
- root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause").each do |c|
214
+ root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause")
215
+ .each do |c|
202
216
  style_warning(c, "Exceeds the maximum clause depth of 7", nil)
203
217
  end
204
218
  end
219
+
220
+ # ISO/IEC DIR 2, 22.3.2
221
+ def onlychild_clause_validate(root)
222
+ root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c|
223
+ next unless c.xpath("../clause").size == 1
224
+
225
+ title = c.at("./title")
226
+ location = c["id"] || "#{c.text[0..60]}..."
227
+ location += ":#{title.text}" if c["id"] && !title.nil?
228
+ @log.add("Style", nil, "#{location}: subclause is only child")
229
+ end
230
+ end
205
231
  end
206
232
  end
207
233
  end
@@ -7,28 +7,32 @@ module Asciidoctor
7
7
  class Converter < Standoc::Converter
8
8
  def extract_text(node)
9
9
  return "" if node.nil?
10
+
10
11
  node1 = Nokogiri::XML.fragment(node.to_s)
11
12
  node1.xpath("//link | //locality | //localityStack").each(&:remove)
12
13
  ret = ""
13
14
  node1.traverse { |x| ret += x.text if x.text? }
14
- ret
15
+ HTMLEntities.new.decode(ret)
15
16
  end
16
17
 
17
18
  # ISO/IEC DIR 2, 12.2
18
19
  def foreword_style(node)
19
20
  return if @novalid
21
+
20
22
  style_no_guidance(node, extract_text(node), "Foreword")
21
23
  end
22
24
 
23
25
  # ISO/IEC DIR 2, 14.2
24
26
  def scope_style(node)
25
27
  return if @novalid
28
+
26
29
  style_no_guidance(node, extract_text(node), "Scope")
27
30
  end
28
31
 
29
32
  # ISO/IEC DIR 2, 13.2
30
33
  def introduction_style(node)
31
34
  return if @novalid
35
+
32
36
  r = requirement_check(extract_text(node))
33
37
  style_warning(node, "Introduction may contain requirement", r) if r
34
38
  end
@@ -36,6 +40,7 @@ module Asciidoctor
36
40
  # ISO/IEC DIR 2, 16.5.6
37
41
  def definition_style(node)
38
42
  return if @novalid
43
+
39
44
  r = requirement_check(extract_text(node))
40
45
  style_warning(node, "Definition may contain requirement", r) if r
41
46
  end
@@ -44,6 +49,7 @@ module Asciidoctor
44
49
  # ISO/IEC DIR 2, 25.5
45
50
  def example_style(node)
46
51
  return if @novalid
52
+
47
53
  style_no_guidance(node, extract_text(node), "Example")
48
54
  style(node, extract_text(node))
49
55
  end
@@ -51,6 +57,7 @@ module Asciidoctor
51
57
  # ISO/IEC DIR 2, 24.5
52
58
  def note_style(node)
53
59
  return if @novalid
60
+
54
61
  style_no_guidance(node, extract_text(node), "Note")
55
62
  style(node, extract_text(node))
56
63
  end
@@ -58,6 +65,7 @@ module Asciidoctor
58
65
  # ISO/IEC DIR 2, 26.5
59
66
  def footnote_style(node)
60
67
  return if @novalid
68
+
61
69
  style_no_guidance(node, extract_text(node), "Footnote")
62
70
  style(node, extract_text(node))
63
71
  end
@@ -70,6 +78,7 @@ module Asciidoctor
70
78
  # and a negative match on its preceding token
71
79
  def style_two_regex_not_prev(n, text, re, re_prev, warning)
72
80
  return if text.nil?
81
+
73
82
  arr = Tokenizer::WhitespaceTokenizer.new.tokenize(text)
74
83
  arr.each_index do |i|
75
84
  m = re.match arr[i]
@@ -80,43 +89,45 @@ module Asciidoctor
80
89
  end
81
90
  end
82
91
 
83
- def style(n, t)
92
+ def style(node, text)
84
93
  return if @novalid
85
- style_number(n, t)
86
- style_percent(n, t)
87
- style_abbrev(n, t)
88
- style_units(n, t)
94
+
95
+ style_number(node, text)
96
+ style_percent(node, text)
97
+ style_abbrev(node, text)
98
+ style_units(node, text)
89
99
  end
90
100
 
91
101
  # ISO/IEC DIR 2, 9.1
92
102
  # ISO/IEC DIR 2, Table B.1
93
- def style_number(n, t)
103
+ def style_number(node, text)
94
104
  style_two_regex_not_prev(
95
- n, t, /^(?<num>-?[0-9]{4,}[,0-9]*)$/,
105
+ node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)$/,
96
106
  %r{\b(ISO|IEC|IEEE/|(in|January|February|March|April|May|June|August|September|October|November|December)\b)$},
97
- "number not broken up in threes")
107
+ "number not broken up in threes"
108
+ )
98
109
  style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i,
99
- "possible decimal point", n, t)
100
- style_regex(/\b(?<num>billion[s]?)\b/i,
101
- "ambiguous number", n, t)
110
+ "possible decimal point", node, text)
111
+ style_regex(/\b(?<num>billions?)\b/i,
112
+ "ambiguous number", node, text)
102
113
  end
103
114
 
104
115
  # ISO/IEC DIR 2, 9.2.1
105
- def style_percent(n, t)
116
+ def style_percent(node, text)
106
117
  style_regex(/\b(?<num>[0-9.,]+%)/,
107
- "no space before percent sign", n, t)
118
+ "no space before percent sign", node, text)
108
119
  style_regex(/\b(?<num>[0-9.,]+ \u00b1 [0-9,.]+ %)/,
109
- "unbracketed tolerance before percent sign", n, t)
120
+ "unbracketed tolerance before percent sign", node, text)
110
121
  end
111
122
 
112
123
  # ISO/IEC DIR 2, 8.4
113
124
  # ISO/IEC DIR 2, 9.3
114
- def style_abbrev(n, t)
125
+ def style_abbrev(node, text)
115
126
  style_regex(/(^|\s)(?!e\.g\.|i\.e\.)
116
127
  (?<num>[a-z]{1,2}\.([a-z]{1,2}|\.))\b/ix,
117
- "no dots in abbreviations", n, t)
128
+ "no dots in abbreviations", node, text)
118
129
  style_regex(/\b(?<num>ppm)\b/i,
119
- "language-specific abbreviation", n, t)
130
+ "language-specific abbreviation", node, text)
120
131
  end
121
132
 
122
133
  # leaving out as problematic: N J K C S T H h d B o E
@@ -125,12 +136,13 @@ module Asciidoctor
125
136
  "bit|kB|MB|Hart|nat|Sh|var)".freeze
126
137
 
127
138
  # ISO/IEC DIR 2, 9.3
128
- def style_units(n, t)
139
+ def style_units(node, text)
129
140
  style_regex(/\b(?<num>[0-9][0-9,]*\s+[\u00b0\u2032\u2033])/,
130
- "space between number and degrees/minutes/seconds", n, t)
141
+ "space between number and degrees/minutes/seconds",
142
+ node, text)
131
143
  style_regex(/\b(?<num>[0-9][0-9,]*#{SI_UNIT})\b/,
132
- "no space between number and SI unit", n, t)
133
- style_non_std_units(n, t)
144
+ "no space between number and SI unit", node, text)
145
+ style_non_std_units(node, text)
134
146
  end
135
147
 
136
148
  NONSTD_UNITS = {
@@ -139,10 +151,10 @@ module Asciidoctor
139
151
  }.freeze
140
152
 
141
153
  # ISO/IEC DIR 2, 9.3
142
- def style_non_std_units(n, t)
154
+ def style_non_std_units(node, text)
143
155
  NONSTD_UNITS.each do |k, v|
144
156
  style_regex(/\b(?<num>[0-9][0-9,]*\s+#{k})\b/,
145
- "non-standard unit (should be #{v})", n, t)
157
+ "non-standard unit (should be #{v})", node, text)
146
158
  end
147
159
  end
148
160
  end