#!/usr/bin/env node
/**
 * KaTeX 服务端渲染脚本
 * 用法: echo "HTML内容" | node katex-render.js
 * 或:   node katex-render.js < input.html > output.html
 *
 * 将 HTML 中的 LaTeX 公式渲染为 KaTeX HTML
 */

import { createRequire } from 'module';
const require = createRequire(import.meta.url);

// 尝试多个路径加载 KaTeX
let katex;
const possiblePaths = [
    '/usr/local/lib/node_modules/katex',        // npm -g 全局安装路径
    '/usr/lib/node_modules/katex',              // Alpine 系统路径
    'katex',                                    // 本地 node_modules
];

let loadError = null;
for (const modulePath of possiblePaths) {
    try {
        katex = require(modulePath);
        break;
    } catch (e) {
        loadError = e;
    }
}

if (!katex) {
    console.error('Error: KaTeX module not found.');
    console.error('Tried paths:', possiblePaths.join(', '));
    if (loadError) console.error('Last error:', loadError.message);
    process.exit(1);
}

// 读取标准输入
let input = '';

process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {
    let chunk;
    while ((chunk = process.stdin.read()) !== null) {
        input += chunk;
    }
});

process.stdin.on('end', () => {
    try {
        const output = renderMathInHtml(input);
        process.stdout.write(output);
    } catch (error) {
        console.error('KaTeX render error:', error.message);
        process.exit(1);
    }
});

/**
 * 解码 HTML 实体
 */
function decodeHtmlEntities(text) {
    return text
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&')
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&apos;/g, "'")
        .replace(/&nbsp;/g, ' ');
}

/**
 * 编码 HTML 实体（用于安全输出）
 */
function encodeHtmlEntities(text) {
    return text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

/**
 * 渲染 HTML 中的所有数学公式
 */
function renderMathInHtml(html) {
    // 定界符配置（按优先级排序）
    const delimiters = [
        { left: '$$', right: '$$', display: true },
        { left: '\\[', right: '\\]', display: true },
        { left: '\\(', right: '\\)', display: false },
        { left: '$', right: '$', display: false },
    ];

    let result = html;

    // 按顺序处理每种定界符
    for (const delimiter of delimiters) {
        result = processDelimiter(result, delimiter.left, delimiter.right, delimiter.display);
    }

    return result;
}

/**
 * 处理特定定界符的公式
 */
function processDelimiter(html, left, right, displayMode) {
    // 转义正则特殊字符
    const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

    const leftEscaped = escapeRegex(left);
    const rightEscaped = escapeRegex(right);

    // 构建正则表达式
    // 【关键修复】排除包含 HTML 标签的内容（不匹配 < 或 >）
    let pattern;
    if (left === '$' && right === '$') {
        // 单个 $...$：不匹配 $$，不匹配包含 < > 的内容
        pattern = new RegExp(`(?<!\\$)\\$(?!\\$)([^$<>]+?)(?<!\\$)\\$(?!\\$)`, 'g');
    } else if (left === '$$' && right === '$$') {
        // $$...$$：不匹配包含 < > 的内容
        pattern = new RegExp(`\\$\\$([^<>]*?)\\$\\$`, 'g');
    } else {
        // \(...\) 和 \[...\]：不匹配包含 < > 的内容
        pattern = new RegExp(`${leftEscaped}([^<>]*?)${rightEscaped}`, 'g');
    }

    return html.replace(pattern, (match, latex) => {
        try {
            // 清理 LaTeX 内容 - 先解码 HTML 实体
            let cleanLatex = decodeHtmlEntities(latex.trim());

            // 跳过空内容
            if (!cleanLatex) {
                return match;
            }

            // 【安全检查】如果内容看起来不像 LaTeX，跳过
            // 跳过只有普通文本的内容（没有任何 LaTeX 特征）
            if (!/[\\^_{}]/.test(cleanLatex) && !/[a-zA-Z]{2,}/.test(cleanLatex)) {
                // 可能只是普通数字或单字母，检查是否有意义
                if (/^[\d\s\.\,\-\+]+$/.test(cleanLatex)) {
                    return match; // 纯数字，不渲染
                }
            }

            // 渲染 KaTeX
            const rendered = katex.renderToString(cleanLatex, {
                displayMode: displayMode,
                throwOnError: false,
                strict: false,
                trust: true,
                output: 'html',
            });

            return rendered;
        } catch (error) {
            // 渲染失败时保留原始内容
            // console.error(`KaTeX error for "${latex.substring(0, 50)}...":`, error.message);
            return match;
        }
    });
}
