File size: 4,786 Bytes
31e2d98 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
/**
* 构建时脚本:从JSON生成带颜色的HTML
*/
const fs = require('fs');
const path = require('path');
// 文件路径配置
const paths = {
en: {
json: path.resolve(__dirname, '../../../data/demo/public/InfoRadar-intro.json'),
html: path.resolve(__dirname, '../content/home.en.html')
},
zh: {
json: path.resolve(__dirname, '../../../data/demo/public/CN/InfoRadar-介绍.json'),
html: path.resolve(__dirname, '../content/home.zh.html')
}
};
// ==========================================
// 颜色计算逻辑(从 SurprisalColorConfig.ts 复制)
// ==========================================
const TOKEN_SURPRISAL_MAX = 18;
/**
* 计算 surprisal(信息量)
*/
function calculateSurprisal(probability) {
return -Math.log2(Math.max(probability, Number.EPSILON));
}
/** RGB 部分,通过 CSS 变量复用 */
const INTRO_RGB = '255, 71, 64';
/** alpha 小数位数 */
const ALPHA_PRECISION = 2;
/**
* 根据 surprisal 计算 alpha(0–0.7),保留指定位数
*/
function getTokenAlpha(surprisal) {
const normalizedValue = surprisal < 0 ? 0 :
surprisal >= TOKEN_SURPRISAL_MAX ? 1 :
surprisal / TOKEN_SURPRISAL_MAX;
const alpha = Math.max(0, Math.min(1, normalizedValue)) * 0.7;
return alpha.toFixed(ALPHA_PRECISION);
}
// ==========================================
// HTML 生成逻辑
// ==========================================
/**
* 转义HTML特殊字符
*/
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
/**
* 从JSON生成带颜色的HTML(使用 CSS 变量 --intro-rgb,span 仅写 alpha)
*/
function generateColoredHTML(jsonPath) {
try {
const content = fs.readFileSync(jsonPath, 'utf-8');
const data = JSON.parse(content);
let html = '';
for (const token of data.result.bpe_strings) {
const text = token.raw;
const prob = token.real_topk[1];
const surprisal = calculateSurprisal(prob);
const alpha = getTokenAlpha(surprisal);
const escapedText = escapeHtml(text);
if (text.includes('\n')) {
const parts = text.split(/(\n)/);
for (const part of parts) {
if (part === '\n') {
html += '<br>';
} else if (part) {
html += `<span class="intro-token" style="--a:${alpha}">${escapeHtml(part)}</span>`;
}
}
} else {
html += `<span class="intro-token" style="--a:${alpha}">${escapedText}</span>`;
}
}
return html;
} catch (error) {
console.error(`Failed to generate HTML from JSON: ${jsonPath}`, error);
return null;
}
}
/**
* 更新HTML文件中的intro-brief内容
*/
function updateHTMLIntro(htmlPath, coloredHTML) {
try {
let html = fs.readFileSync(htmlPath, 'utf-8');
// 匹配 <div class="intro-brief" ...> 到 </div> 之间的内容
const regex = /(<div class="intro-brief"[^>]*>)([\s\S]*?)(<\/div>)/;
if (!regex.test(html)) {
console.error(`intro-brief not found in ${htmlPath}`);
return false;
}
// 替换为带颜色的HTML,容器上定义 CSS 变量供 span 复用
const replacement = `<div class="intro-brief" style="--intro-rgb: ${INTRO_RGB}">\n ${coloredHTML}\n</div>`;
html = html.replace(regex, replacement);
fs.writeFileSync(htmlPath, html, 'utf-8');
console.log(`✓ Updated ${path.basename(htmlPath)}`);
return true;
} catch (error) {
console.error(`Failed to update HTML file: ${htmlPath}`, error);
return false;
}
}
/**
* 主函数
*/
function main() {
console.log('Generating colored intro HTML from JSON...\n');
let success = true;
// 生成并更新英文
const enHTML = generateColoredHTML(paths.en.json);
if (enHTML) {
success = updateHTMLIntro(paths.en.html, enHTML) && success;
} else {
success = false;
}
// 生成并更新中文
const zhHTML = generateColoredHTML(paths.zh.json);
if (zhHTML) {
success = updateHTMLIntro(paths.zh.html, zhHTML) && success;
} else {
success = false;
}
if (success) {
console.log('\n✓ All intro HTML files generated successfully');
} else {
console.error('\n✗ Some generation failed');
process.exit(1);
}
}
// 执行
main();
|