Handlebars, whitespace control

2020-06-30 05:01发布

问题:

i want fine control of whitespace but still have readable templates.

Just wanted to see if other's solution to by simple use case.

{{name}}
{{#if age}}
  , {{age}}
{{/if}}

# outputs {{name}} , {{age}}
# desire: {{name}}, {{age}}

https://github.com/wycats/handlebars.js/issues/479 - submitted a ticket which was closed.

回答1:

Following the history from the pull request to add this feature it looks like this is the correct syntax:

<h4>
{{~#object~}}

Surrounding whitespace would be removed.

{{/object}}
</h4>

Result:

<h4>Surrounding whitespace would be removed.</h4>

There is also this syntax which trims only leading whitespace:

<h4>
{{~#object}}

Only leading whitespace would be removed.

{{/object}}
</h4>

Result:

<h4>Only leading whitespace would be removed.
</h4>


回答2:

Just a comment to Brian answer, If you want to trim whitespace AND do not want handlebars to escape your expression at the same time, the correct syntax to be used is:

{{~{EXPRESSION}~}}

(trimming whitespace before and after the expression while not escaping it)



回答3:

You can add a Handlebars Helper to trim() whitespace

{{#-}}

Surrounding whitespace would be removed.

{{/-}}

more background info: https://github.com/wycats/handlebars.js/pull/336



回答4:

The Handlebar's Whitespace Control Documentation can be found here: https://handlebarsjs.com/guide/expressions.html#whitespace-control

Template whitespace may be omitted from either side of any mustache statement by adding a ~ character by the braces. When applied all whitespace on that side will be removed up to the first handlebars expression or non-whitespace character on that side.

These two, comma-list examples would have the same output:

Case 1:

  {{#each listItems as |item index|}}
    {{#if (eq index 0)}}
      {{~item.name~}}
    {{else~}}
      , {{item.name~}}
    {{/if}}
  {{/each}}

Case 2:

  {{#each listItems as |item index|}}
    {{#if (eq index 0)~}}
      {{item.name}}
    {{~else~}}
      , {{item.name}}
    {{~/if}}
  {{/each}}


回答5:

I think the cleanest implementation of this would be to add {{"\n"~}} where you want a hard-stop on new lines.

The "\n" can technically be anything except for empty, ie "". I used "\n" to make it clear what I am doing in the editor.

Example

Three empty lines after this



{{"\n"~}}







Three empty lines before this


Two empty lines before this. No empty lines after this.


{{~"\n"~}}


No empty lines before this.

Result

Three empty lines after this



Three empty lines before this


Two empty lines before this. No empty lines after this.No empty lines before this.

Basically, as others have said, any helper can be prefixed or suffixed with ~. Here, I've decided to pass a value that won't render as the helper ("\n") which allows us to pass ~ freely to control before and after whitespace.

Edit

Alternatively:

Handlebars.registerHelper(
  'singleLineOnly',
  function (options) { // "this" cannot be provided to inline function!
    return options.fn(this).replace(/[\r\n]+/gm, '')
  }
)
Handlebars.registerHelper(
  'singleSpaceOnly',
  function (options) { // "this" cannot be provided to inline function!
    return options.fn(this).replace(/\s\s+/g, ' ')
  }
)

Which will allow you to take something like this:

{{#each this}}
  {{#singleLineOnly}}
  {{#singleSpaceOnly}}

  {{calculatedAmount}}

  {{!an example comment}}
  {{#if unitOfMeasure.translate}}
    {{{unitOfMeasure.translate.value}}}
  {{/if}}

  {{!some random comment}}
  {{#unless unitOfMeasure.translate}}
    {{{unitOfMeasure.value}}}
  {{/unless}}

  {{!Some random comment}}
  {{#ifNotEquals (lowerCase product.value) "other"}}
    {{!If translated, use translated UOM}}
    {{#if product.translate}}
      {{{product.translate.value}}}
    {{/if}}
    {{!If not translated, use default UOM}}
    {{#unless product.translate}}
      {{{product.value}}}
    {{/unless}}
  {{/ifNotEquals}}

  {{!just some more logic for example}}

  {{#ifNotEquals (lowerCase ingredient.value) "other"}}
    {{!If translated, use translated UOM}}
    {{#if ingredient.translate}}
      {{{ingredient.translate.value}}}
    {{/if}}
    {{!If not translated, use default UOM}}
    {{#unless ingredient.translate}}
      {{{ingredient.value}}}
    {{/unless}}
  {{/ifNotEquals}}
  <br/>

  {{/singleSpaceOnly}}
  {{/singleLineOnly}}
{{/each}}

And end up with this:


1/2 oz. first ingredient <br/>
1 pump(s) another ingredient <br/>
3/4 oz. this ingredient <br/>
2 shot(s) that ingredient <br/>
last instruction <br/>

{{#singleLineOnly}} and {{#singleSpaceOnly}} can be used as a wrapper for any text. You'll most likely want to use these with ~ for additional before/after whitespace control. For example: {{~#singleLineOnly~}}