metanorma-standoc 3.0.15 → 3.1.1
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 +7 -1
- data/lib/metanorma/standoc/blocks_notes.rb +11 -14
- data/lib/metanorma/standoc/cleanup.rb +26 -18
- data/lib/metanorma/standoc/cleanup_block.rb +2 -2
- data/lib/metanorma/standoc/cleanup_boilerplate.rb +4 -14
- data/lib/metanorma/standoc/cleanup_maths.rb +3 -2
- data/lib/metanorma/standoc/cleanup_review.rb +2 -2
- data/lib/metanorma/standoc/cleanup_section_names.rb +12 -12
- data/lib/metanorma/standoc/cleanup_text.rb +3 -3
- data/lib/metanorma/standoc/converter.rb +1 -1
- data/lib/metanorma/standoc/front.rb +9 -1
- data/lib/metanorma/standoc/front_organisation.rb +1 -1
- data/lib/metanorma/standoc/inline.rb +20 -9
- data/lib/metanorma/standoc/isodoc.rng +51 -6
- data/lib/metanorma/standoc/lists.rb +2 -1
- data/lib/metanorma/standoc/macros.rb +7 -9
- data/lib/metanorma/standoc/macros_inline.rb +7 -25
- data/lib/metanorma/standoc/macros_note.rb +2 -0
- data/lib/metanorma/standoc/merge_bibitems.rb +17 -0
- data/lib/metanorma/standoc/table.rb +1 -0
- data/lib/metanorma/standoc/utils.rb +2 -0
- data/lib/metanorma/standoc/validate.rb +35 -57
- data/lib/metanorma/standoc/validate_image.rb +62 -0
- data/lib/metanorma/standoc/validate_section.rb +1 -1
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0a69974476cfd73fd74d1072ae10647b54c1c9f55d3cfb3d3cf9151a3f8be12
|
4
|
+
data.tar.gz: ed1cb04fdc539fafe18e87c4f7b173e9394644425b3791fa56bca4eb6935cd48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a2306e053d66020cfc017e973c30770eb00db604e12bcdccfdccd303fe2b8ddc2c87d7783067665b666e1db49c6c11044a29ae8420b5d72793c5363a9524d04
|
7
|
+
data.tar.gz: eda982b66f7f780b1d8ef7a7d48d5063154446792a5e5f50e5e3bd1470036896bba1d6f8060858a498f01d55a06c4d9f2b4c87fe8cbb67aec2bb1b6fffeee699
|
@@ -318,9 +318,15 @@ h6:hover > a.anchor,
|
|
318
318
|
padding: 0;
|
319
319
|
}
|
320
320
|
|
321
|
+
.svg-container {
|
322
|
+
width: 100%; /* or any desired width */
|
323
|
+
display: block; /* ← removes unwanted inline spacing */
|
324
|
+
}
|
325
|
+
|
321
326
|
svg {
|
322
327
|
width: 100%;
|
323
|
-
|
328
|
+
height: auto; /* ← key to maintaining aspect ratio */
|
329
|
+
display: block; /* ← removes unwanted inline spacing */
|
324
330
|
}
|
325
331
|
|
326
332
|
#standard-band {
|
@@ -14,36 +14,33 @@ module Metanorma
|
|
14
14
|
.merge(type: node.attr("type"))))
|
15
15
|
end
|
16
16
|
|
17
|
-
def sidebar_attrs(node)
|
18
|
-
todo_attrs(node).merge(
|
19
|
-
attr_code(
|
20
|
-
from: node.attr("from"),
|
21
|
-
to: node.attr("to") || node.attr("from"),
|
22
|
-
type: node.attr("type") || nil,
|
23
|
-
),
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
17
|
def sidebar(node)
|
28
18
|
noko do |xml|
|
29
|
-
xml.
|
19
|
+
xml.annotation **sidebar_attrs(node) do |r|
|
30
20
|
wrap_in_para(node, r)
|
31
21
|
end
|
32
22
|
end
|
33
23
|
end
|
34
24
|
|
35
|
-
def
|
25
|
+
def sidebar_attrs(node)
|
36
26
|
date = node.attr("date") || Date.today.iso8601.gsub(/\+.*$/, "")
|
37
27
|
date += "T00:00:00Z" unless date.include?("T")
|
38
28
|
attr_code(id_attr(node)
|
39
29
|
.merge(reviewer: node.attr("reviewer") || node.attr("source") ||
|
40
30
|
"(Unknown)",
|
41
|
-
|
31
|
+
from: node.attr("from"),
|
32
|
+
to: node.attr("to") || node.attr("from"),
|
33
|
+
type: node.attr("type") || "review",
|
34
|
+
date:))
|
35
|
+
end
|
36
|
+
|
37
|
+
def todo_attrs(node)
|
38
|
+
sidebar_attrs(node).merge(type: "todo")
|
42
39
|
end
|
43
40
|
|
44
41
|
def todo(node)
|
45
42
|
noko do |xml|
|
46
|
-
xml.
|
43
|
+
xml.annotation **todo_attrs(node) do |r|
|
47
44
|
wrap_in_para(node, r)
|
48
45
|
end
|
49
46
|
end
|
@@ -160,33 +160,41 @@ module Metanorma
|
|
160
160
|
|
161
161
|
def variant_cleanup(xmldoc)
|
162
162
|
variant_space_cleanup(xmldoc)
|
163
|
-
xmldoc.xpath("//*[variant]").each do |c|
|
164
|
-
|
165
|
-
|
163
|
+
xmldoc.xpath("//*[lang-variant]").each do |c|
|
164
|
+
if only_langvariant_children?(c)
|
165
|
+
duplicate_langvariants(c, c.xpath("./lang-variant"))
|
166
|
+
else
|
167
|
+
c.xpath(".//lang-variant").each { |x| x.name = "span" }
|
166
168
|
end
|
169
|
+
end
|
170
|
+
end
|
167
171
|
|
168
|
-
|
172
|
+
def only_langvariant_children?(node)
|
173
|
+
node.children.none? do |n|
|
174
|
+
n.name != "lang-variant" && (!n.text? || !n.text.strip.empty?)
|
169
175
|
end
|
170
|
-
xmldoc.xpath("//variantwrap").each { |n| n.name = "variant" }
|
171
176
|
end
|
172
177
|
|
173
|
-
def
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
else
|
180
|
-
n.replace("<variantwrap/>").first << n
|
181
|
-
end
|
178
|
+
def duplicate_langvariants(container, variants)
|
179
|
+
lang_variant_to_node(variants.first, container)
|
180
|
+
variants[1..].reverse.each do |node|
|
181
|
+
new = container.dup
|
182
|
+
lang_variant_to_node(node, new)
|
183
|
+
container.next = new
|
182
184
|
end
|
183
185
|
end
|
184
186
|
|
185
|
-
def
|
186
|
-
|
187
|
-
|
187
|
+
def lang_variant_to_node(variant, node)
|
188
|
+
node.children = variant.children
|
189
|
+
node["lang"] = variant["lang"]
|
190
|
+
node.delete("script")
|
191
|
+
variant["script"] and node["script"] = variant["script"]
|
192
|
+
end
|
188
193
|
|
189
|
-
|
194
|
+
def variant_space_cleanup(xmldoc)
|
195
|
+
xmldoc.xpath("//*[lang-variant]").each do |c|
|
196
|
+
c.next.nil? || c.next.next.nil? and next
|
197
|
+
if c.next.text? && c.next.next.name == "lang-variant"
|
190
198
|
c.next.text.gsub(/\s/, "").empty? and
|
191
199
|
c.next.remove
|
192
200
|
end
|
@@ -121,7 +121,7 @@ module Metanorma
|
|
121
121
|
def align_callouts_to_annotations(xmldoc)
|
122
122
|
xmldoc.xpath("//sourcecode").each do |x|
|
123
123
|
callouts = x.xpath("./body/callout")
|
124
|
-
annotations = x.xpath("./annotation")
|
124
|
+
annotations = x.xpath("./callout-annotation")
|
125
125
|
callouts.size == annotations.size and
|
126
126
|
link_callouts_to_annotations(callouts, annotations)
|
127
127
|
end
|
@@ -129,7 +129,7 @@ module Metanorma
|
|
129
129
|
|
130
130
|
def merge_annotations_into_sourcecode(xmldoc)
|
131
131
|
xmldoc.xpath("//sourcecode").each do |x|
|
132
|
-
while x.next_element&.name == "annotation"
|
132
|
+
while x.next_element&.name == "callout-annotation"
|
133
133
|
x.next_element.parent = x
|
134
134
|
end
|
135
135
|
end
|
@@ -48,8 +48,11 @@ module Metanorma
|
|
48
48
|
x = xmldoc.dup
|
49
49
|
x.root.add_namespace(nil, xml_namespace)
|
50
50
|
xml = Nokogiri::XML(x.to_xml)
|
51
|
+
#require "debug"; binding.b
|
51
52
|
@isodoc ||= isodoc(@lang, @script, @locale)
|
52
|
-
@isodoc.
|
53
|
+
# initialise @isodoc.xrefs, for @isodoc.xrefs.info
|
54
|
+
@isodoc.bibdata(xml) # do i18n
|
55
|
+
#@isodoc.info(xml, nil)
|
53
56
|
@isodoc
|
54
57
|
end
|
55
58
|
|
@@ -76,19 +79,6 @@ module Metanorma
|
|
76
79
|
initial_boilerplate(xmldoc, isodoc)
|
77
80
|
end
|
78
81
|
|
79
|
-
# KILL
|
80
|
-
# escape < > & to &gt; etc,
|
81
|
-
# for passthrough insertion into boilerplate
|
82
|
-
def boilerplate_isodoc_values(isodoc)
|
83
|
-
isodoc.meta.get.each do |k, v|
|
84
|
-
if v.is_a?(String)
|
85
|
-
isodoc.meta.set(k, v.gsub("&", "&&&&&&&")
|
86
|
-
.gsub("<", "&lt;").gsub(">", "&gt;")
|
87
|
-
.gsub("&&&&&&&", "&amp;"))
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
82
|
def initial_boilerplate(xml, isodoc)
|
93
83
|
xml.at("//boilerplate") and return
|
94
84
|
preface = xml.at("//preface | //sections | //annex | //references") or
|
@@ -19,6 +19,7 @@ module Metanorma
|
|
19
19
|
def asciimath2mathml_indiv(elem)
|
20
20
|
elem["type"] = "MathML"
|
21
21
|
expr = @c.decode(elem.text)
|
22
|
+
expr.strip.empty? and return
|
22
23
|
ret = asciimath_parse(expr, elem)&.strip
|
23
24
|
ret += "<asciimath>#{@c.encode(expr, :basic)}</asciimath>"
|
24
25
|
elem.children = ret
|
@@ -35,9 +36,9 @@ module Metanorma
|
|
35
36
|
<math xmlns='#{MATHML_NS}'><mstyle displaystyle='false'><mn>#{expr}</mn></mstyle></math>
|
36
37
|
MATH
|
37
38
|
else
|
39
|
+
expr.strip.empty? and return
|
38
40
|
unitsml = if expr.include?("unitsml")
|
39
|
-
{ unitsml: { xml: true,
|
40
|
-
multiplier: :space } }
|
41
|
+
{ unitsml: { xml: true, multiplier: :space } }
|
41
42
|
else {} end
|
42
43
|
Plurimath::Math.parse(expr, "asciimath")
|
43
44
|
.to_mathml(**{ display_style: elem["block"] }.merge(unitsml))
|
@@ -2,9 +2,9 @@ module Metanorma
|
|
2
2
|
module Standoc
|
3
3
|
module Cleanup
|
4
4
|
def review_cleanup(xmldoc)
|
5
|
-
reviews = xmldoc.xpath("//
|
5
|
+
reviews = xmldoc.xpath("//annotation")
|
6
6
|
reviews.empty? and return
|
7
|
-
ctr = xmldoc.root.add_child("<
|
7
|
+
ctr = xmldoc.root.add_child("<annotation-container/>").first
|
8
8
|
reviews.each do |r|
|
9
9
|
review_set_location(r)
|
10
10
|
ctr << r
|
@@ -123,28 +123,28 @@ module Metanorma
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
def terms_subclause_type_tally(node,
|
127
|
-
|
128
|
-
|
129
|
-
|
126
|
+
def terms_subclause_type_tally(node, acc, parent)
|
127
|
+
hasterm = node.at(".//term")
|
128
|
+
sym = if (hasterm && !node.at(".//definitions")) ||
|
129
|
+
(node.name == "terms" && !hasterm)
|
130
|
+
unless acc[:parent] == :term # don't count Term > Term twice
|
130
131
|
:term
|
131
132
|
end
|
132
|
-
elsif
|
133
|
-
elsif
|
134
|
-
elsif
|
135
|
-
elsif
|
133
|
+
elsif hasterm && node.at("./self::*#{SYMnoABBR}") then :tsna
|
134
|
+
elsif hasterm && node.at("./self::*#{ABBRnoSYM}") then :tans
|
135
|
+
elsif hasterm && node.at("./self::*#{SYMABBR}") then :tsa
|
136
|
+
elsif hasterm && node.at("./self::*#{NO_SYMABBR}") then :tnsa
|
136
137
|
elsif node.at("./self::*#{SYMnoABBR}") then :sna
|
137
138
|
elsif node.at("./self::*#{ABBRnoSYM}") then :ans
|
138
139
|
elsif node.at("./self::*#{SYMABBR}") then :sa
|
139
140
|
elsif node.at("./self::*#{NO_SYMABBR}") then :nsa
|
140
141
|
elsif node.name == "definitions" # ignore
|
141
|
-
elsif node == parent && node.at(".//
|
142
|
-
node.at(".//definitions")
|
142
|
+
elsif node == parent && hasterm && node.at(".//definitions")
|
143
143
|
:termdef
|
144
144
|
else :other
|
145
145
|
end
|
146
|
-
node == parent and
|
147
|
-
sym and
|
146
|
+
node == parent and acc[:parent] = sym
|
147
|
+
sym and acc[sym] += 1
|
148
148
|
end
|
149
149
|
|
150
150
|
def sections_variant_title_cleanup(xml)
|
@@ -107,7 +107,7 @@ module Metanorma
|
|
107
107
|
%w(pre sourcecode passthrough metanorma-extension stem).freeze
|
108
108
|
|
109
109
|
STRIP_LINEBREAK_ELEMENTS =
|
110
|
-
%w(title name variant-title figure example
|
110
|
+
%w(title name variant-title figure example annotation admonition
|
111
111
|
note li th td dt dd p quote label annotation
|
112
112
|
preferred admitted related deprecates field-of-application
|
113
113
|
usage-info expression pronunciation grammar-value domain
|
@@ -146,8 +146,8 @@ module Metanorma
|
|
146
146
|
quote label abstract preferred admitted related deprecates
|
147
147
|
field-of-application usage-info expression pronunciation
|
148
148
|
grammar-value domain definition termnote termexample modification
|
149
|
-
description newcontent floating-title tab
|
150
|
-
annotation).include? elem.name
|
149
|
+
description newcontent floating-title tab annotation admonition
|
150
|
+
callout-annotation).include? elem.name
|
151
151
|
end
|
152
152
|
|
153
153
|
def empty_tag_with_text_content?(elem)
|
@@ -56,7 +56,7 @@ module Metanorma
|
|
56
56
|
inline_macro Metanorma::Standoc::IdentifierInlineMacro
|
57
57
|
inline_macro Metanorma::Standoc::ConceptInlineMacro
|
58
58
|
inline_macro Metanorma::Standoc::AutonumberInlineMacro
|
59
|
-
inline_macro Metanorma::Standoc::
|
59
|
+
inline_macro Metanorma::Standoc::LangVariantInlineMacro
|
60
60
|
inline_macro Metanorma::Standoc::FootnoteBlockInlineMacro
|
61
61
|
inline_macro Metanorma::Standoc::TermRefInlineMacro
|
62
62
|
inline_macro Metanorma::Standoc::SymbolRefInlineMacro
|
@@ -30,13 +30,21 @@ module Metanorma
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def metadata_version(node, xml)
|
33
|
+
draft = metadata_version_value(node)
|
33
34
|
xml.edition node.attr("edition") if node.attr("edition")
|
34
35
|
xml.version do |v|
|
35
36
|
v.revision_date node.attr("revdate") if node.attr("revdate")
|
36
|
-
v.draft
|
37
|
+
v.draft draft if draft
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
41
|
+
def metadata_version_value(node)
|
42
|
+
draft = node.attr("version") and return draft
|
43
|
+
draft = node.attr("draft") or return nil
|
44
|
+
draft.empty? and return nil
|
45
|
+
draft
|
46
|
+
end
|
47
|
+
|
40
48
|
def metadata_status(node, xml)
|
41
49
|
xml.status do |s|
|
42
50
|
s.stage (node.attr("status") || node.attr("docstage") || "published")
|
@@ -134,29 +134,40 @@ module Metanorma
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
+
def image_mimetype(uri)
|
138
|
+
types = if /^data:/.match?(uri) then Vectory::Utils::datauri2mime(uri)
|
139
|
+
else MIME::Types.type_for(uri)
|
140
|
+
end
|
141
|
+
types.first.to_s
|
142
|
+
end
|
143
|
+
|
137
144
|
def image_attributes(node)
|
145
|
+
sourceuri = image_src_uri(node)
|
146
|
+
uri = sourceuri
|
147
|
+
type = image_mimetype(uri)
|
148
|
+
uri = uri.sub(%r{^data:image/\*;}, "data:#{type};")
|
149
|
+
image_attributes1(node, uri, sourceuri, type)
|
150
|
+
end
|
151
|
+
|
152
|
+
def image_src_uri(node)
|
138
153
|
nodetarget = node.attr("target") || node.target
|
139
154
|
if Gem.win_platform? && /^[a-zA-Z]:/.match?(nodetarget)
|
140
155
|
nodetarget.prepend("/")
|
141
156
|
end
|
142
|
-
uri = node.image_uri
|
157
|
+
uri = node.image_uri(nodetarget)
|
143
158
|
if Gem.win_platform? && /^\/[a-zA-Z]:/.match?(uri)
|
144
159
|
uri = uri[1..]
|
145
160
|
end
|
146
|
-
|
147
|
-
else MIME::Types.type_for(uri)
|
148
|
-
end
|
149
|
-
type = types.first.to_s
|
150
|
-
uri = uri.sub(%r{^data:image/\*;}, "data:#{type};")
|
151
|
-
image_attributes1(node, uri, type)
|
161
|
+
uri
|
152
162
|
end
|
153
163
|
|
154
|
-
def image_attributes1(node, uri, type)
|
164
|
+
def image_attributes1(node, uri, sourceuri, type)
|
165
|
+
/^data:/.match?(sourceuri) and sourceuri = nil
|
155
166
|
attr_code(id_attr(node)
|
156
167
|
.merge(src: uri, mimetype: type,
|
157
168
|
height: node.attr("height") || "auto",
|
158
169
|
width: node.attr("width") || "auto",
|
159
|
-
filename: node.attr("filename"),
|
170
|
+
filename: node.attr("filename") || sourceuri,
|
160
171
|
title: node.attr("titleattr"),
|
161
172
|
alt: node.alt == node.attr("default-alt") ? nil : node.alt))
|
162
173
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
|
3
|
-
<!-- VERSION v2.0.
|
3
|
+
<!-- VERSION v2.0.8 -->
|
4
4
|
|
5
5
|
<!--
|
6
6
|
ALERT: cannot have root comments, because of https://github.com/metanorma/metanorma/issues/437
|
@@ -72,6 +72,46 @@ but to `@anchor`, the user-supplied cross-reference</a:documentation>
|
|
72
72
|
</oneOrMore>
|
73
73
|
</element>
|
74
74
|
</define>
|
75
|
+
<define name="review">
|
76
|
+
<a:documentation>Generalise BasicDoc element from just review comments, to general annotations;
|
77
|
+
the type attribute defaults to `review` for reviews</a:documentation>
|
78
|
+
<element name="annotation">
|
79
|
+
<ref name="RequiredId"/>
|
80
|
+
<ref name="ReviewAttributes"/>
|
81
|
+
<oneOrMore>
|
82
|
+
<ref name="paragraph">
|
83
|
+
<a:documentation>Reviewer comments content</a:documentation>
|
84
|
+
</ref>
|
85
|
+
</oneOrMore>
|
86
|
+
</element>
|
87
|
+
</define>
|
88
|
+
<define name="ruby_pronunciation">
|
89
|
+
<a:documentation>Ruby annotation giving pronunciation of text: change tag from BasicDoc for disambiguation</a:documentation>
|
90
|
+
<element name="ruby-pronunciation">
|
91
|
+
<attribute name="value">
|
92
|
+
<a:documentation>Ruby annotation value</a:documentation>
|
93
|
+
</attribute>
|
94
|
+
<ref name="LocalizedStringAttributes"/>
|
95
|
+
</element>
|
96
|
+
</define>
|
97
|
+
<define name="ruby_annotation">
|
98
|
+
<a:documentation>Ruby annotation giving information other than pronunciation of text: change tag from BasicDoc for disambiguation</a:documentation>
|
99
|
+
<element name="ruby-annotation">
|
100
|
+
<attribute name="value">
|
101
|
+
<a:documentation>Ruby annotation value</a:documentation>
|
102
|
+
</attribute>
|
103
|
+
<ref name="LocalizedStringAttributes"/>
|
104
|
+
</element>
|
105
|
+
</define>
|
106
|
+
<define name="annotation">
|
107
|
+
<a:documentation>Source code annotation, corresponding to a callout</a:documentation>
|
108
|
+
<element name="callout-annotation">
|
109
|
+
<ref name="RequiredId"/>
|
110
|
+
<oneOrMore>
|
111
|
+
<ref name="paragraph"/>
|
112
|
+
</oneOrMore>
|
113
|
+
</element>
|
114
|
+
</define>
|
75
115
|
<define name="section-title">
|
76
116
|
<a:documentation>Title(s) of a clause</a:documentation>
|
77
117
|
<element name="title">
|
@@ -540,7 +580,7 @@ normative or informative references, some split references into sections organiz
|
|
540
580
|
<ref name="OptionalId"/>
|
541
581
|
<optional>
|
542
582
|
<attribute name="style">
|
543
|
-
<a:documentation>CSS style: only background-color supported</a:documentation>
|
583
|
+
<a:documentation>CSS style: only background-color, color, border supported</a:documentation>
|
544
584
|
</attribute>
|
545
585
|
</optional>
|
546
586
|
</define>
|
@@ -620,7 +660,7 @@ This is done if the footnote reference is already presented in some other form,
|
|
620
660
|
<ref name="RequiredId"/>
|
621
661
|
<optional>
|
622
662
|
<attribute name="style">
|
623
|
-
<a:documentation>CSS style: only background-color supported</a:documentation>
|
663
|
+
<a:documentation>CSS style: only background-color, color, border supported</a:documentation>
|
624
664
|
</attribute>
|
625
665
|
</optional>
|
626
666
|
</define>
|
@@ -700,6 +740,11 @@ titlecase, or lowercase</a:documentation>
|
|
700
740
|
<a:documentation>Width of the table block in rendering</a:documentation>
|
701
741
|
</attribute>
|
702
742
|
</optional>
|
743
|
+
<optional>
|
744
|
+
<attribute name="style">
|
745
|
+
<a:documentation>CSS style: only background-color, color, border supported</a:documentation>
|
746
|
+
</attribute>
|
747
|
+
</optional>
|
703
748
|
<ref name="BlockAttributes"/>
|
704
749
|
</define>
|
705
750
|
<define name="FigureAttributes" combine="interleave">
|
@@ -1417,7 +1462,7 @@ numbers</a:documentation>
|
|
1417
1462
|
</optional>
|
1418
1463
|
<ref name="DocumentBody"/>
|
1419
1464
|
<optional>
|
1420
|
-
<ref name="
|
1465
|
+
<ref name="annotation-container">
|
1421
1466
|
<a:documentation>Annotations to the document</a:documentation>
|
1422
1467
|
</ref>
|
1423
1468
|
</optional>
|
@@ -1461,8 +1506,8 @@ numbers</a:documentation>
|
|
1461
1506
|
</oneOrMore>
|
1462
1507
|
</element>
|
1463
1508
|
</define>
|
1464
|
-
<define name="
|
1465
|
-
<element name="
|
1509
|
+
<define name="annotation-container">
|
1510
|
+
<element name="annotation-container">
|
1466
1511
|
<oneOrMore>
|
1467
1512
|
<ref name="review"/>
|
1468
1513
|
</oneOrMore>
|
@@ -59,6 +59,7 @@ module Metanorma
|
|
59
59
|
def ol_attrs(node)
|
60
60
|
attr_code(id_attr(node).merge(keep_attrs(node)
|
61
61
|
.merge(type: olist_style(node.style),
|
62
|
+
start: node.attr("start"),
|
62
63
|
"explicit-type": olist_style(node.attributes[1]))))
|
63
64
|
end
|
64
65
|
|
@@ -114,7 +115,7 @@ module Metanorma
|
|
114
115
|
def colist(node)
|
115
116
|
noko do |xml|
|
116
117
|
node.items.each_with_index do |item, i|
|
117
|
-
xml.
|
118
|
+
xml.callout_annotation **attr_code(id: i + 1) do |xml_li|
|
118
119
|
xml_li.p { |p| p << item.text }
|
119
120
|
end
|
120
121
|
end
|
@@ -124,11 +124,6 @@ module Metanorma
|
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
# KILL
|
128
|
-
def pass_convert(text)
|
129
|
-
text.sub(/^pass:\[(.+)$/, "pass-format:metanorma[\\1")
|
130
|
-
end
|
131
|
-
|
132
127
|
# InlineLinkRx = %r((^|link:|#{CG_BLANK}|<|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|([^\s\[\]<]*([^\s,.?!\[\]<\)]))))m
|
133
128
|
#
|
134
129
|
InlineLinkRx = %r((^|(?<![-\\])\blink:(?!\+)|\p{Blank}|<|[<>\(\)\[\];"'])((?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)(?:(\[(|.*?[^\\])\])|([^\s\[\]<]*([^\s,.?!\[\]<\)])))))m
|
@@ -226,14 +221,17 @@ module Metanorma
|
|
226
221
|
# pass:[A] => pass-format:metanorma[++A++],
|
227
222
|
# so long as A doesn't already start with ++
|
228
223
|
# ditto pass-format:[A] => pass-format:[++A++]
|
224
|
+
# convert any \] in the ++...++ body to ]
|
229
225
|
def pass_convert(text)
|
230
226
|
text
|
231
|
-
.gsub(/pass-format:([^\[ ]*)\[(?!\+\+)(.+?)(?<!\\)\]
|
232
|
-
|
227
|
+
.gsub(/pass-format:([^\[ ]*)\[(?!\+\+)(.+?)(?<!\\)\]/) do |_m|
|
228
|
+
"pass-format:#{$1}[++#{$2.gsub(/\\\]/, ']')}++]"
|
229
|
+
end
|
233
230
|
.gsub(/pass:\[(?=\+\+)(.+?)(?<!\\)\]/,
|
234
231
|
"pass-format:metanorma[\\1]")
|
235
|
-
.gsub(/pass:\[(?!\+\+)(.+?)(?<!\\)\]
|
236
|
-
|
232
|
+
.gsub(/pass:\[(?!\+\+)(.+?)(?<!\\)\]/) do |_m|
|
233
|
+
"pass-format:metanorma[++#{$1.gsub(/\\\]/, ']')}++]"
|
234
|
+
end
|
237
235
|
end
|
238
236
|
|
239
237
|
def inlinelink(text)
|
@@ -43,7 +43,7 @@ module Metanorma
|
|
43
43
|
attrs = " value='#{target}'"
|
44
44
|
x = args[:lang] and attrs += " lang='#{x}'"
|
45
45
|
x = args[:script] and attrs += " script='#{x}'"
|
46
|
-
"<ruby
|
46
|
+
"<ruby><ruby-#{args[:type]} #{attrs}/>#{out}</ruby>"
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -82,7 +82,7 @@ module Metanorma
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
class
|
85
|
+
class LangVariantInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
86
86
|
use_dsl
|
87
87
|
named :lang
|
88
88
|
parse_content_as :text
|
@@ -91,9 +91,9 @@ module Metanorma
|
|
91
91
|
/^(?<lang>[^-]*)(?:-(?<script>.*))?$/ =~ target
|
92
92
|
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
|
93
93
|
if script
|
94
|
-
%{<variant lang='#{lang}' script='#{script}'>#{out}</variant>}
|
94
|
+
%{<lang-variant lang='#{lang}' script='#{script}'>#{out}</lang-variant>}
|
95
95
|
else
|
96
|
-
%{<variant lang='#{lang}'>#{out}</variant>}
|
96
|
+
%{<lang-variant lang='#{lang}'>#{out}</lang-variant>}
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
@@ -134,7 +134,6 @@ module Metanorma
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
# inject ZWNJ to prevent Asciidoctor from attempting regex substitutions
|
138
137
|
class PassFormatInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
139
138
|
use_dsl
|
140
139
|
named :"pass-format"
|
@@ -143,29 +142,12 @@ module Metanorma
|
|
143
142
|
def process(parent, target, attrs)
|
144
143
|
format = target || "metanorma"
|
145
144
|
out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"],
|
146
|
-
type: :pass, attributes: {
|
145
|
+
type: :pass, attributes: { "subs" => [] })
|
146
|
+
.convert
|
147
147
|
<<~XML.strip
|
148
|
-
<passthrough-inline formats="#{format}">#{
|
148
|
+
<passthrough-inline formats="#{format}">#{out}</passthrough-inline>
|
149
149
|
XML
|
150
150
|
end
|
151
|
-
|
152
|
-
# KILL
|
153
|
-
# Split content into XML tags (including XML-escaped instances),
|
154
|
-
# XML escapes, and text segments
|
155
|
-
# Then only apply ZWNJ to punctuation in text segments
|
156
|
-
def xml_process(out)
|
157
|
-
processed_out = ""
|
158
|
-
segments = out.split(/(<[^>]*>|<[^&]*>|&[^;]*;)/)
|
159
|
-
segments.each_with_index do |segment, index|
|
160
|
-
processed_out += if index.even? # Text segment (not a tag or escape)
|
161
|
-
#segment.gsub(/([[:punct:]])/, "\\1‌")
|
162
|
-
segment
|
163
|
-
else # XML tag or escape
|
164
|
-
segment
|
165
|
-
end
|
166
|
-
end
|
167
|
-
processed_out
|
168
|
-
end
|
169
151
|
end
|
170
152
|
|
171
153
|
class IdentifierInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
@@ -8,6 +8,7 @@ module Metanorma
|
|
8
8
|
def process(parent, reader, attrs)
|
9
9
|
attrs["name"] = "todo"
|
10
10
|
attrs["caption"] = "TODO"
|
11
|
+
# these will be converted from admonition to annotation downstream
|
11
12
|
create_block(parent, :admonition, reader.lines, attrs,
|
12
13
|
content_model: :compound)
|
13
14
|
end
|
@@ -21,6 +22,7 @@ module Metanorma
|
|
21
22
|
para.set_attr("name", "todo")
|
22
23
|
para.set_attr("caption", "TODO")
|
23
24
|
para.lines[0].sub!(/^TODO: /, "")
|
25
|
+
# these will be converted from admonition to annotation downstream
|
24
26
|
para.context = :admonition
|
25
27
|
end
|
26
28
|
end
|
@@ -13,6 +13,23 @@ module Metanorma
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
class ::Hash
|
17
|
+
def deep_merge(second)
|
18
|
+
merger = proc { |_, v1, v2|
|
19
|
+
if ::Hash === v1 && ::Hash === v2
|
20
|
+
v1.merge(v2, &merger)
|
21
|
+
elsif ::Array === v1 && ::Array === v2
|
22
|
+
v2 # overwrite old with new
|
23
|
+
elsif [:undefined].include?(v2)
|
24
|
+
v1
|
25
|
+
else
|
26
|
+
v2
|
27
|
+
end
|
28
|
+
}
|
29
|
+
merge(second.to_h, &merger)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
16
33
|
def initialize(old, new)
|
17
34
|
@old = load_bibitem(old)
|
18
35
|
@new = load_bibitem(new)
|
@@ -87,6 +87,8 @@ module Metanorma
|
|
87
87
|
conv = presentation_xml_converter(EmptyAttr.new)
|
88
88
|
i18n = conv.i18n_init(lang, script, locale, i18nyaml)
|
89
89
|
conv.metadata_init(lang, script, locale, i18n)
|
90
|
+
conv.xref_init(lang, script, nil, i18n, {})
|
91
|
+
conv.xrefs.klass.meta = conv.meta
|
90
92
|
conv
|
91
93
|
end
|
92
94
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require "metanorma/standoc/utils"
|
2
|
+
require_relative "validate_image"
|
2
3
|
require_relative "validate_section"
|
3
4
|
require_relative "validate_table"
|
4
5
|
require_relative "validate_term"
|
5
6
|
require_relative "validate_schema"
|
6
7
|
require "nokogiri"
|
7
8
|
require "iev"
|
8
|
-
require "pngcheck"
|
9
9
|
|
10
10
|
module Metanorma
|
11
11
|
module Standoc
|
@@ -14,7 +14,6 @@ module Metanorma
|
|
14
14
|
@doctype = doc.at("//bibdata/ext/doctype")&.text
|
15
15
|
repeat_id_validate(doc.root) # feeds xref_validate, termsect_validate
|
16
16
|
xref_validate(doc) # feeds nested_asset_validate
|
17
|
-
nested_asset_validate(doc)
|
18
17
|
section_validate(doc)
|
19
18
|
norm_ref_validate(doc)
|
20
19
|
iev_validate(doc.root)
|
@@ -25,6 +24,7 @@ module Metanorma
|
|
25
24
|
table_validate(doc)
|
26
25
|
requirement_validate(doc)
|
27
26
|
image_validate(doc)
|
27
|
+
block_validate(doc)
|
28
28
|
math_validate(doc)
|
29
29
|
fatalerrors = @log.abort_messages
|
30
30
|
fatalerrors.empty? or
|
@@ -98,61 +98,6 @@ module Metanorma
|
|
98
98
|
@log.add("Style", i, err2)
|
99
99
|
end
|
100
100
|
|
101
|
-
def image_validate(doc)
|
102
|
-
image_exists(doc)
|
103
|
-
image_toobig(doc)
|
104
|
-
png_validate(doc)
|
105
|
-
end
|
106
|
-
|
107
|
-
def image_exists(doc)
|
108
|
-
doc.xpath("//image").each do |i|
|
109
|
-
Vectory::Utils::url?(i["src"]) and next
|
110
|
-
Vectory::Utils::datauri?(i["src"]) and next
|
111
|
-
expand_path(i["src"]) and next
|
112
|
-
@log.add("Images", i.parent,
|
113
|
-
"Image not found: #{i['src']}", severity: 0)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def expand_path(loc)
|
118
|
-
relative_path = File.join(@localdir, loc)
|
119
|
-
[loc, relative_path].detect do |p|
|
120
|
-
File.exist?(p) ? p : nil
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def png_validate(doc)
|
125
|
-
doc.xpath("//image[@mimetype = 'image/png']").each do |i|
|
126
|
-
Vectory::Utils::url?(i["src"]) and next
|
127
|
-
decoded = if Vectory::Utils::datauri?(i["src"])
|
128
|
-
Vectory::Utils::decode_datauri(i["src"])[:data]
|
129
|
-
else
|
130
|
-
path = expand_path(i["src"]) or next
|
131
|
-
File.binread(path)
|
132
|
-
end
|
133
|
-
png_validate1(i, decoded)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def png_validate1(img, buffer)
|
138
|
-
PngCheck.check_buffer(buffer)
|
139
|
-
rescue PngCheck::CorruptPngError => e
|
140
|
-
@log.add("Images", img.parent,
|
141
|
-
"Corrupt PNG image detected: #{e.message}")
|
142
|
-
end
|
143
|
-
|
144
|
-
TOO_BIG_IMG_ERR = <<~ERR.freeze
|
145
|
-
Image too large for Data URI encoding: disable Data URI encoding (`:data-uri-image: false`), or set `:data-uri-maxsize: 0`
|
146
|
-
ERR
|
147
|
-
|
148
|
-
def image_toobig(doc)
|
149
|
-
@dataurimaxsize.zero? and return
|
150
|
-
doc.xpath("//image").each do |i|
|
151
|
-
i["src"].size > @dataurimaxsize and
|
152
|
-
@log.add("Images", i.parent, TOO_BIG_IMG_ERR, severity: 0)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
101
|
def validate(doc)
|
157
102
|
content_validate(doc)
|
158
103
|
schema_validate(formattedstr_strip(doc.dup), schema_location)
|
@@ -250,6 +195,39 @@ module Metanorma
|
|
250
195
|
get_anchors_between(from["target"], to_location["target"])
|
251
196
|
.each { |id| @doc_xrefs[id] = from }
|
252
197
|
end
|
198
|
+
|
199
|
+
def block_validate(doc)
|
200
|
+
nested_asset_validate(doc)
|
201
|
+
all_empty_block_validate(doc)
|
202
|
+
end
|
203
|
+
|
204
|
+
def all_empty_block_validate(doc)
|
205
|
+
%w(note example admonition figure quote pre).each do |tag|
|
206
|
+
empty_block_validate(doc, "//#{tag}", nil)
|
207
|
+
end
|
208
|
+
empty_block_validate(doc, "//sourcecode", "body")
|
209
|
+
empty_block_validate(doc, "//formula", "stem")
|
210
|
+
empty_block_validate(doc, "//ol", "li")
|
211
|
+
empty_block_validate(doc, "//ul", "li")
|
212
|
+
empty_block_validate(doc, "//dl", "dt")
|
213
|
+
end
|
214
|
+
|
215
|
+
def empty_block_validate(doc, tag, body)
|
216
|
+
# require "debug"; binding.b
|
217
|
+
doc.xpath(tag).each do |t|
|
218
|
+
body and t = t.at("./#{body}")
|
219
|
+
empty_block?(t) or next
|
220
|
+
@log.add("Blocks", t, "#{tag.sub(/^\/\//, '')} is empty", severity: 1)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def empty_block?(block)
|
225
|
+
content = block.children.reject { |n| n.name == "name" }
|
226
|
+
content.map do |n|
|
227
|
+
%w(image xref eref).include?(n.name) ? n.name : n
|
228
|
+
end
|
229
|
+
content.map(&:to_s).join.strip.empty?
|
230
|
+
end
|
253
231
|
end
|
254
232
|
end
|
255
233
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "pngcheck"
|
2
|
+
|
3
|
+
module Metanorma
|
4
|
+
module Standoc
|
5
|
+
module Validate
|
6
|
+
def image_validate(doc)
|
7
|
+
image_exists(doc)
|
8
|
+
image_toobig(doc)
|
9
|
+
png_validate(doc)
|
10
|
+
end
|
11
|
+
|
12
|
+
def image_exists(doc)
|
13
|
+
doc.xpath("//image").each do |i|
|
14
|
+
Vectory::Utils::url?(i["src"]) and next
|
15
|
+
Vectory::Utils::datauri?(i["src"]) and next
|
16
|
+
expand_path(i["src"]) and next
|
17
|
+
@log.add("Images", i.parent,
|
18
|
+
"Image not found: #{i['src']}", severity: 0)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def expand_path(loc)
|
23
|
+
relative_path = File.join(@localdir, loc)
|
24
|
+
[loc, relative_path].detect do |p|
|
25
|
+
File.exist?(p) ? p : nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def png_validate(doc)
|
30
|
+
doc.xpath("//image[@mimetype = 'image/png']").each do |i|
|
31
|
+
Vectory::Utils::url?(i["src"]) and next
|
32
|
+
decoded = if Vectory::Utils::datauri?(i["src"])
|
33
|
+
Vectory::Utils::decode_datauri(i["src"])[:data]
|
34
|
+
else
|
35
|
+
path = expand_path(i["src"]) or next
|
36
|
+
File.binread(path)
|
37
|
+
end
|
38
|
+
png_validate1(i, decoded)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def png_validate1(img, buffer)
|
43
|
+
PngCheck.check_buffer(buffer)
|
44
|
+
rescue PngCheck::CorruptPngError => e
|
45
|
+
@log.add("Images", img.parent,
|
46
|
+
"Corrupt PNG image detected: #{e.message}")
|
47
|
+
end
|
48
|
+
|
49
|
+
TOO_BIG_IMG_ERR = <<~ERR.freeze
|
50
|
+
Image too large for Data URI encoding: disable Data URI encoding (`:data-uri-image: false`), or set `:data-uri-maxsize: 0`
|
51
|
+
ERR
|
52
|
+
|
53
|
+
def image_toobig(doc)
|
54
|
+
@dataurimaxsize.zero? and return
|
55
|
+
doc.xpath("//image").each do |i|
|
56
|
+
i["src"].size > @dataurimaxsize and
|
57
|
+
@log.add("Images", i.parent, TOO_BIG_IMG_ERR, severity: 0)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -12,7 +12,7 @@ module Metanorma
|
|
12
12
|
def sourcecode_style(root)
|
13
13
|
root.xpath("//sourcecode").each do |x|
|
14
14
|
callouts = x.xpath("./body/callout")
|
15
|
-
annotations = x.xpath("./annotation")
|
15
|
+
annotations = x.xpath("./callout-annotation")
|
16
16
|
callouts_error(x, callouts, annotations)
|
17
17
|
end
|
18
18
|
end
|
data/metanorma-standoc.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.add_dependency "asciidoctor", "~> 2.0.0"
|
33
33
|
spec.add_dependency "crass", "~> 1.0.0"
|
34
34
|
spec.add_dependency "iev", "~> 0.3.5"
|
35
|
-
spec.add_dependency "isodoc", "~> 3.
|
35
|
+
spec.add_dependency "isodoc", "~> 3.2.0"
|
36
36
|
spec.add_dependency "metanorma", ">= 1.6.0"
|
37
37
|
spec.add_dependency "metanorma-plugin-glossarist", "~> 0.2.3"
|
38
38
|
spec.add_dependency "metanorma-plugin-lutaml", "~> 0.7.31"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metanorma-standoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 3.
|
75
|
+
version: 3.2.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 3.
|
82
|
+
version: 3.2.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: metanorma
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -554,6 +554,7 @@ files:
|
|
554
554
|
- lib/metanorma/standoc/terms.rb
|
555
555
|
- lib/metanorma/standoc/utils.rb
|
556
556
|
- lib/metanorma/standoc/validate.rb
|
557
|
+
- lib/metanorma/standoc/validate_image.rb
|
557
558
|
- lib/metanorma/standoc/validate_schema.rb
|
558
559
|
- lib/metanorma/standoc/validate_section.rb
|
559
560
|
- lib/metanorma/standoc/validate_table.rb
|