metanorma-nist 1.2.8 → 1.2.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +3 -0
- data/.rubocop.yml +0 -4
- data/README.adoc +23 -3
- data/lib/asciidoctor/nist/basicdoc.rng +52 -3
- data/lib/asciidoctor/nist/boilerplate.rb +5 -3
- data/lib/asciidoctor/nist/cleanup.rb +4 -3
- data/lib/asciidoctor/nist/converter.rb +5 -2
- data/lib/asciidoctor/nist/front.rb +37 -46
- data/lib/asciidoctor/nist/front_id.rb +18 -7
- data/lib/asciidoctor/nist/isodoc.rng +114 -3
- data/lib/asciidoctor/nist/nist_intro.xml +9 -9
- data/lib/asciidoctor/nist/nist_intro_cswp.xml +9 -9
- data/lib/asciidoctor/nist/validate.rb +17 -6
- data/lib/isodoc/nist/base_convert.rb +2 -3
- data/lib/isodoc/nist/html/header_cswp.html +2 -3
- data/lib/isodoc/nist/html/html_nist_titlepage.html +5 -3
- data/lib/isodoc/nist/html/word_nist_titlepage.html +8 -8
- data/lib/isodoc/nist/html/word_nist_titlepage_cswp.html +2 -0
- data/lib/isodoc/nist/html_convert.rb +6 -8
- data/lib/isodoc/nist/metadata.rb +28 -40
- data/lib/isodoc/nist/metadata_id.rb +3 -7
- data/lib/isodoc/nist/nist.csts.xsl +4844 -0
- data/lib/isodoc/nist/nist.cswp.xsl +517 -292
- data/lib/isodoc/nist/nist.sp.xsl +503 -327
- data/lib/isodoc/nist/pdf_convert.rb +5 -1
- data/lib/isodoc/nist/presentation_xml_convert.rb +30 -10
- data/lib/isodoc/nist/refs.rb +4 -20
- data/lib/isodoc/nist/render.rb +42 -40
- data/lib/isodoc/nist/render_dates.rb +8 -9
- data/lib/isodoc/nist/word_convert.rb +5 -6
- data/lib/isodoc/nist/xref.rb +11 -5
- data/lib/metanorma/nist/processor.rb +12 -0
- data/lib/metanorma/nist/version.rb +1 -1
- data/metanorma-nist.gemspec +2 -2
- metadata +8 -8
- data/lib/metanorma/nist/fonts_manifest.yaml +0 -6
@@ -14,7 +14,11 @@ module IsoDoc
|
|
14
14
|
|
15
15
|
def pdf_stylesheet(docxml)
|
16
16
|
series = docxml&.at(ns("//bibdata/series/abbreviation"))&.text
|
17
|
-
series
|
17
|
+
case series
|
18
|
+
when "NIST CSWP" then "nist.cswp.xsl"
|
19
|
+
when "NIST CSTS" then "nist.csts.xsl"
|
20
|
+
else "nist.sp.xsl"
|
21
|
+
end
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
@@ -22,10 +22,8 @@ module IsoDoc
|
|
22
22
|
def get_linkend(node)
|
23
23
|
contents = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
|
24
24
|
return unless contents.empty?
|
25
|
-
link = anchor_linkend(node, docid_l10n(node["target"] ||
|
26
|
-
|
27
|
-
link += eref_localities(node.xpath(ns("./locality | ./localityStack")),
|
28
|
-
link)
|
25
|
+
link = anchor_linkend(node, docid_l10n(node["target"] || wrap_brackets(node['citeas'])))
|
26
|
+
link += eref_localities(node.xpath(ns("./locality | ./localityStack")), link)
|
29
27
|
non_locality_elems(node).each { |n| n.remove }
|
30
28
|
node.add_child(link)
|
31
29
|
end
|
@@ -57,15 +55,12 @@ module IsoDoc
|
|
57
55
|
elsif foreword = docxml.at(ns("//preface/foreword"))
|
58
56
|
foreword.next = keyword_clause(kw)
|
59
57
|
else
|
60
|
-
preface_init_insert_pt(docxml)&.children&.first&.
|
61
|
-
add_previous_sibling(keyword_clause(kw))
|
58
|
+
preface_init_insert_pt(docxml)&.children&.first&.add_previous_sibling(keyword_clause(kw))
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
65
62
|
def preface_init_insert_pt(docxml)
|
66
|
-
docxml.at(ns("//preface")) ||
|
67
|
-
docxml.at(ns("//sections")).
|
68
|
-
add_previous_sibling("<preface> </preface>").first
|
63
|
+
docxml.at(ns("//preface")) || docxml.at(ns("//sections")).add_previous_sibling("<preface> </preface>").first
|
69
64
|
end
|
70
65
|
|
71
66
|
def clause1(f)
|
@@ -73,8 +68,33 @@ module IsoDoc
|
|
73
68
|
super
|
74
69
|
end
|
75
70
|
|
71
|
+
def references(docxml)
|
72
|
+
docxml.xpath(ns("//references/bibitem")).each do |x|
|
73
|
+
bibitem(x)
|
74
|
+
end
|
75
|
+
@xrefs.parse docxml
|
76
|
+
end
|
77
|
+
|
78
|
+
def bracket_if_num(x)
|
79
|
+
return nil if x.nil?
|
80
|
+
x = x.text.sub(/^\[/, "").sub(/\]$/, "")
|
81
|
+
"[#{x}]"
|
82
|
+
end
|
83
|
+
|
84
|
+
def bibitem(x)
|
85
|
+
if f = x.at(ns("./formattedref"))
|
86
|
+
code = render_identifier(bibitem_ref_code(x))
|
87
|
+
f << " [#{code[1]}] " if code[1]
|
88
|
+
else
|
89
|
+
x.children = ::Iso690Render.render(x.to_xml)
|
90
|
+
end
|
91
|
+
if id = x.at(ns("./docidentifier[@type = 'metanorma']"))
|
92
|
+
id["display"] = "true"
|
93
|
+
id.children = bracket_if_num(id)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
76
97
|
include Init
|
77
98
|
end
|
78
99
|
end
|
79
100
|
end
|
80
|
-
|
data/lib/isodoc/nist/refs.rb
CHANGED
@@ -8,11 +8,7 @@ module IsoDoc
|
|
8
8
|
# we are taking the ref number/code out as prefix to reference
|
9
9
|
def nonstd_bibitem(list, b, ordinal, bibliography)
|
10
10
|
list.p **attr_code(iso_bibitem_entry_attrs(b, bibliography)) do |r|
|
11
|
-
if !b.at(ns("./formattedref"))
|
12
|
-
nist_reference_format(b, r)
|
13
|
-
else
|
14
11
|
reference_format(b, r)
|
15
|
-
end
|
16
12
|
end
|
17
13
|
end
|
18
14
|
|
@@ -21,13 +17,11 @@ module IsoDoc
|
|
21
17
|
end
|
22
18
|
|
23
19
|
def reference_format(b, r)
|
24
|
-
code =
|
25
|
-
|
26
|
-
r << "#{code[0]} "
|
20
|
+
if code = b.at(ns("./docidentifier[@display = 'true']"))
|
21
|
+
r << code.text
|
27
22
|
insert_tab(r, 1)
|
28
23
|
end
|
29
24
|
reference_format1(b, r)
|
30
|
-
r << " [#{code[1]}] " if code[1]
|
31
25
|
end
|
32
26
|
|
33
27
|
def reference_format1(b, r)
|
@@ -52,22 +46,12 @@ module IsoDoc
|
|
52
46
|
super || prefix == "NIST"
|
53
47
|
end
|
54
48
|
|
55
|
-
def nist_reference_format(b, r)
|
56
|
-
code = render_identifier(bibitem_ref_code(b))
|
57
|
-
if code[0]
|
58
|
-
r << "#{code[0]} "
|
59
|
-
insert_tab(r, 1)
|
60
|
-
end
|
61
|
-
bibitem = b.dup.to_xml
|
62
|
-
r.parent.add_child ::Iso690Render.render(bibitem, true)
|
63
|
-
end
|
64
|
-
|
65
49
|
def bibliography_parse(node, out)
|
66
50
|
return if node["hidden"] == "true"
|
67
51
|
title = node&.at(ns("./title"))&.text || ""
|
68
52
|
out.div do |div|
|
69
53
|
unless suppress_biblio_title(node)
|
70
|
-
|
54
|
+
clause_parse_title(node, div, node.at(ns("./title")), out)
|
71
55
|
end
|
72
56
|
biblio_list(node, div, true)
|
73
57
|
end
|
@@ -80,7 +64,7 @@ module IsoDoc
|
|
80
64
|
next if f["hidden"] == "true"
|
81
65
|
out.div do |div|
|
82
66
|
div.h1 **{ class: "Section3" } do |h1|
|
83
|
-
|
67
|
+
f&.at(ns("./title"))&.children.each { |n| parse(n, h1) }
|
84
68
|
end
|
85
69
|
biblio_list(f, div, false)
|
86
70
|
end
|
data/lib/isodoc/nist/render.rb
CHANGED
@@ -18,6 +18,10 @@ module Iso690Render
|
|
18
18
|
doc&.at("./medium")&.text
|
19
19
|
end
|
20
20
|
|
21
|
+
def self.blank?(x)
|
22
|
+
x.nil? || x.empty?
|
23
|
+
end
|
24
|
+
|
21
25
|
=begin
|
22
26
|
def self.edition(doc)
|
23
27
|
x = doc.at("./edition")
|
@@ -51,19 +55,14 @@ module Iso690Render
|
|
51
55
|
end
|
52
56
|
|
53
57
|
def self.series_title(doc)
|
54
|
-
s = doc.at("./series[@type = 'main']") ||
|
55
|
-
doc.at("./series[not(@type)]") ||
|
56
|
-
doc.at("./series")
|
58
|
+
s = doc.at("./series[@type = 'main']") || doc.at("./series[not(@type)]") || doc.at("./series")
|
57
59
|
s&.at("./title")&.text
|
58
60
|
end
|
59
61
|
|
60
62
|
def self.series(doc, type)
|
61
|
-
s = doc.at("./series[@type = 'main']") ||
|
62
|
-
doc.at("./series[not(@type)]") ||
|
63
|
-
doc.at("./series")
|
63
|
+
s = doc.at("./series[@type = 'main']") || doc.at("./series[not(@type)]") || doc.at("./series")
|
64
64
|
return "" unless s
|
65
|
-
f = s.at("./formattedref")
|
66
|
-
return f.text if f
|
65
|
+
f = s.at("./formattedref") and return f.text
|
67
66
|
t = s.at("./title")
|
68
67
|
a = s.at("./abbreviation")
|
69
68
|
n = s.at("./number")
|
@@ -72,7 +71,7 @@ module Iso690Render
|
|
72
71
|
rev = doc&.at(".//edition")&.text&.sub(/^Revision /, "")
|
73
72
|
ret = ""
|
74
73
|
if t
|
75
|
-
title = included(type) ? wrap(t.text, " <
|
74
|
+
title = included(type) ? wrap(t.text, " <em>", "</em>") : wrap(t.text, " ", "")
|
76
75
|
ret += title
|
77
76
|
ret += " (#{a.text.sub(/^NIST /, "")})" if a
|
78
77
|
end
|
@@ -97,16 +96,13 @@ module Iso690Render
|
|
97
96
|
|
98
97
|
def self.standardidentifier1(id)
|
99
98
|
r = ""
|
100
|
-
r += "#{id['type']} " if id["type"] and
|
101
|
-
!%w(ISO IEC NIST).include? id["type"]
|
99
|
+
r += "#{id['type']} " if id["type"] and !%w(ISO IEC NIST).include? id["type"]
|
102
100
|
r += id.text
|
103
101
|
r
|
104
102
|
end
|
105
103
|
|
106
104
|
def self.uri(doc)
|
107
|
-
uri = doc.at("./uri[@type = 'doi']") ||
|
108
|
-
doc.at("./uri[@type = 'uri']") ||
|
109
|
-
doc.at("./uri")
|
105
|
+
uri = doc.at("./uri[@type = 'doi']") || doc.at("./uri[@type = 'uri']") || doc.at("./uri")
|
110
106
|
uri&.text
|
111
107
|
end
|
112
108
|
|
@@ -120,7 +116,7 @@ module Iso690Render
|
|
120
116
|
end
|
121
117
|
|
122
118
|
def self.wrap(text, startdelim = " ", enddelim = ".")
|
123
|
-
return "" if
|
119
|
+
return "" if blank?(text)
|
124
120
|
"#{startdelim}#{text}#{enddelim}"
|
125
121
|
end
|
126
122
|
|
@@ -145,8 +141,7 @@ module Iso690Render
|
|
145
141
|
def self.extent1(localities)
|
146
142
|
ret = []
|
147
143
|
localities.each do |l|
|
148
|
-
ret << extent2(l["type"] || "page",
|
149
|
-
l.at("./referenceFrom"), l.at("./referenceTo"))
|
144
|
+
ret << extent2(l["type"] || "page", l.at("./referenceFrom"), l.at("./referenceTo"))
|
150
145
|
end
|
151
146
|
ret.join(", ")
|
152
147
|
end
|
@@ -199,53 +194,60 @@ module Iso690Render
|
|
199
194
|
end
|
200
195
|
end
|
201
196
|
|
197
|
+
# converting bibitem to <formattedref> + <docidentifier>
|
202
198
|
def self.parse(doc, embedded = false)
|
203
|
-
ret = ""
|
204
199
|
f = doc.at("./formattedref") and
|
205
|
-
return embedded ? f.children.to_xml :
|
200
|
+
return embedded ? f.children.to_xml : doc.to_xml
|
206
201
|
|
202
|
+
ret = ""
|
207
203
|
type = type(doc)
|
208
204
|
container = doc.at("./relation[@type='includedIn']")
|
209
205
|
if container && !date(doc) && date(container&.at("./bibitem"))
|
210
|
-
doc <<
|
211
|
-
( container&.at("./bibitem/date[@type = 'issued' or @type = 'published' or "\
|
206
|
+
doc << ( container&.at("./bibitem/date[@type = 'issued' or @type = 'published' or "\
|
212
207
|
"@type = 'circulated']")&.remove )
|
213
208
|
end
|
214
|
-
ser = series_title(doc)
|
215
209
|
dr = draft(doc)
|
216
|
-
|
210
|
+
cr = creatornames(doc)
|
217
211
|
# NIST has seen fit to completely change rendering based on the type of publication.
|
218
|
-
if
|
219
|
-
|
220
|
-
else
|
221
|
-
ret += embedded ? wrap(creatornames(doc), "", "") : wrap(creatornames(doc), "", "")
|
212
|
+
if series_title(doc) == "NIST Federal Information Processing Standards"
|
213
|
+
cr = "National Institute of Standards and Technology"
|
222
214
|
end
|
215
|
+
pub = placepub(doc)
|
216
|
+
|
217
|
+
ret += wrap(cr, "", "")
|
223
218
|
if dr
|
224
219
|
mdy = MMMddyyyy(date(doc)) and ret += wrap(mdy, " (", ")")
|
225
220
|
else
|
226
221
|
yr = year(date(doc)) and ret += wrap(yr, " (", ")")
|
227
222
|
end
|
228
|
-
ret += included(type) ? wrap(title(doc)) : wrap(title(doc), " <
|
229
|
-
ret += wrap(medium(doc), " [", "]
|
223
|
+
ret += included(type) ? wrap(title(doc), " ", "") : wrap(title(doc), " <em>", "</em>")
|
224
|
+
ret += wrap(medium(doc), " [", "]")
|
230
225
|
#ret += wrap(edition(doc), "", " edition.")
|
231
|
-
|
232
|
-
|
226
|
+
if cr != pub
|
227
|
+
ret += wrap(pub, " (", ")")
|
228
|
+
end
|
229
|
+
if cr != pub && pub && !pub.empty? && (dr || !blank?(series(doc, type)))
|
230
|
+
ret += ","
|
231
|
+
end
|
233
232
|
if dr
|
234
233
|
ret += " Draft (#{dr})"
|
235
234
|
end
|
236
235
|
ret += wrap(series(doc, type), " ", "")
|
237
|
-
ret +=
|
238
|
-
ret += wrap(
|
239
|
-
ret += wrap(
|
240
|
-
ret += wrap(
|
241
|
-
ret += wrap(accessLocation(doc), " At: ", ".")
|
236
|
+
ret += wrap(date(doc), ", ", "")
|
237
|
+
ret += wrap(standardidentifier(doc), ". ", "") unless is_nist(doc)
|
238
|
+
ret += wrap(uri(doc), ". ", "")
|
239
|
+
ret += wrap(accessLocation(doc), ". At: ", "")
|
242
240
|
if container
|
243
|
-
ret += wrap(parse(container.at("./bibitem"), true), " In: ", "")
|
241
|
+
ret += wrap(parse(container.at("./bibitem"), true), ". In: ", "")
|
244
242
|
locality = doc.xpath("./extent")
|
245
|
-
ret += wrap(extent(locality))
|
243
|
+
ret += wrap(extent(locality), ", " , "")
|
246
244
|
else
|
247
|
-
ret += wrap(extent(doc.xpath("./extent")))
|
245
|
+
ret += wrap(extent(doc.xpath("./extent")), ", ", "")
|
248
246
|
end
|
249
|
-
embedded
|
247
|
+
if !embedded
|
248
|
+
ret += "."
|
249
|
+
end
|
250
|
+
|
251
|
+
embedded ? ret : "<formattedref>#{ret}</formattedref>#{doc.xpath('./docidentifier').to_xml}"
|
250
252
|
end
|
251
253
|
end
|
@@ -17,8 +17,7 @@ module Iso690Render
|
|
17
17
|
ret += " (updated #{updated})" if updated
|
18
18
|
return ret
|
19
19
|
end
|
20
|
-
pub = date1(doc&.at("./date[@type = 'circulated']")) and
|
21
|
-
return pub
|
20
|
+
pub = date1(doc&.at("./date[@type = 'circulated']")) and return pub
|
22
21
|
date1(doc&.at("./date"))
|
23
22
|
end
|
24
23
|
|
@@ -31,12 +30,12 @@ module Iso690Render
|
|
31
30
|
return nil if isodate.nil?
|
32
31
|
return isodate if isodate == "--"
|
33
32
|
arr = isodate.split("-")
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
33
|
+
if arr.size == 1 and (/^\d+$/.match isodate)
|
34
|
+
Date.new(*arr.map(&:to_i)).strftime("%Y")
|
35
|
+
elsif arr.size == 2
|
36
|
+
Date.new(*arr.map(&:to_i)).strftime("%B %Y")
|
37
|
+
else
|
38
|
+
Date.parse(isodate).strftime("%B %d, %Y")
|
39
|
+
end
|
41
40
|
end
|
42
41
|
end
|
@@ -22,10 +22,11 @@ module IsoDoc
|
|
22
22
|
|
23
23
|
def convert1(docxml, filename, dir)
|
24
24
|
@series = docxml&.at(ns("//bibdata/series/abbreviation"))&.text
|
25
|
+
@cswp = ["NIST CSWP", "NIST CSTS"].include?(@series)
|
25
26
|
@bibliographycount =
|
26
27
|
docxml.xpath(ns("//bibliography/references | //annex/references | "\
|
27
28
|
"//bibliography/clause/references")).size
|
28
|
-
if @
|
29
|
+
if @cswp
|
29
30
|
@wordstylesheet_name = html_doc_path("wordstyle_cswp.scss")
|
30
31
|
@standardstylesheet_name = html_doc_path("nist_cswp.scss")
|
31
32
|
@wordcoverpage = html_doc_path("word_nist_titlepage_cswp.html")
|
@@ -36,10 +37,8 @@ module IsoDoc
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def default_fonts(options)
|
39
|
-
{ bodyfont:
|
40
|
-
|
41
|
-
headerfont: (options[:script] == "Hans" ? '"SimHei",sans-serif' :
|
42
|
-
'"Arial",sans-serif'),
|
40
|
+
{ bodyfont: '"Times New Roman",serif',
|
41
|
+
headerfont: '"Arial",sans-serif',
|
43
42
|
monospacefont: '"Courier New",monospace',
|
44
43
|
normalfontsize: "12.0pt",
|
45
44
|
footnotefontsize: "10.0pt",
|
@@ -111,7 +110,7 @@ module IsoDoc
|
|
111
110
|
auth1 = docxml&.at("//div[@id = 'authority6']")&.remove
|
112
111
|
dest1 and auth1 and dest1.each { |d| d.replace(auth1) }
|
113
112
|
insert = docxml.at("//div[@class = 'WordSection2']")
|
114
|
-
if @
|
113
|
+
if @cswp
|
115
114
|
auth = docxml&.at("//div[@class = 'authority']")&.remove || return
|
116
115
|
insert.children.first.add_previous_sibling(auth)
|
117
116
|
end
|
data/lib/isodoc/nist/xref.rb
CHANGED
@@ -4,6 +4,9 @@ require "fileutils"
|
|
4
4
|
|
5
5
|
module IsoDoc
|
6
6
|
module NIST
|
7
|
+
class Counter < IsoDoc::XrefGen::Counter
|
8
|
+
end
|
9
|
+
|
7
10
|
class Xref < IsoDoc::Xref
|
8
11
|
SECTIONS_XPATH =
|
9
12
|
"//foreword | //introduction | //reviewnote | //executivesummary | //annex | "\
|
@@ -17,15 +20,18 @@ module IsoDoc
|
|
17
20
|
@in_execsummary = true
|
18
21
|
hierarchical_asset_names(d.xpath("//xmlns:executivesummary"), "ES")
|
19
22
|
@in_execsummary = false
|
20
|
-
|
23
|
+
c = Counter.new
|
24
|
+
clause_names(d, c)
|
21
25
|
middle_section_asset_names(d)
|
22
26
|
termnote_anchor_names(d)
|
23
27
|
termexample_anchor_names(d)
|
24
28
|
end
|
25
29
|
|
26
30
|
def back_anchor_names(docxml)
|
27
|
-
|
28
|
-
|
31
|
+
i = Counter.new("@")
|
32
|
+
docxml.xpath(ns("//annex")).each do |c|
|
33
|
+
i.increment(c)
|
34
|
+
annex_names(c, i.print)
|
29
35
|
end
|
30
36
|
docxml.xpath(ns("//bibliography/clause | "\
|
31
37
|
"//bibliography/references")).each do |b|
|
@@ -44,8 +50,8 @@ module IsoDoc
|
|
44
50
|
|
45
51
|
def clause_names(docxml, sect_num)
|
46
52
|
q = "//xmlns:sections/child::*"
|
47
|
-
docxml.xpath(q).
|
48
|
-
section_names(c,
|
53
|
+
docxml.xpath(q).each do |c|
|
54
|
+
section_names(c, sect_num, 1)
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
@@ -17,6 +17,18 @@ module Metanorma
|
|
17
17
|
)
|
18
18
|
end
|
19
19
|
|
20
|
+
def fonts_manifest
|
21
|
+
{
|
22
|
+
"Arial" => nil,
|
23
|
+
"Calibri" => nil,
|
24
|
+
"Cambria" => nil,
|
25
|
+
"Courier" => nil,
|
26
|
+
"Courier New" => nil,
|
27
|
+
"STIX Two Math" => nil,
|
28
|
+
"Times New Roman" => nil,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
20
32
|
def version
|
21
33
|
"Metanorma::NIST #{Metanorma::NIST::VERSION}"
|
22
34
|
end
|
data/metanorma-nist.gemspec
CHANGED
@@ -30,8 +30,8 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_dependency "iso-639"
|
31
31
|
spec.add_dependency "tzinfo-data" # we need this for windows only
|
32
32
|
|
33
|
-
spec.add_dependency "metanorma-standoc", "~> 1.
|
34
|
-
spec.add_dependency "isodoc", "~> 1.
|
33
|
+
spec.add_dependency "metanorma-standoc", "~> 1.8.2"
|
34
|
+
spec.add_dependency "isodoc", "~> 1.5.0"
|
35
35
|
#spec.add_dependency "relaton-nist", "~> 0.3.0"
|
36
36
|
|
37
37
|
spec.add_development_dependency "byebug", "~> 9.1"
|