markdown_exec 1.3.3.5 → 1.3.7

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.
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ ##
7
+ # This class is used to represent a block label which can be constructed using various components.
8
+ # It handles initialization using a hash and provides a method to create a label string.
9
+ #
10
+ # Example Usage:
11
+ # block = {
12
+ # filename: 'example.md',
13
+ # headings: ['Header1', 'Header2'],
14
+ # menu_blocks_with_docname: true,
15
+ # menu_blocks_with_headings: false,
16
+ # title: 'Sample Title',
17
+ # body: 'Sample Body',
18
+ # text: 'Sample Text'
19
+ # }
20
+ # label_obj = BlockLabel.new(block)
21
+ # label_str = label_obj.make
22
+ #
23
+
24
+ class BlockLabel
25
+ def self.make(filename:, headings:, menu_blocks_with_docname:, menu_blocks_with_headings:, title:, body:, text:)
26
+ label = title
27
+ label = body if label.nil? || label.empty?
28
+ label = text if label.nil? || label.empty?
29
+
30
+ parts = [label]
31
+
32
+ parts << headings.compact.join(' # ') if menu_blocks_with_headings
33
+ parts << filename if menu_blocks_with_docname
34
+
35
+ parts.join(' ')
36
+ rescue StandardError => err
37
+ warn(error = "ERROR ** BlockLabel.make(); #{err.inspect}")
38
+ binding.pry if $tap_enable
39
+ raise ArgumentError, error
40
+ end
41
+ end
42
+
43
+ if $PROGRAM_NAME == __FILE__
44
+ require 'minitest/autorun'
45
+
46
+ class BlockLabelTest < Minitest::Test
47
+ def setup
48
+ @block_data = {
49
+ filename: 'example.md',
50
+ headings: %w[Header1 Header2],
51
+ menu_blocks_with_docname: true,
52
+ menu_blocks_with_headings: false,
53
+ title: 'Sample Title',
54
+ body: 'Sample Body',
55
+ text: 'Sample Text'
56
+ }
57
+ end
58
+
59
+ def test_make_method
60
+ assert_equal 'Sample Title example.md', BlockLabel.make(**@block_data)
61
+ end
62
+
63
+ def test_make_method_without_title
64
+ @block_data[:title] = nil
65
+ label = BlockLabel.make(**@block_data)
66
+ assert_equal 'Sample Body example.md', label
67
+ end
68
+
69
+ def test_make_method_without_title_and_body
70
+ @block_data[:title] = nil
71
+ @block_data[:body] = nil
72
+ label = BlockLabel.make(**@block_data)
73
+ assert_equal 'Sample Text example.md', label
74
+ end
75
+
76
+ def test_make_method_with_headings
77
+ @block_data[:menu_blocks_with_headings] = true
78
+ label = BlockLabel.make(**@block_data)
79
+ assert_equal 'Sample Title Header1 # Header2 example.md', label
80
+ end
81
+ end
82
+ end
data/lib/env_opts.rb CHANGED
@@ -93,9 +93,9 @@ class EnvOpts
93
93
  args_ind = 0
94
94
  while args_ind < argv.count
95
95
  args_consumed = 0
96
- arg = argv.fetch(args_ind, '') #.tap_inspect 'argument', source: 'EnvOpts'
96
+ arg = argv.fetch(args_ind, '')
97
97
  if arg.start_with? '--'
98
- opt_name = arg[2..-1] #.tap_inspect 'opt_name', source: 'EnvOpts'
98
+ opt_name = arg[2..-1]
99
99
  args_consumed = consume_arguments(opt_name,
100
100
  argv.fetch(args_ind + 1, nil))
101
101
  end
@@ -136,7 +136,7 @@ class EnvOpts
136
136
  # option names use hyphens
137
137
  #
138
138
  def self.symbol_name_to_option_name(name)
139
- name.to_s.gsub('_', '-') #.tap_inspect
139
+ name.to_s.gsub('_', '-')
140
140
  end
141
141
 
142
142
  private
@@ -144,7 +144,7 @@ class EnvOpts
144
144
  # convert key name or symbol to an option name
145
145
  #
146
146
  def key_name_to_option_name(key)
147
- (key.is_a?(Symbol) ? EnvOpts.symbol_name_to_option_name(key) : key) #.tap_inspect
147
+ (key.is_a?(Symbol) ? EnvOpts.symbol_name_to_option_name(key) : key)
148
148
  end
149
149
 
150
150
  # get cast of environment variable
@@ -175,7 +175,7 @@ class EnvOpts
175
175
  # option names use hyphens
176
176
  #
177
177
  def method_name_to_option_name(name)
178
- name.to_s.gsub('_', '-') #.tap_inspect
178
+ name.to_s.gsub('_', '-')
179
179
  end
180
180
 
181
181
  # read and write options using the option name as a method
@@ -187,7 +187,7 @@ class EnvOpts
187
187
  set_key_value_as_cast(name, value)
188
188
  else
189
189
  @values[method_name_to_option_name(method_name)]
190
- end #.tap_inspect "ref #{method_name}", source: 'EnvOpts'
190
+ end
191
191
  end
192
192
 
193
193
  # option name to environment name
@@ -146,7 +146,7 @@ class EnvironmentOptParse
146
146
  include Menu
147
147
 
148
148
  def initialize(menu: {}, lambdas: nil, options: nil, version: nil)
149
- @menu = if menu.class.to_s == 'String'
149
+ @menu = if menu.instance_of?(::String)
150
150
  filetext = File.read(menu).tap_yaml 'filetext'
151
151
  fileyaml = YAML.load(filetext)
152
152
  fileyaml.map(&:sym_keys)
@@ -156,7 +156,7 @@ class EnvironmentOptParse
156
156
  @lambdas = lambdas
157
157
  @version = version || '0.1'
158
158
  # @options = {}
159
- @options = if options.class.to_s == 'String'
159
+ @options = if options.instance_of?(::String)
160
160
  YAML.safe_load(File.read(options)).sym_keys.tap_yaml '@options'
161
161
  else
162
162
  {}
@@ -193,7 +193,7 @@ class EnvironmentOptParse
193
193
  exit
194
194
  },
195
195
  val_as_bool: lambda { |value|
196
- value.class.to_s == 'String' ? (value.chomp != '0') : value
196
+ value.instance_of?(::String) ? (value.chomp != '0') : value
197
197
  },
198
198
  val_as_int: ->(value) { value.to_i },
199
199
  val_as_str: ->(value) { value.to_s },
data/lib/fcb.rb ADDED
@@ -0,0 +1,133 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ module MarkdownExec
7
+ class Error < StandardError; end
8
+
9
+ # Fenced Code Block (FCB)
10
+ #
11
+ # This class represents a fenced code block in a markdown document.
12
+ # It allows for setting and getting attributes related to the code block,
13
+ # such as body, call, headings, and more.
14
+ #
15
+ class FCB
16
+ def initialize(options = {})
17
+ @attrs = {
18
+ body: nil,
19
+ call: nil,
20
+ headings: [],
21
+ name: nil,
22
+ reqs: [],
23
+ shell: '',
24
+ title: '',
25
+ random: Random.new.rand,
26
+ text: nil # displayable in menu
27
+ }.merge(options)
28
+ end
29
+
30
+ def to_h
31
+ @attrs
32
+ end
33
+
34
+ def to_yaml
35
+ @attrs.to_yaml
36
+ end
37
+
38
+ private
39
+
40
+ # 2023-10-07 proposed but not functional with code
41
+ #
42
+ # def method_missing(method, *args, &block)
43
+ # method_name = method.to_s
44
+
45
+ # if method_name[-1] == '='
46
+ # @attrs[method_name.chop.to_sym] = args[0]
47
+ # elsif @attrs.key?(method_name.to_sym)
48
+ # @attrs[method_name.to_sym]
49
+ # else
50
+ # super
51
+ # end
52
+ # rescue StandardError => err
53
+ # warn(error = "ERROR ** FCB.method_missing(method: #{method_name}, *args: #{args.inspect}, &block)")
54
+ # warn err.inspect
55
+ # warn(caller[0..4])
56
+ # raise err # Here, we simply propagate the original error instead of wrapping it in a StandardError.
57
+ # end
58
+
59
+ # :reek:ManualDispatch
60
+ def method_missing(method, *args, &block)
61
+ method_name = method.to_s
62
+
63
+ if @attrs.respond_to?(method_name)
64
+ @attrs.send(method_name, *args, &block)
65
+ elsif method_name[-1] == '='
66
+ @attrs[method_name.chop.to_sym] = args[0]
67
+ else
68
+ @attrs[method_name.to_sym]
69
+ end
70
+ rescue StandardError => err
71
+ warn("ERROR ** FCB.method_missing(method: #{method_name}," \
72
+ " *args: #{args.inspect}, &block)")
73
+ warn err.inspect
74
+ warn(caller[0..4])
75
+ # raise StandardError, error
76
+ raise err # Here, we simply propagate the original error instead of wrapping it in a StandardError.
77
+ end
78
+
79
+ def respond_to_missing?(method_name, _include_private = false)
80
+ @attrs.key?(method_name.to_sym) || super
81
+ end
82
+ end
83
+ end
84
+
85
+ if $PROGRAM_NAME == __FILE__
86
+ require 'minitest/autorun'
87
+ require 'yaml'
88
+
89
+ class FCBTest < Minitest::Test
90
+ def setup
91
+ @fcb_data = {
92
+ body: 'Sample body',
93
+ call: 'Sample call',
94
+ headings: %w[Header1 Header2],
95
+ name: 'Sample name',
96
+ reqs: %w[req1 req2],
97
+ shell: 'bash',
98
+ text: 'Sample Text',
99
+ title: 'Sample Title'
100
+ }
101
+ @fcb = MarkdownExec::FCB.new(@fcb_data)
102
+ end
103
+
104
+ def test_initialization_with_correct_data
105
+ assert_equal 'Sample body', @fcb.body
106
+ assert_equal %w[Header1 Header2], @fcb.headings
107
+ end
108
+
109
+ def test_to_h_method
110
+ assert_equal @fcb_data.merge({ random: @fcb.random }), @fcb.to_h
111
+ end
112
+
113
+ def test_to_yaml_method
114
+ assert_equal YAML.load(@fcb_data.merge({ random: @fcb.random }).to_yaml),
115
+ YAML.load(@fcb.to_yaml)
116
+ end
117
+
118
+ def test_method_missing_getter
119
+ assert_equal 'Sample Title', @fcb.title
120
+ end
121
+
122
+ def test_method_missing_setter
123
+ @fcb.title = 'New Title'
124
+ assert_equal 'New Title', @fcb.title
125
+ end
126
+
127
+ # 2023-10-09 does not trigger error; treats as option name
128
+ #
129
+ # def test_method_missing_with_unknown_method
130
+ # assert_raises(NoMethodError) { @fcb.unknown_method }
131
+ # end
132
+ end
133
+ end
data/lib/filter.rb ADDED
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ module MarkdownExec
7
+ # Filter
8
+ #
9
+ # The Filter class provides utilities to determine the inclusion of fenced code blocks (FCB)
10
+ # based on a set of provided options. The primary function, `fcb_select?`, checks
11
+ # various properties of an FCB and decides whether to include or exclude it.
12
+ #
13
+ # :reek:UtilityFunction
14
+
15
+ class Filter
16
+ def self.fcb_select?(options, fcb)
17
+ filters = {
18
+ name_default: true,
19
+ name_exclude: nil,
20
+ name_select: nil,
21
+ shell_default: true,
22
+ shell_exclude: nil,
23
+ shell_select: nil,
24
+ hidden_name: nil
25
+ }
26
+
27
+ name = fcb.fetch(:name, '')
28
+ shell = fcb.fetch(:shell, '')
29
+
30
+ apply_name_filters(options, filters, name)
31
+ apply_shell_filters(options, filters, shell)
32
+ apply_other_filters(options, filters, fcb)
33
+
34
+ evaluate_filters(options, filters)
35
+ rescue StandardError => err
36
+ warn("ERROR ** Filter::fcb_select?(); #{err.inspect}")
37
+ raise err
38
+ end
39
+
40
+ def self.apply_name_filters(options, filters, name)
41
+ if name.present? && options[:block_name]
42
+ if name =~ /#{options[:block_name]}/
43
+ filters[:name_select] = true
44
+ filters[:name_exclude] = false
45
+ else
46
+ filters[:name_exclude] = true
47
+ filters[:name_select] = false
48
+ end
49
+ end
50
+
51
+ if name.present? && filters[:name_select].nil? && options[:select_by_name_regex].present?
52
+ filters[:name_select] = !!(name =~ /#{options[:select_by_name_regex]}/)
53
+ end
54
+
55
+ unless name.present? && filters[:name_exclude].nil? && options[:exclude_by_name_regex].present?
56
+ return
57
+ end
58
+
59
+ filters[:name_exclude] = !!(name =~ /#{options[:exclude_by_name_regex]}/)
60
+ end
61
+
62
+ def self.apply_shell_filters(options, filters, shell)
63
+ filters[:shell_expect] = shell == 'expect'
64
+
65
+ if shell.present? && options[:select_by_shell_regex].present?
66
+ filters[:shell_select] = !!(shell =~ /#{options[:select_by_shell_regex]}/)
67
+ end
68
+
69
+ return unless shell.present? && options[:exclude_by_shell_regex].present?
70
+
71
+ filters[:shell_exclude] = !!(shell =~ /#{options[:exclude_by_shell_regex]}/)
72
+ end
73
+
74
+ def self.apply_other_filters(options, filters, fcb)
75
+ name = fcb.fetch(:name, '')
76
+ shell = fcb.fetch(:shell, '')
77
+ filters[:fcb_chrome] = fcb.fetch(:chrome, false)
78
+
79
+ if name.present? && options[:hide_blocks_by_name] &&
80
+ options[:block_name_hidden_match].present?
81
+ filters[:hidden_name] = !!(name =~ /#{options[:block_name_hidden_match]}/)
82
+ end
83
+
84
+ if shell.present? && options[:hide_blocks_by_shell] &&
85
+ options[:block_shell_hidden_match].present?
86
+ !!(shell =~ /#{options[:block_shell_hidden_match]}/)
87
+ end
88
+
89
+ return unless options[:bash_only]
90
+
91
+ filters[:shell_default] = (shell == 'bash')
92
+ end
93
+
94
+ def self.evaluate_filters(options, filters)
95
+ if options[:no_chrome] && filters[:fcb_chrome]
96
+ false
97
+ elsif options[:exclude_expect_blocks] && filters[:shell_expect]
98
+ false
99
+ elsif filters[:hidden_name] == true
100
+ true
101
+ elsif filters[:name_exclude] == true || filters[:shell_exclude] == true || filters[:name_select] == false || filters[:shell_select] == false
102
+ false
103
+ elsif filters[:name_select] == true || filters[:shell_select] == true
104
+ true
105
+ elsif filters[:name_default] == false || filters[:shell_default] == false
106
+ false
107
+ else
108
+ true
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ if $PROGRAM_NAME == __FILE__
115
+ require 'minitest/autorun'
116
+
117
+ require_relative 'tap'
118
+ include Tap
119
+
120
+ class FilterTest < Minitest::Test
121
+ def test_no_chrome_condition
122
+ options = { no_chrome: true }
123
+ fcb = { chrome: true }
124
+ refute MarkdownExec::Filter.fcb_select?(options, fcb)
125
+ end
126
+
127
+ def test_exclude_expect_blocks_condition
128
+ options = { exclude_expect_blocks: true }
129
+ fcb = { shell: 'expect' }
130
+ refute MarkdownExec::Filter.fcb_select?(options, fcb)
131
+ end
132
+
133
+ def test_hidden_name_condition
134
+ options = { hide_blocks_by_name: true, block_name_hidden_match: 'hidden' }
135
+ fcb = { name: 'hidden_block' }
136
+ assert MarkdownExec::Filter.fcb_select?(options, fcb)
137
+ end
138
+
139
+ def test_name_exclude_condition
140
+ options = { block_name: 'test' }
141
+ fcb = { name: 'sample' }
142
+ refute MarkdownExec::Filter.fcb_select?(options, fcb)
143
+ end
144
+
145
+ def test_shell_exclude_condition
146
+ options = { exclude_by_shell_regex: 'exclude_this' }
147
+ fcb = { shell: 'exclude_this_shell' }
148
+ refute MarkdownExec::Filter.fcb_select?(options, fcb)
149
+ end
150
+
151
+ def test_name_select_condition
152
+ options = { select_by_name_regex: 'select' }
153
+ fcb = { name: 'select_this' }
154
+ assert MarkdownExec::Filter.fcb_select?(options, fcb)
155
+ end
156
+
157
+ def test_shell_select_condition
158
+ options = { select_by_shell_regex: 'select_this' }
159
+ fcb = { shell: 'select_this_shell' }
160
+ assert MarkdownExec::Filter.fcb_select?(options, fcb)
161
+ end
162
+
163
+ def test_bash_only_condition_true
164
+ options = { bash_only: true }
165
+ fcb = { shell: 'bash' }
166
+ assert MarkdownExec::Filter.fcb_select?(options, fcb)
167
+ end
168
+
169
+ def test_bash_only_condition_false
170
+ options = { bash_only: true }
171
+ fcb = { shell: 'zsh' }
172
+ refute MarkdownExec::Filter.fcb_select?(options, fcb)
173
+ end
174
+
175
+ def test_default_case
176
+ options = {}
177
+ fcb = {}
178
+ assert MarkdownExec::Filter.fcb_select?(options, fcb)
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ require_relative 'filter'
7
+
8
+ module MarkdownExec
9
+ ##
10
+ # MarkdownBlockManager represents an imported markdown document.
11
+ #
12
+ # It provides methods to extract and manipulate specific sections
13
+ # of the document, such as code blocks. It also supports recursion
14
+ # to fetch related or dependent blocks.
15
+ #
16
+ class MarkdownBlockManager
17
+ attr_reader :block_table
18
+
19
+ def initialize(block_table)
20
+ @block_table = block_table
21
+ end
22
+
23
+ def collect_required_code(name)
24
+ gather_required_blocks(name)
25
+ .map do |block|
26
+ process_block_code(block)
27
+ end.flatten(1)
28
+ end
29
+
30
+ def get_block(name, default = {})
31
+ @block_table.select { |block| block.fetch(:name, '') == name }.fetch(0, default)
32
+ end
33
+
34
+ def gather_required_blocks(name)
35
+ named_block = get_block(name)
36
+ if named_block.nil? || named_block.keys.empty?
37
+ raise "Named code block `#{name}` not found."
38
+ end
39
+
40
+ all_blocks = [named_block.fetch(:name, '')] + required_blocks(named_block[:reqs])
41
+ @block_table.select { |block| all_blocks.include? block.fetch(:name, '') }
42
+ .map do |block|
43
+ process_block_references(block)
44
+ end.flatten(1)
45
+ end
46
+
47
+ def hide_block_given_options(opts, block)
48
+ (opts[:hide_blocks_by_name] &&
49
+ block[:name]&.match(Regexp.new(opts[:block_name_hidden_match])) &&
50
+ (block[:name]&.present? || block[:label]&.present?)
51
+ )
52
+ end
53
+
54
+ def blocks_per_options(opts = {})
55
+ filtered_blocks = @block_table.select do |block_group|
56
+ Filter.block_selected? opts, block_group
57
+ end
58
+ if opts[:hide_blocks_by_name]
59
+ filtered_blocks.reject { |block| hide_block_given_options opts, block }
60
+ else
61
+ filtered_blocks
62
+ end.map do |block|
63
+ block
64
+ end
65
+ end
66
+
67
+ def required_blocks(reqs)
68
+ return [] unless reqs
69
+
70
+ remaining = reqs
71
+ collected = []
72
+ while remaining.count.positive?
73
+ remaining = remaining.map do |req|
74
+ next if collected.include? req
75
+
76
+ collected += [req]
77
+ get_block(req).fetch(:reqs, [])
78
+ end
79
+ .compact
80
+ .flatten(1)
81
+ end
82
+ collected
83
+ end
84
+
85
+ # Helper method to process block code
86
+ def process_block_code(block)
87
+ body = block[:body].join("\n")
88
+
89
+ if block[:cann]
90
+ xcall = block[:cann][1..-2]
91
+ mstdin = xcall.match(/<(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
92
+ mstdout = xcall.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
93
+
94
+ yqcmd = if mstdin[:type]
95
+ "echo \"$#{mstdin[:name]}\" | yq '#{body}'"
96
+ else
97
+ "yq e '#{body}' '#{mstdin[:name]}'"
98
+ end
99
+ if mstdout[:type]
100
+ "export #{mstdout[:name]}=$(#{yqcmd})"
101
+ else
102
+ "#{yqcmd} > '#{mstdout[:name]}'"
103
+ end
104
+ elsif block[:stdout]
105
+ stdout = block[:stdout]
106
+ body = block[:body].join("\n")
107
+ if stdout[:type]
108
+ %(export #{stdout[:name]}=$(cat <<"EOF"\n#{body}\nEOF\n))
109
+ else
110
+ "cat > '#{stdout[:name]}' <<\"EOF\"\n" \
111
+ "#{body}\n" \
112
+ "EOF\n"
113
+ end
114
+ else
115
+ block[:body]
116
+ end
117
+ end
118
+
119
+ # Helper method to process block references
120
+ def process_block_references(block)
121
+ if (call = block[:call])
122
+ [get_block("[#{call.match(/^%\((\S+) |\)/)[1]}]")
123
+ .merge({ cann: call })]
124
+ else
125
+ []
126
+ end + [block]
127
+ end
128
+ end
129
+ end
130
+
131
+ if $PROGRAM_NAME == __FILE__
132
+ # require 'bundler/setup'
133
+ # Bundler.require(:default)
134
+
135
+ require 'minitest/autorun'
136
+
137
+ require_relative 'tap'
138
+ include Tap
139
+
140
+ module MarkdownExec
141
+ class TestMDoc < Minitest::Test
142
+ def setup
143
+ @table = [
144
+ { name: 'block1', body: ['code for block1'], reqs: ['block2'] },
145
+ { name: 'block2', body: ['code for block2'], reqs: nil },
146
+ { name: 'block3', body: ['code for block3'], reqs: ['block1'] }
147
+ ]
148
+ @doc = MDoc.new(@table)
149
+ end
150
+
151
+ def test_collect_recursively_required_code
152
+ result = @doc.collect_recursively_required_code('block1')
153
+ expected_result = @table[0][:body] + @table[1][:body]
154
+ assert_equal expected_result, result
155
+ end
156
+
157
+ def test_get_block_by_name
158
+ result = @doc.get_block_by_name('block1')
159
+ assert_equal @table[0], result
160
+
161
+ result_missing = @doc.get_block_by_name('missing_block')
162
+ assert_equal({}, result_missing)
163
+ end
164
+
165
+ def test_get_required_blocks
166
+ result = @doc.get_required_blocks('block3')
167
+ expected_result = [@table[0], @table[1], @table[2]]
168
+ assert_equal expected_result, result
169
+
170
+ assert_raises(RuntimeError) { @doc.get_required_blocks('missing_block') }
171
+ end
172
+
173
+ def test_hide_menu_block_per_options
174
+ opts = { hide_blocks_by_name: true, block_name_hidden_match: 'block1' }
175
+ block = { name: 'block1' }
176
+ result = @doc.hide_menu_block_per_options(opts, block)
177
+ assert result # this should be true based on the given logic
178
+ end
179
+
180
+ def test_fcbs_per_options
181
+ opts = { hide_blocks_by_name: true, block_name_hidden_match: 'block1' }
182
+ result = @doc.fcbs_per_options(opts)
183
+ assert_equal [@table[1], @table[2]], result
184
+ end
185
+
186
+ def test_recursively_required
187
+ result = @doc.recursively_required(['block3'])
188
+ assert_equal %w[block3 block1 block2], result
189
+
190
+ result_no_reqs = @doc.recursively_required(nil)
191
+ assert_equal [], result_no_reqs
192
+ end
193
+ end
194
+ end
195
+ end
@@ -7,5 +7,5 @@ module MarkdownExec
7
7
  BIN_NAME = 'mde'
8
8
  GEM_NAME = 'markdown_exec'
9
9
  TAP_DEBUG = 'MDE_DEBUG'
10
- VERSION = '1.3.3.5'
10
+ VERSION = '1.3.7'
11
11
  end