powered by simpleCommunicator - 2.0.28     © 2024 Programmizd 02
Map
Форумы / Серверный JavaScript (Node.js, Ringo, Nitro, Sling) [игнор отключен] [закрыт для гостей] / Node.js нативный шаблонизатор
3 сообщений из 3, страница 1 из 1
Node.js нативный шаблонизатор
    #38054143
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Собственно я написал, вы покритикуйте, что-нибудь посоветуйте.

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

Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
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
Код: html
1.
2.
3.
<%= fetchHeader(vars) %>
<p>Hello, <%= name %></p>
<%= fetchFooter() %>



views/header.htm
Код: html
1.
2.
3.
4.
5.
6.
7.
<!DOCTYPE html>
<html>
    <head>
        <title><%= title %></title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>



views/footer.htm
Код: html
1.
2.
    </body>
</html>



native-template.js
Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
// http://ejohn.org/blog/javascript-micro-templating/ идею отсюда позаимствовал
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', 'vars=vars||{};var out="";with(vars){' + 
            compiled + '};return out')(obj);
    }
}
...
Рейтинг: 0 / 0
Node.js нативный шаблонизатор
    #38057011
Няша ррр
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
up

Короче я долго эксперементировал с этой асинхронностью и понял что она:
а) усложняет читаемость кода(многочисленные вложенные функции)
б) мало того поощряет копипаст

я не смог сделать в шаблонизаторе все асинхронно казалось бы простые действия:
1. проверяем есть ли файл в кэше
2. если есть проверяем время модификации и сравниваемсо временем когда шаблон был скомпилирован
3. если в кэше нет, либо файл был модифицирован парсим
4. собственно выполняем скомпилированный код
все просто, если делать на каком нить руби, пистоне или пыхе, а если асинхронно то получается вонючая куча

вот мой вариант

Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
var fs = require('fs');
var OPEN_TAG = '<%';
var CLOSING_TAG = '%>';
var cache = {};

function compile(source) {
    var compiled = [],
        startPos = 0,
        endPos,
        match;

    while (true) {
        endPos = source.indexOf(OPEN_TAG, startPos);

        if (endPos == -1) {
            endPos = source.length;
        }

        if (startPos < endPos) {
            compiled.push('out+=' + JSON.stringify(source.slice(startPos, endPos)));
        }

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

        startPos = endPos + OPEN_TAG.length;
        endPos = source.indexOf(CLOSING_TAG, startPos);

        if (endPos == -1) {
            endPos = source.length;
        }

        match = source.slice(startPos, endPos);
        compiled.push(match[0] == '=' ? 'out+=' + match.slice(1) : match);
        startPos = endPos + CLOSING_TAG.length;

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

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

    return compiled.join(';');
}

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

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

require('http').ServerResponse.prototype.render = function(filename, context) {
    this.end(template(filename, context));
}



Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
var template = require('./template');
var session = new cookie.Session(SESSION_NAME, SESSION_LIFETIME);

var routes = {
    GET: [
        ['/', function(rq, rs) {
            session.start();

            var ctxt = {
                __: template,
                title: 'Главная',
                content: 'Привет, мир!'
            }

            rs.writeHead(202, {'content-type': 'text/html; charset=utf-8'});
            rs.render('templates/layot.htm', ctxt);
        }],



а вот шаблон, можно использовать полноценный синтаксис javascript

Код: html
1.
2.
3.
4.
5.
6.
<%= __('templates/header.htm', context) %>
        <div class="container">
            <h1 class="title"><%= title %></h1>
            <div class="content"><%= content %></div>
        </div>
<%= __('templates/footer.htm') %>



такой хтмл генерится

Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
<!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>
...
Рейтинг: 0 / 0
Node.js нативный шаблонизатор
    #38059005
private
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот пишут такой код
Код: javascript
1.
... readFileSync ...

и потом удивляются почему нода на тестах показывает не быстрее питона или руби :D

Модератор: Тема перенесена из форума "HTML, JavaScript, VBScript, CSS".
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Серверный JavaScript (Node.js, Ringo, Nitro, Sling) [игнор отключен] [закрыт для гостей] / Node.js нативный шаблонизатор
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]