// 解析模板函数,用于将模板字符串解析成 tokens 数组 // 参数:template - 模板字符串,tags - 自定义标签 // 返回值:tokens 数组 function parseTemplate (template, tags) {

// 如果模板字符串为空,则返回空数组 if (!template) return [];

var sections = []; // 用于保存 section token 的栈 var tokens = []; // 用于保存 tokens 的缓存数组 var spaces = []; // 用于保存当前行中空格 token 的索引 var hasTag = false; // 当前行是否有 {{tag}} var nonSpace = false; // 当前行是否有非空格字符

// 删除当前行中所有空格 token,如果有 {{#tag}} 则同时删除整个行中的 token function stripSpace () { if (hasTag && !nonSpace) { while (spaces.length) delete tokens[spaces.pop()]; } else { spaces = []; }

hasTag = false;
nonSpace = false;

}

var openingTagRe, closingTagRe, closingCurlyRe;

// 编译标签,生成正则表达式 function compileTags (tagsToCompile) { if (typeof tagsToCompile === 'string') tagsToCompile = tagsToCompile.split(spaceRe, 2);

if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
  throw new Error('Invalid tags: ' + tagsToCompile);

openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\s*');
closingTagRe = new RegExp('\s*' + escapeRegExp(tagsToCompile[1]));
closingCurlyRe = new RegExp('\s*' + escapeRegExp('}' + tagsToCompile[1]));

}

// 编译默认标签或用户自定义标签 compileTags(tags || mustache.tags);

var scanner = new Scanner(template);

var start, type, value, chr, token, openSection;

// 循环扫描模板字符串,生成 tokens 数组 while (!scanner.eos()) { start = scanner.pos;

// 匹配 {{tag}} 之间的文本内容
value = scanner.scanUntil(openingTagRe);

if (value) {
  for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
    chr = value.charAt(i);

    if (isWhitespace(chr)) {
      spaces.push(tokens.length);
    } else {
      nonSpace = true;
    }

    // 将文本内容分割成多个 token,每个字符一个 token
    tokens.push([ 'text', chr, start, start + 1 ]);
    start += 1;

    // 如果当前字符为换行符,则删除当前行中的空格 token
    if (chr === '

') stripSpace(); } }

// 匹配 {{tag}}
if (!scanner.scan(openingTagRe))
  break;

hasTag = true;

// 获取 tag 的类型
type = scanner.scan(tagRe) || 'name';
scanner.scan(whiteRe);

// 获取 tag 的值
if (type === '=') {
  value = scanner.scanUntil(equalsRe);
  scanner.scan(equalsRe);
  scanner.scanUntil(closingTagRe);
} else if (type === '{') {
  value = scanner.scanUntil(closingCurlyRe);
  scanner.scan(curlyRe);
  scanner.scanUntil(closingTagRe);
  type = '&';
} else {
  value = scanner.scanUntil(closingTagRe);
}

// 匹配 {{/tag}},检查是否嵌套正确
if (!scanner.scan(closingTagRe))
  throw new Error('Unclosed tag at ' + scanner.pos);

// 将 tag 转换成 token,存入 tokens 数组
token = [ type, value, start, scanner.pos ];
tokens.push(token);

// 如果是 section tag,将其存入 sections 栈中
if (type === '#' || type === '^') {
  sections.push(token);
} else if (type === '/') {
  // 如果是 closing tag,检查嵌套是否正确
  openSection = sections.pop();

  if (!openSection)
    throw new Error('Unopened section '' + value + '' at ' + start);

  if (openSection[1] !== value)
    throw new Error('Unclosed section '' + openSection[1] + '' at ' + start);
} else if (type === 'name' || type === '{' || type === '&') {
  nonSpace = true;
} else if (type === '=') {
  // 如果是等号 tag,设置下一次编译的标签
  compileTags(value);
}

}

// 检查是否有未关闭的 section tag openSection = sections.pop();

if (openSection) throw new Error('Unclosed section '' + openSection[1] + '' at ' + scanner.pos);

// 将 tokens 数组转换成嵌套结构,返回嵌套后的 tokens 数组 return nestTokens(squashTokens(tokens)); }

Mustache.js 模板解析函数 parseTemplate 代码解析

原文地址: https://www.cveoy.top/t/topic/oLhC 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录