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.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +3 -13
- data/.hound.yml +3 -1
- data/.rubocop.yml +4 -8
- data/lib/asciidoctor/standoc/base.rb +31 -35
- data/lib/asciidoctor/standoc/biblio.rng +1 -0
- data/lib/asciidoctor/standoc/blocks.rb +25 -9
- data/lib/asciidoctor/standoc/blocks_notes.rb +41 -24
- data/lib/asciidoctor/standoc/cleanup.rb +59 -84
- data/lib/asciidoctor/standoc/cleanup_block.rb +63 -85
- data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +28 -15
- data/lib/asciidoctor/standoc/cleanup_footnotes.rb +1 -0
- data/lib/asciidoctor/standoc/cleanup_image.rb +71 -0
- data/lib/asciidoctor/standoc/cleanup_inline.rb +117 -77
- data/lib/asciidoctor/standoc/cleanup_maths.rb +36 -27
- data/lib/asciidoctor/standoc/cleanup_ref.rb +31 -15
- data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +1 -1
- data/lib/asciidoctor/standoc/cleanup_reqt.rb +47 -0
- data/lib/asciidoctor/standoc/cleanup_section.rb +77 -135
- data/lib/asciidoctor/standoc/cleanup_section_names.rb +75 -0
- data/lib/asciidoctor/standoc/cleanup_terms.rb +19 -18
- data/lib/asciidoctor/standoc/converter.rb +7 -2
- data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +67 -66
- data/lib/asciidoctor/standoc/front.rb +35 -18
- data/lib/asciidoctor/standoc/front_contributor.rb +70 -45
- data/lib/asciidoctor/standoc/inline.rb +45 -34
- data/lib/asciidoctor/standoc/isodoc.rng +209 -4
- data/lib/asciidoctor/standoc/lists.rb +4 -2
- data/lib/asciidoctor/standoc/macros.rb +11 -11
- data/lib/asciidoctor/standoc/macros_form.rb +63 -0
- data/lib/asciidoctor/standoc/macros_plantuml.rb +19 -21
- data/lib/asciidoctor/standoc/macros_terms.rb +33 -23
- data/lib/asciidoctor/standoc/ref.rb +87 -112
- data/lib/asciidoctor/standoc/ref_date_id.rb +62 -0
- data/lib/asciidoctor/standoc/ref_sect.rb +20 -17
- data/lib/asciidoctor/standoc/section.rb +3 -1
- data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +40 -27
- data/lib/asciidoctor/standoc/terms.rb +25 -18
- data/lib/asciidoctor/standoc/utils.rb +35 -9
- data/lib/asciidoctor/standoc/validate.rb +48 -33
- data/lib/metanorma-standoc.rb +0 -1
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +4 -4
- data/spec/asciidoctor/base_spec.rb +701 -508
- data/spec/asciidoctor/blocks_spec.rb +831 -738
- data/spec/asciidoctor/cleanup_sections_spec.rb +51 -14
- data/spec/asciidoctor/cleanup_spec.rb +889 -682
- data/spec/asciidoctor/inline_spec.rb +62 -14
- data/spec/asciidoctor/isobib_cache_spec.rb +404 -358
- data/spec/asciidoctor/lists_spec.rb +149 -137
- data/spec/asciidoctor/macros_plantuml_spec.rb +8 -8
- data/spec/asciidoctor/macros_spec.rb +923 -503
- data/spec/asciidoctor/macros_yaml2text_spec.rb +1 -1
- data/spec/asciidoctor/refs_dl_spec.rb +4 -4
- data/spec/asciidoctor/refs_spec.rb +1528 -1533
- data/spec/asciidoctor/section_spec.rb +405 -299
- data/spec/asciidoctor/table_spec.rb +6 -6
- data/spec/asciidoctor/validate_spec.rb +342 -304
- data/spec/spec_helper.rb +13 -9
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +54 -54
- data/spec/vcr_cassettes/isobib_get_123.yml +13 -13
- data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
- data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +37 -37
- data/spec/vcr_cassettes/isobib_get_123_2001.yml +12 -12
- data/spec/vcr_cassettes/isobib_get_124.yml +13 -13
- data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
- data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
- metadata +16 -15
- data/lib/liquid/custom_blocks/key_iterator.rb +0 -21
- data/lib/liquid/custom_blocks/with_json_nested_context.rb +0 -18
- data/lib/liquid/custom_blocks/with_yaml_nested_context.rb +0 -19
- 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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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(
|
95
|
-
|
96
|
-
|
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
|
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 ||
|
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(
|
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
|
-
|
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(
|
49
|
+
log.add("AsciiDoc Input", node,
|
40
50
|
%(Error: Term reference in `term[#{target}]` missing: \
|
41
51
|
"#{target}" is not defined in document))
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
node.
|
48
|
-
|
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 =
|
53
|
-
node[
|
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(
|
60
|
-
normalize_id_and_memorize(term_node, res,
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
87
|
+
unless @idhash["term-#{text}"]
|
88
|
+
return "term-#{text}"
|
89
|
+
end
|
90
|
+
|
78
91
|
(1..Float::INFINITY).lazy.each do |index|
|
79
|
-
|
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,
|
15
|
+
def symbols_attrs(node, attr)
|
16
16
|
case sectiontype1(node)
|
17
|
-
when "symbols" then
|
18
|
-
when "abbreviated terms", "abbreviations"
|
17
|
+
when "symbols" then attr.merge(type: "symbols")
|
18
|
+
when "abbreviated terms", "abbreviations"
|
19
|
+
attr.merge(type: "abbreviated_terms")
|
19
20
|
else
|
20
|
-
|
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"
|
55
|
-
|
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
|
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,
|
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(
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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,
|
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
|
-
|
98
|
-
mod.p { |p| p <<
|
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)[^>]+>(
|
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,
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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("–", "\u0096")
|
38
|
-
gsub("—", "\u0097").gsub("–", "\u0096")
|
39
|
-
gsub("—", "\u0097")
|
37
|
+
l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("–", "\u0096")
|
38
|
+
.gsub("—", "\u0097").gsub("–", "\u0096")
|
39
|
+
.gsub("—", "\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(
|
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
|
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
|
48
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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,
|
58
|
-
if ids[
|
59
|
-
@log.add("Anchors",
|
60
|
-
"at line #{ids[
|
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[
|
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
|
-
|
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"], :
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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")
|
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) }
|