This commit is contained in:
harttle
2017-04-24 21:31:30 +08:00
parent 82f84d96c1
commit 2632e3e97e
50 changed files with 3941 additions and 3903 deletions
+9 -9
View File
@@ -1,13 +1,13 @@
const AssertionError = require('./error.js').AssertionError;
const AssertionError = require('./error.js').AssertionError
function assert(predicate, message) {
if (!predicate) {
if (message instanceof Error) {
throw message;
}
var message = message || `expect ${predicate} to be true`;
throw new AssertionError(message);
function assert (predicate, message) {
if (!predicate) {
if (message instanceof Error) {
throw message
}
message = message || `expect ${predicate} to be true`
throw new AssertionError(message)
}
}
module.exports = assert;
module.exports = assert
+88 -88
View File
@@ -1,118 +1,118 @@
const _ = require('./underscore.js');
const _ = require('./underscore.js')
function TokenizationError(message, token) {
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
this.name = this.constructor.name;
function TokenizationError (message, token) {
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor)
}
this.name = this.constructor.name
this.input = token.input;
this.line = token.line;
this.file = token.file;
this.input = token.input
this.line = token.line
this.file = token.file
var context = mkContext(token.input, token.line);
this.message = mkMessage(message, token);
this.stack = context + '\n' + (this.stack || '');
var context = mkContext(token.input, token.line)
this.message = mkMessage(message, token)
this.stack = context + '\n' + (this.stack || '')
}
TokenizationError.prototype = Object.create(Error.prototype);
TokenizationError.prototype.constructor = TokenizationError;
TokenizationError.prototype = Object.create(Error.prototype)
TokenizationError.prototype.constructor = TokenizationError
function ParseError(e, token) {
_.assign(this, e);
this.originalError = e;
this.name = this.constructor.name;
function ParseError (e, token) {
_.assign(this, e)
this.originalError = e
this.name = this.constructor.name
this.input = token.input;
this.line = token.line;
this.file = token.file;
this.input = token.input
this.line = token.line
this.file = token.file
var context = mkContext(token.input, token.line);
this.message = mkMessage(e.message || 'Unkown Error', token);
this.stack = context + '\n' + (e.stack || '');
var context = mkContext(token.input, token.line)
this.message = mkMessage(e.message || 'Unkown Error', token)
this.stack = context + '\n' + (e.stack || '')
}
ParseError.prototype = Object.create(Error.prototype);
ParseError.prototype.constructor = ParseError;
ParseError.prototype = Object.create(Error.prototype)
ParseError.prototype.constructor = ParseError
function RenderError(e, tpl) {
function RenderError (e, tpl) {
// return the original render error
if(e instanceof RenderError){
return e;
}
_.assign(this, e);
this.originalError = e;
this.name = this.constructor.name;
if (e instanceof RenderError) {
return e
}
_.assign(this, e)
this.originalError = e
this.name = this.constructor.name
this.input = tpl.token.input;
this.line = tpl.token.line;
this.file = tpl.token.file;
this.input = tpl.token.input
this.line = tpl.token.line
this.file = tpl.token.file
var context = mkContext(tpl.token.input, tpl.token.line);
this.message = mkMessage(e.message || 'Unkown Error', tpl.token);
this.stack = context + '\n' + (e.stack || '');
var context = mkContext(tpl.token.input, tpl.token.line)
this.message = mkMessage(e.message || 'Unkown Error', tpl.token)
this.stack = context + '\n' + (e.stack || '')
}
RenderError.prototype = Object.create(Error.prototype);
RenderError.prototype.constructor = RenderError;
RenderError.prototype = Object.create(Error.prototype)
RenderError.prototype.constructor = RenderError
function RenderBreakError(message) {
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
this.name = this.constructor.name;
this.message = message || '';
function RenderBreakError (message) {
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor)
}
this.name = this.constructor.name
this.message = message || ''
}
RenderBreakError.prototype = Object.create(Error.prototype);
RenderBreakError.prototype.constructor = RenderBreakError;
RenderBreakError.prototype = Object.create(Error.prototype)
RenderBreakError.prototype.constructor = RenderBreakError
function AssertionError(message) {
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
this.name = this.constructor.name;
this.message = message;
function AssertionError (message) {
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor)
}
this.name = this.constructor.name
this.message = message
}
AssertionError.prototype = Object.create(Error.prototype);
AssertionError.prototype.constructor = AssertionError;
AssertionError.prototype = Object.create(Error.prototype)
AssertionError.prototype.constructor = AssertionError
function mkContext(input, line) {
var lines = input.split('\n');
var begin = Math.max(line - 2, 1);
var end = Math.min(line + 3, lines.length);
function mkContext (input, line) {
var lines = input.split('\n')
var begin = Math.max(line - 2, 1)
var end = Math.min(line + 3, lines.length)
var context = _
var context = _
.range(begin, end + 1)
.map(l => [
(l === line) ? '>> ' : ' ',
align(l, end),
'| ',
lines[l - 1]
(l === line) ? '>> ' : ' ',
align(l, end),
'| ',
lines[l - 1]
].join(''))
.join('\n');
.join('\n')
return context;
return context
}
function align(n, max) {
var length = (max + '').length;
var str = n + '';
var blank = Array(length - str.length).join(' ');
return blank + str;
function align (n, max) {
var length = (max + '').length
var str = n + ''
var blank = Array(length - str.length).join(' ')
return blank + str
}
function mkMessage(msg, token){
msg = msg || '';
if(token.file){
msg += ', file:' + token.file;
}
if(token.line){
msg += ', line:' + token.line;
}
return msg;
function mkMessage (msg, token) {
msg = msg || ''
if (token.file) {
msg += ', file:' + token.file
}
if (token.line) {
msg += ', line:' + token.line
}
return msg
}
module.exports = {
TokenizationError,
ParseError,
RenderBreakError,
AssertionError,
RenderError
};
TokenizationError,
ParseError,
RenderBreakError,
AssertionError,
RenderError
}
+14 -14
View File
@@ -1,20 +1,20 @@
const fs = require('fs');
const fs = require('fs')
function readFileAsync(filepath) {
return new Promise(function(resolve, reject) {
fs.readFile(filepath, 'utf8', function(err, content) {
err ? reject(err) : resolve(content);
});
});
function readFileAsync (filepath) {
return new Promise(function (resolve, reject) {
fs.readFile(filepath, 'utf8', function (err, content) {
err ? reject(err) : resolve(content)
})
})
};
function statFileAsync(path) {
return new Promise(function(resolve, reject) {
fs.stat(path, (err, stat) => err ? reject(err) : resolve(stat))
});
function statFileAsync (path) {
return new Promise(function (resolve, reject) {
fs.stat(path, (err, stat) => err ? reject(err) : resolve(stat))
})
};
module.exports = {
readFileAsync,
statFileAsync
};
readFileAsync,
statFileAsync
}
+19 -19
View File
@@ -1,35 +1,35 @@
const Promise = require('any-promise');
const Promise = require('any-promise')
/*
* Call functions in serial until someone resolved.
* @param {Array} iterable the array to iterate with.
* @param {Array} iteratee returns a new promise.
* The iteratee is invoked with three arguments: (value, index, iterable).
* The iteratee is invoked with three arguments: (value, index, iterable).
*/
function anySeries(iterable, iteratee) {
var ret = Promise.reject(new Error('init'));
iterable.forEach(function(item, idx) {
ret = ret.catch(e => iteratee(item, idx, iterable));
});
return ret;
function anySeries (iterable, iteratee) {
var ret = Promise.reject(new Error('init'))
iterable.forEach(function (item, idx) {
ret = ret.catch(e => iteratee(item, idx, iterable))
})
return ret
}
/*
* Call functions in serial until someone rejected.
* @param {Array} iterable the array to iterate with.
* @param {Array} iteratee returns a new promise.
* The iteratee is invoked with three arguments: (value, index, iterable).
* The iteratee is invoked with three arguments: (value, index, iterable).
*/
function mapSeries(iterable, iteratee) {
var ret = Promise.resolve('init');
var result = [];
iterable.forEach(function(item, idx) {
ret = ret
function mapSeries (iterable, iteratee) {
var ret = Promise.resolve('init')
var result = []
iterable.forEach(function (item, idx) {
ret = ret
.then(() => iteratee(item, idx, iterable))
.then(x => result.push(x));
});
return ret.then(() => result);
.then(x => result.push(x))
})
return ret.then(() => result)
}
exports.anySeries = anySeries;
exports.mapSeries = mapSeries;
exports.anySeries = anySeries
exports.mapSeries = mapSeries
+180 -181
View File
@@ -1,200 +1,199 @@
var monthNames = [
"January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December"
];
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
'September', 'October', 'November', 'December'
]
var monthNamesShort = [
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec"
];
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
'Nov', 'Dec'
]
var dayNames = [
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
];
var dayNamesShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
]
var dayNamesShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
var suffixes = {
1: 'st',
2: 'nd',
3: 'rd',
'default': 'th'
};
1: 'st',
2: 'nd',
3: 'rd',
'default': 'th'
}
// prototype extensions
var _date = {
daysInMonth: function(d) {
var feb = _date.isLeapYear(d) ? 29 : 28;
return [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
},
daysInMonth: function (d) {
var feb = _date.isLeapYear(d) ? 29 : 28
return [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
},
getDayOfYear: function(d) {
var num = 0;
for (var i = 0; i < d.getMonth(); ++i) {
num += _date.daysInMonth(d)[i];
}
return num + d.getDate();
},
// Startday is an integer of which day to start the week measuring from
// TODO: that comment was retarted. fix it.
getWeekOfYear: function(d, startDay) {
// Skip to startDay of this week
var now = this.getDayOfYear(d) + (startDay - d.getDay());
// Find the first startDay of the year
var jan1 = new Date(d.getFullYear(), 0, 1);
var then = (7 - jan1.getDay() + startDay);
return _number.pad(Math.floor((now - then) / 7) + 1, 2);
},
isLeapYear: function(d) {
var year = d.getFullYear();
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)));
},
getSuffix: function(d) {
var str = d.getDate().toString();
var index = parseInt(str.slice(-1));
return suffixes[index] || suffixes['default'];
},
century: function(d) {
return parseInt(d.getFullYear().toString().substring(0, 2), 10);
getDayOfYear: function (d) {
var num = 0
for (var i = 0; i < d.getMonth(); ++i) {
num += _date.daysInMonth(d)[i]
}
};
return num + d.getDate()
},
// Startday is an integer of which day to start the week measuring from
// TODO: that comment was retarted. fix it.
getWeekOfYear: function (d, startDay) {
// Skip to startDay of this week
var now = this.getDayOfYear(d) + (startDay - d.getDay())
// Find the first startDay of the year
var jan1 = new Date(d.getFullYear(), 0, 1)
var then = (7 - jan1.getDay() + startDay)
return _number.pad(Math.floor((now - then) / 7) + 1, 2)
},
isLeapYear: function (d) {
var year = d.getFullYear()
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)))
},
getSuffix: function (d) {
var str = d.getDate().toString()
var index = parseInt(str.slice(-1))
return suffixes[index] || suffixes['default']
},
century: function (d) {
return parseInt(d.getFullYear().toString().substring(0, 2), 10)
}
}
var _number = {
pad: function(value, size, ch) {
if (!ch) ch = '0';
var result = value.toString();
var pad = size - result.length;
pad: function (value, size, ch) {
if (!ch) ch = '0'
var result = value.toString()
var pad = size - result.length
while (pad-- > 0) {
result = ch + result;
}
return result;
while (pad-- > 0) {
result = ch + result
}
};
return result
}
}
var format_codes = {
a: function(d) {
return dayNamesShort[d.getDay()];
},
A: function(d) {
return dayNames[d.getDay()];
},
b: function(d) {
return monthNamesShort[d.getMonth()];
},
B: function(d) {
return monthNames[d.getMonth()];
},
c: function(d) {
return d.toLocaleString();
},
C: function(d) {
return _date.century(d);
},
d: function(d) {
return _number.pad(d.getDate(), 2);
},
e: function(d) {
return _number.pad(d.getDate(), 2, ' ');
},
H: function(d) {
return _number.pad(d.getHours(), 2);
},
I: function(d) {
return _number.pad(d.getHours() % 12 || 12, 2);
},
j: function(d) {
return _number.pad(_date.getDayOfYear(d), 3);
},
k: function(d) {
return _number.pad(d.getHours(), 2, ' ');
},
l: function(d) {
return _number.pad(d.getHours() % 12 || 12, 2, ' ');
},
L: function(d) {
return _number.pad(d.getMilliseconds(), 3);
},
m: function(d) {
return _number.pad(d.getMonth() + 1, 2);
},
M: function(d) {
return _number.pad(d.getMinutes(), 2);
},
p: function(d) {
return (d.getHours() < 12 ? 'AM' : 'PM');
},
P: function(d) {
return (d.getHours() < 12 ? 'am' : 'pm');
},
q: function(d) {
return _date.getSuffix(d);
},
s: function(d) {
return Math.round(d.valueOf() / 1000);
},
S: function(d) {
return _number.pad(d.getSeconds(), 2);
},
u: function(d) {
return d.getDay() || 7;
},
U: function(d) {
return _date.getWeekOfYear(d, 0);
},
w: function(d) {
return d.getDay();
},
W: function(d) {
return _date.getWeekOfYear(d, 1);
},
x: function(d) {
return d.toLocaleDateString();
},
X: function(d) {
return d.toLocaleTimeString();
},
y: function(d) {
return d.getFullYear().toString().substring(2, 4);
},
Y: function(d) {
return d.getFullYear();
},
z: function(d) {
var tz = d.getTimezoneOffset() / 60 * 100;
return (tz > 0 ? '-' : '+') + _number.pad(Math.abs(tz), 4);
},
"%": function() {
return '%';
var formatCodes = {
a: function (d) {
return dayNamesShort[d.getDay()]
},
A: function (d) {
return dayNames[d.getDay()]
},
b: function (d) {
return monthNamesShort[d.getMonth()]
},
B: function (d) {
return monthNames[d.getMonth()]
},
c: function (d) {
return d.toLocaleString()
},
C: function (d) {
return _date.century(d)
},
d: function (d) {
return _number.pad(d.getDate(), 2)
},
e: function (d) {
return _number.pad(d.getDate(), 2, ' ')
},
H: function (d) {
return _number.pad(d.getHours(), 2)
},
I: function (d) {
return _number.pad(d.getHours() % 12 || 12, 2)
},
j: function (d) {
return _number.pad(_date.getDayOfYear(d), 3)
},
k: function (d) {
return _number.pad(d.getHours(), 2, ' ')
},
l: function (d) {
return _number.pad(d.getHours() % 12 || 12, 2, ' ')
},
L: function (d) {
return _number.pad(d.getMilliseconds(), 3)
},
m: function (d) {
return _number.pad(d.getMonth() + 1, 2)
},
M: function (d) {
return _number.pad(d.getMinutes(), 2)
},
p: function (d) {
return (d.getHours() < 12 ? 'AM' : 'PM')
},
P: function (d) {
return (d.getHours() < 12 ? 'am' : 'pm')
},
q: function (d) {
return _date.getSuffix(d)
},
s: function (d) {
return Math.round(d.valueOf() / 1000)
},
S: function (d) {
return _number.pad(d.getSeconds(), 2)
},
u: function (d) {
return d.getDay() || 7
},
U: function (d) {
return _date.getWeekOfYear(d, 0)
},
w: function (d) {
return d.getDay()
},
W: function (d) {
return _date.getWeekOfYear(d, 1)
},
x: function (d) {
return d.toLocaleDateString()
},
X: function (d) {
return d.toLocaleTimeString()
},
y: function (d) {
return d.getFullYear().toString().substring(2, 4)
},
Y: function (d) {
return d.getFullYear()
},
z: function (d) {
var tz = d.getTimezoneOffset() / 60 * 100
return (tz > 0 ? '-' : '+') + _number.pad(Math.abs(tz), 4)
},
'%': function () {
return '%'
}
}
formatCodes.h = formatCodes.b
formatCodes.N = formatCodes.L
var strftime = function (d, format) {
var output = ''
var remaining = format
while (true) {
var r = /%./g
var results = r.exec(remaining)
// No more format codes. Add the remaining text and return
if (!results) {
return output + remaining
}
};
format_codes.h = format_codes.b;
format_codes.N = format_codes.L;
var strftime = function(d, format) {
var output = '';
var remaining = format;
// Add the preceding text
output += remaining.slice(0, r.lastIndex - 2)
remaining = remaining.slice(r.lastIndex)
while (true) {
var r = /%./g;
var results = r.exec(remaining);
// Add the format code
var ch = results[0].charAt(1)
var func = formatCodes[ch]
output += func ? func.call(this, d) : '%' + ch
}
}
// No more format codes. Add the remaining text and return
if (!results) {
return output + remaining;
}
// Add the preceding text
output += remaining.slice(0, r.lastIndex - 2);
remaining = remaining.slice(r.lastIndex);
// Add the format code
var ch = results[0].charAt(1);
var func = format_codes[ch];
output += func ? func.call(this, d) : '%' + ch;
}
};
module.exports = strftime;
module.exports = strftime
+76 -77
View File
@@ -3,39 +3,39 @@
* @param {any} value The value to check.
* @return {Boolean} Returns true if value is a string, else false.
*/
function isString(value) {
return value instanceof String || typeof value === 'string';
function isString (value) {
return value instanceof String || typeof value === 'string'
}
function isError(value) {
var signature = Object.prototype.toString.call(value);
function isError (value) {
var signature = Object.prototype.toString.call(value)
// [object XXXError]
return signature.substr(-6, 5) === 'Error' ||
(typeof value.message == 'string' && typeof value.name == 'string');
return signature.substr(-6, 5) === 'Error' ||
(typeof value.message === 'string' && typeof value.name === 'string')
}
/*
* Iterates over own enumerable string keyed properties of an object and invokes iteratee for each property.
* The iteratee is invoked with three arguments: (value, key, object).
* Iterates over own enumerable string keyed properties of an object and invokes iteratee for each property.
* The iteratee is invoked with three arguments: (value, key, object).
* Iteratee functions may exit iteration early by explicitly returning false.
* @param {Object} object The object to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @return {Object} Returns object.
*/
function forOwn(object, iteratee) {
object = object || {};
for (var k in object) {
if (object.hasOwnProperty(k)) {
if (iteratee(object[k], k, object) === false) break;
}
function forOwn (object, iteratee) {
object = object || {}
for (var k in object) {
if (object.hasOwnProperty(k)) {
if (iteratee(object[k], k, object) === false) break
}
return object;
}
return object
}
/*
* Assigns own enumerable string keyed properties of source objects to the destination object.
* Source objects are applied from left to right.
* Subsequent sources overwrite property assignments of previous sources.
* Assigns own enumerable string keyed properties of source objects to the destination object.
* Source objects are applied from left to right.
* Subsequent sources overwrite property assignments of previous sources.
*
* Note: This method mutates object and is loosely based on Object.assign.
*
@@ -43,89 +43,88 @@ function forOwn(object, iteratee) {
* @param {...Object} sources The source objects.
* @return {Object} Returns object.
*/
function assign(object) {
object = isObject(object) ? object : {};
var srcs = Array.prototype.slice.call(arguments, 1);
srcs.forEach(function(src) {
_assignBinary(object, src);
});
return object;
function assign (object) {
object = isObject(object) ? object : {}
var srcs = Array.prototype.slice.call(arguments, 1)
srcs.forEach(function (src) {
_assignBinary(object, src)
})
return object
}
function _assignBinary(dst, src) {
if (!dst) return dst;
forOwn(src, function(v, k) {
dst[k] = v;
});
return dst;
function _assignBinary (dst, src) {
if (!dst) return dst
forOwn(src, function (v, k) {
dst[k] = v
})
return dst
}
function isArray(value) {
return value instanceof Array;
function isArray (value) {
return value instanceof Array
}
function echo(prefix) {
return v => {
console.log('[' + prefix + ']', v);
return v;
};
function echo (prefix) {
return v => {
console.log('[' + prefix + ']', v)
return v
}
}
function uniq(arr) {
var u = {},
a = [];
for (var i = 0, l = arr.length; i < l; ++i) {
if (u.hasOwnProperty(arr[i])) {
continue;
}
a.push(arr[i]);
u[arr[i]] = 1;
function uniq (arr) {
var u = {}
var a = []
for (var i = 0, l = arr.length; i < l; ++i) {
if (u.hasOwnProperty(arr[i])) {
continue
}
return a;
a.push(arr[i])
u[arr[i]] = 1
}
return a
}
/*
* Checks if value is the language type of Object.
* Checks if value is the language type of Object.
* (e.g. arrays, functions, objects, regexes, new Number(0), and new String(''))
* @param {any} value The value to check.
* @return {Boolean} Returns true if value is an object, else false.
*/
function isObject(value) {
return value !== null && typeof value === 'object';
function isObject (value) {
return value !== null && typeof value === 'object'
}
/*
* A function to create flexibly-numbered lists of integers,
* handy for each and map loops. start, if omitted, defaults to 0; step defaults to 1.
* Returns a list of integers from start (inclusive) to stop (exclusive),
* incremented (or decremented) by step, exclusive.
* Note that ranges that stop before they start are considered to be zero-length instead of
* A function to create flexibly-numbered lists of integers,
* handy for each and map loops. start, if omitted, defaults to 0; step defaults to 1.
* Returns a list of integers from start (inclusive) to stop (exclusive),
* incremented (or decremented) by step, exclusive.
* Note that ranges that stop before they start are considered to be zero-length instead of
* negative — if you'd like a negative range, use a negative step.
*/
function range(start, stop, step) {
if (arguments.length === 1) {
stop = start;
start = 0;
}
step = step || 1;
function range (start, stop, step) {
if (arguments.length === 1) {
stop = start
start = 0
}
step = step || 1
var arr = [];
for (var i = start; i < stop; i += step) {
arr.push(i);
}
return arr;
var arr = []
for (var i = start; i < stop; i += step) {
arr.push(i)
}
return arr
}
exports.isString = isString;
exports.isArray = isArray;
exports.isObject = isObject;
exports.isError = isError;
exports.isString = isString
exports.isArray = isArray
exports.isObject = isObject
exports.isError = isError
exports.range = range;
exports.range = range
exports.forOwn = forOwn;
exports.assign = assign;
exports.uniq = uniq;
exports.forOwn = forOwn
exports.assign = assign
exports.uniq = uniq
exports.echo = echo;
exports.echo = echo