Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tasogarepg committed Feb 3, 2012
0 parents commit 971718f
Show file tree
Hide file tree
Showing 6 changed files with 438 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .gitignore
@@ -0,0 +1,13 @@
# common
.DS_Store

# backup
*~
*.bak

# IDE
.project
.settings

# Node.js
node_modules
77 changes: 77 additions & 0 deletions README.md
@@ -0,0 +1,77 @@
# node-pages

A simple template engine.
Cacheable and Trackable.
You can make breakpoints on the debugger.

## Installation

$ npm install node-pages

## Example
template1.npg

<? if (arg) { ?>
<p><?= arg.name ?></p>
<? } ?>

example.js

var pages = require('node-pages').newInstance({
srcPath : '/path/to/template1.npg';
});

var arg = {name : 'tasogare'};
var str = pages.render(arg);

## Custom tags

Custom tags (e.g. &lt;% %&gt; )

var pages = require('node-pages').newInstance({
openWord : '<%',
closeWord : '%>',
srcPath : '/path/to/template2.npg';
});

template2.npg

<% if (arg) { %>
<p><%= arg.name %></p>
<% } %>

## Custom render arg name

Custom render arg name (e.g. it )

var pages = require('node-pages').newInstance({
renderArgName : 'it',
srcPath : '/path/to/template3.npg';
});

var arg = {name : 'tasogare'};
var str = pages.render(arg);

template3.npg

<? if (it) { ?>
<p><?= it.name ?></p>
<? } ?>


## Html escaped and unescaped

* Escaped with `<?= val ?>`
* Unescaped with `<?- val ?>`

## Options

- `srcPath` Template file path (absolute path)
- `openWord` Open tag. ("<?" is default.)
- `closeWord` Close tag. ("?>" is default.)
- `renderArgName` Render arg name. ("arg" is default.)
- `workDir` Directory of compiled js file. ("node-pages/lib/work" is default.)

## License

The MIT License
164 changes: 164 additions & 0 deletions lib/node-pages.js
@@ -0,0 +1,164 @@
'use strict';
var fs = require('fs');
var path = require('path');

module.exports = Pages;

function Pages(conf) {
conf = conf || {};

this.openWord = conf.openWord || Pages.DEFAULT_OPEN_WORD;
this.closeWord = conf.closeWord || Pages.DEFAULT_CLOSE_WORD;
this.renderArgName = conf.renderArgName || Pages.DEFAULT_RENDER_ARG_NAME;
this.workDir = conf.workDir || Pages.DEFAULT_WORK_DIR;
this.srcPath = null;
this.dstPath = null;
this.name = null;

if (conf.srcPath) {
this.loadFileSync(conf.srcPath);
}
}

Pages.newInstance = function(conf) {
return new Pages(conf);
};

Pages.DEFAULT_OPEN_WORD = '<?';
Pages.DEFAULT_CLOSE_WORD = '?>';
Pages.DEFAULT_RENDER_ARG_NAME = 'arg';
Pages.DEFAULT_WORK_DIR = path.join(__dirname, 'work');
Pages.cache = [];

Pages.prototype.reloadFileSync = function() {
if (!this.srcPath) return;
this.clear();
this.loadFileSync(this.srcPath);
};

Pages.prototype.clear = function() {
this.deleteCache();
this.deleteModule();
};

Pages.prototype.loadFileSync = function(srcPath) {
if (!srcPath) return;
this.srcPath = require.resolve(srcPath);
this.name = this.makeName(this.srcPath);
this.dstPath = this.makeDstPath(this.workDir, this.name);
if (this.isCached()) return;
this.setCache(
this.setModuleSync(
this.createJsFileSync(
this.parse(
stripBOM(fs.readFileSync(this.srcPath, 'utf8'))))));
};

Pages.prototype.makeName = function(filePath) {
return filePath && String(filePath).
replace(/[\/\\]/g, '__').
replace(/[\.:]/g, '-');
};

Pages.prototype.makeDstPath = function(workDir, name) {
return path.join(workDir, name) + '.js';
};

Pages.prototype.setCache = function(mdl, name) {
name = name || this.name;
if (name && mdl && mdl.render) {
Pages.cache[name] = mdl.render;
}
};

Pages.prototype.deleteCache = function(name) {
name = name || this.name;
if (name && Pages.cache[name]) {
delete Pages.cache[name];
}
};

Pages.prototype.isCached = function(name) {
name = name || this.name;
return !!Pages.cache[name];
};

Pages.prototype.setModuleSync = function(filePath) {
filePath = filePath || this.dstPath;
var mdl = null;
try {
mdl = require(filePath);
} catch(e) {
throw new Error(filePath + "\n" + e.stack);
}
return mdl;
};

Pages.prototype.deleteModule = function(filePath) {
filePath = filePath || this.dstPath;
if (filePath && require.cache[filePath]) {
delete require.cache[filePath];
}
};

Pages.prototype.createJsFileSync = function(buf, name, workDir) {
name = name || this.name;
workDir = workDir || this.workDir;
if (!fs.existsSync(workDir)) {
fs.mkdirSync(workDir, parseInt('755', 8));
}
var filePath = this.makeDstPath(workDir, name);
fs.writeFileSync(filePath, buf);
return filePath;
};

Pages.prototype.parse = function(src) {
src = this.closeWord + src + this.openWord;

var buf = "exports.render = function(" + this.renderArgName + "){\n var renderStr = '';\n";
for (var i=0, len=src.length; i<len;) {
var start, end, str;
start = src.indexOf(this.closeWord, i) + this.closeWord.length;
end = src.indexOf(this.openWord, start);
if (end == -1) break;
str = src.substring(start, end).
replace(/\\/g, '\\\\').
replace(/'/g, "\\'").
replace(/\t/g, ' ').
replace(/\r/g, '').
replace(/\n/g, '\\n');
buf += " renderStr += '" + str + "';\n";

start = end + this.openWord.length;
end = src.indexOf(this.closeWord, start);
if (end == -1) break;
str = src.substring(start, end);
switch (str.substring(0, 1)) {
case '-':
str = str.substring(1);
buf += " renderStr += " + str + ";\n";
break;
case '=':
str = str.substring(1);
buf += " renderStr += escape(" + str + ");\n";
break;
default:
buf += str + "\n";
}
i = end;
}
buf += " return renderStr;\n};\n";
buf += "function escape(str){\n" +
" return str && str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n" +
"}\n";
return buf;
};

Pages.prototype.render = function(arg) {
var func = Pages.cache[this.name];
return func ? func(arg) : '';
};

function stripBOM(dat) {
return (dat.charCodeAt(0) === 0xFEFF) ? dat.slice(1) : dat;
}
13 changes: 13 additions & 0 deletions package.json
@@ -0,0 +1,13 @@
{
"name": "node-pages",
"version": "0.1.0",
"description": "A simple template engine. Cacheable and Trackable.",
"keywords": ["template", "view"],
"author": "tasogarepg <tasogare.pg@gmail.com>",
"main": "./lib/node-pages.js",
"engines": { "node": ">= 0.7.1 < 0.8.0" },
"dependencies": {},
"devDependencies": {
"mocha": "*"
}
}
3 changes: 3 additions & 0 deletions test/mocha.opts
@@ -0,0 +1,3 @@
--ui bdd
--reporter spec
--timeout 5000

0 comments on commit 971718f

Please sign in to comment.