Enrole a linha literal do modelo longo em várias linhas sem criar uma nova linha na string

141

Nos literais de modelo es6, como agrupar um literal de modelo longo em várias linhas sem criar uma nova linha na string?

Por exemplo, se você fizer isso:

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

Em seguida, ele criará um novo símbolo de linha para a sequência, como interpretando-a para ter uma nova linha. Como agrupar o modelo longo literal em várias linhas sem criar a nova linha?

Ville Miekk-oja
fonte
2
Como as continuações da linha são difíceis de ler e quebradiças contra espaços inesperados, prefiro a solução de Monte Jones do que a de codificação. FWIW, o guia de estilo do Google recomenda a solução Monte Jones e o guia AirBnB recomenda apenas o uso de uma linha muito longa, ou seja, nem recomenda continuações de linha. FWIW, não consegui encontrar este tópico em uma rápida verificação de outros guias de estilo.
Tom O'Neill

Respostas:

192

Se você introduzir uma continuação de linha ( \) no ponto da nova linha no literal, ela não criará uma nova linha na saída:

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
CodingIntrigue
fonte
1
Não tenho certeza se entendi o que você quer dizer. Você pode fornecer um exemplo REPL ?
CodingIntrigue
1
Não é facilmente no meu caso, uma vez que diferentes variáveis são tomadas a partir de arquivos de configuração Coffeescript etc .. mm .. parece que ele funciona de outra forma, mas por algum motivo ele adiciona espaço vazio lá
Ville Miekk-oja
1
Se você usar uma continuação de linha na primeira linha que não funciona para mim (nó v7)
Danielo515
2
Se você estiver usando isso em teste, às vezes, ele não retornará a mesma string. Eu resolvi minhas dores de cabeça usando Deline que é apenas uma1.1k Airbnb library
iarroyo
44
Essa solução não funciona bem com recuos (e recuos são comuns no desenvolvimento). O caractere após o \ na nova linha deve ser o primeiro caractere nessa linha. Ou seja, ele and continues...precisa começar da 0ª posição na nova linha, quebrando a regra do recuo.
precisa saber é o seguinte
53

Este é antigo. Mas surgiu. Se você deixar algum espaço no editor, ele será colocado lá.

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

basta fazer o símbolo + normal

if
  const text = `a very long string that just continues` +
  `and continues and continues`;
Monte Jones
fonte
Bom, mas parte da razão pela qual eu uso isso é evitar o símbolo '+'. Isso torna o código mais difícil de ler e mais irritante de se trabalhar.
dgo 6/12/19
21

Você pode simplesmente comer as quebras de linha dentro do literal do seu modelo.

// 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
fonte
3
Esse é um truque muito bom, mas falha se você tiver um formatador (como prettier) bonito configurado no seu IDE. prettieragrupa isso de volta à linha única.
Rvy Pandey 10/09/19
11

Edição : Eu fiz um pequeno módulo NPM com este utilitário. Ele funciona na web e no Node e eu recomendo o código na minha resposta abaixo, pois é muito mais robusto. Também permite preservar novas linhas no resultado se você as inserir manualmente como \ne fornece funções para quando você já usa tags literais de modelo para outra coisa: https://github.com/iansan5653/compress-tag


Sei que estou atrasado para responder aqui, mas a resposta aceita ainda tem a desvantagem de não permitir recuos após a quebra de linha, o que significa que você ainda não pode escrever um código muito bonito apenas escapando de novas linhas.

Em vez disso, por que não usar uma função literal de modelo marcado ?

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;
}

Em seguida, você pode simplesmente marcar qualquer literal de modelo no qual deseja quebras de linha:

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.`;

Isso tem a desvantagem de ter um comportamento inesperado se um desenvolvedor futuro não estiver acostumado à sintaxe do modelo marcado ou se você não usar um nome de função descritivo, mas parecer a solução mais limpa no momento.

Ian
fonte
8

Outra opção é usar Array.join, assim:

[
    '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
fonte
3

Use o antigo e o novo. Os literais de modelo são ótimos, mas se você quiser evitar longos literais para ter linhas compactas de código, concatená-los e o ESLint não causará problemas.

const text = `a very long string that just continues`
  +` and continues and continues`;
console.log(text);
Raymond Wachaga
fonte
1

Semelhante à resposta de Doug, isso é aceito pela minha configuração do TSLint e permanece intocado pelo meu formatador automático IntelliJ:

const text = `a very long string that just ${
  continues
} and ${continues} and ${continues}`
Daniel K
fonte
0

A solução proposta por @CodingIntrigue não está funcionando para mim no nó 7. Bem, funciona se eu não usar uma continuação de linha na primeira linha, caso contrário, falhará.

Esta provavelmente não é a melhor solução, mas funciona sem problemas:

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