'use strict';
var Parser = require('./parse/index');
var _parse = Parser.parse;
var utils = require('./utils');
var blockTypes = {
if: true,
foreach: true,
macro: true,
noescape: true,
define: true
};
var customBlocks = [];
/**
* @param {string} str string to parse
* @param {object} blocks self define blocks, such as `#cms(1) hello #end`
* @param {boolean} ignoreSpace if set true, then ignore the newline trim.
* @return {array} ast array
*/
var parse = function(str, blocks, ignoreSpace) {
var asts = _parse(str);
customBlocks = blocks || {};
/**
* remove all newline after all direction such as `#set, #each`
*/
ignoreSpace || utils.forEach(asts, function trim(ast, i) {
var TRIM_REG = /^[ \t]*\n/;
if (ast.type && ast.type !== 'references') {
var _ast = asts[i + 1];
if (typeof _ast === 'string' && TRIM_REG.test(_ast)) {
asts[i + 1] = _ast.replace(TRIM_REG, '');
}
}
});
var ret = makeLevel(asts);
return utils.isArray(ret) ? ret : ret.arr;
};
function makeLevel(block, index) {
var len = block.length;
index = index || 0;
var ret = [];
var ignore = index - 1;
for (var i = index; i < len; i++) {
if (i <= ignore) continue;
var ast = block[i];
var type = ast.type;
var isBlockType = blockTypes[type];
// 自定义类型支持
if (!isBlockType && ast.type === 'macro_call' && customBlocks[ast.id]) {
isBlockType = true;
ast.type = ast.id;
delete ast.id;
}
if (!isBlockType && type !== 'end') {
ret.push(ast);
} else if (type === 'end') {
return {arr: ret, step: i};
} else {
var _ret = makeLevel(block, i + 1);
ignore = _ret.step;
_ret.arr.unshift(block[i]);
ret.push(_ret.arr);
}
}
return ret;
}
module.exports = parse;
|