-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0f5d656
commit 47389fc
Showing
8 changed files
with
199 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* util for adding filters to Leopard, | ||
* return Leopard for chaining invoking | ||
* | ||
* @param {String} name | ||
* @param {Function} handler | ||
* @return {Leopard} | ||
*/ | ||
function filter(name, handler) { | ||
/* istanbul ignore if */ | ||
if (typeof handler !== 'function') { | ||
throw new TypeError( | ||
'Leopard: filter requires a function as handler, but got \"' + | ||
typeof handler + '\" in filter \"' + name + '\"' | ||
) | ||
} | ||
/* istanbul ignore if */ | ||
if (name in this.prototype) { | ||
throw new Error('Leopard: filter \"' + name + '\" has been declared') | ||
} | ||
this.prototype[name] = handler | ||
return this | ||
} | ||
|
||
module.exports = filter |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,15 @@ | ||
var filters = require('./filters') | ||
var escape = require('./utils').escape | ||
var escapeQuotes = function(str) { | ||
return str.replace(/"/g, '\\"') | ||
} | ||
|
||
/** | ||
* check if there is filters in expressions | ||
* expect format: | ||
* - 'name | capitalize | reverse' | ||
* and this will be compile into: | ||
* - 'reverse(capitalize(name))' | ||
* | ||
* @param {String} line | ||
* @return {String} | ||
*/ | ||
var parseFilters = function(line) { | ||
var segments = line.split('|') | ||
return segments.reduce((accumulator, f) => f.trim() + '(' + accumulator.trim() + ')') | ||
} | ||
|
||
/** | ||
* parse the given `tpl` and return Function body string | ||
* | ||
* @param {String} tpl | ||
* @param {Object} data | ||
* @return {String} | ||
*/ | ||
var parser = function(tpl, data) { | ||
data = data || {} | ||
var delimeterRE = /<%(.+?)%>/g | ||
var curMatched = null | ||
var matched = null | ||
var body = 'var lines = [];\n' + | ||
'var rst;\n' + | ||
'with(' + JSON.stringify(data) + ') {\n' | ||
|
||
/** | ||
* push a string into lines | ||
* | ||
* @param {String} str | ||
*/ | ||
function push(str) { | ||
body += 'lines.push(' + str + ');\n' | ||
} | ||
|
||
/** | ||
* generate Function body | ||
* | ||
* @param {String} line | ||
*/ | ||
var generate = function(line) { | ||
if (line.length > 0) { | ||
var type = line.charAt(0) | ||
var Leopard = require('./instance') | ||
var filter = require('./filter') | ||
var presets = require('./filter/presets') | ||
|
||
switch (type) { | ||
// for interpolations we should check filters | ||
case '=': | ||
push('escape(' + parseFilters(line.substr(1).trim()) + ')') | ||
break | ||
case '-': | ||
push(parseFilters(line.substr(1).trim())) | ||
break | ||
default: | ||
body += line + '\n' | ||
} | ||
} | ||
} | ||
// mount `filter` to Leopard as a util | ||
Leopard.filter = filter | ||
|
||
while (curMatched = delimeterRE.exec(tpl)) { | ||
// This is raw HTML | ||
var html = tpl.substring( | ||
matched !== null ? matched.index + matched[0].length : 0, | ||
curMatched.index | ||
) | ||
html && push('\"' + escapeQuotes(html) + '\"') | ||
var js = curMatched[1].trim() | ||
js && generate(js) | ||
matched = curMatched | ||
} | ||
var end = tpl.substr(matched.index + matched[0].length) | ||
end && push('\"' + escapeQuotes(end) + '\"') | ||
body += 'rst = lines.join(\"\");\n' + | ||
'}\n' + | ||
'return rst;' | ||
|
||
return body | ||
// mount presets to Leopard.prototype so that every instance can use them | ||
var presetFilters = Object.keys(presets) | ||
for (var i = 0, l = presetFilters.length, name; i < l; i++) { | ||
name = presetFilters[i] | ||
Leopard.filter(name, presets[name]) | ||
} | ||
|
||
/** | ||
* parse the given template and return HTML string | ||
* | ||
* @param {String} tpl | ||
* @param {Object} data | ||
* @return {String} | ||
*/ | ||
var compiler = function(tpl, data) { | ||
var body = parser(tpl, data) | ||
|
||
// 注入过滤器 | ||
var fun = new Function('escape', ...Object.keys(filters), body) | ||
return fun.call(this, escape, ...Object.values(filters)) | ||
} | ||
|
||
var leo = compiler | ||
|
||
module.exports = leo | ||
module.exports = Leopard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
var escape = require('./utils').escape | ||
var escapeQuotes = function(str) { | ||
return str.replace(/"/g, '\\"') | ||
} | ||
|
||
function Leopard() {} | ||
var p = Leopard.prototype | ||
|
||
/** | ||
* check if there is filters in expressions | ||
* expect format: | ||
* - 'name | capitalize | reverse' | ||
* and this will be compile into: | ||
* - 'reverse(capitalize(name))' | ||
* | ||
* @param {String} line | ||
* @return {String} | ||
*/ | ||
var parseFilters = function(line) { | ||
var segments = line.split('|') | ||
return segments.reduce((accumulator, f) => f.trim() + '(' + accumulator.trim() + ')') | ||
} | ||
|
||
/** | ||
* parse the given `tpl` and return Function body string | ||
* | ||
* @param {String} tpl | ||
* @param {Object} data | ||
* @return {String} | ||
*/ | ||
p.parse = function(tpl, data) { | ||
data = data || {} | ||
var delimeterRE = /<%(.+?)%>/g | ||
var curMatched = null | ||
var matched = null | ||
var body = 'var lines = [];\n' + | ||
'var rst;\n' + | ||
'with(' + JSON.stringify(data) + ') {\n' | ||
|
||
/** | ||
* push a string into lines | ||
* | ||
* @param {String} str | ||
*/ | ||
function push(str) { | ||
body += 'lines.push(' + str + ');\n' | ||
} | ||
|
||
/** | ||
* generate Function body | ||
* | ||
* @param {String} line | ||
*/ | ||
var generate = function(line) { | ||
if (line.length > 0) { | ||
var type = line.charAt(0) | ||
|
||
switch (type) { | ||
// for interpolations we should check filters | ||
case '=': | ||
push('escape(' + parseFilters(line.substr(1).trim()) + ')') | ||
break | ||
case '-': | ||
push(parseFilters(line.substr(1).trim())) | ||
break | ||
default: | ||
body += line + '\n' | ||
} | ||
} | ||
} | ||
|
||
while (curMatched = delimeterRE.exec(tpl)) { | ||
// This is raw HTML | ||
var html = tpl.substring( | ||
matched !== null ? matched.index + matched[0].length : 0, | ||
curMatched.index | ||
) | ||
html && push('\"' + escapeQuotes(html) + '\"') | ||
var js = curMatched[1].trim() | ||
js && generate(js) | ||
matched = curMatched | ||
} | ||
var end = tpl.substr(matched.index + matched[0].length) | ||
end && push('\"' + escapeQuotes(end) + '\"') | ||
body += 'rst = lines.join(\"\");\n' + | ||
'}\n' + | ||
'return rst;' | ||
|
||
return body | ||
} | ||
|
||
/** | ||
* parse the given template and return HTML string | ||
* | ||
* @param {String} tpl | ||
* @param {Object} data | ||
* @return {String} | ||
*/ | ||
p.compile = function(tpl, data) { | ||
var body = this.parse(tpl, data) | ||
// 注入过滤器 | ||
var fun = new Function('escape', ...Object.keys(p), body) | ||
return fun.call(p, escape, ...Object.values(p)) | ||
} | ||
|
||
module.exports = Leopard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
var assert = require('assert') | ||
var Leo = require('../../src') | ||
var filter = require('../../src/filter') | ||
|
||
var noop = function() {} | ||
|
||
describe('filter util', function() { | ||
it('should throw when handler is not a function', function() { | ||
try { | ||
filter.call(Leo, 'test', 1) | ||
} catch (e) { | ||
assert.ok(e instanceof TypeError) | ||
} | ||
}) | ||
|
||
it('should throw when name is Leo\'s reserved word', function() { | ||
try { | ||
filter.call(Leo, 'parse', noop) | ||
} catch (e) { | ||
assert.ok(e instanceof Error) | ||
} | ||
}) | ||
|
||
it('should mount a filter to Leopard.prototype', function() { | ||
filter.call(Leo, 'test', noop) | ||
assert.ok('test' in Leo.prototype) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
var assert = require('assert') | ||
var presets = require('../../src/filter/presets') | ||
|
||
describe('filter presets', function() { | ||
it('capitalize', function() { | ||
assert.strictEqual(presets.capitalize('leopard'), 'Leopard') | ||
}) | ||
|
||
it('reverse', function() { | ||
assert.strictEqual(presets.reverse('leopard'), 'drapoel') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters