'commit'
This commit is contained in:
@@ -1,5 +1,75 @@
|
||||
const { createApp, ref, computed, onMounted } = Vue;
|
||||
|
||||
// 1. 全局渲染器 - 纯手写的高鲁棒性解析器,不再依赖 marked
|
||||
const globalRenderMarkdown = (text) => {
|
||||
if (!text) return '';
|
||||
|
||||
// 0. 预处理:去除 AI 可能返回的代码块标记
|
||||
let cleanText = text.trim();
|
||||
// 去除开头的 ```markdown 或 ```
|
||||
cleanText = cleanText.replace(/^```(markdown)?\s*/i, '');
|
||||
// 去除结尾的 ```
|
||||
cleanText = cleanText.replace(/```\s*$/, '');
|
||||
|
||||
// 1. 预处理:按行分割
|
||||
const lines = cleanText.split('\n');
|
||||
let html = '';
|
||||
let inList = false;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
// 关键:去除行首尾空白,解决缩进导致的解析失败
|
||||
let trimmed = line.trim();
|
||||
|
||||
// 空行处理
|
||||
if (!trimmed) {
|
||||
if (inList) { html += '</ul>\n'; inList = false; }
|
||||
continue; // 忽略空行,或者可以加 <br>
|
||||
}
|
||||
|
||||
// 2. 内联格式处理(加粗、代码、链接)
|
||||
// 加粗 **text** -> <strong>text</strong>
|
||||
trimmed = trimmed.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
|
||||
// 代码 `text` -> <code>text</code>
|
||||
trimmed = trimmed.replace(/`([^`]+)`/g, '<code>$1</code>');
|
||||
|
||||
// 3. 块级元素处理
|
||||
// 标题 ### Title
|
||||
if (trimmed.startsWith('###')) {
|
||||
if (inList) { html += '</ul>\n'; inList = false; }
|
||||
html += `<h3>${trimmed.replace(/^###\s*/, '')}</h3>`;
|
||||
}
|
||||
else if (trimmed.startsWith('##')) {
|
||||
if (inList) { html += '</ul>\n'; inList = false; }
|
||||
html += `<h2>${trimmed.replace(/^##\s*/, '')}</h2>`;
|
||||
}
|
||||
else if (trimmed.startsWith('#')) {
|
||||
if (inList) { html += '</ul>\n'; inList = false; }
|
||||
html += `<h1>${trimmed.replace(/^#\s*/, '')}</h1>`;
|
||||
}
|
||||
// 列表 - Item 或 * Item
|
||||
else if (trimmed.startsWith('- ') || trimmed.startsWith('* ')) {
|
||||
if (!inList) { html += '<ul>\n'; inList = true; }
|
||||
html += `<li>${trimmed.substring(2)}</li>`;
|
||||
}
|
||||
// 数字列表 1. Item
|
||||
else if (/^\d+\.\s/.test(trimmed)) {
|
||||
// 简单起见,数字列表也用 ul,或者你可以维护一个 ordered list 状态
|
||||
if (!inList) { html += '<ul>\n'; inList = true; }
|
||||
html += `<li>${trimmed.replace(/^\d+\.\s/, '')}</li>`;
|
||||
}
|
||||
// 普通段落
|
||||
else {
|
||||
if (inList) { html += '</ul>\n'; inList = false; }
|
||||
html += `<p>${trimmed}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
if (inList) { html += '</ul>\n'; }
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
createApp({
|
||||
setup() {
|
||||
const apiBase = ref(window.location.origin || "http://localhost:8000");
|
||||
@@ -15,96 +85,26 @@ createApp({
|
||||
const summaryLoading = ref(false);
|
||||
const summaryText = ref('');
|
||||
|
||||
// 降级用的简易 Markdown 解析器
|
||||
const simpleMarkdown = (text) => {
|
||||
if (!text) return '';
|
||||
let lines = text.split('\n');
|
||||
let html = '';
|
||||
let inList = false;
|
||||
const parseInline = (str) => {
|
||||
return str
|
||||
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||||
.replace(/`(.*?)`/g, '<code style="background:rgba(148, 163, 184, 0.1); padding:2px 4px; border-radius:4px;">$1</code>');
|
||||
};
|
||||
for (let line of lines) {
|
||||
let trimmed = line.trim();
|
||||
if (!trimmed) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += '<br>';
|
||||
continue;
|
||||
}
|
||||
if (trimmed.startsWith('### ')) {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<h3>${parseInline(trimmed.substring(4))}</h3>`;
|
||||
} else if (trimmed.startsWith('- ') || /^\d+\./.test(trimmed)) {
|
||||
if (!inList) { html += '<ul>'; inList = true; }
|
||||
let content = trimmed.replace(/^(- |\d+\. )/, '');
|
||||
html += `<li>${parseInline(content)}</li>`;
|
||||
} else {
|
||||
if (inList) { html += '</ul>'; inList = false; }
|
||||
html += `<p>${parseInline(trimmed)}</p>`;
|
||||
}
|
||||
}
|
||||
if (inList) html += '</ul>';
|
||||
return html;
|
||||
};
|
||||
|
||||
// Configure Marked
|
||||
if (typeof marked !== 'undefined') {
|
||||
marked.use({
|
||||
gfm: true,
|
||||
breaks: true
|
||||
});
|
||||
}
|
||||
|
||||
// 增强的 Markdown & LaTeX 解析器
|
||||
const renderMarkdownAndLatex = (text) => {
|
||||
if (!text) return '';
|
||||
|
||||
try {
|
||||
let processedText = text;
|
||||
|
||||
// 1. 处理 LaTeX
|
||||
if (typeof katex !== 'undefined') {
|
||||
// 处理块级 LaTeX: $$ ... $$
|
||||
processedText = processedText.replace(/\$\$\s*([\s\S]*?)\s*\$\$/g, (match, formula) => {
|
||||
try {
|
||||
return '<div class="katex-block">' + katex.renderToString(formula, { displayMode: true, throwOnError: false }) + '</div>';
|
||||
} catch (e) { return match; }
|
||||
});
|
||||
|
||||
// 处理行内 LaTeX: $ ... $
|
||||
processedText = processedText.replace(/\$([^\$\n]+?)\$/g, (match, formula) => {
|
||||
try {
|
||||
return katex.renderToString(formula, { displayMode: false, throwOnError: false });
|
||||
} catch (e) { return match; }
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 使用 marked 解析 Markdown
|
||||
if (typeof marked !== 'undefined') {
|
||||
// marked v12+ 使用 marked.parse
|
||||
return marked.parse(processedText);
|
||||
} else {
|
||||
// 降级使用 simpleMarkdown
|
||||
return simpleMarkdown(processedText);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Markdown rendering error:', e);
|
||||
// 最后的兜底:如果 marked 报错,尝试用 simpleMarkdown
|
||||
try {
|
||||
return simpleMarkdown(text);
|
||||
} catch (e2) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 使用全局渲染器
|
||||
const renderedSummary = computed(() => {
|
||||
if (!summaryText.value) return '';
|
||||
return renderMarkdownAndLatex(summaryText.value);
|
||||
const html = globalRenderMarkdown(summaryText.value);
|
||||
return html;
|
||||
});
|
||||
|
||||
// 这里的配置仍然保留,作为双重保险
|
||||
if (typeof marked !== 'undefined') {
|
||||
const m = (typeof marked.marked === 'function') ? marked.marked : marked;
|
||||
if (m.setOptions) {
|
||||
m.setOptions({
|
||||
gfm: true,
|
||||
breaks: true,
|
||||
mangle: false,
|
||||
headerIds: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Methods
|
||||
const startParsing = async () => {
|
||||
if (!shareText.value.trim()) return;
|
||||
|
||||
Reference in New Issue
Block a user