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

Add an option to recursively dedent nested template literal strings #12

Open
rattrayalex-stripe opened this issue Sep 12, 2017 · 16 comments
Labels
status: accepting prs Please, send a pull request to resolve this! type: feature New enhancement or request

Comments

@rattrayalex-stripe
Copy link

rattrayalex-stripe commented Sep 12, 2017

Hijacked by @JoshuaKGoldberg on September 4th, 2023: see #12 (comment). Now accepting PRs for a dedent({ recursive: true }) option.


const a = dedent`
hello
  world
`;
const b = dedent`
  foo.
  ${a}
  bar.
`;

results in

foo.
hello
world
bar.

instead of

foo.
hello
  world
bar.

This is unfortunate because it would be nice to compose dedented strings.

If you decide to fix this, any test cases should also check that inlined dedents make sense:

const weird = dedent`
  foo.
  ${things.map(x => dedent`
    hello
      world
  `).join('\n')}
  bar.
`;
@dralletje
Copy link

I needed exactly the same today, so #13 was born.
It now adds the indention of the line you interpolate on to every line in the interpolated string.

What would your preferred behaviour for the last example be?
In my code now, that would result (when you have 3 items in the things array) in this

foo.
hello
  world
hello
  world
hello
  world
bar.

@rattrayalex-stripe
Copy link
Author

Awesome! Will discuss expected behavior in the PR

@ZhouHansen
Copy link

ZhouHansen commented Dec 11, 2017

indentjs/endent endows suitable indentation for multiline interpolation.

@bertho-zero
Copy link

@ZhouHansen This issue exist also with endent: https://runkit.com/embed/fx2ssy6zqm9x

@ZhouHansen
Copy link

ZhouHansen commented May 21, 2018

@bertho-zero
Copy link

This is not a neested endent.

@dralletje
Copy link

dralletje commented May 22, 2018

@bertho-zero You are right. This is not because of the multiple indentation though. It is a bug in endent that makes it not work well with string that start without indentation at all.

This one (that clearly has one line indented and the other not indented) will output a totally not indented string
https://runkit.com/dral/5b036f8dabe4a00011e3e82e

Once you add a layer of indentation to all your lines, it gives the right output
https://runkit.com/dral/5b037090b225ba00122e66cf

@ZhouHansen This is a bug in endent - ofcourse you want to first apply endent to the substring.. not sure why you made your "right usage" so wrong ;)
I see you made me collaborator on that repo though, so I'll give fixing it a shot tomorrow :)

@ZhouHansen
Copy link

@dralletje that will be very helpful!

@d07RiV
Copy link

d07RiV commented Jun 1, 2018

@dralletje you didn't compile your fork, so it still has the same dist code.

@dralletje
Copy link

@d07RiV Good find, updated it :)

@rattrayalex
Copy link

Thank you @ZhouHansen , I confirm that the endent package has the behavior I want – I have replaced all uses of dedent with it.

By the way, it looks like endent now has over 2.5mm downloads/wk, congrats!

@JoshuaKGoldberg
Copy link
Collaborator

JoshuaKGoldberg commented May 22, 2023

Hmm, I can see why you'd want this behavior... but also it's a bit counter-intuitive to how the package is positioned right now IMO. Today, it's used as a "dedent everything in this string" utility - not a "dedent this string, and still allow indents in some contents".

Perhaps this can become an opt-in? A couple of API starting ideas..

dedent.recursive`
  ${text}
`;

dedent({ recursive: true })`
  ${text}
`;

Thoughts, everyone?

@JoshuaKGoldberg JoshuaKGoldberg added the status: in discussion Not yet ready for implementation or a pull request label May 22, 2023
@bertho-zero
Copy link

This is fixed with ts-dedent: https://runkit.com/embed/di4ek5toqg7o

@magicmark
Copy link

magicmark commented Sep 4, 2023

Perhaps this can become an opt-in? A couple of API starting ideas..
...
Thoughts, everyone?

@JoshuaKGoldberg thanks for pointing me here! To provide some feedback on this - I use this package a lot (I write a lot of cli tooling in particular that spits out formatted error messages to users) and 10/10 times this is the default behavior i'm looking for. That said, I understand and totally respect it's a question of scope and not wanting to fundamentally change (in a backwards incompatible way) the behaviour of this significantly depended-on library!

With that in mind, I feel like it's worthy enough of being a top level namespace thing (rather than buried as an option), and so I like what you initially suggested the most:

dedent.recursive`...`

fwiw in terms of API ideas, here's some prior art for a similar thing in execa: https://github.com/sindresorhus/execa#shared-options - so you'd suggest something like:

import dedent from 'dedent';
const ddedent = dedent({ recursive: true });
console.log(ddedent`...`)

I don't personally love this, the $$ example is neat enough but ddedent or anything else i can think of just looks weird and non obvious. but maybe if you could come up with a catchy alias it could be nice.

3rd option (which could go alongside as an alias of the first option)

import { recursive as dedent } from 'dedent';
console.log(dedent`...`);

@JoshuaKGoldberg
Copy link
Collaborator

The dedent.recursive option is definitely appealing. A similar idea came up with escapeSpecialCharacters too, like dedent.escapeSpecialCharacters. The one issue is that we'd then have to content with a whole bunch of potential options there. Would dedent.escapeSpecialCharacters.recursive need to work too?

For now, let's add it in as an opt-in option: dedent({ recursive: true }).

@JoshuaKGoldberg JoshuaKGoldberg added type: feature New enhancement or request status: accepting prs Please, send a pull request to resolve this! and removed status: in discussion Not yet ready for implementation or a pull request labels Sep 5, 2023
@JoshuaKGoldberg JoshuaKGoldberg changed the title Nested dedents does not work as expected Add an option to recursively dedent nested template literal strings Sep 5, 2023
@rattrayalex
Copy link

Thoughts, everyone?

Heh, hey @JoshuaKGoldberg ! Good to see you here! Sorry I missed this before.

FWIW, it's not my expected behavior to have the library dedent most things, except child strings. I consider the current behavior a bug, not a separate feature, though I may be missing something.

I wouldn't want to have to use an option for a library like this – more specifically, I wouldn't want to have to police that everyone in my codebase always calls the recursive version.

I could maybe be okay with import dedent from 'dedent/recursive', but really I'd much rather this just be the default behavior (though I'll admit it may require a major version bump).

For now, personally, I'd probably simply stick with ts-dedent which has this behavior out of the box (as well as TS types) if a recursive option were added.

Just my 2c!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: accepting prs Please, send a pull request to resolve this! type: feature New enhancement or request
Projects
None yet
Development

No branches or pull requests

8 participants