posthtml / posthtml-expressions

Use variables, JS-like expressions, and even markup-powered logic in your HTML.
Other
123 stars 20 forks source link

[Feature Request] Allow outputting delimiters #61

Closed cossssmin closed 4 years ago

cossssmin commented 4 years ago

Many templating languages use the {{ and }} delimiters.

If you want to have those delimiters output in the compiled HTML, the only way to do so currently is to change the delimiters that posthtml-expressions uses.

This would work, but isn't ideal, as it forces you do add configuration and maybe you just want to use the {{ }} delimiters that the plugin comes with by default.

Proposal

What do you think about having a way to mark content that will not be parsed?

Maybe like this? (inspired by Nunjucks/Jinja)

<p>Your name is <raw>{{ user.name }}</raw>.</p>

That would output:

<p>Your name is {{ user.name }}</p>

Thoughts?

anikethsaha commented 4 years ago

Its interesting to have this.

+1 for this

cossssmin commented 4 years ago

Another idea would be to mark the curly braces like Blade does:

Hello, @{{ user.name }}  // Hello, {{ user.name }}

That could be used for one-offs where you only need to output the braces for one instance.

<raw> could be used to discard everything inside it, so you could wrap it around multiple {{ }}:

<raw>
  <tr>
    <td>{{ user.first }}</td>
    <td>{{ user.last }}</td>
    <td>{{ user.last_login_at }}</td>
  </tr>
</raw>
anikethsaha commented 4 years ago

implementing using <raw> tag will be easy as we do parse tags so we can simply go to the next node. While having blade-like iterator needs custom parsing implementation which will be simple as well in terms of parsing but not as easy as the tags.

While I am +1 for either of them. Having blade-like syntax might be helpful to convey as its already implemented

cossssmin commented 4 years ago

Played around with the @{{ }} approach and got it working with a negative lookbehind + a replacement in lib/index.js:

- const delimitersRegexp = new RegExp(`${before}(.+?)${after}`, 'g')
+ const delimitersRegexp = new RegExp(`${before}(?<!@{{)(.+?)${after}`, 'g')

Then just replaced the @{{ with {{:

// if we have a string, match and replace it
if (typeof node === 'string') {
  node = placeholders(node, ctx, delimitersSettings)

  // naive replacement
  if (/@{{(.+?)}}/.test(node)) {
    node = node.replace('@{{', '{{')
  }

  m.push(node)

  return m
}
cossssmin commented 4 years ago

Of course this is just an example - it would need to use the delimiters as set in the options - but what do you think?

anikethsaha commented 4 years ago

I am up for PoC. We can test both/any implementation.

Feel free to submit a PoC

cossssmin commented 4 years ago

Got the <raw> tag working already (with tests), will submit PR soon and will then move on to the @{{ approach.

cossssmin commented 4 years ago

Need your opinion on what to call tags such as <raw> or <verbatim>.

I want to provide an option for this so that, just like with other tags, the user can define it (some may like <raw>, but others may prefer <verbatim> or even <ignore>...).

I'm thinking of ignoredTags, but maybe we can come up with better wording?

anikethsaha commented 4 years ago

what about <noop> as no operation ?

cossssmin commented 4 years ago

Sorry, perhaps I didn't explain it well :)

So, for the tag itself, I would default it to <raw> or <verbatim>.

But internally, in the plugin's options, we could provide an option through an array to hold these tag names - just as conditionalTags defines the tags for conditionals.

So I was thinking we could use ignoredTags?

options = Object.assign({
    locals: {},
    // ...
    ignoredTags: ['raw', 'verbatim'],
  }, options)
anikethsaha commented 4 years ago

Ohh no. I misunderstood the comment earlier

I would prefer to have a default one but then we can change it using the config . and I guess it is better to have a single tag instead of array to do so as it might be confusing for other developers and also it will give extra operation to this plugin for similar work !

what do you think ?

cossssmin commented 4 years ago

I agree, I'll go with ignoredTag (singular) and set it to be a string instead of an array 👍

cossssmin commented 4 years ago

Working on it in this branch, will try to tackle @{{ }} as well and update the readme.

cossssmin commented 4 years ago

Got the @{{ foo }} working as well.

Question: should the @ be configurable? Should the user be able to set it to some other character?

anikethsaha commented 4 years ago

I dont think so, does blade supports that ?

cossssmin commented 4 years ago

No, it does not. I'll push the commit and open a PR so we can take it from there.

anikethsaha commented 4 years ago

cool 👍

cossssmin commented 4 years ago

Opened https://github.com/posthtml/posthtml-expressions/pull/63, let me know what you think :)

cossssmin commented 4 years ago

Added in https://github.com/posthtml/posthtml-expressions/pull/63, thanks for merging!