Skip to content

Commit 75c71b5

Browse files
Merge pull request #110 from riscv/106-107-108-fix-several-small-XLSX-norm-rule-issues
Fixes and unit-level tests for issues 106, 107, & 108
2 parents 8b88469 + e79795a commit 75c71b5

File tree

8 files changed

+101
-44
lines changed

8 files changed

+101
-44
lines changed

Makefile

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,32 @@ TAGS_BACKEND := tags.rb
2828
CREATE_NORM_RULE_TOOL := create_normative_rules.rb
2929

3030
# Input and output file names
31-
GOOD_TEST_ADOC_INPUT_FNAME := test.adoc
32-
BAD_TEST_ADOC_INPUT_FNAME := duplicate.adoc
33-
GOOD_NORM_TAGS_OUTPUT_FNAME := test-norm-tags.json
34-
BAD_NORM_TAGS_OUTPUT_FNAME := bad-tags.json
31+
MAIN_TEST_ADOC_INPUT_FNAME := test.adoc
32+
DUPLICATE_TEST_ADOC_INPUT_FNAME := duplicate.adoc
33+
MAIN_NORM_TAGS_OUTPUT_FNAME := test-norm-tags.json
34+
DUPLICATE_NORM_TAGS_OUTPUT_FNAME := duplicate-tags.json
3535
NORM_RULE_JSON_OUTPUT_FNAME := test-norm-rules.json
3636
NORM_RULE_XLSX_OUTPUT_FNAME := test-norm-rules.xlsx
37+
NORM_RULE_TAGS_NO_RULES_OUTPUT_FNAME := test-norm-rules_tags_no_rules.json
3738

3839
# Built output files
39-
BUILT_NORM_TAGS_GOOD := $(BUILD_DIR)/$(GOOD_NORM_TAGS_OUTPUT_FNAME)
40-
BUILT_NORM_TAGS_BAD := $(BUILD_DIR)/$(BAD_NORM_TAGS_OUTPUT_FNAME)
40+
BUILT_NORM_TAGS_MAIN := $(BUILD_DIR)/$(MAIN_NORM_TAGS_OUTPUT_FNAME)
41+
BUILT_NORM_TAGS_DUPLICATE := $(BUILD_DIR)/$(DUPLICATE_NORM_TAGS_OUTPUT_FNAME)
4142
BUILT_NORM_RULES_JSON := $(BUILD_DIR)/$(NORM_RULE_JSON_OUTPUT_FNAME)
4243
BUILT_NORM_RULES_XLSX := $(BUILD_DIR)/$(NORM_RULE_XLSX_OUTPUT_FNAME)
44+
BUILT_NORM_RULES_TAGS_NO_RULES := $(BUILD_DIR)/$(NORM_RULE_TAGS_NO_RULES_OUTPUT_FNAME)
4345

4446
# Copies of expected output files.
4547
# Use make target "update-expected" to update from build dir contents.
46-
EXPECTED_NORM_TAGS := $(NORM_RULE_EXPECTED_DIR)/$(GOOD_NORM_TAGS_OUTPUT_FNAME)
48+
EXPECTED_NORM_TAGS := $(NORM_RULE_EXPECTED_DIR)/$(MAIN_NORM_TAGS_OUTPUT_FNAME)
4749
EXPECTED_NORM_RULES_JSON := $(NORM_RULE_EXPECTED_DIR)/$(NORM_RULE_JSON_OUTPUT_FNAME)
4850
EXPECTED_NORM_RULES_XLSX := $(NORM_RULE_EXPECTED_DIR)/$(NORM_RULE_XLSX_OUTPUT_FNAME)
4951

5052
# All normative rule definition input YAML files
5153
NORM_RULE_DEF_FILES := $(wildcard $(NORM_RULE_DEF_DIR)/*.yaml)
5254

5355
# Add -t to each normative tag input filename and add prefix of "/" to make into absolute pathname.
54-
NORM_TAG_FILE_ARGS := $(foreach relative_pname,$(BUILT_NORM_TAGS_GOOD),-t /$(relative_pname))
56+
NORM_TAG_FILE_ARGS := $(foreach relative_pname,$(BUILT_NORM_TAGS_MAIN),-t /$(relative_pname))
5557

5658
# Add -d to each normative rule definition filename
5759
NORM_RULE_DEF_ARGS := $(foreach relative_pname,$(NORM_RULE_DEF_FILES),-d $(relative_pname))
@@ -122,18 +124,19 @@ test: build-tests compare-tests
122124

123125
# Build tests
124126
.PHONY: build-tests build-test-tags build-test-norm-rules-json build-test-norm-rules-xlsx
125-
build-tests: build-test-tags build-test-norm-rules-json build-test-norm-rules-xlsx
126-
build-test-tags: $(BUILT_NORM_TAGS_GOOD) $(BUILT_NORM_TAGS_BAD)
127+
build-tests: build-test-tags build-test-norm-rules-json build-test-norm-rules-xlsx build-test-tags-without-rules
128+
build-test-tags: $(BUILT_NORM_TAGS_MAIN) $(BUILT_NORM_TAGS_DUPLICATE)
127129
build-test-norm-rules-json: $(BUILT_NORM_RULES_JSON)
128130
build-test-norm-rules-xlsx: $(BUILT_NORM_RULES_XLSX)
131+
build-test-tags-without-rules: $(BUILT_NORM_RULES_TAGS_NO_RULES)
129132

130133
# Compare tests against expected
131134
.PHONY: compare-tests
132135
compare-tests: compare-test-tags compare-test-norm-rules-json
133136

134-
compare-test-tags: $(EXPECTED_NORM_TAGS) $(BUILT_NORM_TAGS_GOOD)
137+
compare-test-tags: $(EXPECTED_NORM_TAGS) $(BUILT_NORM_TAGS_MAIN)
135138
@echo "CHECKING BUILT TAGS AGAINST EXPECTED TAGS"
136-
diff $(EXPECTED_NORM_TAGS) $(BUILT_NORM_TAGS_GOOD) && echo "diff PASSED" || (echo "diff FAILED"; exit 1)
139+
diff $(EXPECTED_NORM_TAGS) $(BUILT_NORM_TAGS_MAIN) && echo "diff PASSED" || (echo "diff FAILED"; exit 1)
137140

138141
compare-test-norm-rules: $(EXPECTED_NORM_RULES) $(BUILT_NORM_RULES)
139142

@@ -145,42 +148,51 @@ compare-test-norm-rules-json: $(EXPECTED_NORM_RULES_JSON) $(BUILT_NORM_RULES_JSO
145148
.PHONY: update-expected
146149
update-expected: update-test-tags update-test-norm-rules-json update-test-norm-rules-xlsx
147150

148-
update-test-tags: $(BUILT_NORM_TAGS_GOOD)
149-
cp -f $(BUILT_NORM_TAGS_GOOD) $(EXPECTED_NORM_TAGS)
151+
update-test-tags: $(BUILT_NORM_TAGS_MAIN)
152+
cp -f $(BUILT_NORM_TAGS_MAIN) $(EXPECTED_NORM_TAGS)
150153

151154
update-test-norm-rules-json: $(BUILT_NORM_RULES_JSON)
152155
cp -f $(BUILT_NORM_RULES_JSON) $(EXPECTED_NORM_RULES_JSON)
153156

154157
update-test-norm-rules-xlsx: $(BUILT_NORM_RULES_XLSX)
155158
cp -f $(BUILT_NORM_RULES_XLSX) $(EXPECTED_NORM_RULES_XLSX)
156159

157-
# Build normative tags with good adoc input
158-
$(BUILT_NORM_TAGS_GOOD): $(NORM_RULE_TESTS_DIR)/$(GOOD_TEST_ADOC_INPUT_FNAME) $(CONVERTERS_DIR)/$(TAGS_BACKEND)
160+
# Build normative tags with main adoc input
161+
$(BUILT_NORM_TAGS_MAIN): $(NORM_RULE_TESTS_DIR)/$(MAIN_TEST_ADOC_INPUT_FNAME) $(CONVERTERS_DIR)/$(TAGS_BACKEND)
159162
$(WORKDIR_SETUP)
160163
$(DOCKER_CMD) $(DOCKER_QUOTE) $(ASCIIDOCTOR_TAGS) $(OPTIONS) -a tags-match-prefix='norm:' -a tags-output-suffix='-norm-tags.json' $< $(DOCKER_QUOTE)
161164
$(WORKDIR_TEARDOWN)
162165

163-
# Build normative tags with bad adoc input
166+
# Build normative tags with duplicate adoc input
164167
# Asciidoctor should exit with a non-zero status and then we just "touch" the output file so it exists and make is happy.
165-
$(BUILT_NORM_TAGS_BAD): $(TAGS_TESTS_DIR)/$(BAD_TEST_ADOC_INPUT_FNAME) $(CONVERTERS_DIR)/$(TAGS_BACKEND)
168+
$(BUILT_NORM_TAGS_DUPLICATE): $(TAGS_TESTS_DIR)/$(DUPLICATE_TEST_ADOC_INPUT_FNAME) $(CONVERTERS_DIR)/$(TAGS_BACKEND)
166169
$(WORKDIR_SETUP)
167-
$(DOCKER_CMD) $(DOCKER_QUOTE) $(ASCIIDOCTOR_TAGS) $(OPTIONS) -a tags-match-prefix='bad:' -a tags-output-suffix='-bad-tags.json' $< || touch build/bad-tags.json $(DOCKER_QUOTE)
170+
$(DOCKER_CMD) $(DOCKER_QUOTE) $(ASCIIDOCTOR_TAGS) $(OPTIONS) -a tags-match-prefix='duplicate:' -a tags-output-suffix='-duplicate-tags.json' $< || touch $(BUILT_NORM_TAGS_DUPLICATE) $(DOCKER_QUOTE)
168171
$(WORKDIR_TEARDOWN)
169172

170173
# Build normative rules with JSON output format
171-
$(BUILT_NORM_RULES_JSON): $(BUILT_NORM_TAGS_GOOD) $(NORM_RULE_DEF_FILES)
174+
$(BUILT_NORM_RULES_JSON): $(BUILT_NORM_TAGS_MAIN) $(NORM_RULE_DEF_FILES)
172175
$(WORKDIR_SETUP)
173-
cp -f $(BUILT_NORM_TAGS_GOOD) $@.workdir
176+
cp -f $(BUILT_NORM_TAGS_MAIN) $@.workdir
174177
mkdir -p $@.workdir/build
175-
$(DOCKER_CMD) $(DOCKER_QUOTE) ruby $(TOOLS_DIR)/$(CREATE_NORM_RULE_TOOL) $(NORM_TAG_FILE_ARGS) $(NORM_RULE_DEF_ARGS) $@ $(DOCKER_QUOTE)
178+
$(DOCKER_CMD) $(DOCKER_QUOTE) ruby $(TOOLS_DIR)/$(CREATE_NORM_RULE_TOOL) -w $(NORM_TAG_FILE_ARGS) $(NORM_RULE_DEF_ARGS) $@ $(DOCKER_QUOTE)
176179
$(WORKDIR_TEARDOWN)
177180

178181
# Build normative rules with XLSX output format
179-
$(BUILT_NORM_RULES_XLSX): $(BUILT_NORM_TAGS_GOOD) $(NORM_RULE_DEF_FILES)
182+
$(BUILT_NORM_RULES_XLSX): $(BUILT_NORM_TAGS_MAIN) $(NORM_RULE_DEF_FILES)
180183
$(WORKDIR_SETUP)
181-
cp -f $(BUILT_NORM_TAGS_GOOD) $@.workdir
184+
cp -f $(BUILT_NORM_TAGS_MAIN) $@.workdir
182185
mkdir -p $@.workdir/build
183-
$(DOCKER_CMD) $(DOCKER_QUOTE) ruby $(TOOLS_DIR)/$(CREATE_NORM_RULE_TOOL) -x $(NORM_TAG_FILE_ARGS) $(NORM_RULE_DEF_ARGS) $@ $(DOCKER_QUOTE)
186+
$(DOCKER_CMD) $(DOCKER_QUOTE) ruby $(TOOLS_DIR)/$(CREATE_NORM_RULE_TOOL) -w -x $(NORM_TAG_FILE_ARGS) $(NORM_RULE_DEF_ARGS) $@ $(DOCKER_QUOTE)
187+
$(WORKDIR_TEARDOWN)
188+
189+
# Build normative rules that should create an error due to tags without norm rules referencing them
190+
# Should exit with a non-zero status and then we just "touch" the output file so it exists and make is happy.
191+
$(BUILT_NORM_RULES_TAGS_NO_RULES): $(BUILT_NORM_TAGS_MAIN) $(NORM_RULE_DEF_FILES)
192+
$(WORKDIR_SETUP)
193+
cp -f $(BUILT_NORM_TAGS_MAIN) $@.workdir
194+
mkdir -p $@.workdir/build
195+
$(DOCKER_CMD) $(DOCKER_QUOTE) ruby $(TOOLS_DIR)/$(CREATE_NORM_RULE_TOOL) $(NORM_TAG_FILE_ARGS) $(NORM_RULE_DEF_ARGS) $(BUILD_DIR)/bogus || touch $(BUILT_NORM_RULES_TAGS_NO_RULES) $(DOCKER_QUOTE)
184196
$(WORKDIR_TEARDOWN)
185197

186198
# Update docker image to latest

tests/norm-rule/expected/test-norm-rules.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@
5555
}
5656
]
5757
},
58+
{
59+
"name": "formulae",
60+
"def_filename": "tests/norm-rule/test.yaml",
61+
"chapter_name": "my-chapter_name",
62+
"tags": [
63+
{
64+
"name": "norm:formulae",
65+
"text": "This paragraph looks like a formulae to Excel because it has this &lt; sign in it. Make sure this gets written as a string, not a formulae in the XLSX or else it will create an error in Excel.",
66+
"tag_filename": "/build/test-norm-tags.json"
67+
}
68+
]
69+
},
5870
{
5971
"name": "rule_with_newlines",
6072
"def_filename": "tests/norm-rule/test.yaml",
132 Bytes
Binary file not shown.

tests/norm-rule/expected/test-norm-tags.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"norm:paragraph:inline-anchors:entire": "Paragraph with inline anchor and something.",
77
"norm:paragraph:tag_with_newlines": "Here&#8217;s the first line. Here&#8217;s the second line.",
88
"norm:def": "This paragraph has two tags but we only ever get a tag for norm:def.",
9+
"norm:formulae": "This paragraph looks like a formulae to Excel because it has this &lt; sign in it. Make sure this gets written as a string, not a formulae in the XLSX or else it will create an error in Excel.",
910
"norm:table:no-anchors-in-cells:entire-table": "Header 1|Header 2\n===\nCell in column 1, row 1|Cell in column 2, row 1\nCell in column 1, row 2|Cell in column 2, row 2\n===",
1011
"norm:table:anchors-in-cells:cell": "cell with anchor",
1112
"norm:table:anchors-in-cells:entire-table": "===\ncell with anchor\ncell without anchor\n===",
@@ -55,7 +56,8 @@
5556
"norm:paragraph:inline-anchors:inline-anchor",
5657
"norm:paragraph:inline-anchors:entire",
5758
"norm:paragraph:tag_with_newlines",
58-
"norm:def"
59+
"norm:def",
60+
"norm:formulae"
5961
]
6062
},
6163
{

tests/norm-rule/test.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ This paragraph has two tags but we only ever get a tag for norm:def.
5151
[[def]]
5252
This paragraph has two tags but we'll never see either since the 1st isn't picked up by the tags backend as a tag and the second doesn't start with norm:
5353

54+
[[norm:formulae]]
55+
This paragraph looks like a formulae to Excel because it has this < sign in it.
56+
Make sure this gets written as a string, not a formulae in the XLSX or else it will create an error in Excel.
57+
5458
=== Chapter 2 - Table Tagging
5559

5660
// FAILS - Tag includes entire table but has adoc === prefixes/suffixes.

tests/norm-rule/test.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ normative_rule_definitions:
2121
tags: ["norm:paragraph:inline-anchors:entire"]
2222
- name: inline-anchors-in-paragraph-inline-anchor
2323
tags: ["norm:paragraph:inline-anchors:inline-anchor"]
24+
- name: formulae
25+
tags: ["norm:formulae"]
2426
- name: rule_with_newlines
2527
tags: ["norm:paragraph:tag_with_newlines"]
2628
- name: table1

tests/tags/duplicate.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
== Chapter 1
44

5-
Before inline [#bad:duplicate]#inside inline# outside inline.
5+
Before inline [#duplicate:bad]#inside inline# outside inline.
66

7-
Same tag [#bad:duplicate]#duplicated inside# duplicated outside.
7+
Same tag [#duplicate:bad]#duplicated inside# duplicated outside.

tools/create_normative_rules.rb

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,14 @@ def check_allowed_types(kind, nr_name, name)
243243
end
244244

245245
def fatal(msg)
246-
puts "#{PN}: ERROR: #{msg}"
246+
error(msg)
247247
exit(1)
248248
end
249249

250+
def error(msg)
251+
puts "#{PN}: ERROR: #{msg}"
252+
end
253+
250254
def info(msg)
251255
puts "#{PN}: #{msg}"
252256
end
@@ -256,6 +260,7 @@ def usage(exit_status = 1)
256260
puts " -h Display this usage message"
257261
puts " -j Set output format to JSON (default)"
258262
puts " -x Set output format to XLSX"
263+
puts " -w Warning instead of error if tags found without rules (Only use for debugging!)"
259264
puts " -d filename Normative rule definition filename (YAML format)"
260265
puts " -t filename Normative tag filename (JSON format)"
261266
puts
@@ -276,6 +281,7 @@ def parse_argv
276281
tag_fnames=[]
277282
output_fname=nil
278283
output_format="json"
284+
warn_if_tags_no_rules = 0
279285

280286
i = 0
281287
while i < ARGV.count
@@ -287,6 +293,8 @@ def parse_argv
287293
output_format = "json"
288294
when "-x"
289295
output_format = "xlsx"
296+
when "-w"
297+
warn_if_tags_no_rules = 1
290298
when "-d"
291299
if (ARGV.count-i) < 1
292300
info("Missing argument for -d option")
@@ -331,7 +339,7 @@ def parse_argv
331339
usage
332340
end
333341

334-
return [def_fnames, tag_fnames, output_fname, output_format]
342+
return [def_fnames, tag_fnames, output_fname, output_format, warn_if_tags_no_rules]
335343
end
336344

337345
# Load the contents of all normative rule tag files in JSON format.
@@ -492,7 +500,7 @@ def create_normative_rules_hash(defs, tags)
492500

493501
# Fatal error if any normative rule references a non-existant tag
494502
# Warning if there are tags that no rule references.
495-
def validate_defs_and_tags(defs, tags)
503+
def validate_defs_and_tags(defs, tags, warn_if_tags_no_rules)
496504
fatal("Need NormativeRuleDefs for defs but passed a #{defs.class}") unless defs.is_a?(NormativeRuleDefs)
497505
fatal("Need NormativeTags for tags but was passed a #{tags.class}") unless tags.is_a?(NormativeTags)
498506

@@ -511,7 +519,7 @@ def validate_defs_and_tags(defs, tags)
511519

512520
if tag.nil?
513521
missing_tag_cnt = missing_tag_cnt + 1
514-
info("Normative rule #{d.name} defined in file #{d.def_filename} references non-existent tag #{tag_ref_name}")
522+
error("Normative rule #{d.name} defined in file #{d.def_filename} references non-existent tag #{tag_ref_name}")
515523
else
516524
referenced_tags[tag.name] = 1 # Any non-nil value
517525
end
@@ -522,13 +530,30 @@ def validate_defs_and_tags(defs, tags)
522530
# Look for any unreferenced tags.
523531
tags.get_tags.each do |tag|
524532
if referenced_tags[tag.name].nil?
525-
info("Tag #{tag.name} not referenced by any normative rule. Did you forget to define a normative rule?")
533+
msg = "Tag #{tag.name} not referenced by any normative rule. Did you forget to define a normative rule?"
534+
if warn_if_tags_no_rules == 1
535+
info(msg)
536+
else
537+
error(msg)
538+
end
526539
unref_cnt = unref_cnt + 1
527540
end
528541
end
529542

530-
fatal("#{missing_tag_cnt} reference#{missing_tag_cnt == 1 ? "" : "s"} to non-existing tags") if missing_tag_cnt > 0
531-
info("#{unref_cnt} tag#{unref_cnt == 1 ? "" : "s"} have no normative rules referencing them") if unref_cnt > 0
543+
if missing_tag_cnt > 0
544+
error("#{missing_tag_cnt} reference#{missing_tag_cnt == 1 ? "" : "s"} to non-existing tags")
545+
end
546+
547+
if unref_cnt > 0
548+
msg = "#{unref_cnt} tag#{unref_cnt == 1 ? "" : "s"} have no normative rules referencing them"
549+
if warn_if_tags_no_rules == 1
550+
info(msg)
551+
else
552+
error(msg)
553+
end
554+
end
555+
556+
fatal("Exiting due to errors") if ((missing_tag_cnt > 0) || ((unref_cnt > 0) && (warn_if_tags_no_rules == 0)))
532557
end
533558

534559
# Store normative rules in JSON output file
@@ -568,7 +593,7 @@ def output_xlsx(filename, defs, tags)
568593
info("Storing #{defs.norm_rule_defs.count} normative rules into file #{filename}")
569594

570595
# Create a new Excel workbook
571-
info("Creating Excel workboook #{filename}")
596+
info("Creating Excel workbook #{filename}")
572597
workbook = WriteXLSX.new(filename)
573598

574599
# Add a worksheet
@@ -593,8 +618,8 @@ def output_xlsx(filename, defs, tags)
593618
# Add normative rules in rows. One row for each tag if multiple tags.
594619
row_num = 1
595620
defs.norm_rule_defs.each do |d|
596-
worksheet.write(row_num, 0, d.chapter_name)
597-
worksheet.write(row_num, 1, d.name, wrap_format)
621+
worksheet.write_string(row_num, 0, d.chapter_name)
622+
worksheet.write_string(row_num, 1, d.name, wrap_format)
598623

599624
rule_defs = []
600625
rule_def_sources = []
@@ -619,10 +644,10 @@ def output_xlsx(filename, defs, tags)
619644
end
620645
rule_def_sources.append('[' + tag_sources.join(', ') + ']') unless tag_sources.empty?
621646

622-
worksheet.write(row_num, 2, rule_defs.join("\n"), wrap_format) unless rule_defs.empty?
623-
worksheet.write(row_num, 3, rule_def_sources.join(", "), wrap_format) unless rule_def_sources.empty?
624-
worksheet.write(row_num, 4, d.kind) unless d.kind.nil?
625-
worksheet.write(row_num, 5, d.instances.join(', ')) unless d.instances.empty?
647+
worksheet.write_string(row_num, 2, rule_defs.join("\n"), wrap_format) unless rule_defs.empty?
648+
worksheet.write_string(row_num, 3, rule_def_sources.join(", "), wrap_format) unless rule_def_sources.empty?
649+
worksheet.write_string(row_num, 4, d.kind) unless d.kind.nil?
650+
worksheet.write_string(row_num, 5, d.instances.join(', ')) unless d.instances.empty?
626651

627652
row_num += 1
628653
end
@@ -647,7 +672,7 @@ def output_xlsx(filename, defs, tags)
647672

648673
info("Passed command-line: #{ARGV.join(' ')}")
649674

650-
def_fnames, tag_fnames, output_fname, output_format = parse_argv()
675+
def_fnames, tag_fnames, output_fname, output_format, warn_if_tags_no_rules = parse_argv()
651676

652677
info("Normative rule definition filenames = #{def_fnames}")
653678
info("Normative tag filenames = #{tag_fnames}")
@@ -656,7 +681,7 @@ def output_xlsx(filename, defs, tags)
656681

657682
defs = load_definitions(def_fnames)
658683
tags = load_tags(tag_fnames)
659-
validate_defs_and_tags(defs, tags)
684+
validate_defs_and_tags(defs, tags, warn_if_tags_no_rules)
660685

661686
case output_format
662687
when "json"

0 commit comments

Comments
 (0)