mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 20:30:39 -07:00
refactor: bundle template.js respectively
This commit is contained in:
Vendored
+246
-317
@@ -1230,24 +1230,145 @@ function factory(ctx, opts) {
|
||||
return scope;
|
||||
}
|
||||
|
||||
function get$1(url) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onload = function () {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(xhr.responseText);
|
||||
} else {
|
||||
reject(new Error(xhr.statusText));
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
reject(new Error('An error occurred whilst sending the response.'));
|
||||
};
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
function anySeries(iterable, iteratee) {
|
||||
var ret = Promise.reject(new Error('init'));
|
||||
iterable.forEach(function (item, idx) {
|
||||
ret = ret.catch(function (e) {
|
||||
return 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).
|
||||
*/
|
||||
function mapSeries(iterable, iteratee) {
|
||||
var ret = Promise.resolve('init');
|
||||
var result = [];
|
||||
iterable.forEach(function (item, idx) {
|
||||
ret = ret.then(function () {
|
||||
return iteratee(item, idx, iterable);
|
||||
}).then(function (x) {
|
||||
return result.push(x);
|
||||
});
|
||||
});
|
||||
return ret.then(function () {
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function readFileAsync(filepath) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.readFile(filepath, 'utf8', function (err, content) {
|
||||
err ? reject(err) : resolve(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
function statFileAsync(path$$1) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.stat(path$$1, function (err, stat) {
|
||||
return err ? reject(err) : resolve(stat);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function lookup(filepath, root, options) {
|
||||
var _this = this;
|
||||
|
||||
root = options.root.concat(root || []);
|
||||
root = uniq(root);
|
||||
var paths = root.map(function (root) {
|
||||
return path.resolve(root || location.href, filepath);
|
||||
});
|
||||
return anySeries(paths, function () {
|
||||
var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(path$$1) {
|
||||
return regeneratorRuntime.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
_context.prev = 0;
|
||||
_context.next = 3;
|
||||
return statFileAsync(path$$1);
|
||||
|
||||
case 3:
|
||||
return _context.abrupt('return', path$$1);
|
||||
|
||||
case 6:
|
||||
_context.prev = 6;
|
||||
_context.t0 = _context['catch'](0);
|
||||
|
||||
_context.t0.message = _context.t0.code + ': Failed to lookup ' + filepath + ' in: ' + root;
|
||||
throw _context.t0;
|
||||
|
||||
case 10:
|
||||
case 'end':
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, _this, [[0, 6]]);
|
||||
}));
|
||||
|
||||
return function (_x) {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
}());
|
||||
}
|
||||
|
||||
var resolve = function () {
|
||||
var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(filepath, root, options) {
|
||||
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
||||
while (1) {
|
||||
switch (_context2.prev = _context2.next) {
|
||||
case 0:
|
||||
if (!path.extname(filepath)) {
|
||||
filepath += options.extname;
|
||||
}
|
||||
return _context2.abrupt('return', lookup(filepath, root, options));
|
||||
|
||||
case 2:
|
||||
case 'end':
|
||||
return _context2.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2, this);
|
||||
}));
|
||||
|
||||
return function resolve(_x2, _x3, _x4) {
|
||||
return _ref2.apply(this, arguments);
|
||||
};
|
||||
}();
|
||||
|
||||
var read = function () {
|
||||
var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(filepath) {
|
||||
return regeneratorRuntime.wrap(function _callee3$(_context3) {
|
||||
while (1) {
|
||||
switch (_context3.prev = _context3.next) {
|
||||
case 0:
|
||||
return _context3.abrupt('return', readFileAsync(filepath));
|
||||
|
||||
case 1:
|
||||
case 'end':
|
||||
return _context3.stop();
|
||||
}
|
||||
}
|
||||
}, _callee3, this);
|
||||
}));
|
||||
|
||||
return function read(_x5) {
|
||||
return _ref3.apply(this, arguments);
|
||||
};
|
||||
}();
|
||||
|
||||
function whiteSpaceCtrl(tokens, options) {
|
||||
options = assign({ greedy: true }, options);
|
||||
var inRaw = false;
|
||||
@@ -1373,61 +1494,6 @@ function LineNumber(html) {
|
||||
};
|
||||
}
|
||||
|
||||
function readFileAsync(filepath) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.readFile(filepath, 'utf8', function (err, content) {
|
||||
err ? reject(err) : resolve(content);
|
||||
});
|
||||
});
|
||||
}
|
||||
function statFileAsync(path$$1) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.stat(path$$1, function (err, stat) {
|
||||
return err ? reject(err) : resolve(stat);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/;
|
||||
var urlRe = /^(?:\w+:)?\/\/([^\s.]+\.\S{2}|localhost[:?\d]*)\S*$/;
|
||||
|
||||
// https://github.com/jinder/path/blob/master/path.js#L567
|
||||
function extname(path$$1) {
|
||||
return splitPathRe.exec(path$$1).slice(1)[3];
|
||||
}
|
||||
|
||||
// https://www.npmjs.com/package/is-url
|
||||
function valid(path$$1) {
|
||||
return urlRe.test(path$$1);
|
||||
}
|
||||
|
||||
function resolve(root, path$$1) {
|
||||
if (isArray(root)) {
|
||||
root = root[0];
|
||||
}
|
||||
if (root && last(root) !== '/') {
|
||||
root += '/';
|
||||
}
|
||||
return resolveUrl(root, path$$1);
|
||||
}
|
||||
|
||||
function resolveUrl(root, path$$1) {
|
||||
var base = document.createElement('base');
|
||||
base.href = arguments[0];
|
||||
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
head.insertBefore(base, head.firstChild);
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.href = path$$1;
|
||||
var resolved = a.href;
|
||||
base.href = resolved;
|
||||
|
||||
head.removeChild(base);
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
function Operators (isTruthy) {
|
||||
return {
|
||||
'==': function _(l, r) {
|
||||
@@ -1996,43 +2062,6 @@ function Parser (Tag, Filter) {
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
function anySeries(iterable, iteratee) {
|
||||
var ret = Promise.reject(new Error('init'));
|
||||
iterable.forEach(function (item, idx) {
|
||||
ret = ret.catch(function (e) {
|
||||
return 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).
|
||||
*/
|
||||
function mapSeries(iterable, iteratee) {
|
||||
var ret = Promise.resolve('init');
|
||||
var result = [];
|
||||
iterable.forEach(function (item, idx) {
|
||||
ret = ret.then(function () {
|
||||
return iteratee(item, idx, iterable);
|
||||
}).then(function (x) {
|
||||
return result.push(x);
|
||||
});
|
||||
});
|
||||
return ret.then(function () {
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function For (liquid, Liquid) {
|
||||
var render = function () {
|
||||
var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(scope, hash$$1) {
|
||||
@@ -2046,7 +2075,7 @@ function For (liquid, Liquid) {
|
||||
collection = Liquid.evalExp(this.collection, scope);
|
||||
|
||||
|
||||
if (!Array.isArray(collection)) {
|
||||
if (!isArray(collection)) {
|
||||
if (isString(collection) && collection.length > 0) {
|
||||
collection = [collection];
|
||||
} else if (isObject(collection)) {
|
||||
@@ -2056,7 +2085,7 @@ function For (liquid, Liquid) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!(!Array.isArray(collection) || !collection.length)) {
|
||||
if (!(!isArray(collection) || !collection.length)) {
|
||||
_context2.next = 4;
|
||||
break;
|
||||
}
|
||||
@@ -3408,35 +3437,126 @@ var _engine = {
|
||||
|
||||
return parseAndRender;
|
||||
}(),
|
||||
renderFile: function () {
|
||||
var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(filepath, ctx, opts) {
|
||||
var templates;
|
||||
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
||||
getTemplate: function () {
|
||||
var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(file, root) {
|
||||
var _this = this;
|
||||
|
||||
var filepath;
|
||||
return regeneratorRuntime.wrap(function _callee3$(_context3) {
|
||||
while (1) {
|
||||
switch (_context2.prev = _context2.next) {
|
||||
switch (_context3.prev = _context3.next) {
|
||||
case 0:
|
||||
opts = assign({}, opts);
|
||||
_context2.next = 3;
|
||||
return this.getTemplate(filepath, opts.root);
|
||||
_context3.next = 2;
|
||||
return resolve(file, root, this.options);
|
||||
|
||||
case 3:
|
||||
templates = _context2.sent;
|
||||
return _context2.abrupt('return', this.render(templates, ctx, opts));
|
||||
case 2:
|
||||
filepath = _context3.sent;
|
||||
return _context3.abrupt('return', this.respectCache(filepath, asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
|
||||
var str;
|
||||
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
||||
while (1) {
|
||||
switch (_context2.prev = _context2.next) {
|
||||
case 0:
|
||||
_context2.next = 2;
|
||||
return read(filepath);
|
||||
|
||||
case 5:
|
||||
case 2:
|
||||
str = _context2.sent;
|
||||
return _context2.abrupt('return', _this.parse(str, filepath));
|
||||
|
||||
case 4:
|
||||
case 'end':
|
||||
return _context2.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2, _this);
|
||||
}))));
|
||||
|
||||
case 4:
|
||||
case 'end':
|
||||
return _context2.stop();
|
||||
return _context3.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2, this);
|
||||
}, _callee3, this);
|
||||
}));
|
||||
|
||||
function renderFile(_x4, _x5, _x6) {
|
||||
function getTemplate(_x4, _x5) {
|
||||
return _ref2.apply(this, arguments);
|
||||
}
|
||||
|
||||
return getTemplate;
|
||||
}(),
|
||||
renderFile: function () {
|
||||
var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(file, ctx, opts) {
|
||||
var templates;
|
||||
return regeneratorRuntime.wrap(function _callee4$(_context4) {
|
||||
while (1) {
|
||||
switch (_context4.prev = _context4.next) {
|
||||
case 0:
|
||||
opts = assign({}, opts);
|
||||
_context4.next = 3;
|
||||
return this.getTemplate(file, opts.root);
|
||||
|
||||
case 3:
|
||||
templates = _context4.sent;
|
||||
return _context4.abrupt('return', this.render(templates, ctx, opts));
|
||||
|
||||
case 5:
|
||||
case 'end':
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, this);
|
||||
}));
|
||||
|
||||
function renderFile(_x6, _x7, _x8) {
|
||||
return _ref4.apply(this, arguments);
|
||||
}
|
||||
|
||||
return renderFile;
|
||||
}(),
|
||||
respectCache: function () {
|
||||
var _ref5 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(key, getter) {
|
||||
var cacheEnabled, value;
|
||||
return regeneratorRuntime.wrap(function _callee5$(_context5) {
|
||||
while (1) {
|
||||
switch (_context5.prev = _context5.next) {
|
||||
case 0:
|
||||
cacheEnabled = this.options.cache;
|
||||
|
||||
if (!(cacheEnabled && this.cache[key])) {
|
||||
_context5.next = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context5.abrupt('return', this.cache[key]);
|
||||
|
||||
case 3:
|
||||
_context5.next = 5;
|
||||
return getter();
|
||||
|
||||
case 5:
|
||||
value = _context5.sent;
|
||||
|
||||
if (cacheEnabled) {
|
||||
this.cache[key] = value;
|
||||
}
|
||||
return _context5.abrupt('return', value);
|
||||
|
||||
case 8:
|
||||
case 'end':
|
||||
return _context5.stop();
|
||||
}
|
||||
}
|
||||
}, _callee5, this);
|
||||
}));
|
||||
|
||||
function respectCache(_x9, _x10) {
|
||||
return _ref5.apply(this, arguments);
|
||||
}
|
||||
|
||||
return respectCache;
|
||||
}(),
|
||||
evalValue: function evalValue$$1(str, scope) {
|
||||
var tpl = this.parser.parseValue(str.trim());
|
||||
return this.renderer.evalValue(tpl, scope);
|
||||
@@ -3447,202 +3567,11 @@ var _engine = {
|
||||
registerTag: function registerTag(name, tag) {
|
||||
return this.tag.register(name, tag);
|
||||
},
|
||||
lookup: function lookup(filepath, root) {
|
||||
var _this = this;
|
||||
|
||||
root = this.options.root.concat(root || []);
|
||||
root = uniq(root);
|
||||
var paths = root.map(function (root) {
|
||||
return path.resolve(root, filepath);
|
||||
});
|
||||
return anySeries(paths, function () {
|
||||
var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(path$$1) {
|
||||
return regeneratorRuntime.wrap(function _callee3$(_context3) {
|
||||
while (1) {
|
||||
switch (_context3.prev = _context3.next) {
|
||||
case 0:
|
||||
_context3.prev = 0;
|
||||
_context3.next = 3;
|
||||
return statFileAsync(path$$1);
|
||||
|
||||
case 3:
|
||||
return _context3.abrupt('return', path$$1);
|
||||
|
||||
case 6:
|
||||
_context3.prev = 6;
|
||||
_context3.t0 = _context3['catch'](0);
|
||||
|
||||
_context3.t0.message = _context3.t0.code + ': Failed to lookup ' + filepath + ' in: ' + root;
|
||||
throw _context3.t0;
|
||||
|
||||
case 10:
|
||||
case 'end':
|
||||
return _context3.stop();
|
||||
}
|
||||
}
|
||||
}, _callee3, _this, [[0, 6]]);
|
||||
}));
|
||||
|
||||
return function (_x7) {
|
||||
return _ref3.apply(this, arguments);
|
||||
};
|
||||
}());
|
||||
},
|
||||
getTemplate: function getTemplate(filepath, root) {
|
||||
return typeof XMLHttpRequest === 'undefined' ? this.getTemplateFromFile(filepath, root) : this.getTemplateFromUrl(filepath, root);
|
||||
},
|
||||
getTemplateFromFile: function () {
|
||||
var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(filepath, root) {
|
||||
var _this2 = this;
|
||||
|
||||
return regeneratorRuntime.wrap(function _callee5$(_context5) {
|
||||
while (1) {
|
||||
switch (_context5.prev = _context5.next) {
|
||||
case 0:
|
||||
if (!path.extname(filepath)) {
|
||||
filepath += this.options.extname;
|
||||
}
|
||||
_context5.next = 3;
|
||||
return this.lookup(filepath, root);
|
||||
|
||||
case 3:
|
||||
filepath = _context5.sent;
|
||||
return _context5.abrupt('return', this.respectCache(filepath, asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
|
||||
var str;
|
||||
return regeneratorRuntime.wrap(function _callee4$(_context4) {
|
||||
while (1) {
|
||||
switch (_context4.prev = _context4.next) {
|
||||
case 0:
|
||||
_context4.next = 2;
|
||||
return readFileAsync(filepath);
|
||||
|
||||
case 2:
|
||||
str = _context4.sent;
|
||||
return _context4.abrupt('return', _this2.parse(str, filepath));
|
||||
|
||||
case 4:
|
||||
case 'end':
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, _this2);
|
||||
}))));
|
||||
|
||||
case 5:
|
||||
case 'end':
|
||||
return _context5.stop();
|
||||
}
|
||||
}
|
||||
}, _callee5, this);
|
||||
}));
|
||||
|
||||
function getTemplateFromFile(_x8, _x9) {
|
||||
return _ref4.apply(this, arguments);
|
||||
}
|
||||
|
||||
return getTemplateFromFile;
|
||||
}(),
|
||||
getTemplateFromUrl: function () {
|
||||
var _ref6 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(filepath, root) {
|
||||
var _this3 = this;
|
||||
|
||||
var fullUrl;
|
||||
return regeneratorRuntime.wrap(function _callee7$(_context7) {
|
||||
while (1) {
|
||||
switch (_context7.prev = _context7.next) {
|
||||
case 0:
|
||||
fullUrl = void 0;
|
||||
|
||||
if (valid(filepath)) {
|
||||
fullUrl = filepath;
|
||||
} else {
|
||||
if (!extname(filepath)) {
|
||||
filepath += this.options.extname;
|
||||
}
|
||||
fullUrl = resolve(root || this.options.root, filepath);
|
||||
}
|
||||
return _context7.abrupt('return', this.respectCache(filepath, asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6() {
|
||||
return regeneratorRuntime.wrap(function _callee6$(_context6) {
|
||||
while (1) {
|
||||
switch (_context6.prev = _context6.next) {
|
||||
case 0:
|
||||
_context6.t0 = _this3;
|
||||
_context6.next = 3;
|
||||
return get$1(fullUrl);
|
||||
|
||||
case 3:
|
||||
_context6.t1 = _context6.sent;
|
||||
return _context6.abrupt('return', _context6.t0.parse.call(_context6.t0, _context6.t1));
|
||||
|
||||
case 5:
|
||||
case 'end':
|
||||
return _context6.stop();
|
||||
}
|
||||
}
|
||||
}, _callee6, _this3);
|
||||
}))));
|
||||
|
||||
case 3:
|
||||
case 'end':
|
||||
return _context7.stop();
|
||||
}
|
||||
}
|
||||
}, _callee7, this);
|
||||
}));
|
||||
|
||||
function getTemplateFromUrl(_x10, _x11) {
|
||||
return _ref6.apply(this, arguments);
|
||||
}
|
||||
|
||||
return getTemplateFromUrl;
|
||||
}(),
|
||||
respectCache: function () {
|
||||
var _ref8 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(key, getter) {
|
||||
var cacheEnabled, value;
|
||||
return regeneratorRuntime.wrap(function _callee8$(_context8) {
|
||||
while (1) {
|
||||
switch (_context8.prev = _context8.next) {
|
||||
case 0:
|
||||
cacheEnabled = this.options.cache;
|
||||
|
||||
if (!(cacheEnabled && this.cache[key])) {
|
||||
_context8.next = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context8.abrupt('return', this.cache[key]);
|
||||
|
||||
case 3:
|
||||
_context8.next = 5;
|
||||
return getter();
|
||||
|
||||
case 5:
|
||||
value = _context8.sent;
|
||||
|
||||
if (cacheEnabled) {
|
||||
this.cache[key] = value;
|
||||
}
|
||||
return _context8.abrupt('return', value);
|
||||
|
||||
case 8:
|
||||
case 'end':
|
||||
return _context8.stop();
|
||||
}
|
||||
}
|
||||
}, _callee8, this);
|
||||
}));
|
||||
|
||||
function respectCache(_x12, _x13) {
|
||||
return _ref8.apply(this, arguments);
|
||||
}
|
||||
|
||||
return respectCache;
|
||||
}(),
|
||||
express: function express(opts) {
|
||||
opts = opts || {};
|
||||
var self = this;
|
||||
return function (filePath, ctx, cb) {
|
||||
assert(Array.isArray(this.root) || isString(this.root), 'illegal views root, are you using express.js?');
|
||||
assert(isArray(this.root) || isString(this.root), 'illegal views root, are you using express.js?');
|
||||
opts.root = this.root;
|
||||
self.renderFile(filePath, ctx, opts).then(function (html) {
|
||||
return cb(null, html);
|
||||
@@ -3652,7 +3581,7 @@ var _engine = {
|
||||
};
|
||||
|
||||
function normalizeStringArray(value) {
|
||||
if (Array.isArray(value)) return value;
|
||||
if (isArray(value)) return value;
|
||||
if (isString(value)) return [value];
|
||||
return [];
|
||||
}
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+175
-306
@@ -825,19 +825,6 @@
|
||||
return arr[arr.length - 1];
|
||||
}
|
||||
|
||||
function uniq(arr) {
|
||||
var u = {};
|
||||
var 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;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if value is the language type of Object.
|
||||
* (e.g. arrays, functions, objects, regexes, new Number(0), and new String(''))
|
||||
@@ -1229,24 +1216,74 @@
|
||||
return scope;
|
||||
}
|
||||
|
||||
function get$1(url) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onload = function () {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(xhr.responseText);
|
||||
} else {
|
||||
reject(new Error(xhr.statusText));
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
reject(new Error('An error occurred whilst sending the response.'));
|
||||
};
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
function domResolve(root, path) {
|
||||
var base = document.createElement('base');
|
||||
base.href = root;
|
||||
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
head.insertBefore(base, head.firstChild);
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.href = path;
|
||||
var resolved = a.href;
|
||||
head.removeChild(base);
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
function resolve(filepath, root, options) {
|
||||
root = root || options.root;
|
||||
if (isArray(root)) {
|
||||
root = root[0];
|
||||
}
|
||||
if (root.length && last(root) !== '/') {
|
||||
root += '/';
|
||||
}
|
||||
var url = domResolve(root, filepath);
|
||||
return url.replace(/^(\w+:\/\/[^/]+)(\/[^?]+)/, function (str, origin, path) {
|
||||
var last$$1 = path.split('/').pop();
|
||||
if (/\.\w+$/.test(last$$1)) {
|
||||
return str;
|
||||
}
|
||||
return origin + path + options.extname;
|
||||
});
|
||||
}
|
||||
|
||||
var read = function () {
|
||||
var _ref = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(url) {
|
||||
return regeneratorRuntime.wrap(function _callee$(_context) {
|
||||
while (1) {
|
||||
switch (_context.prev = _context.next) {
|
||||
case 0:
|
||||
return _context.abrupt('return', new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onload = function () {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(xhr.responseText);
|
||||
} else {
|
||||
reject(new Error(xhr.statusText));
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
reject(new Error('An error occurred whilst receiving the response.'));
|
||||
};
|
||||
xhr.open('GET', url);
|
||||
xhr.send();
|
||||
}));
|
||||
|
||||
case 1:
|
||||
case 'end':
|
||||
return _context.stop();
|
||||
}
|
||||
}
|
||||
}, _callee, this);
|
||||
}));
|
||||
|
||||
return function read(_x) {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
}();
|
||||
|
||||
function whiteSpaceCtrl(tokens, options) {
|
||||
options = assign({ greedy: true }, options);
|
||||
var inRaw = false;
|
||||
@@ -1372,65 +1409,6 @@
|
||||
};
|
||||
}
|
||||
|
||||
var fs = {};
|
||||
|
||||
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, function (err, stat) {
|
||||
return err ? reject(err) : resolve(stat);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var path = {};
|
||||
|
||||
var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/;
|
||||
var urlRe = /^(?:\w+:)?\/\/([^\s.]+\.\S{2}|localhost[:?\d]*)\S*$/;
|
||||
|
||||
// https://github.com/jinder/path/blob/master/path.js#L567
|
||||
function extname(path) {
|
||||
return splitPathRe.exec(path).slice(1)[3];
|
||||
}
|
||||
|
||||
// https://www.npmjs.com/package/is-url
|
||||
function valid(path) {
|
||||
return urlRe.test(path);
|
||||
}
|
||||
|
||||
function resolve(root, path) {
|
||||
if (isArray(root)) {
|
||||
root = root[0];
|
||||
}
|
||||
if (root && last(root) !== '/') {
|
||||
root += '/';
|
||||
}
|
||||
return resolveUrl(root, path);
|
||||
}
|
||||
|
||||
function resolveUrl(root, path) {
|
||||
var base = document.createElement('base');
|
||||
base.href = arguments[0];
|
||||
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
head.insertBefore(base, head.firstChild);
|
||||
|
||||
var a = document.createElement('a');
|
||||
a.href = path;
|
||||
var resolved = a.href;
|
||||
base.href = resolved;
|
||||
|
||||
head.removeChild(base);
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
function Operators (isTruthy) {
|
||||
return {
|
||||
'==': function _(l, r) {
|
||||
@@ -2005,15 +1983,6 @@
|
||||
* @param {Array} iteratee returns a new promise.
|
||||
* 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(function (e) {
|
||||
return iteratee(item, idx, iterable);
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call functions in serial until someone rejected.
|
||||
@@ -2049,7 +2018,7 @@
|
||||
collection = Liquid.evalExp(this.collection, scope);
|
||||
|
||||
|
||||
if (!Array.isArray(collection)) {
|
||||
if (!isArray(collection)) {
|
||||
if (isString(collection) && collection.length > 0) {
|
||||
collection = [collection];
|
||||
} else if (isObject(collection)) {
|
||||
@@ -2059,7 +2028,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (!(!Array.isArray(collection) || !collection.length)) {
|
||||
if (!(!isArray(collection) || !collection.length)) {
|
||||
_context2.next = 4;
|
||||
break;
|
||||
}
|
||||
@@ -3411,35 +3380,126 @@
|
||||
|
||||
return parseAndRender;
|
||||
}(),
|
||||
renderFile: function () {
|
||||
var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(filepath, ctx, opts) {
|
||||
var templates;
|
||||
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
||||
getTemplate: function () {
|
||||
var _ref2 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(file, root) {
|
||||
var _this = this;
|
||||
|
||||
var filepath;
|
||||
return regeneratorRuntime.wrap(function _callee3$(_context3) {
|
||||
while (1) {
|
||||
switch (_context2.prev = _context2.next) {
|
||||
switch (_context3.prev = _context3.next) {
|
||||
case 0:
|
||||
opts = assign({}, opts);
|
||||
_context2.next = 3;
|
||||
return this.getTemplate(filepath, opts.root);
|
||||
_context3.next = 2;
|
||||
return resolve(file, root, this.options);
|
||||
|
||||
case 3:
|
||||
templates = _context2.sent;
|
||||
return _context2.abrupt('return', this.render(templates, ctx, opts));
|
||||
case 2:
|
||||
filepath = _context3.sent;
|
||||
return _context3.abrupt('return', this.respectCache(filepath, asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
|
||||
var str;
|
||||
return regeneratorRuntime.wrap(function _callee2$(_context2) {
|
||||
while (1) {
|
||||
switch (_context2.prev = _context2.next) {
|
||||
case 0:
|
||||
_context2.next = 2;
|
||||
return read(filepath);
|
||||
|
||||
case 5:
|
||||
case 2:
|
||||
str = _context2.sent;
|
||||
return _context2.abrupt('return', _this.parse(str, filepath));
|
||||
|
||||
case 4:
|
||||
case 'end':
|
||||
return _context2.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2, _this);
|
||||
}))));
|
||||
|
||||
case 4:
|
||||
case 'end':
|
||||
return _context2.stop();
|
||||
return _context3.stop();
|
||||
}
|
||||
}
|
||||
}, _callee2, this);
|
||||
}, _callee3, this);
|
||||
}));
|
||||
|
||||
function renderFile(_x4, _x5, _x6) {
|
||||
function getTemplate(_x4, _x5) {
|
||||
return _ref2.apply(this, arguments);
|
||||
}
|
||||
|
||||
return getTemplate;
|
||||
}(),
|
||||
renderFile: function () {
|
||||
var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(file, ctx, opts) {
|
||||
var templates;
|
||||
return regeneratorRuntime.wrap(function _callee4$(_context4) {
|
||||
while (1) {
|
||||
switch (_context4.prev = _context4.next) {
|
||||
case 0:
|
||||
opts = assign({}, opts);
|
||||
_context4.next = 3;
|
||||
return this.getTemplate(file, opts.root);
|
||||
|
||||
case 3:
|
||||
templates = _context4.sent;
|
||||
return _context4.abrupt('return', this.render(templates, ctx, opts));
|
||||
|
||||
case 5:
|
||||
case 'end':
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, this);
|
||||
}));
|
||||
|
||||
function renderFile(_x6, _x7, _x8) {
|
||||
return _ref4.apply(this, arguments);
|
||||
}
|
||||
|
||||
return renderFile;
|
||||
}(),
|
||||
respectCache: function () {
|
||||
var _ref5 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(key, getter) {
|
||||
var cacheEnabled, value;
|
||||
return regeneratorRuntime.wrap(function _callee5$(_context5) {
|
||||
while (1) {
|
||||
switch (_context5.prev = _context5.next) {
|
||||
case 0:
|
||||
cacheEnabled = this.options.cache;
|
||||
|
||||
if (!(cacheEnabled && this.cache[key])) {
|
||||
_context5.next = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context5.abrupt('return', this.cache[key]);
|
||||
|
||||
case 3:
|
||||
_context5.next = 5;
|
||||
return getter();
|
||||
|
||||
case 5:
|
||||
value = _context5.sent;
|
||||
|
||||
if (cacheEnabled) {
|
||||
this.cache[key] = value;
|
||||
}
|
||||
return _context5.abrupt('return', value);
|
||||
|
||||
case 8:
|
||||
case 'end':
|
||||
return _context5.stop();
|
||||
}
|
||||
}
|
||||
}, _callee5, this);
|
||||
}));
|
||||
|
||||
function respectCache(_x9, _x10) {
|
||||
return _ref5.apply(this, arguments);
|
||||
}
|
||||
|
||||
return respectCache;
|
||||
}(),
|
||||
evalValue: function evalValue$$1(str, scope) {
|
||||
var tpl = this.parser.parseValue(str.trim());
|
||||
return this.renderer.evalValue(tpl, scope);
|
||||
@@ -3450,202 +3510,11 @@
|
||||
registerTag: function registerTag(name, tag) {
|
||||
return this.tag.register(name, tag);
|
||||
},
|
||||
lookup: function lookup(filepath, root) {
|
||||
var _this = this;
|
||||
|
||||
root = this.options.root.concat(root || []);
|
||||
root = uniq(root);
|
||||
var paths = root.map(function (root) {
|
||||
return path.resolve(root, filepath);
|
||||
});
|
||||
return anySeries(paths, function () {
|
||||
var _ref3 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(path$$1) {
|
||||
return regeneratorRuntime.wrap(function _callee3$(_context3) {
|
||||
while (1) {
|
||||
switch (_context3.prev = _context3.next) {
|
||||
case 0:
|
||||
_context3.prev = 0;
|
||||
_context3.next = 3;
|
||||
return statFileAsync(path$$1);
|
||||
|
||||
case 3:
|
||||
return _context3.abrupt('return', path$$1);
|
||||
|
||||
case 6:
|
||||
_context3.prev = 6;
|
||||
_context3.t0 = _context3['catch'](0);
|
||||
|
||||
_context3.t0.message = _context3.t0.code + ': Failed to lookup ' + filepath + ' in: ' + root;
|
||||
throw _context3.t0;
|
||||
|
||||
case 10:
|
||||
case 'end':
|
||||
return _context3.stop();
|
||||
}
|
||||
}
|
||||
}, _callee3, _this, [[0, 6]]);
|
||||
}));
|
||||
|
||||
return function (_x7) {
|
||||
return _ref3.apply(this, arguments);
|
||||
};
|
||||
}());
|
||||
},
|
||||
getTemplate: function getTemplate(filepath, root) {
|
||||
return typeof XMLHttpRequest === 'undefined' ? this.getTemplateFromFile(filepath, root) : this.getTemplateFromUrl(filepath, root);
|
||||
},
|
||||
getTemplateFromFile: function () {
|
||||
var _ref4 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(filepath, root) {
|
||||
var _this2 = this;
|
||||
|
||||
return regeneratorRuntime.wrap(function _callee5$(_context5) {
|
||||
while (1) {
|
||||
switch (_context5.prev = _context5.next) {
|
||||
case 0:
|
||||
if (!path.extname(filepath)) {
|
||||
filepath += this.options.extname;
|
||||
}
|
||||
_context5.next = 3;
|
||||
return this.lookup(filepath, root);
|
||||
|
||||
case 3:
|
||||
filepath = _context5.sent;
|
||||
return _context5.abrupt('return', this.respectCache(filepath, asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
|
||||
var str;
|
||||
return regeneratorRuntime.wrap(function _callee4$(_context4) {
|
||||
while (1) {
|
||||
switch (_context4.prev = _context4.next) {
|
||||
case 0:
|
||||
_context4.next = 2;
|
||||
return readFileAsync(filepath);
|
||||
|
||||
case 2:
|
||||
str = _context4.sent;
|
||||
return _context4.abrupt('return', _this2.parse(str, filepath));
|
||||
|
||||
case 4:
|
||||
case 'end':
|
||||
return _context4.stop();
|
||||
}
|
||||
}
|
||||
}, _callee4, _this2);
|
||||
}))));
|
||||
|
||||
case 5:
|
||||
case 'end':
|
||||
return _context5.stop();
|
||||
}
|
||||
}
|
||||
}, _callee5, this);
|
||||
}));
|
||||
|
||||
function getTemplateFromFile(_x8, _x9) {
|
||||
return _ref4.apply(this, arguments);
|
||||
}
|
||||
|
||||
return getTemplateFromFile;
|
||||
}(),
|
||||
getTemplateFromUrl: function () {
|
||||
var _ref6 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(filepath, root) {
|
||||
var _this3 = this;
|
||||
|
||||
var fullUrl;
|
||||
return regeneratorRuntime.wrap(function _callee7$(_context7) {
|
||||
while (1) {
|
||||
switch (_context7.prev = _context7.next) {
|
||||
case 0:
|
||||
fullUrl = void 0;
|
||||
|
||||
if (valid(filepath)) {
|
||||
fullUrl = filepath;
|
||||
} else {
|
||||
if (!extname(filepath)) {
|
||||
filepath += this.options.extname;
|
||||
}
|
||||
fullUrl = resolve(root || this.options.root, filepath);
|
||||
}
|
||||
return _context7.abrupt('return', this.respectCache(filepath, asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6() {
|
||||
return regeneratorRuntime.wrap(function _callee6$(_context6) {
|
||||
while (1) {
|
||||
switch (_context6.prev = _context6.next) {
|
||||
case 0:
|
||||
_context6.t0 = _this3;
|
||||
_context6.next = 3;
|
||||
return get$1(fullUrl);
|
||||
|
||||
case 3:
|
||||
_context6.t1 = _context6.sent;
|
||||
return _context6.abrupt('return', _context6.t0.parse.call(_context6.t0, _context6.t1));
|
||||
|
||||
case 5:
|
||||
case 'end':
|
||||
return _context6.stop();
|
||||
}
|
||||
}
|
||||
}, _callee6, _this3);
|
||||
}))));
|
||||
|
||||
case 3:
|
||||
case 'end':
|
||||
return _context7.stop();
|
||||
}
|
||||
}
|
||||
}, _callee7, this);
|
||||
}));
|
||||
|
||||
function getTemplateFromUrl(_x10, _x11) {
|
||||
return _ref6.apply(this, arguments);
|
||||
}
|
||||
|
||||
return getTemplateFromUrl;
|
||||
}(),
|
||||
respectCache: function () {
|
||||
var _ref8 = asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(key, getter) {
|
||||
var cacheEnabled, value;
|
||||
return regeneratorRuntime.wrap(function _callee8$(_context8) {
|
||||
while (1) {
|
||||
switch (_context8.prev = _context8.next) {
|
||||
case 0:
|
||||
cacheEnabled = this.options.cache;
|
||||
|
||||
if (!(cacheEnabled && this.cache[key])) {
|
||||
_context8.next = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return _context8.abrupt('return', this.cache[key]);
|
||||
|
||||
case 3:
|
||||
_context8.next = 5;
|
||||
return getter();
|
||||
|
||||
case 5:
|
||||
value = _context8.sent;
|
||||
|
||||
if (cacheEnabled) {
|
||||
this.cache[key] = value;
|
||||
}
|
||||
return _context8.abrupt('return', value);
|
||||
|
||||
case 8:
|
||||
case 'end':
|
||||
return _context8.stop();
|
||||
}
|
||||
}
|
||||
}, _callee8, this);
|
||||
}));
|
||||
|
||||
function respectCache(_x12, _x13) {
|
||||
return _ref8.apply(this, arguments);
|
||||
}
|
||||
|
||||
return respectCache;
|
||||
}(),
|
||||
express: function express(opts) {
|
||||
opts = opts || {};
|
||||
var self = this;
|
||||
return function (filePath, ctx, cb) {
|
||||
assert(Array.isArray(this.root) || isString(this.root), 'illegal views root, are you using express.js?');
|
||||
assert(isArray(this.root) || isString(this.root), 'illegal views root, are you using express.js?');
|
||||
opts.root = this.root;
|
||||
self.renderFile(filePath, ctx, opts).then(function (html) {
|
||||
return cb(null, html);
|
||||
@@ -3655,7 +3524,7 @@
|
||||
};
|
||||
|
||||
function normalizeStringArray(value) {
|
||||
if (Array.isArray(value)) return value;
|
||||
if (isArray(value)) return value;
|
||||
if (isString(value)) return [value];
|
||||
return [];
|
||||
}
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Generated
+3743
-1324
File diff suppressed because it is too large
Load Diff
+10
-6
@@ -7,11 +7,10 @@
|
||||
"browser": "dist/liquid.js",
|
||||
"scripts": {
|
||||
"lint": "eslint src/ test/ *.js",
|
||||
"test": "npm run test:unit && npm run test:e2e",
|
||||
"test:unit": "mocha test/unit",
|
||||
"test:e2e": "mocha test/e2e",
|
||||
"test": "mocha test/unit",
|
||||
"e2e": "mocha test/e2e",
|
||||
"coverage": "cross-env NODE_ENV=test nyc report --reporter=html mocha test/unit",
|
||||
"coveralls": "cross-env NODE_ENV=test nyc report --reporter=text-lcov mocha | coveralls",
|
||||
"coveralls": "cross-env NODE_ENV=test nyc report --reporter=text-lcov mocha test/unit | coveralls",
|
||||
"dist": "rollup -c && ls -lh dist",
|
||||
"demo:browser": "echo open http://localhost:8080/demo/browser && http-server -c-1",
|
||||
"demo:nodejs": "node ./demo/nodejs/index.js",
|
||||
@@ -66,6 +65,7 @@
|
||||
"nyc": "^12.0.2",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"rollup": "^0.64.1",
|
||||
"rollup-plugin-alias": "^1.4.0",
|
||||
"rollup-plugin-babel": "^3.0.7",
|
||||
"rollup-plugin-node-resolve": "^3.3.0",
|
||||
"rollup-plugin-shim": "^1.0.0",
|
||||
@@ -82,7 +82,9 @@
|
||||
"instrument": false
|
||||
},
|
||||
"babel": {
|
||||
"presets": ["env"],
|
||||
"presets": [
|
||||
"env"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"transform-runtime",
|
||||
@@ -96,7 +98,9 @@
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
"plugins": ["istanbul"]
|
||||
"plugins": [
|
||||
"istanbul"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import shim from 'rollup-plugin-shim'
|
||||
import alias from 'rollup-plugin-alias'
|
||||
import babel from 'rollup-plugin-babel'
|
||||
import {uglify} from 'rollup-plugin-uglify'
|
||||
import pkg from './package.json'
|
||||
@@ -48,6 +49,9 @@ export default [{
|
||||
}],
|
||||
plugins: [
|
||||
shim(fake),
|
||||
alias({
|
||||
'./template': './template-browser'
|
||||
}),
|
||||
nodeResolve(),
|
||||
babel(babelConf)
|
||||
],
|
||||
|
||||
+20
-61
@@ -1,18 +1,14 @@
|
||||
import 'regenerator-runtime/runtime'
|
||||
import * as Scope from './scope'
|
||||
import {get as httpGet} from './util/http.js'
|
||||
import * as template from './template'
|
||||
import * as _ from './util/underscore.js'
|
||||
import assert from './util/assert.js'
|
||||
import * as tokenizer from './tokenizer.js'
|
||||
import {statFileAsync, readFileAsync} from './util/fs.js'
|
||||
import path from 'path'
|
||||
import {valid as isValidUrl, extname, resolve} from './util/url.js'
|
||||
import Render from './render.js'
|
||||
import Tag from './tag.js'
|
||||
import Filter from './filter.js'
|
||||
import Parser from './parser'
|
||||
import {isTruthy, isFalsy, evalExp, evalValue} from './syntax.js'
|
||||
import {anySeries} from './util/promise.js'
|
||||
import {ParseError, TokenizationError, RenderBreakError, AssertionError} from './util/error.js'
|
||||
import tags from './tags/index.js'
|
||||
import filters from './filters.js'
|
||||
@@ -46,64 +42,17 @@ const _engine = {
|
||||
const tpl = await this.parse(html)
|
||||
return this.render(tpl, ctx, opts)
|
||||
},
|
||||
renderFile: async function (filepath, ctx, opts) {
|
||||
opts = _.assign({}, opts)
|
||||
const templates = await this.getTemplate(filepath, opts.root)
|
||||
return this.render(templates, ctx, opts)
|
||||
},
|
||||
evalValue: function (str, scope) {
|
||||
const tpl = this.parser.parseValue(str.trim())
|
||||
return this.renderer.evalValue(tpl, scope)
|
||||
},
|
||||
registerFilter: function (name, filter) {
|
||||
return this.filter.register(name, filter)
|
||||
},
|
||||
registerTag: function (name, tag) {
|
||||
return this.tag.register(name, tag)
|
||||
},
|
||||
lookup: function (filepath, root) {
|
||||
root = this.options.root.concat(root || [])
|
||||
root = _.uniq(root)
|
||||
const paths = root.map(root => path.resolve(root, filepath))
|
||||
return anySeries(paths, async path => {
|
||||
try {
|
||||
await statFileAsync(path)
|
||||
return path
|
||||
} catch (e) {
|
||||
e.message = `${e.code}: Failed to lookup ${filepath} in: ${root}`
|
||||
throw e
|
||||
}
|
||||
})
|
||||
},
|
||||
getTemplate: function (filepath, root) {
|
||||
return typeof XMLHttpRequest === 'undefined'
|
||||
? this.getTemplateFromFile(filepath, root)
|
||||
: this.getTemplateFromUrl(filepath, root)
|
||||
},
|
||||
getTemplateFromFile: async function (filepath, root) {
|
||||
if (!path.extname(filepath)) {
|
||||
filepath += this.options.extname
|
||||
}
|
||||
filepath = await this.lookup(filepath, root)
|
||||
getTemplate: async function (file, root) {
|
||||
const filepath = await template.resolve(file, root, this.options)
|
||||
return this.respectCache(filepath, async () => {
|
||||
const str = await readFileAsync(filepath)
|
||||
const str = await template.read(filepath)
|
||||
return this.parse(str, filepath)
|
||||
})
|
||||
},
|
||||
getTemplateFromUrl: async function (filepath, root) {
|
||||
let fullUrl
|
||||
if (isValidUrl(filepath)) {
|
||||
fullUrl = filepath
|
||||
} else {
|
||||
if (!extname(filepath)) {
|
||||
filepath += this.options.extname
|
||||
}
|
||||
fullUrl = resolve(root || this.options.root, filepath)
|
||||
}
|
||||
return this.respectCache(
|
||||
filepath,
|
||||
async () => this.parse(await httpGet(fullUrl))
|
||||
)
|
||||
renderFile: async function (file, ctx, opts) {
|
||||
opts = _.assign({}, opts)
|
||||
const templates = await this.getTemplate(file, opts.root)
|
||||
return this.render(templates, ctx, opts)
|
||||
},
|
||||
respectCache: async function (key, getter) {
|
||||
const cacheEnabled = this.options.cache
|
||||
@@ -116,11 +65,21 @@ const _engine = {
|
||||
}
|
||||
return value
|
||||
},
|
||||
evalValue: function (str, scope) {
|
||||
const tpl = this.parser.parseValue(str.trim())
|
||||
return this.renderer.evalValue(tpl, scope)
|
||||
},
|
||||
registerFilter: function (name, filter) {
|
||||
return this.filter.register(name, filter)
|
||||
},
|
||||
registerTag: function (name, tag) {
|
||||
return this.tag.register(name, tag)
|
||||
},
|
||||
express: function (opts) {
|
||||
opts = opts || {}
|
||||
const self = this
|
||||
return function (filePath, ctx, cb) {
|
||||
assert(Array.isArray(this.root) || _.isString(this.root),
|
||||
assert(_.isArray(this.root) || _.isString(this.root),
|
||||
'illegal views root, are you using express.js?')
|
||||
opts.root = this.root
|
||||
self.renderFile(filePath, ctx, opts).then(html => cb(null, html), cb)
|
||||
@@ -129,7 +88,7 @@ const _engine = {
|
||||
}
|
||||
|
||||
function normalizeStringArray (value) {
|
||||
if (Array.isArray(value)) return value
|
||||
if (_.isArray(value)) return value
|
||||
if (_.isString(value)) return [value]
|
||||
return []
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
import {mapSeries} from '../util/promise.js'
|
||||
import {isString, isObject} from '../util/underscore.js'
|
||||
import {isString, isObject, isArray} from '../util/underscore.js'
|
||||
import assert from '../util/assert.js'
|
||||
import {identifier, value, hash} from '../lexical.js'
|
||||
|
||||
@@ -38,14 +38,14 @@ export default function (liquid, Liquid) {
|
||||
async function render (scope, hash) {
|
||||
let collection = Liquid.evalExp(this.collection, scope)
|
||||
|
||||
if (!Array.isArray(collection)) {
|
||||
if (!isArray(collection)) {
|
||||
if (isString(collection) && collection.length > 0) {
|
||||
collection = [collection]
|
||||
} else if (isObject(collection)) {
|
||||
collection = Object.keys(collection).map((key) => [key, collection[key]])
|
||||
}
|
||||
}
|
||||
if (!Array.isArray(collection) || !collection.length) {
|
||||
if (!isArray(collection) || !collection.length) {
|
||||
return liquid.renderer.renderTemplates(this.elseTemplates, scope)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import {last, isArray} from './util/underscore'
|
||||
|
||||
function domResolve (root, path) {
|
||||
const base = document.createElement('base')
|
||||
base.href = root
|
||||
|
||||
const head = document.getElementsByTagName('head')[0]
|
||||
head.insertBefore(base, head.firstChild)
|
||||
|
||||
const a = document.createElement('a')
|
||||
a.href = path
|
||||
const resolved = a.href
|
||||
head.removeChild(base)
|
||||
|
||||
return resolved
|
||||
}
|
||||
|
||||
export function resolve (filepath, root, options) {
|
||||
root = root || options.root
|
||||
if (isArray(root)) {
|
||||
root = root[0]
|
||||
}
|
||||
if (root.length && last(root) !== '/') {
|
||||
root += '/'
|
||||
}
|
||||
const url = domResolve(root, filepath)
|
||||
return url.replace(/^(\w+:\/\/[^/]+)(\/[^?]+)/, (str, origin, path) => {
|
||||
const last = path.split('/').pop()
|
||||
if (/\.\w+$/.test(last)) {
|
||||
return str
|
||||
}
|
||||
return origin + path + options.extname
|
||||
})
|
||||
}
|
||||
|
||||
export async function read (url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.onload = () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(xhr.responseText)
|
||||
} else {
|
||||
reject(new Error(xhr.statusText))
|
||||
}
|
||||
}
|
||||
xhr.onerror = () => {
|
||||
reject(new Error('An error occurred whilst receiving the response.'))
|
||||
}
|
||||
xhr.open('GET', url)
|
||||
xhr.send()
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import * as _ from './util/underscore.js'
|
||||
import path from 'path'
|
||||
import {anySeries} from './util/promise.js'
|
||||
import {statFileAsync, readFileAsync} from './util/fs.js'
|
||||
|
||||
function lookup (filepath, root, options) {
|
||||
root = options.root.concat(root || [])
|
||||
root = _.uniq(root)
|
||||
const paths = root.map(root => path.resolve(root || location.href, filepath))
|
||||
return anySeries(paths, async path => {
|
||||
try {
|
||||
await statFileAsync(path)
|
||||
return path
|
||||
} catch (e) {
|
||||
e.message = `${e.code}: Failed to lookup ${filepath} in: ${root}`
|
||||
throw e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function resolve (filepath, root, options) {
|
||||
if (!path.extname(filepath)) {
|
||||
filepath += options.extname
|
||||
}
|
||||
return lookup(filepath, root, options)
|
||||
}
|
||||
|
||||
export async function read (filepath) {
|
||||
return readFileAsync(filepath)
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
export function get (url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.onload = () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(xhr.responseText)
|
||||
} else {
|
||||
reject(new Error(xhr.statusText))
|
||||
}
|
||||
}
|
||||
xhr.onerror = () => {
|
||||
reject(new Error('An error occurred whilst sending the response.'))
|
||||
}
|
||||
xhr.open('GET', url)
|
||||
xhr.send()
|
||||
})
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import {last, isArray} from './underscore'
|
||||
|
||||
const splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^/]+?|)(\.[^./]*|))(?:[/]*)$/
|
||||
const urlRe = /^(?:\w+:)?\/\/([^\s.]+\.\S{2}|localhost[:?\d]*)\S*$/
|
||||
|
||||
// https://github.com/jinder/path/blob/master/path.js#L567
|
||||
export function extname (path) {
|
||||
return splitPathRe.exec(path).slice(1)[3]
|
||||
}
|
||||
|
||||
// https://www.npmjs.com/package/is-url
|
||||
export function valid (path) {
|
||||
return urlRe.test(path)
|
||||
}
|
||||
|
||||
export function resolve (root, path) {
|
||||
if (isArray(root)) {
|
||||
root = root[0]
|
||||
}
|
||||
if (root && last(root) !== '/') {
|
||||
root += '/'
|
||||
}
|
||||
return resolveUrl(root, path)
|
||||
}
|
||||
|
||||
function resolveUrl (root, path) {
|
||||
const base = document.createElement('base')
|
||||
base.href = arguments[0]
|
||||
|
||||
const head = document.getElementsByTagName('head')[0]
|
||||
head.insertBefore(base, head.firstChild)
|
||||
|
||||
const a = document.createElement('a')
|
||||
a.href = path
|
||||
const resolved = a.href
|
||||
base.href = resolved
|
||||
|
||||
head.removeChild(base)
|
||||
|
||||
return resolved
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@ const chai = require('chai')
|
||||
const request = require('supertest')
|
||||
const express = require('express')
|
||||
const mock = require('mock-fs')
|
||||
const Liquid = require('../..')
|
||||
const Liquid = require('../../dist/liquid.common.js')
|
||||
const chaiAsPromised = require('chai-as-promised')
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
+13
-9
@@ -1,4 +1,4 @@
|
||||
var Liquid = require('../..')
|
||||
var Liquid = require('../../dist/liquid.js')
|
||||
var sinon = require('sinon')
|
||||
var chai = require('chai')
|
||||
var expect = chai.expect
|
||||
@@ -6,16 +6,17 @@ chai.use(require('chai-as-promised'))
|
||||
|
||||
describe('xhr', () => {
|
||||
if (process.version.match(/^v(\d+)/)[1] < 8) {
|
||||
console.info('jsdom not supported, skipping xhr...')
|
||||
return
|
||||
}
|
||||
var JSDOM = require('jsdom').JSDOM
|
||||
var server, engine, dom
|
||||
var server, engine
|
||||
beforeEach(() => {
|
||||
server = sinon.createFakeServer()
|
||||
server.autoRespond = true
|
||||
server.respondWith('GET', 'https://example.com/views/hello.html',
|
||||
[200, {'Content-Type': 'text/plain'}, 'hello {{name}}'])
|
||||
dom = new JSDOM('', {
|
||||
var dom = new JSDOM('', {
|
||||
url: 'https://example.com/foo/bar.html',
|
||||
contentType: 'text/html',
|
||||
includeNodeLocations: true
|
||||
@@ -65,15 +66,18 @@ describe('xhr', () => {
|
||||
})
|
||||
it('should throw error', function (done) {
|
||||
engine.renderFile('hello.html')
|
||||
.then(() => done('should not be resolved'))
|
||||
.catch(function (e) {
|
||||
expect(e.message).to.equal('An error occurred whilst sending the response.')
|
||||
expect(e.message).to.equal('An error occurred whilst receiving the response.')
|
||||
done()
|
||||
})
|
||||
server.requests[0].error()
|
||||
global.XMLHttpRequest.onCreate = function (request) {
|
||||
setTimeout(() => request.error())
|
||||
}
|
||||
})
|
||||
})
|
||||
describe('root', () => {
|
||||
it('should support with null', () => {
|
||||
describe('#renderFile() with root specified', () => {
|
||||
it('should support undefined root', () => {
|
||||
engine = Liquid({
|
||||
extname: '.html'
|
||||
})
|
||||
@@ -82,12 +86,12 @@ describe('xhr', () => {
|
||||
return expect(engine.renderFile('hello.html', {name: 'alice5'}))
|
||||
.to.eventually.equal('hello alice5')
|
||||
})
|
||||
it('should support with empty', () => {
|
||||
it('should support empty root', () => {
|
||||
engine = Liquid({
|
||||
root: '',
|
||||
extname: '.html'
|
||||
})
|
||||
server.respondWith('GET', 'https://example.com/foo/hello.html',
|
||||
server.respondWith('https://example.com/foo/hello.html',
|
||||
[200, {'Content-Type': 'text/plain'}, 'hello {{name}}'])
|
||||
return expect(engine.renderFile('hello.html', {name: 'alice5'}))
|
||||
.to.eventually.equal('hello alice5')
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import {resolve} from '../../src/template-browser.js'
|
||||
import chai from 'chai'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('template-browser', function () {
|
||||
if (process.version.match(/^v(\d+)/)[1] < 8) {
|
||||
console.info('jsdom not supported, skipping template-browser...')
|
||||
return
|
||||
}
|
||||
const JSDOM = require('jsdom').JSDOM
|
||||
beforeEach(function () {
|
||||
const dom = new JSDOM(``, {
|
||||
url: 'https://example.com/foo/bar/',
|
||||
contentType: 'text/html',
|
||||
includeNodeLocations: true
|
||||
})
|
||||
global.document = dom.window.document
|
||||
})
|
||||
afterEach(function () {
|
||||
delete global.document
|
||||
})
|
||||
describe('resolve', function () {
|
||||
it('should support relative root', function () {
|
||||
expect(resolve('foo', './views/', {
|
||||
extname: '',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/foo/bar/views/foo')
|
||||
})
|
||||
it('should treat root as directory', function () {
|
||||
expect(resolve('foo', './views', {
|
||||
extname: '',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/foo/bar/views/foo')
|
||||
})
|
||||
it('should support absolute root', function () {
|
||||
expect(resolve('foo', '/views', {
|
||||
extname: '',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/views/foo')
|
||||
})
|
||||
it('should support empty root', function () {
|
||||
expect(resolve('page.html', '', {
|
||||
extname: '',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/foo/bar/page.html')
|
||||
})
|
||||
it('should support full url as root', function () {
|
||||
expect(resolve('page.html', 'https://example.com/views/', {
|
||||
extname: '',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/views/page.html')
|
||||
})
|
||||
it('should use options.root when root argument absent', function () {
|
||||
expect(resolve('page.html', null, {
|
||||
extname: '',
|
||||
root: ['https://example.com/views', 'https://google.com/views']
|
||||
})).to.equal('https://example.com/views/page.html')
|
||||
})
|
||||
it('should add extname when absent', function () {
|
||||
expect(resolve('page', 'https://example.com/views/', {
|
||||
extname: '.html',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/views/page.html')
|
||||
})
|
||||
it('should add extname for urls have searchParams', function () {
|
||||
expect(resolve('page?foo=bar', 'https://example.com/views/', {
|
||||
extname: '.html',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/views/page.html?foo=bar')
|
||||
})
|
||||
it('should not add extname when full url is given', function () {
|
||||
expect(resolve('https://google.com/page.php', 'https://example.com/views/', {
|
||||
extname: '.html',
|
||||
root: ['.']
|
||||
})).to.equal('https://google.com/page.php')
|
||||
})
|
||||
it('should not add extname when already have one', function () {
|
||||
expect(resolve('page.php', 'https://example.com/views/', {
|
||||
extname: '.html',
|
||||
root: ['.']
|
||||
})).to.equal('https://example.com/views/page.php')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,63 +0,0 @@
|
||||
import {extname, resolve} from '../../../src/util/url.js'
|
||||
import chai from 'chai'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('util/url', function () {
|
||||
if (process.version.match(/^v(\d+)/)[1] < 8) {
|
||||
return
|
||||
}
|
||||
const JSDOM = require('jsdom').JSDOM
|
||||
let dom
|
||||
beforeEach(function () {
|
||||
dom = new JSDOM(``, {
|
||||
url: 'https://example.com/foo/bar/',
|
||||
contentType: 'text/html',
|
||||
includeNodeLocations: true
|
||||
})
|
||||
global.document = dom.window.document
|
||||
})
|
||||
afterEach(function () {
|
||||
delete global.document
|
||||
})
|
||||
describe('resolve', function () {
|
||||
describe('root', function () {
|
||||
it('should support relative root', function () {
|
||||
expect(resolve('./views', 'foo'))
|
||||
.to.equal('https://example.com/foo/bar/views/foo')
|
||||
expect(resolve('./views/', 'foo'))
|
||||
.to.equal('https://example.com/foo/bar/views/foo')
|
||||
})
|
||||
it('should support absolute root', function () {
|
||||
expect(resolve('/views', 'foo'))
|
||||
.to.equal('https://example.com/views/foo')
|
||||
expect(resolve('/views/', 'foo'))
|
||||
.to.equal('https://example.com/views/foo')
|
||||
})
|
||||
it('should support empty root', function () {
|
||||
expect(resolve('', 'page.html'))
|
||||
.to.equal('https://example.com/foo/bar/page.html')
|
||||
})
|
||||
it('should support full url as root', function () {
|
||||
expect(resolve('https://example.com/views', 'page.html'))
|
||||
.to.equal('https://example.com/views/page.html')
|
||||
expect(resolve('https://example.com/views/', 'page.html'))
|
||||
.to.equal('https://example.com/views/page.html')
|
||||
})
|
||||
it('should get the first value when argument is array', function () {
|
||||
expect(resolve(['https://example.com/views', 'https://google.com/views'], 'page.html'))
|
||||
.to.equal('https://example.com/views/page.html')
|
||||
expect(resolve(['https://example.com/views/', 'https://google.com/views'], 'page.html'))
|
||||
.to.equal('https://example.com/views/page.html')
|
||||
})
|
||||
})
|
||||
describe('extname', function () {
|
||||
it('should support relative path', function () {
|
||||
expect(extname('./views/page.html')).to.equal('.html')
|
||||
})
|
||||
it('should support absolute path', function () {
|
||||
expect(extname('/views/page.xml')).to.equal('.xml')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user