Comparing version 0.0.6 to 0.0.7
122
index.js
@@ -12,11 +12,5 @@ /** | ||
/** | ||
* Creates an odesza object. | ||
* | ||
* @param {Object} context Initial context | ||
* @return {Object} | ||
*/ | ||
var odesza = {}; | ||
module.exports = odesza; | ||
var blocks = {}; | ||
var keywords = ['extends', 'block', 'include']; | ||
@@ -29,4 +23,4 @@ /** | ||
* variables to be used in the template. | ||
* @param {string} [basePath] Optional. The base path to use for import and | ||
* require statements. | ||
* @param {string} [basePath] Optional. The base path to use if extend or | ||
* include statements are present. | ||
* @return {string} The rendered template. | ||
@@ -39,15 +33,47 @@ */ | ||
// matches import(''), import(""), require(''), require("") | ||
var rgx = /(import|require)\([\'\"]([\w.\/]+)[\'\"]\)/g; | ||
var matches = template.match(rgx) || []; | ||
var s = statements(template); | ||
// make matches array values unique | ||
var imports = matches.filter((m, i) => matches.indexOf(m) == i); | ||
// if an extend statement is found, fill the extended template blocks in | ||
if (s.extend.length) { | ||
// only allow one extend statement | ||
if (s.extend.length > 1) { | ||
throw new Error('An odesza template can only extend one file'); | ||
} | ||
// loop over block statements, putting them into memory | ||
s.blocks.forEach(block => { | ||
// if the block is in memory, this means there is multiple inheritence, | ||
// i.e. this has already extended | ||
if (blocks[block] != null) return; | ||
let start = template.indexOf(block) + block.length; | ||
let end = template.indexOf(block.replace('block', 'end')); | ||
if (end == -1) { | ||
throw new Error(`end statement required after ${block}`); | ||
} | ||
blocks[block] = template.substr(start, end - start).trim(); | ||
}); | ||
let path = `${basePath}${s.extend[0].split('\'')[1]}`; | ||
template = odesza.compile(path, options); | ||
s = statements(template); | ||
} else { | ||
s.blocks.forEach(block => { | ||
if (blocks[block] != null) { | ||
template = template.split(block).join(blocks[block]); | ||
delete blocks[block]; | ||
} else { | ||
// if not in memory, it is a block statement that can be ignored | ||
template = template.split(block).join(''); | ||
} | ||
}); | ||
} | ||
// recursively replace each import statement with its compiled template | ||
imports.forEach(statement => { | ||
let path = basePath + statement.split('\'')[1]; | ||
template = template | ||
.split(statement) | ||
.join(odesza.compile(path, options)); | ||
s.includes.forEach(statement => { | ||
let path = `${basePath}${statement.split('\'')[1]}`; | ||
template = template.split(statement).join(odesza.compile(path, options)); | ||
}); | ||
@@ -71,8 +97,3 @@ | ||
odesza.compile = function(path, options) { | ||
if (typeof path != 'string') { | ||
throw new TypeError('path must be a string'); | ||
} | ||
if (path.indexOf('.') == -1) { | ||
path += '.odesza'; | ||
} | ||
path = resolve(path); | ||
try { | ||
@@ -88,18 +109,2 @@ var basePath = path.substr(0, path.lastIndexOf('/') + 1); | ||
/** | ||
* Install plugin. | ||
* | ||
* @param {Function} fn Middlware | ||
* @return {Object} odesza | ||
*/ | ||
odesza.use = function(fn) { | ||
if ('function' == typeof fn) { | ||
odesza.middleware.push(fn); | ||
} else { | ||
throw new TypeError('Middleware must provide a function.') | ||
} | ||
return this; | ||
}; | ||
/** | ||
* Adds support for express. | ||
@@ -119,1 +124,34 @@ * | ||
}; | ||
// matches keyword statements | ||
const rstr = `(${keywords.join('|')})\\([\\\'\\\"]([\\w.\\/]+)[\\\'\\\"]\\)`; | ||
const keyWordsRegex = new RegExp(rstr, 'g'); | ||
// extracts statements from template | ||
const statements = template => { | ||
var statements = {}; | ||
var m = template.match(keyWordsRegex) || []; | ||
statements.extend = m.filter(s => s.indexOf('extend') == 0); | ||
statements.blocks = m.filter(s => s.indexOf('block') == 0); | ||
statements.includes = m.filter(s => s.indexOf('include') == 0); | ||
return statements; | ||
}; | ||
// resolves the template file path, throwing an error if anything is wrong | ||
const resolve = path => { | ||
if (typeof path != 'string') { | ||
throw new TypeError('path must be a string'); | ||
} | ||
if (!fs.existsSync(path)) { | ||
if (fs.existsSync(`${path}.ode`)) { | ||
path += '.ode'; | ||
} else if (fs.existsSync(`${path}.odesza`)) { | ||
path += '.odesza'; | ||
} else { | ||
throw new Error(`cannot find file with path: ${path}`); | ||
} | ||
} | ||
return path; | ||
}; | ||
module.exports = odesza; |
{ | ||
"name": "odesza", | ||
"version": "0.0.6", | ||
"description": "The most straightforward template engine for JavaScript, using ES6 template string syntax.", | ||
"version": "0.0.7", | ||
"description": "Write clean, expressive templates with just HTML and inline JavaScript", | ||
"main": "index.js", | ||
"author": "Wells Johnston", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/littlstar/odesza" | ||
}, | ||
"scripts": { | ||
@@ -9,0 +13,0 @@ "test": "node test" |
@@ -1,20 +0,42 @@ | ||
# odesza | ||
# Odesza | ||
*odesza* allows you to write clean, familiar-looking templates using plain HTML and JavaScript. Under the hood, content is rendered as ES6 template strings, which allows you to write native JS inline with your HTML. Odesza supports Express out of the box. | ||
**Odesza** allows you to write clean, expressive templates with just HTML and inline JavaScript without any learning curve. | ||
It offers | ||
- multiple inheritence | ||
- fully expressive inline JavaScript | ||
- native support for Express framework | ||
- no magic, 0 dependencies, and just 150 lines of code | ||
It does NOT offer | ||
- HTML shorthand | ||
- special functions | ||
##Install | ||
``` | ||
npm install odesza --save | ||
``` | ||
##Render | ||
```javascript | ||
var odesza = require('odesza'); | ||
var options = { | ||
var vars = { | ||
name: 'world' | ||
}; | ||
odesza.render('hello ${name}!', options); // hello world! | ||
odesza.render('hello ${name}!', vars); // hello world! | ||
``` | ||
##Compile | ||
Compile odesza files. Odesza first tries the literal path given, then *.ode*, then *.odesza*. | ||
##Install | ||
*index.odesza* | ||
``` | ||
npm install odesza --save | ||
hello ${name}! | ||
``` | ||
##Express Support | ||
```javascript | ||
var odesza = require('odesza'); | ||
var vars = { | ||
name: 'world' | ||
}; | ||
odesza.compile('index', vars); // hello world! | ||
``` | ||
##Express | ||
server.js | ||
@@ -21,0 +43,0 @@ ```javascript |
@@ -8,4 +8,2 @@ 'use strict'; | ||
const fs = require('fs'); | ||
const read = file => fs.readFileSync(file, 'utf-8'); | ||
const fixture = file => path.join(__dirname, 'fixtures', file); | ||
@@ -16,3 +14,3 @@ | ||
let string = odesza.render('hello ${value}', vars); | ||
t.ok(string == 'hello world', 'template renders') | ||
t.ok(string == 'hello world', 'template strings render') | ||
t.end(); | ||
@@ -23,26 +21,65 @@ }); | ||
let vars = { value: 'world' }; | ||
let string = odesza.compile(fixture('simple.txt'), vars); | ||
t.ok(string == 'hello world', 'template compiles'); | ||
let string = odesza.compile(fixture('simple'), vars); | ||
t.ok(string == 'hello world', 'template files compile'); | ||
t.end(); | ||
}); | ||
test('import', t => { | ||
test('file with variables', t => { | ||
let vars = { name : 'yo' }; | ||
let string = odesza.compile(fixture('message1'), vars); | ||
t.ok(string == 'yo1', 'import statement works'); | ||
let string = odesza.compile(fixture('messages/message1'), vars); | ||
console.log(string); | ||
t.ok(string == 'hello yo!', 'variables work'); | ||
t.end(); | ||
}); | ||
test('recursive imports', t => { | ||
test('include single file', t => { | ||
let vars = { name: 'yo' }; | ||
let string = odesza.compile(fixture('message3.txt'), vars); | ||
t.ok(string == 'yo3yo1', 'recursive import statements'); | ||
let string = odesza.compile(fixture('messages/message3'), vars); | ||
t.ok(string == 'yo3hello yo!', 'single file was included'); | ||
t.end(); | ||
}); | ||
test('multiple import statements', t => { | ||
test('multiple recursive include statements', t => { | ||
let vars = { name: 'yo' }; | ||
let string = odesza.compile(fixture('messages.txt'), vars); | ||
t.ok(string == 'yo1yo2yo3yo1', 'multiple import statements'); | ||
let string = odesza.compile(fixture('includes'), vars); | ||
console.log(string); | ||
t.ok(string == 'hello yo!yo2yo3hello yo!', 'multiple files were included recursively'); | ||
t.end(); | ||
}); | ||
test('extend with block statement', t => { | ||
let vars = { | ||
title: 'hello world', | ||
name: 'world', | ||
basePath: '/public/js/' | ||
}; | ||
let template = odesza.compile(fixture('content.odesza'), vars).split('\n').join('').trim(); | ||
var answer = fs.readFileSync(fixture('answers/complex_answer1')).toString().trim(); | ||
t.ok(template == answer, 'extended template with block statement'); | ||
t.end(); | ||
}); | ||
test('multiple inheritence by chaining extends', t => { | ||
let vars = { | ||
title: 'hello world', | ||
name: 'world', | ||
basePath: '/public/js/' | ||
}; | ||
let template = odesza.compile(fixture('extend_content.odesza'), vars).split('\n').join('').trim(); | ||
var answer = fs.readFileSync(fixture('answers/complex_answer2')).toString().trim(); | ||
t.ok(template == answer, 'multiple inheritence with extends'); | ||
t.end(); | ||
}); | ||
test('list content using native array methods', t => { | ||
let names = ['wells', 'joe', 'dom']; | ||
let vars = { | ||
title: 'world', | ||
names: names, | ||
basePath: 'public/js/' | ||
}; | ||
let template = odesza.compile(fixture('complex_functions'), vars).split('\n').join('').trim(); | ||
var answer = fs.readFileSync(fixture('answers/complex_answer3')).toString().trim(); | ||
t.ok(template == answer, 'complex js functions work inline') | ||
t.end(); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
10740
19
200
46
3