metanorma-standoc 1.10.8 → 1.11.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/Rakefile +1 -1
- data/lib/asciidoctor/standoc/base.rb +5 -4
- data/lib/asciidoctor/standoc/cleanup.rb +20 -11
- data/lib/asciidoctor/standoc/cleanup_inline.rb +20 -7
- data/lib/asciidoctor/standoc/cleanup_maths.rb +5 -6
- data/lib/asciidoctor/standoc/cleanup_reqt.rb +2 -21
- data/lib/asciidoctor/standoc/cleanup_symbols.rb +48 -0
- data/lib/asciidoctor/standoc/cleanup_terms.rb +37 -77
- data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +162 -0
- data/lib/asciidoctor/standoc/converter.rb +2 -0
- data/lib/asciidoctor/standoc/inline.rb +7 -5
- data/lib/asciidoctor/standoc/isodoc.rng +218 -27
- data/lib/asciidoctor/standoc/macros_plantuml.rb +29 -14
- data/lib/asciidoctor/standoc/macros_terms.rb +49 -5
- data/lib/asciidoctor/standoc/ref_sect.rb +24 -17
- data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +50 -11
- data/lib/asciidoctor/standoc/terms.rb +12 -2
- data/lib/asciidoctor/standoc/utils.rb +36 -23
- data/lib/asciidoctor/standoc/validate.rb +24 -15
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +1 -1
- data/spec/asciidoctor/base_spec.rb +4 -3
- data/spec/asciidoctor/blocks_spec.rb +149 -21
- data/spec/asciidoctor/cleanup_sections_spec.rb +7 -7
- data/spec/asciidoctor/cleanup_spec.rb +21 -195
- data/spec/asciidoctor/cleanup_terms_spec.rb +990 -0
- data/spec/asciidoctor/inline_spec.rb +2 -2
- data/spec/asciidoctor/macros_plantuml_spec.rb +36 -1
- data/spec/asciidoctor/macros_spec.rb +189 -112
- data/spec/asciidoctor/refs_spec.rb +2 -24
- data/spec/asciidoctor/section_spec.rb +18 -18
- data/spec/asciidoctor/validate_spec.rb +59 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +46 -46
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +12 -12
- data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
- data/spec/vcr_cassettes/isobib_get_123_1.yml +26 -26
- data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +32 -32
- data/spec/vcr_cassettes/isobib_get_123_2001.yml +11 -11
- data/spec/vcr_cassettes/isobib_get_124.yml +12 -12
- data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
- data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +45 -65
- metadata +8 -5
@@ -1,4 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true.
|
2
|
+
require "asciidoctor/standoc/utils"
|
3
|
+
|
2
4
|
|
3
5
|
module Asciidoctor
|
4
6
|
module Standoc
|
@@ -13,7 +15,7 @@ module Asciidoctor
|
|
13
15
|
def initialize(xmldoc, log)
|
14
16
|
@xmldoc = xmldoc
|
15
17
|
@log = log
|
16
|
-
@termlookup = { term: {}, symbol: {} }
|
18
|
+
@termlookup = { term: {}, symbol: {}, secondary2primary: {} }
|
17
19
|
@idhash = {}
|
18
20
|
end
|
19
21
|
|
@@ -22,6 +24,7 @@ module Asciidoctor
|
|
22
24
|
@termlookup = replace_automatic_generated_ids_terms
|
23
25
|
set_termxref_tags_target
|
24
26
|
concept_cleanup
|
27
|
+
related_cleanup
|
25
28
|
end
|
26
29
|
|
27
30
|
private
|
@@ -29,6 +32,19 @@ module Asciidoctor
|
|
29
32
|
def concept_cleanup
|
30
33
|
xmldoc.xpath("//concept").each do |n|
|
31
34
|
n.delete("type")
|
35
|
+
refterm = n.at("./refterm") or next
|
36
|
+
p = @termlookup[:secondary2primary][refterm.text] and
|
37
|
+
refterm.children = p
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def related_cleanup
|
42
|
+
xmldoc.xpath("//related").each do |n|
|
43
|
+
refterm = n.at("./refterm") or next
|
44
|
+
p = @termlookup[:secondary2primary][refterm.text] and
|
45
|
+
refterm.children = p
|
46
|
+
refterm.replace("<preferred><expression><name>#{refterm.children.to_xml}"\
|
47
|
+
"</name></expression></preferred>")
|
32
48
|
end
|
33
49
|
end
|
34
50
|
|
@@ -47,8 +63,7 @@ module Asciidoctor
|
|
47
63
|
remove_missing_ref(node, target)
|
48
64
|
next
|
49
65
|
end
|
50
|
-
x = node.at("../xrefrender")
|
51
|
-
modify_ref_node(x, target)
|
66
|
+
x = node.at("../xrefrender") and modify_ref_node(x, target)
|
52
67
|
node.name = "refterm"
|
53
68
|
end
|
54
69
|
end
|
@@ -66,12 +81,12 @@ module Asciidoctor
|
|
66
81
|
%(Error: Term reference in `term[#{target}]` missing: \
|
67
82
|
"#{target}" is not defined in document))
|
68
83
|
node.name = "strong"
|
69
|
-
node
|
84
|
+
node&.at("../xrefrender")&.remove
|
70
85
|
display = node&.at("../renderterm")&.remove&.children
|
71
86
|
display = [] if display.nil? || display&.to_xml == node.text
|
72
87
|
d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
|
73
88
|
node.children = "term <tt>#{node.text}</tt>#{d} "\
|
74
|
-
|
89
|
+
"not resolved via ID <tt>#{target}</tt>"
|
75
90
|
end
|
76
91
|
|
77
92
|
def remove_missing_ref_symbol(node, target)
|
@@ -79,12 +94,12 @@ module Asciidoctor
|
|
79
94
|
%(Error: Symbol reference in `symbol[#{target}]` missing: \
|
80
95
|
"#{target}" is not defined in document))
|
81
96
|
node.name = "strong"
|
82
|
-
node
|
97
|
+
node&.at("../xrefrender")&.remove
|
83
98
|
display = node&.at("../renderterm")&.remove&.children
|
84
99
|
display = [] if display.nil? || display&.to_xml == node.text
|
85
100
|
d = display.empty? ? "" : ", display <tt>#{display.to_xml}</tt>"
|
86
101
|
node.children = "symbol <tt>#{node.text}</tt>#{d} "\
|
87
|
-
|
102
|
+
"not resolved via ID <tt>#{target}</tt>"
|
88
103
|
end
|
89
104
|
|
90
105
|
def modify_ref_node(node, target)
|
@@ -92,24 +107,40 @@ module Asciidoctor
|
|
92
107
|
s = termlookup[:symbol][target]
|
93
108
|
t = termlookup[:term][target]
|
94
109
|
type = node.parent["type"]
|
95
|
-
if type == "term" || !type && t
|
110
|
+
if type == "term" || ((!type || node.parent.name == "related") && t)
|
96
111
|
node["target"] = t
|
97
|
-
elsif type == "symbol" ||
|
112
|
+
elsif type == "symbol" ||
|
113
|
+
((!type || node.parent.name == "related") && s)
|
98
114
|
node["target"] = s
|
99
115
|
end
|
100
116
|
end
|
101
117
|
|
102
118
|
def replace_automatic_generated_ids_terms
|
103
119
|
r = xmldoc.xpath("//term").each.with_object({}) do |n, res|
|
104
|
-
normalize_id_and_memorize(n, res, "./preferred",
|
120
|
+
normalize_id_and_memorize(n, res, "./preferred//name",
|
121
|
+
"term")
|
105
122
|
end
|
106
123
|
s = xmldoc.xpath("//definitions//dt").each.with_object({}) do |n, res|
|
107
124
|
normalize_id_and_memorize(n, res, ".", "symbol")
|
108
125
|
end
|
109
|
-
{ term: r, symbol: s }
|
126
|
+
{ term: r, symbol: s, secondary2primary: pref_secondary2primary }
|
127
|
+
end
|
128
|
+
|
129
|
+
def pref_secondary2primary
|
130
|
+
xmldoc.xpath("//term").each.with_object({}) do |n, res|
|
131
|
+
n.xpath("./preferred//name").each_with_index do |p, i|
|
132
|
+
i.zero? and term = p.text
|
133
|
+
i.positive? and res[p.text] = term
|
134
|
+
end
|
135
|
+
end
|
110
136
|
end
|
111
137
|
|
112
138
|
def normalize_id_and_memorize(node, res_table, text_selector, prefix)
|
139
|
+
normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
|
140
|
+
memorize_other_pref_terms(node, res_table, text_selector)
|
141
|
+
end
|
142
|
+
|
143
|
+
def normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
|
113
144
|
term_text = normalize_ref_id(node.at(text_selector).text)
|
114
145
|
unless AUTOMATIC_GENERATED_ID_REGEXP.match(node["id"]).nil? &&
|
115
146
|
!node["id"].nil?
|
@@ -120,6 +151,14 @@ module Asciidoctor
|
|
120
151
|
res_table[term_text] = node["id"]
|
121
152
|
end
|
122
153
|
|
154
|
+
def memorize_other_pref_terms(node, res_table, text_selector)
|
155
|
+
node.xpath(text_selector).each_with_index do |p, i|
|
156
|
+
next unless i.positive?
|
157
|
+
|
158
|
+
res_table[normalize_ref_id(p.text)] = node["id"]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
123
162
|
def normalize_ref_id(text)
|
124
163
|
Metanorma::Utils::to_ncname(text.downcase.gsub(/[[:space:]]/, "-"))
|
125
164
|
end
|
@@ -69,7 +69,7 @@ module Asciidoctor
|
|
69
69
|
|
70
70
|
def term_def_subclause_parse1(attrs, xml, node)
|
71
71
|
xml.term **attr_code(attrs) do |xml_section|
|
72
|
-
xml_section
|
72
|
+
term_designation(xml_section, node, "preferred", node.title)
|
73
73
|
xml_section << node.content
|
74
74
|
end
|
75
75
|
end
|
@@ -84,6 +84,14 @@ module Asciidoctor
|
|
84
84
|
end
|
85
85
|
end
|
86
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
|
+
|
87
95
|
def term_source_attrs(_node, seen_xref)
|
88
96
|
{ case: seen_xref.children[0]["case"],
|
89
97
|
droploc: seen_xref.children[0]["droploc"],
|
@@ -124,7 +132,9 @@ module Asciidoctor
|
|
124
132
|
def termsource(node)
|
125
133
|
matched = extract_termsource_refs(node.content, node) || return
|
126
134
|
noko do |xml|
|
127
|
-
|
135
|
+
status = node.attr("status") ||
|
136
|
+
(matched[:text] ? "modified" : "identical")
|
137
|
+
attrs = { status: status, type: node.attr("type") || "authoritative" }
|
128
138
|
xml.termsource **attrs do |xml_t|
|
129
139
|
seen_xref = Nokogiri::XML.fragment(matched[:xref])
|
130
140
|
add_term_source(node, xml_t, seen_xref, matched)
|
@@ -40,10 +40,9 @@ module Asciidoctor
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def attr_code(attributes)
|
43
|
-
attributes
|
44
|
-
|
45
|
-
|
46
|
-
end.to_h
|
43
|
+
attributes.compact.transform_values do |v|
|
44
|
+
v.is_a?(String) ? HTMLEntities.new.decode(v) : v
|
45
|
+
end
|
47
46
|
end
|
48
47
|
|
49
48
|
# if the contents of node are blocks, output them to out;
|
@@ -56,7 +55,7 @@ module Asciidoctor
|
|
56
55
|
end
|
57
56
|
|
58
57
|
SUBCLAUSE_XPATH = "//clause[not(parent::sections)]"\
|
59
|
-
|
58
|
+
"[not(ancestor::boilerplate)]".freeze
|
60
59
|
|
61
60
|
def isodoc(lang, script, i18nyaml = nil)
|
62
61
|
conv = html_converter(EmptyAttr.new)
|
@@ -67,29 +66,43 @@ module Asciidoctor
|
|
67
66
|
|
68
67
|
def default_script(lang)
|
69
68
|
case lang
|
70
|
-
when "ar", "fa"
|
71
|
-
|
72
|
-
when "
|
73
|
-
|
74
|
-
when "
|
75
|
-
|
76
|
-
when "
|
77
|
-
|
78
|
-
when "
|
79
|
-
"Grek"
|
80
|
-
when "zh"
|
81
|
-
"Hans"
|
82
|
-
when "ko"
|
83
|
-
"Kore"
|
84
|
-
when "he"
|
85
|
-
"Hebr"
|
86
|
-
when "ja"
|
87
|
-
"Jpan"
|
69
|
+
when "ar", "fa" then "Arab"
|
70
|
+
when "ur" then "Aran"
|
71
|
+
when "ru", "bg" then "Cyrl"
|
72
|
+
when "hi" then "Deva"
|
73
|
+
when "el" then "Grek"
|
74
|
+
when "zh" then "Hans"
|
75
|
+
when "ko" then "Kore"
|
76
|
+
when "he" then "Hebr"
|
77
|
+
when "ja" then "Jpan"
|
88
78
|
else
|
89
79
|
"Latn"
|
90
80
|
end
|
91
81
|
end
|
92
82
|
|
83
|
+
def dl_to_attrs(elem, dlist, name)
|
84
|
+
e = dlist.at("./dt[text()='#{name}']") or return
|
85
|
+
val = e.at("./following::dd/p") || e.at("./following::dd") or return
|
86
|
+
elem[name] = val.text
|
87
|
+
end
|
88
|
+
|
89
|
+
def dl_to_elems(ins, elem, dlist, name)
|
90
|
+
a = elem.at("./#{name}[last()]")
|
91
|
+
ins = a if a
|
92
|
+
dlist.xpath("./dt[text()='#{name}']").each do |e|
|
93
|
+
v = e.at("./following::dd")
|
94
|
+
e = v.elements and e.size == 1 && e.first.name == "p" and v = e.first
|
95
|
+
v.name = name
|
96
|
+
ins.next = v
|
97
|
+
ins = ins.next
|
98
|
+
end
|
99
|
+
ins
|
100
|
+
end
|
101
|
+
|
102
|
+
def term_expr(elem)
|
103
|
+
"<expression><name>#{elem}</name></expression>"
|
104
|
+
end
|
105
|
+
|
93
106
|
class EmptyAttr
|
94
107
|
def attr(_any_attribute)
|
95
108
|
nil
|
@@ -7,7 +7,7 @@ require "iev"
|
|
7
7
|
module Asciidoctor
|
8
8
|
module Standoc
|
9
9
|
module Validate
|
10
|
-
SOURCELOCALITY = "./
|
10
|
+
SOURCELOCALITY = "./origin//locality[@type = 'clause']/"\
|
11
11
|
"referenceFrom".freeze
|
12
12
|
|
13
13
|
def init_iev
|
@@ -21,18 +21,25 @@ module Asciidoctor
|
|
21
21
|
def iev_validate(xmldoc)
|
22
22
|
@iev = init_iev or return
|
23
23
|
xmldoc.xpath("//term").each do |t|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
m << x&.text&.downcase
|
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)
|
29
28
|
end
|
30
|
-
pref.include?(iev.downcase) or
|
31
|
-
@log.add("Bibliography", t, %(Term "#{pref[0]}" does not match ) +
|
32
|
-
%(IEV #{loc} "#{iev}"))
|
33
29
|
end
|
34
30
|
end
|
35
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
|
+
|
36
43
|
def content_validate(doc)
|
37
44
|
@fatalerror = []
|
38
45
|
xref_validate(doc)
|
@@ -40,7 +47,8 @@ module Asciidoctor
|
|
40
47
|
norm_ref_validate(doc)
|
41
48
|
repeat_id_validate(doc.root)
|
42
49
|
iev_validate(doc.root)
|
43
|
-
concept_validate(doc)
|
50
|
+
concept_validate(doc, "concept", "refterm")
|
51
|
+
concept_validate(doc, "related", "preferred//name")
|
44
52
|
@fatalerror.empty? or clean_abort(@fatalerror.join("\n"), doc.to_xml)
|
45
53
|
end
|
46
54
|
|
@@ -57,19 +65,20 @@ module Asciidoctor
|
|
57
65
|
found and @fatalerror << "Numeric reference in normative references"
|
58
66
|
end
|
59
67
|
|
60
|
-
def concept_validate(doc)
|
68
|
+
def concept_validate(doc, tag, refterm)
|
61
69
|
found = false
|
62
|
-
doc.xpath("
|
70
|
+
doc.xpath("//#{tag}/xref").each do |x|
|
63
71
|
next if doc.at("//term[@id = '#{x['target']}']")
|
64
72
|
next if doc.at("//definitions//dt[@id = '#{x['target']}']")
|
65
73
|
|
66
|
-
ref = x&.at("
|
74
|
+
ref = x&.at("../#{refterm}")&.text
|
67
75
|
@log.add("Anchors", x,
|
68
|
-
"
|
76
|
+
"#{tag.capitalize} #{ref} is pointing to "\
|
69
77
|
"#{x['target']}, which is not a term or symbol")
|
70
78
|
found = true
|
71
79
|
end
|
72
|
-
found and
|
80
|
+
found and
|
81
|
+
@fatalerror << "#{tag.capitalize} not cross-referencing term or symbol"
|
73
82
|
end
|
74
83
|
|
75
84
|
def repeat_id_validate1(ids, elem)
|
data/metanorma-standoc.gemspec
CHANGED
@@ -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.2.1"
|
31
|
-
spec.add_dependency "isodoc", "~> 1.
|
31
|
+
spec.add_dependency "isodoc", "~> 1.8.0"
|
32
32
|
spec.add_dependency "metanorma-plugin-datastruct"
|
33
33
|
spec.add_dependency "metanorma-plugin-lutaml"
|
34
34
|
spec.add_dependency "ruby-jing"
|
@@ -959,14 +959,15 @@ QU1FOiB0ZXN0Cgo=
|
|
959
959
|
|
960
960
|
it "process mn2pdf attributes" do
|
961
961
|
node = Nokogiri::XML("<fake/>").at("fake")
|
962
|
-
node[
|
962
|
+
node[Asciidoctor::Standoc::Base::FONTS_MANIFEST] =
|
963
|
+
"passed/as/font/manifest/to/mn2pdf.jar"
|
963
964
|
|
964
965
|
options = Asciidoctor::Standoc::Converter
|
965
966
|
.new(:standoc, header_footer: true)
|
966
967
|
.doc_extract_attributes(node)
|
967
968
|
|
968
|
-
expect(options.dig(:mn2pdf, :
|
969
|
-
.to eq(node[
|
969
|
+
expect(options.dig(:mn2pdf, :font_manifest))
|
970
|
+
.to eq(node[Asciidoctor::Standoc::Base::FONTS_MANIFEST])
|
970
971
|
end
|
971
972
|
|
972
973
|
private
|