metanorma-standoc 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) 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 +4 -8
  5. data/lib/asciidoctor/standoc/base.rb +31 -35
  6. data/lib/asciidoctor/standoc/biblio.rng +1 -0
  7. data/lib/asciidoctor/standoc/blocks.rb +25 -9
  8. data/lib/asciidoctor/standoc/blocks_notes.rb +41 -24
  9. data/lib/asciidoctor/standoc/cleanup.rb +59 -84
  10. data/lib/asciidoctor/standoc/cleanup_block.rb +63 -85
  11. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +28 -15
  12. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +1 -0
  13. data/lib/asciidoctor/standoc/cleanup_image.rb +71 -0
  14. data/lib/asciidoctor/standoc/cleanup_inline.rb +117 -77
  15. data/lib/asciidoctor/standoc/cleanup_maths.rb +36 -27
  16. data/lib/asciidoctor/standoc/cleanup_ref.rb +31 -15
  17. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +1 -1
  18. data/lib/asciidoctor/standoc/cleanup_reqt.rb +47 -0
  19. data/lib/asciidoctor/standoc/cleanup_section.rb +77 -135
  20. data/lib/asciidoctor/standoc/cleanup_section_names.rb +75 -0
  21. data/lib/asciidoctor/standoc/cleanup_terms.rb +19 -18
  22. data/lib/asciidoctor/standoc/converter.rb +7 -2
  23. data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +67 -66
  24. data/lib/asciidoctor/standoc/front.rb +35 -18
  25. data/lib/asciidoctor/standoc/front_contributor.rb +70 -45
  26. data/lib/asciidoctor/standoc/inline.rb +45 -34
  27. data/lib/asciidoctor/standoc/isodoc.rng +209 -4
  28. data/lib/asciidoctor/standoc/lists.rb +4 -2
  29. data/lib/asciidoctor/standoc/macros.rb +11 -11
  30. data/lib/asciidoctor/standoc/macros_form.rb +63 -0
  31. data/lib/asciidoctor/standoc/macros_plantuml.rb +19 -21
  32. data/lib/asciidoctor/standoc/macros_terms.rb +33 -23
  33. data/lib/asciidoctor/standoc/ref.rb +87 -112
  34. data/lib/asciidoctor/standoc/ref_date_id.rb +62 -0
  35. data/lib/asciidoctor/standoc/ref_sect.rb +20 -17
  36. data/lib/asciidoctor/standoc/section.rb +3 -1
  37. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +40 -27
  38. data/lib/asciidoctor/standoc/terms.rb +25 -18
  39. data/lib/asciidoctor/standoc/utils.rb +35 -9
  40. data/lib/asciidoctor/standoc/validate.rb +48 -33
  41. data/lib/metanorma-standoc.rb +0 -1
  42. data/lib/metanorma/standoc/version.rb +1 -1
  43. data/metanorma-standoc.gemspec +4 -4
  44. data/spec/asciidoctor/base_spec.rb +701 -508
  45. data/spec/asciidoctor/blocks_spec.rb +831 -738
  46. data/spec/asciidoctor/cleanup_sections_spec.rb +51 -14
  47. data/spec/asciidoctor/cleanup_spec.rb +889 -682
  48. data/spec/asciidoctor/inline_spec.rb +62 -14
  49. data/spec/asciidoctor/isobib_cache_spec.rb +404 -358
  50. data/spec/asciidoctor/lists_spec.rb +149 -137
  51. data/spec/asciidoctor/macros_plantuml_spec.rb +8 -8
  52. data/spec/asciidoctor/macros_spec.rb +923 -503
  53. data/spec/asciidoctor/macros_yaml2text_spec.rb +1 -1
  54. data/spec/asciidoctor/refs_dl_spec.rb +4 -4
  55. data/spec/asciidoctor/refs_spec.rb +1528 -1533
  56. data/spec/asciidoctor/section_spec.rb +405 -299
  57. data/spec/asciidoctor/table_spec.rb +6 -6
  58. data/spec/asciidoctor/validate_spec.rb +342 -304
  59. data/spec/spec_helper.rb +13 -9
  60. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +54 -54
  61. data/spec/vcr_cassettes/isobib_get_123.yml +13 -13
  62. data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
  63. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +37 -37
  64. data/spec/vcr_cassettes/isobib_get_123_2001.yml +12 -12
  65. data/spec/vcr_cassettes/isobib_get_124.yml +13 -13
  66. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
  67. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
  68. metadata +16 -15
  69. data/lib/liquid/custom_blocks/key_iterator.rb +0 -21
  70. data/lib/liquid/custom_blocks/with_json_nested_context.rb +0 -18
  71. data/lib/liquid/custom_blocks/with_yaml_nested_context.rb +0 -19
  72. data/lib/liquid/custom_filters/values.rb +0 -7
@@ -10,10 +10,10 @@ module Asciidoctor
10
10
  end
11
11
 
12
12
  def reference(node)
13
- noko do |xml|
14
- node.items.each { |item| reference1(node, item.text, xml) }
15
- end.join
16
- end
13
+ noko do |xml|
14
+ node.items.each { |item| reference1(node, item.text, xml) }
15
+ end.join
16
+ end
17
17
 
18
18
  def bibliography_parse(attrs, xml, node)
19
19
  node.option? "bibitem" and return bibitem_parse(attrs, xml, node)
@@ -43,12 +43,12 @@ module Asciidoctor
43
43
  node.attr("style") == "bibliography" or
44
44
  @log.add("AsciiDoc Input", node, "Section not marked up as [bibliography]!")
45
45
  @norm_ref = true
46
- xml.references **attr_code(attrs.merge(
47
- normative: node.attr("normative") || true)) do |xml_section|
48
- xml_section.title { |t| t << node.title }
49
- xml_section << node.content
50
- end
51
- @norm_ref = false
46
+ attrs = attrs.merge(normative: node.attr("normative") || true)
47
+ xml.references **attr_code(attrs) do |xml_section|
48
+ xml_section.title { |t| t << node.title }
49
+ xml_section << node.content
50
+ end
51
+ @norm_ref = false
52
52
  end
53
53
 
54
54
  def global_ievcache_name
@@ -57,6 +57,7 @@ module Asciidoctor
57
57
 
58
58
  def local_ievcache_name(cachename)
59
59
  return nil if cachename.nil?
60
+
60
61
  cachename += "_iev" unless cachename.empty?
61
62
  cachename = "iev" if cachename.empty?
62
63
  "#{cachename}/cache"
@@ -64,10 +65,11 @@ module Asciidoctor
64
65
 
65
66
  def fetch_ref(xml, code, year, **opts)
66
67
  return nil if opts[:no_year]
68
+
67
69
  code = code.sub(/^\([^)]+\)/, "")
68
- #require "byebug"; byebug if opts[:lang] == "fr"
69
70
  hit = @bibdb&.fetch(code, year, opts)
70
71
  return nil if hit.nil?
72
+
71
73
  xml.parent.add_child(smart_render_xml(hit, code, opts))
72
74
  xml
73
75
  rescue RelatonBib::RequestError
@@ -91,10 +93,9 @@ module Asciidoctor
91
93
  "<docidentifier type='metanorma'>#{mn_code(usrlbl)}</docidentifier>"
92
94
  end
93
95
 
94
- def smart_render_xml(x, code, opts)
95
- x.respond_to? :to_xml or return nil
96
- xstr = x.to_xml(lang: opts[:lang])
97
- xml = Nokogiri::XML(xstr)
96
+ def smart_render_xml(xml, code, opts)
97
+ xml.respond_to? :to_xml or return nil
98
+ xml = Nokogiri::XML(xml.to_xml(lang: opts[:lang]))
98
99
  emend_biblio(xml, code, opts[:title], opts[:usrlbl])
99
100
  xml.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
100
101
  xml.traverse do |n|
@@ -105,17 +106,19 @@ module Asciidoctor
105
106
 
106
107
  def init_bib_caches(node)
107
108
  return if @no_isobib
109
+
108
110
  global = !@no_isobib_cache && !node.attr("local-cache-only")
109
111
  local = node.attr("local-cache") || node.attr("local-cache-only")
110
112
  local = nil if @no_isobib_cache
111
113
  @bibdb = Relaton::DbCache.init_bib_caches(
112
114
  local_cache: local,
113
115
  flush_caches: node.attr("flush-caches"),
114
- global_cache: global)
116
+ global_cache: global
117
+ )
115
118
  end
116
119
 
117
120
  def init_iev_caches(node)
118
- unless (@no_isobib_cache || @no_isobib)
121
+ unless @no_isobib_cache || @no_isobib
119
122
  node.attr("local-cache-only") or
120
123
  @iev_globalname = global_ievcache_name
121
124
  @iev_localname = local_ievcache_name(node.attr("local-cache") ||
@@ -10,7 +10,9 @@ module Asciidoctor
10
10
  @norm_ref = false
11
11
 
12
12
  def sectiontype1(node)
13
- node&.attr("heading")&.downcase || node.title.gsub(/<[^>]+>/, "").downcase
13
+ node&.attr("heading")&.downcase ||
14
+ node.title.gsub(%r{<index>.*?</index>}m, "").gsub(/<[^>]+>/, "")
15
+ .strip.downcase
14
16
  end
15
17
 
16
18
  def sectiontype(node, level = true)
@@ -3,11 +3,9 @@
3
3
  module Asciidoctor
4
4
  module Standoc
5
5
  # Intelligent term lookup xml modifier
6
- # Lookup all `term` and `calause` tags and replace `termxref` tags with
7
- # `xref`:target tag
8
6
  class TermLookupCleanup
9
- AUTOMATIC_GENERATED_ID_REGEXP = /\A_/
10
- EXISTING_TERM_REGEXP = /\Aterm-/
7
+ AUTOMATIC_GENERATED_ID_REGEXP = /\A_/.freeze
8
+ EXISTING_TERM_REGEXP = /\Aterm-/.freeze
11
9
 
12
10
  attr_reader :xmldoc, :termlookup, :log
13
11
 
@@ -15,68 +13,83 @@ module Asciidoctor
15
13
  @xmldoc = xmldoc
16
14
  @log = log
17
15
  @termlookup = {}
16
+ @idhash = {}
18
17
  end
19
18
 
20
19
  def call
20
+ @idhash = populate_idhash
21
21
  @termlookup = replace_automatic_generated_ids_terms
22
22
  set_termxref_tags_target
23
23
  end
24
24
 
25
25
  private
26
26
 
27
+ def populate_idhash
28
+ xmldoc.xpath("//*[@id]").each_with_object({}) do |n, mem|
29
+ next unless /^term-/.match?(n["id"])
30
+
31
+ mem[n["id"]] = true
32
+ end
33
+ end
34
+
27
35
  def set_termxref_tags_target
28
- xmldoc.xpath('//termxref').each do |node|
36
+ xmldoc.xpath("//termxref").each do |node|
29
37
  target = normalize_ref_id(node.text)
30
38
  if termlookup[target].nil?
31
39
  remove_missing_ref(node, target)
32
40
  next
33
41
  end
34
- modify_ref_node(node, target)
42
+ x = node.at("../xrefrender")
43
+ modify_ref_node(x, target)
44
+ node.name = "refterm"
35
45
  end
36
46
  end
37
47
 
38
48
  def remove_missing_ref(node, target)
39
- log.add('AsciiDoc Input', node,
49
+ log.add("AsciiDoc Input", node,
40
50
  %(Error: Term reference in `term[#{target}]` missing: \
41
51
  "#{target}" is not defined in document))
42
- term_name_node = node.previous.previous
43
- term_name_node.remove
44
- term_name_node.name = "strong"
45
- term_name_node.children.first.content =
46
- %(term "#{term_name_node.text}" not resolved)
47
- node.add_previous_sibling(term_name_node)
48
- node.remove
52
+ node.name = "strong"
53
+ node.at("../xrefrender").remove
54
+ display = node&.at("../renderterm")&.remove&.children
55
+ display = [] if display.nil? || display&.to_xml == node.text
56
+ d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
57
+ node.children = "term <tt>#{node.text}</tt>#{d} "\
58
+ "not resolved via ID <tt>#{target}</tt>"
49
59
  end
50
60
 
51
61
  def modify_ref_node(node, target)
52
- node.name = 'xref'
53
- node['target'] = termlookup[target]
54
- node.children.remove
55
- node.remove_attribute('defaultref')
62
+ node.name = "xref"
63
+ node["target"] = termlookup[target]
56
64
  end
57
65
 
58
66
  def replace_automatic_generated_ids_terms
59
- xmldoc.xpath('//term').each.with_object({}) do |term_node, res|
60
- normalize_id_and_memorize(term_node, res, './preferred')
67
+ xmldoc.xpath("//term").each.with_object({}) do |term_node, res|
68
+ normalize_id_and_memorize(term_node, res, "./preferred")
61
69
  end
62
70
  end
63
71
 
64
72
  def normalize_id_and_memorize(term_node, res_table, text_selector)
65
73
  term_text = normalize_ref_id(term_node.at(text_selector).text)
66
- unless AUTOMATIC_GENERATED_ID_REGEXP.match(term_node['id']).nil?
67
- term_node['id'] = unique_text_id(term_text)
68
- end
69
- res_table[term_text] = term_node['id']
74
+ unless AUTOMATIC_GENERATED_ID_REGEXP.match(term_node["id"]).nil?
75
+ id = unique_text_id(term_text)
76
+ term_node["id"] = id
77
+ @idhash[id] = true
78
+ end
79
+ res_table[term_text] = term_node["id"]
70
80
  end
71
81
 
72
82
  def normalize_ref_id(text)
73
- text.downcase.gsub(/[[:space:]]/, '-')
83
+ text.downcase.gsub(/[[:space:]]/, "-")
74
84
  end
75
85
 
76
86
  def unique_text_id(text)
77
- return "term-#{text}" if xmldoc.at("//*[@id = 'term-#{text}']").nil?
87
+ unless @idhash["term-#{text}"]
88
+ return "term-#{text}"
89
+ end
90
+
78
91
  (1..Float::INFINITY).lazy.each do |index|
79
- if xmldoc.at("//*[@id = 'term-#{text}-#{index}']").nil?
92
+ unless @idhash["term-#{text}-#{index}"]
80
93
  break("term-#{text}-#{index}")
81
94
  end
82
95
  end
@@ -12,12 +12,13 @@ module Asciidoctor
12
12
  @definitions = defs
13
13
  end
14
14
 
15
- def symbols_attrs(node, a)
15
+ def symbols_attrs(node, attr)
16
16
  case sectiontype1(node)
17
- when "symbols" then a.merge(type: "symbols")
18
- when "abbreviated terms", "abbreviations" then a.merge(type: "abbreviated_terms")
17
+ when "symbols" then attr.merge(type: "symbols")
18
+ when "abbreviated terms", "abbreviations"
19
+ attr.merge(type: "abbreviated_terms")
19
20
  else
20
- a
21
+ attr
21
22
  end
22
23
  end
23
24
 
@@ -51,13 +52,17 @@ module Asciidoctor
51
52
 
52
53
  # subclause contains subclauses
53
54
  def term_def_subclause_parse(attrs, xml, node)
54
- node.role == "nonterm" and return nonterm_term_def_subclause_parse(attrs, xml, node)
55
- node.role == "boilerplate" and return terms_boilerplate_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)
56
59
  st = sectiontype(node, false)
57
60
  return symbols_parse(attrs, xml, node) if @definitions
61
+
58
62
  sub = node.find_by(context: :section) { |s| s.level == node.level + 1 }
59
63
  sub.empty? || (return term_def_parse(attrs, xml, node, false))
60
- st == "symbols and abbreviated terms" and (return symbols_parse(attrs, xml, node))
64
+ st == "symbols and abbreviated terms" and
65
+ return symbols_parse(attrs, xml, node)
61
66
  st == "terms and definitions" and return clause_parse(attrs, xml, node)
62
67
  term_def_subclause_parse1(attrs, xml, node)
63
68
  end
@@ -69,7 +74,7 @@ module Asciidoctor
69
74
  end
70
75
  end
71
76
 
72
- def term_def_parse(attrs, xml, node, toplevel)
77
+ def term_def_parse(attrs, xml, node, _toplevel)
73
78
  xml.terms **attr_code(attrs) do |section|
74
79
  section.title { |t| t << node.title }
75
80
  (s = node.attr("source")) && s.split(/,/).each do |s1|
@@ -79,14 +84,14 @@ module Asciidoctor
79
84
  end
80
85
  end
81
86
 
82
- def term_source_attrs(node, seen_xref)
83
- { case: seen_xref.children[0]["case"],
84
- droploc: seen_xref.children[0]["droploc"],
85
- bibitemid: seen_xref.children[0]["target"],
86
- format: seen_xref.children[0]["format"], type: "inline" }
87
+ def term_source_attrs(_node, seen_xref)
88
+ { case: seen_xref.children[0]["case"],
89
+ droploc: seen_xref.children[0]["droploc"],
90
+ bibitemid: seen_xref.children[0]["target"],
91
+ format: seen_xref.children[0]["format"], type: "inline" }
87
92
  end
88
93
 
89
- def add_term_source(node, xml_t, seen_xref, m)
94
+ def add_term_source(node, xml_t, seen_xref, match)
90
95
  if seen_xref.children[0].name == "concept"
91
96
  xml_t.origin { |o| o << seen_xref.children[0].to_xml }
92
97
  else
@@ -94,13 +99,13 @@ module Asciidoctor
94
99
  attrs.delete(:text)
95
100
  xml_t.origin seen_xref.children[0].content, **attr_code(attrs)
96
101
  end
97
- m[:text] && xml_t.modification do |mod|
98
- mod.p { |p| p << m[:text].sub(/^\s+/, "") }
102
+ match[:text] && xml_t.modification do |mod|
103
+ mod.p { |p| p << match[:text].sub(/^\s+/, "") }
99
104
  end
100
105
  end
101
106
 
102
107
  TERM_REFERENCE_RE_STR = <<~REGEXP.freeze
103
- ^(?<xref><(xref|concept)[^>]+>([^<]*</(xref|concept)>)?)
108
+ ^(?<xref><(xref|concept)[^>]+>(.*?</(xref|concept)>)?)
104
109
  (,\s(?<text>.*))?
105
110
  $
106
111
  REGEXP
@@ -110,7 +115,9 @@ module Asciidoctor
110
115
 
111
116
  def extract_termsource_refs(text, node)
112
117
  matched = TERM_REFERENCE_RE.match text
113
- matched.nil? and @log.add("AsciiDoc Input", node, "term reference not in expected format: #{text}")
118
+ matched.nil? and @log.add("AsciiDoc Input", node,
119
+ "term reference not in expected format:"\
120
+ "#{text}")
114
121
  matched
115
122
  end
116
123
 
@@ -19,11 +19,11 @@ module Asciidoctor
19
19
  end
20
20
 
21
21
  NOKOHEAD = <<~HERE.freeze
22
- <!DOCTYPE html SYSTEM
23
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
24
- <html xmlns="http://www.w3.org/1999/xhtml">
25
- <head> <title></title> <meta charset="UTF-8" /> </head>
26
- <body> </body> </html>
22
+ <!DOCTYPE html SYSTEM
23
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
24
+ <html xmlns="http://www.w3.org/1999/xhtml">
25
+ <head> <title></title> <meta charset="UTF-8" /> </head>
26
+ <body> </body> </html>
27
27
  HERE
28
28
 
29
29
  # block for processing XML document fragments as XHTML,
@@ -34,9 +34,9 @@ module Asciidoctor
34
34
  fragment = doc.fragment("")
35
35
  ::Nokogiri::XML::Builder.with fragment, &block
36
36
  fragment.to_xml(encoding: "US-ASCII", indent: 0).lines.map do |l|
37
- l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("&#150;", "\u0096").
38
- gsub("&#151;", "\u0097").gsub("&#x96;", "\u0096").
39
- gsub("&#x97;", "\u0097")
37
+ l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("&#150;", "\u0096")
38
+ .gsub("&#151;", "\u0097").gsub("&#x96;", "\u0096")
39
+ .gsub("&#x97;", "\u0097")
40
40
  end
41
41
  end
42
42
 
@@ -66,10 +66,36 @@ module Asciidoctor
66
66
  conv
67
67
  end
68
68
 
69
+ def default_script(lang)
70
+ case lang
71
+ when "ar", "fa"
72
+ "Arab"
73
+ when "ur"
74
+ "Aran"
75
+ when "ru", "bg"
76
+ "Cyrl"
77
+ when "hi"
78
+ "Deva"
79
+ when "el"
80
+ "Grek"
81
+ when "zh"
82
+ "Hans"
83
+ when "ko"
84
+ "Kore"
85
+ when "he"
86
+ "Hebr"
87
+ when "ja"
88
+ "Jpan"
89
+ else
90
+ "Latn"
91
+ end
92
+ end
93
+
69
94
  class EmptyAttr
70
- def attr(_x)
95
+ def attr(_any_attribute)
71
96
  nil
72
97
  end
98
+
73
99
  def attributes
74
100
  {}
75
101
  end
@@ -1,5 +1,5 @@
1
1
  require "asciidoctor/standoc/utils"
2
- require_relative "./validate_section.rb"
2
+ require_relative "./validate_section"
3
3
  require "nokogiri"
4
4
  require "jing"
5
5
  require "iev"
@@ -7,22 +7,22 @@ require "iev"
7
7
  module Asciidoctor
8
8
  module Standoc
9
9
  module Validate
10
-
11
10
  SOURCELOCALITY = "./termsource/origin//locality[@type = 'clause']/"\
12
11
  "referenceFrom".freeze
13
12
 
14
13
  def init_iev
15
14
  return nil if @no_isobib
16
15
  return @iev if @iev
16
+
17
17
  @iev = Iev::Db.new(@iev_globalname, @iev_localname) unless @no_isobib
18
18
  @iev
19
19
  end
20
20
 
21
21
  def iev_validate(xmldoc)
22
+ @iev = init_iev or return
22
23
  xmldoc.xpath("//term").each do |t|
23
24
  /^IEC 60050-/.match(t&.at("./termsource/origin/@citeas")&.text) &&
24
25
  loc = t.xpath(SOURCELOCALITY)&.text or next
25
- @iev = init_iev or return
26
26
  iev = @iev.fetch(loc, xmldoc&.at("//language")&.text || "en") or next
27
27
  pref = t.xpath("./preferred").inject([]) do |m, x|
28
28
  m << x&.text&.downcase
@@ -38,29 +38,44 @@ module Asciidoctor
38
38
  norm_ref_validate(doc)
39
39
  repeat_id_validate(doc.root)
40
40
  iev_validate(doc.root)
41
+ concept_validate(doc)
41
42
  end
42
43
 
43
44
  def norm_ref_validate(doc)
44
45
  found = false
45
46
  doc.xpath("//references[@normative = 'true']/bibitem").each do |b|
46
47
  next unless docid = b.at("./docidentifier[@type = 'metanorma']")
47
- next unless /^\[\d+\]$/.match(docid.text)
48
- @log.add("Bibliography", b, "Numeric reference in normative references")
48
+ next unless /^\[\d+\]$/.match?(docid.text)
49
+
50
+ @log.add("Bibliography", b,
51
+ "Numeric reference in normative references")
49
52
  found = true
50
53
  end
51
- if found
52
- clean_exit
53
- abort("Numeric reference in normative references")
54
+ found and
55
+ clean_abort("Numeric reference in normative references", doc.to_xml)
56
+ end
57
+
58
+ def concept_validate(doc)
59
+ found = false
60
+ doc.xpath("//concept/xref").each do |x|
61
+ next if doc.at("//term[@id = '#{x['target']}']")
62
+
63
+ ref = x&.at("../refterm")&.text
64
+ @log.add("Anchors", x, "Concept #{ref} is pointing to "\
65
+ "#{x['target']}, which is not a term")
66
+ found = true
54
67
  end
68
+ found and
69
+ clean_abort("Concept not cross-referencing term", doc.to_xml)
55
70
  end
56
71
 
57
- def repeat_id_validate1(ids, x)
58
- if ids[x["id"]]
59
- @log.add("Anchors", x, "Anchor #{x['id']} has already been used "\
60
- "at line #{ids[x['id']]}")
72
+ def repeat_id_validate1(ids, elem)
73
+ if ids[elem["id"]]
74
+ @log.add("Anchors", elem, "Anchor #{elem['id']} has already been "\
75
+ "used at line #{ids[elem['id']]}")
61
76
  raise StandardError.new "Error: multiple instances of same ID"
62
77
  else
63
- ids[x["id"]] = x.line
78
+ ids[elem["id"]] = elem.line
64
79
  end
65
80
  ids
66
81
  end
@@ -72,29 +87,28 @@ module Asciidoctor
72
87
  ids = repeat_id_validate1(ids, x)
73
88
  end
74
89
  rescue StandardError => e
75
- clean_exit
76
- abort(e.message)
90
+ clean_abort(e.message, doc.to_xml)
77
91
  end
78
92
  end
79
93
 
80
94
  def schema_validate(doc, schema)
81
- Tempfile.open(["tmp", ".xml"], :encoding => 'UTF-8') do |f|
82
- begin
83
- f.write(doc.to_xml)
84
- f.close
85
- errors = Jing.new(schema).validate(f.path)
86
- warn "Syntax Valid!" if errors.none?
87
- errors.each do |e|
88
- @log.add("Metanorma XML Syntax",
89
- "XML Line #{"%06d" % e[:line]}:#{e[:column]}",
90
- e[:message])
91
- end
92
- rescue Jing::Error => e
93
- clean_exit
94
- abort "Jing failed with error: #{e}"
95
- ensure
96
- f.close!
97
- end
95
+ Tempfile.open(["tmp", ".xml"], encoding: "UTF-8") do |f|
96
+ schema_validate1(f, doc, schema)
97
+ rescue Jing::Error => e
98
+ clean_abort("Jing failed with error: #{e}", doc.to_xml)
99
+ ensure
100
+ f.close!
101
+ end
102
+ end
103
+
104
+ def schema_validate1(file, doc, schema)
105
+ file.write(doc.to_xml)
106
+ file.close
107
+ errors = Jing.new(schema).validate(file.path)
108
+ warn "Syntax Valid!" if errors.none?
109
+ errors.each do |e|
110
+ @log.add("Metanorma XML Syntax",
111
+ "XML Line #{'%06d' % e[:line]}:#{e[:column]}", e[:message])
98
112
  end
99
113
  end
100
114
 
@@ -104,7 +118,8 @@ module Asciidoctor
104
118
  def formattedstr_strip(doc)
105
119
  doc.xpath("//*[@format] | //stem | //bibdata//description | "\
106
120
  "//formattedref | //bibdata//note | //bibdata/abstract | "\
107
- "//bibitem/abstract | //bibitem/note | //misc-container").each do |n|
121
+ "//bibitem/abstract | //bibitem/note | //misc-container")
122
+ .each do |n|
108
123
  n.elements.each do |e|
109
124
  e.traverse do |e1|
110
125
  e1.element? and e1.each { |k, _v| e1.delete(k) }