metanorma-ieee 0.0.1 → 0.0.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +1 -1
  3. data/lib/html2doc/ieee/lists.rb +44 -0
  4. data/lib/html2doc/ieee/notes.rb +57 -0
  5. data/lib/html2doc/ieee.rb +4 -86
  6. data/lib/isodoc/ieee/base_convert.rb +56 -0
  7. data/lib/isodoc/ieee/html/header.html +1 -2
  8. data/lib/isodoc/ieee/html/header_amd.html +105 -0
  9. data/lib/isodoc/ieee/html/html_ieee_titlepage.html +14 -12
  10. data/lib/isodoc/ieee/html/htmlstyle.css +2 -1
  11. data/lib/isodoc/ieee/html/htmlstyle.scss +1 -0
  12. data/lib/isodoc/ieee/html/ieee.css +46 -273
  13. data/lib/isodoc/ieee/html/ieee.scss +46 -257
  14. data/lib/isodoc/ieee/html/word_ieee_intro.html +1 -1
  15. data/lib/isodoc/ieee/html/word_ieee_titlepage.html +12 -1
  16. data/lib/isodoc/ieee/html/wordstyle.css +20 -23
  17. data/lib/isodoc/ieee/html/wordstyle.scss +20 -17
  18. data/lib/isodoc/ieee/html_convert.rb +37 -1
  19. data/lib/isodoc/ieee/i18n-en.yaml +5 -0
  20. data/lib/isodoc/ieee/ieee.amendment.xsl +5488 -3540
  21. data/lib/isodoc/ieee/ieee.standard.xsl +5488 -3540
  22. data/lib/isodoc/ieee/metadata.rb +35 -51
  23. data/lib/isodoc/ieee/pdf_convert.rb +2 -2
  24. data/lib/isodoc/ieee/presentation_ref.rb +70 -0
  25. data/lib/isodoc/ieee/presentation_terms.rb +105 -32
  26. data/lib/isodoc/ieee/presentation_xml_convert.rb +136 -0
  27. data/lib/isodoc/ieee/word_authority.rb +73 -3
  28. data/lib/isodoc/ieee/word_cleanup.rb +55 -65
  29. data/lib/isodoc/ieee/word_cleanup_blocks.rb +151 -0
  30. data/lib/isodoc/ieee/word_convert.rb +98 -2
  31. data/lib/isodoc/ieee/xref.rb +31 -0
  32. data/lib/metanorma/ieee/boilerplate.xml +72 -23
  33. data/lib/metanorma/ieee/cleanup.rb +142 -77
  34. data/lib/metanorma/ieee/cleanup_ref.rb +126 -0
  35. data/lib/metanorma/ieee/converter.rb +8 -0
  36. data/lib/metanorma/ieee/front.rb +44 -53
  37. data/lib/metanorma/ieee/ieee.rng +44 -6
  38. data/lib/metanorma/ieee/isodoc.rng +32 -1
  39. data/lib/metanorma/ieee/reqt.rng +1 -1
  40. data/lib/metanorma/ieee/term_lookup_cleanup.rb +11 -0
  41. data/lib/metanorma/ieee/validate.rb +105 -57
  42. data/lib/metanorma/ieee/validate_section.rb +14 -7
  43. data/lib/metanorma/ieee/validate_style.rb +58 -1
  44. data/lib/metanorma/ieee/version.rb +1 -1
  45. data/lib/relaton/render/config.yml +44 -0
  46. data/lib/relaton/render/general.rb +13 -0
  47. data/metanorma-itu.gemspec +1 -1
  48. metadata +13 -4
@@ -4,6 +4,9 @@ module Metanorma
4
4
  def metadata_committee(node, xml)
5
5
  return unless node.attr("committee") || node.attr("society")
6
6
 
7
+ node.attr("balloting-group") && !node.attr("balloting-group-type") and
8
+ node.set_attr("balloting-group-type", "individual")
9
+
7
10
  xml.editorialgroup do |a|
8
11
  committee_component("society", node, a)
9
12
  committee_component("balloting-group", node, a)
@@ -29,59 +32,6 @@ module Metanorma
29
32
  xml.docnumber node.attr("docnumber")
30
33
  end
31
34
 
32
- def metadata_author(node, xml)
33
- super
34
- wg_members(node, xml)
35
- bg_members(node, xml)
36
- std_board_members(node, xml)
37
- end
38
-
39
- def metadata_editor(name, role, xml)
40
- xml.contributor do |c|
41
- c.role role, **{ type: "editor" }
42
- c.person do |p|
43
- p.name do |n|
44
- n.completename name
45
- end
46
- end
47
- end
48
- end
49
-
50
- def metadata_multi_editors(names, role, xml)
51
- csv_split(names).each do |n|
52
- metadata_editor(n, role, xml)
53
- end
54
- end
55
-
56
- def wg_members(node, xml)
57
- a = node.attr("wg_chair") and
58
- metadata_editor(a, "Working Group Chair", xml)
59
- a = node.attr("wg_vicechair") and
60
- metadata_editor(a, "Working Group Vice-Chair", xml)
61
- a = node.attr("wg_secretary") and
62
- metadata_editor(a, "Working Group Secretary", xml)
63
- a = node.attr("wg_members") and
64
- metadata_multi_editors(a, "Working Group Member", xml)
65
- end
66
-
67
- def bg_members(node, xml)
68
- a = node.attr("balloting_group_members") and
69
- metadata_multi_editors(a, "Balloting Group Member", xml)
70
- end
71
-
72
- def std_board_members(node, xml)
73
- a = node.attr("std_board_chair") and
74
- metadata_editor(a, "Standards Board Chair", xml)
75
- a = node.attr("std_board_vicechair") and
76
- metadata_editor(a, "Standards Board Vice-Chair", xml)
77
- a = node.attr("std_board_pastchair") and
78
- metadata_editor(a, "Standards Board Past Chair", xml)
79
- a = node.attr("std_board_secretary") and
80
- metadata_editor(a, "Standards Board Secretary", xml)
81
- a = node.attr("balloting_group_members") and
82
- metadata_multi_editors(a, "Standards Board Member", xml)
83
- end
84
-
85
35
  def metadata_publisher(node, xml)
86
36
  publishers = node.attr("publisher") || "IEEE"
87
37
  csv_split(publishers).each do |p|
@@ -112,9 +62,50 @@ module Metanorma
112
62
  end
113
63
  end
114
64
 
65
+ def metadata_status(node, xml)
66
+ status = node.attr("status") || node.attr("docstage") ||
67
+ (node.attr("draft") ? "developing" : "active")
68
+ xml.status do |s|
69
+ s.stage status
70
+ end
71
+ end
72
+
73
+ def datetypes
74
+ super + %w{feedback-ended}
75
+ end
76
+
77
+ def metadata_subdoctype(node, xml)
78
+ xml.subdoctype (node.attr("docsubtype") || "document")
79
+ s = node.attr("trial-use") and xml.trial_use s
80
+ end
81
+
115
82
  def org_abbrev
116
83
  { "Institute of Electrical and Electronic Engineers" => "IEEE" }
117
84
  end
85
+
86
+ def relaton_relations
87
+ super + %w(merges updates)
88
+ end
89
+
90
+ def metadata_ext(node, xml)
91
+ super
92
+ structured_id(node, xml)
93
+ end
94
+
95
+ def structured_id(node, xml)
96
+ return unless node.attr("docnumber")
97
+
98
+ xml.structuredidentifier do |i|
99
+ i.docnumber node.attr("docnumber")
100
+ i.agency "IEEE"
101
+ i.class_ doctype(node)
102
+ a = node.attr("edition") and i.edition a
103
+ a = node.attr("draft") and i.version a
104
+ a = node.attr("amendment-number") and i.amendment a
105
+ a = node.attr("corrigendum-number") and i.corrigendum a
106
+ a = node.attr("copyright-year") and i.year a
107
+ end
108
+ end
118
109
  end
119
110
  end
120
111
  end
@@ -1,5 +1,5 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <grammar ns="https://www.metanorma.org/ns/ieee" xmlns="http://relaxng.org/ns/structure/1.0">
2
+ <grammar ns="https://www.metanorma.org/ns/ieee" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
3
3
  <!--
4
4
  Currently we inherit from a namespaced grammar, isostandard. Until we inherit from isodoc,
5
5
  we cannot have a new default namespace: we will end up with a grammar with two different
@@ -16,18 +16,37 @@
16
16
  <value>standard</value>
17
17
  </choice>
18
18
  </define>
19
+ <define name="stage">
20
+ <element name="stage">
21
+ <choice>
22
+ <value>developing</value>
23
+ <value>active</value>
24
+ <value>inactive</value>
25
+ </choice>
26
+ </element>
27
+ </define>
19
28
  <define name="editorialgroup">
20
29
  <element name="editorialgroup">
21
- <ref name="society"/>
22
- <ref name="balloting-group"/>
23
- <ref name="working-group"/>
30
+ <optional>
31
+ <ref name="society"/>
32
+ </optional>
33
+ <optional>
34
+ <ref name="balloting-group"/>
35
+ </optional>
36
+ <optional>
37
+ <ref name="working-group"/>
38
+ </optional>
24
39
  <oneOrMore>
25
40
  <ref name="committee"/>
26
41
  </oneOrMore>
27
42
  </element>
28
43
  </define>
29
44
  <define name="DocumentSubtype">
30
- <value>trial-use</value>
45
+ <choice>
46
+ <value>amendment</value>
47
+ <value>corrigendum</value>
48
+ <value>erratum</value>
49
+ </choice>
31
50
  </define>
32
51
  <define name="BibDataExtensionType">
33
52
  <optional>
@@ -36,14 +55,33 @@
36
55
  <optional>
37
56
  <ref name="docsubtype"/>
38
57
  </optional>
39
- <ref name="editorialgroup"/>
58
+ <optional>
59
+ <ref name="trialuse"/>
60
+ </optional>
61
+ <optional>
62
+ <ref name="editorialgroup"/>
63
+ </optional>
40
64
  <zeroOrMore>
41
65
  <ref name="ics"/>
42
66
  </zeroOrMore>
43
67
  </define>
44
68
  </include>
69
+ <define name="BibliographicDateType" combine="choice">
70
+ <value>feecback-ended</value>
71
+ </define>
72
+ <define name="trialuse">
73
+ <element name="trial-use">
74
+ <data type="boolean"/>
75
+ </element>
76
+ </define>
45
77
  <define name="balloting-group">
46
78
  <element name="balloting-group">
79
+ <attribute name="type">
80
+ <choice>
81
+ <value>individual</value>
82
+ <value>entity</value>
83
+ </choice>
84
+ </attribute>
47
85
  <text/>
48
86
  </element>
49
87
  </define>
@@ -69,6 +69,17 @@
69
69
  </zeroOrMore>
70
70
  </element>
71
71
  </define>
72
+ <define name="AdmonitionType">
73
+ <choice>
74
+ <value>warning</value>
75
+ <value>note</value>
76
+ <value>tip</value>
77
+ <value>important</value>
78
+ <value>caution</value>
79
+ <value>statement</value>
80
+ <value>editorial</value>
81
+ </choice>
82
+ </define>
72
83
  <define name="index">
73
84
  <element name="index">
74
85
  <optional>
@@ -116,6 +127,11 @@
116
127
  <data type="boolean"/>
117
128
  </attribute>
118
129
  </optional>
130
+ <optional>
131
+ <attribute name="suppress_identifier">
132
+ <data type="boolean"/>
133
+ </attribute>
134
+ </optional>
119
135
  <ref name="BibliographicItem"/>
120
136
  </element>
121
137
  </define>
@@ -1269,7 +1285,12 @@
1269
1285
  </define>
1270
1286
  <define name="span">
1271
1287
  <element name="span">
1272
- <attribute name="class"/>
1288
+ <optional>
1289
+ <attribute name="class"/>
1290
+ </optional>
1291
+ <optional>
1292
+ <attribute name="style"/>
1293
+ </optional>
1273
1294
  <oneOrMore>
1274
1295
  <ref name="TextElement"/>
1275
1296
  </oneOrMore>
@@ -2488,6 +2509,16 @@
2488
2509
  <text/>
2489
2510
  </element>
2490
2511
  </optional>
2512
+ <optional>
2513
+ <element name="amendment">
2514
+ <text/>
2515
+ </element>
2516
+ </optional>
2517
+ <optional>
2518
+ <element name="corrigendum">
2519
+ <text/>
2520
+ </element>
2521
+ </optional>
2491
2522
  <optional>
2492
2523
  <element name="language">
2493
2524
  <text/>
@@ -108,7 +108,7 @@
108
108
  </element>
109
109
  </define>
110
110
  <define name="label">
111
- <element name="label">
111
+ <element name="identifier">
112
112
  <oneOrMore>
113
113
  <ref name="TextElement"/>
114
114
  </oneOrMore>
@@ -0,0 +1,11 @@
1
+ module Metanorma
2
+ module IEEE
3
+ class TermLookupCleanup < Metanorma::Standoc::TermLookupCleanup
4
+ def remove_missing_ref_term(node, _target)
5
+ node.at("../xrefrender")&.remove
6
+ node.replace("<preferred><expression><name>#{node.children.to_xml}"\
7
+ "</name></expression></preferred>")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -14,76 +14,49 @@ module Metanorma
14
14
  super
15
15
  bibdata_validate(doc.root)
16
16
  title_validate(doc.root)
17
- locality_erefs_validate(doc.root)
17
+ locality_validate(doc.root)
18
18
  bibitem_validate(doc.root)
19
- listcount_validate(doc)
19
+ list_validate(doc)
20
20
  table_style(doc)
21
21
  figure_validate(doc)
22
+ amend_validate(doc)
22
23
  end
23
24
 
24
25
  def bibdata_validate(doc)
25
26
  doctype_validate(doc)
26
- # stage_validate(doc)
27
- # substage_validate(doc)
27
+ stage_validate(doc)
28
28
  end
29
29
 
30
30
  def doctype_validate(xmldoc)
31
31
  doctype = xmldoc&.at("//bibdata/ext/doctype")&.text
32
- %w(standard recommended-practice guide
33
- amendment technical-corrigendum).include? doctype or
32
+ %w(standard recommended-practice guide).include? doctype or
34
33
  @log.add("Document Attributes", nil,
35
34
  "#{doctype} is not a recognised document type")
35
+ docsubtype = xmldoc&.at("//bibdata/ext/subdoctype")&.text or return
36
+ %w(amendment corrigendum erratum document).include? docsubtype or
37
+ @log.add("Document Attributes", nil,
38
+ "#{docsubtype} is not a recognised document subtype")
36
39
  end
37
40
 
38
- def title_validate(xml)
39
- title_validate_type(xml)
40
- title_validate_capitalisation(xml)
41
- end
42
-
43
- # Style Manual 11.3
44
- def title_validate_type(xml)
45
- title = xml.at("//bibdata/title") or return
46
- draft = xml.at("//bibdata//draft")
47
- type = xml.at("//bibdata/ext/doctype")
48
- subtype = xml.at("//bibdata/ext/subdoctype")
49
- target = draft ? "Draft " : ""
50
- target += subtype ? "#{strict_capitalize_phrase(subtype.text)} " : ""
51
- target += type ? "#{strict_capitalize_phrase(type.text)} " : ""
52
- /^#{target}/.match?(title.text) or
53
- @log.add("Style", title,
54
- "Expected title to start as: #{target}")
55
- end
56
-
57
- def strict_capitalize_phrase(str)
58
- ret = str.split(/[ -]/).map do |w|
59
- letters = w.chars
60
- letters.first.upcase! unless /^[ -]/.match?(w)
61
- letters.join
62
- end.join(" ")
63
- ret = "Trial-Use" if ret == "Trial Use"
64
- ret
65
- end
66
-
67
- # Style Manual 11.3
68
- def title_validate_capitalisation(xml)
69
- title = xml.at("//bibdata/title") or return
70
- found = false
71
- title.text.split(/[ -]/).each do |w|
72
- /^[[:upper:]]/.match?(w) or preposition?(w) or
73
- found = true
74
- end
75
- found and @log.add("Style", title,
76
- "Title contains uncapitalised word other than preposition")
41
+ def stage_validate(xmldoc)
42
+ stage = xmldoc&.at("//bibdata/status/stage")&.text
43
+ %w(active inactive developing).include? stage or
44
+ @log.add("Document Attributes", nil,
45
+ "#{stage} is not a recognised stage")
77
46
  end
78
47
 
79
- def preposition?(word)
80
- %w(aboard about above across after against along amid among anti around
81
- as at before behind below beneath beside besides between beyond but
82
- by concerning considering despite down during except excepting
83
- excluding following for from in inside into like minus near of off
84
- on onto opposite outside over past per plus regarding round save
85
- since than through to toward towards under underneath unlike until
86
- up upon versus via with within without a an the).include?(word)
48
+ def locality_validate(root)
49
+ locality_range_validate(root)
50
+ locality_erefs_validate(root)
51
+ end
52
+
53
+ # Style manual 17.2 &c
54
+ def locality_range_validate(root)
55
+ root.xpath("//eref | xref").each do |e|
56
+ e.at(".//localityStack[@connective = 'from'] | .//referenceTo") and
57
+ @log.add("Style", e, "Cross-reference contains range, "\
58
+ "should be separate cross-references")
59
+ end
87
60
  end
88
61
 
89
62
  # Style manual 12.3.2
@@ -91,7 +64,7 @@ module Metanorma
91
64
  root.xpath("//eref[descendant::locality]").each do |t|
92
65
  if !/[:-](\d+{4})$/.match?(t["citeas"])
93
66
  @log.add("Style", t,
94
- "undated reference #{t['citeas']} should not contain "\
67
+ "Undated reference #{t['citeas']} should not contain "\
95
68
  "specific elements")
96
69
  end
97
70
  end
@@ -110,9 +83,30 @@ module Metanorma
110
83
  end
111
84
  end
112
85
 
86
+ def list_validate(doc)
87
+ listcount_validate(doc)
88
+ listdepth_validate(doc)
89
+ end
90
+
91
+ # Template provision of styles
92
+ def listdepth_validate(doc)
93
+ doc.xpath("//ul[.//ul//ul]").each do |u|
94
+ next unless u.ancestors("ul").empty?
95
+
96
+ @log.add("Style", u,
97
+ "Use ordered lists for lists more than two levels deep.")
98
+ end
99
+ doc.xpath("//ol[.//ol//ol//ol//ol//ol]").each do |u|
100
+ next unless u.ancestors("ol").empty?
101
+
102
+ @log.add("Style", u,
103
+ "Ordered lists should not be more than five levels deep.")
104
+ end
105
+ end
106
+
113
107
  # Style manual 13.3
114
108
  def listcount_validate(doc)
115
- doc.xpath("//clause | //annex").each do |c|
109
+ doc.xpath("//sections//clause | //annex").each do |c|
116
110
  next if c.xpath(".//ol").empty?
117
111
 
118
112
  ols = c.xpath(".//ol") -
@@ -127,6 +121,7 @@ module Metanorma
127
121
  def figure_validate(xmldoc)
128
122
  xrefs = xrefs(xmldoc)
129
123
  figure_name_validate(xmldoc, xrefs)
124
+ figure_name_style_validate(xmldoc)
130
125
  table_figure_name_validate(xmldoc, xrefs)
131
126
  table_figure_quantity_validate(xmldoc)
132
127
  end
@@ -159,10 +154,18 @@ module Metanorma
159
154
  num = xrefs.anchor(f["id"], :label)
160
155
  File.basename(i["src"], ".*") == "#{pref}_fig#{num}" or
161
156
  @log.add("Style", i,
162
- "image name #{i['src']} is expected to be #{pref}_fig#{num}")
157
+ "Image name #{i['src']} is expected to be #{pref}_fig#{num}")
163
158
  end
164
159
  end
165
160
 
161
+ # Style manual 17.2
162
+ def figure_name_style_validate(docxml)
163
+ docxml.xpath("//figure/name").each do |td|
164
+ style_regex(/^(?<num>\p{Lower}\s*)/, "figure heading should be capitalised",
165
+ td, td.text)
166
+ end
167
+ end
168
+
166
169
  def table_figure_name_validate(xmldoc, xrefs)
167
170
  xmldoc.xpath("//table[.//figure]").each do |t|
168
171
  xmldoc.xpath(".//figure").each do |f|
@@ -172,7 +175,7 @@ module Metanorma
172
175
  num = tablefigurenumber(t, f, xrefs)
173
176
  File.basename(i["src"]) == num or
174
177
  @log.add("Style", i,
175
- "image name #{i['src']} is expected to be #{num}")
178
+ "Image name #{i['src']} is expected to be #{num}")
176
179
  end
177
180
  end
178
181
  end
@@ -193,6 +196,51 @@ module Metanorma
193
196
  "More than one image in the table cell")
194
197
  end
195
198
  end
199
+
200
+ # Style manual 20.2.2
201
+ def amend_validate(xmldoc)
202
+ xmldoc.xpath("//amend").each do |a|
203
+ desc = a.at("./description")
204
+ if desc && !desc.text.strip.empty?
205
+ amend_validate1(a, desc.text.strip,
206
+ a.at("./newcontent//figure | "\
207
+ "./newcontent//formula"))
208
+ else @log.add("Style", a,
209
+ "Editorial instruction is missing from change")
210
+ end
211
+ end
212
+ end
213
+
214
+ def amend_validate1(amend, description, figure_or_formula)
215
+ case amend["change"]
216
+ when "add" then /^Insert /.match?(description) or
217
+ @log.add("Style", amend,
218
+ "'Add' change description should start with _Insert_")
219
+ when "delete" then /^Insert /.match?(description) or
220
+ @log.add("Style", amend,
221
+ "'Delete' change description should start with _Delete_")
222
+ when "modify"
223
+ amend_validate_modify(amend, description, figure_or_formula)
224
+ end
225
+ end
226
+
227
+ AMD_VALID_MOD = [
228
+ "'Modify' change description should start with _Change_ or _Replace_",
229
+ "'Modify' change description for change involving figure or equation "\
230
+ "should start with _Replace_",
231
+ "'Modify' change description for change not involving figure or "\
232
+ "equation should start with _Change_",
233
+ ].freeze
234
+
235
+ def amend_validate_modify(amend, description, figure_or_formula)
236
+ if !/^Change |^Replace/.match?(description)
237
+ @log.add("Style", amend, AMD_VALID_MOD[0])
238
+ elsif /^Change /.match?(description)
239
+ !figure_or_formula or @log.add("Style", amend, AMD_VALID_MOD[1])
240
+ else
241
+ figure_or_formula or @log.add("Style", amend, AMD_VALID_MOD[2])
242
+ end
243
+ end
196
244
  end
197
245
  end
198
246
  end
@@ -58,6 +58,7 @@ module Metanorma
58
58
  names, n = sections_sequence_validate_start(root)
59
59
  names, n = sections_sequence_validate_body(names, n)
60
60
  sections_sequence_validate_end(names, n)
61
+ bibliography_validate(root)
61
62
  end
62
63
 
63
64
  def sections_sequence_validate_start(root)
@@ -86,13 +87,6 @@ module Metanorma
86
87
  elem&.at("./self::references[@normative = 'true']") ||
87
88
  @log.add("Style", nil, "Document must include (references) "\
88
89
  "Normative References")
89
- elem = names&.shift
90
- elem&.at("./self::references[@normative = 'false']") ||
91
- @log.add("Style", elem,
92
- "Final section must be (references) Bibliography")
93
- names.empty? ||
94
- @log.add("Style", elem,
95
- "There are sections after the final Bibliography")
96
90
  end
97
91
 
98
92
  # Style manual 13.1
@@ -114,6 +108,19 @@ module Metanorma
114
108
  @log.add("Style", nil, "#{location}: subclause is only child")
115
109
  end
116
110
  end
111
+
112
+ # Style manual 19.1
113
+ def bibliography_validate(root)
114
+ bib = root.at("//references[@normative = 'false']") or return
115
+ if annex = bib.at(".//ancestor::annex")
116
+ prec = annex.xpath("./preceding-sibling::annex")
117
+ foll = annex.xpath("./following-sibling::annex")
118
+ valid = prec.empty? || foll.empty?
119
+ else valid = false
120
+ end
121
+ valid or @log.add("Style", bib, "Bibliography must be either the first "\
122
+ "or the last document annex")
123
+ end
117
124
  end
118
125
  end
119
126
  end
@@ -68,13 +68,17 @@ module Metanorma
68
68
  "unit is needed on both value and tolerance", node, text)
69
69
  end
70
70
 
71
- # Style manual 16.3.2
71
+ # Style manual 16.2, 16.3.2
72
72
  def table_style(docxml)
73
73
  docxml.xpath("//td").each do |td|
74
74
  style_regex(/^(?<num>[\u2212-]?[0-9]{5,}[.0-9]*|-?[0-9]+\.[0-9]{5,})$/,
75
75
  "number in table not broken up in threes", td, td.text)
76
76
  end
77
77
  docxml.xpath("//table").each { |t| table_style_columns(t) }
78
+ docxml.xpath("//table/name | //th").each do |td|
79
+ style_regex(/^(?<num>\p{Lower}\S*)/, "table heading should be capitalised",
80
+ td, td.text)
81
+ end
78
82
  end
79
83
 
80
84
  # deliberately doing naive, ignoring rowspan
@@ -102,6 +106,59 @@ module Metanorma
102
106
  end
103
107
  end
104
108
  ret.map { |x| x.is_a?(Array) ? x : [] }
109
+ end
110
+
111
+ def title_validate(xml)
112
+ title_validate_type(xml)
113
+ title_validate_capitalisation(xml)
114
+ end
115
+
116
+ # Style Manual 11.3
117
+ def title_validate_type(xml)
118
+ title = xml.at("//bibdata/title") or return
119
+ draft = xml.at("//bibdata//draft")
120
+ type = xml.at("//bibdata/ext/doctype")
121
+ subtype = xml.at("//bibdata/ext/subdoctype")
122
+ subtype = "" if subtype == "document"
123
+ trial = xml.at("//bibdata/ext/trial-use[text() = 'true']")
124
+ target = draft ? "Draft " : ""
125
+ target += trial ? "Trial-Use " : ""
126
+ target += type ? "#{strict_capitalize_phrase(type.text)} " : ""
127
+ /^#{target}/.match?(title.text) or
128
+ @log.add("Style", title,
129
+ "Expected title to start as: #{target}")
130
+ end
131
+
132
+ def strict_capitalize_phrase(str)
133
+ ret = str.split(/[ -]/).map do |w|
134
+ letters = w.chars
135
+ letters.first.upcase! unless /^[ -]/.match?(w)
136
+ letters.join
137
+ end.join(" ")
138
+ ret = "Trial-Use" if ret == "Trial Use"
139
+ ret
140
+ end
141
+
142
+ # Style Manual 11.3
143
+ def title_validate_capitalisation(xml)
144
+ title = xml.at("//bibdata/title") or return
145
+ found = false
146
+ title.text.split(/[ -]/).each do |w|
147
+ /^[[:upper:]]/.match?(w) or preposition?(w) or
148
+ found = true
149
+ end
150
+ found and @log.add("Style", title,
151
+ "Title contains uncapitalised word other than preposition")
152
+ end
153
+
154
+ def preposition?(word)
155
+ %w(aboard about above across after against along amid among anti around
156
+ as at before behind below beneath beside besides between beyond but
157
+ by concerning considering despite down during except excepting
158
+ excluding following for from in inside into like minus near of off
159
+ on onto opposite outside over past per plus regarding round save
160
+ since than through to toward towards under underneath unlike until
161
+ up upon versus via with within without a an the).include?(word)
105
162
  end
106
163
  end
107
164
  end
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  module IEEE
3
- VERSION = "0.0.1".freeze
3
+ VERSION = "0.0.4".freeze
4
4
  end
5
5
  end