根据算法，获得指定版本
http://stackoverflow.com/questions/22343224/difference-between-tilde-and-caret-in-package-json
http://fredkschott.com/post/2014/02/npm-no-longer-defaults-to-tildes/
345588
function getTargetVersion(body, args) {
  var versionArr = Object.keys(body.packages),
      argsVersion = args.version || 'stable';

  argsVersion = argsVersion.trim();

  // 如果package.json中配置了db:*，则返回最新版本
  if(argsVersion == '*'){
    // 获取最新
  }

  // db 或 db@stable: lego install db或者lego install db@stable
  else if(argsVersion.indexOf('.') < 0){
    versionArr = versionArr.filter(function(cur) {
      return body.packages[cur].tag === argsVersion;
    });
  }

  // 如果package.json中配置了db:~1.2.3，则返回 1.2.*<= version < 1.3.*
  // 但有特例，以0开始的版本，db:~0.1.2 和 db:^0.1.2，都返回 0.1.x <= version < 0.2.*
  else if (argsVersion.indexOf('~') === 0 || argsVersion.indexOf('^0') === 0) {
    // 只要比较第一位和第二位数字相同即可
    var targetArr = getArrFromVersion(argsVersion.substr(1));
    if (targetArr.length > 1) {
      versionArr = versionArr.filter(function(cur) {
        var curArr = getArrFromVersion(cur);
        return curArr.length > 1 && curArr[0] === targetArr[0] && curArr[1] === targetArr[1];
      });
    }
  }

  // 如果package.json中配置了db:^1.2.3，则返回 1.2.*<= version < 2.*.*
  // 但有特例，以0开始的版本，db:~0.1.2 和 db:^0.1.2，都返回 0.1.x <= version < 0.2.*
  else if (argsVersion.indexOf('^') === 0) {
    // 只要比较第一位和第二位数字相同即可
    var targetArr = getArrFromVersion(argsVersion.substr(1));
    if (targetArr.length > 1) {
      versionArr = versionArr.filter(function(cur) {
        var curArr = getArrFromVersion(cur);
        return curArr.length > 1 && curArr[0] === targetArr[0];
      });
    }
  }

  // 其他情况只考虑指定版本，例如 lego install db@1.2.3或者在package.json中定义了db:1.2.3
  else {
    versionArr = versionArr.filter(function(cur) {
      return cur === argsVersion;
    });
  }

  // 排序使版本号从大到小
  versionArr.sort(function(a, b) {
    var aArr = a.split('.'),
        bArr = b.split('.');

    for (var i = 0; i < 3; i++) {
      var na = parseInt(aArr[i], 10),
          nb = parseInt(bArr[i], 10);

      if (na > nb) {
        return -1;
      } else if (na < nb) {
        return 1;
      }
    }

    return 0;
  });

  // 返回排序之后的最大的版本号
  return versionArr[0];
}
227777
function commitlint () {
  const baseDir = getBaseDir()

  co(function * () {
    const readOptions = {
      cwd: baseDir,
      edit: '.git/COMMIT_EDITMSG'
    }

    debug('commitlint.read options: %o', readOptions)

    const gitMsgFilePath = path.join(readOptions.cwd, readOptions.edit)

    if (!fs.existsSync(gitMsgFilePath)) {
      debug(`can not found "${gitMsgFilePath}"`)
      throw new Error('无法读取 git commit 信息')
    }

    const [message, config] = yield Promise.all([read(readOptions), load()])

    debug('git commit message: %o', message)
    debug('commitlint config: %o', config)

    const rules = config.rules
    const options = config.parserPreset ? { parserOpts: config.parserPreset.parserOpts } : {}
    const report = yield lint(message[0], rules, options)
    const formatted = format({
      results: [report]
    })

    console.log()
    console.log(Array.isArray(formatted) ? formatted.join('\n') : formatted)
    console.log()

    process.exit(report.errors.length ? 1 : 0)
  }).catch(error => {
    log.error(error.message)
    process.exit(1)
  })
}
45592
function parsePackScript(file, context, opts) {
    var content = file.getContent();
    var packScriptFiles = [];

    var hasScriptPlaceholder
        = content.indexOf(opts.scriptPlaceholder) !== -1;
    var hasScriptAsyncPlaceholder
        = content.indexOf(opts.scriptAsyncPlaceholder) !== -1;
    var hasRequireConfigPlaceholder
        = content.indexOf(opts.resourceConfigPlaceholder) !== -1;

    var getPlaceholder = function (isLoader) {
        if (!opts.autoInsertPlaceholder) {
            return;
        }
        // 在requirejs之后 requrie.config 脚本
        if (isLoader && !hasRequireConfigPlaceholder) {
            hasRequireConfigPlaceholder = true;
            return opts.resourceConfigPlaceholder;
        }
        //在异步入口模块前插入合成后的pkg
        else if (!hasScriptAsyncPlaceholder) {
            hasScriptAsyncPlaceholder = true;
            return opts.scriptAsyncPlaceholder;
        }
    };
    /*
    //在body之前插入scriptPlaceholder
    if(!hasScriptPlaceholder){
        hasScriptPlaceholder = true;
        var rBody = /<!--([\s\S]*?)(?:-->|$)|<\/body>/ig;
         content = content.replace(rBody, function(all, comment) {
          if (comment) {
            return all;
          } else {
            return '\n' + opts.scriptPlaceholder + '\n' + all;
          }
        });
    }*/


    content = _.parseHtmlScript(content, function (found) {
        var placeholder;
        var match = found.match;

        if (found.isScriptLink) {
            var src = found.src;
            var scriptFile = context.getFileByUrl(src, file);
            var loaderName = scriptFile
                ? scriptFile.basename
                : _.ext(src).basename;

            if (found.isLoader
                || opts.loaderScripts.indexOf(loaderName) !== -1
            ) {
                placeholder = getPlaceholder(true);
                if (placeholder) {
                    return match + placeholder+'\n';
                }
            }
            else if (scriptFile && opts.packJs) {
                packScriptFiles.push({
                    file: scriptFile,
                    raw: match,
                    attrs: found.attrs
                });
            }
        }
        else if (found.isInlineScript) {
            // 对于内联脚本，如果指定了异步入口模块或者包含异步 require，则在前面插入脚本占位符
            if (found.isEntryScript
                || _.extractAsyncModuleIds(found.inlineContent).length) {
                placeholder = getPlaceholder();
                if (placeholder) {
                    return placeholder+'\n' + match;
                }
            }
        }

        return match;
    });

    if (packScriptFiles.length
        && !hasScriptPlaceholder
        && opts.autoInsertPlaceholder
    ) {
        var lastScript = packScriptFiles[packScriptFiles.length - 1].raw;
        content = content.replace(lastScript, lastScript + opts.scriptPlaceholder);
    }

    file.setContent(content);
    file._initScriptPlacedholder = true;

    return packScriptFiles;
}
1321429
function getPackageVersion() {
  var packageJson = path.join(process.cwd(), 'package.json'),
    version;
  try {
    version = require(packageJson).version;
  } catch (unused) {
    throw new Error('Could not load package.json, please make sure it exists');
  }
  if (!semver.valid(version)) {
    throw new Error('Invalid version number found in package.json, please make sure it is valid');
  }

  return [ semver.major(version), semver.minor(version), semver.patch(version) ].join('.');
}
579360
function buildJSONSource() {

  var data = getModularSource();

  addCorePackage();
  prepareData();
  outputJSON('source.json', data);

  function addCorePackage() {
    data.modules.unshift({
      name: 'Core'
    });
    data.packages.unshift({
      name: 'Sugar',
      type: 'core',
      module: 'Core',
      dependencies: [],
      bodyWithComments: readFile('lib/core.js').trim()
    });
  }

  function bundleSetPackages() {
    var packages = [], handledSets = {}, p;

    for (var i = 0; i < data.packages.length; i++) {
      p = data.packages[i];
      if (p.set) {
        // If the package has been handled already then just skip.
        if (!handledSets[p.namespace + p.setName]) {
          packages.push({
            setName: p.setName,
            name: p.setName.replace(/[\[\]]/g, ''),
            sample: p.set.slice(0, 3).concat('...').join(', '),
            type: p.type,
            alias: p.alias,
            module: p.module,
            namespace: p.namespace,
            dependencies: p.dependencies,
            bodyWithComments: p.bodyWithComments
          });
          handledSets[p.namespace + p.setName] = true;
        }
      } else {
        packages.push(p);
      }
    }

    return packages;
  }

  function prepareData() {
    var bundledPackages = bundleSetPackages();
    data.modules.forEach(function(m) {
      indentField(m, 'comment');
    });
    bundledPackages.forEach(function(p) {

      // Pre-indenting all packages rather than doing it on compile to
      // save some cycles and also correctly calculate the package size.
      indentField(p, 'blockStart');
      indentField(p, 'blockEnd');
      indentField(p, 'bodyWithComments');

      cleanSourcePackage(p);
    });
    data.packages = bundledPackages;
  }

  function indentField(p, field) {
    if (p[field]) {
      p[field] = p[field].replace(/^(?=.)/gm, '  ');
    }
  }

  function cleanSourcePackage(p) {
    if (sourcePackageIsDependency(p)) {
      delete p.type;
    }
    delete p.vars;
    delete p.target;
    delete p.body;
    delete p.path;
    delete p.assigns;
    delete p.comments;
    delete p.defineMethod;
    delete p.varDependencies;
    compactField(p, 'bodyWithComments');
    compactField(p, 'dependencies');
  }

  function compactField(p, field) {
    var val = p[field];
    if (!val || (Array.isArray(val) && !val.length)) {
      delete p[field];
    }
  }

}
593205
function fn(metadataGetter, dataAdapter, opts = {}) {
    if (typeof metadataGetter !== 'function') {
        throw new Error(`'metadataGetter' must be a function.`);
    }
    if (typeof dataAdapter !== 'object') {
        throw new Error(`dataAdapter' must be an object.`);
    }
    Object.assign(metadata, metadataGetter.call(null));

    if (!opts.strategy) {
        if (opts.router) {
            opts.strategy = 'ROUTER';
        } else {
            opts.strategy = 'MIDDLEWARE';
        }
    }

    if (typeof opts.getLocaleString !== 'function') {
        opts.getLocaleString = (key) => {
            const object = {
                mongoose_adapter_error_list: '查询失败，请稍后重试',
                mongoose_adapter_error_count: '查询失败，请稍后重试',
                mongoose_adapter_error_id: '查询失败，请稍后重试',
                mongoose_adapter_error_create: '新增失败',
                mongoose_adapter_error_update: '更新失败',
                mongoose_adapter_error_remove: '删除失败',
            };
            return object[key];
        };
    }

    switch (opts.strategy) {
        case 'ROUTER':
            // 路由器挂载
            if (!opts.router) {
                throw new Error(`'router' can not be empty when using ROUTER strategy.`);
            }
            return routerStrategy(metadata, dataAdapter, opts);
        case 'MIDDLEWARE':
            // 中间件过滤
            if (opts.filter && typeof opts.filter !== 'function') {
                throw new Error(`'filter' must be a function type.`);
            }
            return middlewareStrategy(metadata, dataAdapter, opts);
            break;
    }
}
574121
function () {
        const editor = this.editor
        const $textElem = editor.$textElem

        $textElem.on('keydown', e => {
            if (e.keyCode !== 8) {
                return
            }
            const txtHtml = $textElem.html().toLowerCase().trim()
            if (txtHtml === '<p><br></p>') {
                // 最后剩下一个空行，就不再删除了
                e.preventDefault()
                return
            }
        })

        $textElem.on('keyup', e => {
            if (e.keyCode !== 8) {
                return
            }
            let $p
            const txtHtml = $textElem.html().toLowerCase().trim()

            // firefox 时用 txtHtml === '<br>' 判断，其他用 !txtHtml 判断
            if (!txtHtml || txtHtml === '<br>') {
                // 内容空了
                $p = $('<p><br/></p>')
                $textElem.html('') // 一定要先清空，否则在 firefox 下有问题
                $textElem.append($p)
                editor.selection.createRangeByElem($p, false, true)
                editor.selection.restoreSelection()
            }
        })

    }
1232498
async function mitm(options) {
	// 不在参数解构是考虑到时候也许直接把options传给某个库
	const { origin, dest, log = false, host = '0.0.0.0', port = rand(1025, 65535) } = options;
	if (typeof origin !== 'string' || !origin || typeof dest !== 'string' || !dest) {
		throw new TypeError('origin and dest in mitm options must set correctly.');
	}

	if (origin === dest) {
		throw new Error('Same origin and dest may cause request loop.');
	}

	const [originHostname, originPort = 80] = origin.trim().toLowerCase().split(':');
	const [destHostname, destPort = 80] = dest.trim().toLowerCase().split(':');

	const server = new Server();

	// 目前只支持HTTP代理
	server.on('request', (cReq, cRes) => {
		let { hostname, port, pathname } = new URL(cReq.url);
		port = port || 80;

		let opts = {
			protocol: 'http:',
			method: cReq.method,
			path: pathname,
			headers: cReq.headers
		};
		if (hostname === originHostname && port == originPort) {
			opts.hostname = destHostname;
			opts.port = parseInt(destPort, 10);
		} else {
			opts.hostname = hostname;
			opts.port = parseInt(port, 10);
		}
		const sReq = request(opts, sRes => {
			cRes.writeHead(sRes.statusCode, sRes.statusMessage, sRes.headers);
			sRes.pipe(cRes);
		});

		sReq.on('error', function (err) {
			log && logger.error(err.message);
			this.end();
		});

		cReq.pipe(sReq);
	});

	server.on('connect', (req, cSocket, header) => {
		const [hostname, port] = req.url.split(':');
		const sSocket = createConnection(parseInt(port, 10) || 443, hostname, function () {
			cSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
			this.write(header);
			this.pipe(cSocket).pipe(this);
		});

		sSocket.on('error', function (err) {
			log && logger.error(err.message);
			this.end();
		});

		cSocket.on('error', function (err) {
			log && logger.error(err.message);
			this.end();
		});
	});

	server.on('error', err => {
		logger.error(err.message);
	});

	// 什么傻屌操作???
	let resolve = null;
	const delayLog = new Promise(rs => resolve = rs);
	server.listen(parseInt(port, 10), host, err => {
		if (err) {
			throw err;
		}
		resolve();
	});

	await delayLog;
	logger.success(`MITM proxy listening on ${chalk.cyan.underline(`http://${host}:${port}`)} From ${chalk.cyan.underline(origin)} to ${chalk.cyan.underline(dest)}`);


	return server;
}
85599
async function checkNewVersion() {
    try {
        const file = path.join(constants.GLOBAL_DIR, constants.GLOBAL_INFO);

        // If it does not exist, create it.
        if (!fs.existsSync(file)) {
            createFile({
                name: file,
                source: `{"lastCheckForUpdate": 0}\n`,
            });
        }

        // Read info file
        const json = fs.readJsonSync(file, 'utf8');
        const lastCheckForUpdate = json.lastCheckForUpdate;

        // Show update message
        if (lastCheckForUpdate + (6 * 3600 * 1000) < Date.now()) {
            const latestVersion = await request(`${constants.FIREBASE_DATABASE_URL}/version/cli/latest.json`);
            if (latestVersion && latestVersion !== 'null' && latestVersion !== `"${pjson.version}"`) {
                const scale = pjson.version.length + latestVersion.length - 10;

                console.log();
                console.log(`${`   ┏`.yellow}${`─`.repeat(scale + 45).yellow}${`┓`.yellow}`);
                console.log(`${`   │`.yellow}${` `.repeat(scale + 45)}${`│`.yellow}`);
                console.log(`${`   │`.yellow}${`      Update available ${pjson.version} -> `}${`${latestVersion}`.green}${`        │`.yellow}`);
                console.log(`${`   │`.yellow}${`  Run `}${`npm i -g google-apps-script`.red}${` to update`}${` `.repeat(scale + 2)}${`│`.yellow}`);
                console.log(`${`   │`.yellow}${` `.repeat(scale + 45)}${`│`.yellow}`);
                console.log(`${`   ┗`.yellow}${`─`.repeat(scale + 45).yellow}${`┛`.yellow}`);
                console.log();
            }

            // Update lastCheckForUpdate
            json.lastCheckForUpdate = Date.now();
            createFile({
                name: file,
                source: JSON.stringify(json),
            });
            return true;
        }
        return false;
    } catch (err) {
        err.origin = 'checkNewVersion';
        await error.log(err);
        return false;
    }
}
495690
function toUrl( source ) {
        // 分离 模块标识 和 .extension
        var extReg = /(\.[a-z0-9]+)$/i;
        var queryReg = /(\?[^#]*)$/;
        var extname = '';
        var id = source;
        var query = '';

        if ( queryReg.test( source ) ) {
            query = RegExp.$1;
            source = source.replace( queryReg, '' );
        }

        if ( extReg.test( source ) ) {
            extname = RegExp.$1;
            id = source.replace( extReg, '' );
        }

        var url = id;

        // paths处理和匹配
        var isPathMap;
        each( pathsIndex, function ( item ) {
            var key = item.k;
            if ( createPrefixRegexp( key ).test( id ) ) {
                url = url.replace( key, item.v );
                isPathMap = 1;
                return false;
            }
        } );

        // packages处理和匹配
        if ( !isPathMap ) {
            each(
                packagesIndex,
                function ( packageConf ) {
                    var name = packageConf.name;
                    if ( createPrefixRegexp( name ).test( id ) ) {
                        url = url.replace( name, packageConf.location );
                        return false;
                    }
                }
            );
        }

        // 相对路径时，附加baseUrl
        if ( !/^([a-z]{2,10}:\/)?\//i.test( url ) ) {
            url = requireConf.baseUrl + url;
        }

        // 附加 .extension 和 query
        url += extname + query;


        var isUrlArgsAppended;

        /**
         * 为url附加urlArgs
         *
         * @ignore
         * @param {string} args urlArgs串
         */
        function appendUrlArgs( args ) {
            if ( !isUrlArgsAppended ) {
                url += ( url.indexOf( '?' ) > 0 ? '&' : '?' ) + args;
                isUrlArgsAppended = 1;
            }
        }

        // urlArgs处理和匹配
        each( urlArgsIndex, function ( item ) {
            if ( createPrefixRegexp( item.k ).test( id ) ) {
                appendUrlArgs( item.v );
                return false;
            }
        } );
        defaultUrlArgs && appendUrlArgs( defaultUrlArgs );

        return url;
    }
655831
function setResCookies(ctx, headers) {
    if (!headers || !validateCookies(headers['set-cookie'])) {
      return
    }

    let cookies = headers['set-cookie'];
    let _headers = ctx.res._headers || {};
    ctx.res._headerNames = ctx.res._headerNames || {}
    // 参考：https://github.com/nodejs/node/blob/master/lib/_http_outgoing.js
    // 在Nodejs 8.x的版本里res._headers被改成了getter/setter 通过 headers['set-cookies'] = 'test' 不触发setter，从而导致设置cookie报错
    ctx.res._headers = Object.assign({}, _headers, {
      'set-cookie': (_headers['set-cookie'] || []).concat(cookies)
    })
    ctx.res._headerNames['set-cookie'] = 'Set-Cookie';
  }
654927
function mergeEnv(opts, env) {
    //用环境变量替换当前配置
    for (var i in env) {
        //console.log("", i);
        if (i.startsWith('pomjs_')) {

            var config = i.substring(6);
            if (config.indexOf('_') == -1) {
                opts[config] = env[i];
            } else {
                var temp = 'opts';
                var vs = config.split('_');
                for (var index = 0; index < vs.length; index++) {
                    temp += '.' + vs[index];
                    //console.log(temp, eval(temp));
                    if (!eval(temp) || index === vs.length - 1) {
                        var tempValue = index < vs.length - 1 ? '{}' : "'" + env[i] + "'";
                        eval(temp + '=' + tempValue);
                    }
                }
            }
        }
    }

    console.log(opts.saluki);
}
1270456
function parseTemplate(source, options) {
    options = options || {};
    options.trimWhitespace = options.trimWhitespace || 'none';

    var rootNode = {
        directives: {},
        props: [],
        events: [],
        children: []
    };

    if (typeof source !== 'string') {
        return rootNode;
    }

    source = source.replace(/<!--([\s\S]*?)-->/mg, '').replace(/(^\s+|\s+$)/g, '');
    var walker = new Walker(source);

    var tagReg = /<(\/)?([a-z0-9-]+)\s*/ig;
    var attrReg = /([-:0-9a-z\[\]_]+)(\s*=\s*(['"])([^\3]*?)\3)?\s*/ig;

    var tagMatch;
    var currentNode = rootNode;
    var stack = [rootNode];
    var stackIndex = 0;
    var beforeLastIndex = 0;

    while ((tagMatch = walker.match(tagReg)) != null) {
        var tagMatchStart = walker.index - tagMatch[0].length;
        var tagEnd = tagMatch[1];
        var tagName = tagMatch[2];
        if (!svgTags[tagName]) {
            tagName = tagName.toLowerCase();
        }

        // 62: >
        // 47: /
        // 处理 </xxxx >
        if (tagEnd) {
            if (walker.currentCode() === 62) {
                // 满足关闭标签的条件时，关闭标签
                // 向上查找到对应标签，找不到时忽略关闭
                var closeIndex = stackIndex;

                // #[begin] error
                // 如果正在闭合一个自闭合的标签，例如 </input>，报错
                if (autoCloseTags[tagName]) {
                    throw new Error(''
                        + '[SAN ERROR] ' + getXPath(stack, tagName) + ' is a `auto closed` tag, '
                        + 'so it cannot be closed with </' + tagName + '>'
                    );
                }

                // 如果关闭的 tag 和当前打开的不一致，报错
                if (
                    stack[closeIndex].tagName !== tagName
                    // 这里要把 table 自动添加 tbody 的情况给去掉
                    && !(tagName === 'table' && stack[closeIndex].tagName === 'tbody')
                ) {
                    throw new Error('[SAN ERROR] ' + getXPath(stack) + ' is closed with ' + tagName);
                }
                // #[end]


                pushTextNode(source.slice(beforeLastIndex, tagMatchStart));
                while (closeIndex > 0 && stack[closeIndex].tagName !== tagName) {
                    closeIndex--;
                }

                if (closeIndex > 0) {
                    stackIndex = closeIndex - 1;
                    currentNode = stack[stackIndex];
                }
                walker.go(1);
            }
            // #[begin] error
            else {
                // 处理 </xxx 非正常闭合标签

                // 如果闭合标签时，匹配后的下一个字符是 <，即下一个标签的开始，那么当前闭合标签未闭合
                if (walker.currentCode() === 60) {
                    throw new Error(''
                        + '[SAN ERROR] ' + getXPath(stack)
                        + '\'s close tag not closed'
                    );
                }

                // 闭合标签有属性
                throw new Error(''
                    + '[SAN ERROR] ' + getXPath(stack)
                    + '\'s close tag has attributes'
                );
            }
            // #[end]
        }
        else {
            var aElement = {
                directives: {},
                props: [],
                events: [],
                children: [],
                tagName: tagName
            };
            var tagClose = autoCloseTags[tagName];

            // 解析 attributes

            /* eslint-disable no-constant-condition */
            while (1) {
            /* eslint-enable no-constant-condition */

                var nextCharCode = walker.currentCode();

                // 标签结束时跳出 attributes 读取
                // 标签可能直接结束或闭合结束
                if (nextCharCode === 62) {
                    walker.go(1);
                    break;
                }

                // 遇到 /> 按闭合处理
                if (nextCharCode === 47
                    && walker.charCode(walker.index + 1) === 62
                ) {
                    walker.go(2);
                    tagClose = 1;
                    break;
                }

                // template 串结束了
                // 这时候，说明这个读取周期的所有内容，都是text
                if (!nextCharCode) {
                    pushTextNode(walker.cut(beforeLastIndex));
                    aElement = null;
                    break;
                }

                // #[begin] error
                // 在处理一个 open 标签时，如果遇到了 <， 即下一个标签的开始，则当前标签未能正常闭合，报错
                if (nextCharCode === 60) {
                    throw new Error('[SAN ERROR] ' + getXPath(stack, tagName) + ' is not closed');
                }
                // #[end]

                // 读取 attribute
                var attrMatch = walker.match(attrReg);
                if (attrMatch) {

                    // #[begin] error
                    // 如果属性有 =，但没取到 value，报错
                    if (
                        walker.charCode(attrMatch.index + attrMatch[1].length) === 61
                        && !attrMatch[2]
                    ) {
                        throw new Error(''
                            + '[SAN ERROR] ' + getXPath(stack, tagName) + ' attribute `'
                            + attrMatch[1] + '` is not wrapped with ""'
                        );
                    }
                    // #[end]

                    integrateAttr(
                        aElement,
                        attrMatch[1],
                        attrMatch[2] ? attrMatch[4] : '',
                        options
                    );
                }

            }

            if (aElement) {
                pushTextNode(source.slice(beforeLastIndex, tagMatchStart));

                // match if directive for else/elif directive
                var elseDirective = aElement.directives['else'] // eslint-disable-line dot-notation
                    || aElement.directives.elif;

                if (elseDirective) {
                    var parentChildrenLen = currentNode.children.length;
                    var ifANode = null;

                    while (parentChildrenLen--) {
                        var parentChild = currentNode.children[parentChildrenLen];
                        if (parentChild.textExpr) {
                            currentNode.children.splice(parentChildrenLen, 1);
                            continue;
                        }

                        ifANode = parentChild;
                        break;
                    }

                    // #[begin] error
                    if (!ifANode || !parentChild.directives['if']) { // eslint-disable-line dot-notation
                        throw new Error('[SAN FATEL] else not match if.');
                    }
                    // #[end]

                    if (ifANode) {
                        ifANode.elses = ifANode.elses || [];
                        ifANode.elses.push(aElement);
                    }
                }
                else {
                    if (aElement.tagName === 'tr' && currentNode.tagName === 'table') {
                        var tbodyNode = {
                            directives: {},
                            props: [],
                            events: [],
                            children: [],
                            tagName: 'tbody'
                        };
                        currentNode.children.push(tbodyNode);
                        currentNode = tbodyNode;
                        stack[++stackIndex] = tbodyNode;
                    }

                    currentNode.children.push(aElement);
                }

                if (!tagClose) {
                    currentNode = aElement;
                    stack[++stackIndex] = aElement;
                }
            }

        }

        beforeLastIndex = walker.index;
    }

    pushTextNode(walker.cut(beforeLastIndex));

    return rootNode;

    /**
     * 在读取栈中添加文本节点
     *
     * @inner
     * @param {string} text 文本内容
     */
    function pushTextNode(text) {
        switch (options.trimWhitespace) {
            case 'blank':
                if (/^\s+$/.test(text)) {
                    text = null;
                }
                break;

            case 'all':
                text = text.replace(/(^\s+|\s+$)/g, '');
                break;
        }

        if (text) {
            currentNode.children.push({
                textExpr: parseText(text, options.delimiters)
            });
        }
    }
}
312750
function install (presetName, options = {}) {
  debug('run install from cli, arguments: %o', arguments)

  /**
   * 处理 preset name
   */
  const parsedPresetName = parse(presetName)
  debug('parsed presetName object: %o', parsedPresetName)

  if (!parsedPresetName || !parsedPresetName.name) {
    log.error('请输入正确的 presetName.')
    process.exit(1)
  }

  const { name, scope, version } = parsedPresetName

  /**
   * 处理 options
   */
  const keep = options.keep || process.env.npm_config_keep || ''
  const registry = getRegistryUrl(
    options.registry || process.env.npm_config_registry || ''
  )

  // registryUrl 存在但是不合法
  if (registry && !/^https?:\/\//.test(registry)) {
    log.error('registry must be a full url with http(s)://')
    process.exit(1)
  }

  debug('parsed options: %o', { keep, registry })

  // 临时安装目录
  const tmpdir = path.join(os.tmpdir(), `elint_tmp_${Date.now()}`)
  const prestPackageName = stringify({ scope, name })
  const presetModulePath = process.platform === 'win32'
    ? path.join(tmpdir, `node_modules/${prestPackageName}`)
    : path.join(tmpdir, `lib/node_modules/${prestPackageName}`)
  const presetPkgPath = path.join(presetModulePath, 'package.json')

  debug(`tmpdir: ${tmpdir}`)
  debug(`preset module path: ${presetModulePath}`)
  debug(`preset package.json path: ${presetPkgPath}`)

  fs.ensureDirSync(tmpdir)

  co(function * () {
    /**
     * step1: 安装 preset
     */
    const installName = stringify({ scope, name, version })
    console.log(`install "${installName}"...`)

    yield npmInstall(installName, {
      prefix: tmpdir,
      registry
    })

    /**
     * step2: mv config file
     */
    link(presetModulePath, keep)

    // eslint-disable-next-line global-require
    const dependencies = require(presetPkgPath).dependencies
    if (!dependencies) {
      // 无需执行 step3, step4
      return
    }

    /**
     * step3: 修改 package.json
     *
     * 将 preset 的 dependencies 写入项目 package.json 的 devDependencies
     */
    console.log('save dependencies to package.json')
    writePkg(dependencies)

    /**
     * step4: 安装 preset 的 dependencies
     */
    console.log('install dependencies...')

    // 兼容 node v6
    const packages = _.toPairs(dependencies)
      .map(([name, range]) => {
        return `${name}@${packageVersion(range)}`
      })

    yield npmInstall(packages, {
      saveDev: true
    })

    // 清理临时目录
    fs.removeSync(tmpdir)
  }).catch(error => {
    log.error(error.message)
    process.exit(1)
  })
}
1195883
function initText(elem, parsed, extra){
  var param = extra.param;
  var throttle, lazy = param.lazy

  if('throttle' in param){
    // <input throttle r-model>
    if(param.throttle === true){
      throttle = 400;
    }else{
      throttle = parseInt(param.throttle, 10)
    }
  }

  var self = this;
  var wc = this.$watch(parsed, function(newValue){
    if(elem.value !== newValue) elem.value = newValue == null? "": "" + newValue;
  }, STABLE);

  // @TODO to fixed event
  var isCompositing = false;
  var handler = function (ev){

    if(isCompositing) return;

    isCompositing = false;

    var that = this;
    if(ev.type==='cut' || ev.type==='paste'){
      _.nextTick(function(){
        var value = that.value
        parsed.set(self, value);
        wc.last = value;
        self.$update();
      })
    }else{
        var value = that.value
        parsed.set(self, value);
        wc.last = value;
        self.$update();
    }
  };

  function onCompositionStart(){
    isCompositing = true;
  }

  function onCompositionEnd(ev){
    isCompositing = false;
    handler.call(this,ev)
  }

  if(throttle && !lazy){
    var preHandle = handler, tid;
    handler = _.throttle(handler, throttle);
  }

  if(hasInput === undefined){
    hasInput = dom.msie !== 9 && "oninput" in document.createElement('input')
  }

  if(lazy){
    dom.on(elem, 'change', handler)
  }else{

    if(typeof CompositionEvent === 'function' ){ //lazy的情况不需要compositionend
      elem.addEventListener("compositionstart", onCompositionStart );
      elem.addEventListener("compositionend", onCompositionEnd );
    }

    if( hasInput){
      elem.addEventListener("input", handler );
    }else{
      dom.on(elem, "paste keyup cut change", handler)
    }
  }
  if(parsed.get(self) === undefined && elem.value){
     parsed.set(self, elem.value);
  }
  return function (){
    if(lazy) return dom.off(elem, "change", handler);
    if( hasInput ){
      elem.removeEventListener("input", handler );
    }else{
      dom.off(elem, "paste keyup cut change", handler)
    }
  }
}
324381
function parseTemplate(code, parserOptions) {
    const sourceCodeStore = new SourceCodeStore(code)

    // 文字位置をそのままにしてscriptとhtmlを分解
    let script = ""
    let pre = 0
    let template = ""
    const microTemplateTokens = [] // テンプレートTokens
    for (const token of genMicroTemplateTokens(
        code,
        parserOptions,
        sourceCodeStore
    )) {
        microTemplateTokens.push(token)
        const start = token.start
        const end = token.end

        const part = code.slice(pre, start)
        script += replaceToWhitespace(part)
        template += part

        const scriptBeforeBase = token.expressionStart.chars
        const scriptAfterBase = token.expressionEnd.chars
        const scriptBefore = replaceToWhitespace(scriptBeforeBase)
        let scriptAfter = replaceToWhitespace(scriptAfterBase)
        if (token.type !== "MicroTemplateEvaluate") {
            scriptAfter = scriptAfter.replace(/ /u, ";")
        }
        script += `${scriptBefore}${token.code}${scriptAfter}`

        template += replaceToWhitespace(code.slice(start, end))

        pre = end
    }
    const part = code.slice(pre, code.length)
    script += replaceToWhitespace(part)
    template += part

    const scriptResult = parseScript(script, parserOptions)

    sourceCodeStore.template = template
    sourceCodeStore.script = script

    const service = new MicroTemplateService({
        code,
        template,
        script,
        microTemplateTokens,
        sourceCodeStore,
        ast: scriptResult.ast,
    })
    container.addService(parserOptions.filePath, service)
    scriptResult.services = Object.assign(scriptResult.services || {}, {
        getMicroTemplateService() {
            return service
        },
    })
    return scriptResult
}
387411
function buildSingleModuleSimple (app, mod, conf, args) {
  if (!mod) {
    mod = conf.moduleConf.module;
  }
  conf = getConf(app, mod);
  del.sync(path.join(conf.modulePath, 'dist'));
  var allPromise = taskList.all($, conf.appConf, conf.moduleConf, args);
  var athenaMatePromise = taskList.athena_mate($, conf.appConf, conf.moduleConf, args);
  var sassPromise = taskList.sass($, conf.appConf, conf.moduleConf, args);
  var lessPromise = taskList.less($, conf.appConf, conf.moduleConf, args);
  var transImagesPromise = taskList.trans_images($, conf.appConf, conf.moduleConf, args);
  var stylesPromise = taskList.styles($, conf.appConf, conf.moduleConf, args);
  var scriptsPromise = taskList.scripts($, conf.appConf, conf.moduleConf, args);
  var serveTransPromise = taskList.serve_trans($, conf.appConf, conf.moduleConf, args);
  var tempPromise = taskList.temp($, conf.appConf, conf.moduleConf, args);

  $.util.log($.util.colors.green('开始编译模块' + mod + '！'));
  return allPromise(mod, conf.modulePath, conf.appPath)
    .then(sassPromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(lessPromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(athenaMatePromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(transImagesPromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(stylesPromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(scriptsPromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(serveTransPromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(tempPromise.bind(null, mod, conf.modulePath, conf.appPath))
    .then(function () {
      $.util.log($.util.colors.green('结束编译模块' + mod + '！'));
      return Promise.resolve(mod);
    }).catch(function (e) {
      if (e) {
        console.log(e.plugin);
        if (e.stack) {
          console.log(e.stack);
        }
      }
    });
}