///|
/// JavaScript RegExp object wrapper.
///
/// Corresponds to JavaScript's `RegExp` constructor and object.
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
#external
pub type RegExp
///|
pub fn RegExp::to_any(self : RegExp) -> @core.Any = "%identity"
///|
/// Result of RegExp.exec() method.
///
/// Corresponds to the return value of JavaScript's `RegExp.prototype.exec()`.
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
pub struct RegExpResult {
full : String
input : String
index : Int
lastIndex : Int
groups : Map[String, String]?
}
///|
pub fn RegExpResult::to_any(self : RegExpResult) -> @core.Any = "%identity"
///|
/// Result of String.match() or String.matchAll() methods.
///
/// Corresponds to the return value of JavaScript's `String.prototype.match()` and `String.prototype.matchAll()`.
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll
pub struct RegExpMatchArray {
matches : Array[String]
index : Int?
input : String?
groups : Map[String, String]?
}
///|
pub fn RegExpMatchArray::to_any(self : RegExpMatchArray) -> @core.Any = "%identity"
///|
extern "js" fn ffi_regexp_new(s : String, flags : String) -> RegExp =
#|(s, flags) => new RegExp(s, flags)
///|
extern "js" fn RegExp::ffi_regexp_test(self : RegExp, string : String) -> Bool =
#|(re, string) => re.test(string)
///|
extern "js" fn RegExp::ffi_regexp_exec(
self : RegExp,
string : String,
) -> @core.Any =
#|(re, string) => re.exec(string)
///|
/// JavaScript API: RegExp.prototype.source
extern "js" fn RegExp::ffi_regexp_source(self : RegExp) -> String =
#|(re) => re.source
///|
/// JavaScript API: RegExp.prototype.flags
extern "js" fn RegExp::ffi_regexp_flags(self : RegExp) -> String =
#|(re) => re.flags
///|
/// JavaScript API: RegExp.prototype.global
extern "js" fn RegExp::ffi_regexp_global(self : RegExp) -> Bool =
#|(re) => re.global
///|
/// JavaScript API: RegExp.prototype.ignoreCase
extern "js" fn RegExp::ffi_regexp_ignore_case(self : RegExp) -> Bool =
#|(re) => re.ignoreCase
///|
/// JavaScript API: RegExp.prototype.multiline
extern "js" fn RegExp::ffi_regexp_multiline(self : RegExp) -> Bool =
#|(re) => re.multiline
///|
/// JavaScript API: RegExp.prototype.sticky
extern "js" fn RegExp::ffi_regexp_sticky(self : RegExp) -> Bool =
#|(re) => re.sticky
///|
/// JavaScript API: RegExp.prototype.unicode
extern "js" fn RegExp::ffi_regexp_unicode(self : RegExp) -> Bool =
#|(re) => re.unicode
///|
/// JavaScript API: RegExp.prototype.dotAll
extern "js" fn RegExp::ffi_regexp_dot_all(self : RegExp) -> Bool =
#|(re) => re.dotAll
///|
/// JavaScript API: RegExp.prototype.hasIndices
extern "js" fn RegExp::ffi_regexp_has_indices(self : RegExp) -> Bool =
#|(re) => re.hasIndices
///|
/// JavaScript API: RegExp.prototype.lastIndex (getter)
extern "js" fn RegExp::ffi_regexp_get_last_index(self : RegExp) -> Int =
#|(re) => re.lastIndex
///|
/// JavaScript API: RegExp.prototype.lastIndex (setter)
extern "js" fn RegExp::ffi_regexp_set_last_index(
self : RegExp,
index : Int,
) -> Unit =
#|(re, index) => { re.lastIndex = index; }
///|
/// JavaScript API: RegExp.prototype.toString()
extern "js" fn RegExp::ffi_regexp_to_string(self : RegExp) -> String =
#|(re) => re.toString()
///|
/// JavaScript API: String.prototype.match()
extern "js" fn ffi_string_match(string : String, re : RegExp) -> @core.Any =
#|(string, re) => string.match(re)
///|
/// JavaScript API: String.prototype.matchAll()
extern "js" fn ffi_string_match_all(string : String, re : RegExp) -> @core.Any =
#|(string, re) => Array.from(string.matchAll(re))
///|
/// JavaScript API: String.prototype.replace()
extern "js" fn ffi_string_replace(
string : String,
re : RegExp,
replacement : String,
) -> String =
#|(string, re, replacement) => string.replace(re, replacement)
///|
/// JavaScript API: String.prototype.replaceAll()
extern "js" fn ffi_string_replace_all(
string : String,
re : RegExp,
replacement : String,
) -> String =
#|(string, re, replacement) => string.replaceAll(re, replacement)
///|
/// JavaScript API: String.prototype.replace() with replacer function
extern "js" fn ffi_string_replace_fn(
string : String,
re : RegExp,
replacer : @core.Any,
) -> String =
#|(string, re, replacer) => string.replace(re, replacer)
///|
/// JavaScript API: String.prototype.replaceAll() with replacer function
extern "js" fn ffi_string_replace_all_fn(
string : String,
re : RegExp,
replacer : @core.Any,
) -> String =
#|(string, re, replacer) => string.replaceAll(re, replacer)
///|
/// JavaScript API: String.prototype.search()
extern "js" fn ffi_string_search(string : String, re : RegExp) -> Int =
#|(string, re) => string.search(re)
///|
/// JavaScript API: String.prototype.split()
extern "js" fn ffi_string_split(
string : String,
re : RegExp,
limit : @core.Any,
) -> Array[String] =
#|(string, re, limit) => string.split(re, limit === null ? undefined : limit)
///|
/// Get the source pattern of the regular expression.
///
/// JavaScript API: `RegExp.prototype.source`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source
pub fn RegExp::source(self : RegExp) -> String {
RegExp::ffi_regexp_source(self)
}
///|
/// Get the flags string of the regular expression.
///
/// JavaScript API: `RegExp.prototype.flags`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags
pub fn RegExp::flags(self : RegExp) -> String {
RegExp::ffi_regexp_flags(self)
}
///|
/// Check if the global flag is set.
///
/// JavaScript API: `RegExp.prototype.global`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/global
pub fn RegExp::global(self : RegExp) -> Bool {
RegExp::ffi_regexp_global(self)
}
///|
/// Check if the ignoreCase flag is set.
///
/// JavaScript API: `RegExp.prototype.ignoreCase`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase
pub fn RegExp::ignore_case(self : RegExp) -> Bool {
RegExp::ffi_regexp_ignore_case(self)
}
///|
/// Check if the multiline flag is set.
///
/// JavaScript API: `RegExp.prototype.multiline`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/multiline
pub fn RegExp::multiline(self : RegExp) -> Bool {
RegExp::ffi_regexp_multiline(self)
}
///|
/// Check if the sticky flag is set.
///
/// JavaScript API: `RegExp.prototype.sticky`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/sticky
pub fn RegExp::sticky(self : RegExp) -> Bool {
RegExp::ffi_regexp_sticky(self)
}
///|
/// Check if the unicode flag is set.
///
/// JavaScript API: `RegExp.prototype.unicode`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode
pub fn RegExp::unicode(self : RegExp) -> Bool {
RegExp::ffi_regexp_unicode(self)
}
///|
/// Check if the dotAll flag is set.
///
/// JavaScript API: `RegExp.prototype.dotAll`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/dotAll
pub fn RegExp::dotAll(self : RegExp) -> Bool {
RegExp::ffi_regexp_dot_all(self)
}
///|
/// Check if the hasIndices flag is set.
///
/// JavaScript API: `RegExp.prototype.hasIndices`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/hasIndices
pub fn RegExp::hasIndices(self : RegExp) -> Bool {
RegExp::ffi_regexp_has_indices(self)
}
///|
/// Get the index at which to start the next match.
///
/// JavaScript API: `RegExp.prototype.lastIndex` (getter)
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex
pub fn RegExp::lastIndex(self : RegExp) -> Int {
RegExp::ffi_regexp_get_last_index(self)
}
///|
/// Set the index at which to start the next match.
///
/// JavaScript API: `RegExp.prototype.lastIndex` (setter)
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex
pub fn RegExp::set_last_index(self : RegExp, index : Int) -> Unit {
RegExp::ffi_regexp_set_last_index(self, index)
}
///|
/// Convert the regular expression to a string.
///
/// JavaScript API: `RegExp.prototype.toString()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/toString
pub fn RegExp::to_string(self : RegExp) -> String {
RegExp::ffi_regexp_to_string(self)
}
///|
/// Test if the pattern matches the given string.
///
/// JavaScript API: `RegExp.prototype.test()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test
pub fn RegExp::test_(self : RegExp, string : String) -> Bool {
RegExp::ffi_regexp_test(self, string)
}
///|
/// Execute the regular expression and return detailed match information.
///
/// JavaScript API: `RegExp.prototype.exec()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
pub fn RegExp::exec(self : RegExp, s : String) -> RegExpResult? {
let v : @core.Any = RegExp::ffi_regexp_exec(self, s) |> @core.any
if @core.is_null(v) {
return None
}
let full : String = v["0"].cast()
let index : Int = v["index"].cast()
let last_index : Int = v["lastIndex"].cast()
let input : String = v["input"].cast()
let groups : Map[String, String]? = if @core.is_undefined(v["groups"]) {
None
} else {
let g : Map[String, String] = Map([])
let keys = @core.object_keys(v["groups"])
for k in keys {
g[k] = v["groups"][k].cast()
}
Some(g)
}
{ full, input, index, lastIndex: last_index, groups } |> Some
}
///|
/// Create a new RegExp instance.
///
/// JavaScript API: `new RegExp(pattern, flags)`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp
pub fn RegExp::new(pattern : String, flags? : String) -> RegExp {
let flags_str = match flags {
None => ""
Some(f) => f
}
ffi_regexp_new(pattern, flags_str)
}
///|
/// Match a regular expression against a string.
///
/// JavaScript API: `String.prototype.match()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match
pub fn RegExp::match_(self : RegExp, string : String) -> RegExpMatchArray? {
let v : @core.Any = ffi_string_match(string, self) |> @core.any
if @core.is_null(v) {
return None
}
let len : Int = v["length"].cast()
let matches : Array[String] = Array::new(capacity=len)
for i = 0; i < len; i = i + 1 {
matches.push(v[i.to_string()].cast())
}
let index : Int? = if @core.is_undefined(v["index"]) {
None
} else {
Some(v["index"].cast())
}
let input : String? = if @core.is_undefined(v["input"]) {
None
} else {
Some(v["input"].cast())
}
let groups : Map[String, String]? = if @core.is_undefined(v["groups"]) {
None
} else {
let g : Map[String, String] = Map([])
let keys = @core.object_keys(v["groups"])
for k in keys {
g[k] = v["groups"][k].cast()
}
Some(g)
}
Some({ matches, index, input, groups })
}
///|
/// Return all matches of a regular expression against a string.
///
/// JavaScript API: `String.prototype.matchAll()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll
pub fn RegExp::matchAll(
self : RegExp,
string : String,
) -> Array[RegExpMatchArray] {
let v : @core.Any = ffi_string_match_all(string, self) |> @core.any
let len : Int = v["length"].cast()
let results : Array[RegExpMatchArray] = []
for i = 0; i < len; i = i + 1 {
let item = v[i.to_string()]
let match_len : Int = item["length"].cast()
let matches : Array[String] = Array::new(capacity=match_len)
for j = 0; j < match_len; j = j + 1 {
matches.push(item[j.to_string()].cast())
}
let index : Int? = if @core.is_undefined(item["index"]) {
None
} else {
Some(item["index"].cast())
}
let input : String? = if @core.is_undefined(item["input"]) {
None
} else {
Some(item["input"].cast())
}
let groups : Map[String, String]? = if @core.is_undefined(item["groups"]) {
None
} else {
let g : Map[String, String] = Map([])
let keys = @core.object_keys(item["groups"])
for k in keys {
g[k] = item["groups"][k].cast()
}
Some(g)
}
results.push({ matches, index, input, groups })
}
results
}
///|
/// Replace matches of the regular expression with a string.
///
/// JavaScript API: `String.prototype.replace()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
pub fn RegExp::replace(
self : RegExp,
string : String,
replacement : String,
) -> String {
ffi_string_replace(string, self, replacement)
}
///|
/// Replace all matches of the regular expression with a string.
///
/// JavaScript API: `String.prototype.replaceAll()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
pub fn RegExp::replace_all(
self : RegExp,
string : String,
replacement : String,
) -> String {
ffi_string_replace_all(string, self, replacement)
}
///|
/// Replace matches of the regular expression using a replacer function.
///
/// JavaScript API: `String.prototype.replace()` with replacer function
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
pub fn RegExp::replace_fn(
self : RegExp,
string : String,
replacer : (String, Array[String], Int, String) -> String,
) -> String {
let wrapper = fn(
matched : String,
groups_val : @core.Any,
offset : Int,
input : String,
) -> String {
let gv : @core.Any = groups_val |> @core.any
let groups_len : Int = gv["length"].cast()
let groups : Array[String] = Array::new(capacity=groups_len)
for i = 0; i < groups_len; i = i + 1 {
let item = gv[i.to_string()]
if @core.is_undefined(item) {
groups.push("")
} else {
groups.push(item.cast())
}
}
replacer(matched, groups, offset, input)
}
ffi_string_replace_fn(string, self, @core.any(wrapper))
}
///|
/// Replace all matches of the regular expression using a replacer function.
///
/// JavaScript API: `String.prototype.replaceAll()` with replacer function
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
pub fn RegExp::replace_all_fn(
self : RegExp,
string : String,
replacer : (String, Array[String], Int, String) -> String,
) -> String {
let wrapper = fn(
matched : String,
groups_val : @core.Any,
offset : Int,
input : String,
) -> String {
let gv : @core.Any = groups_val |> @core.any
let groups_len : Int = gv["length"].cast()
let groups : Array[String] = Array::new(capacity=groups_len)
for i = 0; i < groups_len; i = i + 1 {
let item = gv[i.to_string()]
if @core.is_undefined(item) {
groups.push("")
} else {
groups.push(item.cast())
}
}
replacer(matched, groups, offset, input)
}
ffi_string_replace_all_fn(string, self, @core.any(wrapper))
}
///|
/// Search for a match and return the index of the first occurrence.
///
/// JavaScript API: `String.prototype.search()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search
pub fn RegExp::search(self : RegExp, string : String) -> Int {
ffi_string_search(string, self)
}
///|
/// Split a string using the regular expression as the separator.
///
/// JavaScript API: `String.prototype.split()`
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
pub fn RegExp::split(
self : RegExp,
string : String,
limit? : Int,
) -> Array[String] {
let limit_val = match limit {
None => @core.null()
Some(n) => @core.identity(n)
}
ffi_string_split(string, self, limit_val |> @core.any)
}