metanorma-standoc 3.0.7 → 3.0.9
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/lib/isodoc/html/htmlstyle.css +0 -2
- data/lib/metanorma/standoc/anchor.rb +1 -1
- data/lib/metanorma/standoc/base.rb +1 -1
- data/lib/metanorma/standoc/basicdoc.rng +9 -5
- data/lib/metanorma/standoc/blocks.rb +8 -5
- data/lib/metanorma/standoc/blocks_image.rb +2 -6
- data/lib/metanorma/standoc/blocks_notes.rb +2 -6
- data/lib/metanorma/standoc/cleanup.rb +5 -1
- data/lib/metanorma/standoc/cleanup_amend.rb +6 -8
- data/lib/metanorma/standoc/cleanup_asciibib.rb +17 -13
- data/lib/metanorma/standoc/cleanup_bibdata.rb +19 -13
- data/lib/metanorma/standoc/cleanup_bibitem.rb +9 -6
- data/lib/metanorma/standoc/cleanup_block.rb +6 -6
- data/lib/metanorma/standoc/cleanup_boilerplate.rb +5 -4
- data/lib/metanorma/standoc/cleanup_footnotes.rb +2 -4
- data/lib/metanorma/standoc/cleanup_image.rb +3 -3
- data/lib/metanorma/standoc/cleanup_inline.rb +22 -47
- data/lib/metanorma/standoc/cleanup_review.rb +7 -5
- data/lib/metanorma/standoc/cleanup_section.rb +30 -5
- data/lib/metanorma/standoc/cleanup_table.rb +1 -2
- data/lib/metanorma/standoc/cleanup_terms.rb +1 -1
- data/lib/metanorma/standoc/cleanup_terms_designations.rb +1 -1
- data/lib/metanorma/standoc/cleanup_text.rb +5 -3
- data/lib/metanorma/standoc/cleanup_toc.rb +1 -1
- data/lib/metanorma/standoc/cleanup_xref.rb +1 -1
- data/lib/metanorma/standoc/converter.rb +15 -7
- data/lib/metanorma/standoc/init.rb +15 -7
- data/lib/metanorma/standoc/inline.rb +12 -7
- data/lib/metanorma/standoc/isodoc.rng +145 -5
- data/lib/metanorma/standoc/localbib.rb +1 -2
- data/lib/metanorma/standoc/macros.rb +0 -1
- data/lib/metanorma/standoc/macros_form.rb +21 -3
- data/lib/metanorma/standoc/macros_inline.rb +24 -1
- data/lib/metanorma/standoc/macros_link.rb +13 -5
- data/lib/metanorma/standoc/macros_plantuml.rb +28 -14
- data/lib/metanorma/standoc/ref.rb +2 -2
- data/lib/metanorma/standoc/ref_sect.rb +1 -1
- data/lib/metanorma/standoc/ref_utility.rb +4 -3
- data/lib/metanorma/standoc/section.rb +9 -10
- data/lib/metanorma/standoc/sectiontype.rb +28 -20
- data/lib/metanorma/standoc/table.rb +9 -13
- data/lib/metanorma/standoc/term_lookup_cleanup.rb +17 -9
- data/lib/metanorma/standoc/terms.rb +1 -1
- data/lib/metanorma/standoc/utils.rb +4 -0
- data/lib/metanorma/standoc/validate.rb +50 -23
- data/lib/metanorma/standoc/validate_schema.rb +2 -0
- data/lib/metanorma/standoc/validate_term.rb +8 -7
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +2 -3
- metadata +6 -20
@@ -4,9 +4,15 @@ module Metanorma
|
|
4
4
|
use_dsl
|
5
5
|
named :input
|
6
6
|
|
7
|
+
def map_attr_name(attr)
|
8
|
+
attr == "id" ? "anchor" : attr
|
9
|
+
end
|
10
|
+
|
7
11
|
def process(_parent, target, attr)
|
8
12
|
m = %w(id name value disabled readonly checked maxlength minlength)
|
9
|
-
.map { |a| attr[a] ? " #{a}='#{attr[a]}'" : nil }
|
13
|
+
.map { |a| attr[a] ? " #{map_attr_name(a)}='#{attr[a]}'" : nil }
|
14
|
+
.compact
|
15
|
+
m << " id='_#{UUIDTools::UUID.random_create}'"
|
10
16
|
%{<input type='#{target}' #{m.join}/>}
|
11
17
|
end
|
12
18
|
end
|
@@ -27,9 +33,15 @@ module Metanorma
|
|
27
33
|
named :textarea
|
28
34
|
using_format :short
|
29
35
|
|
36
|
+
def map_attr_name(attr)
|
37
|
+
attr == "id" ? "anchor" : attr
|
38
|
+
end
|
39
|
+
|
30
40
|
def process(_parent, _target, attr)
|
31
41
|
m = %w(id name rows cols value)
|
32
|
-
.map { |a| attr[a] ? " #{a}='#{attr[a]}'" : nil }
|
42
|
+
.map { |a| attr[a] ? " #{map_attr_name(a)}='#{attr[a]}'" : nil }
|
43
|
+
.compact
|
44
|
+
m << " id='_#{UUIDTools::UUID.random_create}'"
|
33
45
|
%{<textarea #{m.join}/>}
|
34
46
|
end
|
35
47
|
end
|
@@ -39,9 +51,15 @@ module Metanorma
|
|
39
51
|
named :select
|
40
52
|
using_format :short
|
41
53
|
|
54
|
+
def map_attr_name(attr)
|
55
|
+
attr == "id" ? "anchor" : attr
|
56
|
+
end
|
57
|
+
|
42
58
|
def process(parent, _target, attr)
|
43
59
|
m = %w(id name size disabled multiple value)
|
44
|
-
.map { |a| attr[a] ? " #{a}='#{attr[a]}'" : nil }
|
60
|
+
.map { |a| attr[a] ? " #{map_attr_name(a)}='#{attr[a]}'" : nil }
|
61
|
+
.compact
|
62
|
+
m << " id='_#{UUIDTools::UUID.random_create}'"
|
45
63
|
out = Asciidoctor::Inline.new(parent, :quoted, attr["text"]).convert
|
46
64
|
%{<select #{m.join}>#{out}</select>}
|
47
65
|
end
|
@@ -58,6 +58,30 @@ module Metanorma
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
class AnchorInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
62
|
+
use_dsl
|
63
|
+
named :anchor
|
64
|
+
parse_content_as :text
|
65
|
+
|
66
|
+
def process(parent, target, attrs)
|
67
|
+
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
|
68
|
+
id = "_#{UUIDTools::UUID.random_create}"
|
69
|
+
%{<span id='#{id}' anchor='#{target}'>#{out}</span>}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class SourceIdInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
74
|
+
use_dsl
|
75
|
+
named :"source-id"
|
76
|
+
parse_content_as :text
|
77
|
+
|
78
|
+
def process(parent, target, attrs)
|
79
|
+
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
|
80
|
+
id = "_#{UUIDTools::UUID.random_create}"
|
81
|
+
%{<span id='#{id}' source='#{target}'>#{out}</span>}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
61
85
|
class VariantInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
62
86
|
use_dsl
|
63
87
|
named :lang
|
@@ -117,7 +141,6 @@ module Metanorma
|
|
117
141
|
parse_content_as :text
|
118
142
|
|
119
143
|
def process(parent, target, attrs)
|
120
|
-
#require "debug"; binding.b
|
121
144
|
format = target || "metanorma"
|
122
145
|
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
|
123
146
|
.gsub(/((?![<>&])[[:punct:]])/, "\\1‌")
|
@@ -68,13 +68,21 @@ module Metanorma
|
|
68
68
|
|
69
69
|
def process(parent, _target, attrs)
|
70
70
|
t = attrs["text"]
|
71
|
-
t = if
|
71
|
+
t = if t.include?(",")
|
72
72
|
t.sub(/,/, "%")
|
73
|
-
else
|
74
|
-
"#{t}%"
|
73
|
+
else "#{t}%"
|
75
74
|
end
|
76
|
-
|
77
|
-
|
75
|
+
target = attrs["text"].sub(/,.*$/, "").gsub(":", "_") # special char
|
76
|
+
create_anchor(parent, "hidden=#{t}", type: :xref, target: target)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class SourceIncludeInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
81
|
+
use_dsl
|
82
|
+
named :source_include
|
83
|
+
|
84
|
+
def process(_parent, target, _attrs)
|
85
|
+
"<source-include path='#{target}'/>"
|
78
86
|
end
|
79
87
|
end
|
80
88
|
end
|
@@ -15,8 +15,13 @@ module Metanorma
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def self.run(umlfile, outfile)
|
19
|
-
|
18
|
+
def self.run(umlfile, outfile, fmt)
|
19
|
+
valid_formats = %w[png svg eps]
|
20
|
+
unless valid_formats.include?(fmt)
|
21
|
+
raise ArgumentError, "Invalid format: #{fmt}. Allowed formats are: #{valid_formats.join(', ')}"
|
22
|
+
end
|
23
|
+
system(plantuml_bin, umlfile.path, "-t#{fmt}") or
|
24
|
+
(warn $? and return false)
|
20
25
|
i = 0
|
21
26
|
until !Gem.win_platform? || File.exist?(outfile) || i == 15
|
22
27
|
sleep(1)
|
@@ -34,16 +39,24 @@ module Metanorma
|
|
34
39
|
# Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
|
35
40
|
# This is why we need to copy and then unlink.
|
36
41
|
def self.generate_file(parent, reader)
|
37
|
-
ldir =
|
38
|
-
|
39
|
-
umlfile, outfile
|
40
|
-
run(umlfile, outfile) or
|
42
|
+
ldir, imagesdir, fmt = generate_file_prep(parent)
|
43
|
+
umlfile, outfile = save_plantuml parent, reader, ldir, fmt
|
44
|
+
run(umlfile, outfile, fmt) or
|
41
45
|
raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
|
42
46
|
umlfile.unlink
|
43
|
-
|
47
|
+
absolute_path, relative_path = path_prep(ldir, imagesdir)
|
44
48
|
filename = File.basename(outfile.to_s)
|
45
|
-
FileUtils.cp(outfile,
|
46
|
-
imagesdir ? filename : File.join(path, filename)
|
49
|
+
FileUtils.cp(outfile, absolute_path) and outfile.unlink
|
50
|
+
#imagesdir ? filename : File.join(path, filename)
|
51
|
+
File.join(relative_path, filename)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.generate_file_prep(parent)
|
55
|
+
ldir = localdir(parent)
|
56
|
+
imagesdir = parent.document.attr("imagesdir")
|
57
|
+
fmt = parent.document.attr("plantuml-image-format")&.strip&.downcase ||
|
58
|
+
"png"
|
59
|
+
[ldir, imagesdir, fmt]
|
47
60
|
end
|
48
61
|
|
49
62
|
def self.localdir(parent)
|
@@ -54,21 +67,22 @@ module Metanorma
|
|
54
67
|
end
|
55
68
|
|
56
69
|
def self.path_prep(localdir, imagesdir)
|
57
|
-
path = Pathname.new(localdir) + (imagesdir || "plantuml")
|
70
|
+
#path = Pathname.new(localdir) + (imagesdir || "plantuml")
|
71
|
+
path = Pathname.new(File.join(localdir, "_plantuml_images"))
|
72
|
+
sourcepath = imagesdir ? File.join(localdir, imagesdir) : localdir
|
58
73
|
path.mkpath
|
59
74
|
File.writable?(path) or
|
60
75
|
raise "Destination path #{path} not writable for PlantUML!"
|
61
|
-
|
62
|
-
path
|
76
|
+
[path, Pathname.new(path).relative_path_from(Pathname.new(sourcepath)).to_s]
|
63
77
|
end
|
64
78
|
|
65
|
-
def self.save_plantuml(_parent, reader, _localdir)
|
79
|
+
def self.save_plantuml(_parent, reader, _localdir, fmt)
|
66
80
|
src = prep_source(reader)
|
67
81
|
/^@startuml (?<fn>[^\n]+)\n/ =~ src
|
68
82
|
Tempfile.open(["plantuml", ".pml"], encoding: "utf-8") do |f|
|
69
83
|
f.write(src)
|
70
84
|
[f, File.join(File.dirname(f.path),
|
71
|
-
"#{fn || File.basename(f.path, '.pml')}
|
85
|
+
"#{fn || File.basename(f.path, '.pml')}.#{fmt}")]
|
72
86
|
end
|
73
87
|
end
|
74
88
|
|
@@ -131,8 +131,8 @@ module Metanorma
|
|
131
131
|
|
132
132
|
def refitem_render(xml, match, code)
|
133
133
|
xml.bibitem **attr_code(
|
134
|
-
|
135
|
-
hidden: code[:hidden]
|
134
|
+
anchor: match[:anchor], suppress_identifier: code[:dropid],
|
135
|
+
hidden: code[:hidden], id: "_#{UUIDTools::UUID.random_create}"
|
136
136
|
) do |t|
|
137
137
|
refitem_render_formattedref(t, match[:text])
|
138
138
|
yr_match = refitem1yr(code[:id])
|
@@ -76,7 +76,7 @@ module Metanorma
|
|
76
76
|
@log.add("Bibliography", nil,
|
77
77
|
"ERROR: No title retrieved for #{code}")
|
78
78
|
!fmt and
|
79
|
-
|
79
|
+
xml.root << "<title>#{title || '(MISSING TITLE)'}</title>"
|
80
80
|
end
|
81
81
|
fmt and xml.root << "<formattedref>#{title}</formattedref>"
|
82
82
|
end
|
@@ -32,7 +32,8 @@ module Metanorma
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def use_my_anchor(ref, id, opt)
|
35
|
-
ref.parent.elements.last["
|
35
|
+
ref.parent.elements.last["anchor"] = id
|
36
|
+
add_id(ref.parent.elements.last)
|
36
37
|
a = opt[:hidden] and ref.parent.elements.last["hidden"] = a
|
37
38
|
a = opt[:dropid] and
|
38
39
|
ref.parent.elements.last["suppress_identifier"] = a
|
@@ -195,8 +196,8 @@ module Metanorma
|
|
195
196
|
|
196
197
|
def ref_attributes(match)
|
197
198
|
code = analyse_ref_code(match[:code])
|
198
|
-
|
199
|
-
|
199
|
+
{ anchor: match[:anchor], id: "_#{UUIDTools::UUID.random_create}",
|
200
|
+
type: "standard",
|
200
201
|
suppress_identifier: code[:dropid] || nil }
|
201
202
|
end
|
202
203
|
|
@@ -11,13 +11,12 @@ module Metanorma
|
|
11
11
|
@norm_ref = false
|
12
12
|
|
13
13
|
def section_attributes(node)
|
14
|
-
ret =
|
15
|
-
{
|
16
|
-
unnumbered: node.option?("unnumbered") ? "true" : nil,
|
17
|
-
annex: role_style(node, "appendix") && node.level == 1 ? true : nil,
|
14
|
+
ret = id_unnum_attrs(node).merge(
|
15
|
+
{ annex: role_style(node, "appendix") && node.level == 1 ? true : nil,
|
18
16
|
colophon: role_style(node, "colophon") ? true : nil,
|
19
|
-
preface: role_style(node, "preface") ? true : nil }
|
20
|
-
|
17
|
+
preface: role_style(node, "preface") ? true : nil },
|
18
|
+
)
|
19
|
+
%w(language script branch-number type tag keeptitle
|
21
20
|
multilingual-rendering).each do |k|
|
22
21
|
a = node.attr(k) and ret[k.to_sym] = a
|
23
22
|
end
|
@@ -36,8 +35,8 @@ module Metanorma
|
|
36
35
|
a = section_attributes(node)
|
37
36
|
noko do |xml|
|
38
37
|
case sectiontype(node)
|
39
|
-
when "
|
40
|
-
|
38
|
+
when "metanorma-extension"
|
39
|
+
metanorma_extension_parse(a, xml, node)
|
41
40
|
when "introduction" then introduction_parse(a, xml, node)
|
42
41
|
when "foreword" then foreword_parse(a, xml, node)
|
43
42
|
when "scope" then scope_parse(a, xml, node)
|
@@ -97,8 +96,8 @@ module Metanorma
|
|
97
96
|
end
|
98
97
|
end
|
99
98
|
|
100
|
-
def
|
101
|
-
xml.send :"
|
99
|
+
def metanorma_extension_parse(_attrs, xml, node)
|
100
|
+
xml.send :"metanorma-extension-clause" do |xml_section|
|
102
101
|
xml_section << node.content
|
103
102
|
end
|
104
103
|
end
|
@@ -14,7 +14,9 @@ module Metanorma
|
|
14
14
|
def sectiontype(node, level = true)
|
15
15
|
ret = sectiontype1(node)
|
16
16
|
ret1 = preface_main_filter(sectiontype_streamline(ret), node)
|
17
|
-
|
17
|
+
# permit multiple instances
|
18
|
+
["symbols and abbreviated terms",
|
19
|
+
"metanorma-extension"].include?(ret1) and return ret1
|
18
20
|
!level || node.level == 1 || node.attr("heading") or return nil
|
19
21
|
!node.attr("heading") && @seen_headers.include?(ret) and return nil
|
20
22
|
@seen_headers << ret unless ret1.nil?
|
@@ -22,31 +24,37 @@ module Metanorma
|
|
22
24
|
ret1
|
23
25
|
end
|
24
26
|
|
27
|
+
SECTIONTYPE_STREAMLINE =
|
28
|
+
{ "terms and definitions":
|
29
|
+
["terms, definitions, symbols and abbreviated terms",
|
30
|
+
"terms, definitions, symbols and abbreviations",
|
31
|
+
"terms, definitions and symbols",
|
32
|
+
"terms, definitions and abbreviations",
|
33
|
+
"terms, definitions and abbreviated terms",
|
34
|
+
"terms and definitions"],
|
35
|
+
"symbols and abbreviated terms":
|
36
|
+
["symbols and abbreviated terms",
|
37
|
+
"symbols", "abbreviated terms", "abbreviations",
|
38
|
+
"symbols and abbreviations",
|
39
|
+
"symbols and abbreviated terms"],
|
40
|
+
"acknowledgements":
|
41
|
+
["acknowledgements", "acknowledgments"],
|
42
|
+
"executivesummary":
|
43
|
+
["executive summary", "executive-summary",
|
44
|
+
"executive_summary"],
|
45
|
+
"metanorma-extension":
|
46
|
+
["misc-container", "metanorma-extension"] }.freeze
|
47
|
+
|
25
48
|
def sectiontype_streamline(ret)
|
26
|
-
|
27
|
-
|
28
|
-
"terms, definitions, symbols and abbreviated terms",
|
29
|
-
"terms, definitions, symbols and abbreviations",
|
30
|
-
"terms, definitions and symbols",
|
31
|
-
"terms, definitions and abbreviations",
|
32
|
-
"terms, definitions and abbreviated terms"
|
33
|
-
"terms and definitions"
|
34
|
-
when "symbols and abbreviated terms",
|
35
|
-
"symbols", "abbreviated terms", "abbreviations",
|
36
|
-
"symbols and abbreviations"
|
37
|
-
"symbols and abbreviated terms"
|
38
|
-
when "acknowledgements", "acknowledgments"
|
39
|
-
"acknowledgements"
|
40
|
-
when "executive summary", "executive-summary", "executive_summary"
|
41
|
-
"executivesummary"
|
42
|
-
else
|
43
|
-
ret
|
49
|
+
SECTIONTYPE_STREAMLINE.each do |k, v|
|
50
|
+
v.include?(ret) and return k.to_s
|
44
51
|
end
|
52
|
+
ret
|
45
53
|
end
|
46
54
|
|
47
55
|
PREFACE_CLAUSE_NAMES =
|
48
56
|
%w(abstract foreword introduction metanorma-extension termdocsource
|
49
|
-
|
57
|
+
metanorma-extension acknowledgements executivesummary)
|
50
58
|
.freeze
|
51
59
|
|
52
60
|
MAIN_CLAUSE_NAMES =
|
@@ -3,11 +3,8 @@ module Metanorma
|
|
3
3
|
module Table
|
4
4
|
def table_attrs(node)
|
5
5
|
keep_attrs(node)
|
6
|
-
.merge(
|
7
|
-
|
8
|
-
unnumbered: node.option?("unnumbered") ? "true" : nil,
|
9
|
-
number: node.attr("number"),
|
10
|
-
subsequence: node.attr("subsequence"),
|
6
|
+
.merge(id_unnum_attrs(node))
|
7
|
+
.merge(headerrows: node.attr("headerrows"),
|
11
8
|
alt: node.attr("alt"),
|
12
9
|
summary: node.attr("summary"),
|
13
10
|
width: node.attr("width"))
|
@@ -28,11 +25,9 @@ module Metanorma
|
|
28
25
|
private
|
29
26
|
|
30
27
|
def colgroup(node, xml_table)
|
31
|
-
|
32
|
-
|
33
|
-
cols
|
34
|
-
return unless (cols.size > 1) && cols.all? { |c| /\d/.match(c) }
|
35
|
-
|
28
|
+
node.option? "autowidth" and return
|
29
|
+
cols = node.attr("cols")&.split(",") or return
|
30
|
+
(cols.size > 1) && cols.all? { |c| /\d/.match(c) } or return
|
36
31
|
xml_table.colgroup do |cg|
|
37
32
|
node.columns.each do |col|
|
38
33
|
cg.col width: "#{col.attr 'colpcwidth'}%"
|
@@ -57,9 +52,10 @@ module Metanorma
|
|
57
52
|
end
|
58
53
|
|
59
54
|
def table_cell(node, xml_tr, tblsec)
|
60
|
-
cell_attributes =
|
61
|
-
{
|
62
|
-
rowspan: node.rowspan, align: node.attr("halign") }
|
55
|
+
cell_attributes = id_attr(node).merge(
|
56
|
+
{ colspan: node.colspan, valign: node.attr("valign"),
|
57
|
+
rowspan: node.rowspan, align: node.attr("halign") },
|
58
|
+
)
|
63
59
|
cell_tag = "td"
|
64
60
|
cell_tag = "th" if tblsec == :head || node.style == :header
|
65
61
|
xml_tr.send cell_tag, **attr_code(cell_attributes) do |thd|
|
@@ -16,7 +16,7 @@ module Metanorma
|
|
16
16
|
@unique_designs = {}
|
17
17
|
@c = HTMLEntities.new
|
18
18
|
@terms_tags = xmldoc.xpath("//terms").each_with_object({}) do |t, m|
|
19
|
-
m[t["
|
19
|
+
m[t["anchor"]] = true
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -29,6 +29,7 @@ module Metanorma
|
|
29
29
|
related_cleanup
|
30
30
|
remove_missing_refs
|
31
31
|
concept_cleanup2
|
32
|
+
anchor_to_id
|
32
33
|
end
|
33
34
|
|
34
35
|
private
|
@@ -36,7 +37,7 @@ module Metanorma
|
|
36
37
|
def unique_designators
|
37
38
|
ret = xmldoc
|
38
39
|
.xpath("//preferred/expression/name | //admitted/expression/name | " \
|
39
|
-
"//
|
40
|
+
"//deprecates/expression/name").each_with_object({}) do |n, m|
|
40
41
|
m[n.text] ||= 0
|
41
42
|
m[n.text] += 1
|
42
43
|
end
|
@@ -69,9 +70,9 @@ module Metanorma
|
|
69
70
|
end
|
70
71
|
|
71
72
|
def populate_idhash
|
72
|
-
xmldoc.xpath("//*[@
|
73
|
-
/^(term|symbol)-/.match?(n["
|
74
|
-
mem[n["
|
73
|
+
xmldoc.xpath("//*[@anchor]").each_with_object({}) do |n, mem|
|
74
|
+
/^(term|symbol)-/.match?(n["anchor"]) or next
|
75
|
+
mem[n["anchor"]] = true
|
75
76
|
end
|
76
77
|
end
|
77
78
|
|
@@ -207,18 +208,18 @@ module Metanorma
|
|
207
208
|
|
208
209
|
def norm_id_memorize_init(node, res_table, selector, prefix, use_domain)
|
209
210
|
term_text = norm_ref_id(node, selector, use_domain) or return
|
210
|
-
unless AUTO_GEN_ID_REGEXP.match(node["
|
211
|
+
unless AUTO_GEN_ID_REGEXP.match(node["anchor"]).nil? && !node["anchor"].nil?
|
211
212
|
id = unique_text_id(term_text, prefix)
|
212
|
-
node["
|
213
|
+
node["anchor"] = id
|
213
214
|
@idhash[id] = true
|
214
215
|
end
|
215
|
-
res_table[term_text] = node["
|
216
|
+
res_table[term_text] = node["anchor"]
|
216
217
|
end
|
217
218
|
|
218
219
|
def memorize_other_pref_terms(node, res_table, text_selector, use_domain)
|
219
220
|
node.xpath(text_selector).each_with_index do |p, i|
|
220
221
|
i.positive? or next
|
221
|
-
res_table[norm_ref_id1(p, use_domain ? node : nil)] = node["
|
222
|
+
res_table[norm_ref_id1(p, use_domain ? node : nil)] = node["anchor"]
|
222
223
|
end
|
223
224
|
end
|
224
225
|
|
@@ -255,6 +256,13 @@ module Metanorma
|
|
255
256
|
end
|
256
257
|
end
|
257
258
|
|
259
|
+
def anchor_to_id
|
260
|
+
xmldoc.xpath("//*[@anchor]").each do |n|
|
261
|
+
/^(term|symbol)-/.match?(n["anchor"]) or next
|
262
|
+
n["id"] or add_id(n)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
258
266
|
include ::Metanorma::Standoc::Utils
|
259
267
|
end
|
260
268
|
end
|
@@ -157,7 +157,7 @@ module Metanorma
|
|
157
157
|
def termsource(node)
|
158
158
|
matched = extract_termsource_refs(node.content, node) or return
|
159
159
|
noko do |xml|
|
160
|
-
xml.
|
160
|
+
xml.source **termsource_attrs(node, matched) do |xml_t|
|
161
161
|
seen_xref = Nokogiri::XML.fragment(matched[:xref])
|
162
162
|
add_term_source(node, xml_t, seen_xref, matched)
|
163
163
|
end
|
@@ -35,6 +35,10 @@ module Metanorma
|
|
35
35
|
Metanorma::Utils::attr_code(attributes)
|
36
36
|
end
|
37
37
|
|
38
|
+
def add_id(node)
|
39
|
+
node["id"] = "_#{UUIDTools::UUID.random_create}"
|
40
|
+
end
|
41
|
+
|
38
42
|
def csv_split(text, delim = ";")
|
39
43
|
Metanorma::Utils::csv_split(@c.decode(text), delim)
|
40
44
|
.map { |x| @c.encode(x, :basic, :hexadecimal) }
|
@@ -12,7 +12,7 @@ module Metanorma
|
|
12
12
|
module Validate
|
13
13
|
def content_validate(doc)
|
14
14
|
@doctype = doc.at("//bibdata/ext/doctype")&.text
|
15
|
-
repeat_id_validate(doc.root) # feeds xref_validate
|
15
|
+
repeat_id_validate(doc.root) # feeds xref_validate, termsect_validate
|
16
16
|
xref_validate(doc) # feeds nested_asset_validate
|
17
17
|
nested_asset_validate(doc)
|
18
18
|
section_validate(doc)
|
@@ -92,7 +92,7 @@ module Metanorma
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def nested_asset_xref_report(outer, inner, _doc)
|
95
|
-
i = @doc_xrefs[inner["
|
95
|
+
i = @doc_xrefs[inner["anchor"]] or return
|
96
96
|
err2 = "There is a crossreference to an instance of #{inner.name} " \
|
97
97
|
"nested within #{outer.name}: #{i.to_xml}"
|
98
98
|
@log.add("Style", i, err2)
|
@@ -158,37 +158,63 @@ module Metanorma
|
|
158
158
|
schema_validate(formattedstr_strip(doc.dup), schema_location)
|
159
159
|
end
|
160
160
|
|
161
|
+
# Check should never happen with content ids, but will check it anyway
|
162
|
+
# since consequences are so catastrophic
|
161
163
|
def repeat_id_validate1(elem)
|
162
164
|
if @doc_ids[elem["id"]]
|
163
165
|
@log.add("Anchors", elem,
|
164
|
-
"
|
165
|
-
"used at line #{@doc_ids[elem['id']]}", severity: 0)
|
166
|
+
"ID #{elem['id']} has already been " \
|
167
|
+
"used at line #{@doc_ids[elem['id']][:line]}", severity: 0)
|
166
168
|
else
|
167
|
-
@doc_ids[elem["id"]] =
|
169
|
+
@doc_ids[elem["id"]] =
|
170
|
+
{ line: elem.line, anchor: elem["anchor"] }.compact
|
168
171
|
end
|
169
172
|
end
|
170
173
|
|
174
|
+
def repeat_anchor_validate1(elem)
|
175
|
+
if @doc_anchors[elem["anchor"]]
|
176
|
+
@log.add("Anchors", elem,
|
177
|
+
"Anchor #{elem['anchor']} has already been used at line " \
|
178
|
+
"#{@doc_anchors[elem['anchor']][:line]}", severity: 0)
|
179
|
+
else
|
180
|
+
@doc_anchors[elem["anchor"]] = { line: elem.line, id: elem["id"] }
|
181
|
+
@doc_anchor_seq << elem["anchor"]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Check should never happen with content ids, but will check it anyway
|
171
186
|
def repeat_id_validate(doc)
|
172
|
-
|
173
|
-
@doc_id_seq = [] # ordered list of all ids in document
|
187
|
+
repeat_id_validate_prep
|
174
188
|
doc.xpath("//*[@id]").each do |x|
|
175
189
|
@doc_id_seq << x["id"]
|
176
190
|
repeat_id_validate1(x)
|
191
|
+
x["anchor"] and repeat_anchor_validate1(x)
|
177
192
|
end
|
178
|
-
@doc_id_seq.
|
193
|
+
@doc_id_seq_hash = @doc_id_seq.each_with_index
|
194
|
+
.with_object({}) do |(x, i), m|
|
195
|
+
m[x] = i
|
196
|
+
end
|
197
|
+
@doc_anchor_seq_hash = @doc_anchor_seq.each_with_index
|
198
|
+
.with_object({}) do |(x, i), m|
|
199
|
+
m[x] = i
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def repeat_id_validate_prep
|
204
|
+
@doc_ids = {} # hash of all ids in document to line number, anchor
|
205
|
+
@doc_anchors = {} # hash of all anchors in document to line number, id
|
206
|
+
@doc_id_seq = [] # ordered list of all ids in document
|
207
|
+
@doc_anchor_seq = [] # ordered list of all anchors in document
|
179
208
|
end
|
180
209
|
|
181
|
-
# Retrieve
|
210
|
+
# Retrieve anchors between two nominated values
|
182
211
|
# (exclusive of start_id AND exclusive of end_id)
|
183
|
-
def
|
184
|
-
start_index = @
|
185
|
-
end_index = @
|
186
|
-
|
187
|
-
start_index.nil? and return []
|
188
|
-
# end_id is greater than all elements
|
189
|
-
end_index.nil? and end_index = @doc_id_seq.length
|
212
|
+
def get_anchors_between(start_id, end_id)
|
213
|
+
start_index = @doc_anchor_seq_hash[start_id]
|
214
|
+
end_index = @doc_anchor_seq_hash[end_id]
|
215
|
+
start_index.nil? || end_index.nil? and return []
|
190
216
|
start_index >= end_index and return []
|
191
|
-
@
|
217
|
+
@doc_anchor_seq[start_index...end_index]
|
192
218
|
end
|
193
219
|
|
194
220
|
# manually check for xref/@target et sim. integrity
|
@@ -198,14 +224,15 @@ module Metanorma
|
|
198
224
|
end
|
199
225
|
|
200
226
|
def xref_validate_exists(doc)
|
201
|
-
@doc_xrefs =
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
@
|
227
|
+
@doc_xrefs = {}
|
228
|
+
Metanorma::Utils::anchor_attributes.each do |a|
|
229
|
+
doc.xpath("//#{a[0]}/@#{a[1]}").each do |x|
|
230
|
+
@doc_xrefs[x.text] = x.parent
|
231
|
+
@doc_anchors[x.text] and next
|
206
232
|
@log.add("Anchors", x.parent,
|
207
233
|
"Crossreference target #{x} is undefined", severity: 1)
|
208
234
|
end
|
235
|
+
end
|
209
236
|
end
|
210
237
|
|
211
238
|
# If there is an xref range, record the IDs between the two targets
|
@@ -220,7 +247,7 @@ module Metanorma
|
|
220
247
|
from = to_location.previous_element
|
221
248
|
from && from.name == "location" or return
|
222
249
|
from["target"] && to_location["target"] or return
|
223
|
-
|
250
|
+
get_anchors_between(from["target"], to_location["target"])
|
224
251
|
.each { |id| @doc_xrefs[id] = from }
|
225
252
|
end
|
226
253
|
end
|