Zawijaj długi wiersz literału szablonu do multilinii bez tworzenia nowego wiersza w ciągu

142

W literałach szablonów es6, jak można zawinąć długi literał szablonu na multilinię bez tworzenia nowej linii w ciągu?

Na przykład, jeśli to zrobisz:

const text = `a very long string that just continues
and continues and continues`

Następnie utworzy nowy symbol linii w łańcuchu, interpretując go jako nową linię. Jak można zawinąć długi literał szablonu na wiele wierszy bez tworzenia nowej linii?

Ville Miekk-oja
źródło
2
FWIW kontynuacje linii są trudne do odczytania i kruche w przypadku nieoczekiwanych przestrzeni, więc wolę rozwiązanie Monte Jones od rozwiązania Codingintrigue. FWIW przewodnik stylistyczny Google zaleca rozwiązanie Monte Jones, a przewodnik AirBnB zaleca używanie zamiast tego bardzo długiej linii - to znaczy, że żadne z nich nie zaleca kontynuacji linii. FWIW, nie mogłem znaleźć tego tematu w szybkim sprawdzeniu innych poradników stylistycznych.
Tom O'Neill,

Odpowiedzi:

192

Jeśli wprowadzisz kontynuację linii ( \) w punkcie nowej linii w literale, nie utworzy ona nowej linii na wyjściu:

const text = `a very long string that just continues\
and continues and continues`;
console.log(text); // a very long string that just continuesand continues and continues
Kodowanie Zmęczenie
źródło
1
Nie jestem pewien, czy rozumiem, co masz na myśli. Czy możesz podać przykład REPL ?
CodingIntrigue
1
W moim przypadku nie jest to łatwe, ponieważ różne zmienne są pobierane z plików konfiguracyjnych coffeescript itp. Mm .. wygląda na to, że działa inaczej, ale z jakiegoś powodu dodaje tam puste miejsce
Ville Miekk-oja
1
Jeśli użyjesz kontynuacji linii w pierwszej linii, to nie działa dla mnie (węzeł v7)
Danielo515
2
Jeśli używasz tego w teście, czasami nie zwraca tego samego ciągu. Rozwiązałem swoje bóle głowy używając deline, które jest po prostu1.1k Airbnb library
iarroyo
45
To rozwiązanie nie działa dobrze z wcięciami (a wcięcia są powszechne w programowaniu). Znak po \ w nowej linii musi być pierwszym znakiem w tej linii. Oznacza to, że and continues...musi zaczynać się od zerowej pozycji w nowym wierszu, łamiąc zasadę wcięcia.
King Julian
54

To jest stary. Ale wyszło. Jeśli zostawisz jakieś spacje w edytorze, umieści je tam.

if
  const text = `a very long string that just continues\
  and continues and continues`;

po prostu zrób normalny symbol +

if
  const text = `a very long string that just continues` +
  `and continues and continues`;
Monte Jones
źródło
Dobrze, ale jednym z powodów, dla których to używam, jest unikanie symbolu „+”. To sprawia, że ​​kod jest trudniejszy do odczytania, a praca z nim jest bardziej irytująca.
dgo
21

Możesz po prostu zjeść podziały wierszy wewnątrz swojego szablonu.

// Thanks to https://twitter.com/awbjs for introducing me to the idea
// here: https://esdiscuss.org/topic/multiline-template-strings-that-don-t-break-indentation

const printLongLine = continues => {
    const text = `a very long string that just ${continues}${''
                 } and ${continues} and ${continues}`;
    return text;
}
console.log(printLongLine('continues'));

Doug Coburn
źródło
3
To bardzo dobry hack, ale zawodzi, jeśli masz ładny program formatujący (taki jak prettier) skonfigurowany w swoim IDE. prettierzawija to z powrotem do jednej linii.
Rvy Pandey
11

EDYCJA : stworzyłem mały moduł NPM za pomocą tego narzędzia. Działa w sieci i w Node i bardzo polecam go nad kodem w mojej poniższej odpowiedzi, ponieważ jest znacznie bardziej niezawodny. Pozwala również na zachowanie nowych linii w wyniku, jeśli ręcznie wprowadzisz je jako \n, i zapewnia funkcje, gdy używasz już tagów literału szablonu do czegoś innego: https://github.com/iansan5653/compress-tag


Wiem, że spóźniłem się na odpowiedź, ale zaakceptowana odpowiedź nadal ma tę wadę, że nie zezwala na wcięcia po podziale wiersza, co oznacza, że ​​nadal nie można napisać bardzo ładnie wyglądającego kodu, po prostu unikając nowych linii.

Zamiast tego, dlaczego nie użyć funkcji literału z tagiem szablonu ?

function noWhiteSpace(strings, ...placeholders) {
  // Build the string as normal, combining all the strings and placeholders:
  let withSpace = strings.reduce((result, string, i) => (result + placeholders[i - 1] + string));
  let withoutSpace = withSpace.replace(/\s\s+/g, ' ');
  return withoutSpace;
}

Następnie możesz po prostu otagować dowolny literał szablonu, w którym chcesz wprowadzić podziały wierszy:

let myString = noWhiteSpace`This is a really long string, that needs to wrap over
    several lines. With a normal template literal you can't do that, but you can 
    use a template literal tag to allow line breaks and indents.`;

Ma to tę wadę, że może mieć nieoczekiwane zachowanie, jeśli przyszły programista nie jest przyzwyczajony do składni otagowanego szablonu lub jeśli nie używasz opisowej nazwy funkcji, ale wydaje się, że na razie jest to najczystsze rozwiązanie.

Ian
źródło
8

Inną opcją jest użycie Array.join, na przykład:

[
    'This is a very long string. ',
    'It just keeps going ',
    'and going ',
    'and going ',
    'and going ',
    'and going ',
    'and going ',
    'and going',
].join('')
Liran H.
źródło
3

Użyj starego i nowego. Literały szablonów są świetne, ale jeśli chcesz uniknąć długich literałów i mieć zwarte wiersze kodu, połącz je, a ESLint nie spowoduje zamieszania.

const text = `a very long string that just continues`
  +` and continues and continues`;
console.log(text);
Raymond Wachaga
źródło
1

Podobnie jak odpowiedź Douga, jest to akceptowane przez moją konfigurację TSLint i pozostaje nietknięte przez mój autoformatator IntelliJ:

const text = `a very long string that just ${
  continues
} and ${continues} and ${continues}`
Daniel K.
źródło
0

Rozwiązanie zaproponowane przez @CodingIntrigue nie działa u mnie w węźle 7. Cóż, działa, jeśli nie używam kontynuacji linii w pierwszej linii, w przeciwnym razie zawodzi.

To chyba nie jest najlepsze rozwiązanie, ale działa bez problemów:

(`
    border:1px solid blue;
    border-radius:10px;
    padding: 14px 25px;
    text-decoration:none;
    display: inline-block;
    text-align: center;`).replace(/\n/g,'').trim();
Danielo515
źródło