去除Mustache/Handlebars文件冗余空白的JavaScript解决方案问询
嘿,这个问题我之前也碰到过!要清理Mustache模板里的冗余空白但又不破坏结构和文本内容,确实不能直接全局替换空格,得精准区分哪些空白可以删。我给你两种解决方案,按需选就行~
方案一:正则表达式快速处理(适合简单模板)
如果你的模板结构不算特别复杂,用几个精准的正则就能搞定核心需求——只清理Mustache标签、HTML标签之间的冗余空白,保留文本内容里的空格(比如示例里的"My span")。
这里的思路是针对性匹配:
- 清理Mustache块标签(
{{#...}}/{{/...}})前后的冗余空白 - 清理普通Mustache变量标签(
{{...}})前后的冗余空白 - 清理HTML标签之间的冗余空白
直接上代码:
function cleanMustacheWhitespace(template) { // 清理{{#块标签}}后面的所有空白(空格、制表符、换行) template = template.replace(/({{#[^{}]+}})[\s\t\n\r]+/g, '$1'); // 清理{{/块标签}}前面的所有空白 template = template.replace(/[\s\t\n\r]+({{\/[^{}]+}})/g, '$1'); // 清理普通{{变量标签}}后面的所有空白 template = template.replace(/({{[^{}]+}})[\s\t\n\r]+/g, '$1'); // 清理普通{{变量标签}}前面的所有空白 template = template.replace(/[\s\t\n\r]+({{[^{}]+}})/g, '$1'); // 清理HTML标签之间的冗余空白(比如<div> <span>变成<div><span>) template = template.replace(/(>)[\s\t\n\r]+(<\/?[a-zA-Z0-9-]+)/g, '$1$2'); return template; } // 测试你的示例模板 const original = '<div>{{#typeSettings.showCaret}} <span>My span</span>{{/typeSettings.showCaret}}</div>'; const cleaned = cleanMustacheWhitespace(original); console.log(cleaned); // 输出结果:<div>{{#typeSettings.showCaret}}<span>My span</span>{{/typeSettings.showCaret}}</div>
这个方案的优点是轻量、不需要额外依赖,缺点是对极端复杂的模板(比如嵌套多层section、标签内有特殊字符)可能不够稳妥。
方案二:AST解析法(适合复杂大型模板)
如果你的模板是大型且结构复杂的,用AST(抽象语法树)解析是更可靠的选择——它能准确识别Mustache的各个节点(文本、section、变量等),不会误删文本里的必要空格,也不会破坏模板结构。
我们可以用官方的mustache.js来解析和重构模板:
步骤1:安装依赖
npm install mustache
步骤2:编写清理函数
const mustache = require('mustache'); function cleanMustacheWhitespaceAST(template) { // 把模板解析成AST结构 const ast = mustache.parse(template); // 遍历AST节点,清理冗余空白 function traverseNodes(node) { if (Array.isArray(node)) { for (let i = 0; i < node.length; i++) { const child = node[i]; if (typeof child === 'string') { // 处理文本节点:判断是否是标签之间的纯空白,是的话直接移除 const prevNode = i > 0 ? node[i-1] : null; const nextNode = i < node.length - 1 ? node[i+1] : null; const isSurroundedByTags = (prevNode && typeof prevNode !== 'string') || (nextNode && typeof nextNode !== 'string'); if (isSurroundedByTags && /^\s+$/.test(child)) { node[i] = ''; } else { // 保留文本内的空格,只清理文本首尾和标签相邻的冗余空白 child = child.replace(/^\s+(?=<|{{)/, '').replace(/(?<=}}|>)\s+$/, ''); node[i] = child; } } else { // 递归处理嵌套的section节点 traverseNodes(child); } } // 过滤掉空字符串节点 return node.filter(item => item !== ''); } return node; } // 处理AST并重新生成模板 const cleanedAst = traverseNodes(ast); return mustache.render(cleanedAst, {}, { noEscape: true }); } // 测试示例 const original = '<div>{{#typeSettings.showCaret}} <span>My span</span>{{/typeSettings.showCaret}}</div>'; const cleaned = cleanMustacheWhitespaceAST(original); console.log(cleaned); // 输出结果:<div>{{#typeSettings.showCaret}}<span>My span</span>{{/typeSettings.showCaret}}</div>
这个方案的优势是能完美适配各种复杂模板结构,比如嵌套section、partial、注释等,完全不用担心破坏Mustache的语法,适合处理你提到的大型压缩模板。
内容的提问来源于stack exchange,提问作者Fleming Slone
相关产品推荐
相关产品推荐

