Regular expression and template are not working

12

I'm trying to create a template engine using JavaScript. The syntax will be more or less similar to that of Laravel (blade), with some modifications.

I'm part of creating expressions. The first one I'm doing is if , but right away I've faced a problem.

First of all, I would like to make it clear that I created a template in a separate file, which has the content viewed through the fs module. To be able to run in the browser, I put all string returned within a template constant:

const template = '
<div class="wrapper">
  <p>Um paráfrafo qualquer fora do if.</p>
  @if (true)
    <p>
      Um parágrado dentro do if.
      <strong>Tags aninhadas.</strong>
    </p>
  @endif
</div>
';

I created the following regular expression to do searches within the view:

/@if(?:\s+|)\(([\s\S]*?)\)([\s\S]*?)@endif/gi

And I'm using the following code to "run" the expression if :

const renderView = (template, data = {}) => {
  const IF_REGEX = /@if(?:\s+|)\(([\s\S]*?)\)([\s\S]*?)@endif/gi;
  template = template.replace(IF_REGEX, (template, conditional, content) => {
    if (! eval(conditional)) return '';
    return content;
  });

  return template;
};

It works perfectly when there is only one block if (without block nesting).

However, when I nest two blocks:

<div class="wrapper">
  <p>Parágrafo fora dos ifs.</p>

  @if (false)
    <div>Oi?</div>
    @if (true)
    <span>Span...</span>
    @endif
  @endif
</div> 

It does not work as expected:
- > View a screenshot .

How can I correct this error? I guess it's in regular expression .

    
asked by anonymous 21.03.2018 / 18:00

1 answer

8

The problem is in your regex that will only select until the first final occurrence in @endif , ignoring the second (or too many).

To solve, add the quantifier + that will allow you to select how many occurrences preceded by @endif :

@if(?:\s+|)\(([\s\S]*?)\)([\s\S]*?)+@endif
                                   ↑
                             quantificador

See the print on regexr.com :

    
25.03.2018 / 06:24