markdown_exec 2.6.0 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -2
  3. data/Gemfile.lock +2 -2
  4. data/Rakefile +36 -0
  5. data/bats/command-substitution.bats +8 -0
  6. data/bats/options.bats +4 -4
  7. data/bats/plain.bats +8 -0
  8. data/bats/table.bats +6 -1
  9. data/bats/variable-expansion.bats +4 -4
  10. data/bin/bmde +46 -2
  11. data/bin/tab_completion.sh +1 -1
  12. data/docs/dev/command-substitution.md +24 -0
  13. data/docs/dev/load_code.md +14 -0
  14. data/docs/dev/no-active-elements.md +6 -0
  15. data/docs/dev/screen-width.md +21 -0
  16. data/docs/dev/table-invalid.md +20 -0
  17. data/examples/bash-blocks.md +2 -1
  18. data/examples/block-names.md +2 -1
  19. data/examples/block-types.md +2 -1
  20. data/examples/data-files.md +1 -0
  21. data/examples/document_options.md +1 -0
  22. data/examples/example-document-opts.md +6 -0
  23. data/examples/index.md +1 -1
  24. data/examples/interrupt.md +1 -0
  25. data/examples/link-blocks-load-save.md +8 -10
  26. data/examples/link-blocks-vars.md +12 -9
  27. data/examples/linked.md +9 -12
  28. data/examples/linked1.md +7 -6
  29. data/examples/linked2.md +6 -7
  30. data/examples/linked3.md +6 -5
  31. data/examples/linked_show.md +5 -4
  32. data/examples/nickname.md +1 -0
  33. data/examples/opts-blocks-require.md +1 -0
  34. data/examples/opts-blocks.md +1 -0
  35. data/examples/opts_output_execution.md +1 -0
  36. data/examples/pass-through-arguments.md +1 -0
  37. data/examples/pause-after-execution.md +1 -0
  38. data/examples/port-blocks.md +14 -10
  39. data/examples/save.md +1 -0
  40. data/examples/text-markup.md +2 -1
  41. data/examples/variable-expansion-save-block.md +48 -0
  42. data/examples/variable-expansion.md +3 -1
  43. data/examples/vars-blocks.md +14 -24
  44. data/examples/wrap.md +2 -1
  45. data/lib/collapser.rb +83 -47
  46. data/lib/evaluate_shell_expressions.rb +3 -2
  47. data/lib/fcb.rb +8 -2
  48. data/lib/hash_delegator.rb +214 -118
  49. data/lib/input_sequencer.rb +0 -7
  50. data/lib/markdown_exec/version.rb +1 -1
  51. data/lib/markdown_exec.rb +6 -1
  52. data/lib/menu.src.yml +22 -9
  53. data/lib/menu.yml +22 -7
  54. data/lib/ww.rb +1 -1
  55. metadata +16 -9
  56. data/docs/dev/table-crash.md +0 -39
  57. data/examples/load_code.md +0 -10
  58. /data/{examples → docs/dev}/load1.sh +0 -0
data/examples/linked3.md CHANGED
@@ -5,8 +5,9 @@
5
5
 
6
6
  ::: This Bash block displays the value of variables "PAGE3_VAR_VIA_INHERIT" and "page3_var_via_environment"
7
7
 
8
- ```bash :show_vars
9
- source bin/colorize_env_vars.sh
10
- colorize_env_vars 'vars for page2' PAGE2_VAR_VIA_INHERIT page2_var_via_environment
11
- colorize_env_vars 'vars for page3' PAGE3_VAR_VIA_INHERIT page3_var_via_environment
12
- ```
8
+ | Variable| Value
9
+ | -| -
10
+ | PAGE2_VAR_VIA_INHERIT| ${PAGE2_VAR_VIA_INHERIT}
11
+ | page2_var_via_environment| ${page2_var_via_environment}
12
+ | PAGE3_VAR_VIA_INHERIT| ${PAGE3_VAR_VIA_INHERIT}
13
+ | page3_var_via_environment| ${page3_var_via_environment}
@@ -1,7 +1,8 @@
1
1
  # Demo document linking
2
2
 
3
3
  ::: Display variables set in the calling document
4
- ```bash :show_vars
5
- source bin/colorize_env_vars.sh
6
- colorize_env_vars 'from linked.md load1.sh' var1 var2
7
- ```
4
+
5
+ | Variable| Value
6
+ | -| -
7
+ | var1| ${var1}
8
+ | var2| ${var2}
data/examples/nickname.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Demo block nicknames
2
2
 
3
+ @import example-document-opts.md
3
4
  ```opts :(document_opts)
4
5
  pause_after_script_execution: true
5
6
  ```
@@ -1,4 +1,5 @@
1
1
  # Demonstrate requiring blocks
2
+ @import example-document-opts.md
2
3
  ```opts :(document_opts) +(custom) +[custom]
3
4
  menu_divider_color: red # color to indicate failure
4
5
  ```
@@ -19,6 +19,7 @@ menu_note_match: "^\\+ +(?<line>.+?) *$"
19
19
  menu_task_color: fg_rgb_127_127_255
20
20
  ```
21
21
 
22
+ @import example-document-opts.md
22
23
  ```opts :(document_opts)
23
24
  menu_divider_color: green
24
25
  menu_link_color: fg_rgbh_88_cc_66
@@ -1,6 +1,7 @@
1
1
  # Demo options: output_execution_report, output_execution_summary
2
2
 
3
3
  ::: Options are initially True
4
+ @import example-document-opts.md
4
5
  ```opts :(document_opts) +[document_options]
5
6
  output_execution_report: true
6
7
  output_execution_summary: true
@@ -1,3 +1,4 @@
1
+ @import example-document-opts.md
1
2
  ```opts :(document_opts)
2
3
  execute_in_own_window: false
3
4
  pause_after_script_execution: true
@@ -1,5 +1,6 @@
1
1
  # Demonstrate pause for user approval before returning to the menu
2
2
  Controlled by option `pause_after_script_execution`.
3
+ @import example-document-opts.md
3
4
  ```opts :(document_opts)
4
5
  pause_after_script_execution: true
5
6
  ```
@@ -1,13 +1,5 @@
1
1
  # Demo variable porting
2
2
 
3
- ```opts :(document_opts)
4
- dump_inherited_lines: true
5
- execute_in_own_window: false
6
- output_execution_report: false
7
- output_execution_summary: false
8
- pause_after_script_execution: true
9
- ```
10
-
11
3
  ::: Set the VAULT value in memory.
12
4
  ::: Call this block prior to `show` to demonstrate in-memory value being written to script.
13
5
 
@@ -27,6 +19,18 @@ VAULT2
27
19
 
28
20
  ```bash :show +[vault]
29
21
  : ${VAULT:=This variable has not been set.}
30
- source bin/colorize_env_vars.sh
31
- colorize_env_vars '' VAULT
32
22
  ```
23
+
24
+ | Variable| Value
25
+ | -| -
26
+ | VAULT| ${VAULT}
27
+ | VAULT2| ${VAULT2}
28
+
29
+ @import example-document-opts.md
30
+ ```opts :(document_opts)
31
+ dump_inherited_lines: true
32
+ execute_in_own_window: false
33
+ output_execution_report: false
34
+ output_execution_summary: false
35
+ pause_after_script_execution: true
36
+ ```
data/examples/save.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # Demonstrate custom file names
2
+ @import example-document-opts.md
2
3
  ```opts :(document_opts) +[custom]
3
4
  pause_after_script_execution: true # for interactive demos
4
5
  save_executed_script: true # demonstrate saved scripts
@@ -47,6 +47,7 @@ line_decor_post | Line-oriented text decoration (Post)
47
47
  line_decor_pre | Line-oriented text decoration (Pre)
48
48
  menu_note_match | Pattern for notes in block selection menu
49
49
 
50
+ @import example-document-opts.md
50
51
  ```opts :(document_opts)
51
52
  line_decor_post:
52
53
  - :color_method: blue
@@ -55,4 +56,4 @@ line_decor_post:
55
56
  :pattern: '!([^!]{0,64})!green!'
56
57
  - :color_method: red
57
58
  :pattern: '!([^!]{0,64})!red!'
58
- ```
59
+ ```
@@ -0,0 +1,48 @@
1
+ ```vars :sample-configuration
2
+ NAME: name01
3
+ ```
4
+ - NAME: ${NAME}
5
+
6
+ ```link :enter-variable-value +(enter-variable-value)
7
+ exec: true
8
+ ```
9
+ ```bash :(enter-variable-value)
10
+ echo >&2 "NAME [$NAME]?: "
11
+ read -r response
12
+ echo "NAME=$(printf "%q" "${response:-$NAME}")"
13
+ ```
14
+
15
+ ```history :list_ec2_instance_configuration_files
16
+ directory: test
17
+ filename_pattern: '^(?<name>.*)$'
18
+ glob: '*.sh'
19
+ view: '%{name}'
20
+ ```
21
+
22
+ ```load :load_configuration_document_from_directory
23
+ directory: test
24
+ glob: '*.sh'
25
+ ```
26
+
27
+ ```save :save_stack_file_names
28
+ directory: test
29
+ glob: "${NAME}.sh"
30
+ ```
31
+
32
+ ```bash :loggable-action
33
+ echo `date -u`
34
+ ```
35
+ ```opts :(document_opts)
36
+ save_executed_script: true
37
+ save_execution_output: true
38
+
39
+ # Add "NAME" named group to default shell expansion.
40
+ # Include a wildcard as default to allow for matching when undefined.
41
+ saved_asset_format: "%{prefix}%{join}${NAME:-*}%{join}%{time}%{join}%{filename}%{join}%{mark}%{join}%{blockname}%{join}%{exts}"
42
+
43
+ # Add "name" capture group to default expression
44
+ saved_asset_match: "^(?<prefix>.+)(?<join>_)(?<name>.*)\\g'join'(?<time>[0-9\\-]+)\\g'join'(?<filename>.+)\\g'join'(?<mark>~)\\g'join'(?<blockname>.+)\\g'join'(?<exts>\\..+)$"
45
+
46
+ # Add "name" capture group to default format
47
+ saved_history_format: "%{name} %{time} %{blockname} %{exts}"
48
+ ```
@@ -59,8 +59,9 @@ directory: tmp
59
59
  glob: ${ALPHA}.sh
60
60
  ```
61
61
  ```view
62
+ View
62
63
  ```
63
- ```edit
64
+ ```edit :edit
64
65
  ```
65
66
  ```save
66
67
  directory: tmp
@@ -68,6 +69,7 @@ glob: ${ALPHA}.sh
68
69
  ```
69
70
 
70
71
  / import bats-document-configuration.md
72
+ @import example-document-opts.md
71
73
  ```opts :(document_opts)
72
74
  divider4_center: false
73
75
 
@@ -1,38 +1,28 @@
1
+ @import example-document-opts.md
1
2
  ```opts :(document_opts)
2
3
  execute_in_own_window: false
3
4
  output_execution_report: false
4
5
  output_execution_summary: false
5
6
  pause_after_script_execution: true
6
7
  ```
7
- The hidden block "(defaults)" sets the environment variable VAULT to "default" if it is unset.
8
- ```bash :(defaults)
9
- : ${VAULT:=default}
10
- ```
11
-
12
- ::: Select below to trigger. If it prints "VAULT: default", the shell block was processed.
13
- The named block prints the environment variable VAULT. It requires hidden block "(defaults)" before printing.
14
- ```bash :show_vars +(defaults)
15
- source bin/colorize_env_vars.sh
16
- colorize_env_vars '' VAULT
17
- ```
8
+ /The hidden block "(defaults)" sets the environment variable VAULT to "default" if it is unset.
9
+ /```bash :(defaults)
10
+ /: ${VAULT:=default}
11
+ /```
12
+ | Variable| Value
13
+ | -| -
14
+ | VAULT| ${VAULT}
18
15
 
16
+ ::: Select below to trigger.
19
17
  The block sets the environment variable VAULT to "11".
20
- When clicked, it adds the variable to the inherited code. It does not output.
18
+ When clicked, it adds the variable to the inherited code.
21
19
  ```vars :[set_vault_11]
22
20
  VAULT: 11
23
21
  ```
24
22
 
25
- # DOES NOT WORK 2024-07-20
26
- ## This does not evaluate the shell block.
27
- ::: Select below to trigger. If it prints "VAULT: 22", the shell block was processed.
28
- The block sets the environment variable VAULT to "22". It requires block "show_vars". Notice block "show_vars" is called after the variable is set.
29
- ```vars :[set_with_show] +show_vars
23
+ ::: Select below to trigger.
24
+ The block sets the environment variable VAULT to "22".
25
+ When clicked, it adds the variable to the inherited code.
26
+ ```vars :[set_with_show]
30
27
  VAULT: 22
31
28
  ```
32
-
33
- ## This outputs the value before the variable is set.
34
- The named block prints the environment variable VAULT. It requires block "set".
35
- ```bash :show_with_set +[set_vault_11]
36
- source bin/colorize_env_vars.sh
37
- colorize_env_vars '' VAULT
38
- ```
data/examples/wrap.md CHANGED
@@ -100,6 +100,7 @@ shell_code_label_format_above: "# -^-"
100
100
  shell_code_label_format_below: "# -v- +%{block_name} -o- %{document_filename} -o- %{time_now_date} -v-"
101
101
  ```
102
102
 
103
+ @import example-document-opts.md
103
104
  ```opts :(document_opts)
104
105
  execute_in_own_window: false
105
106
  output_execution_report: false
@@ -108,4 +109,4 @@ pause_after_script_execution: true
108
109
  line_decor_pre:
109
110
  - :color_method: :underline_italic
110
111
  :pattern: '"([^"]{0,64})"'
111
- ```
112
+ ```
data/lib/collapser.rb CHANGED
@@ -1,3 +1,8 @@
1
+ #!/usr/bin/env bundle exec ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+ # v2024-12-02
1
6
  require_relative 'constants'
2
7
 
3
8
  class Collapser
@@ -12,11 +17,11 @@ class Collapser
12
17
  @collapsed_level = collapsed_level
13
18
  @collapsible_types = collapsible_types.dup
14
19
  @options = options.dup
15
- @state = state.dup # do not dup
20
+ @state = state # do not dup
16
21
  end
17
22
 
18
23
  def collapse_per_options?(fcb, options: @options)
19
- criteria = options["#{fcb.type}#{fcb.level}_collapse".to_sym]
24
+ criteria = options[:"#{fcb.type}#{fcb.level}_collapse"]
20
25
  return false if criteria.nil?
21
26
 
22
27
  criteria
@@ -36,7 +41,7 @@ class Collapser
36
41
  end
37
42
 
38
43
  def collapsible_per_options?(fcb, options: @options)
39
- criteria = options["#{fcb.type}#{fcb.level}_collapsible".to_sym]
44
+ criteria = options[:"#{fcb.type}#{fcb.level}_collapsible"]
40
45
  return false if criteria.nil?
41
46
 
42
47
  criteria
@@ -83,19 +88,17 @@ class Collapser
83
88
  collapsed_level = fcb.level if fcb.collapse
84
89
  fcb.hide = true # block is at a deeper level thus hidden
85
90
 
86
- else
91
+ elsif fcb.collapsible
87
92
  # Currently expanded; evaluate for the current block
88
- if fcb.collapsible
89
- fcb.collapse = collapse?(fcb, initialize: initialize)
90
- collapsed_level = fcb.collapse ? fcb.level : nil
91
- fcb.hide = false
92
- elsif collapsible_per_type?(fcb)
93
- fcb.collapsible = false
94
- fcb.collapse = false
95
- fcb.hide = false
96
- else
97
- fcb.hide = true
98
- end
93
+ fcb.collapse = collapse?(fcb, initialize: initialize)
94
+ collapsed_level = fcb.collapse ? fcb.level : nil
95
+ fcb.hide = false
96
+ elsif collapsible_per_type?(fcb)
97
+ fcb.collapsible = false
98
+ fcb.collapse = false
99
+ fcb.hide = false
100
+ else
101
+ fcb.hide = true
99
102
  end
100
103
  @state[fcb.id] = fcb.level if fcb.collapse
101
104
 
@@ -147,7 +150,7 @@ class CollapserTest < Minitest::Test
147
150
  def test_analyze
148
151
  # Define test scenarios as arrays of FCB objects and expected filtered results
149
152
 
150
- # :id, :type, :level, :token
153
+ # :id, :type, :level, :token (in order for FCB.new)
151
154
  ff_h1a = ['h1a', 'heading', 1, '']
152
155
  ff_h1b = ['h1b', 'heading', 1, '']
153
156
  ff_h2a = ['h2a', 'heading', 2, '']
@@ -159,8 +162,10 @@ class CollapserTest < Minitest::Test
159
162
  ff_h1a_collapse = ['h1a', 'heading', 1, COLLAPSIBLE_TOKEN_COLLAPSE]
160
163
  ff_h1a_expand = ['h1a', 'heading', 1, COLLAPSIBLE_TOKEN_EXPAND]
161
164
  ff_h1b_expand = ['h1b', 'heading', 1, COLLAPSIBLE_TOKEN_EXPAND]
165
+ ff_h2a_collapse = ['h2a', 'heading', 2, COLLAPSIBLE_TOKEN_COLLAPSE]
166
+ ff_h2b_collapse = ['h2b', 'heading', 2, COLLAPSIBLE_TOKEN_COLLAPSE]
162
167
 
163
- # :collapse, :collapsible, :hide
168
+ # :collapse, :collapsible, :hide (in order for FCB.new)
164
169
  cc_init = [false, false, false]
165
170
  cc_collapse = [true, false, false]
166
171
  cc_collapse_collapsible = [true, true, false]
@@ -169,52 +174,81 @@ class CollapserTest < Minitest::Test
169
174
  cc_hide = [false, false, true]
170
175
  cc_undefined_hide = [nil, nil, false]
171
176
 
177
+ fc_h1a__collapse = FCB.new(*ff_h1a, *cc_collapse)
178
+ fc_h1a__collapse_collapsible = FCB.new(*ff_h1a, *cc_collapse_collapsible)
179
+ fc_h1a__collapsed_init = FCB.new(*ff_h1a_collapse, *cc_init)
180
+ fc_h1a__collapsible = FCB.new(*ff_h1a, *cc_collapsible)
181
+ fc_h1a__collapsible_hide = FCB.new(*ff_h1a, *cc_collapsible_hide)
182
+ fc_h1a__expanded_init = FCB.new(*ff_h1a_expand, *cc_init)
172
183
  fc_h1a__init = FCB.new(*ff_h1a, *cc_init)
173
- fc_h1b__init = FCB.new(*ff_h1b, *cc_init)
174
- fc_h2a__init = FCB.new(*ff_h2a, *cc_init)
175
- fc_h2b__init = FCB.new(*ff_h2b, *cc_init)
176
- fc_t1__init = FCB.new(*ff_t1, *cc_init)
177
- fc_t2__init = FCB.new(*ff_t2, *cc_init)
178
- fc_t3__init = FCB.new(*ff_t3, *cc_init)
179
- fc_t4__init = FCB.new(*ff_t4, *cc_init)
180
184
 
181
- fc_h1a__collapse = FCB.new(*ff_h1a, *cc_collapse)
185
+ fc_h1b__init = FCB.new(*ff_h1b, *cc_init)
182
186
 
183
- fc_h1a__collapse_collapsible = FCB.new(*ff_h1a, *cc_collapse_collapsible)
187
+ fc_h2a__collapse = FCB.new(*ff_h2a, *cc_collapse)
184
188
  fc_h2a__collapse_collapsible = FCB.new(*ff_h2a, *cc_collapse_collapsible)
185
-
186
- fc_h1a__collapsible = FCB.new(*ff_h1a, *cc_collapsible)
189
+ fc_h2a__collapsed_collapsible = FCB.new(*ff_h2a_collapse, *cc_collapsible)
187
190
  fc_h2a__collapsible = FCB.new(*ff_h2a, *cc_collapsible)
191
+ fc_h2a__hide = FCB.new(*ff_h2a, *cc_hide)
192
+ fc_h2a__init = FCB.new(*ff_h2a, *cc_init)
188
193
 
189
- fc_h1a__collapsible_hide = FCB.new(*ff_h1a, *cc_collapsible_hide)
194
+ fc_h2b__init = FCB.new(*ff_h2b, *cc_init)
190
195
 
191
196
  fc_t1__hide = FCB.new(*ff_t1, *cc_hide)
197
+ fc_t1__init = FCB.new(*ff_t1, *cc_init)
192
198
  fc_t2__hide = FCB.new(*ff_t2, *cc_hide)
193
- fc_h2a__hide = FCB.new(*ff_h2a, *cc_hide)
199
+ fc_t2__init = FCB.new(*ff_t2, *cc_init)
200
+ fc_t3__init = FCB.new(*ff_t3, *cc_init)
201
+ fc_t4__hide = FCB.new(*ff_t4, *cc_hide)
202
+ fc_t4__init = FCB.new(*ff_t4, *cc_init)
194
203
 
195
204
  analyze_cases = {
196
205
  with_token: [
197
206
  { name: 'collapse',
198
- fcbs: [FCB.new(*ff_h1a_collapse, *cc_init)],
207
+ fcbs: [fc_h1a__collapsed_init],
199
208
  expected: [FCB.new(*ff_h1a_collapse, *cc_collapse)] },
200
209
  { name: 'expand',
201
- fcbs: [FCB.new(*ff_h1a_expand, *cc_init)],
202
- expected: [FCB.new(*ff_h1a_expand, *cc_init)] },
210
+ fcbs: [fc_h1a__expanded_init],
211
+ expected: [fc_h1a__expanded_init] },
203
212
  { name: 'collapse, against options',
204
- fcbs: [FCB.new(*ff_h1a_collapse, *cc_init)],
213
+ fcbs: [fc_h1a__collapsed_init],
205
214
  options: { heading1_collapse: false },
206
215
  expected: [FCB.new(*ff_h1a_collapse, *cc_collapse)] },
207
216
  { name: 'expand, against options',
208
- fcbs: [FCB.new(*ff_h1a_expand, *cc_init)],
217
+ fcbs: [fc_h1a__expanded_init],
209
218
  options: { heading1_collapse: true },
210
- expected: [FCB.new(*ff_h1a_expand, *cc_init)] },
219
+ expected: [fc_h1a__expanded_init] }
211
220
  ],
212
221
 
213
222
  with_no_state: [
214
- { name: ' ',
215
- fcbs: [FCB.new(*ff_h1a_expand, *cc_init), fc_t1__init, fc_h2a__init, fc_t2__init, FCB.new(*ff_h1b_expand, *cc_init), fc_t3__init, fc_h2b__init, fc_t4__init],
223
+ { name: 'heading2_collapse',
224
+ fcbs: [
225
+ fc_h1a__init,
226
+ fc_h2a__init,
227
+ fc_h1b__init,
228
+ fc_h2b__init
229
+ ],
230
+ options: { heading2_collapse: true },
231
+ expected: [
232
+ fc_h1a__init,
233
+ fc_h2a__collapse, # s/b fc_h2a__collapse_collapsible, ok for test
234
+ fc_h1b__init,
235
+ fc_h2b__init # s/b fc_h2b__collapse_collapsible, ok for test
236
+ ] },
237
+
238
+ { name: 'hide subsections',
239
+ fcbs: [
240
+ fc_h1a__init, fc_t1__init,
241
+ fc_h2a__init, fc_t2__init,
242
+ fc_h1b__init, fc_t3__init,
243
+ fc_h2b__init, fc_t4__init
244
+ ],
216
245
  options: { heading2_collapse: true },
217
- expected: [FCB.new(*ff_h1a_expand, *cc_init), fc_t1__init, FCB.new(*ff_h2a, *cc_collapse), FCB.new(*ff_h1b_expand, *cc_init), fc_t3__init, FCB.new(*ff_h2b, *cc_collapse)] },
246
+ expected: [
247
+ fc_h1a__init, fc_t1__init,
248
+ fc_h2a__collapse, fc_t2__hide,
249
+ fc_h1b__init, fc_t3__init,
250
+ fc_h2b__init, fc_t4__hide
251
+ ] },
218
252
 
219
253
  { name: 'not collapsible',
220
254
  fcbs: [fc_h1a__init],
@@ -263,7 +297,7 @@ class CollapserTest < Minitest::Test
263
297
  heading2_collapsible: true },
264
298
  expected: [fc_h1a__init,
265
299
  fc_h2a__collapse_collapsible,
266
- fc_t1__hide] },
300
+ fc_t1__hide] }
267
301
  ],
268
302
 
269
303
  with_empty_state: [
@@ -271,25 +305,27 @@ class CollapserTest < Minitest::Test
271
305
  fcbs: [fc_h1a__init],
272
306
  options: { heading1_collapsible: true },
273
307
  initialize: false,
274
- expected: [fc_h1a__collapsible] },
308
+ expected: [fc_h1a__collapsible] }
275
309
  ],
276
310
 
277
311
  with_collapsed_state: [
278
312
  { name: 'collapsed remains collapsed',
279
313
  fcbs: [fc_h1a__collapse_collapsible],
280
314
  options: { heading1_collapsible: true },
281
- state: { "h1a" => 1 },
315
+ state: { 'h1a' => 1 },
282
316
  initialize: false,
283
- expected: [fc_h1a__collapse_collapsible] },
317
+ expected: [fc_h1a__collapse_collapsible] }
284
318
  ]
285
319
  }
286
320
 
287
321
  analyze_cases.each do |name, test_cases|
288
322
  test_cases.each_with_index do |test_case, index|
289
- @collapser = Collapser.new(collapsed_level: test_case[:collapsed_level],
290
- collapsible_types: test_case[:collapsible_types] || COLLAPSIBLE_TYPES,
291
- options: (test_case[:options] || OPTIONS).dup,
292
- state: (test_case[:state] || STATE).dup)
323
+ @collapser = Collapser.new(
324
+ collapsed_level: test_case[:collapsed_level],
325
+ collapsible_types: test_case[:collapsible_types] || COLLAPSIBLE_TYPES,
326
+ options: (test_case[:options] || OPTIONS).dup,
327
+ state: (test_case[:state] || STATE).dup
328
+ )
293
329
  analysis = @collapser.analyze(
294
330
  test_case[:fcbs],
295
331
  initialize: test_case[:initialize].nil? ? true : test_case[:initialize]
@@ -6,9 +6,10 @@
6
6
  require 'open3'
7
7
 
8
8
  def evaluate_shell_expressions(initial_code, expressions, shell: '/bin/bash',
9
- key_format: "%%<%s>")
9
+ key_format: "%%<%s>",
10
+ initial_code_required: false)
10
11
  # !!p initial_code expressions key_format shell
11
- return if initial_code.nil? || initial_code.empty? ||
12
+ return if (initial_code_required && (initial_code.nil? || initial_code.empty?)) ||
12
13
  expressions.nil? || expressions.empty? ||
13
14
  key_format.nil? || key_format.empty?
14
15
 
data/lib/fcb.rb CHANGED
@@ -157,13 +157,19 @@ module MarkdownExec
157
157
  ### update name, nickname, title, label ???
158
158
 
159
159
  # Replace variables in `dname` using the replacements dictionary
160
- @attrs[:dname] = @attrs[:dname].gsub(pattern) do |match|
160
+ @attrs[:dname] = @attrs[:dname]&.gsub(pattern) do |match|
161
+ replacements[match]
162
+ end
163
+ @attrs[:s0printable] = @attrs[:s0printable]&.gsub(pattern) do |match|
164
+ replacements[match]
165
+ end
166
+ @attrs[:s1decorated] = @attrs[:s1decorated]&.gsub(pattern) do |match|
161
167
  replacements[match]
162
168
  end
163
169
 
164
170
  # Replace variables in each line of `body` if `body` is present
165
171
  if @attrs[:body]
166
- @attrs[:body] = @attrs[:body].map do |line|
172
+ @attrs[:body] = @attrs[:body]&.map do |line|
167
173
  if line.empty?
168
174
  line
169
175
  else