isodoc 1.6.2 → 1.6.7
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 +2 -12
- data/.hound.yml +3 -1
- data/.rubocop.yml +4 -6
- data/Rakefile +2 -2
- data/isodoc.gemspec +3 -2
- data/lib/isodoc-yaml/i18n-en.yaml +1 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
- data/lib/isodoc.rb +0 -2
- data/lib/isodoc/convert.rb +7 -1
- data/lib/isodoc/function/blocks.rb +5 -4
- data/lib/isodoc/function/cleanup.rb +52 -43
- data/lib/isodoc/function/inline.rb +7 -7
- data/lib/isodoc/function/references.rb +32 -51
- data/lib/isodoc/function/section.rb +28 -16
- data/lib/isodoc/function/table.rb +21 -22
- data/lib/isodoc/function/terms.rb +6 -7
- data/lib/isodoc/function/to_word_html.rb +6 -3
- data/lib/isodoc/function/utils.rb +181 -163
- data/lib/isodoc/gem_tasks.rb +8 -9
- data/lib/isodoc/headlesshtml_convert.rb +8 -7
- data/lib/isodoc/html_convert.rb +5 -1
- data/lib/isodoc/html_function/comments.rb +14 -12
- data/lib/isodoc/html_function/footnotes.rb +14 -7
- data/lib/isodoc/html_function/html.rb +30 -26
- data/lib/isodoc/html_function/postprocess.rb +191 -182
- data/lib/isodoc/html_function/sectionsplit.rb +230 -0
- data/lib/isodoc/metadata.rb +22 -20
- data/lib/isodoc/metadata_contributor.rb +31 -28
- data/lib/isodoc/pdf_convert.rb +11 -13
- data/lib/isodoc/presentation_function/bibdata.rb +61 -30
- data/lib/isodoc/presentation_function/inline.rb +34 -27
- data/lib/isodoc/presentation_function/section.rb +54 -19
- data/lib/isodoc/presentation_xml_convert.rb +2 -0
- data/lib/isodoc/sassc_importer.rb +1 -1
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/postprocess.rb +50 -36
- data/lib/isodoc/xref.rb +2 -0
- data/lib/isodoc/xref/xref_counter.rb +1 -2
- data/lib/isodoc/xref/xref_gen.rb +21 -14
- data/lib/isodoc/xref/xref_gen_seq.rb +60 -35
- data/lib/isodoc/xref/xref_sect_gen.rb +15 -15
- data/spec/assets/scripts_override.html +3 -0
- data/spec/isodoc/blocks_spec.rb +624 -997
- data/spec/isodoc/cleanup_spec.rb +40 -42
- data/spec/isodoc/i18n_spec.rb +694 -821
- data/spec/isodoc/inline_spec.rb +482 -328
- data/spec/isodoc/metadata_spec.rb +384 -379
- data/spec/isodoc/postproc_spec.rb +163 -55
- data/spec/isodoc/presentation_xml_spec.rb +355 -278
- data/spec/isodoc/ref_spec.rb +5 -5
- data/spec/isodoc/section_spec.rb +216 -199
- data/spec/isodoc/sectionsplit_spec.rb +190 -0
- data/spec/isodoc/table_spec.rb +41 -42
- data/spec/isodoc/terms_spec.rb +84 -84
- data/spec/isodoc/xref_spec.rb +974 -932
- metadata +22 -5
data/lib/isodoc/pdf_convert.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
require_relative "html_function/comments
|
2
|
-
require_relative "html_function/footnotes
|
3
|
-
require_relative "html_function/html
|
1
|
+
require_relative "html_function/comments"
|
2
|
+
require_relative "html_function/footnotes"
|
3
|
+
require_relative "html_function/html"
|
4
4
|
require "metanorma"
|
5
5
|
|
6
6
|
module IsoDoc
|
7
7
|
class PdfConvert < ::IsoDoc::Convert
|
8
|
-
|
9
8
|
include HtmlFunction::Comments
|
10
9
|
include HtmlFunction::Footnotes
|
11
10
|
include HtmlFunction::Html
|
@@ -13,6 +12,8 @@ module IsoDoc
|
|
13
12
|
def initialize(options)
|
14
13
|
@standardstylesheet = nil
|
15
14
|
super
|
15
|
+
@format = :pdf
|
16
|
+
@suffix = "pdf"
|
16
17
|
@scripts = @scripts_pdf if @scripts_pdf
|
17
18
|
@maxwidth = 500
|
18
19
|
@maxheight = 800
|
@@ -22,22 +23,19 @@ module IsoDoc
|
|
22
23
|
"_pdfimages"
|
23
24
|
end
|
24
25
|
|
25
|
-
def initialize(options)
|
26
|
-
@format = :pdf
|
27
|
-
@suffix = "pdf"
|
28
|
-
super
|
29
|
-
end
|
30
|
-
|
31
26
|
def convert(input_filename, file = nil, debug = false, output_filename = nil)
|
32
27
|
file = File.read(input_filename, encoding: "utf-8") if file.nil?
|
33
28
|
@openmathdelim, @closemathdelim = extract_delims(file)
|
34
29
|
docxml, filename, dir = convert_init(file, input_filename, debug)
|
35
30
|
result = convert1(docxml, filename, dir)
|
36
31
|
return result if debug
|
37
|
-
|
32
|
+
|
33
|
+
postprocess(result, "#{filename}.tmp.html", dir)
|
38
34
|
FileUtils.rm_rf dir
|
39
|
-
::Metanorma::Output::Pdf.new.convert(
|
40
|
-
|
35
|
+
::Metanorma::Output::Pdf.new.convert(
|
36
|
+
"#{filename}.tmp.html",
|
37
|
+
output_filename || "#{filename}.#{@suffix}",
|
38
|
+
)
|
41
39
|
FileUtils.rm_rf ["#{filename}.tmp.html", tmpimagedir]
|
42
40
|
end
|
43
41
|
|
@@ -1,13 +1,40 @@
|
|
1
1
|
module IsoDoc
|
2
2
|
class PresentationXMLConvert < ::IsoDoc::Convert
|
3
3
|
def bibdata(docxml)
|
4
|
+
docid_prefixes(docxml)
|
4
5
|
a = bibdata_current(docxml) or return
|
6
|
+
address_precompose(a)
|
5
7
|
bibdata_i18n(a)
|
6
8
|
a.next =
|
7
|
-
"<localized-strings>#{i8n_name(trim_hash(@i18n.get),
|
9
|
+
"<localized-strings>#{i8n_name(trim_hash(@i18n.get), '').join('')}"\
|
8
10
|
"</localized-strings>"
|
9
11
|
end
|
10
12
|
|
13
|
+
def docid_prefixes(docxml)
|
14
|
+
docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
|
15
|
+
i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def address_precompose(bib)
|
20
|
+
bib.xpath(ns("//bibdata//address")).each do |b|
|
21
|
+
next if b.at(ns("./formattedAddress"))
|
22
|
+
|
23
|
+
x = address_precompose1(b)
|
24
|
+
b.children = "<formattedAddress>#{x}</formattedAddress>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def address_precompose1(addr)
|
29
|
+
ret = []
|
30
|
+
addr.xpath(ns("./street")).each { |s| ret << s.children.to_xml }
|
31
|
+
a = addr.at(ns("./city")) and ret << a.children.to_xml
|
32
|
+
addr.xpath(ns("./state")).each { |s| ret << s.children.to_xml }
|
33
|
+
a = addr.at(ns("./country")) and ret << a.children.to_xml
|
34
|
+
a = addr.at(ns("./postcode")) and ret[-1] += " #{a.children.to_xml}"
|
35
|
+
ret.join("<br/>")
|
36
|
+
end
|
37
|
+
|
11
38
|
def bibdata_current(docxml)
|
12
39
|
a = docxml.at(ns("//bibdata")) or return
|
13
40
|
a.xpath(ns("./language")).each do |l|
|
@@ -19,10 +46,10 @@ module IsoDoc
|
|
19
46
|
a
|
20
47
|
end
|
21
48
|
|
22
|
-
def bibdata_i18n(
|
23
|
-
hash_translate(
|
24
|
-
hash_translate(
|
25
|
-
hash_translate(
|
49
|
+
def bibdata_i18n(bib)
|
50
|
+
hash_translate(bib, @i18n.get["doctype_dict"], "./ext/doctype")
|
51
|
+
hash_translate(bib, @i18n.get["stage_dict"], "./status/stage")
|
52
|
+
hash_translate(bib, @i18n.get["substage_dict"], "./status/substage")
|
26
53
|
end
|
27
54
|
|
28
55
|
def hash_translate(bibdata, hash, xpath, lang = @lang)
|
@@ -35,58 +62,62 @@ module IsoDoc
|
|
35
62
|
x.next.children = hash[x.text]
|
36
63
|
end
|
37
64
|
|
38
|
-
def i18n_tag(
|
39
|
-
"<localized-string key='#{
|
65
|
+
def i18n_tag(key, value)
|
66
|
+
"<localized-string key='#{key}' language='#{@lang}'>#{value}"\
|
67
|
+
"</localized-string>"
|
40
68
|
end
|
41
69
|
|
42
|
-
def i18n_safe(
|
43
|
-
|
70
|
+
def i18n_safe(key)
|
71
|
+
key.to_s.gsub(/\s|\./, "_")
|
44
72
|
end
|
45
73
|
|
46
|
-
def i8n_name(
|
47
|
-
if
|
48
|
-
elsif
|
49
|
-
|
50
|
-
with_index do |(v1, g), i|
|
74
|
+
def i8n_name(hash, pref)
|
75
|
+
if hash.is_a? Hash then i8n_name1(hash, pref)
|
76
|
+
elsif hash.is_a? Array
|
77
|
+
hash.reject { |a| blank?(a) }.each_with_object([])
|
78
|
+
.with_index do |(v1, g), i|
|
51
79
|
i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
|
52
80
|
end
|
53
|
-
else [i18n_tag(pref,
|
81
|
+
else [i18n_tag(pref, hash)]
|
54
82
|
end
|
55
83
|
end
|
56
84
|
|
57
|
-
def i8n_name1(
|
58
|
-
|
85
|
+
def i8n_name1(hash, pref)
|
86
|
+
hash.reject { |_k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
|
59
87
|
if v.is_a? Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
|
60
88
|
elsif v.is_a? Array
|
61
89
|
v.reject { |a| blank?(a) }.each_with_index do |v1, i|
|
62
90
|
i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
|
63
91
|
end
|
64
92
|
else
|
65
|
-
g << i18n_tag("#{pref}#{pref.empty? ?
|
93
|
+
g << i18n_tag("#{pref}#{pref.empty? ? '' : '.'}#{i18n_safe(k)}", v)
|
66
94
|
end
|
67
95
|
end
|
68
96
|
end
|
69
97
|
|
70
|
-
#https://stackoverflow.com/a/31822406
|
71
|
-
def blank?(
|
72
|
-
|
98
|
+
# https://stackoverflow.com/a/31822406
|
99
|
+
def blank?(elem)
|
100
|
+
elem.nil? || elem.respond_to?(:empty?) && elem.empty?
|
73
101
|
end
|
74
102
|
|
75
|
-
def trim_hash(
|
103
|
+
def trim_hash(hash)
|
76
104
|
loop do
|
77
|
-
h_new = trim_hash1(
|
78
|
-
break
|
79
|
-
|
105
|
+
h_new = trim_hash1(hash)
|
106
|
+
break hash if hash == h_new
|
107
|
+
|
108
|
+
hash = h_new
|
80
109
|
end
|
81
110
|
end
|
82
111
|
|
83
|
-
def trim_hash1(
|
84
|
-
return
|
85
|
-
|
112
|
+
def trim_hash1(hash)
|
113
|
+
return hash unless hash.is_a? Hash
|
114
|
+
|
115
|
+
hash.each_with_object({}) do |(k, v), g|
|
86
116
|
next if blank?(v)
|
87
|
-
|
117
|
+
|
118
|
+
g[k] = if v.is_a? Hash then trim_hash1(hash[k])
|
88
119
|
elsif v.is_a? Array
|
89
|
-
|
120
|
+
hash[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
|
90
121
|
else
|
91
122
|
v
|
92
123
|
end
|
@@ -9,8 +9,8 @@ module IsoDoc
|
|
9
9
|
return @xrefs.anchor(node["bibitemid"], :xref) || "???"
|
10
10
|
elsif node["target"] && node["droploc"]
|
11
11
|
return @xrefs.anchor(node["target"], :value) ||
|
12
|
-
|
13
|
-
|
12
|
+
@xrefs.anchor(node["target"], :label) ||
|
13
|
+
@xrefs.anchor(node["target"], :xref) || "???"
|
14
14
|
elsif node["target"] && !/.#./.match(node["target"])
|
15
15
|
linkend = anchor_linkend1(node)
|
16
16
|
end
|
@@ -33,6 +33,10 @@ module IsoDoc
|
|
33
33
|
return linkend&.downcase if node["case"] == "lowercase"
|
34
34
|
return linkend if linkend[0, 1].match?(/\p{Upper}/)
|
35
35
|
|
36
|
+
capitalise_xref1(node, linkend)
|
37
|
+
end
|
38
|
+
|
39
|
+
def capitalise_xref1(node, linkend)
|
36
40
|
prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
|
37
41
|
node.xpath("./preceding::text()")
|
38
42
|
if prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map(&:text).join)
|
@@ -43,8 +47,8 @@ module IsoDoc
|
|
43
47
|
|
44
48
|
def nearest_block_parent(node)
|
45
49
|
until %w(p title td th name formula li dt dd sourcecode pre)
|
46
|
-
|
47
|
-
|
50
|
+
.include?(node.name)
|
51
|
+
node = node.parent
|
48
52
|
end
|
49
53
|
node
|
50
54
|
end
|
@@ -68,55 +72,55 @@ module IsoDoc
|
|
68
72
|
# so not <origin bibitemid="ISO7301" citeas="ISO 7301">
|
69
73
|
# <locality type="section"><reference>3.1</reference></locality></origin>
|
70
74
|
|
71
|
-
def eref_localities(refs, target,
|
75
|
+
def eref_localities(refs, target, node)
|
72
76
|
ret = ""
|
73
77
|
refs.each_with_index do |r, i|
|
74
78
|
delim = ","
|
75
79
|
delim = ";" if r.name == "localityStack" && i.positive?
|
76
|
-
ret = eref_locality_stack(r, i, target, delim, ret,
|
80
|
+
ret = eref_locality_stack(r, i, target, delim, ret, node)
|
77
81
|
end
|
78
82
|
ret
|
79
83
|
end
|
80
84
|
|
81
|
-
def eref_locality_stack(
|
82
|
-
if
|
83
|
-
|
84
|
-
ret += eref_localities0(rr, j, target, delim,
|
85
|
+
def eref_locality_stack(ref, idx, target, delim, ret, node)
|
86
|
+
if ref.name == "localityStack"
|
87
|
+
ref.elements.each_with_index do |rr, j|
|
88
|
+
ret += eref_localities0(rr, j, target, delim, node)
|
85
89
|
delim = ","
|
86
90
|
end
|
87
91
|
else
|
88
|
-
ret += eref_localities0(
|
92
|
+
ret += eref_localities0(ref, idx, target, delim, node)
|
89
93
|
end
|
90
94
|
ret
|
91
95
|
end
|
92
96
|
|
93
|
-
def eref_localities0(
|
94
|
-
if
|
97
|
+
def eref_localities0(ref, _idx, target, delim, node)
|
98
|
+
if ref["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
|
95
99
|
else
|
96
|
-
eref_localities1(target,
|
97
|
-
|
100
|
+
eref_localities1(target, ref["type"], ref.at(ns("./referenceFrom")),
|
101
|
+
ref.at(ns("./referenceTo")), delim, node, @lang)
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
101
105
|
# TODO: move to localization file
|
102
|
-
def eref_localities1_zh(_target, type, from,
|
106
|
+
def eref_localities1_zh(_target, type, from, upto, node, delim)
|
103
107
|
ret = "#{delim} 第#{from.text}" if from
|
104
|
-
ret += "–#{
|
108
|
+
ret += "–#{upto.text}" if upto
|
105
109
|
loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize)
|
106
|
-
ret += " #{loc}" unless
|
110
|
+
ret += " #{loc}" unless node["droploc"] == "true"
|
107
111
|
ret
|
108
112
|
end
|
109
113
|
|
110
114
|
# TODO: move to localization file
|
111
|
-
def eref_localities1(target, type, from,
|
115
|
+
def eref_localities1(target, type, from, upto, delim, node, lang = "en")
|
112
116
|
return "" if type == "anchor"
|
113
117
|
|
114
118
|
lang == "zh" and
|
115
|
-
return l10n(eref_localities1_zh(target, type, from,
|
119
|
+
return l10n(eref_localities1_zh(target, type, from, upto, node, delim))
|
116
120
|
ret = delim
|
117
|
-
ret += eref_locality_populate(type,
|
121
|
+
ret += eref_locality_populate(type, node)
|
118
122
|
ret += " #{from.text}" if from
|
119
|
-
ret += "–#{
|
123
|
+
ret += "–#{upto.text}" if upto
|
120
124
|
l10n(ret)
|
121
125
|
end
|
122
126
|
|
@@ -158,12 +162,15 @@ module IsoDoc
|
|
158
162
|
end
|
159
163
|
|
160
164
|
def concept1(node)
|
161
|
-
content = node.first_element_child.children.
|
162
|
-
|
165
|
+
content = node.first_element_child.children.reject do |c|
|
166
|
+
%w{locality localityStack}.include? c.name
|
163
167
|
end.select { |c| !c.text? || /\S/.match(c) }
|
164
|
-
|
165
|
-
|
166
|
-
|
168
|
+
n = if content.empty?
|
169
|
+
@i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml)
|
170
|
+
else
|
171
|
+
"<em>#{node.children.to_xml}</em>"
|
172
|
+
end
|
173
|
+
node.replace(n)
|
167
174
|
end
|
168
175
|
|
169
176
|
def variant(docxml)
|
@@ -2,20 +2,21 @@ module IsoDoc
|
|
2
2
|
class PresentationXMLConvert < ::IsoDoc::Convert
|
3
3
|
def clause(docxml)
|
4
4
|
docxml.xpath(ns("//clause | "\
|
5
|
-
"//terms | //definitions | //references"))
|
6
|
-
|
5
|
+
"//terms | //definitions | //references"))
|
6
|
+
.each do |f|
|
7
7
|
clause1(f)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def clause1(
|
12
|
-
level = @xrefs.anchor(
|
13
|
-
t =
|
14
|
-
return if !
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
def clause1(elem)
|
12
|
+
level = @xrefs.anchor(elem["id"], :level, false) || "1"
|
13
|
+
t = elem.at(ns("./title")) and t["depth"] = level
|
14
|
+
return if !elem.ancestors("boilerplate").empty? ||
|
15
|
+
@suppressheadingnumbers || elem["unnumbered"]
|
16
|
+
|
17
|
+
lbl = @xrefs.anchor(elem["id"], :label,
|
18
|
+
elem.parent.name != "sections") or return
|
19
|
+
prefix_name(elem, "<tab/>", "#{lbl}#{clausedelim}", "title")
|
19
20
|
end
|
20
21
|
|
21
22
|
def annex(docxml)
|
@@ -24,12 +25,12 @@ module IsoDoc
|
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
def annex1(
|
28
|
-
lbl = @xrefs.anchor(
|
29
|
-
if t =
|
28
|
+
def annex1(elem)
|
29
|
+
lbl = @xrefs.anchor(elem["id"], :label)
|
30
|
+
if t = elem.at(ns("./title"))
|
30
31
|
t.children = "<strong>#{t.children.to_xml}</strong>"
|
31
32
|
end
|
32
|
-
prefix_name(
|
33
|
+
prefix_name(elem, "<br/><br/>", lbl, "title")
|
33
34
|
end
|
34
35
|
|
35
36
|
def term(docxml)
|
@@ -38,18 +39,52 @@ module IsoDoc
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
|
-
def term1(
|
42
|
-
lbl = @xrefs.get[
|
43
|
-
prefix_name(
|
42
|
+
def term1(elem)
|
43
|
+
lbl = @xrefs.get[elem["id"]][:label] or return
|
44
|
+
prefix_name(elem, "", "#{lbl}#{clausedelim}", "name")
|
44
45
|
end
|
45
46
|
|
46
47
|
def references(docxml)
|
47
48
|
end
|
48
49
|
|
50
|
+
def docid_prefixes(docxml)
|
51
|
+
docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
|
52
|
+
i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
49
56
|
def index(docxml)
|
50
|
-
docxml.xpath(ns("//index | //index-xref | //indexsect")).each
|
51
|
-
|
57
|
+
docxml.xpath(ns("//index | //index-xref | //indexsect")).each(&:remove)
|
58
|
+
end
|
59
|
+
|
60
|
+
def display_order_at(docxml, xpath, idx)
|
61
|
+
return idx unless c = docxml.at(ns(xpath))
|
62
|
+
|
63
|
+
idx += 1
|
64
|
+
c["displayorder"] = idx
|
65
|
+
idx
|
66
|
+
end
|
67
|
+
|
68
|
+
def display_order_xpath(docxml, xpath, idx)
|
69
|
+
docxml.xpath(ns(xpath)).each do |c|
|
70
|
+
idx += 1
|
71
|
+
c["displayorder"] = idx
|
52
72
|
end
|
73
|
+
idx
|
74
|
+
end
|
75
|
+
|
76
|
+
def display_order(docxml)
|
77
|
+
i = 0
|
78
|
+
i = display_order_xpath(docxml, "//preface/*", i)
|
79
|
+
i = display_order_at(docxml, "//clause[@type = 'scope']", i)
|
80
|
+
i = display_order_at(docxml, @xrefs.klass.norm_ref_xpath, i)
|
81
|
+
i = display_order_at(docxml, "//sections/terms | "\
|
82
|
+
"//sections/clause[descendant::terms]", i)
|
83
|
+
i = display_order_at(docxml, "//sections/definitions", i)
|
84
|
+
i = display_order_xpath(docxml, @xrefs.klass.middle_clause(docxml), i)
|
85
|
+
i = display_order_xpath(docxml, "//annex", i)
|
86
|
+
i = display_order_xpath(docxml, @xrefs.klass.bibliography_xpath, i)
|
87
|
+
display_order_xpath(docxml, "//indexsect", i)
|
53
88
|
end
|
54
89
|
end
|
55
90
|
end
|
@@ -22,12 +22,14 @@ module IsoDoc
|
|
22
22
|
|
23
23
|
def conversions(docxml)
|
24
24
|
bibdata docxml
|
25
|
+
@xrefs.parse docxml
|
25
26
|
section docxml
|
26
27
|
block docxml
|
27
28
|
inline docxml
|
28
29
|
end
|
29
30
|
|
30
31
|
def section(docxml)
|
32
|
+
display_order docxml
|
31
33
|
clause docxml
|
32
34
|
annex docxml
|
33
35
|
term docxml
|