Простой компилятор шаблонов для NodeJS
/** * Id: template * */ (function() { function escapeHtml(str) { return str .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function compile(strTpl) { var fn = new Function('viewData, escape', "var _view = []; function print() { _view.push.apply(_view, arguments); } with (viewData) { _view.push('" + String(strTpl).replace(/(?:^|%>)[\s\S]+?(?:$|<%)/g, function($0) { return $0 .split('\\').join('\\\\') .split("'").join("\\'") .split('\r').join('\\r') .split('\n').join('\\n'); }) .replace(/<%=([\s\S]+?)%>/g, "', $1, '") .replace(/<%:([\s\S]+?)%>/g, "', escape([$1].join('')), '") .split('<%').join("'); ") .split('%>').join("; _view.push('") + "'); } return _view;"); return function(viewData, escape) { return fn.call(this, viewData || {}, escape || escapeHtml).join(''); }; } exports.compile = compile; })(); Понимает вставки <% code %>, <%= val %>, <%: val %>. В последней подставляемое значение пропускается по умолчанию через escapeHtml, можно использовать свою функцию отправляя ее вторым аргументом: function myEscape(str) { return str.replace(/5/g, '[5]'); } alert( compile('<html><body><%:x%></body></html>')({x: 12589546}, myEscape) );// <html><body>12[5]89[5]46</body></html> Критика, вопросы и т. д., прошу :) . |
Что будет, если в шаблоне заюзать не переданную переменную? Что будет, если заюзать не переданную пременную, но случайно есть такое же свойство у window? Хотя второй вопрос про браузерный JS.
Это всё последствия использования with. Я ушёл от него к использованию this при обращении к переданным переменным, т.е. шаблону не передаётся объект с данными, а шаблон вызывается в контексте объекта с данными. |
Цитата:
Что касается выбора между viewData и this, я сам долго присматривался к this на эту роль, но потом мыслил так: шаблон - это в некотором смысле обычная функция (после "компиляции" вообще так и есть), такой более удобный способ записи функций определенного типа, и если обычную функцию можно запустить в любом контексте, то чем хуже шаблон? Именно поэтому fn запускается через call - перебрасывается контекст. Да я понимаю, что аргумент не очень, но и контраргументы тоже слабые: this короче, автокомплит полностью решает проблему, ну и свойства viewData в viewData быть не должно. Так же на выбор повлиял ASP MVC Framework, там тоже есть viewData и свойства класса отвечающего за страницу можно использовать как переменные в шаблоне, правда там viewData.x !== x , а у меня они равны. Оттуда же экранирующие вставки, но там, кажется, нет возможности свой escape поставить, точно не помню про это. Для полноты картины можно еще сделать вставки для подгрузки подшаблонов <%@filename%>, но это уже надо делать на уровне функции load, сам compile никакими загрузками заниматься не должен, как-то так (не запускал): var cache = {}; var fs = require('fs'); function load(filename) { if (filename in cache) { return cache[filename]; } var strTpl = fs.readFileSync(filename, 'utf8'); strTpl = strTpl.replace(/<%@([\s\S]+?)%>/g, function($0, $1) { return load($1); }); return cache[filename] = compile(strTpl); } exports.load = load; function clearCache() { cache = {}; } exports.clearCache = clearCache; Kolyaj, а вот этот кусок: Цитата:
|
Цитата:
Цитата:
|
Цитата:
Цитата:
|
Болезнь таких компиляторов.
console.log(compile("<html><b><% _view = []; _view.push = function() { console.log(\"BWA-HA-HA-HA\"); }; %></b></html>")()); |
console.log(compile('<html><b><% _view = []; _view.push = function() { console.log("Like I care..."); }; %></b></html>')()); а каким должен быть шаблонизатор? |
Цитата:
Моё кунг-фу сильнее :) |
Цитата:
while (true) {} это теперь болезнь javascript-а? И в шаблоне я могу так написать, это тоже будем лечить? Я видел шаблонизатор, где пытались (во многом успешно) лечить многие такие болезни, но зачем? Как я писал выше, шаблон удобно воспринимать как функцию (по сути, так и есть), записываемую по немного другим правилам. В этой функции объявлен "print" (и "_view", и еще что-то), если я в обычной функции переопределю его, он начнет вести себя по-другому, это нормально, и в шаблоне это нормально. Я не хочу чтобы шаблонизатор лишал меня возможности совершать глупости - ограничивал меня. Я хочу иметь возможность совершать глупости :) . В общем, на мой взгляд, это хорошая болезнь. |
Я хочу использовать _view у себя в шаблоне.
|
Часовой пояс GMT +3, время: 20:26. |