feat(prettier) Use minimum amount of escapes in strings (#1376)

```ts
[
    "foo",
    'bar',
    "bar'",
    'bar\'',
    'bar"',
    "bar\"",
    "bar\"\"\"''",
    "bar\"\"\"'''",
]

```

Becomes:
```ts
["foo", "bar", "bar'", "bar'", 'bar"', 'bar"', 'bar"""\'\'', "bar\"\"\"'''"];
```
This commit is contained in:
Cameron 2023-11-17 12:44:17 +00:00 committed by GitHub
parent 7b85843981
commit 5f5926e0ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 2 deletions

View file

@ -21,6 +21,7 @@ mod function_parameters;
mod module;
mod object;
mod statement;
mod string;
mod ternary;
use crate::{
@ -720,8 +721,7 @@ impl<'a> Format<'a> for RegExpLiteral {
impl<'a> Format<'a> for StringLiteral {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let quote = if p.options.single_quote { "'" } else { "\"" };
array!(p, ss!(quote), p.str(&self.value), ss!(quote))
array!(p, p.str(&string::print_string(self.value.as_str(), p.options.single_quote)))
}
}

View file

@ -0,0 +1,57 @@
fn get_preferred_quote(raw: &str, prefer_single_quote: bool) -> char {
let (preferred_quote_char, alternate_quote_char) =
if prefer_single_quote { ('\'', '"') } else { ('"', '\'') };
let mut preferred_quote_count = 0;
let mut alternate_quote_count = 0;
for character in raw.chars() {
if character == preferred_quote_char {
preferred_quote_count += 1;
} else if character == alternate_quote_char {
alternate_quote_count += 1;
}
}
if preferred_quote_count > alternate_quote_count {
alternate_quote_char
} else {
preferred_quote_char
}
}
fn make_string(raw_text: &str, enclosing_quote: char) -> String {
let other_quote = if enclosing_quote == '"' { '\'' } else { '"' };
let mut result = String::new();
result.push(enclosing_quote);
let mut chars = raw_text.chars().peekable();
while let Some(c) = chars.next() {
match c {
'\\' => {
if let Some(&next_char) = chars.peek() {
if next_char != other_quote {
result.push('\\');
}
result.push(next_char);
chars.next();
} else {
result.push('\\');
}
}
_ if c == enclosing_quote => {
result.push('\\');
result.push(c);
}
_ => result.push(c),
}
}
result.push(enclosing_quote);
result
}
pub(super) fn print_string(raw_text: &str, prefer_single_quote: bool) -> String {
let enclosing_quote = get_preferred_quote(raw_text, prefer_single_quote);
make_string(raw_text, enclosing_quote)
}