Sha256: a979aa8cb9b6a96fa8d01c4634baa479ec4a5283feb7d8763aa806921d27bad2

Contents?: true

Size: 1.42 KB

Versions: 2

Compression:

Stored size: 1.42 KB

Contents

# frozen_string_literal: true

require 'regexp_parser'

module Capybara
  class Selector
    # @api private
    class RegexpDisassembler
      def initialize(regexp)
        @regexp = regexp
      end

      def substrings
        @substrings ||= begin
          strs = extract_strings(Regexp::Parser.parse(@regexp), [+''])
          strs.map!(&:upcase) if @regexp.casefold?
          strs.reject(&:empty?).uniq
        end
      end

    private

      def min_repeat(exp)
        exp.quantifier&.min || 1
      end

      def fixed_repeat?(exp)
        min_repeat(exp) == (exp.quantifier&.max || 1)
      end

      def optional?(exp)
        min_repeat(exp).zero?
      end

      def extract_strings(expression, strings)
        expression.each do |exp|
          if optional?(exp)
            strings.push(+'')
            next
          end

          if %i[meta set].include?(exp.type)
            strings.push(+'')
            next
          end

          if exp.terminal?
            case exp.type
            when :literal
              strings.last << (exp.text * min_repeat(exp))
            when :escape
              strings.last << (exp.char * min_repeat(exp))
            else
              strings.push(+'')
            end
          else
            min_repeat(exp).times { extract_strings(exp, strings) }
          end
          strings.push(+'') unless fixed_repeat?(exp)
        end
        strings
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
capybara-3.10.1 lib/capybara/selector/regexp_disassembler.rb
capybara-3.10.0 lib/capybara/selector/regexp_disassembler.rb