benchpressjs / benchpressjs

ultralight javascript templating framework
MIT License
90 stars 17 forks source link

Deep nesting problem in complex templates #61

Closed Radiergummi closed 7 years ago

Radiergummi commented 8 years ago

When creating rather complex templates, eg. nested loops and several IF statements, at some point templates.js messes up. Some comments stay in the output, data is not necessarily parsed as intended at all.
I managed to put a test case together, see below:

Template:

<div class="always-visible">
<!-- IF firstCondition -->
  <div class="visible-if-first-true">
  <!-- IF secondCondition -->
    <div class="visible-if-second-true">
      <!-- IF firstLoop.length -->
        <!-- IF firstLoopHasOnlyOneItem -->
        <span class="first-loop-has-only-one-item">Only one!</span>
        <!-- ELSE -->
        <span class="first-loop-has-multiple-items">Multiple.</span>
        <!-- ENDIF firstLoopHasOnlyOneItem -->
        <!-- BEGIN firstLoop -->
          <div class="item">
            Item {@index}: {firstLoop.unreasonably.deep.nested.property1}, {firstLoop.unreasonably.deep.nested.property2}
            <div class="sub">
              <!-- IF firstLoop.secondLoop.length -->
                <!-- BEGIN firstLoop.secondLoop -->
                  <div class="sub-item">Subitem {@index}: {firstLoop.secondLoop.data.name} => {firstLoop.secondLoop.data.content}</div>
                <!-- END firstLoop.secondLoop -->
              <!-- ELSE -->
                <span class="second-loop-has-no-content">No content in second.</span>
              <!-- ENDIF firstLoop.secondLoop.length -->
            </div>
          </div>
      <!-- END firstLoop -->
      <!-- ELSE -->
        <span class="first-loop-has-no-content">No content in first.</span>
      <!-- ENDIF firstLoop.length -->
    </div>
  <!-- ENDIF secondCondition -->
  </div>
<!-- ENDIF firstCondition -->
</div>

Options:

var options = {
  firstCondition: true,
  secondCondition: true,
  firstLoop: [
    {
       secondLoop: [ 
         { data: { name: 'fooName', content: 'useless clutter'} },
         { data: { name: 'barName', content: 'even uselesser'} }
       ],
       unreasonably: { deep: { nested: { property1: 'foo', property2: 'bar'} } }
    }
  ]
};

Expected output:

<div class="always-visible">
  <div class="visible-if-first-true">
  <div class="visible-if-second-true">
        <span class="first-loop-has-multiple-items">Multiple.</span>
          <div class="item">
            Item 1: foo, bar
            <div class="sub">
                  <div class="sub-item">Subitem 1: fooName => useless clutter</div>
                  <div class="sub-item">Subitem 2: barName => even uselesser</div>
            </div>
          </div>
    </div>
  </div>
</div>

Actual output (templates.parse(test, options)):

<div class="always-visible">
  <div class="visible-if-first-true">
    <!-- IF secondCondition -->
    <div class="visible-if-second-true">
      <!-- IF firstLoop.length -->
     <span class="first-loop-has-multiple-items">Multiple.</span>

                  <div class="item">
            Item : foo, bar
            <div class="sub">

                                 <div class="sub-item">Subitem : fooName => useless clutter</div>
                \n                  <div class="sub-item">Subitem : barName => even uselesser</div>

            </div>
          </div>

</div>

Now, once running this without any options (templates.parse(test, {})):

<div class="always-visible">
                <span class="second-loop-has-no-content">No content in second.</span>
              <!-- ENDIF firstLoop.secondLoop.length -->
            </div>

          </div>
      <!-- END firstLoop -->

</div>

First condition false (templates.parse(test, { firstCondition: false })):

<div class="always-visible">
        <span class="first-loop-has-no-content">No content in first.</span>
      <!-- ENDIF firstLoop.length -->
    </div>
  <!-- ENDIF secondCondition -->

  </div>
</div>

First condition true, second false, firstLoop present but empty (templates.parse(test, { firstCondition: true, secondCondition: false, firstLoop: [] })):

<div class="always-visible">
  <div class="visible-if-first-true">
  <!-- IF secondCondition -->
    <div class="visible-if-second-true">
      <!-- IF firstLoop.length -->

     <span class="first-loop-has-multiple-items">Multiple.</span>

</div>
Kombustor commented 7 years ago

Still not fixed @psychobunny..

I'm running the newest template.js-version, but when trying to add an if-statement to the category-template in NodeBB, it messes up the html

`

S
        <h2 component="topic/header" class="title">
            <i component="topic/pinned" class="fa fa-thumb-tack hide" title="Pinned"></i>
            <i component="topic/locked" class="fa fa-lock hide" title="Locked"></i>
            <i component="topic/moved" class="fa fa-arrow-circle-right hide" title="Moved"></i>

            <!-- IF !topics.noAnchor -->
            <a href="/topic/3/asdasdasd" itemprop="url">Asdasdasd</a><br>
</h2></div>`
Radiergummi commented 7 years ago

hmm.. Have abandoned templates.js in favor of handlebars now, which is sad actually. I find the syntax with handlebars way worse.

pitaj commented 7 years ago

Fixed in Benchpress