lib/text_analyzer.rb in markdown_exec-2.3.0 vs lib/text_analyzer.rb in markdown_exec-2.4.0

- old
+ new

@@ -9,17 +9,21 @@ # @param match_color [String] the color for matching segments # # @return [Array<Hash>, Array<Array<Hash>>] an array or nested arrays of highlighted segments # # @raise [ArgumentError] if the hierarchy structure is neither a String nor an Array - def self.analyze_hierarchy(hierarchy, pattern, default_color, match_color) + def self.analyze_hierarchy( + hierarchy, pattern, default_color, match_color, + text_sym: :text, style_sym: :color + ) case hierarchy when String highlight_segments(hierarchy, pattern, default_color, match_color) + when Hash - decorated = highlight_segments(hierarchy[:text], pattern, - hierarchy[:color], match_color) + decorated = highlight_segments(hierarchy[text_sym], pattern, + hierarchy[style_sym], match_color) case decorated when String hierarchy when Array @@ -29,22 +33,23 @@ decorated end else decorated end + when Array hierarchy.map do |element| analyze_hierarchy(element, pattern, default_color, match_color) end - when HierarchyString + when HierarchyString hierarchy.replace_text! do |substring| - substring ### no change + substring # no change end else - binding.irb + warn [hierarchy.class, hierarchy].inspect raise ArgumentError, 'Invalid hierarchy structure' end end # Highlights segments of the text based on the pattern @@ -75,26 +80,157 @@ # @param pattern [Regexp] the pattern to match against the text # # @yieldparam segment [String] a segment of the text # @yieldparam is_match [Boolean] true if the segment matches the pattern, false otherwise def self.yield_matches_and_non_matches(text, pattern) - last_end = 0 + last_end = nil text.scan(pattern) do |match| match_start = Regexp.last_match.begin(0) match_end = Regexp.last_match.end(0) # Yield the non-matching segment before the match - yield text[last_end...match_start], false if match_start > last_end + yield text[(last_end || 0)...match_start], false if last_end.nil? || match_start > last_end # Yield the matching segment yield match.first, true last_end = match_end end + last_end ||= 0 # Yield any remaining non-matching segment after the last match return unless last_end < text.length yield text[last_end..-1], false + end +end + +return if $PROGRAM_NAME != __FILE__ + +require 'minitest/autorun' +require_relative 'hierarchy_string' + +$default_color = :upcase +$match_color = :downcase + +class TestTextAnalyzer < Minitest::Test + def test_analyze_hierarchy_with_string + text = 'This is a test string.' + pattern = /(test)/ + + expected_output = [[[ + { text: 'This is a ', color: $default_color }, + { text: 'test', color: $match_color }, + { text: ' string.', color: $default_color } + ]]] + + tree = HierarchyString.new([{ text: text, color: $default_color }]) + assert_equal expected_output, + TextAnalyzer.analyze_hierarchy(tree.substrings, pattern, $default_color, + $match_color) + end + + def test_analyze_hierarchy_with_array + hierarchy = [ + 'This is a test string.', + 'Another test line.' + ] + pattern = /(test)/ + + expected_output = [ + [ + { text: 'This is a ', color: $default_color }, + { text: 'test', color: $match_color }, + { text: ' string.', color: $default_color } + ], + [ + { text: 'Another ', color: $default_color }, + { text: 'test', color: $match_color }, + { text: ' line.', color: $default_color } + ] + ] + + assert_equal expected_output, + TextAnalyzer.analyze_hierarchy(hierarchy, pattern, + $default_color, $match_color) + end + + def test_analyze_hierarchy_with_nested_array + hierarchy = [ + 'This is a test string.', + ['Another test line.', 'Yet another test.'] + ] + pattern = /(test)/ + + expected_output = [ + [ + { text: 'This is a ', color: $default_color }, + { text: 'test', color: $match_color }, + { text: ' string.', color: $default_color } + ], + [ + [ + { text: 'Another ', color: $default_color }, + { text: 'test', color: $match_color }, + { text: ' line.', color: $default_color } + ], + [ + { text: 'Yet another ', color: $default_color }, + { text: 'test', color: $match_color }, + { text: '.', color: $default_color } + ] + ] + ] + + assert_equal expected_output, + TextAnalyzer.analyze_hierarchy(hierarchy, pattern, + $default_color, $match_color) + end + + def test_analyze_hierarchy_with_invalid_type + hierarchy = 12_345 + # hierarchy = HierarchyString.new([{ text: '12345', color: $default_color }]) + pattern = /(test)/ + + assert_raises(ArgumentError) do + TextAnalyzer.analyze_hierarchy(hierarchy, pattern, $default_color, + $match_color) + end + end + + def test_highlight_segments + text = 'This is a test string.' + pattern = /(test)/ + + expected_output = [ + { text: 'This is a ', color: $default_color }, + { text: 'test', color: $match_color }, + { text: ' string.', color: $default_color } + ] + + assert_equal expected_output, + TextAnalyzer.highlight_segments(text, pattern, $default_color, + $match_color) + end + + def test_yield_matches_and_non_matches + text = 'This is a test string with multiple tests.' + pattern = /(test)/ + segments = [] + + TextAnalyzer.yield_matches_and_non_matches(text, + pattern) do |segment, is_match| + segments << { text: segment, is_match: is_match } + end + + expected_output = [ + { text: 'This is a ', is_match: false }, + { text: 'test', is_match: true }, + { text: ' string with multiple ', is_match: false }, + { text: 'test', is_match: true }, + { text: 's.', is_match: false } + ] + + assert_equal expected_output, segments end end