String identity template tag

Mark Miller erights at
Thu Dec 13 19:00:30 UTC 2018

I think this is the right question. I agree that String.cook or whatever it
is called with typically be called explicitly rather than used
syntactically as a tag. However, putting the optional mapping function
aside for a moment, if the job it is doing is equivalent to that done by a
tag function, and if there are similar existing tags that can be called as
a function to do a similar job, I think it would be better for them to have
a similar signature and be used in an API compatible way.

In this case, if we choose a name like "cook" or "cooked" in order to make
the analogy with String.raw, then it should have the same API surface as
String.raw. Otherwise, there's too much to remember.

As for the optional mapping function, there's nothing about that which is
more relevant to cooked base strings than to raw base strings. We should be
able to apply mapping functions to either, as well as to other base tags,
in a similar way. This suggests tag combinators:

const mapTag = (baseTag, mapFn) => (template, ...aubs) => baseTag(template,;

mapTag(String.cooked, escapeHTML)`...`


As a completely separate point, this way of escaping html is not context
sensitive, and likely horribly unsafe. Much of the motivation for template
literals in the first place is to support context sensitive escaping, where
the escaping of the x data in


depends on where in the html parsing of the literal parts it is
encountered. See the work of Mike Samuel (cc'ed).

On Thu, Dec 13, 2018 at 10:44 AM T.J. Crowder <
tj.crowder at> wrote:

> On Thu, Dec 13, 2018 at 6:37 PM T.J. Crowder
> <tj.crowder at> wrote:
> >
> > But called normally, it's a useful helper, for instance in
> > Isiah's `escape`...
> Going through the process of the example for my message just now made me
> think more about this function. Suppose it:
> 1. Accepted an array of substitutions rather than a rest parameter, and
> 2. Accepted an optional mapping function
> Then, what I wrote on my last message as:
> ```js
> const escape = (strings, ...subs) => {
>     return String.cook(strings,;
> };
> ```
> would be
> ```js
> const escape = (strings, ...subs) => *String.cook(strings, subs,
> escapeHTML)*;
> ```
> (
> ...while still supporting the earlier usage (just without spread) if
> desired.
> -- T.J. Crowder

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list