metanorma-standoc 1.9.0 → 1.10.0
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.
- 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) }
|