-
-
Notifications
You must be signed in to change notification settings - Fork 12
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
Escape-free, error-free, parser-based chalk-template #18
base: main
Are you sure you want to change the base?
Conversation
Hi there, this is a rather large departure from the current status quo, and it's also breaking a lot of expected functionality (e.g. I'm not opposed to a more robust parser implementation but as of now I'm not really seeing the motivation other than the beginning/ending delimiters. Instead, it might be simpler to construct the regular expression objects with the delimiters interpolated directly into the pattern using Perhaps a bit of a hack to your particular problem, but as of now the change of base behavior is a non-starter for me, personally. Happy to discuss further, though :) |
Hey! Thanks for your time and comments. I appreciate and share your concern for security. I’d be happy to work through your concerns to make sure that value is being added in a constructive way. To that end, before I do any more work, I’d like to talk through the use case, the concerns, and the mitigations and proposals - to make sure I'm on the right track. Use Cases:
ConstraintsAssume the user does not have direct access to chalk or chalk-template, herein known as the "template fn." So all configuration must be via the string. i.e. assume the user just has access to a tagged template function called This is playing on hard-mode. Doing it within opts on the template fn is probably fine for most people. AnalysisPoint 1Changing the delimiters of a style to a different character could work, but that would like require access to the template fn. Unless we take a page from Mitigations:1a. Changing the Point 2The extra constraint of only using strings is a bummer. I realized it could have been solved if I had just pre-rendered the template to ANSI and then just inserted the ANSI in the next template. i.e.
Point 3I totally agree that invoking arbitrary functions from template strings is risky. But breaking it down - its not always risky. Its not risky if you are in full control of the argument (i.e. did not come user). Its not risky if chalk hadn't been customized. But, lets be secure-by-default and make the default be escaping all arguments - but lets give the user an ability to opt-in to rendering args. Mitigations:3a. Create a new function
or better yet, just use the template again
-- which is basically an application of [2] ProposalI'll do 1a and 1b. These will be options on the template builder fn.
For 3 I will go ahead and make escaping of args true by default, to match previous behavior and to make it secure.
All that being said, this definitely deserves a bump to 2.0.0. |
Hey @sindresorhus and @Qix- - please check out this enhanced chalk-template function. This started out as a contribution to google/zx#635 - but after thinking about it, it would be more appropriate upstreamed here.
I happen to enjoy writing parsers - weird hobby, I know.
Background: When creating that PR for zx, I realized that I couldn't just send arbitrary text through chalkTemplate - it is very picky about escaping, and matching parenthesis, and styles, etc. I started to write a pre-processor for the template, to adopt a different start/end syntax. I was planning using new new prefix like
ct:{
but that wasn't short enough, and it might have been common enough to require escaping, which is a PITA to handle correctly. Then I realized - hey I already have the parser that is pre-processing the template - I could just go all the way and do the actual styling too. This would also solve another problem I had with chalkTemplate - you couldn't use a template as an argument to a template, since it would be automatically escaped by chalkTemplate.Then I realized - hey - we don't need to handle escapes at all. The syntax of
{style
or{rgb(
or{#
was already unique enough to not conflict with most arbitrary text. And, since its a parser, I didn't need to throw errors for mismatching { }s or anything - the fallback would be to just not style the unmatched text.And so, the parser, AST, and renderer was born. This was written with typescript annotations as well, so I added typescript and prettier as dependencies.
Additionally, I changed the project layout a bit: created
/src
and/dist
. Lastly, the exports were manipulated a little bit. There is no more default-export. There is one that uses chalk, one that uses chalkStderr, and one that you can use to bring your own chalk. There is also an 'experimental' export that exposes the AST. This is really just used to help play/develop the parser, but maybe its useful to someone. Its experimental as this is v1 of the AST and it may need some time to bake before being "API."Technically, the parser is flexible to allow changing the 'prefix' of the template, currently set to
{
- this could be configurable, but currently it is not. The suffix is always '}' but that too could probably be configureable without much work - not sure if its a good idea.Anyways, I'm wondering if there is any appetite for merging this PR, especially since this is basically a rewrite. I'm open to all comments/critiques - especially around the actual exported functions. And naming. Naming is hard. I'm bad at it.
This PR probably needs more documentation, more tests, and more general refinement. But I wanted to start the discussion before deciding if it was worth any more effort.