metanorma-standoc 1.10.6 → 1.11.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.adoc +19 -23
- data/Rakefile +1 -1
- data/lib/asciidoctor/standoc/base.rb +10 -17
- data/lib/asciidoctor/standoc/basicdoc.rng +21 -4
- data/lib/asciidoctor/standoc/blocks.rb +23 -23
- data/lib/asciidoctor/standoc/blocks_notes.rb +17 -22
- data/lib/asciidoctor/standoc/cleanup.rb +46 -12
- data/lib/asciidoctor/standoc/cleanup_block.rb +3 -71
- data/lib/asciidoctor/standoc/cleanup_image.rb +6 -7
- data/lib/asciidoctor/standoc/cleanup_inline.rb +42 -106
- data/lib/asciidoctor/standoc/cleanup_maths.rb +5 -6
- data/lib/asciidoctor/standoc/cleanup_ref.rb +5 -0
- data/lib/asciidoctor/standoc/cleanup_reqt.rb +5 -24
- data/lib/asciidoctor/standoc/cleanup_section_names.rb +5 -5
- data/lib/asciidoctor/standoc/cleanup_symbols.rb +48 -0
- data/lib/asciidoctor/standoc/cleanup_table.rb +68 -0
- data/lib/asciidoctor/standoc/cleanup_terms.rb +37 -77
- data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +162 -0
- data/lib/asciidoctor/standoc/cleanup_text.rb +5 -2
- data/lib/asciidoctor/standoc/cleanup_xref.rb +107 -0
- data/lib/asciidoctor/standoc/converter.rb +14 -0
- data/lib/asciidoctor/standoc/inline.rb +7 -5
- data/lib/asciidoctor/standoc/isodoc.rng +419 -77
- data/lib/asciidoctor/standoc/lists.rb +15 -15
- data/lib/asciidoctor/standoc/macros.rb +14 -43
- data/lib/asciidoctor/standoc/macros_note.rb +45 -0
- data/lib/asciidoctor/standoc/macros_plantuml.rb +29 -14
- data/lib/asciidoctor/standoc/macros_terms.rb +55 -8
- data/lib/asciidoctor/standoc/ref_sect.rb +26 -18
- data/lib/asciidoctor/standoc/reqt.rng +23 -2
- 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 +45 -27
- data/lib/asciidoctor/standoc/validate_section.rb +5 -2
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +1 -1
- data/spec/asciidoctor/base_spec.rb +4 -36
- data/spec/asciidoctor/blank_spec.rb +37 -0
- data/spec/asciidoctor/blocks_spec.rb +208 -49
- data/spec/asciidoctor/cleanup_sections_spec.rb +153 -12
- data/spec/asciidoctor/cleanup_spec.rb +104 -285
- data/spec/asciidoctor/cleanup_terms_spec.rb +990 -0
- data/spec/asciidoctor/inline_spec.rb +38 -2
- data/spec/asciidoctor/lists_spec.rb +6 -6
- data/spec/asciidoctor/macros_plantuml_spec.rb +37 -2
- data/spec/asciidoctor/macros_spec.rb +191 -114
- data/spec/asciidoctor/refs_spec.rb +12 -30
- data/spec/asciidoctor/section_spec.rb +18 -18
- data/spec/asciidoctor/validate_spec.rb +87 -2
- data/spec/fixtures/datamodel_description_sections_tree.xml +3 -2
- data/spec/spec_helper.rb +6 -7
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +51 -51
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +13 -13
- data/spec/vcr_cassettes/isobib_get_123.yml +13 -13
- data/spec/vcr_cassettes/isobib_get_123_1.yml +26 -26
- data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +34 -34
- 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 +16 -16
- data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +51 -49
- metadata +12 -5
@@ -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,8 +7,8 @@ require "iev"
|
|
7
7
|
module Asciidoctor
|
8
8
|
module Standoc
|
9
9
|
module Validate
|
10
|
-
SOURCELOCALITY = "./
|
11
|
-
|
10
|
+
SOURCELOCALITY = "./origin//locality[@type = 'clause']/"\
|
11
|
+
"referenceFrom".freeze
|
12
12
|
|
13
13
|
def init_iev
|
14
14
|
return nil if @no_isobib
|
@@ -21,24 +21,35 @@ 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)
|
44
|
+
@fatalerror = []
|
45
|
+
xref_validate(doc)
|
37
46
|
section_validate(doc)
|
38
47
|
norm_ref_validate(doc)
|
39
48
|
repeat_id_validate(doc.root)
|
40
49
|
iev_validate(doc.root)
|
41
|
-
concept_validate(doc)
|
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)
|
42
53
|
end
|
43
54
|
|
44
55
|
def norm_ref_validate(doc)
|
@@ -51,30 +62,30 @@ module Asciidoctor
|
|
51
62
|
"Numeric reference in normative references")
|
52
63
|
found = true
|
53
64
|
end
|
54
|
-
found and
|
55
|
-
clean_abort("Numeric reference in normative references", doc.to_xml)
|
65
|
+
found and @fatalerror << "Numeric reference in normative references"
|
56
66
|
end
|
57
67
|
|
58
|
-
def concept_validate(doc)
|
68
|
+
def concept_validate(doc, tag, refterm)
|
59
69
|
found = false
|
60
|
-
doc.xpath("
|
70
|
+
doc.xpath("//#{tag}/xref").each do |x|
|
61
71
|
next if doc.at("//term[@id = '#{x['target']}']")
|
62
72
|
next if doc.at("//definitions//dt[@id = '#{x['target']}']")
|
63
73
|
|
64
|
-
ref = x&.at("
|
65
|
-
@log.add("Anchors", x,
|
74
|
+
ref = x&.at("../#{refterm}")&.text
|
75
|
+
@log.add("Anchors", x,
|
76
|
+
"#{tag.capitalize} #{ref} is pointing to "\
|
66
77
|
"#{x['target']}, which is not a term or symbol")
|
67
78
|
found = true
|
68
79
|
end
|
69
|
-
found and
|
70
|
-
|
80
|
+
found and
|
81
|
+
@fatalerror << "#{tag.capitalize} not cross-referencing term or symbol"
|
71
82
|
end
|
72
83
|
|
73
84
|
def repeat_id_validate1(ids, elem)
|
74
85
|
if ids[elem["id"]]
|
75
86
|
@log.add("Anchors", elem, "Anchor #{elem['id']} has already been "\
|
76
|
-
|
77
|
-
|
87
|
+
"used at line #{ids[elem['id']]}")
|
88
|
+
@fatalerror << "Multiple instances of same ID: #{elem['id']}"
|
78
89
|
else
|
79
90
|
ids[elem["id"]] = elem.line
|
80
91
|
end
|
@@ -83,12 +94,8 @@ module Asciidoctor
|
|
83
94
|
|
84
95
|
def repeat_id_validate(doc)
|
85
96
|
ids = {}
|
86
|
-
|
87
|
-
|
88
|
-
ids = repeat_id_validate1(ids, x)
|
89
|
-
end
|
90
|
-
rescue StandardError => e
|
91
|
-
clean_abort(e.message, doc.to_xml)
|
97
|
+
doc.xpath("//*[@id]").each do |x|
|
98
|
+
ids = repeat_id_validate1(ids, x)
|
92
99
|
end
|
93
100
|
end
|
94
101
|
|
@@ -130,6 +137,17 @@ module Asciidoctor
|
|
130
137
|
doc
|
131
138
|
end
|
132
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
|
+
|
133
151
|
def validate(doc)
|
134
152
|
content_validate(doc)
|
135
153
|
schema_validate(formattedstr_strip(doc.dup),
|
@@ -14,7 +14,8 @@ module Asciidoctor
|
|
14
14
|
callouts = x.elements.select { |e| e.name == "callout" }
|
15
15
|
annotations = x.elements.select { |e| e.name == "annotation" }
|
16
16
|
if callouts.size != annotations.size
|
17
|
-
|
17
|
+
@log.add("AsciiDoc Input", x,
|
18
|
+
"mismatch of callouts and annotations")
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
@@ -42,7 +43,9 @@ module Asciidoctor
|
|
42
43
|
root.xpath("//clause | //annex | //foreword | //introduction | "\
|
43
44
|
"//acknowledgements").each do |c|
|
44
45
|
next unless c.at("./clause")
|
45
|
-
next if c.elements.reject
|
46
|
+
next if c.elements.reject do |n|
|
47
|
+
%w(clause title).include? n.name
|
48
|
+
end.empty?
|
46
49
|
|
47
50
|
style_warning(c, "Hanging paragraph in clause")
|
48
51
|
end
|
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"
|
@@ -6,39 +6,6 @@ RSpec.describe Asciidoctor::Standoc do
|
|
6
6
|
expect(Metanorma::Standoc::VERSION).not_to be nil
|
7
7
|
end
|
8
8
|
|
9
|
-
it "processes a blank document" do
|
10
|
-
input = <<~INPUT
|
11
|
-
#{ASCIIDOC_BLANK_HDR}
|
12
|
-
INPUT
|
13
|
-
output = <<~OUTPUT
|
14
|
-
#{BLANK_HDR}
|
15
|
-
<sections/>
|
16
|
-
</standard-document>
|
17
|
-
OUTPUT
|
18
|
-
expect(xmlpp(Asciidoctor.convert(input, *OPTIONS)))
|
19
|
-
.to be_equivalent_to xmlpp(output)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "converts a blank document" do
|
23
|
-
FileUtils.rm_f "test.doc"
|
24
|
-
input = <<~INPUT
|
25
|
-
= Document title
|
26
|
-
Author
|
27
|
-
:docfile: test.adoc
|
28
|
-
:novalid:
|
29
|
-
INPUT
|
30
|
-
output = <<~OUTPUT
|
31
|
-
#{BLANK_HDR}
|
32
|
-
<sections/>
|
33
|
-
</standard-document>
|
34
|
-
OUTPUT
|
35
|
-
expect(xmlpp(Asciidoctor.convert(input, *OPTIONS)))
|
36
|
-
.to be_equivalent_to xmlpp(output)
|
37
|
-
expect(File.exist?("test.doc")).to be true
|
38
|
-
expect(File.exist?("test.pdf")).to be true
|
39
|
-
expect(File.exist?("htmlstyle.css")).to be false
|
40
|
-
end
|
41
|
-
|
42
9
|
it "assigns default scripts to major languages" do
|
43
10
|
FileUtils.rm_f "test.doc"
|
44
11
|
input = <<~INPUT
|
@@ -992,14 +959,15 @@ QU1FOiB0ZXN0Cgo=
|
|
992
959
|
|
993
960
|
it "process mn2pdf attributes" do
|
994
961
|
node = Nokogiri::XML("<fake/>").at("fake")
|
995
|
-
node[
|
962
|
+
node[Asciidoctor::Standoc::Base::FONTS_MANIFEST] =
|
963
|
+
"passed/as/font/manifest/to/mn2pdf.jar"
|
996
964
|
|
997
965
|
options = Asciidoctor::Standoc::Converter
|
998
966
|
.new(:standoc, header_footer: true)
|
999
967
|
.doc_extract_attributes(node)
|
1000
968
|
|
1001
|
-
expect(options.dig(:mn2pdf, :
|
1002
|
-
.to eq(node[
|
969
|
+
expect(options.dig(:mn2pdf, :font_manifest))
|
970
|
+
.to eq(node[Asciidoctor::Standoc::Base::FONTS_MANIFEST])
|
1003
971
|
end
|
1004
972
|
|
1005
973
|
private
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
RSpec.describe Asciidoctor::Standoc do
|
5
|
+
it "processes a blank document" do
|
6
|
+
input = <<~INPUT
|
7
|
+
#{ASCIIDOC_BLANK_HDR}
|
8
|
+
INPUT
|
9
|
+
output = <<~OUTPUT
|
10
|
+
#{BLANK_HDR}
|
11
|
+
<sections/>
|
12
|
+
</standard-document>
|
13
|
+
OUTPUT
|
14
|
+
expect(xmlpp(Asciidoctor.convert(input, *OPTIONS)))
|
15
|
+
.to be_equivalent_to xmlpp(output)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "converts a blank document" do
|
19
|
+
FileUtils.rm_f "test.doc"
|
20
|
+
input = <<~INPUT
|
21
|
+
= Document title
|
22
|
+
Author
|
23
|
+
:docfile: test.adoc
|
24
|
+
:novalid:
|
25
|
+
INPUT
|
26
|
+
output = <<~OUTPUT
|
27
|
+
#{BLANK_HDR}
|
28
|
+
<sections/>
|
29
|
+
</standard-document>
|
30
|
+
OUTPUT
|
31
|
+
expect(xmlpp(Asciidoctor.convert(input, *OPTIONS)))
|
32
|
+
.to be_equivalent_to xmlpp(output)
|
33
|
+
expect(File.exist?("test.doc")).to be true
|
34
|
+
expect(File.exist?("test.pdf")).to be true
|
35
|
+
expect(File.exist?("htmlstyle.css")).to be false
|
36
|
+
end
|
37
|
+
end
|