Регулярное выражение Javascript для соответствия шаблону, но НЕ соответствует литералу регулярного выражения (оптимизатор r.js и проблема с uglify)?

У меня есть приложение Backbone, организованное в модули с использованием Require.js. Один из этих модулей содержит хелпер Handlebars, у которого есть метод, который я использую для извлечения легального заголовка из всех наших HTML-шаблонов для каждого представления. Заголовок содержится в комментарии HTML, поэтому я использую следующее регулярное выражение, чтобы удалить его:

/<!--[\s\S]*?-->/g

Теперь, когда я оптимизирую (объединяю/компилирую/минифицирую) приложение с помощью r.js, я делаю то же самое удаление комментариев HTML, используя метод onBuildWrite() r.js:

onBuildWrite: function (moduleName, path, contents) {
    var htmlCommentRegex = /<!--[\s\S]*?-->/g;

    return contents.replace(htmlCommentRegex, "");
},

К сожалению, это означает, что когда модуль Require.js, содержащий вспомогательную функцию Handlebars, втягивается в оптимизированную для r.js сборку, литерал регулярного выражения внутри вспомогательной функции удаляется, в результате чего весь мой модуль r.js построить, чтобы бомбить.

Я попытался решить проблему, выборочно применив регулярное выражение в onBuildWrite() ко всем модулям, ЗА ИСКЛЮЧЕНИЕМ помощника:

onBuildWrite: function (moduleName, path, contents) {
    var htmlCommentRegex = /<!--[\s\S]*?-->/g;

    if (moduleName !== "helpers/handlebars.compileClean") {
        contents = contents.replace(htmlCommentRegex, "");
    }

    return contents;
},

Но это не работает, когда в конфигурации r.js включена функция uglification; Регулярное выражение ПО-ПРЕЖНЕМУ выполняется для всего собранного скрипта, включая помощника, что приводит к сбою сборки.

Если в конфиге r.js отключен uglify, то все работает нормально.

У кого-нибудь есть идеи, почему uglify может сломать это? Решит ли переключение на другое регулярное выражение, которое будет фиксировать HTML-комментарии, но ИГНОРИРОВАТЬ литерал регулярного выражения HTML-комментария? Если да, то как будет выглядеть это регулярное выражение?


person J. Ky Marsh    schedule 07.02.2013    source источник
comment
Как вы вставляете свой JS в HTML? Возможно, ваш шаблон действует как HTML-комментарий...   -  person kbec    schedule 07.02.2013
comment
Внедрить мой JS? Извините, я не слежу.   -  person J. Ky Marsh    schedule 07.02.2013
comment
Я не использую магистраль и другие вещи, но вы должны каким-то образом загрузить свой javascript в html.   -  person kbec    schedule 07.02.2013
comment
Что ж, конечным результатом оптимизации r.js является файл JS, а не файл HTML, поэтому, даже если бы литерал регулярного выражения действовал как комментарий HTML, я бы не ожидал, что ошибка произойдет именно в том месте, где литерал регулярного выражения находится во вспомогательном модуле. Я взгляну еще раз, имея это в виду, хотя!   -  person J. Ky Marsh    schedule 07.02.2013


Ответы (1)


Измените регулярное выражение на:

var htmlCommentRegex = /[<]!--[\s\S]*?-->/g;

Односимвольный класс [<] эквивалентен < в том, что касается процессора RE, но теперь RE больше не соответствует самому себе.

Другой способ — экранировать один из буквальных символов в RE:

var htmlCommentRegex = /<\!--[\s\S]*?-->/g;

Или вы можете построить RE из строк:

var htmlCommentRegex = new RegExp('<!'+'--[\s\S]*?-->', 'g');

Если r.js оптимизирует все это до исходного текста, попробуйте следующее:

var commentPrefix = '<!';
var htmlCommentRegex = new Regexp(commentPrefix+'--[\s\S]*?-->', 'g');

Надеюсь, он не проведет достаточного анализа кода, чтобы отменить эту запутанность.

person Barmar    schedule 07.02.2013
comment
или просто экранируйте его, как /\<!--.*?--\>/g - person kbec; 07.02.2013
comment
Я попробую, я помню, как uglify жаловался на неэкранированные символы. Любая идея, почему uglify будет жаловаться на неэкранированные символы, но сам JS не имеет проблем с литералом регулярного выражения? - person J. Ky Marsh; 07.02.2013
comment
@kbec Нужен только второй побег. - person Barmar; 07.02.2013
comment
Я не знаком с uglify, поэтому понятия не имею. Вы уверены, что он жаловался на RE, а не на что-то еще в коде? - person Barmar; 07.02.2013
comment
Что ж, ошибки колеблются в зависимости от настроек uglify и используемого регулярного выражения. Обязательно попробую ваше предложение и отчитаюсь. - person J. Ky Marsh; 07.02.2013
comment
Обновление: похоже, что r.js обрабатывает вставленные модули как текст, поэтому, когда мое регулярное выражение в конфигурации сборки запускается, оно будет каждый раз извлекать вспомогательное регулярное выражение, даже если литерал регулярного выражения в конфигурации немного отличается от хелпера, потому что он по-прежнему совпадает с хелпером, когда хелпер обрабатывается как текст. Использование конструктора RegExp также не помогло. Я предполагаю, что единственным решением будет регулярное выражение, которое соответствует комментариям HTML, но НЕ соответствует точному литералу регулярного выражения в помощнике. - person J. Ky Marsh; 07.02.2013
comment
Я не понимаю, как это может происходить. Весь смысл моего ответа в том, что текст в помощнике не соответствует регулярному выражению. Регулярное выражение соответствует <, за которым следует !, но текст имеет <, за которым следует ]. - person Barmar; 07.02.2013
comment
Хм, я полагаю, что r.js может оптимизировать JS и понимает, что [<] можно упростить до <. Как и в случае со строкой, он выполняет конкатенацию при оптимизации. У меня есть идея попробовать обойти это. - person Barmar; 07.02.2013
comment
Да, похоже, ваше последнее обновление сделало это! Итак, я полагаю, это означает, что вставленные модули Require.js фактически обрабатываются как текст во время событий onBuild, а не выполняются как настоящий JS. Огромное спасибо! - person J. Ky Marsh; 07.02.2013