Регулярное выражение Javascript для содержимого шаблонов Twig

Я использую Rich Text Editor, чтобы разрешить онлайн модификацию шаблонов Twig. Twig - это шаблонизатор, использующий следующий синтаксис для отображения переменных:

{{ object.property }}

Он также использует функции для генерации URL, такие как:

{{ url('mr_message_read', {id: message.id}) }}

Теперь я хочу отобразить рядом с моим редактором список переменных и функций TWIG, используемых в шаблоне. Для этого я извлекаю текущее содержимое в формате HTML с помощью ключевых слов "twig", как показано выше. Чтобы извлечь ключевые слова, я использую регулярное выражение ниже:

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

Это будет работать в примере 1, но не в примере 2, так как для функции Twig требуется строка }. Итак, я попробовал несколько других синтаксисов, чтобы разрешить "все, кроме}}". Ни один из них не кажется подходящим

    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

Я борюсь сейчас. Я полагаю, это проблема с побегом, но я застрял:)

Пример содержания:

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

РЕДАКТИРОВАТЬ: мое решение на основе кода Томаса

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) => {
            if(match !== 'undefined' && groupIndex == 1)
                // console.log(`Found match: group ${groupIndex}: ${match}`);
                keywords[keywords.length] = match;
        });
    }

    return keywords;
}

1 ответ

Решение

Вы можете использовать этот код:

const regex = /{{\s*([^{]*{([^{]*):\s*(.*?)}.*?|[^{]*)\s*}}/g;
const str = `{{ url('mr_message_read', {id: message.id}) }}
{{ object.property }}`;
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) => {
      if(match !== 'undefined' && groupIndex > 0)
        console.log(`Found match: group ${groupIndex}: ${match}`);
    });
}

Другие вопросы по тегам