zspecza / common-tags

🔖 Useful template literal tags for dealing with strings in ES2015+
Other
2k stars 61 forks source link

`source` doesn't seem to work when put into a new template literal? #56

Closed zaynv closed 6 years ago

zaynv commented 8 years ago

Here is my current code:

function generateFruits () {
  const fruits = [
    {
      name: 'apples',
      quantity: 3
    },
    {
      name: 'oranges',
      quantity: 2
    }
  ]

  return source`
    Fruits
      ${fruits.map(f => `${f.name}: ${f.quantity}`)}
  `
}

If I do console.log(generateFruits()), I get the expected output:

Fruits
  apples: 3
  oranges: 2

However, if I create a variable called template and use generateFruits() inside of there, it doesn't seem to work:

const template = stripIndent`
  ${generateFruits()}
`

I thought that this would give the same output, but instead it seems to give this:

Fruits
apples: 3
oranges: 2

And if I remove the stripIndent, it gives this:

  Fruits
  apples: 3
  oranges: 2

Why does using generateFruits() inside a different template literal make it lose the indentation?

zspecza commented 7 years ago

Hi @zaynv - so sorry I couldn't respond sooner!

I have a hunch this is to do with the way template tags work - some can be nested, some cannot - depending on the logic performed in the tag. This case is an example of the latter: stripIndent trims surrounding whitespace, then processes substitutions - so it's likely that this is correct output. I however am not 100% certain that what you're trying to accomplish here is impossible, so I will investigate it when I have some time.

fatfisz commented 6 years ago

This might be related: #109.

fatfisz commented 6 years ago

It turns out this was related. The reason for the code not working as expected is that sourceIndent does not indent multiline strings from substitutions, unlike source. What would work instead is using the source tag again:

const template = source`
  ${generateFruits()}
`

This might be misleading, so I added a note to the docs.