metanorma-standoc 1.11.3 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +3 -31
  3. data/.gitignore +23 -0
  4. data/Gemfile +0 -1
  5. data/lib/asciidoctor/standoc/base.rb +2 -145
  6. data/lib/asciidoctor/standoc/blocks.rb +2 -238
  7. data/lib/asciidoctor/standoc/blocks_notes.rb +2 -100
  8. data/lib/asciidoctor/standoc/cleanup.rb +2 -208
  9. data/lib/asciidoctor/standoc/cleanup_amend.rb +2 -53
  10. data/lib/asciidoctor/standoc/cleanup_block.rb +2 -172
  11. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +2 -212
  12. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +2 -108
  13. data/lib/asciidoctor/standoc/cleanup_image.rb +2 -69
  14. data/lib/asciidoctor/standoc/cleanup_inline.rb +2 -189
  15. data/lib/asciidoctor/standoc/cleanup_maths.rb +2 -221
  16. data/lib/asciidoctor/standoc/cleanup_ref.rb +2 -169
  17. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +2 -103
  18. data/lib/asciidoctor/standoc/cleanup_reqt.rb +2 -110
  19. data/lib/asciidoctor/standoc/cleanup_section.rb +2 -184
  20. data/lib/asciidoctor/standoc/cleanup_section_names.rb +2 -91
  21. data/lib/asciidoctor/standoc/cleanup_symbols.rb +2 -47
  22. data/lib/asciidoctor/standoc/cleanup_table.rb +2 -67
  23. data/lib/asciidoctor/standoc/cleanup_terms.rb +2 -139
  24. data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +2 -192
  25. data/lib/asciidoctor/standoc/cleanup_text.rb +2 -95
  26. data/lib/asciidoctor/standoc/cleanup_toc.rb +3 -0
  27. data/lib/asciidoctor/standoc/cleanup_xref.rb +2 -106
  28. data/lib/asciidoctor/standoc/converter.rb +2 -123
  29. data/lib/asciidoctor/standoc/datamodel/attributes_table_preprocessor.rb +2 -56
  30. data/lib/asciidoctor/standoc/datamodel/diagram_preprocessor.rb +2 -102
  31. data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +3 -404
  32. data/lib/asciidoctor/standoc/deprecated.rb +5 -0
  33. data/lib/asciidoctor/standoc/front.rb +2 -219
  34. data/lib/asciidoctor/standoc/front_contributor.rb +2 -191
  35. data/lib/asciidoctor/standoc/inline.rb +2 -231
  36. data/lib/asciidoctor/standoc/lists.rb +2 -119
  37. data/lib/asciidoctor/standoc/macros.rb +2 -203
  38. data/lib/asciidoctor/standoc/macros_form.rb +2 -62
  39. data/lib/asciidoctor/standoc/macros_note.rb +2 -44
  40. data/lib/asciidoctor/standoc/macros_plantuml.rb +2 -112
  41. data/lib/asciidoctor/standoc/macros_terms.rb +2 -180
  42. data/lib/asciidoctor/standoc/ref.rb +2 -251
  43. data/lib/asciidoctor/standoc/ref_sect.rb +2 -153
  44. data/lib/asciidoctor/standoc/ref_utility.rb +2 -0
  45. data/lib/asciidoctor/standoc/render.rb +2 -116
  46. data/lib/asciidoctor/standoc/reqt.rb +2 -89
  47. data/lib/asciidoctor/standoc/section.rb +2 -194
  48. data/lib/asciidoctor/standoc/table.rb +2 -84
  49. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +2 -178
  50. data/lib/asciidoctor/standoc/terms.rb +2 -153
  51. data/lib/asciidoctor/standoc/utils.rb +2 -100
  52. data/lib/asciidoctor/standoc/validate.rb +2 -157
  53. data/lib/asciidoctor/standoc/validate_section.rb +2 -54
  54. data/lib/isodoc/html/htmlstyle.css +44 -29
  55. data/lib/isodoc/html/htmlstyle.scss +17 -12
  56. data/lib/metanorma/standoc/base.rb +163 -0
  57. data/lib/{asciidoctor → metanorma}/standoc/basicdoc.rng +0 -0
  58. data/lib/{asciidoctor → metanorma}/standoc/biblio.rng +2 -2
  59. data/lib/metanorma/standoc/blocks.rb +239 -0
  60. data/lib/metanorma/standoc/blocks_notes.rb +101 -0
  61. data/lib/metanorma/standoc/cleanup.rb +157 -0
  62. data/lib/metanorma/standoc/cleanup_amend.rb +54 -0
  63. data/lib/metanorma/standoc/cleanup_block.rb +173 -0
  64. data/lib/metanorma/standoc/cleanup_boilerplate.rb +213 -0
  65. data/lib/metanorma/standoc/cleanup_footnotes.rb +109 -0
  66. data/lib/metanorma/standoc/cleanup_image.rb +70 -0
  67. data/lib/metanorma/standoc/cleanup_inline.rb +190 -0
  68. data/lib/metanorma/standoc/cleanup_maths.rb +222 -0
  69. data/lib/metanorma/standoc/cleanup_ref.rb +170 -0
  70. data/lib/metanorma/standoc/cleanup_ref_dl.rb +104 -0
  71. data/lib/metanorma/standoc/cleanup_reqt.rb +111 -0
  72. data/lib/metanorma/standoc/cleanup_section.rb +212 -0
  73. data/lib/metanorma/standoc/cleanup_section_names.rb +92 -0
  74. data/lib/metanorma/standoc/cleanup_symbols.rb +48 -0
  75. data/lib/metanorma/standoc/cleanup_table.rb +68 -0
  76. data/lib/metanorma/standoc/cleanup_terms.rb +140 -0
  77. data/lib/metanorma/standoc/cleanup_terms_designations.rb +199 -0
  78. data/lib/metanorma/standoc/cleanup_text.rb +74 -0
  79. data/lib/metanorma/standoc/cleanup_toc.rb +98 -0
  80. data/lib/metanorma/standoc/cleanup_xref.rb +107 -0
  81. data/lib/metanorma/standoc/converter.rb +126 -0
  82. data/lib/metanorma/standoc/datamodel/attributes_table_preprocessor.rb +57 -0
  83. data/lib/metanorma/standoc/datamodel/diagram_preprocessor.rb +103 -0
  84. data/lib/metanorma/standoc/datamodel/plantuml_renderer.rb +409 -0
  85. data/lib/metanorma/standoc/front.rb +224 -0
  86. data/lib/metanorma/standoc/front_contributor.rb +192 -0
  87. data/lib/metanorma/standoc/inline.rb +232 -0
  88. data/lib/{asciidoctor → metanorma}/standoc/isodoc.rng +104 -3
  89. data/lib/metanorma/standoc/lists.rb +120 -0
  90. data/lib/metanorma/standoc/macros.rb +205 -0
  91. data/lib/metanorma/standoc/macros_embed.rb +72 -0
  92. data/lib/metanorma/standoc/macros_form.rb +63 -0
  93. data/lib/metanorma/standoc/macros_note.rb +45 -0
  94. data/lib/metanorma/standoc/macros_plantuml.rb +113 -0
  95. data/lib/metanorma/standoc/macros_terms.rb +194 -0
  96. data/lib/metanorma/standoc/ref.rb +243 -0
  97. data/lib/metanorma/standoc/ref_sect.rb +153 -0
  98. data/lib/{asciidoctor/standoc/ref_date_id.rb → metanorma/standoc/ref_utility.rb} +43 -5
  99. data/lib/metanorma/standoc/render.rb +115 -0
  100. data/lib/metanorma/standoc/reqt.rb +90 -0
  101. data/lib/{asciidoctor → metanorma}/standoc/reqt.rng +0 -0
  102. data/lib/metanorma/standoc/section.rb +209 -0
  103. data/lib/metanorma/standoc/table.rb +85 -0
  104. data/lib/metanorma/standoc/term_lookup_cleanup.rb +179 -0
  105. data/lib/metanorma/standoc/terms.rb +160 -0
  106. data/lib/metanorma/standoc/utils.rb +101 -0
  107. data/lib/metanorma/standoc/validate.rb +158 -0
  108. data/lib/metanorma/standoc/validate_section.rb +55 -0
  109. data/lib/metanorma/standoc/version.rb +1 -1
  110. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/model_representation.adoc.erb +0 -0
  111. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/plantuml_representation.adoc.erb +0 -0
  112. data/lib/metanorma-standoc.rb +1 -1
  113. data/metanorma-standoc.gemspec +1 -1
  114. data/spec/assets/a1.adoc +8 -0
  115. data/spec/assets/a2.adoc +8 -0
  116. data/spec/assets/a3.adoc +9 -0
  117. data/spec/assets/a4.adoc +4 -0
  118. data/spec/{asciidoctor → metanorma}/base_spec.rb +499 -407
  119. data/spec/{asciidoctor → metanorma}/blank_spec.rb +1 -1
  120. data/spec/{asciidoctor → metanorma}/blocks_spec.rb +1 -1
  121. data/spec/{asciidoctor → metanorma}/cleanup_blocks_spec.rb +1 -1
  122. data/spec/{asciidoctor → metanorma}/cleanup_sections_spec.rb +1 -1
  123. data/spec/{asciidoctor → metanorma}/cleanup_spec.rb +5 -5
  124. data/spec/{asciidoctor → metanorma}/cleanup_terms_spec.rb +227 -119
  125. data/spec/{asciidoctor → metanorma}/datamodel/attributes_table_preprocessor_spec.rb +1 -1
  126. data/spec/{asciidoctor → metanorma}/datamodel/diagram_preprocessor_spec.rb +1 -1
  127. data/spec/{asciidoctor → metanorma}/inline_spec.rb +170 -1
  128. data/spec/{asciidoctor → metanorma}/isobib_cache_spec.rb +1 -1
  129. data/spec/{asciidoctor → metanorma}/lists_spec.rb +1 -1
  130. data/spec/{asciidoctor → metanorma}/macros_json2text_spec.rb +0 -0
  131. data/spec/{asciidoctor → metanorma}/macros_plantuml_spec.rb +3 -3
  132. data/spec/{asciidoctor → metanorma}/macros_spec.rb +97 -6
  133. data/spec/{asciidoctor → metanorma}/macros_yaml2text_spec.rb +0 -0
  134. data/spec/metanorma/refs_dl_spec.rb +863 -0
  135. data/spec/{asciidoctor → metanorma}/refs_spec.rb +522 -15
  136. data/spec/{asciidoctor → metanorma}/section_spec.rb +59 -1
  137. data/spec/{asciidoctor → metanorma}/table_spec.rb +1 -1
  138. data/spec/{asciidoctor → metanorma}/validate_spec.rb +2 -2
  139. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +46 -46
  140. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +12 -12
  141. data/spec/vcr_cassettes/hide_refs.yml +599 -0
  142. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  143. data/spec/vcr_cassettes/isobib_get_123_1.yml +24 -24
  144. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +35 -35
  145. data/spec/vcr_cassettes/isobib_get_123_2001.yml +13 -13
  146. data/spec/vcr_cassettes/isobib_get_124.yml +10 -10
  147. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +18 -18
  148. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
  149. metadata +88 -32
  150. data/spec/asciidoctor/refs_dl_spec.rb +0 -864
@@ -0,0 +1,160 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Section
4
+ def in_terms?
5
+ @term_def
6
+ end
7
+
8
+ def nonterm_symbols_parse(attrs, xml, node)
9
+ defs = @definitions
10
+ @definitions = false
11
+ clause_parse(attrs, xml, node)
12
+ @definitions = defs
13
+ end
14
+
15
+ def symbols_attrs(node, attr)
16
+ case sectiontype1(node)
17
+ when "symbols" then attr.merge(type: "symbols")
18
+ when "abbreviated terms", "abbreviations"
19
+ attr.merge(type: "abbreviated_terms")
20
+ else
21
+ attr
22
+ end
23
+ end
24
+
25
+ def symbols_parse(attr, xml, node)
26
+ node.role == "nonterm" and return nonterm_symbols_parse(attr, xml, node)
27
+ xml.definitions **attr_code(attr) do |xml_section|
28
+ xml_section.title { |t| t << node.title }
29
+ defs = @definitions
30
+ termdefs = @term_def
31
+ @definitions = true
32
+ @term_def = false
33
+ xml_section << node.content
34
+ @definitions = defs
35
+ @term_def = termdefs
36
+ end
37
+ end
38
+
39
+ def nonterm_term_def_subclause_parse(attrs, xml, node)
40
+ defs = @term_def
41
+ @term_def = false
42
+ clause_parse(attrs, xml, node)
43
+ @term_def = defs
44
+ end
45
+
46
+ def terms_boilerplate_parse(attrs, xml, node)
47
+ defs = @term_def
48
+ @term_def = false
49
+ clause_parse(attrs.merge(type: "boilerplate"), xml, node)
50
+ @term_def = defs
51
+ end
52
+
53
+ # subclause contains subclauses
54
+ def term_def_subclause_parse(attrs, xml, node)
55
+ node.role == "nonterm" and
56
+ return nonterm_term_def_subclause_parse(attrs, xml, node)
57
+ node.role == "boilerplate" and
58
+ return terms_boilerplate_parse(attrs, xml, node)
59
+ st = sectiontype(node, false)
60
+ return symbols_parse(attrs, xml, node) if @definitions
61
+
62
+ sub = node.find_by(context: :section) { |s| s.level == node.level + 1 }
63
+ sub.empty? || (return term_def_parse(attrs, xml, node, false))
64
+ st == "symbols and abbreviated terms" and
65
+ return symbols_parse(attrs, xml, node)
66
+ st == "terms and definitions" and return clause_parse(attrs, xml, node)
67
+ term_def_subclause_parse1(attrs, xml, node)
68
+ end
69
+
70
+ def term_def_subclause_parse1(attrs, xml, node)
71
+ xml.term **attr_code(attrs) do |xml_section|
72
+ term_designation(xml_section, node, "preferred", node.title)
73
+ xml_section << node.content
74
+ end
75
+ end
76
+
77
+ def term_def_parse(attrs, xml, node, _toplevel)
78
+ xml.terms **attr_code(attrs) do |section|
79
+ section.title { |t| t << node.title }
80
+ (s = node.attr("source")) && s.split(",").each do |s1|
81
+ section.termdocsource(nil, **attr_code(bibitemid: s1))
82
+ end
83
+ section << node.content
84
+ end
85
+ end
86
+
87
+ def term_designation(xml, _node, tag, text)
88
+ xml.send tag do |p|
89
+ p.expression do |e|
90
+ e.name { |name| name << text }
91
+ end
92
+ end
93
+ end
94
+
95
+ def term_source_attrs(_node, seen_xref)
96
+ { case: seen_xref.children[0]["case"],
97
+ droploc: seen_xref.children[0]["droploc"],
98
+ bibitemid: seen_xref.children[0]["target"],
99
+ format: seen_xref.children[0]["format"], type: "inline" }
100
+ end
101
+
102
+ def add_term_source(node, xml_t, seen_xref, match)
103
+ if seen_xref.children[0].name == "concept"
104
+ xml_t.origin { |o| o << seen_xref.children[0].to_xml }
105
+ else
106
+ attrs = term_source_attrs(node, seen_xref)
107
+ attrs.delete(:text)
108
+ xml_t.origin **attr_code(attrs) do |o|
109
+ o << seen_xref.children[0].children.to_xml
110
+ end
111
+ end
112
+ add_term_source_mod(xml_t, match)
113
+ end
114
+
115
+ def add_term_source_mod(xml_t, match)
116
+ match[:text] && xml_t.modification do |mod|
117
+ mod.p { |p| p << match[:text].sub(/^\s+/, "") }
118
+ end
119
+ end
120
+
121
+ TERM_REFERENCE_RE_STR = <<~REGEXP.freeze
122
+ ^(?<xref><(xref|concept)[^>]+>(.*?</(xref|concept)>)?)
123
+ (,\s(?<text>.*))?
124
+ $
125
+ REGEXP
126
+ TERM_REFERENCE_RE =
127
+ Regexp.new(TERM_REFERENCE_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
128
+ Regexp::IGNORECASE | Regexp::MULTILINE)
129
+
130
+ def extract_termsource_refs(text, node)
131
+ matched = TERM_REFERENCE_RE.match text
132
+ matched.nil? and @log.add("AsciiDoc Input", node,
133
+ "term reference not in expected format:"\
134
+ "#{text}")
135
+ matched
136
+ end
137
+
138
+ def termsource(node)
139
+ matched = extract_termsource_refs(node.content, node) || return
140
+ noko do |xml|
141
+ status = node.attr("status") ||
142
+ (matched[:text] ? "modified" : "identical")
143
+ attrs = { status: status, type: node.attr("type") || "authoritative" }
144
+ xml.termsource **attrs do |xml_t|
145
+ seen_xref = Nokogiri::XML.fragment(matched[:xref])
146
+ add_term_source(node, xml_t, seen_xref, matched)
147
+ end
148
+ end.join("\n")
149
+ end
150
+
151
+ def termdefinition(node)
152
+ noko do |xml|
153
+ xml.definition do |d|
154
+ d << node.content
155
+ end
156
+ end.join("\n")
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,101 @@
1
+ require "date"
2
+ require "nokogiri"
3
+ require "htmlentities"
4
+ require "json"
5
+ require "pathname"
6
+ require "uuidtools"
7
+
8
+ module Metanorma
9
+ module Standoc
10
+ module Utils
11
+ def convert(node, transform = nil, opts = {})
12
+ transform ||= node.node_name
13
+ opts.empty? ? (send transform, node) : (send transform, node, opts)
14
+ end
15
+
16
+ def document_ns_attributes(_doc)
17
+ nil
18
+ end
19
+
20
+ NOKOHEAD = <<~HERE.freeze
21
+ <!DOCTYPE html SYSTEM
22
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
23
+ <html xmlns="http://www.w3.org/1999/xhtml">
24
+ <head> <title></title> <meta charset="UTF-8" /> </head>
25
+ <body> </body> </html>
26
+ HERE
27
+
28
+ # block for processing XML document fragments as XHTML,
29
+ # to allow for HTMLentities
30
+ # Unescape special chars used in Asciidoctor substitution processing
31
+ def noko(&block)
32
+ doc = ::Nokogiri::XML.parse(NOKOHEAD)
33
+ fragment = doc.fragment("")
34
+ ::Nokogiri::XML::Builder.with fragment, &block
35
+ fragment.to_xml(encoding: "US-ASCII", indent: 0).lines.map do |l|
36
+ l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("&#150;", "\u0096")
37
+ .gsub("&#151;", "\u0097").gsub("&#x96;", "\u0096")
38
+ .gsub("&#x97;", "\u0097")
39
+ end
40
+ end
41
+
42
+ def attr_code(attributes)
43
+ attributes.compact.transform_values do |v|
44
+ v.is_a?(String) ? HTMLEntities.new.decode(v) : v
45
+ end
46
+ end
47
+
48
+ # if the contents of node are blocks, output them to out;
49
+ # else, wrap them in <p>
50
+ def wrap_in_para(node, out)
51
+ if node.blocks? then out << node.content
52
+ else
53
+ out.p { |p| p << node.content }
54
+ end
55
+ end
56
+
57
+ SUBCLAUSE_XPATH = "//clause[not(parent::sections)]"\
58
+ "[not(ancestor::boilerplate)]".freeze
59
+
60
+ def isodoc(lang, script, i18nyaml = nil)
61
+ conv = html_converter(EmptyAttr.new)
62
+ i18n = conv.i18n_init(lang, script, i18nyaml)
63
+ conv.metadata_init(lang, script, i18n)
64
+ conv
65
+ end
66
+
67
+ def dl_to_attrs(elem, dlist, name)
68
+ e = dlist.at("./dt[text()='#{name}']") or return
69
+ val = e.at("./following::dd/p") || e.at("./following::dd") or return
70
+ elem[name] = val.text
71
+ end
72
+
73
+ def dl_to_elems(ins, elem, dlist, name)
74
+ a = elem.at("./#{name}[last()]")
75
+ ins = a if a
76
+ dlist.xpath("./dt[text()='#{name}']").each do |e|
77
+ v = e.at("./following::dd")
78
+ e = v.elements and e.size == 1 && e.first.name == "p" and v = e.first
79
+ v.name = name
80
+ ins.next = v
81
+ ins = ins.next
82
+ end
83
+ ins
84
+ end
85
+
86
+ def term_expr(elem)
87
+ "<expression><name>#{elem}</name></expression>"
88
+ end
89
+
90
+ class EmptyAttr
91
+ def attr(_any_attribute)
92
+ nil
93
+ end
94
+
95
+ def attributes
96
+ {}
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,158 @@
1
+ require "metanorma/standoc/utils"
2
+ require_relative "./validate_section"
3
+ require "nokogiri"
4
+ require "jing"
5
+ require "iev"
6
+
7
+ module Metanorma
8
+ module Standoc
9
+ module Validate
10
+ SOURCELOCALITY = "./origin//locality[@type = 'clause']/"\
11
+ "referenceFrom".freeze
12
+
13
+ def init_iev
14
+ return nil if @no_isobib
15
+ return @iev if @iev
16
+
17
+ @iev = Iev::Db.new(@iev_globalname, @iev_localname) unless @no_isobib
18
+ @iev
19
+ end
20
+
21
+ def iev_validate(xmldoc)
22
+ @iev = init_iev or return
23
+ xmldoc.xpath("//term").each do |t|
24
+ t.xpath(".//termsource").each do |src|
25
+ (/^IEC 60050-/.match(src&.at("./origin/@citeas")&.text) &&
26
+ loc = src.xpath(SOURCELOCALITY)&.text) or next
27
+ iev_validate1(t, loc, xmldoc)
28
+ end
29
+ end
30
+ end
31
+
32
+ def iev_validate1(term, loc, xmldoc)
33
+ iev = @iev.fetch(loc,
34
+ xmldoc&.at("//language")&.text || "en") or return
35
+ pref = term.xpath("./preferred//name").inject([]) do |m, x|
36
+ m << x&.text&.downcase
37
+ end
38
+ pref.include?(iev.downcase) or
39
+ @log.add("Bibliography", term, %(Term "#{pref[0]}" does not match ) +
40
+ %(IEV #{loc} "#{iev}"))
41
+ end
42
+
43
+ def content_validate(doc)
44
+ @fatalerror = []
45
+ xref_validate(doc)
46
+ section_validate(doc)
47
+ norm_ref_validate(doc)
48
+ repeat_id_validate(doc.root)
49
+ iev_validate(doc.root)
50
+ concept_validate(doc, "concept", "refterm")
51
+ concept_validate(doc, "related", "preferred//name")
52
+ @fatalerror.empty? or clean_abort(@fatalerror.join("\n"), doc.to_xml)
53
+ end
54
+
55
+ def norm_ref_validate(doc)
56
+ found = false
57
+ doc.xpath("//references[@normative = 'true']/bibitem").each do |b|
58
+ next unless docid = b.at("./docidentifier[@type = 'metanorma']")
59
+ next unless /^\[\d+\]$/.match?(docid.text)
60
+
61
+ @log.add("Bibliography", b,
62
+ "Numeric reference in normative references")
63
+ found = true
64
+ end
65
+ found and @fatalerror << "Numeric reference in normative references"
66
+ end
67
+
68
+ def concept_validate(doc, tag, refterm)
69
+ found = false
70
+ doc.xpath("//#{tag}/xref").each do |x|
71
+ next if doc.at("//term[@id = '#{x['target']}']")
72
+ next if doc.at("//definitions//dt[@id = '#{x['target']}']")
73
+
74
+ ref = x&.at("../#{refterm}")&.text
75
+ @log.add("Anchors", x,
76
+ "#{tag.capitalize} #{ref} is pointing to "\
77
+ "#{x['target']}, which is not a term or symbol")
78
+ found = true
79
+ end
80
+ found and
81
+ @fatalerror << "#{tag.capitalize} not cross-referencing term or symbol"
82
+ end
83
+
84
+ def repeat_id_validate1(ids, elem)
85
+ if ids[elem["id"]]
86
+ @log.add("Anchors", elem, "Anchor #{elem['id']} has already been "\
87
+ "used at line #{ids[elem['id']]}")
88
+ @fatalerror << "Multiple instances of same ID: #{elem['id']}"
89
+ else
90
+ ids[elem["id"]] = elem.line
91
+ end
92
+ ids
93
+ end
94
+
95
+ def repeat_id_validate(doc)
96
+ ids = {}
97
+ doc.xpath("//*[@id]").each do |x|
98
+ ids = repeat_id_validate1(ids, x)
99
+ end
100
+ end
101
+
102
+ def schema_validate(doc, schema)
103
+ Tempfile.open(["tmp", ".xml"], encoding: "UTF-8") do |f|
104
+ schema_validate1(f, doc, schema)
105
+ rescue Jing::Error => e
106
+ clean_abort("Jing failed with error: #{e}", doc.to_xml)
107
+ ensure
108
+ f.close!
109
+ end
110
+ end
111
+
112
+ def schema_validate1(file, doc, schema)
113
+ file.write(doc.to_xml)
114
+ file.close
115
+ errors = Jing.new(schema, encoding: "UTF-8").validate(file.path)
116
+ warn "Syntax Valid!" if errors.none?
117
+ errors.each do |e|
118
+ @log.add("Metanorma XML Syntax",
119
+ "XML Line #{'%06d' % e[:line]}:#{e[:column]}", e[:message])
120
+ end
121
+ end
122
+
123
+ # RelaxNG cannot cope well with wildcard attributes. So we strip
124
+ # any attributes from FormattedString instances (which can contain
125
+ # xs:any markup, and are signalled with @format) before validation.
126
+ def formattedstr_strip(doc)
127
+ doc.xpath("//*[@format] | //stem | //bibdata//description | "\
128
+ "//formattedref | //bibdata//note | //bibdata/abstract | "\
129
+ "//bibitem/abstract | //bibitem/note | //misc-container")
130
+ .each do |n|
131
+ n.elements.each do |e|
132
+ e.traverse do |e1|
133
+ e1.element? and e1.each { |k, _v| e1.delete(k) }
134
+ end
135
+ end
136
+ end
137
+ doc
138
+ end
139
+
140
+ # manually check for xref/@target, xref/@to integrity
141
+ def xref_validate(doc)
142
+ ids = doc.xpath("//*/@id").each_with_object({}) { |x, m| m[x.text] = 1 }
143
+ doc.xpath("//xref/@target | //xref/@to").each do |x|
144
+ next if ids[x.text]
145
+
146
+ @log.add("Anchors", x.parent,
147
+ "Crossreference target #{x.text} is undefined")
148
+ end
149
+ end
150
+
151
+ def validate(doc)
152
+ content_validate(doc)
153
+ schema_validate(formattedstr_strip(doc.dup),
154
+ File.join(File.dirname(__FILE__), "isodoc.rng"))
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,55 @@
1
+ require "nokogiri"
2
+
3
+ module Metanorma
4
+ module Standoc
5
+ module Validate
6
+ def section_validate(doc)
7
+ sourcecode_style(doc.root)
8
+ hanging_para_style(doc.root)
9
+ asset_style(doc.root)
10
+ end
11
+
12
+ def sourcecode_style(root)
13
+ root.xpath("//sourcecode").each do |x|
14
+ callouts = x.elements.select { |e| e.name == "callout" }
15
+ annotations = x.elements.select { |e| e.name == "annotation" }
16
+ if callouts.size != annotations.size
17
+ @log.add("AsciiDoc Input", x,
18
+ "mismatch of callouts and annotations")
19
+ end
20
+ end
21
+ end
22
+
23
+ def style_warning(node, msg, text = nil)
24
+ w = msg
25
+ w += ": #{text}" if text
26
+ @log.add("Metanorma XML Style Warning", node, w)
27
+ end
28
+
29
+ def asset_title_style(root)
30
+ root.xpath("//figure[image][not(name)]").each do |node|
31
+ style_warning(node, "Figure should have title", nil)
32
+ end
33
+ root.xpath("//table[not(name)]").each do |node|
34
+ style_warning(node, "Table should have title", nil)
35
+ end
36
+ end
37
+
38
+ def asset_style(root)
39
+ asset_title_style(root)
40
+ end
41
+
42
+ def hanging_para_style(root)
43
+ root.xpath("//clause | //annex | //foreword | //introduction | "\
44
+ "//acknowledgements").each do |c|
45
+ next unless c.at("./clause")
46
+ next if c.elements.reject do |n|
47
+ %w(clause title).include? n.name
48
+ end.empty?
49
+
50
+ style_warning(c, "Hanging paragraph in clause")
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "1.11.3".freeze
22
+ VERSION = "2.0.2".freeze
23
23
  end
24
24
  end
@@ -1,6 +1,6 @@
1
1
  require "asciidoctor" unless defined? Asciidoctor::Converter
2
2
  require_relative "isodoc/pdf_convert"
3
- require_relative "asciidoctor/standoc/converter"
3
+ require_relative "metanorma/standoc/converter"
4
4
  require_relative "metanorma/standoc/version"
5
5
  require "asciidoctor/extensions"
6
6
 
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  spec.add_dependency "asciidoctor", "~> 2.0.0"
30
30
  spec.add_dependency "iev", "~> 0.3.0"
31
- spec.add_dependency "isodoc", "~> 1.8.0"
31
+ spec.add_dependency "isodoc", "~> 2.0.0"
32
32
  spec.add_dependency "metanorma-plugin-datastruct"
33
33
  spec.add_dependency "metanorma-plugin-lutaml"
34
34
  spec.add_dependency "ruby-jing"
@@ -0,0 +1,8 @@
1
+ = X
2
+ A
3
+
4
+ == Clause 1
5
+
6
+ X
7
+
8
+ embed::spec/assets/a2.adoc[]
@@ -0,0 +1,8 @@
1
+ = X
2
+ A
3
+
4
+ == Clause 2
5
+
6
+ X
7
+
8
+ embed::spec/assets/a3.adoc[]
@@ -0,0 +1,9 @@
1
+ = X
2
+ A
3
+
4
+ == Clause 3
5
+
6
+ X
7
+
8
+ include::spec/assets/a4.adoc[]
9
+
@@ -0,0 +1,4 @@
1
+ == Clause 4
2
+
3
+ X
4
+