|
| 1 | +/** |
| 2 | + * @description 转义尖括号脚本 |
| 3 | + * @author Siz Long |
| 4 | + * @date 2025-09-27 |
| 5 | + */ |
| 6 | +import { promises as fs } from "node:fs"; |
| 7 | +import fg from "fast-glob"; |
| 8 | + |
| 9 | +/** |
| 10 | + * 极简策略: |
| 11 | + * 1) 跳过 fenced code / inline code(保留原样) |
| 12 | + * 2) 仅在普通文本行内转义形如 <数字开头...> 或 <单词里含逗号/空格/数学符号...> 的片段 |
| 13 | + * 3) 不动像 <Component> / <div> 这类“正常标签/组件名”的片段 |
| 14 | + */ |
| 15 | +const files = await fg(["app/docs/**/*.mdx"], { dot: false }); |
| 16 | + |
| 17 | +for (const file of files) { |
| 18 | + let src = await fs.readFile(file, "utf8"); |
| 19 | + |
| 20 | + // 粗粒度:把代码块剥离(防止误替换),留下占位符 |
| 21 | + const blocks = []; |
| 22 | + src = src.replace(/```[\s\S]*?```/g, (m) => { |
| 23 | + blocks.push(m); |
| 24 | + return `__CODE_BLOCK_${blocks.length - 1}__`; |
| 25 | + }); |
| 26 | + |
| 27 | + // 行内代码也剥离 |
| 28 | + src = src.replace(/`[^`]*`/g, (m) => { |
| 29 | + blocks.push(m); |
| 30 | + return `__CODE_BLOCK_${blocks.length - 1}__`; |
| 31 | + }); |
| 32 | + |
| 33 | + // 在普通文本里做“可疑尖括号”的转义: |
| 34 | + // - <\d...> 如 <8>、<1,2,3> |
| 35 | + // - <[^\s/>][^>]*[,;+\-*/= ]+[^>]*> 含明显非标签符号的 |
| 36 | + src = src |
| 37 | + .replace(/<\d[^>]*>/g, (m) => |
| 38 | + m.replaceAll("<", "<").replaceAll(">", ">"), |
| 39 | + ) |
| 40 | + .replace(/<(?![A-Za-z/][A-Za-z0-9:_-]*\s*\/?>)[^>]*>/g, (m) => |
| 41 | + m.replaceAll("<", "<").replaceAll(">", ">"), |
| 42 | + ); |
| 43 | + |
| 44 | + // 还原占位的代码块/行内代码 |
| 45 | + src = src.replace(/__CODE_BLOCK_(\d+)__/g, (_, i) => blocks[Number(i)]); |
| 46 | + |
| 47 | + await fs.writeFile(file, src, "utf8"); |
| 48 | + console.log(`Escaped angles in ${file}`); |
| 49 | +} |
0 commit comments