metanorma-iso 1.7.1 → 1.8.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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +11 -41
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +6 -2
  5. data/lib/asciidoctor/iso/base.rb +18 -16
  6. data/lib/asciidoctor/iso/biblio.rng +4 -6
  7. data/lib/asciidoctor/iso/cleanup.rb +28 -24
  8. data/lib/asciidoctor/iso/front.rb +26 -16
  9. data/lib/asciidoctor/iso/front_id.rb +30 -25
  10. data/lib/asciidoctor/iso/isodoc.rng +172 -3
  11. data/lib/asciidoctor/iso/isostandard-amd.rng +3 -0
  12. data/lib/asciidoctor/iso/isostandard.rng +17 -97
  13. data/lib/asciidoctor/iso/validate.rb +22 -109
  14. data/lib/asciidoctor/iso/validate_image.rb +97 -0
  15. data/lib/asciidoctor/iso/validate_requirements.rb +26 -20
  16. data/lib/asciidoctor/iso/validate_section.rb +39 -20
  17. data/lib/asciidoctor/iso/validate_style.rb +36 -24
  18. data/lib/asciidoctor/iso/validate_title.rb +23 -17
  19. data/lib/isodoc/iso/base_convert.rb +19 -2
  20. data/lib/isodoc/iso/html/style-human.css +7 -0
  21. data/lib/isodoc/iso/html/style-iso.css +7 -0
  22. data/lib/isodoc/iso/html_convert.rb +0 -1
  23. data/lib/isodoc/iso/i18n-en.yaml +4 -0
  24. data/lib/isodoc/iso/i18n-fr.yaml +4 -0
  25. data/lib/isodoc/iso/i18n-zh-Hans.yaml +4 -0
  26. data/lib/isodoc/iso/index.rb +140 -0
  27. data/lib/isodoc/iso/iso.amendment.xsl +1092 -208
  28. data/lib/isodoc/iso/iso.international-standard.xsl +1092 -208
  29. data/lib/isodoc/iso/presentation_xml_convert.rb +45 -37
  30. data/lib/isodoc/iso/word_convert.rb +0 -1
  31. data/lib/isodoc/iso/xref.rb +15 -7
  32. data/lib/metanorma/iso/processor.rb +1 -0
  33. data/lib/metanorma/iso/version.rb +1 -1
  34. data/metanorma-iso.gemspec +8 -8
  35. data/spec/asciidoctor/amd_spec.rb +696 -0
  36. data/spec/asciidoctor/base_spec.rb +733 -0
  37. data/spec/asciidoctor/blocks_spec.rb +527 -0
  38. data/spec/asciidoctor/cleanup_spec.rb +1134 -0
  39. data/spec/asciidoctor/inline_spec.rb +195 -0
  40. data/spec/asciidoctor/lists_spec.rb +197 -0
  41. data/spec/asciidoctor/refs_spec.rb +375 -0
  42. data/spec/asciidoctor/section_spec.rb +393 -0
  43. data/spec/asciidoctor/table_spec.rb +329 -0
  44. data/spec/asciidoctor/validate_spec.rb +1627 -0
  45. data/spec/isodoc/amd_spec.rb +967 -946
  46. data/spec/isodoc/blocks_spec.rb +530 -507
  47. data/spec/isodoc/i18n_spec.rb +953 -911
  48. data/spec/isodoc/inline_spec.rb +355 -293
  49. data/spec/isodoc/iso_spec.rb +338 -314
  50. data/spec/isodoc/metadata_spec.rb +392 -382
  51. data/spec/isodoc/postproc_spec.rb +836 -657
  52. data/spec/isodoc/ref_spec.rb +374 -331
  53. data/spec/isodoc/section_spec.rb +821 -519
  54. data/spec/isodoc/table_spec.rb +472 -411
  55. data/spec/isodoc/terms_spec.rb +209 -185
  56. data/spec/isodoc/xref_spec.rb +1370 -1236
  57. data/spec/metanorma/processor_spec.rb +28 -26
  58. data/spec/spec_helper.rb +178 -193
  59. metadata +65 -66
  60. data/.rubocop.ribose.yml +0 -66
  61. data/lib/isodoc/iso/html/scripts.html +0 -178
  62. data/spec/asciidoctor-iso/amd_spec.rb +0 -694
  63. data/spec/asciidoctor-iso/base_spec.rb +0 -713
  64. data/spec/asciidoctor-iso/blocks_spec.rb +0 -482
  65. data/spec/asciidoctor-iso/cleanup_spec.rb +0 -1025
  66. data/spec/asciidoctor-iso/inline_spec.rb +0 -170
  67. data/spec/asciidoctor-iso/lists_spec.rb +0 -190
  68. data/spec/asciidoctor-iso/refs_spec.rb +0 -317
  69. data/spec/asciidoctor-iso/section_spec.rb +0 -362
  70. data/spec/asciidoctor-iso/table_spec.rb +0 -313
  71. data/spec/asciidoctor-iso/validate_spec.rb +0 -1621
  72. data/spec/assets/xref_error.adoc +0 -7
@@ -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,37 +75,38 @@ 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)
100
102
  names = root.xpath(SECTIONS_XPATH)
101
- names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
103
+ names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
102
104
  n = names[0]
103
- names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
105
+ names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
104
106
  if n&.at("./self::introduction")
105
- names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
107
+ names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
106
108
  end
107
- names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
109
+ names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
108
110
  n = names.shift
109
111
  if n&.at("./self::definitions")
110
112
  n = names.shift
@@ -117,11 +119,11 @@ module Asciidoctor
117
119
  "Terms and Definitions")
118
120
  n&.at("./self::clause[@type = 'scope']") &&
119
121
  @log.add("Style", nil, "Scope must occur before Terms and Definitions")
120
- n = names.shift
122
+ n = names.shift
121
123
  while n&.name == "clause"
122
124
  n&.at("./self::clause[@type = 'scope']")
123
125
  @log.add("Style", nil, "Scope must occur before Terms and Definitions")
124
- n = names.shift
126
+ n = names.shift
125
127
  end
126
128
  unless %w(annex references).include? n&.name
127
129
  @log.add("Style", nil, "Only annexes and references can follow clauses")
@@ -145,6 +147,7 @@ module Asciidoctor
145
147
 
146
148
  def style_warning(node, msg, text = nil)
147
149
  return if @novalid
150
+
148
151
  w = msg
149
152
  w += ": #{text}" if text
150
153
  @log.add("Style", node, w)
@@ -165,15 +168,18 @@ module Asciidoctor
165
168
 
166
169
  def tech_report_style(root)
167
170
  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
171
+ root.xpath("//sections/clause[not(@type = 'scope')] | //annex")
172
+ .each do |s|
173
+ r = requirement_check(extract_text(s)) and
174
+ style_warning(s,
175
+ "Technical Report clause may contain requirement", r)
171
176
  end
172
177
  end
173
178
 
174
179
  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
180
+ "//termsource | //formula | //termnote | "\
181
+ "//p[not(ancestor::boilerplate)] | //li[not(p)] | //dt | "\
182
+ "//dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
177
183
 
178
184
  NORM_BIBITEMS =
179
185
  "//references[@normative = 'true']/bibitem".freeze
@@ -198,10 +204,23 @@ module Asciidoctor
198
204
  end
199
205
 
200
206
  def subclause_validate(root)
201
- root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause").each do |c|
207
+ root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause")
208
+ .each do |c|
202
209
  style_warning(c, "Exceeds the maximum clause depth of 7", nil)
203
210
  end
204
211
  end
212
+
213
+ # ISO/IEC DIR 2, 22.3.2
214
+ def onlychild_clause_validate(root)
215
+ root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c|
216
+ next unless c.xpath("../clause").size == 1
217
+
218
+ title = c.at("./title")
219
+ location = c["id"] || "#{c.text[0..60]}..."
220
+ location += ":#{title.text}" if c["id"] && !title.nil?
221
+ @log.add("Style", nil, "#{location}: subclause is only child")
222
+ end
223
+ end
205
224
  end
206
225
  end
207
226
  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