Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 08.10.2011, 07:33
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Простой компилятор шаблонов для NodeJS
/**
 * Id: template
 * */

(function() {

function escapeHtml(str) {
	return str
		.replace(/&/g, '&')
		.replace(/</g, '&lt;')
		.replace(/>/g, '&gt;')
		.replace(/"/g, '&quot;')
		.replace(/'/g, '&apos;');
}

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>


Критика, вопросы и т. д., прошу .

Последний раз редактировалось Riim, 08.10.2011 в 08:07.
Ответить с цитированием
  #2 (permalink)  
Старый 08.10.2011, 09:08
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Что будет, если в шаблоне заюзать не переданную переменную? Что будет, если заюзать не переданную пременную, но случайно есть такое же свойство у window? Хотя второй вопрос про браузерный JS.

Это всё последствия использования with. Я ушёл от него к использованию this при обращении к переданным переменным, т.е. шаблону не передаётся объект с данными, а шаблон вызывается в контексте объекта с данными.
Ответить с цитированием
  #3 (permalink)  
Старый 08.10.2011, 19:32
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Kolyaj
Это всё последствия использования with. Я ушёл от него к использованию this при обращении к переданным переменным, т.е. шаблону не передаётся объект с данными, а шаблон вызывается в контексте объекта с данными.
тут не в with проблема, он никак не мешает использовать this, так как ты его используешь, но при нем уже есть выбор: если переменная обязательна в шаблоне, вплоть до того, что даже хорошо, что происходит ошибка при ее отсутствии, тогда пишем без this (пишем так в шаблоне не ради ошибки, а потому что точно уверены, что переменная есть), а через 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, а вот этот кусок:
Сообщение от Riim
[$1].join('')
сразу понятно зачем он?
Ответить с цитированием
  #4 (permalink)  
Старый 08.10.2011, 19:36
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от Riim
но при нем уже есть выбор: если переменная обязательна в шаблоне, вплоть до того, что даже хорошо, что происходит ошибка при ее отсутствии, тогда пишем без this (пишем так в шаблоне не ради ошибки, а потому что точно уверены, что переменная есть), а через this обращаемся уже к необязательным переменным.
Выбор почти всегда плохо. А если обязательная переменная стала необязательной? Весь шаблон перепахиваем? А если опять обязательной стала? Опять перепахиваем?


Сообщение от Riim
сразу понятно зачем он?
join такая хорошая функция, она null и undefined пустой строкой считает. То что надо для шаблонов.
Ответить с цитированием
  #5 (permalink)  
Старый 08.10.2011, 19:45
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Kolyaj
Выбор почти всегда плохо. А если обязательная переменная стала необязательной? Весь шаблон перепахиваем? А если опять обязательной стала? Опять перепахиваем?
даже при этом он не мешает уже всегда через this писать. В общем, со временем видно будет, убрать with всегда успею.


Сообщение от Kolyaj
join такая хорошая функция, она null и undefined пустой строкой считает. То что надо для шаблонов.
супер , а то я думал кто-нибудь спросит что за фигню наворотил.

Последний раз редактировалось Riim, 08.10.2011 в 19:50.
Ответить с цитированием
  #6 (permalink)  
Старый 12.10.2011, 23:05
Отправить личное сообщение для Андрей Параничев Посмотреть профиль Найти все сообщения от Андрей Параничев
 
Регистрация: 21.02.2008
Сообщений: 1,250

Болезнь таких компиляторов.
console.log(compile("<html><b><% _view = []; _view.push = function() { console.log(\"BWA-HA-HA-HA\"); }; %></b></html>")());
Ответить с цитированием
  #7 (permalink)  
Старый 13.10.2011, 01:53
Аватар для x-yuri
Отправить личное сообщение для x-yuri Посмотреть профиль Найти все сообщения от x-yuri
 
Регистрация: 27.12.2008
Сообщений: 4,201

console.log(compile('<html><b><% _view = []; _view.push = function() { console.log("Like I care..."); }; %></b></html>')());

а каким должен быть шаблонизатор?
Ответить с цитированием
  #8 (permalink)  
Старый 13.10.2011, 12:22
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от Андрей Параничев
Болезнь таких компиляторов.
https://github.com/Kolyaj/CrossJS/bl...String.js#L387
Моё кунг-фу сильнее
Ответить с цитированием
  #9 (permalink)  
Старый 15.10.2011, 12:39
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Андрей Параничев
Болезнь таких компиляторов.
не совсем согласен. Вот, например, в javascript-е я могу написать так:
while (true) {}

это теперь болезнь javascript-а? И в шаблоне я могу так написать, это тоже будем лечить? Я видел шаблонизатор, где пытались (во многом успешно) лечить многие такие болезни, но зачем? Как я писал выше, шаблон удобно воспринимать как функцию (по сути, так и есть), записываемую по немного другим правилам. В этой функции объявлен "print" (и "_view", и еще что-то), если я в обычной функции переопределю его, он начнет вести себя по-другому, это нормально, и в шаблоне это нормально. Я не хочу чтобы шаблонизатор лишал меня возможности совершать глупости - ограничивал меня. Я хочу иметь возможность совершать глупости .

В общем, на мой взгляд, это хорошая болезнь.

Последний раз редактировалось Riim, 15.10.2011 в 13:01.
Ответить с цитированием
  #10 (permalink)  
Старый 18.10.2011, 03:41
Отправить личное сообщение для Андрей Параничев Посмотреть профиль Найти все сообщения от Андрей Параничев
 
Регистрация: 21.02.2008
Сообщений: 1,250

Я хочу использовать _view у себя в шаблоне.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Решение проблемы кодировок для AJAX и PHP без iconv (cp1251 в AJAX) Serge Ageyev AJAX и COMET 10 24.04.2013 20:48
Новая система управления сайтом Scripto CMS deepslam Ваши сайты и скрипты 38 31.01.2011 14:55
Comet: NodeJS - с чего начать разработку? Vulkan AJAX и COMET 13 27.11.2010 19:25
простой show/hide для контента M.C. Элементы интерфейса 44 17.01.2009 19:29