parser.js
function compile(content, filePath, opt) {
  var fileUrl, //include的文件地址
    templateFile; //include的文件内容

  //如果文件目录下存在config.js，则将以ejs模板的形式包装
  var configPath = path.join(path.dirname(filePath), configName);
  if (fs.existsSync(configPath)) {
    var delimiter = ejs.delimiter || "%";
    var configFile = "<" + delimiter + fs.readFileSync(configPath).toString() + delimiter + ">";
    content = configFile + content;
  }

  opt = opt || {};

  try {
    var result = ejs.render(content, opt);
  } catch (e) {
    console.log("\x1B[31mbuild " + filePath + " fail\x1B[0m");
    console.log("\x1B[31mEjs error：" + e.message + "\x1B[0m");
    return;
  }

  var fragments = [];
  var matches;
  var str = result;

  // 递归处理html内容
  while(matches = str.match(includeRegx)) {
    fragments.push(str.substring(0, matches.index));

    var obj, nobj;
    var space = RegExp.$1;
    fileUrl = RegExp.$2;
    obj = RegExp.$3 || "{}";

    if (!(typeof baseDir === "string") || NOBASE_RE.test(fileUrl)) {
      fileUrl = url.resolve(filePath, fileUrl);
    } else {
      fileUrl = path.join(baseDir, fileUrl);
    }

    //如果文件没有文件类型扩展名，则加上
    fileUrl += (new RegExp("." + suffix + "$")).test(fileUrl) ? "" : ("." + suffix);

    // 如果有template才进一步处理
    if (templateFile = getFileString(fileUrl)) {
      //获取@@include里传入的参数，并转成对象
      try {
        obj = eval("(" + obj.replace(/\r\n/, '') + ")");
      } catch (e) {
        obj = {};
      }

      //将参数对象拷贝，并且与include里传入的参数合并
      nobj = deepCopy(opt);

      for (var k in obj) {
        nobj[k] = obj[k];
      }

      // 把引用的html文件也扔进文档流
      fragments.push(compile(templateFile, fileUrl, nobj) || '');
    }

    // 更新剩余扫描的字符
    str = str.substring(matches.index + matches[0].length);
  }

  fragments.push(str);

  // 返回组装的数据
  return fragments.join('');
}
function compile(content, filePath, opt) {
  var fileUrl, //include的文件地址
    templateFile; //include的文件内容

  //如果文件目录下存在config.js，则将以ejs模板的形式包装
  var configPath = path.join(path.dirname(filePath), configName);
  if (fs.existsSync(configPath)) {
    var delimiter = ejs.delimiter || "%";
    var configFile = "<" + delimiter + fs.readFileSync(configPath).toString() + delimiter + ">";
    content = configFile + content;
  }

  opt = opt || {};

  try {
    var result = ejs.render(content, opt);
  } catch (e) {
    console.log("\x1B[31mbuild " + filePath + " fail\x1B[0m");
    console.log("\x1B[31mEjs error：" + e.message + "\x1B[0m");
    return;
  }

  var fragments = [];
  var matches;
  var str = result;

  // 递归处理html内容
  while(matches = str.match(includeRegx)) {
    fragments.push(str.substring(0, matches.index));

    var obj, nobj;
    var space = RegExp.$1;
    fileUrl = RegExp.$2;
    obj = RegExp.$3 || "{}";

    if (!(typeof baseDir === "string") || NOBASE_RE.test(fileUrl)) {
      fileUrl = url.resolve(filePath, fileUrl);
    } else {
      fileUrl = path.join(baseDir, fileUrl);
    }

    //如果文件没有文件类型扩展名，则加上
    fileUrl += (new RegExp("." + suffix + "$")).test(fileUrl) ? "" : ("." + suffix);

    // 如果有template才进一步处理
    if (templateFile = getFileString(fileUrl)) {
      //获取@@include里传入的参数，并转成对象
      try {
        obj = eval("(" + obj.replace(/\r\n/, '') + ")");
      } catch (e) {
        obj = {};
      }

      //将参数对象拷贝，并且与include里传入的参数合并
      nobj = deepCopy(opt);

      for (var k in obj) {
        nobj[k] = obj[k];
      }

      // 把引用的html文件也扔进文档流
      fragments.push(compile(templateFile, fileUrl, nobj) || '');
    }

    // 更新剩余扫描的字符
    str = str.substring(matches.index + matches[0].length);
  }

  fragments.push(str);

  // 返回组装的数据
  return fragments.join('');
}
将@@include替换成相应文件