import gradio as gr
import os
import re
import markdown
from typing import Dict, Any
def create_manual_tab(constant: Dict[str, Any]) -> Dict[str, Any]:
# 添加自定义CSS,增大文本大小并添加左侧导航栏样式
custom_css = """
"""
# 添加JavaScript代码,用于处理导航点击
custom_js = """
"""
# 使用Python的markdown库将Markdown转换为HTML
def markdown_to_html(markdown_content, base_path="src/web/manual"):
"""将Markdown内容转换为HTML,并将图片嵌入为base64编码"""
# 处理图片路径,使用base64编码直接嵌入图片
def embed_image(match):
alt_text = match.group(1)
img_path = match.group(2)
# 检查路径是否为外部URL
if img_path.startswith(('http://', 'https://')):
return f'
'
# 处理本地图片路径
try:
# 去掉开头的/以获取正确的路径
if img_path.startswith('/'):
img_path = img_path[1:]
# 获取绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(current_dir))
abs_img_path = os.path.join(project_root, img_path)
# 读取图片并转换为base64
import base64
from pathlib import Path
image_path = Path(abs_img_path)
if image_path.exists():
image_type = image_path.suffix.lstrip('.').lower()
if image_type == 'jpg':
image_type = 'jpeg'
with open(image_path, "rb") as img_file:
encoded_string = base64.b64encode(img_file.read()).decode('utf-8')
return f'
'
else:
print(f"图片文件不存在: {abs_img_path}")
return f'[图片不存在: {img_path}]'
except Exception as e:
print(f"处理图片时出错: {e}, 路径: {img_path}")
return f'[图片加载错误: {img_path}]'
# 使用正则表达式处理所有图片标记
pattern = r'!\[(.*?)\]\((.*?)\)'
processed_content = re.sub(pattern, embed_image, markdown_content)
# 使用Python的markdown库进行转换
html = markdown.markdown(
processed_content,
extensions=[
'tables',
'fenced_code',
'codehilite',
'nl2br',
'extra',
'mdx_truly_sane_lists'
],
extension_configs={
'mdx_truly_sane_lists': {
'nested_indent': 2,
'truly_sane': True
}
}
)
return html
# 从Markdown内容生成HTML导航栏和处理内容
def generate_toc_and_content(markdown_content):
"""从Markdown内容生成HTML导航栏和处理内容"""
# 提取所有标题
headers = re.findall(r'^(#{1,3})\s+(.+)$', markdown_content, re.MULTILINE)
if not headers:
return "
", markdown_content
toc_html = ""
# 为每个标题创建导航项
for i, (level, title) in enumerate(headers):
level_num = len(level)
header_id = f"header-{i}"
# 根据标题级别添加类
css_class = ""
if level_num == 2:
css_class = "nav-h2"
elif level_num == 3:
css_class = "nav-h3"
toc_html += f"- {title}
"
toc_html += "
"
# 为Markdown内容中的标题添加ID
processed_content = markdown_content
for i, (level, title) in enumerate(headers):
header_id = f"header-{i}"
header_pattern = f"{level} {title}"
header_replacement = f"{level} {title}"
processed_content = processed_content.replace(header_pattern, header_replacement, 1)
# 将处理后的Markdown转换为HTML
html_content = markdown_to_html(processed_content)
return toc_html, html_content
with gr.Tab("Manual"):
# 添加自定义CSS和JavaScript
gr.HTML(custom_css + custom_js)
with gr.Row():
language = gr.Dropdown(choices=['English', 'Chinese'], value='English', label='Language', interactive=True)
with gr.Tab("Training"):
training_content = load_manual_training(language.value)
toc_html, html_content = generate_toc_and_content(training_content)
training_md = gr.HTML(f"""
{toc_html}
{html_content}
""")
with gr.Tab("Prediction"):
prediction_content = load_manual_prediction(language.value)
toc_html, html_content = generate_toc_and_content(prediction_content)
prediction_md = gr.HTML(f"""
{toc_html}
{html_content}
""")
with gr.Tab("Evaluation"):
evaluation_content = load_manual_evaluation(language.value)
toc_html, html_content = generate_toc_and_content(evaluation_content)
evaluation_md = gr.HTML(f"""
{toc_html}
{html_content}
""")
with gr.Tab("Download"):
download_content = load_manual_download(language.value)
toc_html, html_content = generate_toc_and_content(download_content)
download_md = gr.HTML(f"""
{toc_html}
{html_content}
""")
with gr.Tab("FAQ"):
faq_content = load_manual_faq(language.value)
toc_html, html_content = generate_toc_and_content(faq_content)
faq_md = gr.HTML(f"""
{toc_html}
{html_content}
""")
# 正确绑定语言切换事件
language.change(
fn=update_manual,
inputs=[language],
outputs=[training_md, prediction_md, evaluation_md, download_md, faq_md]
)
return {"training_md": training_md, "prediction_md": prediction_md, "evaluation_md": evaluation_md, "download_md": download_md, "faq_md": faq_md}
def update_manual(language):
"""更新手册内容"""
training_content = load_manual_training(language)
prediction_content = load_manual_prediction(language)
evaluation_content = load_manual_evaluation(language)
download_content = load_manual_download(language)
faq_content = load_manual_faq(language)
# 使用Python的markdown库将Markdown转换为HTML
def markdown_to_html(markdown_content, base_path="src/web/manual"):
"""将Markdown内容转换为HTML,并将图片嵌入为base64编码"""
# 处理图片路径,使用base64编码直接嵌入图片
def embed_image(match):
alt_text = match.group(1)
img_path = match.group(2)
# 检查路径是否为外部URL
if img_path.startswith(('http://', 'https://')):
return f'
'
# 处理本地图片路径
try:
# 去掉开头的/以获取正确的路径
if img_path.startswith('/'):
img_path = img_path[1:]
# 获取绝对路径
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(current_dir))
abs_img_path = os.path.join(project_root, img_path)
# 读取图片并转换为base64
import base64
from pathlib import Path
image_path = Path(abs_img_path)
if image_path.exists():
image_type = image_path.suffix.lstrip('.').lower()
if image_type == 'jpg':
image_type = 'jpeg'
with open(image_path, "rb") as img_file:
encoded_string = base64.b64encode(img_file.read()).decode('utf-8')
return f'
'
else:
print(f"图片文件不存在: {abs_img_path}")
return f'[图片不存在: {img_path}]'
except Exception as e:
print(f"处理图片时出错: {e}, 路径: {img_path}")
return f'[图片加载错误: {img_path}]'
# 使用正则表达式处理所有图片标记
pattern = r'!\[(.*?)\]\((.*?)\)'
processed_content = re.sub(pattern, embed_image, markdown_content)
# 使用Python的markdown库进行转换
html = markdown.markdown(
processed_content,
extensions=[
'tables',
'fenced_code',
'codehilite',
'nl2br',
'extra',
'mdx_truly_sane_lists'
],
extension_configs={
'mdx_truly_sane_lists': {
'nested_indent': 2,
'truly_sane': True
}
}
)
return html
# 为每个内容生成导航栏和HTML内容
def generate_toc_and_content(markdown_content):
"""从Markdown内容生成HTML导航栏和处理内容"""
# 提取所有标题
headers = re.findall(r'^(#{1,3})\s+(.+)$', markdown_content, re.MULTILINE)
if not headers:
return "", markdown_content
toc_html = ""
# 为每个标题创建导航项
for i, (level, title) in enumerate(headers):
level_num = len(level)
header_id = f"header-{i}"
# 根据标题级别添加类
css_class = ""
if level_num == 2:
css_class = "nav-h2"
elif level_num == 3:
css_class = "nav-h3"
toc_html += f"- {title}
"
toc_html += "
"
# 为Markdown内容中的标题添加ID
processed_content = markdown_content
for i, (level, title) in enumerate(headers):
header_id = f"header-{i}"
header_pattern = f"{level} {title}"
header_replacement = f"{level} {title}"
processed_content = processed_content.replace(header_pattern, header_replacement, 1)
# 将处理后的Markdown转换为HTML
html_content = markdown_to_html(processed_content)
return toc_html, html_content
# 生成带导航栏的HTML
training_toc, training_html = generate_toc_and_content(training_content)
prediction_toc, prediction_html = generate_toc_and_content(prediction_content)
evaluation_toc, evaluation_html = generate_toc_and_content(evaluation_content)
download_toc, download_html = generate_toc_and_content(download_content)
faq_toc, faq_html = generate_toc_and_content(faq_content)
training_output = f"""
{training_toc}
{training_html}
"""
prediction_output = f"""
{prediction_toc}
{prediction_html}
"""
evaluation_output = f"""
{evaluation_toc}
{evaluation_html}
"""
download_output = f"""
{download_toc}
{download_html}
"""
faq_output = f"""
"""
return training_output, prediction_output, evaluation_output, download_output, faq_output
def load_manual_training(language):
if language == 'Chinese':
manual_path = os.path.join("src/web/manual", "TrainingManual_ZH.md")
else:
manual_path = os.path.join("src/web/manual", "TrainingManual_EN.md")
try:
with open(manual_path, "r", encoding="utf-8") as f:
return f.read()
except Exception as e:
return f"# Error loading manual\n\n{str(e)}"
def load_manual_prediction(language):
if language == 'Chinese':
manual_path = os.path.join("src/web/manual", "PredictionManual_ZH.md")
else:
manual_path = os.path.join("src/web/manual", "PredictionManual_EN.md")
try:
with open(manual_path, "r", encoding="utf-8") as f:
return f.read()
except Exception as e:
return f"# Error loading manual\n\n{str(e)}"
def load_manual_evaluation(language):
if language == 'Chinese':
manual_path = os.path.join("src/web/manual", "EvaluationManual_ZH.md")
else:
manual_path = os.path.join("src/web/manual", "EvaluationManual_EN.md")
try:
with open(manual_path, "r", encoding="utf-8") as f:
return f.read()
except Exception as e:
return f"# Error loading manual\n\n{str(e)}"
def load_manual_download(language):
if language == 'Chinese':
manual_path = os.path.join("src/web/manual", "DownloadManual_ZH.md")
else:
manual_path = os.path.join("src/web/manual", "DownloadManual_EN.md")
try:
with open(manual_path, "r", encoding="utf-8") as f:
return f.read()
except Exception as e:
return f"# Error loading manual\n\n{str(e)}"
def load_manual_faq(language):
if language == 'Chinese':
manual_path = os.path.join("src/web/manual", "QAManual_ZH.md")
else:
manual_path = os.path.join("src/web/manual", "QAManual_EN.md")
try:
with open(manual_path, "r", encoding="utf-8") as f:
return f.read()
except Exception as e:
return f"# FAQ\n\n{str(e)}"