metanorma-ieee 0.0.1 → 0.0.4

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