mirror of
https://github.com/StrawberryMaster/wayback-machine-downloader.git
synced 2025-12-17 17:56:44 +00:00
Refactoring
This commit is contained in:
parent
4d5f187f15
commit
fdcb81f1a0
@ -1,17 +1,25 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module ToRegex
|
module ToRegex
|
||||||
module StringMixin
|
module StringMixin
|
||||||
|
INLINE_OPTIONS = /[imxnesu]*/i.freeze
|
||||||
|
REGEXP_DELIMITERS = {
|
||||||
|
'%r{' => '}'.freeze,
|
||||||
|
'/' => '/'.freeze
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
REGEX_FLAGS = {
|
||||||
|
ignore_case: Regexp::IGNORECASE,
|
||||||
|
multiline: Regexp::MULTILINE,
|
||||||
|
extended: Regexp::EXTENDED
|
||||||
|
}.freeze
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def literal?(str)
|
def literal?(str)
|
||||||
REGEXP_DELIMITERS.none? { |s, e| str.start_with?(s) and str =~ /#{e}#{INLINE_OPTIONS}\z/ }
|
REGEXP_DELIMITERS.none? { |start, ending| str.start_with?(start) && str.match?(/#{ending}#{INLINE_OPTIONS}\z/) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
INLINE_OPTIONS = /[imxnesu]*/
|
|
||||||
REGEXP_DELIMITERS = {
|
|
||||||
'%r{' => '}',
|
|
||||||
'/' => '/',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get a regex back
|
# Get a regex back
|
||||||
#
|
#
|
||||||
# Without :literal or :detect, `"foo".to_regex` will return nil.
|
# Without :literal or :detect, `"foo".to_regex` will return nil.
|
||||||
@ -24,54 +32,72 @@ module ToRegex
|
|||||||
# @option options [true,false] :extended /foo/x
|
# @option options [true,false] :extended /foo/x
|
||||||
# @option options [true,false] :lang /foo/[nesu]
|
# @option options [true,false] :lang /foo/[nesu]
|
||||||
def to_regex(options = {})
|
def to_regex(options = {})
|
||||||
if args = as_regexp(options)
|
args = as_regexp(options)
|
||||||
::Regexp.new(*args)
|
args ? Regexp.new(*args) : nil
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# Return arguments that can be passed to `Regexp.new`
|
# Return arguments that can be passed to `Regexp.new`
|
||||||
# @see to_regexp
|
# @see to_regexp
|
||||||
def as_regexp(options = {})
|
def as_regexp(options = {})
|
||||||
unless options.is_a?(::Hash)
|
raise ArgumentError, '[to_regexp] Options must be a Hash' unless options.is_a?(Hash)
|
||||||
raise ::ArgumentError, "[to_regexp] Options must be a Hash"
|
|
||||||
end
|
|
||||||
str = self
|
str = self
|
||||||
|
return if options[:detect] && str.empty?
|
||||||
|
|
||||||
return if options[:detect] and str == ''
|
if should_treat_as_literal?(str, options)
|
||||||
|
content = Regexp.escape(str)
|
||||||
|
elsif (delim_set = extract_delimiters(str))
|
||||||
|
content, options = parse_regexp_string(str, delim_set, options)
|
||||||
|
return unless content
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if options[:literal] or (options[:detect] and ToRegexp::String.literal?(str))
|
build_regexp_args(content, options)
|
||||||
content = ::Regexp.escape str
|
end
|
||||||
elsif delim_set = REGEXP_DELIMITERS.detect { |k, _| str.start_with?(k) }
|
|
||||||
delim_start, delim_end = delim_set
|
private
|
||||||
/\A#{delim_start}(.*)#{delim_end}(#{INLINE_OPTIONS})\z/u =~ str
|
|
||||||
content = $1
|
def should_treat_as_literal?(str, options)
|
||||||
inline_options = $2
|
options[:literal] || (options[:detect] && ToRegex::StringMixin.literal?(str))
|
||||||
return unless content.is_a?(::String)
|
end
|
||||||
content.gsub! '\\/', '/'
|
|
||||||
if inline_options
|
def extract_delimiters(str)
|
||||||
|
REGEXP_DELIMITERS.find { |start, _| str.start_with?(start) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_regexp_string(str, delim_set, options)
|
||||||
|
start_delim, end_delim = delim_set
|
||||||
|
match = /\A#{start_delim}(.*)#{end_delim}(#{INLINE_OPTIONS})\z/u.match(str)
|
||||||
|
return unless match
|
||||||
|
|
||||||
|
content = match[1].gsub('\\/', '/')
|
||||||
|
parse_inline_options(match[2], options)
|
||||||
|
[content, options]
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_inline_options(inline_options, options)
|
||||||
|
return unless inline_options
|
||||||
options[:ignore_case] = true if inline_options.include?('i')
|
options[:ignore_case] = true if inline_options.include?('i')
|
||||||
options[:multiline] = true if inline_options.include?('m')
|
options[:multiline] = true if inline_options.include?('m')
|
||||||
options[:extended] = true if inline_options.include?('x')
|
options[:extended] = true if inline_options.include?('x')
|
||||||
# 'n', 'N' = none, 'e', 'E' = EUC, 's', 'S' = SJIS, 'u', 'U' = UTF-8
|
# 'n', 'N' = none, 'e', 'E' = EUC, 's', 'S' = SJIS, 'u', 'U' = UTF-8
|
||||||
options[:lang] = inline_options.scan(/[nesu]/i).join.downcase
|
options[:lang] = inline_options.scan(/[nesu]/i).join.downcase
|
||||||
end
|
end
|
||||||
else
|
|
||||||
return
|
def build_regexp_args(content, options)
|
||||||
|
flags = calculate_flags(options)
|
||||||
|
lang = normalize_lang_option(options[:lang])
|
||||||
|
|
||||||
|
lang.empty? ? [content, flags] : [content, flags, lang]
|
||||||
end
|
end
|
||||||
|
|
||||||
ignore_case = options[:ignore_case] ? ::Regexp::IGNORECASE : 0
|
def calculate_flags(options)
|
||||||
multiline = options[:multiline] ? ::Regexp::MULTILINE : 0
|
REGEX_FLAGS.sum { |key, value| options[key] ? value : 0 }
|
||||||
extended = options[:extended] ? ::Regexp::EXTENDED : 0
|
|
||||||
lang = options[:lang] || ''
|
|
||||||
if ::RUBY_VERSION > '1.9' and lang.include?('u')
|
|
||||||
lang = lang.delete 'u'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if lang.empty?
|
def normalize_lang_option(lang)
|
||||||
[ content, (ignore_case|multiline|extended) ]
|
return '' unless lang
|
||||||
else
|
RUBY_VERSION >= '1.9' ? lang.delete('u') : lang
|
||||||
[ content, (ignore_case|multiline|extended), lang ]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user