7

I have a very specific edge case which I need to use a template literal within a template literal but can't get it done.

The code looks something like this:

<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>

However I will have to wrap that in a function, while maintaining the value of the SOMELINK variable, this causes errors to happen. Whether I escape the ticks or not.

someFunction (`<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>`)

With escaped ticks I get the following error message:

Error: Expected SOMELINK but none provided

Without, I get:

Unexpected token, expected ","

How do I handle this?

Edit: It should probably be noted that the code being passed in someFunction will be rendered and it need to be used. It will eventually be passed in to another tag through dangerouslySetInnetHTML. So it will look something like this:

<div dangerouslySetInnerHTML={{__html: someFunction(`<p>Something something <a href={`${SOMELINK}/blah`}>SomeLink</a></p>`)}}/>

Not sure if this is relevant, but someFunction just does some modifications on the text.

theJuls
  • 6,788
  • 14
  • 73
  • 160
  • that's because template-literals is a feature of javascript no html5... you should just read: https://wesbos.com/template-strings-html/ and just in case https://css-tricks.com/html-templates-via-javascript-template-literals/ – manAbl May 25 '18 at 16:23
  • This looks like JSX syntax. You cannot put that in a template literal. – Bergi May 25 '18 at 16:26
  • @ManuelBlanco This question has `reactjs` tagged, so it's more likely to be JSX not HTML5. you should read: https://reactjs.org/docs/jsx-in-depth.html – Derek 朕會功夫 May 25 '18 at 16:34
  • oops! ... Didn't realize the tag HAHAH my bad @Derek朕會功夫 – manAbl May 25 '18 at 16:36

5 Answers5

4

I think you're overcomplicating it. If you only need to maintain the value of SOMELINK, this should work:

someFunction(`<p>Something something <a href="${SOMELINK}/blah">SomeLink</a></p>`)
imjared
  • 19,492
  • 4
  • 49
  • 72
  • That will be rendered though. And if I do that, it sends me to the wrong link. Instead of going to where `SOMELINK` sends me to, it will go to: `http://www.myoriginalpage.com/%7B%22http://www.somelinkpage.com/blah%22%7D`. Instead of `http://www.somelinkpage.com/blah` – theJuls May 25 '18 at 16:23
  • Seems like that's an issue with your function and that function isn't described in your question. – imjared May 25 '18 at 16:27
  • I didn't think it was relevant, but now thinking about it, it is. That literal passed in the function will be passed in to another tag and I use `dangerouslySetInnerHTML` to render the content. I'll update the OP to include this in more detail. – theJuls May 25 '18 at 16:30
  • Update: I don't know what I did differently from the first time around when I originally replied to your answer. But I tried it a second time and it worked perfectly. Probably my own incompetence. Thanks! – theJuls May 25 '18 at 17:02
2

You can do like:

someFunction(`<p>Something something <a href={${SOMELINK}/blah>SomeLink</a></p>`);
Hitesh Chaudhari
  • 705
  • 1
  • 7
  • 12
2

Introduction

As imjared says in his answer, you're certainly complicating what a JavaScript template is. But I'd like to make it clearer by explaining the grammar of a template.

There are up to four different parts in a template and you can write a template within a template as I'll show you below, but not quite the way you mentioned it.

Fancy Strings

First of all, a template a nothing more than a fancy way to write a string with expressions defined within. If you type:

typeof `this template`                                      (1)

in your browser console, it will write "string".

In the old days, when you wanted to concatenate many strings together, you would end up writing:

"string1" + "string2" + ... + "stringN"                     (2)

Some of the parameter could be numbers which would then be converted to string automatically (in most cases, it would work as expected). However, if you wanted to compute an expression, you most often had to write that expression between parenthesis:

"string1" + (a + b * c) + "string2"                         (3)

Modern JavaScript has Templates

Templates replace that with the ${...} special syntax. Within the ${...}, you can write your expression. This means (3) can be rewritten like follow using the template syntax:

`string1${a + b * c}string2`                                (4)

The syntax also has the advantage to look like you can insert a variable within a template like so:

`string1${varname}string2`                                  (5)

This is still an expression, it just happens to be limited to varname.

As a result, you have four possible different parts in a template:

  1. One String

    If your template is just one string (i.e. no ${...}) then it is just like a string.

    `this is just like a string`                            (6)
    
  2. Two Parts

    If you have one expression within a template, then you have a HEAD and a TAIL in your template. (4) and (5) above are templates with a HEAD and a TAIL.

  3. Three Parts

    If you write a template with more than one expression, that adds one or more special parts in between the expressions. These are called MIDDLE templates.

    `head${expr1}middle${expr2}middle${expr3}tail`          (7)
    

Templates Inside a Template

As I mentioned above, you can actually write a template inside a template. In most likelihood, you won't need such, but it is possible because what appears between the ${ and } is an expression and a template is viewed a primary literal (more or less, it's a tad bit more complicated than that...)

`string1${v
  + `sub-template${ sub_sub_template_is_possible }tail`
  + w}string2`                                             (8)

As mention within the sub-template example in (8), you could have another sub-sub-template within the sub-template. I think that in most cases, you are not likely to need such since the root template already gives you all the necessary functionality.

Escape Characters

Templates, just like strings, support escaping various characters using the backslash as the introducer:

  • \<octal>

  • \x<hexadecimal>

  • \u<hexadecimal>

  • Some special characters such as the character n which represents the newline (\n)

  • Finally, the other characters are escaped as is, this would include:

    \`                                                      (9)
    

    to escape the template quotes, in which case they are viewed as the quote character, not a template starting or ending point. In other words, string (10) is equal to string (11):

    `\``                                                   (10)
    "`"                                                    (11)
    

Very Much Simplified Grammar

Here are the parts mentioned above in simplified BNF-like syntax:

TemplateLiteral ::= Template
              | TemplateHead TemplateExpression* TemplateTail

TemplateExpression ::= Expression
              | TemplateExpression TemplateMiddle Expression

Template ::= '`' Character* '`'

TemplateHead ::= '`' Character* '${'

TemplateMiddle ::= '}' Character* '${'

TemplateTail ::= '}' Character* '`'

Character ::= ... -- characters valid in strings,
                     except '${' and '`'                 (12)

Reference

The JavaScript language is described in the ECMA-262 document found on this page:

https://www.ecma-international.org/publications-and-standards/standards/ecma-262/

Search for Template Literal Lexical Components. You will find the four parts (and much more) that I mentioned above: Template, TemplateHead, TemplateMiddle, and TemplateTail.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
1

Try this

someFunction("<p>Something something <a href={"+`${SOMELINK}/blah`+"}>SomeLink</a></p>")

I think you also need to make the route relative

"<p>Something something <a href={/"+`${SOMELINK}/blah`+"}>SomeLink</a></p>"
supra28
  • 1,646
  • 10
  • 17
0

I think that SOMELINK variable is not available in that case. You should provide SOMELINK first.

dieu
  • 50
  • 5