metanorma-ogc 1.0.3 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +10 -10
  3. data/.github/workflows/ubuntu.yml +25 -11
  4. data/.github/workflows/windows.yml +11 -12
  5. data/README.adoc +3 -2
  6. data/lib/asciidoctor/ogc/biblio.rng +144 -49
  7. data/lib/asciidoctor/ogc/boilerplate.xml +37 -69
  8. data/lib/asciidoctor/ogc/converter.rb +6 -11
  9. data/lib/asciidoctor/ogc/isodoc.rng +49 -5
  10. data/lib/asciidoctor/ogc/ogc.rng +0 -4
  11. data/lib/isodoc/ogc/base_convert.rb +13 -112
  12. data/lib/isodoc/ogc/biblio.rb +13 -2
  13. data/lib/isodoc/ogc/html/html_ogc_titlepage.html +2 -6
  14. data/lib/isodoc/ogc/html/htmlstyle.scss +11 -1
  15. data/lib/isodoc/ogc/html/scripts.html +14 -27
  16. data/lib/isodoc/ogc/html/word_ogc_titlepage.html +13 -4
  17. data/lib/isodoc/ogc/html_convert.rb +1 -0
  18. data/lib/isodoc/ogc/i18n-en.yaml +3 -0
  19. data/lib/isodoc/ogc/metadata.rb +1 -31
  20. data/lib/isodoc/ogc/ogc.abstract-specification-topic.xsl +3387 -0
  21. data/lib/isodoc/ogc/ogc.best-practice.xsl +3387 -0
  22. data/lib/isodoc/ogc/ogc.change-request-supporting-document.xsl +3387 -0
  23. data/lib/isodoc/ogc/ogc.community-practice.xsl +3387 -0
  24. data/lib/isodoc/ogc/ogc.community-standard.xsl +3387 -0
  25. data/lib/isodoc/ogc/ogc.discussion-paper.xsl +3387 -0
  26. data/lib/isodoc/ogc/ogc.engineering-report.xsl +3387 -0
  27. data/lib/isodoc/ogc/ogc.other.xsl +3387 -0
  28. data/lib/isodoc/ogc/ogc.policy.xsl +3387 -0
  29. data/lib/isodoc/ogc/ogc.reference-model.xsl +3387 -0
  30. data/lib/isodoc/ogc/ogc.release-notes.xsl +3387 -0
  31. data/lib/isodoc/ogc/ogc.standard.xsl +3387 -0
  32. data/lib/isodoc/ogc/ogc.test-suite.xsl +3387 -0
  33. data/lib/isodoc/ogc/ogc.user-guide.xsl +3387 -0
  34. data/lib/isodoc/ogc/ogc.white-paper.xsl +3387 -0
  35. data/lib/isodoc/ogc/pdf_convert.rb +18 -77
  36. data/lib/isodoc/ogc/reqt.rb +74 -114
  37. data/lib/isodoc/ogc/reqt_xref.rb +96 -0
  38. data/lib/isodoc/ogc/sections.rb +111 -0
  39. data/lib/isodoc/ogc/word_convert.rb +17 -11
  40. data/lib/metanorma/ogc/processor.rb +8 -0
  41. data/lib/metanorma/ogc/version.rb +1 -1
  42. data/metanorma-ogc.gemspec +1 -1
  43. metadata +21 -5
  44. data/lib/isodoc/ogc/html/scripts.pdf.html +0 -72
@@ -1,96 +1,37 @@
1
1
  require_relative "base_convert"
2
- require "fileutils"
3
2
  require "isodoc"
4
- require_relative "metadata"
5
3
 
6
4
  module IsoDoc
7
5
  module Ogc
8
6
  # A {Converter} implementation that generates PDF HTML output, and a
9
7
  # document schema encapsulation of the document for validation
10
- class PdfConvert < IsoDoc::PdfConvert
8
+ class PdfConvert < IsoDoc::XslfoPdfConvert
11
9
  def initialize(options)
12
10
  @libdir = File.dirname(__FILE__)
13
11
  super
14
- #FileUtils.cp html_doc_path('logo.jpg'), "logo.jpg"
15
- #@files_to_delete << "logo.jpg"
16
12
  end
17
13
 
18
- def default_fonts(options)
19
- {
20
- bodyfont: (options[:script] == "Hans" ? '"SimSun",serif' : '"Overpass",sans-serif'),
21
- headerfont: (options[:script] == "Hans" ? '"SimHei",sans-serif' : '"Overpass",sans-serif'),
22
- monospacefont: '"Space Mono",monospace'
23
- }
14
+ def pdf_stylesheet(docxml)
15
+ doctype = docxml&.at(ns("//bibdata/ext/doctype"))&.text
16
+ doctype = "other" unless %w(abstract-specification-topic best-practice
17
+ change-request-supporting-document community-practice community-standard
18
+ discussion-paper engineering-report policy reference-model release-notes
19
+ standard user-guide test-suite white-paper).include? doctype
20
+ "ogc.#{doctype}.xsl"
24
21
  end
25
22
 
26
- def default_file_locations(_options)
27
- {
28
- htmlstylesheet: html_doc_path("htmlstyle.scss"),
29
- htmlcoverpage: html_doc_path("html_ogc_titlepage.html"),
30
- htmlintropage: html_doc_path("html_ogc_intro.html"),
31
- scripts_pdf: html_doc_path("scripts.pdf.html"),
32
- }
33
- end
34
-
35
- def metadata_init(lang, script, labels)
36
- @meta = Metadata.new(lang, script, labels)
37
- end
38
-
39
- def googlefonts
40
- <<~HEAD.freeze
41
- <link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i|Space+Mono:400,700" rel="stylesheet" />
42
- <link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet" />
43
- <link href="https://fonts.googleapis.com/css?family=Teko:300,400,500" rel="stylesheet">
44
- HEAD
45
- end
46
-
47
- def admonition_class(node)
48
- case node["type"]
49
- when "important" then "Admonition.Important"
50
- when "warning" then "Admonition.Warning"
51
- else
52
- "Admonition"
23
+ def convert(filename, file = nil, debug = false)
24
+ file = File.read(filename, encoding: "utf-8") if file.nil?
25
+ docxml, outname_html, dir = convert_init(file, filename, debug)
26
+ /\.xml$/.match(filename) or
27
+ filename = Tempfile.open([outname_html, ".xml"], encoding: "utf-8") do |f|
28
+ f.write file
29
+ f.path
53
30
  end
31
+ FileUtils.rm_rf dir
32
+ ::Metanorma::Output::XslfoPdf.new.convert(
33
+ filename, outname_html + ".pdf", File.join(@libdir, pdf_stylesheet(docxml)))
54
34
  end
55
-
56
- def make_body(xml, docxml)
57
- body_attr = { lang: "EN-US", link: "blue", vlink: "#954F72", "xml:lang": "EN-US", class: "container" }
58
- xml.body **body_attr do |body|
59
- make_body1(body, docxml)
60
- make_body2(body, docxml)
61
- make_body3(body, docxml)
62
- end
63
- end
64
-
65
- def html_toc(docxml)
66
- docxml
67
- end
68
-
69
- def make_body3(body, docxml)
70
- body.div **{ class: "main-section" } do |div3|
71
- @prefacenum = 0
72
- boilerplate docxml, div3
73
- abstract docxml, div3
74
- keywords docxml, div3
75
- foreword docxml, div3
76
- introduction docxml, div3
77
- submittingorgs docxml, div3
78
- submitters docxml, div3
79
- preface docxml, div3
80
- acknowledgements docxml, div3
81
- middle docxml, div3
82
- footnotes div3
83
- comments div3
84
- end
85
- end
86
-
87
- def authority_cleanup(docxml)
88
- authority_cleanup1(docxml, "contact")
89
- super
90
- end
91
-
92
- include BaseConvert
93
35
  end
94
36
  end
95
37
  end
96
-
@@ -1,38 +1,49 @@
1
1
  require "isodoc"
2
- require_relative "metadata"
3
- require "fileutils"
2
+ require_relative "reqt_xref"
4
3
 
5
4
  module IsoDoc
6
5
  module Ogc
7
6
  module BaseConvert
8
7
  def recommend_class(node)
9
8
  return "recommendtest" if node["type"] == "verification"
9
+ return "recommendtest" if node["type"] == "abstracttest"
10
10
  return "recommendclass" if node["type"] == "class"
11
+ return "recommendclass" if node["type"] == "conformanceclass"
11
12
  "recommend"
12
13
  end
13
14
 
14
15
  def recommend_table_attr(node)
15
- attr_code(id: node["id"],
16
- class: recommend_class(node),
16
+ attr_code(id: node["id"], class: recommend_class(node),
17
17
  style: "border-collapse:collapse;border-spacing:0;")
18
18
  end
19
19
 
20
20
  REQ_TBL_ATTR =
21
21
  { style: "vertical-align:top;", class: "recommend" }.freeze
22
22
 
23
+ def recommendation_class(node)
24
+ %w(verification abstracttest).include?(node["type"]) ?
25
+ "RecommendationTestTitle" : "RecommendationTitle"
26
+ end
27
+
23
28
  def recommendation_name(node, out, type)
24
29
  label, title, lbl = recommendation_labels(node)
25
- out.p **{ class: node["type"] == "verification" ?
26
- "RecommendationTestTitle" : "RecommendationTitle" } do |b|
27
- lbl = anchor(node['id'], :label, false)
28
- b << (lbl.nil? ? l10n("#{type}:") : l10n("#{type} #{lbl}:"))
29
- if title
30
- b << " "
31
- title.children.each { |n| parse(n,b) }
30
+ out.p **{ class: recommendation_class(node) } do |b|
31
+ if inject_crossreference_reqt?(node, label)
32
+ lbl = anchor(@reqtlabels[label.text], :xref, false)
33
+ b << (lbl.nil? ? l10n("#{type}:") : l10n("#{lbl}:"))
34
+ else
35
+ b << (lbl.nil? ? l10n("#{type}:") : l10n("#{type} #{lbl}:"))
32
36
  end
37
+ recommendation_name1(title, node, label, b)
33
38
  end
34
39
  end
35
40
 
41
+ def recommendation_name1(title, node, label, b)
42
+ return unless title && !inject_crossreference_reqt?(node, label)
43
+ b << " "
44
+ title.children.each { |n| parse(n,b) }
45
+ end
46
+
36
47
  def recommend_title(node, out)
37
48
  label = node.at(ns("./label")) or return
38
49
  out.tr do |tr|
@@ -44,27 +55,52 @@ module IsoDoc
44
55
  end
45
56
  end
46
57
 
58
+ # embedded reqts xref to top level reqts via label lookup
59
+ def inject_crossreference_reqt?(node, label)
60
+ !node.ancestors("requirement, recommendation, permission").empty? &&
61
+ @reqtlabels[label&.text]
62
+ end
63
+
47
64
  def recommendation_attributes1(node)
48
65
  out = []
49
66
  oblig = node["obligation"] and out << ["Obligation", oblig]
50
- subj = node&.at(ns("./subject"))&.text and
51
- out << [node["type"] == "class" ? "Target Type" : "Subject", subj]
52
- node.xpath(ns("./inherit")).each { |i| out << ["Dependency", i.text] }
67
+ subj = node&.at(ns("./subject"))&.text and out << [rec_subj(node), subj]
68
+ node.xpath(ns("./inherit")).each do |i|
69
+ out << recommendation_attr_parse(i, "Dependency")
70
+ end
53
71
  node.xpath(ns("./classification")).each do |c|
54
- tag = c.at(ns("./tag")) or next
55
- value = c.at(ns("./value")) or next
56
- out << [tag.text.capitalize, value.text]
72
+ line = recommendation_attr_keyvalue(c, "tag", "value") and out << line
57
73
  end
58
74
  out
59
75
  end
60
76
 
77
+ def rec_subj(node)
78
+ %w(class conformanceclass).include?(node["type"]) ?
79
+ "Target Type" : "Subject"
80
+ end
81
+
82
+ def recommendation_attr_parse(node, label)
83
+ text = noko do |xml|
84
+ node.children.each { |n| parse(n, xml) }
85
+ end.join
86
+ [label, text]
87
+ end
88
+
89
+ def recommendation_attr_keyvalue(node, key, value)
90
+ tag = node.at(ns("./#{key}")) or return nil
91
+ value = node.at(ns("./#{value}")) or return nil
92
+ [tag.text.capitalize, value.text]
93
+ end
94
+
61
95
  def recommendation_attributes(node, out)
62
- ret = recommendation_attributes1(node)
63
- return if ret.empty?
64
- ret.each do |i|
96
+ recommendation_attributes1(node).each do |i|
65
97
  out.tr do |tr|
66
- tr.td i[0], **REQ_TBL_ATTR
67
- tr.td i[1], **REQ_TBL_ATTR
98
+ tr.td **REQ_TBL_ATTR do |td|
99
+ td << i[0]
100
+ end
101
+ tr.td **REQ_TBL_ATTR do |td|
102
+ td << i[1]
103
+ end
68
104
  end
69
105
  end
70
106
  end
@@ -118,107 +154,31 @@ module IsoDoc
118
154
  end
119
155
 
120
156
  def recommendation_parse(node, out)
121
- label = case node["type"]
122
- when "verification" then @labels["recommendationtest"]
123
- when "class" then @labels["recommendationclass"]
124
- else
125
- @recommendation_lbl
126
- end
127
- recommendation_parse1(node, out, label)
157
+ recommendation_parse0(node, out, "recommendation")
128
158
  end
129
159
 
130
- def requirement_parse(node, out)
131
- label = case node["type"]
132
- when "verification" then @labels["requirementtest"]
133
- when "class" then @labels["requirementclass"]
134
- else
135
- @requirement_lbl
136
- end
137
- recommendation_parse1(node, out, label)
138
- end
139
-
140
- def permission_parse(node, out)
160
+ def recommendation_parse0(node, out, r)
141
161
  label = case node["type"]
142
- when "verification" then @labels["permissiontest"]
143
- when "class" then @labels["permissionclass"]
144
- else
145
- @permission_lbl
162
+ when "verification" then @labels["#{r}test"]
163
+ when "class" then @labels["#{r}class"]
164
+ when "abstracttest" then @labels["abstracttest"]
165
+ when "conformanceclass" then @labels["conformanceclass"]
166
+ else
167
+ case r
168
+ when "recommendation" then @recommendation_lbl
169
+ when "requirement" then @requirement_lbl
170
+ when "permission" then @permission_lbl
171
+ end
146
172
  end
147
173
  recommendation_parse1(node, out, label)
148
174
  end
149
175
 
150
- FIRST_LVL_REQ = IsoDoc::Function::XrefGen::FIRST_LVL_REQ
151
-
152
- def sequential_permission_names(clause, klass, label)
153
- c = ::IsoDoc::Function::XrefGen::Counter.new
154
- clause.xpath(ns(".//#{klass}#{FIRST_LVL_REQ}")).each do |t|
155
- next if t["id"].nil? || t["id"].empty?
156
- id = c.increment(t).print
157
- @anchors[t["id"]] = anchor_struct(id, t, label, klass, t["unnumbered"])
158
- sequential_permission_children(t, id)
159
- end
160
- end
161
-
162
- def sequential_permission_children(t, id)
163
- sequential_permission_names1(t, id, "permission[not(@type = 'verification' or @type = 'class')]", @permission_lbl)
164
- sequential_permission_names1(t, id, "requirement[not(@type = 'verification' or @type = 'class')]", @requirement_lbl)
165
- sequential_permission_names1(t, id, "recommendation[not(@type = 'verification' or @type = 'class')]", @recommendation_lbl)
166
- sequential_permission_names1(t, id, "permission[@type = 'verification']", @labels["permissiontest"])
167
- sequential_permission_names1(t, id, "requirement[@type = 'verification']", @labels["requirementtest"])
168
- sequential_permission_names1(t, id, "recommendation[@type = 'verification']", @labels["recommendationtest"])
169
- sequential_permission_names1(t, id, "permission[@type = 'class']", @labels["permissionclass"])
170
- sequential_permission_names1(t, id, "requirement[@type = 'class']", @labels["requirementclass"])
171
- sequential_permission_names1(t, id, "recommendation[@type = 'class']", @labels["recommendationclass"])
172
- end
173
-
174
- def sequential_permission_names1(block, lbl, klass, label)
175
- c = ::IsoDoc::Function::XrefGen::Counter.new
176
- block.xpath(ns("./#{klass}")).each do |t|
177
- next if t["id"].nil? || t["id"].empty?
178
- id = "#{lbl}#{hierfigsep}#{c.increment(t).print}"
179
- @anchors[t["id"]] = anchor_struct(id, t, label, klass, t["unnumbered"])
180
- sequential_permission_children(t, id)
181
- end
176
+ def requirement_parse(node, out)
177
+ recommendation_parse0(node, out, "requirement")
182
178
  end
183
179
 
184
- def sequential_asset_names(clause)
185
- sequential_table_names(clause)
186
- sequential_figure_names(clause)
187
- sequential_formula_names(clause)
188
- sequential_permission_names(clause, "permission[not(@type = 'verification' or @type = 'class')]", @permission_lbl)
189
- sequential_permission_names(clause, "requirement[not(@type = 'verification' or @type = 'class')]", @requirement_lbl)
190
- sequential_permission_names(clause, "recommendation[not(@type = 'verification' or @type = 'class')]", @recommendation_lbl)
191
- sequential_permission_names(clause, "permission[@type = 'verification']", @labels["permissiontest"])
192
- sequential_permission_names(clause, "requirement[@type = 'verification']", @labels["requirementtest"])
193
- sequential_permission_names(clause, "recommendation[@type = 'verification']", @labels["recommendationtest"])
194
- sequential_permission_names(clause, "permission[@type = 'class']", @labels["permissionclass"])
195
- sequential_permission_names(clause, "requirement[@type = 'class']", @labels["requirementclass"])
196
- sequential_permission_names(clause, "recommendation[@type = 'class']", @labels["recommendationclass"])
197
- end
198
-
199
- def hierarchical_asset_names(clause, num)
200
- hierarchical_table_names(clause, num)
201
- hierarchical_figure_names(clause, num)
202
- hierarchical_formula_names(clause, num)
203
- hierarchical_permission_names(clause, num, "permission[not(@type = 'verification' or @type = 'class')]", @permission_lbl)
204
- hierarchical_permission_names(clause, num, "requirement[not(@type = 'verification' or @type = 'class')]", @requirement_lbl)
205
- hierarchical_permission_names(clause, num, "recommendation[not(@type = 'verification' or @type = 'class')]", @recommendation_lbl)
206
- hierarchical_permission_names(clause, num, "permission[@type = 'verification']", @labels["permissiontest"])
207
- hierarchical_permission_names(clause, num, "requirement[@type = 'verification']", @labels["requirementtest"])
208
- hierarchical_permission_names(clause, num, "recommendation[@type = 'verification']", @labels["recommendationtest"])
209
- hierarchical_permission_names(clause, num, "permission[@type = 'class']", @labels["permissionclass"])
210
- hierarchical_permission_names(clause, num, "requirement[@type = 'class']", @labels["requirementclass"])
211
- hierarchical_permission_names(clause, num, "recommendation[@type = 'class']", @labels["recommendationclass"])
212
- end
213
-
214
- def hierarchical_permission_names(clause, num, klass, label)
215
- c = ::IsoDoc::Function::XrefGen::Counter.new
216
- clause.xpath(ns(".//#{klass}#{FIRST_LVL_REQ}")).each do |t|
217
- next if t["id"].nil? || t["id"].empty?
218
- lbl = "#{num}#{hiersep}#{c.increment(t).print}"
219
- @anchors[t["id"]] = anchor_struct(lbl, t, label, klass, t["unnumbered"])
220
- sequential_permission_children(t, lbl)
221
- end
180
+ def permission_parse(node, out)
181
+ recommendation_parse0(node, out, "permission")
222
182
  end
223
183
  end
224
184
  end
@@ -0,0 +1,96 @@
1
+ module IsoDoc
2
+ module Ogc
3
+ module BaseConvert
4
+ FIRST_LVL_REQ = IsoDoc::Function::XrefGen::FIRST_LVL_REQ
5
+
6
+ def sequential_permission_names(clause, klass, label)
7
+ c = ::IsoDoc::Function::XrefGen::Counter.new
8
+ clause.xpath(ns(".//#{klass}#{FIRST_LVL_REQ}")).each do |t|
9
+ next if t["id"].nil? || t["id"].empty?
10
+ id = c.increment(t).print
11
+ @anchors[t["id"]] = anchor_struct(id, t, label, klass, t["unnumbered"])
12
+ l = t.at(ns("./label"))&.text and @reqtlabels[l] = t["id"]
13
+ sequential_permission_children(t, id)
14
+ end
15
+ end
16
+
17
+ def req_class_paths
18
+ { "class" => "@type = 'class'",
19
+ "test" => "@type = 'verification'",
20
+ "" => "not(@type = 'verification' or @type = 'class' or "\
21
+ "@type = 'abstracttest' or @type = 'conformanceclass')", }
22
+ end
23
+
24
+ def req_class_paths2
25
+ { "abstracttest" => "@type = 'abstracttest'",
26
+ "conformanceclass" => "@type = 'conformanceclass'", }
27
+ end
28
+
29
+ def sequential_permission_children(t, id)
30
+ req_class_paths.each do |k, v|
31
+ %w(permission requirement recommendation).each do |r|
32
+ sequential_permission_names1(t, id, "#{r}[#{v}]", @labels["#{r}#{k}"])
33
+ sequential_permission_names1(t, id, "#{r}[#{v}]", @labels["#{r}#{k}"])
34
+ sequential_permission_names1(t, id, "#{r}[#{v}]", @labels["#{r}#{k}"])
35
+ end
36
+ end
37
+ req_class_paths2.each do |k, v|
38
+ sequential_permission_names1(t, id, "*[#{v}]", @labels[k])
39
+ end
40
+ end
41
+
42
+ def sequential_permission_names1(block, lbl, klass, label)
43
+ c = ::IsoDoc::Function::XrefGen::Counter.new
44
+ block.xpath(ns("./#{klass}")).each do |t|
45
+ next if t["id"].nil? || t["id"].empty?
46
+ id = "#{lbl}#{hierfigsep}#{c.increment(t).print}"
47
+ @anchors[t["id"]] = anchor_struct(id, t, label, klass, t["unnumbered"])
48
+ sequential_permission_children(t, id)
49
+ end
50
+ end
51
+
52
+ def sequential_asset_names(clause)
53
+ sequential_table_names(clause)
54
+ sequential_figure_names(clause)
55
+ sequential_formula_names(clause)
56
+ req_class_paths.each do |k, v|
57
+ %w(permission requirement recommendation).each do |r|
58
+ sequential_permission_names(clause, "#{r}[#{v}]", @labels["#{r}#{k}"])
59
+ sequential_permission_names(clause, "#{r}[#{v}]", @labels["#{r}#{k}"])
60
+ sequential_permission_names(clause, "#{r}[#{v}]", @labels["#{r}#{k}"])
61
+ end
62
+ end
63
+ req_class_paths2.each do |k, v|
64
+ sequential_permission_names(clause, "*[#{v}]", @labels[k])
65
+ end
66
+ end
67
+
68
+ def hierarchical_asset_names(clause, num)
69
+ hierarchical_table_names(clause, num)
70
+ hierarchical_figure_names(clause, num)
71
+ hierarchical_formula_names(clause, num)
72
+ req_class_paths.each do |k, v|
73
+ %w(permission requirement recommendation).each do |r|
74
+ hierarchical_permission_names(clause, num, "#{r}[#{v}]", @labels["#{r}#{k}"])
75
+ hierarchical_permission_names(clause, num, "#{r}[#{v}]", @labels["#{r}#{k}"])
76
+ hierarchical_permission_names(clause, num, "#{r}[#{v}]", @labels["#{r}#{k}"])
77
+ end
78
+ end
79
+ req_class_paths2.each do |k, v|
80
+ hierarchical_permission_names(clause, num, "*[#{v}]", @labels[k])
81
+ end
82
+ end
83
+
84
+ def hierarchical_permission_names(clause, num, klass, label)
85
+ c = ::IsoDoc::Function::XrefGen::Counter.new
86
+ clause.xpath(ns(".//#{klass}#{FIRST_LVL_REQ}")).each do |t|
87
+ next if t["id"].nil? || t["id"].empty?
88
+ lbl = "#{num}#{hiersep}#{c.increment(t).print}"
89
+ @anchors[t["id"]] = anchor_struct(lbl, t, label, klass, t["unnumbered"])
90
+ l = t.at(ns("./label"))&.text and @reqtlabels[l] = t["id"]
91
+ sequential_permission_children(t, lbl)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end