I never needed those. I would just have an application wide object property like:

            text: {
                angry    : "\u001b[1m\u001b[31m",
                blue     : "\u001b[34m",
                bold     : "\u001b[1m",
                boldLine : "\u001b[1m\u001b[4m",
                clear    : "\u001b[24m\u001b[22m",
                cyan     : "\u001b[36m",
                green    : "\u001b[32m",
                noColor  : "\u001b[39m",
                none     : "\u001b[0m",
                purple   : "\u001b[35m",
                red      : "\u001b[31m",
                underline: "\u001b[4m",
                yellow   : "\u001b[33m"
            }
And then you can call that directly like:

    `${vars.text.green}whatever${vars.text.none}`;

This is the problem with people trying to be clever. Now you output escape sequences regardless of terminal setting.

Using a library which handles that (an a thousand other quirks) makes much more sense

There is no cleverness involved. The escape sequences are decades old and universally supported as a de facto standard. In this case the escape sequences are assigned to variables that are attached to other strings. This is as clever as using an operator. These escape sequences are even supported by Chromes dev tools console directly in the browser.

The real issue is invented here syndrome. People irrationally defer to libraries to cure their emotional fear of uncertainty. For really large problems, like complete terminal emulation, I understand that. However, when taken to an extreme, like the left pad debacle, it’s clear people are loading up on dependencies for irrational reasons.

I despise these microlibraries as much as anyone, but your solution will also print escape codes when they're not needed (such as when piping output to e.g. grep). If it's something that makes sense only in interactive mode, then fine, but I've seen enough broken programs that clearly weren't designed to be run as a part of a UNIX shell, even when it makes a lot of sense.

It's easy to solve though, simply assign empty strings to escape code variables when the output is not an interactive shell.

Yes, the tree view of dependencies in pnpm breaks my terminal environment when I attempt to pipe it through |less. Several JS related tools seem to have this undesirable behavior. I assume most users never view dependencies at that depth or use a more elaborate tool to do so. I found this symptomatic of the state of the JS ecosystem.

That is not a string output problem. That is a terminal emulator problem. It is not the job of an application to know the modes and behaviors of the invoking terminal/shell. This applies exactly the same for all other applications that write to stdout. There is no cleverness here. But, if you really really want to avoid the ANSI descriptors for other reasons, maybe you just don't liked colored output, my applications features a no-color option that replaces the ANSI control string values with empty strings.

The terminal emulator is not involved in piping to other processes. Grep will search over escape codes if you don’t suppress them in non-interactive environments, so this most definitely is a string output problem.

If you want to do it yourself, do it right—or defer to one of the battle-tested libraries that handle this for you, and additional edge cases you didn’t think of (such as NO_COLOR).

How do you define battle tested?

Typically JS developers define that as assuming something must be safe if enough people use it. That is a huge rift between the typical JS developer and organizations that actually take security more seriously. There is no safety rating for most software on NPM and more and more highly consumed packages are being identified as malicious or compromised.

If you do it yourself and get it wrong there is still a good chance you are in a safer place than completely throwing dependency management to the wind or making wild guesses upon vetted by the community.

I mean we’re talking about libraries to format strings here, not rendering engines. If you doubt the quality of such a lib, go read the source on GitHub. That’s what I usually do before deciding if I install something or implement it myself.

Lots of applications use isTTY to determine how they output FYI

It is 100% the job of the application. This is why a lot of programs have options like --color=auto so it infers the best output mode based on the output FD type e.g. use colours for terminals but no colours for pipes.

It depends on the audience / environment where your app is used. Public, a library is better. Internal / defined company environment, you don't need extra dependencies (but only when it comes to such simple solutions, that could be replaced easy with a lib).

I think the widely-implemented terminal escape sequences are well-known at this point, but I don't see why I'd want to copy this into every project.

Also, I'm guessing if I pipe your logs to a file you'll still write escapes into it? Why not just make life easier?

Arguably, using a library is also "copy it into every project".

that's needlessly pedantic. the GP is noting that it's built into node's standard library, which might discourage you from installing a library or copying a table of ansi escapes.

I have a "ascii.txt" file ready to copy/paste the "book emoji" block chars to prepend my logs. It makes logs less noisy. HN can't display them, so I'll have to link to page w/ them: https://www.piliapp.com/emojis/books/

Why would you call that "ascii.txt"?

Caz it has more than those book emojis. It makes writing geometric code docstrings easier. Here's the rest of it (HN doesn't format it good, try copy/paste it).

   cjk→⋰⋱| | ← cjk space btw | |
   thinsp | |
   deg° 
   ⋯ …
   ‾⎻⎼⎽ lines
   _ light lines
   ⏤ wide lines
   ↕
   ∧∨ 
 ┌────┬────┐ 
 │    │ ⋱  ⎸ ← left bar, right bar: ⎹
 └────┴────┘
    ⊃⊂ ⊐≣⊏
    ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯====›‥‥‥‥
◁ ◿ ◺ ◻ ◸ Λ ╱│╲ ╱ │ ╲ ──┼── ╲ │ ╱ ╲│╱ V ┌ ─┏━━┳━━━━━━━┓ │ ┃ ┃ ┃ ├ ─┣━━╋━━━━━━━┫ │ ┃ ┃ ┃ └ ─┗━━┻━━━━━━━┛ ┌ ─ ┬ ─ ┐ ├ ─ ┼ ─ ┤ └ ─ ┴ ─ ┘ ┌───┬───┐ ├───┼───┤ │ │ │ └───┴───┘ . ╱│╲ ↘╱ │ ╲ ↙ ╱ │ ╲ →‹───┼───›← ╲ │ ╱ ↗ ╲ │ ╱ ↖ ╲│╱ ↓↑ ╳ . ╱ ╲ ╱ ╲ ╱ ⋰ ╲ ╱⋰______╲

To be fair, I do this when writing shell scripts by hand. But if it’s built in, why would I?