Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 27.11.2012, 01:33
Профессор
Посмотреть профиль Найти все сообщения от Антон Крамолов
 
Регистрация: 11.04.2012
Сообщений: 255

Нативный шаблонизатор
Собственно я написал, вы покритикуйте, что-нибудь посоветуйте.

Использование.

var nt = require('./native-template');
var session = new cookie.Session(SESSION_NAME, SESSION_LIFETIME);

fetchHeader = nt.render('views/header.htm');
fetchFooter = nt.render('views/footer.htm');
var homeView = nt.render('views/home.htm');

var routes = {
    GET: [
        ['/', function(rq, rs) {
            session.start();           
            rs.writeHead(202, {'content-type': 'text/html; charset=utf-8'});
            rs.end( homeView({title: 'Main', name: 'world'}) );
        }],

        ['/index.htm', function(rq, rs) {
            rs.writeHead(302, {location: '/'})
            rs.end();
        }],

        ['/cookie.htm', function(rq, rs) {
            session.start();
            rs.end(JSON.stringify(rq.cookie));
        }]
    ],

    POST: []
};


Шаблоны

views/home.htm
<%= fetchHeader(vars) %>
<p>Hello, <%= name %></p>
<%= fetchFooter({}) %>


views/header.htm
<!DOCTYPE html>
<html>
    <head>
        <title><%= title %></title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>


views/footer.htm
</body>
</html>


native-template.js
// [url]http://ejohn.org/blog/javascript-micro-templating/[/url] идею отсюда позаимствовал
var fs = require('fs');
var OPEN_TAG = '<%';
var CLOSING_TAG = '%>';
var cache = {};

function compile(input) {
    var output = '';
    var startPos = 0;
    var endPos;
    var data;

    while (true) {
        endPos = input.indexOf(OPEN_TAG, startPos);
        endPos = (endPos > -1) ? endPos : input.length;

        if (startPos < endPos) {
            output += 'out+="' + input.slice(startPos, endPos).replace(/\r/g, '\\r').
                      replace(/\n/g, '\\n').replace(/"/g, '\\"') + '"\n';
        }

        if (endPos == input.length) {
            break;
        }

        startPos = endPos + OPEN_TAG.length;
        endPos = input.indexOf(CLOSING_TAG, startPos);
        endPos = (endPos < 0) ? input.length : endPos;
        data = input.slice(startPos, endPos);
        output += ((data[0] == '=') ? 'out+=' + data.slice(1) : data) + '\n';
        startPos = endPos + CLOSING_TAG.length;

        if (input[startPos] == '\r') {
            ++startPos;
        }

        if (input[startPos] == '\n') {
            ++startPos;
        }
    }

    return output;
}

exports.render = function(filename) {
    var source = fs.readFileSync(filename, 'utf-8');
    var compiled = compile(source);

    return function(obj) {
        return new Function('vars', 'var out=""\nwith(vars){' + 
            compiled + '}\nreturn out')(obj);
    }
}
Ответить с цитированием
  #2 (permalink)  
Старый 27.11.2012, 01:43
Профессор
Посмотреть профиль Найти все сообщения от Антон Крамолов
 
Регистрация: 11.04.2012
Сообщений: 255

Очевидный фикс:
exports.render = function(filename) {
    var source = fs.readFileSync(filename, 'utf-8');
    var compiled = compile(source);

    return function(obj) {
        return new Function('vars', 'vars=vars||{};var out="";with(vars){' + 
            compiled + '};return out')(obj);
    }
}
Ответить с цитированием
  #3 (permalink)  
Старый 27.11.2012, 02:28
Профессор
Посмотреть профиль Найти все сообщения от Антон Крамолов
 
Регистрация: 11.04.2012
Сообщений: 255

с диска только раз читает
var homeView = nt.render('views/home.htm');

exports.render = function(filename) {
    var source = fs.readFileSync(filename, 'utf-8');
    // вот схоронили в "кеше"
    var compiled = compile(source);

    return function(obj) {
        return new Function('vars', 'vars=vars||{};var out="";with(vars){' + 
            compiled + '};return out')(obj);
    }
}
Ответить с цитированием
  #4 (permalink)  
Старый 27.11.2012, 11:42
Профессор
Посмотреть профиль Найти все сообщения от Антон Крамолов
 
Регистрация: 11.04.2012
Сообщений: 255

exports.render = function(filename) {
    var source = fs.readFileSync(filename, 'utf-8');
    var compiled = compile(source);
    var time = new Date().getTime();

    return function(obj) {
        fs.stat(filename, function(err, stat) {
            if (err) {
                throw new Error(err);
            }
            
            if (new Date(stat.mtime).getTime() > time) {
                fs.readFile(filename, 'utf-8', function(err, data) {
                    if (err) {
                        throw new Error(err);
                    }
                    
                    compiled = compile(data);
                    time = new Date().getTime();
                    console.log('file was changed');
                });
            }
        });
    
        // console.log(compiled);
        return new Function('vars', 'vars=vars||{};var out="";with(vars){' + 
            compiled + '};return out')(obj);
    }
}


Вот обновляются но в последующий раз с этой конченной ассинхронностью какая-то хрень получается. если синхронно сделать, то все будет норм, при изменении шаблона все тут же будет отображаться, а ассинхронно как сделать не представляю(ну вот вариант привел, если чото изменяешь, то сначала из кэша, потом показывается уже измененный вариант)
Ответить с цитированием
  #5 (permalink)  
Старый 28.11.2012, 12:15
Аватар для keen
Профессор
Отправить личное сообщение для keen Посмотреть профиль Найти все сообщения от keen
 
Регистрация: 28.03.2012
Сообщений: 376

а смысл сюда выкладывать-то? почитай топики, тут народ про аякс не знает, а ты вон чо пишешь.
впрочем, и на хабр тоже - очередной шаблонизатор и велосипедостроение там вряд ли найдут понимание.
Ответить с цитированием
  #6 (permalink)  
Старый 28.11.2012, 16:44
Профессор
Посмотреть профиль Найти все сообщения от Антон Крамолов
 
Регистрация: 11.04.2012
Сообщений: 255

Вообщем после долгих экспериментов как-то переписать все ассинхронно у меня не получилось. ассинхронный код - это вонючая куча из вложенных функций с callback'ами. Синхронный код прост и понятен, асинхронный же сплошь и рядом копипастинг

var KB = 1024;
var MB = 1048576;
var GB = 1073741824;
var SECOND = 1000;
var MINUTE = 60000;
var HOUR = 3600000;
var DAY = 86400000;
var WEEK = 604800000;
var MONTH = 2628000000;
var YEAR = 31536000000;
var ALLOWED_METHODS = ['GET', 'POST'];
var LISTEN_PORT = 8080;
var STATIC_FILES_DIRECTORY = './public';
var MAX_REQUEST_LENGTH = 4 * MB;
var SESSION_NAME = 'sess';
var SESSION_LIFETIME = 20 * MINUTE;
var http = require('http');
var fs = require('fs');
var qs = require('querystring');
var url = require('url');
var mime = require('./mime');
var cookie = require('./cookie');
var template = require('./template');
var session = new cookie.Session(SESSION_NAME, SESSION_LIFETIME);

var routes = {
    GET: [
        ['/', function(rq, rs) {
            session.start();           
            
            var ctxt = {
                'render': template.render, 
                'title': 'Главная',
                'content': 'Привет, мир!'
            }
            
            rs.writeHead(202, {'content-type': 'text/html; charset=utf-8'});
            rs.render('templates/layot.htm', ctxt);
        }],

        ['/index.htm', function(rq, rs) {
            rs.writeHead(302, {location: '/'})
            rs.end();
        }],

        ['/cookie.htm', function(rq, rs) {
            session.start();
            rs.end(JSON.stringify(rq.cookie));
        }]
    ],

    POST: []
};

// еще 200 строк кода пропущены


Модуль шаблонов

// [url]http://ejohn.org/blog/javascript-micro-templating/[/url] идею отсюда позаимствовал
var fs = require('fs');
var OPEN_TAG = '<%';
var CLOSING_TAG = '%>';
var cache = {/*[$compiled, $timestamp]*/};

function compile(s) {
    var c = [],
        p0 = 0,
        p1,
        m;

    while (true) {
        p1 = s.indexOf(OPEN_TAG, p0);

        if (p1 == -1) {
            p1 = s.length;
        }

        if (p0 < p1) {
            c.push('out+=' + JSON.stringify(s.slice(p0, p1)));
        }

        if (p1 == s.length) {
            break;
        }

        p0 = p1 + OPEN_TAG.length;
        p1 = s.indexOf(CLOSING_TAG, p0);

        if (p1 == -1) {
            p1 = s.length;
        }

        m = s.slice(p0, p1);
        c.push(m[0] == '=' ? 'out+=' + m.slice(1) : m);
        p0 = p1 + CLOSING_TAG.length;

        if (s[p0] == '\r') {
            ++p0;
        }

        if (s[p0] == '\n') {
            ++p0;
        }
    }

    return c.join(';');
}

var render = module.exports.render = function(fn, obj) {
    try {
        if (!cache[fn] || new Date(fs.statSync(fn).mtime).getTime() > cache[fn][1]) {
            cache[fn] = [
                compile(fs.readFileSync(fn, 'utf-8')), 
                new Date().getTime()
            ];
        }

        return new Function('context', 'var out="";with(context){' + cache[fn][0] + '}return out')(obj || {});
    } 
    catch (e) {
        console.log(e);
    }
}

require('http').ServerResponse.prototype.render = function(fn, obj) { 
    this.end(render(fn, obj));
}


Шаблоны все, которые использовал
<!DOCTYPE html>
<html>
    <head>
        <title><%= title %></title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>


</body>
</html>
HTML]

[HTML]
<%= render('templates/header.htm', context) %>
        <div class="container">
            <h1 class="title"><%= title %></h1>
            <div class="content"><%= content %></div>
        </div>
<%= render('templates/footer.htm') %>


На выходе
<!DOCTYPE html>
<html>
    <head>
        <title>Главная</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
        <div class="container">
            <h1 class="title">Главная</h1>
            <div class="content">Привет, мир!</div>
        </div>
    </body>
</html>


Содержимое кэша

{ 'templates/layot.htm': 
   [ 'out+= render(\'templates/header.htm\', context) ;out+="        <div class=\\"container\\">\\r\\n            <h1 class=\\"title\\">";out+= title ;out+="</h1>\\r\\n            <div class=\\"content\\">";out+= content ;out+="</div>\\r\\n        </div>\\r\\n";out+= render(\'templates/footer.htm\') ',
     1354106612748 ],
  'templates/header.htm': 
   [ 'out+="<!DOCTYPE html>\\r\\n<html>\\r\\n    <head>\\r\\n        <title>";out+= title ;out+="</title>\\r\\n        <meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=utf-8\\">\\r\\n    </head>\\r\\n    <body>\\r\\n"',
     1354106612748 ],
  'templates/footer.htm': [ 'out+="    </body>\\r\\n</html>\\r\\n"', 1354106612758 ] }
Ответить с цитированием
  #7 (permalink)  
Старый 28.11.2012, 17:06
Аватар для keen
Профессор
Отправить личное сообщение для keen Посмотреть профиль Найти все сообщения от keen
 
Регистрация: 28.03.2012
Сообщений: 376

Сообщение от Антон Крамолов Посмотреть сообщение
ассинхронный код - это вонючая куча из вложенных функций с callback'ами. Синхронный код прост и понятен, асинхронный же сплошь и рядом копипастинг
Ответить с цитированием
  #8 (permalink)  
Старый 28.11.2012, 17:15
Профессор
Посмотреть профиль Найти все сообщения от Антон Крамолов
 
Регистрация: 11.04.2012
Сообщений: 255

хорошо, перепиши этот код асинхронно
Ответить с цитированием
  #9 (permalink)  
Старый 28.11.2012, 17:18
Профессор
Посмотреть профиль Найти все сообщения от Антон Крамолов
 
Регистрация: 11.04.2012
Сообщений: 255

а на счет велосипедостроения. это насколько нужно быть дебилом с усохшими мозгами чтобы не уметь реализовать механизм сессии и т.д.. хотя есть программисты, есть кодеры. последние тупо кодомакаки, которым дай готовый API, фреймворк и они по примерам смогут что-то собрать...
Ответить с цитированием
  #10 (permalink)  
Старый 28.11.2012, 17:24
Аватар для keen
Профессор
Отправить личное сообщение для keen Посмотреть профиль Найти все сообщения от keen
 
Регистрация: 28.03.2012
Сообщений: 376

ты знаешь что такое уровни абстракций?)

и повторюсь: уметь реализовать != использовать самописные неконкурентоспособные библиотеки.

впрочем, после заявлений о том что express уг, как и асинхронный код в целом..

удачи.
Ответить с цитированием
Ответ



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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
JS шаблонизатор Andrei jQuery 9 07.11.2011 16:46
Extjs + шаблонизатор + фреймворк Sea ExtJS 1 24.09.2010 15:52