markdown_exec 3.1.1 → 3.3.0
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/CHANGELOG.md +46 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +3 -3
- data/bats/block-type-ux-auto.bats +1 -1
- data/bats/block-type-ux-default.bats +1 -1
- data/bats/block-type-ux-echo-hash-transform.bats +1 -1
- data/bats/block-type-ux-echo-hash.bats +2 -2
- data/bats/block-type-ux-exec-hash-transform.bats +8 -0
- data/bats/block-type-ux-exec-hash.bats +15 -0
- data/bats/block-type-ux-exec.bats +1 -1
- data/bats/block-type-ux-force.bats +9 -0
- data/bats/block-type-ux-formats.bats +8 -0
- data/bats/block-type-ux-readonly.bats +1 -1
- data/bats/block-type-ux-row-format.bats +1 -1
- data/bats/block-type-ux-transform.bats +1 -1
- data/bats/import-directive-parameter-symbols.bats +9 -0
- data/bats/import-duplicates.bats +4 -2
- data/bats/import-parameter-symbols.bats +8 -0
- data/bats/markup.bats +1 -1
- data/bats/options.bats +1 -1
- data/bin/tab_completion.sh +5 -1
- data/docs/dev/block-type-ux-echo-hash-transform.md +14 -12
- data/docs/dev/block-type-ux-exec-hash-transform.md +37 -0
- data/docs/dev/block-type-ux-exec-hash.md +93 -0
- data/docs/dev/block-type-ux-force.md +20 -0
- data/docs/dev/block-type-ux-formats.md +58 -0
- data/docs/dev/hexdump_format.md +267 -0
- data/docs/dev/import/parameter-symbols.md +6 -0
- data/docs/dev/import-directive-parameter-symbols.md +9 -0
- data/docs/dev/import-parameter-symbols-template.md +24 -0
- data/docs/dev/import-parameter-symbols.md +6 -0
- data/docs/dev/load-vars-state-demo.md +35 -0
- data/docs/ux-blocks-examples.md +3 -3
- data/examples/import_with_substitution_demo.md +130 -26
- data/examples/imports/organism_template.md +86 -29
- data/lib/cached_nested_file_reader.rb +265 -27
- data/lib/constants.rb +8 -1
- data/lib/env_interface.rb +13 -7
- data/lib/evaluate_shell_expressions.rb +1 -0
- data/lib/fcb.rb +123 -19
- data/lib/format_table.rb +56 -23
- data/lib/fout.rb +5 -0
- data/lib/hash_delegator.rb +1196 -337
- data/lib/markdown_exec/version.rb +2 -1
- data/lib/markdown_exec.rb +2 -0
- data/lib/mdoc.rb +12 -6
- data/lib/menu.src.yml +150 -33
- data/lib/menu.yml +126 -31
- data/lib/string_util.rb +80 -0
- data/lib/table_extractor.rb +170 -64
- data/lib/ww.rb +328 -30
- metadata +18 -2
data/lib/fcb.rb
CHANGED
@@ -25,7 +25,7 @@ def parse_yaml_of_ux_block(
|
|
25
25
|
exec: export['exec'],
|
26
26
|
force: export['force'],
|
27
27
|
init: export['init'],
|
28
|
-
menu_format: export['format'] || export['menu_format'] || menu_format
|
28
|
+
menu_format: export['format'] || export['menu_format'], # || menu_format,####
|
29
29
|
name: name,
|
30
30
|
prompt: export['prompt'] || prompt,
|
31
31
|
readonly: export['readonly'].nil? ? false : export['readonly'],
|
@@ -93,7 +93,8 @@ module MarkdownExec
|
|
93
93
|
# 2024-08-04 match nickname
|
94
94
|
# may not exist if block name is duplicated
|
95
95
|
def delete_matching_name!(dependencies)
|
96
|
-
dependencies.delete(@attrs[:
|
96
|
+
dependencies.delete(@attrs[:id]) ||
|
97
|
+
dependencies.delete(@attrs[:dname]) ||
|
97
98
|
dependencies.delete(@attrs[:nickname]) ||
|
98
99
|
dependencies.delete(@attrs[:oname]) ||
|
99
100
|
dependencies.delete(@attrs.pub_name) ||
|
@@ -127,6 +128,7 @@ module MarkdownExec
|
|
127
128
|
# @return [Object] The modified functional code block with updated
|
128
129
|
# summary attributes.
|
129
130
|
def for_menu!(
|
131
|
+
appopts:,
|
130
132
|
block_calls_scan:,
|
131
133
|
block_name_match:,
|
132
134
|
block_name_nick_match:,
|
@@ -162,12 +164,19 @@ module MarkdownExec
|
|
162
164
|
when Hash
|
163
165
|
export = parse_yaml_of_ux_block(
|
164
166
|
data,
|
165
|
-
menu_format: menu_format,
|
166
167
|
prompt: prompt
|
167
168
|
)
|
168
169
|
|
170
|
+
if !export.menu_format || export.menu_format.empty?
|
171
|
+
format_symbol = option_to_format_ux_block(export)
|
172
|
+
export.menu_format = appopts[format_symbol]
|
173
|
+
if !export.menu_format || export.menu_format.empty?
|
174
|
+
export.menu_format = appopts[:menu_ux_row_format]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
@attrs[:oname] = oname = format(export.menu_format, export.to_h)
|
178
|
+
|
169
179
|
@attrs[:center] = table_center
|
170
|
-
oname = @attrs[:oname] = format(export.menu_format, export.to_h)
|
171
180
|
@attrs[:readonly] = export.readonly
|
172
181
|
else
|
173
182
|
# triggered by an empty or non-YAML block
|
@@ -180,7 +189,8 @@ module MarkdownExec
|
|
180
189
|
end
|
181
190
|
|
182
191
|
@attrs[:dname] = HashDelegator.indent_all_lines(
|
183
|
-
|
192
|
+
# yield the text and option name for the color
|
193
|
+
(yield oname, option_to_decorate_ux_block),
|
184
194
|
@attrs[:indent]
|
185
195
|
)
|
186
196
|
|
@@ -198,6 +208,38 @@ module MarkdownExec
|
|
198
208
|
end.join("\n")
|
199
209
|
end
|
200
210
|
|
211
|
+
def self.is_allow?(export)
|
212
|
+
export&.allow&.present?
|
213
|
+
end
|
214
|
+
|
215
|
+
def is_allow?
|
216
|
+
FCB.is_allow?(export)
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.is_echo?(export)
|
220
|
+
export&.echo&.present?
|
221
|
+
end
|
222
|
+
|
223
|
+
def is_echo?
|
224
|
+
FCB.is_echo?(export)
|
225
|
+
end
|
226
|
+
|
227
|
+
def self.is_edit?(export)
|
228
|
+
export&.edit&.present?
|
229
|
+
end
|
230
|
+
|
231
|
+
def is_edit?
|
232
|
+
FCB.is_edit?(export)
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.is_exec?(export)
|
236
|
+
export&.exec&.present?
|
237
|
+
end
|
238
|
+
|
239
|
+
def is_exec?
|
240
|
+
FCB.is_exec?(export)
|
241
|
+
end
|
242
|
+
|
201
243
|
def self.act_source(export)
|
202
244
|
# If `false`, the UX block is not activated.
|
203
245
|
# If one of `:allow`, `:echo`, `:edit`, or `:exec` is specified,
|
@@ -205,18 +247,22 @@ module MarkdownExec
|
|
205
247
|
# If not present, the default value is `:edit`.
|
206
248
|
if export.act.nil?
|
207
249
|
export.act = if export.init.to_s == 'false'
|
208
|
-
if export.allow.present?
|
250
|
+
# if export.allow.present?
|
251
|
+
if FCB.is_allow?(export)
|
209
252
|
UxActSource::ALLOW
|
210
|
-
elsif export.echo.present?
|
253
|
+
# elsif export.echo.present?
|
254
|
+
elsif FCB.is_echo?(export)
|
211
255
|
UxActSource::ECHO
|
212
|
-
elsif export.edit.present?
|
256
|
+
# elsif export.edit.present?
|
257
|
+
elsif FCB.is_edit?(export)
|
213
258
|
UxActSource::EDIT
|
214
|
-
elsif export.exec.present?
|
259
|
+
# elsif export.exec.present?
|
260
|
+
elsif FCB.is_exec?(export)
|
215
261
|
UxActSource::EXEC
|
216
262
|
else
|
217
263
|
UxActSource::EDIT
|
218
264
|
end
|
219
|
-
elsif
|
265
|
+
elsif FCB.is_allow?(export)
|
220
266
|
UxActSource::ALLOW
|
221
267
|
else
|
222
268
|
UxActSource::EDIT
|
@@ -236,13 +282,15 @@ module MarkdownExec
|
|
236
282
|
# `:allow`, `:default`, `:echo`, or `:exec` is present.
|
237
283
|
if export.init.nil?
|
238
284
|
export.init = case
|
239
|
-
when
|
285
|
+
when FCB.is_allow?(export)
|
240
286
|
UxActSource::ALLOW
|
241
287
|
when export.default.present?
|
242
288
|
UxActSource::DEFAULT
|
243
|
-
when export.echo.present?
|
289
|
+
# when export.echo.present?
|
290
|
+
when FCB.is_echo?(export)
|
244
291
|
UxActSource::ECHO
|
245
|
-
when export.exec.present?
|
292
|
+
# when export.exec.present?
|
293
|
+
when FCB.is_exec?(export)
|
246
294
|
UxActSource::EXEC
|
247
295
|
else
|
248
296
|
UxActSource::FALSE
|
@@ -255,7 +303,8 @@ module MarkdownExec
|
|
255
303
|
# :reek:ManualDispatch
|
256
304
|
# 2024-08-04 match nickname
|
257
305
|
def is_dependency_of?(dependency_names)
|
258
|
-
dependency_names.include?(@attrs[:
|
306
|
+
dependency_names.include?(@attrs[:id]) ||
|
307
|
+
dependency_names.include?(@attrs[:dname]) ||
|
259
308
|
dependency_names.include?(@attrs[:nickname]) ||
|
260
309
|
dependency_names.include?(@attrs[:oname]) ||
|
261
310
|
dependency_names.include?(@attrs.pub_name) ||
|
@@ -271,11 +320,16 @@ module MarkdownExec
|
|
271
320
|
end
|
272
321
|
|
273
322
|
def is_named?(name)
|
274
|
-
|
275
|
-
@attrs[:
|
276
|
-
|
277
|
-
@attrs
|
278
|
-
|
323
|
+
if /^ItrBlk/.match(name)
|
324
|
+
@attrs[:id] == name
|
325
|
+
else
|
326
|
+
@attrs[:id] == name ||
|
327
|
+
@attrs[:dname] == name ||
|
328
|
+
@attrs[:nickname] == name ||
|
329
|
+
@attrs[:oname] == name ||
|
330
|
+
@attrs.pub_name == name ||
|
331
|
+
@attrs[:s2title] == name
|
332
|
+
end
|
279
333
|
end
|
280
334
|
|
281
335
|
# true if this is a line split block
|
@@ -332,6 +386,54 @@ module MarkdownExec
|
|
332
386
|
end
|
333
387
|
end
|
334
388
|
|
389
|
+
# calc the decoration sybol for the current block
|
390
|
+
def option_to_decorate_ux_block
|
391
|
+
symbol_or_hash = BLOCK_TYPE_COLOR_OPTIONS[@attrs[:type]]
|
392
|
+
if @attrs[:type] == BlockType::UX
|
393
|
+
# only UX blocks accept a symbol or a hash
|
394
|
+
if symbol_or_hash.is_a? Hash
|
395
|
+
# default to the first symbol
|
396
|
+
symbol = symbol_or_hash.first.last
|
397
|
+
symbol_or_hash.keys.each do |key|
|
398
|
+
if key == true
|
399
|
+
symbol = symbol_or_hash[key]
|
400
|
+
break
|
401
|
+
elsif symbol_or_hash[key].present? && send(key)
|
402
|
+
symbol = symbol_or_hash[key]
|
403
|
+
break
|
404
|
+
end
|
405
|
+
end
|
406
|
+
symbol
|
407
|
+
else
|
408
|
+
# only symbol
|
409
|
+
symbol_or_hash
|
410
|
+
end
|
411
|
+
else
|
412
|
+
# only symbol
|
413
|
+
symbol_or_hash
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
def option_to_format_ux_block(export)
|
418
|
+
if export.readonly
|
419
|
+
:menu_ux_row_format_readonly
|
420
|
+
else
|
421
|
+
case FCB.act_source(export)
|
422
|
+
when UxActSource::ALLOW
|
423
|
+
:menu_ux_row_format_allow
|
424
|
+
when UxActSource::ECHO
|
425
|
+
:menu_ux_row_format_echo
|
426
|
+
when UxActSource::EDIT
|
427
|
+
:menu_ux_row_format_edit
|
428
|
+
when UxActSource::EXEC
|
429
|
+
:menu_ux_row_format_exec
|
430
|
+
else
|
431
|
+
# this UX block does not have a format, treat as editable
|
432
|
+
:menu_ux_row_format_edit
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
335
437
|
def respond_to_missing?(method_name, include_private = false)
|
336
438
|
@attrs.key?(method_name.to_sym) || super
|
337
439
|
end
|
@@ -361,6 +463,7 @@ module MarkdownExec
|
|
361
463
|
end
|
362
464
|
|
363
465
|
# Expand variables in attributes
|
466
|
+
# @return [void]
|
364
467
|
def expand_variables_in_attributes!(pattern, replacements)
|
365
468
|
@attrs[:raw_dname] ||= @attrs[:dname]
|
366
469
|
@attrs[:dname] = @attrs[:dname]&.gsub(pattern) do |match|
|
@@ -380,6 +483,7 @@ module MarkdownExec
|
|
380
483
|
# Replace variables in each line of `body` if `body` is present
|
381
484
|
return unless @attrs[:body]
|
382
485
|
|
486
|
+
# save body for YAML and re-interpretation
|
383
487
|
@attrs[:raw_body] ||= @attrs[:body]
|
384
488
|
@attrs[:body] = @attrs[:body]&.map do |line|
|
385
489
|
if line.empty?
|
data/lib/format_table.rb
CHANGED
@@ -141,7 +141,10 @@ module MarkdownTableFormatter
|
|
141
141
|
end
|
142
142
|
|
143
143
|
def format_table__hs(
|
144
|
-
|
144
|
+
column_count:,
|
145
|
+
lines:,
|
146
|
+
table:,
|
147
|
+
decorate: nil,
|
145
148
|
table_width: nil,
|
146
149
|
truncate: true
|
147
150
|
)
|
@@ -152,7 +155,9 @@ module MarkdownTableFormatter
|
|
152
155
|
end
|
153
156
|
end
|
154
157
|
|
155
|
-
rows = raw_lines_into_row_role_cells(
|
158
|
+
rows = raw_lines_into_row_role_cells(
|
159
|
+
lines, column_count, delimiter: table[:delimiter]
|
160
|
+
)
|
156
161
|
|
157
162
|
alignment_indicators, column_widths =
|
158
163
|
calculate_column_alignment_and_widths(rows, column_count)
|
@@ -182,18 +187,22 @@ module MarkdownTableFormatter
|
|
182
187
|
result
|
183
188
|
end
|
184
189
|
|
185
|
-
def raw_lines_into_row_role_cells(
|
190
|
+
def raw_lines_into_row_role_cells(
|
191
|
+
lines, column_count, delimiter:
|
192
|
+
)
|
186
193
|
role = :header_row
|
187
194
|
counter = -1
|
188
195
|
|
189
196
|
ret = []
|
190
197
|
lines.each do |line|
|
191
|
-
line +=
|
198
|
+
line += delimiter unless line.end_with?(delimiter)
|
199
|
+
|
192
200
|
counter += 1
|
193
201
|
|
194
202
|
role = role_for_raw_row(role, line)
|
195
203
|
counter = reset_counter_if_needed(role, counter)
|
196
|
-
cells = split_decorated_row_into_cells(line, column_count
|
204
|
+
cells = split_decorated_row_into_cells(line, column_count,
|
205
|
+
delimiter: delimiter)
|
197
206
|
ret << OpenStruct.new(cells: cells, role: role, counter: counter)
|
198
207
|
end
|
199
208
|
ret
|
@@ -220,8 +229,8 @@ module MarkdownTableFormatter
|
|
220
229
|
end
|
221
230
|
end
|
222
231
|
|
223
|
-
def split_decorated_row_into_cells(line, column_count)
|
224
|
-
cells = line.split(
|
232
|
+
def split_decorated_row_into_cells(line, column_count, delimiter: '|')
|
233
|
+
cells = line.split(delimiter).map(&:strip)[1..-1]
|
225
234
|
cells&.slice(0, column_count)&.fill('', cells.length...column_count)
|
226
235
|
end
|
227
236
|
end
|
@@ -239,11 +248,12 @@ class TestMarkdownTableFormatter < Minitest::Test
|
|
239
248
|
'| Row 2 Col 1 | Row 2 Col 2 | Row 2 Col 3 |'
|
240
249
|
]
|
241
250
|
@column_count = 3
|
251
|
+
@table = { delimiter: '|' }
|
242
252
|
end
|
243
253
|
|
244
254
|
def test_format_table
|
245
255
|
result = MarkdownTableFormatter.format_table(
|
246
|
-
column_count: @column_count, lines: @lines
|
256
|
+
column_count: @column_count, lines: @lines, table: @table
|
247
257
|
)
|
248
258
|
expected = [
|
249
259
|
'| Header 1 | Header 2 | Header 3 |',
|
@@ -259,7 +269,8 @@ class TestMarkdownTableFormatter < Minitest::Test
|
|
259
269
|
result = MarkdownTableFormatter.format_table(
|
260
270
|
column_count: @column_count,
|
261
271
|
decorate: decorate,
|
262
|
-
lines: @lines
|
272
|
+
lines: @lines,
|
273
|
+
table: @table
|
263
274
|
)
|
264
275
|
expected = [
|
265
276
|
'| HEADER 1 | HEADER 2 | HEADER 3 |',
|
@@ -280,7 +291,8 @@ class TestMarkdownTableFormatter < Minitest::Test
|
|
280
291
|
]
|
281
292
|
result = MarkdownTableFormatter.format_table(
|
282
293
|
lines: lines_with_empty,
|
283
|
-
column_count: @column_count
|
294
|
+
column_count: @column_count,
|
295
|
+
table: @table
|
284
296
|
)
|
285
297
|
expected = [
|
286
298
|
'| Header 1 | Header 2 | Header 3 |',
|
@@ -299,7 +311,8 @@ class TestMarkdownTableFormatter < Minitest::Test
|
|
299
311
|
]
|
300
312
|
result = MarkdownTableFormatter.format_table(
|
301
313
|
lines: lines_with_alignment,
|
302
|
-
column_count: @column_count
|
314
|
+
column_count: @column_count,
|
315
|
+
table: @table
|
303
316
|
)
|
304
317
|
expected = [
|
305
318
|
'| Header 1 | Header 2 | Header 3 |',
|
@@ -310,6 +323,10 @@ class TestMarkdownTableFormatter < Minitest::Test
|
|
310
323
|
end
|
311
324
|
|
312
325
|
class TestFormatTable < Minitest::Test
|
326
|
+
def setup
|
327
|
+
@table = { delimiter: '|' }
|
328
|
+
end
|
329
|
+
|
313
330
|
def test_basic_formatting
|
314
331
|
lines = [
|
315
332
|
'| Species| Genus| Family',
|
@@ -326,7 +343,8 @@ class TestFormatTable < Minitest::Test
|
|
326
343
|
]
|
327
344
|
assert_equal expected, MarkdownTableFormatter.format_table(
|
328
345
|
lines: lines,
|
329
|
-
column_count: column_count
|
346
|
+
column_count: column_count,
|
347
|
+
table: @table
|
330
348
|
)
|
331
349
|
end
|
332
350
|
|
@@ -344,7 +362,8 @@ class TestFormatTable < Minitest::Test
|
|
344
362
|
]
|
345
363
|
assert_equal expected, MarkdownTableFormatter.format_table(
|
346
364
|
lines: lines,
|
347
|
-
column_count: column_count
|
365
|
+
column_count: column_count,
|
366
|
+
table: @table
|
348
367
|
)
|
349
368
|
end
|
350
369
|
|
@@ -364,7 +383,8 @@ class TestFormatTable < Minitest::Test
|
|
364
383
|
def test_empty_input
|
365
384
|
assert_equal [], MarkdownTableFormatter.format_table(
|
366
385
|
lines: [],
|
367
|
-
column_count: 3
|
386
|
+
column_count: 3,
|
387
|
+
table: @table
|
368
388
|
)
|
369
389
|
end
|
370
390
|
|
@@ -382,7 +402,8 @@ class TestFormatTable < Minitest::Test
|
|
382
402
|
]
|
383
403
|
assert_equal expected, MarkdownTableFormatter.format_table(
|
384
404
|
lines: lines,
|
385
|
-
column_count: column_count
|
405
|
+
column_count: column_count,
|
406
|
+
table: @table
|
386
407
|
)
|
387
408
|
end
|
388
409
|
|
@@ -398,12 +419,17 @@ class TestFormatTable < Minitest::Test
|
|
398
419
|
]
|
399
420
|
assert_equal expected, MarkdownTableFormatter.format_table(
|
400
421
|
lines: lines,
|
401
|
-
column_count: column_count
|
422
|
+
column_count: column_count,
|
423
|
+
table: @table
|
402
424
|
)
|
403
425
|
end
|
404
426
|
end
|
405
427
|
|
406
428
|
class TestFormatTable2 < Minitest::Test
|
429
|
+
def setup
|
430
|
+
@table = { delimiter: '|' }
|
431
|
+
end
|
432
|
+
|
407
433
|
def test_basic_formatting
|
408
434
|
lines = [
|
409
435
|
'| Name | Age | City |',
|
@@ -417,7 +443,8 @@ class TestFormatTable2 < Minitest::Test
|
|
417
443
|
]
|
418
444
|
assert_equal expected_output, MarkdownTableFormatter.format_table(
|
419
445
|
lines: lines,
|
420
|
-
column_count: 3
|
446
|
+
column_count: 3,
|
447
|
+
table: @table
|
421
448
|
)
|
422
449
|
end
|
423
450
|
|
@@ -434,7 +461,8 @@ class TestFormatTable2 < Minitest::Test
|
|
434
461
|
]
|
435
462
|
assert_equal expected_output, MarkdownTableFormatter.format_table(
|
436
463
|
lines: lines,
|
437
|
-
column_count: 3
|
464
|
+
column_count: 3,
|
465
|
+
table: @table
|
438
466
|
)
|
439
467
|
end
|
440
468
|
|
@@ -451,7 +479,8 @@ class TestFormatTable2 < Minitest::Test
|
|
451
479
|
]
|
452
480
|
assert_equal expected_output, MarkdownTableFormatter.format_table(
|
453
481
|
lines: lines,
|
454
|
-
column_count: 4
|
482
|
+
column_count: 4,
|
483
|
+
table: @table
|
455
484
|
)
|
456
485
|
end
|
457
486
|
|
@@ -468,7 +497,8 @@ class TestFormatTable2 < Minitest::Test
|
|
468
497
|
]
|
469
498
|
assert_equal expected_output, MarkdownTableFormatter.format_table(
|
470
499
|
lines: lines,
|
471
|
-
column_count: 3
|
500
|
+
column_count: 3,
|
501
|
+
table: @table
|
472
502
|
)
|
473
503
|
end
|
474
504
|
|
@@ -477,7 +507,8 @@ class TestFormatTable2 < Minitest::Test
|
|
477
507
|
expected_output = ['| Name | Age | City |']
|
478
508
|
assert_equal expected_output, MarkdownTableFormatter.format_table(
|
479
509
|
lines: lines,
|
480
|
-
column_count: 3
|
510
|
+
column_count: 3,
|
511
|
+
table: @table
|
481
512
|
)
|
482
513
|
end
|
483
514
|
|
@@ -486,7 +517,8 @@ class TestFormatTable2 < Minitest::Test
|
|
486
517
|
expected_output = []
|
487
518
|
assert_equal expected_output, MarkdownTableFormatter.format_table(
|
488
519
|
lines: lines,
|
489
|
-
column_count: 3
|
520
|
+
column_count: 3,
|
521
|
+
table: @table
|
490
522
|
)
|
491
523
|
end
|
492
524
|
|
@@ -501,7 +533,8 @@ class TestFormatTable2 < Minitest::Test
|
|
501
533
|
]
|
502
534
|
assert_equal expected_output, MarkdownTableFormatter.format_table(
|
503
535
|
lines: lines,
|
504
|
-
column_count: 3
|
536
|
+
column_count: 3,
|
537
|
+
table: @table
|
505
538
|
)
|
506
539
|
end
|
507
540
|
end
|
data/lib/fout.rb
CHANGED
@@ -33,6 +33,11 @@ class FOut
|
|
33
33
|
puts str
|
34
34
|
end
|
35
35
|
|
36
|
+
# `puts` guarantees exactly one line break per item it prints. For each
|
37
|
+
# argument (and for each element when given an Array), it appends a newline
|
38
|
+
# only if the string does not already end with "\n". If it does, `puts`
|
39
|
+
# does not add another. Net effect: trailing newlines in your data are
|
40
|
+
# consumed rather than duplicated, so "Line\n" does not create a blank line.
|
36
41
|
def fout_list(str)
|
37
42
|
puts str
|
38
43
|
end
|