import json
import re
from typing import Pattern, Union
def escape_regex_flags(pattern: Pattern) -> str:
flags = ""
if pattern.flags != 0:
flags = ""
if pattern.flags & int(re.IGNORECASE) != 0:
flags += "i"
if pattern.flags & int(re.DOTALL) != 0:
flags += "s"
if pattern.flags & int(re.MULTILINE) != 0:
flags += "m"
assert (
pattern.flags
& ~(int(re.MULTILINE) | int(re.IGNORECASE) | int(re.DOTALL) | int(re.UNICODE))
== 0
), (
"Unexpected re.Pattern flag, only MULTILINE, IGNORECASE and DOTALL are supported."
)
return flags
def escape_for_regex(text: str) -> str:
return re.sub("[.*+?^>${}()|[\\]\\\\]", "\\$&", text)
def escape_regex_for_selector(text: Pattern) -> str:
return (
"/"
+ re.sub(
"(^|[^\\\\])(\\\\\\\\)*([\"\\'`])", "\\1\\2\\\\\\3", text.pattern
).replace(">>", "\\>\\>")
+ "/"
+ escape_regex_flags(text)
)
def escape_for_text_selector(
text: Union[str, Pattern[str]], exact: bool = None, case_sensitive: bool = None
) -> str:
if isinstance(text, Pattern):
return escape_regex_for_selector(text)
return json.dumps(text) + ("s" if exact else "i")
def escape_for_attribute_selector(
value: Union[str, Pattern], exact: bool = None
) -> str:
if isinstance(value, Pattern):
return escape_regex_for_selector(value)
return (
'"'
+ value.replace("\\", "\\\\").replace('"', '\\"')
+ '"'
+ ("s" if exact else "i")
)