Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Syntax proposals (meta issue) #40

Closed
jridgewell opened this issue Jan 30, 2022 · 10 comments · Fixed by #47
Closed

Syntax proposals (meta issue) #40

jridgewell opened this issue Jan 30, 2022 · 10 comments · Fixed by #47
Labels

Comments

@jridgewell
Copy link
Member

jridgewell commented Jan 30, 2022

In the order in which I find them while going through everything. There seems to be strong support in the community for a syntax feature (based on how many suggestions we're getting), instead of a String.dedent tag function.

  • Triple tick syntax backwards compatibility #8
    We know this isn't 100% backwards compatible for tagged template expressions, but usage of an empty initial template which (the first foo`` in foo``````) returns a function could be low enough that we can continue with this option.
    const text = ```
      content...
      ${expression}
    ```;
    const text = foo```
      content...
      ${expression}
    ```;
  • Has """this""" and ''''this''' been considered? #24
    (Coffeescript also uses this)
    const text = """
      content...
      ${expression}
    """;
    const text = foo"""
      content...
      ${expression}
    """;
  • Switch to @ prefix syntax #35
    const text = @`
      content...
      ${expression}
    `;
    const text = foo@`
      content...
      ${expression}
    `;
  • ""` syntax suggestion #37
    const text = """
      content...
      no expression
    """;
    const text = ""`
      content...
      ${expression}
    `"";
    // I assume a tagged template form would be allowed

See also #21 (comment). A syntax feature can be minified, whereas a runtime tag function could only be minified if we unsafely assume runtime behavior.

@bakkot
Copy link
Contributor

bakkot commented Jan 30, 2022

Even though ``` can currently be used without error, as here, I think it might still be compatible enough to ship if it's just one or two websites using it. I wonder if it would be possible to ship a use-counter for ``` in a browser for a while to determine if it's actually something which comes up in practice.

@jridgewell
Copy link
Member Author

I've added ``` syntax to the list.

@Alhadis
Copy link

Alhadis commented Feb 4, 2022

(CoffeeScript also uses this)

So does Python, which doesn't use either syntax:

#!/usr/bin/env python3
str = """
	Hash: #{1 + 2}
	Cash: ${1 + 2}
"""
str = '''
	Hash: #{1 + 2}
	Cash: ${1 + 2}
'''

Supporting ${…} (or any other interpolation syntax) in double-quoted strings would break consistency with how double-quoted strings are currently handled. Moreover, it would complicate tools that perform minification, since "${foo}" !== """${foo}""".

but usage of an empty initial template which (the first foo`` in foo``````) returns a function

This discrepancy feels… wrong. First, it has the potential to mess with code that performs deindentation of its own (or worse still, requires it). Second, an initial template literal might be blank because its tag function interprets a blank string differently to a non-blank one. Consider something like:

import {writeFileSync} from "fs";

// Write to the specified file, or stdout if path is empty
function print([to]){
	return ([content]) => "" === to
		? process.stdout.write(content)
		: fs.writeFileSync(to, content, "utf8");
}

print `output.txt``
	Contents of file, which are expected
		to be written to the destination
		verbatim.
`;

print ```
	Message written to standard output, indented by one tab.
```;

A safer alternative would be to implement a String.dedent method that returns a function if used to tag an empty template literal. This avoids making assumptions about author intent, and provides users with a more helpful alternative to String.raw when interpolated expressions are expected to be indented too:

String.rawString.dedent
const str = "Multi-\nline\ntext.";
String.raw `<body>
	${str}
</body>`;
const str = "Multi-\nline\ntext.";
String.dedent `<body>
	${str}
</body>`;
Return values
<body>
	Multi-
line
text.
</body>
<body>
Multi-
line
text.
</body>

@jridgewell
Copy link
Member Author

So does Python, which doesn't use either syntax... Supporting ${…} (or any other interpolation syntax) in double-quoted strings would break consistency with how double-quoted strings are currently handled.

Python does, you just have to preface the literal with a f:

f"""
  {1 + 2}
"""
# '\n3\n'

@Alhadis
Copy link

Alhadis commented Feb 5, 2022

Python does, you just have to preface the literal with a f:

I confess I didn't know that (because I'm not a Python programmer), but for the sake of this discussion, I'd argue that f""" and """ are two different syntaxes (we're not proposing that f"""/f''' be added to JavaScript, after all).

@bathos
Copy link

bathos commented Feb 5, 2022

Regarding triple-tick, I'm not sure if "(currently possible) syntax not in use" is quite the same as "property not in use". There's something unsettling about the idea that a tagged template written with the "new" syntax would not be a syntax error in agents which haven't yet implemented it but would instead be a different also-valid expression with different semantics. Would this create bugs? Issues for tooling/ecosystem that currently parse and compile triple ticks differently? Is it exploitable as a way to mask conditional behavior that, being syntactic, cannot be denied in prepared envs?

(Not rhetorical questions - I really don't know the answers and they may all be "no". I just get a weird tingle about the premise which suggests these things may need consideration because valid (a) -> valid (b) is a seemingly pretty different scenario from invalid -> valid. Is there a similar example of valid (a) -> valid (b) happening before?

Edit: Trying to think through this more and I suspect the answers would depend in part on whether or not a single tick within the “block” still requires escaping. As long as it does, then there’s probably no nasty tricks possible. But if it doesn’t, then whether the following alert is JS code being evaluated or an inert string would depend on ES “version”:

x = () => x;
x
```
`
alert("am i an inert string ... or am I eval? depends on your browser, if single backticks don’t need escaping!");
x
`
```

@mon-jai
Copy link

mon-jai commented Jul 14, 2022

I doubt that anyone except library maintainers will use String.dedent as a function. It requires too many keystrokes for a simple thing.

Maybe we could add the API, as well as some kind of syntax sugar in the same time?

@jridgewell
Copy link
Member Author

Based on conversations with other delegates, it's unlikely we'll be able to get a syntax form. I'm planning on doing const dd = String.dedent; and using it like dd`foo`.

@hax
Copy link
Member

hax commented Jul 19, 2022

One problem of current template literal is, you can't have unescaped ` in the literal (it always end the literal). This is very inconvenient for text contains backticks, eg. markdown.

This issue is not directly relate to dedent, but consider the main use cases of dedent is long text, I really hope we can revisit the syntax options which could allow unescaped backticks.

Syntax also make String.dedent(tag) unnecessary. I feel String.dedent(tag) is a little bit hard to understand for average programmers, and String.dedent(obj.foo) may not work. (need String.dedent(obj.foo.bind(obj)).)

@sken130
Copy link

sken130 commented Jul 24, 2023

If we are to introduce new syntax, we should make it worthwhile by including more features and solving as many problems as possible, otherwise the features proposed too late will become breaking changes in the future.

Here is my proposal of adding raw string literal to ECMAScript/JavaScript to solve multiple problems together:

  • indentation/dedentation
  • string interpolation
  • multi-line string
  • containing arbitrary text without escaping

https://es.discourse.group/t/raw-string-literals-that-can-contain-any-arbitrary-text-without-the-need-for-special-escape-sequences/1757/3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants