mirror of
https://github.com/swc-project/swc.git
synced 2024-12-26 07:02:28 +03:00
feat(css/parser): Normalize urange (#6704)
This commit is contained in:
parent
35b72b59c8
commit
8af627d5c4
@ -454,14 +454,21 @@ pub enum UrlModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node("UnicodeRange")]
|
#[ast_node("UnicodeRange")]
|
||||||
#[derive(Eq, Hash, EqIgnoreSpan)]
|
#[derive(Eq, Hash)]
|
||||||
pub struct UnicodeRange {
|
pub struct UnicodeRange {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub prefix: char,
|
|
||||||
#[cfg_attr(feature = "rkyv", with(swc_atoms::EncodeJsWord))]
|
#[cfg_attr(feature = "rkyv", with(swc_atoms::EncodeJsWord))]
|
||||||
pub start: JsWord,
|
pub start: JsWord,
|
||||||
#[cfg_attr(feature = "rkyv", with(swc_atoms::EncodeJsWord))]
|
#[cfg_attr(feature = "rkyv", with(swc_atoms::EncodeJsWord))]
|
||||||
pub end: Option<JsWord>,
|
pub end: Option<JsWord>,
|
||||||
|
pub raw: Option<Atom>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EqIgnoreSpan for UnicodeRange {
|
||||||
|
#[inline]
|
||||||
|
fn eq_ignore_span(&self, other: &Self) -> bool {
|
||||||
|
self.start == other.start && self.end == other.end
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[ast_node("CalcSum")]
|
#[ast_node("CalcSum")]
|
||||||
|
@ -1998,8 +1998,7 @@ where
|
|||||||
+ 2,
|
+ 2,
|
||||||
);
|
);
|
||||||
|
|
||||||
value.push(n.prefix);
|
value.push_str("u+");
|
||||||
value.push('+');
|
|
||||||
value.push_str(&n.start);
|
value.push_str(&n.start);
|
||||||
|
|
||||||
if let Some(end) = &n.end {
|
if let Some(end) = &n.end {
|
||||||
|
@ -287,6 +287,44 @@ impl VisitMut for NormalizeTest {
|
|||||||
n.raw = None;
|
n.raw = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_mut_unicode_range(&mut self, n: &mut UnicodeRange) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
n.raw = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_declaration(&mut self, n: &mut Declaration) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
if let DeclarationName::Ident(name) = &mut n.name {
|
||||||
|
name.value = name.value.to_lowercase().into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_pseudo_class_selector(&mut self, n: &mut PseudoClassSelector) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
n.name.value = n.name.value.to_lowercase().into();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_pseudo_element_selector(&mut self, n: &mut PseudoElementSelector) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
n.name.value = n.name.value.to_lowercase().into();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_tag_name_selector(&mut self, n: &mut TagNameSelector) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
n.name.value.value = n.name.value.value.to_lowercase().into();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_mut_attribute_selector_modifier(&mut self, n: &mut AttributeSelectorModifier) {
|
||||||
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
n.value.value = n.value.value.to_lowercase().into();
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_mut_an_plus_b_notation(&mut self, n: &mut AnPlusBNotation) {
|
fn visit_mut_an_plus_b_notation(&mut self, n: &mut AnPlusBNotation) {
|
||||||
n.visit_mut_children_with(self);
|
n.visit_mut_children_with(self);
|
||||||
|
|
||||||
|
@ -46,9 +46,9 @@ impl Compressor {
|
|||||||
|
|
||||||
for (idx, start_c) in start.chars().enumerate() {
|
for (idx, start_c) in start.chars().enumerate() {
|
||||||
if let Some(end_c) = &end.chars().nth(idx) {
|
if let Some(end_c) = &end.chars().nth(idx) {
|
||||||
if start_c.eq_ignore_ascii_case(end_c) && question_counter == 0 {
|
if start_c == *end_c && question_counter == 0 {
|
||||||
minified.push(start_c);
|
minified.push(start_c);
|
||||||
} else if start_c == '0' && end_c.eq_ignore_ascii_case(&'f') {
|
} else if start_c == '0' && *end_c == 'f' {
|
||||||
question_counter += 1;
|
question_counter += 1;
|
||||||
|
|
||||||
minified.push('?')
|
minified.push('?')
|
||||||
|
@ -109,3 +109,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
unicode-range: U+000450-0004FF;
|
unicode-range: U+000450-0004FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
unicode-range: U+26;
|
||||||
|
unicode-range: u+26;
|
||||||
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
@font-face{unicode-range:U+26}@font-face{unicode-range:U+-7F}@font-face{unicode-range:U+25-FF}@font-face{unicode-range:U+25-FF,U+4??}@font-face{unicode-range:U+10????}@font-face{unicode-range:U+2b??}@font-face{unicode-range:u+2b??}@font-face{unicode-range:U+1e??}@font-face{unicode-range:U+2125-2128}@font-face{unicode-range:U+4??}@font-face{unicode-range:U+25-FF,U+4??}@font-face{unicode-range:U+450-4FF}@font-face{unicode-range:U+A5,U+4E00-9FFF,U+30??,U+FF00-FF9F}@font-face{unicode-range:U+????}@font-face{unicode-range:U+????}@font-face{unicode-range:U+10????}@font-face{unicode-range:U+10????}@font-face{unicode-range:U+1e1e?}@font-face{unicode-range:u+????,U+1????,U+10????}@font-face{unicode-range:U+25}@font-face{unicode-range:U+1e1e?}@font-face{unicode-range:U+25}@font-face{unicode-range:U+125}@font-face{unicode-range:U+100-FFFF}@font-face{unicode-range:U+10125}@font-face{unicode-range:U+450-4FF}@font-face{unicode-range:U+450-4FF}@font-face{unicode-range:U+450-4FF}
|
@font-face{unicode-range:u+26}@font-face{unicode-range:u+-7f}@font-face{unicode-range:u+25-ff}@font-face{unicode-range:u+25-ff,u+4??}@font-face{unicode-range:u+10????}@font-face{unicode-range:u+2b??}@font-face{unicode-range:u+2b??}@font-face{unicode-range:u+1e??}@font-face{unicode-range:u+2125-2128}@font-face{unicode-range:u+4??}@font-face{unicode-range:u+25-ff,u+4??}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+a5,u+4e00-9fff,u+30??,u+ff00-ff9f}@font-face{unicode-range:u+????}@font-face{unicode-range:u+????}@font-face{unicode-range:u+10????}@font-face{unicode-range:u+10????}@font-face{unicode-range:u+1e1e?}@font-face{unicode-range:u+????,u+1????,u+10????}@font-face{unicode-range:u+25}@font-face{unicode-range:u+1e1e?}@font-face{unicode-range:u+25}@font-face{unicode-range:u+125}@font-face{unicode-range:u+100-ffff}@font-face{unicode-range:u+10125}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+450-4ff}@font-face{unicode-range:u+26}
|
||||||
|
@ -2726,14 +2726,14 @@ where
|
|||||||
// should start with `u` or `U`
|
// should start with `u` or `U`
|
||||||
match cur!(self) {
|
match cur!(self) {
|
||||||
Token::Ident { value, .. } if matches_eq_ignore_ascii_case!(value, js_word!("u")) => {
|
Token::Ident { value, .. } if matches_eq_ignore_ascii_case!(value, js_word!("u")) => {
|
||||||
let ident = match bump!(self) {
|
let u = match bump!(self) {
|
||||||
Token::Ident { value, .. } => value,
|
Token::Ident { value, .. } => value,
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
unicode_range.push_str(&ident);
|
unicode_range.push_str(&u);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::new(span, ErrorKind::Expected("'u' ident token")));
|
return Err(Error::new(span, ErrorKind::Expected("'u' ident token")));
|
||||||
@ -2915,12 +2915,12 @@ where
|
|||||||
|
|
||||||
// 1. Skipping the first u token, concatenate the representations of all the
|
// 1. Skipping the first u token, concatenate the representations of all the
|
||||||
// tokens in the production together. Let this be text.
|
// tokens in the production together. Let this be text.
|
||||||
let prefix = chars.next().unwrap();
|
chars.next();
|
||||||
|
|
||||||
let mut next = chars.next();
|
|
||||||
|
|
||||||
// 2. If the first character of text is U+002B PLUS SIGN, consume it. Otherwise,
|
// 2. If the first character of text is U+002B PLUS SIGN, consume it. Otherwise,
|
||||||
// this is an invalid <urange>, and this algorithm must exit.
|
// this is an invalid <urange>, and this algorithm must exit.
|
||||||
|
let mut next = chars.next();
|
||||||
|
|
||||||
if next != Some('+') {
|
if next != Some('+') {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
span,
|
span,
|
||||||
@ -2944,7 +2944,7 @@ where
|
|||||||
next = chars.next();
|
next = chars.next();
|
||||||
}
|
}
|
||||||
Some(c @ 'A'..='F') | Some(c @ 'a'..='f') => {
|
Some(c @ 'A'..='F') | Some(c @ 'a'..='f') => {
|
||||||
start.push(c);
|
start.push(c.to_ascii_lowercase());
|
||||||
|
|
||||||
next = chars.next();
|
next = chars.next();
|
||||||
}
|
}
|
||||||
@ -2999,9 +2999,9 @@ where
|
|||||||
// 4. Exit this algorithm.
|
// 4. Exit this algorithm.
|
||||||
return Ok(UnicodeRange {
|
return Ok(UnicodeRange {
|
||||||
span: span!(self, span.lo),
|
span: span!(self, span.lo),
|
||||||
prefix,
|
|
||||||
start: start.into(),
|
start: start.into(),
|
||||||
end: None,
|
end: None,
|
||||||
|
raw: Some(unicode_range.into()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3013,9 +3013,9 @@ where
|
|||||||
if next.is_none() {
|
if next.is_none() {
|
||||||
return Ok(UnicodeRange {
|
return Ok(UnicodeRange {
|
||||||
span: span!(self, span.lo),
|
span: span!(self, span.lo),
|
||||||
prefix,
|
|
||||||
start: start.into(),
|
start: start.into(),
|
||||||
end: None,
|
end: None,
|
||||||
|
raw: Some(unicode_range.into()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3044,7 +3044,7 @@ where
|
|||||||
next = chars.next();
|
next = chars.next();
|
||||||
}
|
}
|
||||||
Some(c @ 'A'..='F') | Some(c @ 'a'..='f') => {
|
Some(c @ 'A'..='F') | Some(c @ 'a'..='f') => {
|
||||||
end.push(c);
|
end.push(c.to_ascii_lowercase());
|
||||||
next = chars.next();
|
next = chars.next();
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -3073,9 +3073,9 @@ where
|
|||||||
|
|
||||||
return Ok(UnicodeRange {
|
return Ok(UnicodeRange {
|
||||||
span: span!(self, span.lo),
|
span: span!(self, span.lo),
|
||||||
prefix,
|
|
||||||
start: start.into(),
|
start: start.into(),
|
||||||
end: Some(end.into()),
|
end: Some(end.into()),
|
||||||
|
raw: Some(unicode_range.into()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,9 +148,9 @@
|
|||||||
"end": 102,
|
"end": 102,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "26",
|
"start": "26",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+26"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -180,9 +180,9 @@
|
|||||||
"end": 164,
|
"end": 164,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "u",
|
|
||||||
"start": "26",
|
"start": "26",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "u+26"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -212,9 +212,9 @@
|
|||||||
"end": 191,
|
"end": 191,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "0",
|
"start": "0",
|
||||||
"end": "7F"
|
"end": "7f",
|
||||||
|
"raw": "U+0-7F"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -244,9 +244,9 @@
|
|||||||
"end": 223,
|
"end": 223,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "0025",
|
"start": "0025",
|
||||||
"end": "00FF"
|
"end": "00ff",
|
||||||
|
"raw": "U+0025-00FF"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -276,9 +276,9 @@
|
|||||||
"end": 278,
|
"end": 278,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "4??",
|
"start": "4??",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+4??"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -308,9 +308,9 @@
|
|||||||
"end": 344,
|
"end": 344,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "0025",
|
"start": "0025",
|
||||||
"end": "00FF"
|
"end": "00ff",
|
||||||
|
"raw": "U+0025-00FF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Delimiter",
|
"type": "Delimiter",
|
||||||
@ -328,9 +328,9 @@
|
|||||||
"end": 351,
|
"end": 351,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "4??",
|
"start": "4??",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+4??"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -360,9 +360,9 @@
|
|||||||
"end": 398,
|
"end": 398,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
"start": "a5",
|
||||||
"start": "A5",
|
"end": null,
|
||||||
"end": null
|
"raw": "U+A5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Delimiter",
|
"type": "Delimiter",
|
||||||
@ -380,9 +380,9 @@
|
|||||||
"end": 411,
|
"end": 411,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
"start": "4e00",
|
||||||
"start": "4E00",
|
"end": "9fff",
|
||||||
"end": "9FFF"
|
"raw": "U+4E00-9FFF"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Delimiter",
|
"type": "Delimiter",
|
||||||
@ -400,9 +400,9 @@
|
|||||||
"end": 419,
|
"end": 419,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "30??",
|
"start": "30??",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+30??"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Delimiter",
|
"type": "Delimiter",
|
||||||
@ -420,9 +420,9 @@
|
|||||||
"end": 432,
|
"end": 432,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
"start": "ff00",
|
||||||
"start": "FF00",
|
"end": "ff9f",
|
||||||
"end": "FF9F"
|
"raw": "U+FF00-FF9F"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -452,9 +452,9 @@
|
|||||||
"end": 481,
|
"end": 481,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "????",
|
"start": "????",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+????"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -484,9 +484,9 @@
|
|||||||
"end": 510,
|
"end": 510,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "??????",
|
"start": "??????",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+??????"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -516,9 +516,9 @@
|
|||||||
"end": 535,
|
"end": 535,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "12",
|
"start": "12",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+12"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -548,9 +548,9 @@
|
|||||||
"end": 564,
|
"end": 564,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "12e112",
|
"start": "12e112",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+12e112"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -580,9 +580,9 @@
|
|||||||
"end": 593,
|
"end": 593,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "1e1ee1",
|
"start": "1e1ee1",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+1e1ee1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -612,9 +612,9 @@
|
|||||||
"end": 629,
|
"end": 629,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "1e1ee1",
|
"start": "1e1ee1",
|
||||||
"end": "FFFFFF"
|
"end": "ffffff",
|
||||||
|
"raw": "U+1e1ee1-FFFFFF"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -644,9 +644,9 @@
|
|||||||
"end": 658,
|
"end": 658,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "1e1ee?",
|
"start": "1e1ee?",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "U+1e1ee?"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
@ -676,9 +676,9 @@
|
|||||||
"end": 686,
|
"end": 686,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "U",
|
|
||||||
"start": "12",
|
"start": "12",
|
||||||
"end": "13"
|
"end": "13",
|
||||||
|
"raw": "U+12-13"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"important": null
|
"important": null
|
||||||
|
@ -1875,9 +1875,9 @@
|
|||||||
"end": 651,
|
"end": 651,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "u",
|
|
||||||
"start": "123",
|
"start": "123",
|
||||||
"end": "456"
|
"end": "456",
|
||||||
|
"raw": "u+123-456"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "UnicodeRange",
|
"type": "UnicodeRange",
|
||||||
@ -1886,9 +1886,9 @@
|
|||||||
"end": 660,
|
"end": 660,
|
||||||
"ctxt": 0
|
"ctxt": 0
|
||||||
},
|
},
|
||||||
"prefix": "u",
|
|
||||||
"start": "123???",
|
"start": "123???",
|
||||||
"end": null
|
"end": null,
|
||||||
|
"raw": "u+123???"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Function",
|
"type": "Function",
|
||||||
|
@ -308,9 +308,9 @@ define!({
|
|||||||
|
|
||||||
pub struct UnicodeRange {
|
pub struct UnicodeRange {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub prefix: char,
|
|
||||||
pub start: JsWord,
|
pub start: JsWord,
|
||||||
pub end: Option<JsWord>,
|
pub end: Option<JsWord>,
|
||||||
|
pub raw: Option<Atom>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CalcSum {
|
pub struct CalcSum {
|
||||||
|
Loading…
Reference in New Issue
Block a user