markdown_exec 3.5.2 → 3.6.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +1 -1
  5. data/bats/block-type-shell-context-eval.bats +48 -0
  6. data/bats/block-type-ux-echo.bats +1 -1
  7. data/bats/block-type-ux-force.bats +1 -1
  8. data/bats/block-type-ux-invalid.bats +1 -1
  9. data/bats/block-type-ux-require.bats +1 -1
  10. data/bats/document-shell.bats +2 -2
  11. data/bats/import.bats +1 -1
  12. data/bats/load-vars-state-demo.bats +4 -4
  13. data/bin/tab_completion.sh +3 -3
  14. data/docs/dev/bats-document-configuration.md +1 -1
  15. data/docs/dev/block-type-shell-context-eval.md +52 -0
  16. data/docs/dev/block-type-shell-require-ux.md +6 -2
  17. data/docs/dev/block-type-ux-echo.md +3 -3
  18. data/docs/dev/block-type-ux-force.md +1 -1
  19. data/docs/dev/block-type-ux-require-chained.md +1 -1
  20. data/docs/dev/block-type-ux-require.md +2 -2
  21. data/docs/dev/import-parameter-symbols.md +1 -1
  22. data/docs/dev/linked-file.md +1 -1
  23. data/docs/dev/load-vars-state-demo.md +1 -1
  24. data/docs/dev/requiring-blocks.md +1 -1
  25. data/docs/dev/specs.md +2 -2
  26. data/docs/shell-script-evaluation.md +78 -0
  27. data/examples/link-blocks-vars.md +2 -2
  28. data/examples/linked.md +1 -1
  29. data/examples/linked1.md +2 -9
  30. data/examples/opts-blocks.md +2 -2
  31. data/examples/port-blocks.md +1 -1
  32. data/examples/variable-expansion.md +1 -1
  33. data/lib/cached_nested_file_reader.rb +10 -7
  34. data/lib/hash_delegator.rb +325 -284
  35. data/lib/input_sequencer.rb +4 -3
  36. data/lib/link_history.rb +76 -28
  37. data/lib/markdown_exec/version.rb +1 -1
  38. data/lib/mdoc.rb +93 -65
  39. data/lib/menu.src.yml +5 -5
  40. data/lib/menu.yml +5 -5
  41. data/lib/ww.rb +1 -1
  42. metadata +5 -2
@@ -35,7 +35,7 @@ class InputSequencer
35
35
  document_filename: next_state.document_filename || current.document_filename,
36
36
  inherited_block_names: next_state.inherited_block_names,
37
37
  inherited_dependencies: next_state.inherited_dependencies,
38
- inherited_lines: next_state.inherited_lines,
38
+ context_code: next_state.context_code,
39
39
  prior_block_was_link: next_state.prior_block_was_link.nil? ? current.prior_block_was_link : next_state.prior_block_was_link
40
40
  )
41
41
  # rubocop:disable Style/RescueStandardError
@@ -49,13 +49,13 @@ class InputSequencer
49
49
 
50
50
  def self.next_link_state(
51
51
  block_name: nil, display_menu: nil, document_filename: nil,
52
- inherited_lines: nil, keep_code: false, prior_block_was_link: false
52
+ context_code: nil, keep_code: false, prior_block_was_link: false
53
53
  )
54
54
  MarkdownExec::LinkState.new(
55
55
  block_name: block_name,
56
56
  display_menu: display_menu,
57
57
  document_filename: document_filename,
58
- inherited_lines: inherited_lines,
58
+ context_code: context_code,
59
59
  keep_code: keep_code,
60
60
  prior_block_was_link: prior_block_was_link
61
61
  )
@@ -96,6 +96,7 @@ class InputSequencer
96
96
  if now_menu.display_menu
97
97
  # !!b
98
98
  break if run_yield(:end_of_cli, &block) == :exit
99
+
99
100
  # !!b
100
101
 
101
102
  exit_when_bq_empty = false
data/lib/link_history.rb CHANGED
@@ -17,18 +17,21 @@ module MarkdownExec
17
17
  # @param inherited_block_names [Array<String>, nil] the names of
18
18
  # the inherited blocks.
19
19
  # @param inherited_dependencies [?, nil] the dependecy hierarcy.
20
- # @param inherited_lines [Array<String>, nil] the inherited lines of code.
20
+ # @param context_code [Array<String>, nil] the context code (shell code that provides
21
+ # the necessary code and data for the evaluation of individual blocks).
22
+ # @param context_code [Array<String>, nil] Deprecated: Use context_code instead.
21
23
  def initialize(
22
24
  block_name: nil, display_menu: nil, document_filename: nil,
23
25
  inherited_block_names: [], inherited_dependencies: nil,
24
- inherited_lines: nil, keep_code: false, prior_block_was_link: nil
26
+ context_code: nil, keep_code: false, prior_block_was_link: nil
25
27
  )
26
28
  @block_name = block_name
27
29
  @display_menu = display_menu
28
30
  @document_filename = document_filename
29
31
  @inherited_block_names = inherited_block_names
30
32
  @inherited_dependencies = inherited_dependencies
31
- @inherited_lines = inherited_lines
33
+ # Support both new and deprecated parameter names
34
+ @context_code = context_code
32
35
  @keep_code = keep_code
33
36
  @prior_block_was_link = prior_block_was_link
34
37
  wwt :link_state, self, caller.deref
@@ -51,50 +54,50 @@ module MarkdownExec
51
54
  other.document_filename == document_filename &&
52
55
  other.inherited_block_names == inherited_block_names &&
53
56
  other.inherited_dependencies == inherited_dependencies &&
54
- other.inherited_lines == inherited_lines &&
57
+ other.context_code == context_code &&
55
58
  other.keep_code == keep_code &&
56
59
  other.prior_block_was_link == prior_block_was_link
57
60
  end
58
61
 
59
- def inherited_lines
60
- @inherited_lines.tap do |ret|
61
- pp ['LinkState.inherited_lines() ->', ret] if $pd
62
+ def context_code
63
+ @context_code.tap do |ret|
64
+ pp ['LinkState.context_code() ->', ret] if $pd
62
65
  end
63
66
  end
64
67
 
65
- def inherited_lines=(value)
66
- @inherited_lines = value.tap do |ret|
67
- pp ['LinkState.inherited_lines=() ->', ret, caller.deref(3).last] if $pd
68
+ def context_code=(value)
69
+ @context_code = value.tap do |ret|
70
+ pp ['LinkState.context_code=() ->', ret, caller.deref(3).last] if $pd
68
71
  end
69
72
  end
70
73
 
71
- def inherited_lines_append(value)
72
- @inherited_lines = ((@inherited_lines || []) + value).tap do |ret|
73
- pp ['LinkState.inherited_lines_append() ->', ret] if $pd
74
+ def context_code_append(value)
75
+ @context_code = ((@context_code || []) + value).tap do |ret|
76
+ pp ['LinkState.context_code_append() ->', ret] if $pd
74
77
  end
75
78
  end
76
79
 
77
- def inherited_lines_block
78
- (@inherited_lines || []).join("\n").tap do |ret|
79
- pp ['LinkState.inherited_lines_block() ->', ret] if $pd
80
+ def context_code_block
81
+ (@context_code || []).join("\n").tap do |ret|
82
+ pp ['LinkState.context_code_block() ->', ret] if $pd
80
83
  end
81
84
  end
82
85
 
83
- def inherited_lines_count
84
- (@inherited_lines&.count || 0).tap do |ret|
85
- pp ['LinkState.inherited_lines_count() ->', ret] if $pd
86
+ def context_code_count
87
+ (@context_code&.count || 0).tap do |ret|
88
+ pp ['LinkState.context_code_count() ->', ret] if $pd
86
89
  end
87
90
  end
88
91
 
89
- def inherited_lines_map(&block)
90
- @inherited_lines.map(&block).tap do |ret|
91
- pp ['LinkState.inherited_lines_map() ->', ret] if $pd
92
+ def context_code_map(&block)
93
+ @context_code.map(&block).tap do |ret|
94
+ pp ['LinkState.context_code_map() ->', ret] if $pd
92
95
  end
93
96
  end
94
97
 
95
- def inherited_lines_present?
96
- @inherited_lines.present?.tap do |ret|
97
- pp ['LinkState.inherited_lines_present?() ->', ret] if $pd
98
+ def context_code_present?
99
+ @context_code.present?.tap do |ret|
100
+ pp ['LinkState.context_code_present?() ->', ret] if $pd
98
101
  end
99
102
  end
100
103
  end
@@ -140,11 +143,11 @@ if $PROGRAM_NAME == __FILE__
140
143
  @link_history = LinkHistory.new
141
144
  @link_state1 = LinkState.new(
142
145
  block_name: 'block1', document_filename: 'document1.txt',
143
- inherited_lines: ['code1.rb']
146
+ context_code: ['code1.rb']
144
147
  )
145
148
  @link_state2 = LinkState.new(
146
149
  block_name: 'block2', document_filename: 'document2.txt',
147
- inherited_lines: ['code2.rb']
150
+ context_code: ['code2.rb']
148
151
  )
149
152
  end
150
153
 
@@ -167,6 +170,51 @@ if $PROGRAM_NAME == __FILE__
167
170
  def test_pop_empty
168
171
  assert_equal LinkState.empty, @link_history.pop
169
172
  end
173
+
174
+ def test_context_code_accessor
175
+ state = LinkState.new(context_code: %w[line1 line2])
176
+ assert_equal %w[line1 line2], state.context_code
177
+ end
178
+
179
+ def test_context_code_block
180
+ state = LinkState.new(context_code: %w[line1 line2])
181
+ assert_equal "line1\nline2", state.context_code_block
182
+ end
183
+
184
+ def test_context_code_append
185
+ state = LinkState.new(context_code: ['line1'])
186
+ state.context_code_append(['line2'])
187
+ assert_equal %w[line1 line2], state.context_code
188
+ end
189
+
190
+ def test_context_code_count
191
+ state = LinkState.new(context_code: %w[line1 line2 line3])
192
+ assert_equal 3, state.context_code_count
193
+ end
194
+
195
+ def test_context_code_present?
196
+ state_with_code = LinkState.new(context_code: ['line1'])
197
+ state_without_code = LinkState.new(context_code: nil)
198
+ assert state_with_code.context_code_present?
199
+ refute state_without_code.context_code_present?
200
+ end
201
+
202
+ def test_context_code_equality
203
+ state1 = LinkState.new(context_code: ['line1'])
204
+ state2 = LinkState.new(context_code: ['line1'])
205
+ state3 = LinkState.new(context_code: ['line2'])
206
+ assert_equal state1, state2
207
+ refute_equal state1, state3
208
+ end
209
+
210
+ def test_deprecated_context_code_methods
211
+ state = LinkState.new(context_code: %w[line1 line2])
212
+ # Test backward compatibility
213
+ assert_equal %w[line1 line2], state.context_code
214
+ assert_equal "line1\nline2", state.context_code_block
215
+ assert_equal 2, state.context_code_count
216
+ assert state.context_code_present?
217
+ end
170
218
  end
171
219
  end
172
220
  end
@@ -180,7 +228,7 @@ To generate the Ruby classes `LinkState` and `LinkHistory` with their current fe
180
228
  Create Ruby classes `LinkState` and `LinkHistory` with the following specifications:
181
229
 
182
230
  1. **Class `LinkState`**:
183
- - Attributes: `block_name`, `document_filename`, `inherited_lines`.
231
+ - Attributes: `block_name`, `document_filename`, `context_code`.
184
232
  - Initialize with optional parameters for each attribute, defaulting to `nil`.
185
233
  - Include a class method `empty` that creates an instance with all attributes set to `nil`.
186
234
  - Implement a custom `==` method for comparing instances based on attribute values.
@@ -8,5 +8,5 @@ module MarkdownExec
8
8
  BIN_NAME = 'mde'
9
9
  GEM_NAME = 'markdown_exec'
10
10
  TAP_DEBUG = 'MDE_DEBUG'
11
- VERSION = '3.5.2'
11
+ VERSION = '3.6.0'
12
12
  end
data/lib/mdoc.rb CHANGED
@@ -68,25 +68,43 @@ module MarkdownExec
68
68
  @table = table
69
69
  end
70
70
 
71
- def collect_block_code_cann(fcb)
71
+ # Generates a yq (YAML query) shell command from a call annotation.
72
+ # The call annotation specifies I/O redirection patterns:
73
+ # - <$VAR_NAME: read YAML from environment variable, apply expression from block body
74
+ # - <FILE_NAME: read YAML from file, apply expression from block body
75
+ # - >$VAR_NAME: write result to environment variable
76
+ # - >FILE_NAME: write result to file
77
+ #
78
+ # @param fcb [FCB] The fenced code block containing the call annotation and body
79
+ # @return [String] A shell command string that executes the yq query
80
+ def generate_yq_command_from_call_annotation(fcb)
72
81
  body = fcb.body.join("\n")
73
82
  xcall = fcb[:cann][1..-2]
83
+ # match <$VAR_NAME, <FILE_NAME, >$VAR_NAME, >FILE_NAME
74
84
  mstdin = xcall.match(/<(?<type>\$)?(?<name>[\-.\w]+)/)
75
85
  mstdout = xcall.match(/>(?<type>\$)?(?<name>[\-.\w]+)/)
76
86
 
77
87
  yqcmd = if mstdin[:type]
88
+ # when <$VAR_NAME
89
+ # the value of the variable is the expression to apply to the YAML from the block body.
78
90
  "echo \"$#{mstdin[:name]}\" | yq '#{body}'"
79
91
  else
92
+ # when <FILE_NAME
93
+ # the block body is the expression to apply to the YAML file.
80
94
  "yq e '#{body}' '#{mstdin[:name]}'"
81
95
  end
82
96
  if mstdout[:type]
97
+ # when >$VAR_NAME
98
+ # set the value of the variable to the result of the expression
83
99
  "export #{mstdout[:name]}=$(#{yqcmd})"
84
100
  else
101
+ # when >FILE_NAME
102
+ # write the result of the expression to the file
85
103
  "#{yqcmd} > '#{mstdout[:name]}'"
86
104
  end
87
105
  end
88
106
 
89
- # Generates a shell command to redirect a block's body to either a shell variable or a file.
107
+ # Generates a shell command to copy the block's body to either a shell variable or a file.
90
108
  #
91
109
  # @param [Hash] fcb A hash containing information about the script block's stdout and body.
92
110
  # @option fcb [Hash] :stdout A hash specifying the stdout details.
@@ -165,12 +183,12 @@ module MarkdownExec
165
183
  # Collects recursively required code blocks and returns them as an array of strings.
166
184
  #
167
185
  # @param name [String] The name of the code block to start the collection from.
168
- # @return [Array<String>] An array of strings containing the collected code blocks.
186
+ # @return [OpenStruct]
169
187
  #
170
188
  def collect_recursively_required_code(
171
189
  anyname:, block_source:,
172
190
  label_body: true, label_format_above: nil, label_format_below: nil,
173
- inherited_lines: [] ###s
191
+ context_code: []
174
192
  )
175
193
  raise 'unexpected label_body' unless label_body
176
194
 
@@ -179,22 +197,28 @@ module MarkdownExec
179
197
  blocks = collect_wrapped_blocks(block_search[:blocks])
180
198
  # !!t blocks.count
181
199
 
182
- code_inherit = blocks.map do |fcb|
200
+ context_transient_codes = blocks.map do |fcb|
183
201
  process_block_to_code(
184
202
  fcb, block_source,
185
203
  label_body, label_format_above, label_format_below,
186
- inherited_lines: inherited_lines
204
+ context_code: context_code
187
205
  )
188
- end
206
+ end.tap { ww anyname, _1 }
189
207
 
190
208
  block_search.merge(
191
- { block_names: blocks.map(&:pub_name),
192
- code: code_inherit.map(&:first).compact.flatten(1).compact,
193
- inherit: code_inherit.map(&:last).compact.flatten(1).compact }
209
+ {
210
+ block_names: blocks.map(&:pub_name),
211
+ context_code:
212
+ context_transient_codes.map(&:context_code).compact.flatten(1).compact,
213
+ transient_code:
214
+ context_transient_codes.map(&:transient_code).compact.flatten(1).compact
215
+ }
194
216
  )
195
217
  else
196
- block_search.merge({ block_names: [], code: [], inherit: [] })
197
- end
218
+ block_search.merge(
219
+ { block_names: [], context_code: [], transient_code: [] }
220
+ )
221
+ end.tap { wwr _1 }
198
222
  rescue StandardError
199
223
  error_handler('collect_recursively_required_code')
200
224
  end
@@ -286,9 +310,7 @@ module MarkdownExec
286
310
  # remove
287
311
  # . empty chrome between code; edges are same as blanks
288
312
  #
289
- select_elements_with_neighbor_conditions(selrows) do |prev_element,
290
- current,
291
- next_element|
313
+ select_elements_with_neighbor_conditions(selrows) do |prev_element, current, next_element|
292
314
  !(current[:chrome] && !current.oname.present?) ||
293
315
  !(!prev_element.nil? &&
294
316
  prev_element.shell.present? &&
@@ -415,61 +437,67 @@ module MarkdownExec
415
437
  # @return [String, Array, nil] The code representation of the block, or nil if the block should be skipped.
416
438
  #
417
439
  def process_block_to_code(fcb, block_source, label_body, label_format_above,
418
- label_format_below, inherited_lines: [])
440
+ label_format_below, context_code: [])
419
441
  raise 'unexpected label_body' unless label_body
420
442
 
421
- new_inherited_lines = []
422
-
423
- new_code_lines = if fcb[:cann]
424
- collect_block_code_cann(fcb)
425
- elsif fcb[:stdout]
426
- code_for_fcb_body_into_var_or_file(fcb)
427
- elsif [BlockType::OPTS].include? fcb.type
428
- fcb.body # entire body is returned to requesing block
429
-
430
- elsif [BlockType::LINK,
431
- BlockType::LOAD,
432
- BlockType::UX,
433
- BlockType::VARS].include? fcb.type
434
- nil # Vars for all types are collected later
435
- elsif fcb[:chrome] # for Link blocks like History
436
- nil
437
- elsif fcb.type == BlockType::PORT
438
- generate_env_variable_shell_commands(fcb)
439
- elsif label_body
440
- raise 'unexpected type' if fcb.type != BlockType::SHELL
441
-
442
- # BlockType:: SHELL block
443
- if fcb.start_line =~ /@eval/ ###s
444
- command_result = HashDelegator.execute_bash_script_lines(
445
- code_lines: inherited_lines + fcb.body,
446
- export: OpenStruct.new(exportable: true, name: ''),
447
- force: true,
448
- shell: fcb.shell || 'bash'
449
- )
450
- command_result.new_lines.map { _1[:text] }.tap do
451
- if fcb.start_line =~ /@inherit/ ###s
452
- new_inherited_lines = _1
443
+ new_context_code = []
444
+
445
+ new_transient_code = if fcb[:cann]
446
+ generate_yq_command_from_call_annotation(fcb)
447
+ elsif fcb[:stdout]
448
+ # copy the block's body to either a shell variable or a file
449
+ code_for_fcb_body_into_var_or_file(fcb)
450
+ elsif [BlockType::OPTS].include? fcb.type
451
+ fcb.body # entire body is returned to requesing block
452
+
453
+ elsif [BlockType::LINK,
454
+ BlockType::LOAD,
455
+ BlockType::UX,
456
+ BlockType::VARS].include? fcb.type
457
+ nil # Vars for all types are collected later
458
+ elsif fcb[:chrome] # for Link blocks like History
459
+ nil
460
+ elsif fcb.type == BlockType::PORT
461
+ generate_env_variable_shell_commands(fcb)
462
+ elsif label_body
463
+ raise 'unexpected type' if fcb.type != BlockType::SHELL
464
+
465
+ # BlockType:: SHELL block
466
+ if fcb.start_line =~ /@eval/
467
+ command_result = HashDelegator.execute_bash_script_lines(
468
+ transient_code: context_code + fcb.body,
469
+ export: OpenStruct.new(exportable: false, name: ''),
470
+ export_name: '',
471
+ force: true,
472
+ shell: fcb.shell || 'bash'
473
+ )
474
+ command_result.stdout.split("\n").tap do
475
+ if fcb.start_line =~ /@context/
476
+ new_context_code = _1
477
+ end
478
+ end
479
+ elsif fcb.start_line =~ /@context/
480
+ # raw body
481
+ ### expansions?
482
+ new_context_code = fcb.body
483
+ [] # collect later or return as code to inherit
484
+
485
+ else
486
+ wrap_block_body_with_labels(
487
+ fcb, block_source,
488
+ label_format_above, label_format_below
489
+ )
453
490
  end
491
+ else # raw body
492
+ fcb.body
454
493
  end
455
494
 
456
- elsif fcb.start_line =~ /@inherit/ ###s
457
- # raw body
458
- ### expansions?
459
- new_inherited_lines = fcb.body
460
- nil # collect later or return as code to inherit
461
-
462
- else
463
- wrap_block_body_with_labels(
464
- fcb, block_source,
465
- label_format_above, label_format_below
466
- )
467
- end
468
- else # raw body
469
- fcb.body
470
- end
471
-
472
- [new_code_lines, new_inherited_lines].tap { wwr _1 }
495
+ OpenStruct.new(
496
+ context_code: new_context_code,
497
+ transient_code: new_transient_code
498
+ ).tap { wwr _1 }
499
+ rescue StandardError
500
+ wwe $!
473
501
  end
474
502
 
475
503
  # Recursively fetches required code blocks for a given list of requirements.
data/lib/menu.src.yml CHANGED
@@ -308,9 +308,9 @@
308
308
  :default: false
309
309
  :procname: val_as_bool
310
310
 
311
- - :opt_name: dump_inherited_lines
312
- :long_name: dump-inherited-lines
313
- :env_var: MDE_DUMP_INHERITED_LINES
311
+ - :opt_name: dump_context_code
312
+ :long_name: dump-context-code
313
+ :env_var: MDE_DUMP_CONTEXT_CODE
314
314
  :description: Display inherited code lines from imported documents (debug/diagnostic output)
315
315
  :arg_name: BOOL
316
316
  :default: false
@@ -1206,8 +1206,8 @@
1206
1206
  :default: true
1207
1207
  :procname: val_as_bool
1208
1208
 
1209
- - :opt_name: menu_with_inherited_lines
1210
- :env_var: MDE_MENU_WITH_INHERITED_LINES
1209
+ - :opt_name: menu_with_context_code
1210
+ :env_var: MDE_MENU_WITH_CONTEXT_CODE
1211
1211
  :description: Display inherited lines in menu
1212
1212
  :arg_name: BOOL
1213
1213
  :default: false
data/lib/menu.yml CHANGED
@@ -272,9 +272,9 @@
272
272
  :arg_name: BOOL
273
273
  :default: false
274
274
  :procname: val_as_bool
275
- - :opt_name: dump_inherited_lines
276
- :long_name: dump-inherited-lines
277
- :env_var: MDE_DUMP_INHERITED_LINES
275
+ - :opt_name: dump_context_code
276
+ :long_name: dump-context-code
277
+ :env_var: MDE_DUMP_CONTEXT_CODE
278
278
  :description: Display inherited code lines from imported documents (debug/diagnostic
279
279
  output)
280
280
  :arg_name: BOOL
@@ -1046,8 +1046,8 @@
1046
1046
  :arg_name: BOOL
1047
1047
  :default: true
1048
1048
  :procname: val_as_bool
1049
- - :opt_name: menu_with_inherited_lines
1050
- :env_var: MDE_MENU_WITH_INHERITED_LINES
1049
+ - :opt_name: menu_with_context_code
1050
+ :env_var: MDE_MENU_WITH_CONTEXT_CODE
1051
1051
  :description: Display inherited lines in menu
1052
1052
  :arg_name: BOOL
1053
1053
  :default: false
data/lib/ww.rb CHANGED
@@ -245,7 +245,7 @@ class Array
245
245
  # exclude vendor and .bundle directories
246
246
  # limit the count to 4
247
247
  # replace the home directory with a .
248
- def deref(count = 4)
248
+ def deref(count = 6)
249
249
  dir_pwd = Dir.pwd
250
250
  map(&:deref).reject do |line|
251
251
  %r{^/(vendor|\.bundle)/}.match(line)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdown_exec
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.2
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fareed Stevenson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-12-03 00:00:00.000000000 Z
11
+ date: 2025-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -118,6 +118,7 @@ files:
118
118
  - bats/block-type-link.bats
119
119
  - bats/block-type-opts.bats
120
120
  - bats/block-type-port.bats
121
+ - bats/block-type-shell-context-eval.bats
121
122
  - bats/block-type-shell-require-ux.bats
122
123
  - bats/block-type-ux-act-init.bats
123
124
  - bats/block-type-ux-allowed.bats
@@ -195,6 +196,7 @@ files:
195
196
  - docs/dev/block-type-bash.md
196
197
  - docs/dev/block-type-opts.md
197
198
  - docs/dev/block-type-port.md
199
+ - docs/dev/block-type-shell-context-eval.md
198
200
  - docs/dev/block-type-shell-require-ux.md
199
201
  - docs/dev/block-type-ux-act-init.md
200
202
  - docs/dev/block-type-ux-allowed.md
@@ -285,6 +287,7 @@ files:
285
287
  - docs/execution-control.md
286
288
  - docs/getting-started.md
287
289
  - docs/import-options.md
290
+ - docs/shell-script-evaluation.md
288
291
  - docs/tab-completion.md
289
292
  - docs/ux-blocks.md
290
293
  - examples/bash-blocks.md