-
Notifications
You must be signed in to change notification settings - Fork 16
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
Indent expressions #25
Comments
Going through this, I think it would only work for a non-tagged form. In tagged form, the dedented strings array is given to the tag without processing the arguments to the tag invocation (because it's up to the tag to do things with args). In this specific case, couldn't the user just do a |
Yes, although as you already mention tagged templates process the arguments anyway.
Yes, although I don't agree that it would be a sticky question as to how the engine would handle it. I still feel like indenting embedded expressions is a more useful default for the majority of use cases for |
Sorry, I wasn't super clear in my comment. What I'm bringing up is the wrapped tagged template form (or a tagged dedent template if we have a syntax): String.dedent(foo)`
${indent()}
`
// or
foo```
${indent()}
``` In this case, we don't interpolate the expression, we only dedent the template strings array. We then pass the dedented array and expressions to |
Well like you say, this is ultimately up to function html(strings, ...expressions) {
return String.raw(strings.raw, ...expressions.map(expr => {
if (typeof expr === "string") {
return escapeHTMLSomehow(expr);
} else if (expr instanceof String.isIndent(expr)) { //
return String.indent(escapeHTMLSomehow(expr.value));
} else if (expr instanceof Element) {
return stringifyHTMLElementSomehow(expr);
}
throw new RangeError("invalid type of expression");
});
}
String.dedent(html)`
<html>
<p>
${ String.indent(getTextSomehow()) }
</p>
</html>
` This has a slight cost for those writing template tags, however for users of the tags they do not have to care how this internal processing occurs. Although I think that yes in order to support custom tags, direct support in the existing |
It would be impossible, because then you’d have a function that had magic abilities attached to it that normally would require syntax. There’s all sorts of reasons that wouldn’t fly. |
There is no "magic abilities", libraries like const s
= ```
<html>
<p>
${ someContent }
</p>
</html>
``` If say someContent were: const someContent
= String.dedent```
<span>
Hello <b>world!</b>
</span>
``` Then as I'm proposing here it would be nice if this were indented by default into: <html>
<p>
<span>
Hello <b>world!</b>
</span>
</p>
</html> Now perhaps this should be opt-in, in which case we'd just replace But okay well how does this work with tags? Well whether the behaviour was default behaviour OR opt-in, one would just pass the indent objects straight through to the tag i.e.: const s
= html```
<html>
<p>
${ String.indent(someContent) }
</p>
</html>
``` would pass the But again, there is no magic here, in fact this feature doesn't even need to part of this proposal, it would work with regular template strings anyway (i.e. how |
Maybe i misunderstood your comment about “branded object”. It must not be possible for an interpolation containing any function call - which is just a normal expression context - to implicitly receive information about the source code that triggered it. That’s the magic I’m assuming you mean. |
The tags wouldn't know anything other than what is passed to them. In the explicit form with To have The branded object thing is just so that there is some way for tag code to actually understand the difference between The indent-by-default behaviour could be built easily on top of not-by-default, the main thing that is hard to do in userland though is that there is no common signal to template tags that something should be indented. Without this every single tag needs to reimplement essentially the same algorithm in order to get indenting working again, even though in most cases that isn't their primary goal (i.e. |
I also realized that a general And sure every single library could provide it's own |
Just to simplify the above examples, all Really all the Although if there was interest in such a larger proposal allowing sharing formatting info with as many tags as possible, it could just be the case |
I can see this being helpful enough that we can discuss it in committee. I think the simplest API is a class Indentable {
#indentable; // this is an internal slot for the spec
constructor(str) {
if (typeof str !== 'string') throw new TypeError();
this.#indentable = str;
}
// This is so that non-spec things can stringify
toString(indent = '') {
return AddIdentationTo2ndPlusLines(this.#indentable, indent);
}
} We'd then modify |
Yep this is pretty much
Note that still generally makes sense to pass non-string objects to indentable, i.e. in HTML you might have Although it might be the case that most libraries that generate DSLs as strings would want to pass to indent anyway in which case the user wouldn't even bother specifying. |
Currently in the demo the behaviour of the following:
Produces the following string:
While this matches the popular
dedent
library behaviour, it isn't particularly great as it makes it hard to compose separate indented chunks (not necessarily just of code).I'd like to propose changing the behaviour so that the above snippet would produce the following:
This behaviour is currently implemented by the fairly popular npm library
endent
.Note that this behaviour is not possible to add to the strings themselves because the indentation level is not known. For example this won't work:
Because the function
indented
would have no way of knowing the current indent.An alternative strategy could be to expose a wrapper that allows embedded expressions to receive the current indentation level e.g.:
The text was updated successfully, but these errors were encountered: