How to use template literals (``) within template literals? - javascript

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.

I think you're overcomplicating it. If you only need to maintain the value of SOMELINK, this should work:
someFunction(`<p>Something something SomeLink</p>`)

You can do like:
someFunction(`<p>Something something <a href={${SOMELINK}/blah>SomeLink</a></p>`);

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>"

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:
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)
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.
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.

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

Related

[Nearley]: how to parse matching opening and closing tag

I'm trying to parse a very simple language with nearley: you can put a string between matching opening and closing tags, and you can chain some tags. It looks like a kind of XML, but with[ instead of < , with tag always 2 chars long, and without nesting.
[aa]My text[/aa][ab]Another Text[/ab]
But I don't seem to be able to parse correctly this, as I get the grammar should be unambiguous as soon as I have more than one tag.
The grammar that I have right now:
#builtin "string.ne"
#builtin "whitespace.ne"
openAndCloseTag[X] -> "[" $X "]" string "[/" $X "]"
languages -> openAndCloseTag[[a-zA-Z] [a-zA-Z]] (_ openAndCloseTag[[a-zA-Z] [a-zA-Z]]):*
string -> sstrchar:* {% (d) => d[0].join("") %}
And related, Ideally I would like the tags to be case insensitive (eg. [bc]TESt[/BC] would be valid)
Has anyone any idea how we can do that? I wasn't able to find a nearley XML parser example .
Your language is almost too simple to need a parser generator. And at the same time, it is not context free, which makes it difficult to use a parser generator. So it is quite possible that the Nearly parser is not the best tool for you, although it is probably possible to make it work with a bit of hackery.
First things first. You have not actually provided an unambiguous definition of your language, which is why your parser reports an ambiguity. To see the ambiguity, consider the input
[aa]My text[/ab][ab]Another Text[/aa]
That's very similar to your test input; all I did was swap a pair of letters. Now, here's the question: Is that a valid input consisting of a single aa tag? Or is it a syntax error? (That's a serious question. Some definitions of tagging systems like this consider a tag to only be closed by a matching close tag, so that things which look like different tags are considered to be plain text. Such systems would accept the input as a single tagged value.)
The problem is that you define string as sstrchar:*, and if we look at the definition of sstrchar in string.ne, we see (leaving out the postprocessing actions, which are irrelevant):
sstrchar -> [^\\'\n]
| "\\" strescape
| "\\'"
Now, the first possibility is "any character other than a backslash, a single quote or a newline", and it's easy to see that all of the characters in [/ab] are in sstrchar. (It's not clear to me why you chose sstrchar; single quotes don't appear to be special in your language. Or perhaps you just didn't mention their significance.) So a string could extend up to the end of the input. Of course, the syntax requires a closing tag, and the Nearley parser is determined to find a match if there is one. But, in fact, there are two of them. So the parser declares an ambiguity, since it doesn't have any criterion to choose between the two close tags.
And here's where we come up against the issue that your language is not context-free. (Actually, it is context-free in some technical sense, because there are "only" 676 two-letter case-insensitive tags, and it would theoretically be possible to list all 676 possibilities. But I'm guessing you don't want to do that.)
A context-free grammar cannot express a language that insists that two non-terminals expand to the same string. That's the very definition of context-free: if one non-terminal can only match the same input as a previous non-terminal, then
the second non-terminals match is dependent on the context, specifically on the match produced by the first non-terminal. In a context-free grammar, a non-terminal expands to the same thing, regardless of the rest of the text. The context in which the non-terminal appears is not allowed to influence the expansion.
Now, you quite possibly expected that your macro definition:
openAndCloseTag[X] -> "[" $X "]" string "[/" $X "]"
is expressing a context-sensitive match by repeating the $X macro parameter. But it is not by accident that the Nearley documentation describes this construct as a macro. X here refers exactly to the string used in the macro invocation. So when you say:
openAndCloseTag[[a-zA-Z] [a-zA-Z]]
Nearly macro expands that to
"[" [a-zA-Z] [a-zA-Z] "]" string "[/" [a-zA-Z] [a-zA-Z] "]"
and that's what it will use as the grammar production. Observe that the two $X macro parameters were expanded to the same argument, but that doesn't mean that will match the same input text. Each of those subpatterns will independently match any two alphabetic characters. Context-freely.
As I alluded to earlier, you could use this macro to write out the 676 possible tag patterns:
tag -> openAndCloseTag["aa"i]
| openAndCloseTag["ab"i]
| openAndCloseTag["ac"i]
| ...
| openAndCloseTag["zz"i]
If you did that (and you managed to correctly list all of the possibilities) then the parser would not complain about ambiguity as long as you never use the same tag twice in the same input. So it would be ok with both your original input and my altered input (as long as you accept the interpretation that my input is a single tagged object). But it would still report the following as ambiguous:
[aa]My text[/aa][aa]Another Text[/aa]
That's ambiguous because the grammar allows it to be either a single aa tagged string (whose text includes characters which look like close and open tags) or as two consecutive aa tagged strings.
To eliminate the ambiguity you would have to write the string pattern in a way which does not permit internal tags, in the same way that sstrchar doesn't allow internal single quotes. Except, of course, it is not nearly so simple to match a string which doesn't contain a pattern, than to match a string which doesn't contain a single character. It could be done using Nearley, but I really don't think that it's what you want.
Probably your best bet is to use native Javascript regular expressions to match tagged strings. This will prove simpler because Javascript regular expressions are much more powerful than mathematical regular expressions, even allowing the possibility of matching (certain) context-sensitive constructions. You could, for example, use Javascript regular expressions with the Moo lexer, which integrates well into Nearley. Or you could just use the regular expressions directly, since once you match the tagged text, there isn't much else you need to do.
To get you started, here's a simple Javascript regular expression which matches tagged strings with matching case-insensitive labels (the i flag at the end):
/\[([a-zA-Z]{2})\].*?\[\/\1\]/gmi
You can play with it online using Regex 101

Passing a multiline string as parameter to js function

When calling displayBarNotification(stringIPass, 'success', 3500) of nopcommerce originally defined in public.common.js seems the call fails when stringIPass contains newlines.
The error on the client-side was something like
Unexpected line break in a string literal
I tried replacing the C# newline character in the ajax function to the js equivalent and it worked. However, I intend to keep the "newlines" for readability reasons. What approach would you suggest?
Pardon me for the lack of the exact error expr. but it's because I'm currently not at work. I will update tomorrow if necessary.
Official documentation:
Template literals are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them.
Use back-ticks ( ` ) to introduce a template literal:
var example = `
this
is
a
test
`;
console.log(example);

How to Use ES6 Template Literals in Freemarker? [duplicate]

I'm trying to use Freemarker in conjunction with jQuery Templates.
Both frameworks use dollar sign/curly brackets to identify expressions for substitution (or as they're called in freemarker, "interpolations") , e.g. ${person.name} .
So when I define a jQuery Template with expressions in that syntax, Freemarker tries to interpret them (and fails).
I've tried various combinations of escaping the ${ sequence to pass it through Freemarker to no avail - \${, \$\{, $\{, etc.
Inserting a freemarker comment in between the dollar and the curly (e.g. $<#-- -->{expression}) DOES work - but I'm looking for a more concise and elegant solution.
Is there a simpler way to get a Freemarker template to output the character sequence ${?
This should print ${person.name}:
${r"${person.name}"}
From the freemarker docs
A special kind of string literals is the raw string literals. In raw string literals, backslash and ${ have no special meaning, they are considered as plain characters. To indicate that a string literal is a raw string literal, you have to put an r directly before the opening quotation mark or apostrophe-quote
For longer sections without FreeMarker markup, use <#noparse>...</#noparse>.
Starting with FreeMarker 2.3.28, configure FreeMarker to use square bracket syntax ([=exp]) instead of brace syntax (${exp}) by setting the interpolation_syntax configuration option to square_bracket.
Note that unlike the tag syntax, the interpolation syntax cannot be specified inside the template. Changing the interpolation syntax requires calling the Java API:
Configuration cfg;
// ...
cfg.setInterpolationSyntax(SQUARE_BRACKET_INTERPOLATION_SYNTAX);
Then FreeMarker will consider ${exp} to be static text.
Do not confuse interpolation syntax with tag syntax, which also can have square_bracket value, but is independent of the interpolation syntax.
When using FreeMarker-based file PreProcessor (FMPP), either configure the setting via config.fmpp or on the command-line, such as:
fmpp --verbose --interpolation-syntax squareBracket ...
This will call the appropriate Java API prior to processing the file.
See also:
https://freemarker.apache.org/docs/dgui_misc_alternativesyntax.html
http://fmpp.sourceforge.net/settings.html#templateSyntax
Another option is to use #include with parse=false option. That is, put your jQuery Templates into the separate include page and use parse=false so that freemarker doesn't try and parse it.
This would be a good option when the templates are larger and contain double quotes.
I had to spent some time to figure out the following scenarios to escape ${expression} -
In Freemarker assignment:
<#assign var = r"${expression}">
In html attribute:
Some link
In Freemarker concatenation:
<#assign x = "something&"+r"${expression}"/>
If ${ is your only problem, then you could use the alternate syntax in the jQuery Templates plugin like this: {{= person.name}}
Maybe a little cleaner than escaping it.
Did you try $$?
I found from the Freemarker manual that ${r"${person.name}"} will print out ${person.name} without attempting to render it.
Perhaps you should also take a look at Freemarker escaping freemarker
I can confirm that the
${r"${item.id}"}
is the correct way as an example.
So I kinda full example will look like
<span> Remove </span>
and the output will be :
<span> Remove </span>
In the case when you want to use non-raw strings so that you can escape double quotes, apostrophes, etc, you can do the following:
Imagine that you want to use the string ${Hello}-"My friend's friend" inside of a string. You cannot do that with raw strings. What I have used that works is:
${"\x0024{Hello}-\"My friend's friend\""}
I have not escaped the apostrophe since I used double quotes.

es6 multiline template strings with no new lines and allow indents

Been using es6 more and more for most work these days. One caveat is template strings.
I like to limit my line character count to 80. So if I need to concatenate a long string, it works fine because concatenation can be multiple lines like this:
const insert = 'dog';
const str = 'a really long ' + insert + ' can be a great asset for ' +
insert + ' when it is a ' + dog;
However, trying to do that with template literals would just give you a multi-line string with ${insert} placing dog in the resulting string. Not ideal when you want to use template literals for things like url assembly, etc.
I haven't yet found a good way to maintain my line character limit and still use long template literals. Anyone have some ideas?
The other question that is marked as an accepted is only a partial answer. Below is another problem with template literals that I forgot to include before.
The problem with using new line characters is that it doesn't allow for indentation without inserting spaces into the final string. i.e.
const insert = 'dog';
const str = `a really long ${insert} can be a great asset for\
${insert} when it is a ${insert}`;
The resulting string looks like this:
a really long dog can be a great asset for dog when it is a dog
Overall this is a minor issue but would be interesting if there was a fix to allow multiline indenting.
Two answers for this problem, but only one may be considered optimal.
Inside template literals, javascript can be used inside of expressions like ${}. Its therefore possible to have indented multiline template literals such as the following. The caveat is some valid js character or value must be present in the expression, such as an empty string or variable.
const templateLiteral = `abcdefgh${''
}ijklmnopqrst${''
}uvwxyz`;
// "abcdefghijklmnopqrstuvwxyz"
This method makes your code look like crap. Not recommended.
The second method was recommended by #SzybkiSasza and seems to be the best option available. For some reason concatenating template literals didn't occur to me as possible. I'm derp.
const templateLiteral = `abcdefgh` +
`ijklmnopqrst` +
`uvwxyz`;
// "abcdefghijklmnopqrstuvwxyz"
Why not use a tagged template literal function?
function noWhiteSpace(strings, ...placeholders) {
let withSpace = strings.reduce((result, string, i) => (result + placeholders[i - 1] + string));
let withoutSpace = withSpace.replace(/$\n^\s*/gm, ' ');
return withoutSpace;
}
Then you can just tag any template literal you want to have line breaks in:
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.`;
The provided function will strip all line breaks and line-leading tabs & spaces, yielding the following:
> 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.
I published this as the compress-tag library.

What is the correct mustache template config for _.templateSettings of underscore.template?

I've searched around and I couldn't find one that really works.
In Mustache, when you throw 2 curly, the string inside will be escaped, and if you throw 3, it will NOT.
// when you pass {foo: '"bar"'} as hash, the following template will be:
{{foo}} // => "bar"
{{{foo}}} // => "bar"
right? So I created the following.
http://jsfiddle.net/beatak/6s5PU/
and this shows interpolate and escape opposite, meaning 2 curly for unescaped 3 for escaped. When I flip between escape and interpolate in _.templateSettings, it just doesn't work. WHY? Underscore template has precedence of those three (escape, interpolate and evaluate)?
I know I'm ignoring evaluate on jsfiddle now, if that works together that'll be fantastic, but for now, I want to make 2 and 3 curly works just fineā€¦
The regex for escape is searched, then interpolate, then evaluate. That's why your escaped form {{ }} is matching before your unescaped form {{{ }}}. You can change the order yourself in the source for _.template.
var matcher = new RegExp([
(settings.escape || noMatch).source,
(settings.interpolate || noMatch).source,
(settings.evaluate || noMatch).source
].join('|') + '|$', 'g');
Changing the order of the lines above will change the priority.
If you don't want to change the underscore priority, you can use a more complex escaping regular expression. It's tricky to do without negative look-behind, but I came up with:
/\{\{([^\{\}]+?)(?!\}\}\})\}\}/
which should mean: {{, followed by one or more non-brace characters, that shall not be followed by triple brace (}}}), followed by double brace }}. It works on your fiddle and hopefully will work for you.

Categories

Resources