Javascript regex for Twig templates contents
<p>I use a Rich Text Editor to allow online modification of Twig templates. Twig is a template engine using the following syntax to display variables:</p>

<pre><code>{{ object.property }}
</code></pre>

<p>It also uses functions to generate URLS, such as:</p>

<pre><code>{{ url('mr_message_read', {id: message.id}) }}
</code></pre>

<p>Now what i want is to display, next to my editor, the list of TWIG variables <strong>and</strong> functions used in the template. For this, i retrieve the current content as HTML with twig "keywords" as shown above. To extract keywords, i use the regex below:</p>

<pre><code>var reg = /{{[^}]+}}/g;
var match = text.match(reg);
console.log( match );
</code></pre>

<p>This will work work <strong>example 1</strong> but not for <strong>example 2</strong>, as the Twig function requires the <strong>}</strong> string. So, i tried several other syntaxes to allow "<em>anything except }}</em>". None of them seem fit:</p>

<pre><code>    var reg = /{{[^}]+}}/g; // GOOD but ignores second example
    var reg = /{{[^}}]+}}/g; // Idem
    var reg = /{{[^}}]*}}/g; // Idem
    var reg = /{{(^}}+)}}/; // null
    var reg = /{{(^}})+}}/; // null
    var reg = /\{\{[^\}\}]+\}\}/g; // Ignores second example
    var reg = /\{\{[^}}]+\}\}/g; // Ignores second example
    var reg = /\{\{[^\}\}]+\}\}/g; // Ignores second example
    var reg = /\{\{[^[}}]]+\}\}/g; // Ignores second example
</code></pre>

<p>I'm struggling now. I guess it's an escaping issue, but i'm stuck :)</p>

<p><strong>Sample content :</strong></p>

<pre><code>&lt;p&gt;{{ author.fullname }} wrote you a message. Read it here: &lt;a href="{{ url('mr_message_read', {id: message.id}) }}"&gt;Messagerie&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;blockquote&gt;
&lt;p&gt;{{ message.content|nl2br }}&lt;/p&gt;
&lt;/blockquote&gt;
</code></pre>

<hr>

<p><strong>EDIT: My solution based on Thomas code</strong></p>

<pre><code>function getTwigTags(){

    var str = CKEDITOR.instances['form_content'].getData();
    var regex = /{{\s*([^{]*{([^{]*):\s*(.*?)}.*?|[^{]*)\s*}}/g;
    var keywords = new Array();
    let m;

    while ((m = regex.exec(str)) !== null) {
        // This is necessary to avoid infinite loops with zero-width matches
        if (m.index === regex.lastIndex) {
            regex.lastIndex++;
        }

        // The result can be accessed through the `m`-variable.
        m.forEach((match, groupIndex) =&gt; {
            if(match !== 'undefined' &amp;&amp; groupIndex == 1)
                // console.log(`Found match: group ${groupIndex}: ${match}`);
                keywords[keywords.length] = match;
        });
    }

    return keywords;
}
</code></pre>