js、css完全本地化,显示元信息

This commit is contained in:
xunbu
2025-05-26 10:49:50 +08:00
parent f71a4a868e
commit 0b40d96222
12 changed files with 2809 additions and 139 deletions

134
.idea/workspace.xml generated
View File

@@ -5,7 +5,18 @@
</component>
<component name="ChangeListManager">
<list default="true" id="6b18b44a-df57-4212-a857-9e291ebe5dd2" name="更改" comment="">
<change afterPath="$PROJECT_DIR$/docutranslate/static/MathJax.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/docutranslate/static/mermaid.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/docutranslate/template/__init__.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/docutranslate/template/markdown.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docutranslate/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/docutranslate/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docutranslate/agents/agent.py" beforeDir="false" afterPath="$PROJECT_DIR$/docutranslate/agents/agent.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docutranslate/app.py" beforeDir="false" afterPath="$PROJECT_DIR$/docutranslate/app.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docutranslate/global_values/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/docutranslate/global_values/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docutranslate/static/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/docutranslate/static/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docutranslate/translater.py" beforeDir="false" afterPath="$PROJECT_DIR$/docutranslate/translater.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pyproject.toml" beforeDir="false" afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -15,9 +26,10 @@
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="HTML File" />
<option value="CSS File" />
<option value="JavaScript File" />
<option value="Python Script" />
<option value="HTML File" />
</list>
</option>
</component>
@@ -35,62 +47,62 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"DefaultHtmlFileTemplate": "HTML File",
"JavaScript 调试.output.html (1).executor": "Run",
"JavaScript 调试.output.html.executor": "Run",
"JavaScript 调试.regex.md_中文.html.executor": "Run",
"JavaScript 调试.regex_中文.html.executor": "Run",
"JavaScript 调试.test.html.executor": "Run",
"JavaScript 调试.test2.html.executor": "Run",
"JavaScript 调试.test2_英文.html.executor": "Run",
"JavaScript 调试.test4-1_中文.html.executor": "Run",
"JavaScript 调试.互联网认证授权机制.html.executor": "Run",
"JavaScript 调试.互联网认证授权机制_英文.html.executor": "Run",
"JavaScript 调试.毕业论文_英文.html.executor": "Run",
"ModuleVcsDetector.initialDetectionPerformed": "true",
"Python 测试.Python 测试 (markdown_mask.py 内).executor": "Run",
"Python 测试.markdown_mask.Test.test_basic_link_masking 的 Python 测试.executor": "Run",
"Python 测试.pytest (test_html.py 内).executor": "Run",
"Python.1test.executor": "Run",
"Python.2test2 (1).executor": "Run",
"Python.PDFtranslater (1).executor": "Run",
"Python.PDFtranslater (2).executor": "Run",
"Python.agent.executor": "Debug",
"Python.agent_utils.executor": "Run",
"Python.app (1).executor": "Run",
"Python.app.executor": "Run",
"Python.app2.executor": "Run",
"Python.app_test (1).executor": "Run",
"Python.convert.executor": "Run",
"Python.converter_docling.executor": "Run",
"Python.converter_mineru.executor": "Run",
"Python.markdown_splitter.executor": "Debug",
"Python.markdown_utils.executor": "Run",
"Python.test.executor": "Run",
"Python.test1.executor": "Run",
"Python.test2.executor": "Run",
"Python.test3.executor": "Run",
"Python.test4.executor": "Run",
"Python.testhtml.executor": "Run",
"Python.translater.executor": "Run",
"Python.切分测试.executor": "Run",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager": "true",
"RunOnceActivity.git.unshallow": "true",
"git-widget-placeholder": "dev",
"last_opened_file_path": "C:/Users/jxgm/Desktop/translate/docutranslate",
"list.type.of.created.stylesheet": "CSS",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;DefaultHtmlFileTemplate&quot;: &quot;HTML File&quot;,
&quot;JavaScript 调试.output.html (1).executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.output.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.regex.md_中文.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.regex_中文.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.test.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.test2.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.test2_英文.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.test4-1_中文.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.互联网认证授权机制.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.互联网认证授权机制_英文.html.executor&quot;: &quot;Run&quot;,
&quot;JavaScript 调试.毕业论文_英文.html.executor&quot;: &quot;Run&quot;,
&quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;,
&quot;Python 测试.Python 测试 (markdown_mask.py 内).executor&quot;: &quot;Run&quot;,
&quot;Python 测试.markdown_mask.Test.test_basic_link_masking 的 Python 测试.executor&quot;: &quot;Run&quot;,
&quot;Python 测试.pytest (test_html.py 内).executor&quot;: &quot;Run&quot;,
&quot;Python.1test.executor&quot;: &quot;Run&quot;,
&quot;Python.2test2 (1).executor&quot;: &quot;Run&quot;,
&quot;Python.PDFtranslater (1).executor&quot;: &quot;Run&quot;,
&quot;Python.PDFtranslater (2).executor&quot;: &quot;Run&quot;,
&quot;Python.agent.executor&quot;: &quot;Debug&quot;,
&quot;Python.agent_utils.executor&quot;: &quot;Run&quot;,
&quot;Python.app (1).executor&quot;: &quot;Run&quot;,
&quot;Python.app.executor&quot;: &quot;Run&quot;,
&quot;Python.app2.executor&quot;: &quot;Run&quot;,
&quot;Python.app_test (1).executor&quot;: &quot;Run&quot;,
&quot;Python.convert.executor&quot;: &quot;Run&quot;,
&quot;Python.converter_docling.executor&quot;: &quot;Run&quot;,
&quot;Python.converter_mineru.executor&quot;: &quot;Run&quot;,
&quot;Python.markdown_splitter.executor&quot;: &quot;Debug&quot;,
&quot;Python.markdown_utils.executor&quot;: &quot;Run&quot;,
&quot;Python.test.executor&quot;: &quot;Run&quot;,
&quot;Python.test1.executor&quot;: &quot;Run&quot;,
&quot;Python.test2.executor&quot;: &quot;Run&quot;,
&quot;Python.test3.executor&quot;: &quot;Run&quot;,
&quot;Python.test4.executor&quot;: &quot;Run&quot;,
&quot;Python.testhtml.executor&quot;: &quot;Run&quot;,
&quot;Python.translater.executor&quot;: &quot;Run&quot;,
&quot;Python.切分测试.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager&quot;: &quot;true&quot;,
&quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;dev&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/jxgm/Desktop/translate/docutranslate&quot;,
&quot;list.type.of.created.stylesheet&quot;: &quot;CSS&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}]]></component>
}</component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\jxgm\Desktop\translate\docutranslate" />
@@ -508,10 +520,10 @@
<recent_temporary>
<list>
<item itemvalue="Python.app_test (1)" />
<item itemvalue="Python.2test2 (1)" />
<item itemvalue="Python.1test" />
<item itemvalue="Python.converter_docling" />
<item itemvalue="Python.converter_mineru" />
<item itemvalue="Python.2test2 (1)" />
</list>
</recent_temporary>
</component>
@@ -606,6 +618,8 @@
<workItem from="1747972866946" duration="205000" />
<workItem from="1748093422441" duration="1038000" />
<workItem from="1748094483009" duration="843000" />
<workItem from="1748186982208" duration="3003000" />
<workItem from="1748220705934" duration="6440000" />
</task>
<servers />
</component>
@@ -628,14 +642,14 @@
<breakpoints>
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
<url>file://$PROJECT_DIR$/docutranslate/translater.py</url>
<line>247</line>
<line>250</line>
<option name="timeStamp" value="2" />
</line-breakpoint>
</breakpoints>
</breakpoint-manager>
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/filetranslate$app_test__1_.coverage" NAME="app_test (1) 覆盖结果" MODIFIED="1748164803307" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />
<SUITE FILE_PATH="coverage/filetranslate$app_test__1_.coverage" NAME="app_test (1) 覆盖结果" MODIFIED="1748227675220" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />
<SUITE FILE_PATH="coverage/filetranslate$test.coverage" NAME="test 覆盖结果" MODIFIED="1747472297913" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />
<SUITE FILE_PATH="coverage/filetranslate$convert.coverage" NAME="convert 覆盖结果" MODIFIED="1746963490689" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/docutranslate/utils" />
<SUITE FILE_PATH="coverage/PDFtranslate$PDFtranslater__1_.coverage" NAME="PDFtranslater (1) 覆盖结果" MODIFIED="1746633258205" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/pdftranslate_packages" />
@@ -654,7 +668,7 @@
<SUITE FILE_PATH="coverage/filetranslate$agent.coverage" NAME="agent 覆盖结果" MODIFIED="1746805293987" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/docutranslate/Agents" />
<SUITE FILE_PATH="coverage/filetranslate$PDFtranslater__2_.coverage" NAME="PDFtranslater (2) 覆盖结果" MODIFIED="1746679546680" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/filetranslate_packages" />
<SUITE FILE_PATH="coverage/PDFtranslate$test.coverage" NAME="test 覆盖结果" MODIFIED="1746629433597" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />
<SUITE FILE_PATH="coverage/filetranslate$2test2__1_.coverage" NAME="2test2 (1) 覆盖结果" MODIFIED="1747722801777" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />
<SUITE FILE_PATH="coverage/filetranslate$2test2__1_.coverage" NAME="2test2 (1) 覆盖结果" MODIFIED="1748221794831" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />
<SUITE FILE_PATH="coverage/docutranslate$.coverage" NAME="遮罩测试 覆盖结果" MODIFIED="1747743097281" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />
<SUITE FILE_PATH="coverage/filetranslate$agent_utils.coverage" NAME="agent_utils 覆盖结果" MODIFIED="1746708534311" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/docutranslate/utils" />
<SUITE FILE_PATH="coverage/filetranslate$.coverage" NAME="切分测试 覆盖结果" MODIFIED="1747187128847" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/tests" />

View File

@@ -1,4 +1,4 @@
__version__="0.2.25"

View File

@@ -32,7 +32,7 @@ class PromptsCount:
self.lock.release()
TIMEOUT = 500
TIMEOUT = 600
class Agent:

View File

@@ -10,14 +10,13 @@ from urllib.parse import quote
import uvicorn
from fastapi import FastAPI, File, Form, UploadFile, Request, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse,FileResponse
from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse, FileResponse
from fastapi.staticfiles import StaticFiles
from docutranslate import FileTranslater
from docutranslate import FileTranslater, __version__
from docutranslate.logger import translater_logger
from docutranslate.utils.resource_utils import resource_path
from docutranslate.global_values import available_packages
# --- 全局配置 ---
log_queue: Optional[asyncio.Queue] = None
current_state: Dict[str, Any] = {
@@ -92,11 +91,13 @@ async def lifespan(app: FastAPI):
translater_logger.info("应用启动完成,日志队列/历史处理器已正确配置。")
yield
app = FastAPI(lifespan=lifespan)
STATIC_DIR=resource_path("static")
STATIC_DIR = resource_path("static")
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
app.mount("/static",StaticFiles(directory=STATIC_DIR), name="static")
# --- Background Task Logic ---
async def _perform_translation(params: Dict[str, Any], file_contents: bytes, original_filename: str):
@@ -190,7 +191,7 @@ async def main_page(request: Request):
"Pragma": "no-cache", # 兼容 HTTP/1.0
"Expires": "0", # 兼容旧版代理/缓存
}
return FileResponse(index_path,headers=no_cache_headers)
return FileResponse(index_path, headers=no_cache_headers)
@app.post("/translate")
@@ -327,11 +328,12 @@ async def cancel_translate_task():
@app.get("/get-engin-list")
async def get_engin_list():
engin_list=["mineru"]
engin_list = ["mineru"]
if available_packages.get("docling"):
engin_list.append("docling")
return JSONResponse(content=engin_list)
@app.get("/get-status")
async def get_status():
global current_state
@@ -384,7 +386,8 @@ async def download_markdown(filename_with_ext: str):
return StreamingResponse(
io.StringIO(current_state["markdown_content"]),
media_type="text/markdown",
headers={"Content-Disposition": f"attachment; filename*=UTF-8''{quote(actual_filename, safe='', encoding='utf-8')}"}
headers={
"Content-Disposition": f"attachment; filename*=UTF-8''{quote(actual_filename, safe='', encoding='utf-8')}"}
)
@@ -402,10 +405,16 @@ async def download_html(filename_with_ext: str):
return HTMLResponse(
content=current_state["html_content"],
media_type="text/html",
headers={"Content-Disposition": f"attachment; filename*=UTF-8''{quote(actual_filename, safe='', encoding='utf-8')}"}
headers={
"Content-Disposition": f"attachment; filename*=UTF-8''{quote(actual_filename, safe='', encoding='utf-8')}"}
)
@app.get("/meta")
async def get_app_version():
return JSONResponse(content={"version": __version__})
def find_free_port(start_port):
"""从指定端口开始查找可用的端口"""
port = start_port
@@ -414,6 +423,8 @@ def find_free_port(start_port):
if sock.connect_ex(('127.0.0.1', port)) != 0: # 端口可用
return port
port += 1 # 端口被占用,尝试下一个端口
def run_app():
initial_port = 8010
try:
@@ -429,5 +440,4 @@ def run_app():
if __name__ == "__main__":
run_app()

File diff suppressed because one or more lines are too long

View File

@@ -34,6 +34,15 @@
margin-top: 1rem;
}
.meta {
margin-top: 2rem;
font-size: 0.8rem;
}
.meta * {
font-size: inherit;
}
.error-message {
color: #d32f2f;
}
@@ -404,6 +413,13 @@
</div>
<h4 style="margin-top: 1.5rem;">运行日志</h4>
<div class="log-area" id="logArea"></div>
<ul class="meta">
<li id="versionDisplay"></li>
<li>QQ交流群1047781902</li>
<li><a class="no-style"
target="_blank"
href="https://github.com/xunbu/docutranslate">项目主页github.com/xunbu/docutranslate</a></li>
</ul>
</main>
<!-- MODIFIED MODAL STRUCTURE -->
@@ -438,7 +454,6 @@
</div>
<iframe id="printFrame" style="display:none;"></iframe>
<script>
const platformSelect = document.getElementById('platform_select');
const apiHref = document.getElementById('api_href')
@@ -484,6 +499,8 @@
const fileNameDisplay = document.getElementById('fileNameDisplay');
const fileDropPrompt = document.getElementById('fileDropPrompt');
const versionDisplay = document.getElementById("versionDisplay")
let logPollIntervalId = null;
let statusPollIntervalId = null;
let isTranslating = false;
@@ -677,7 +694,16 @@
}
}, false);
// 初始化调用
(async () => {
try {
const response = await fetch("/meta")
let meta = await response.json();
console.log(meta)
versionDisplay.textContent = `版本号${meta.version}`;
} catch (error) {
console.warn("获取版本号失败", error);
}
try {
const response = await fetch('/get-engin-list')
if (!response.ok) {

File diff suppressed because one or more lines are too long

View File

View File

@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{title}}</title>
{{pico}}
<style>
html {
padding: 2vh 10vw;
font-size: 15px;
}
</style>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
messageStyle: "none",
tex2jax: {
inlineMath: [ ['$','$'], ["\\\\(","\\\\)"] ],
processEscapes: true
}
});
</script>
{{MathJax}}
</head>
<body>
{{markdown}}
</body>
{{mermaid}}
<script>
mermaid.initialize({
securityLevel: 'loose',
startOnLoad: true
});
let observer = new MutationObserver(mutations => {
for (let mutation of mutations) {
mutation.target.style.visibility = "visible";
}
});
document.querySelectorAll("pre.mermaid-pre div.mermaid").forEach(item => {
observer.observe(item, {
attributes: true,
attributeFilter: ['data-processed']
});
});
</script>
</html>

View File

@@ -2,6 +2,7 @@ import asyncio
from pathlib import Path
from typing import Literal
import markdown2
import jinja2
from docutranslate.agents import Agent, AgentArgs
from docutranslate.agents import MDRefineAgent, MDTranslateAgent
from docutranslate.converter import Document, ConverterMineru
@@ -9,10 +10,12 @@ from docutranslate.utils.markdown_splitter import split_markdown_text, join_mark
from docutranslate.utils.markdown_utils import uris2placeholder, placeholder2_uris, MaskDict
from docutranslate.logger import translater_logger
from docutranslate.global_values import available_packages
DOCLING_FLAG=True if available_packages.get("docling") else False
DOCLING_FLAG = True if available_packages.get("docling") else False
if DOCLING_FLAG:
from docutranslate.converter import ConverterDocling
class FileTranslater:
def __init__(self, file_path: Path | str | None = None, chunksize: int = 2000,
base_url="", key=None, model_id="", temperature=0.7,
@@ -304,57 +307,18 @@ class FileTranslater:
markdowner = markdown2.Markdown(extras=['tables', 'fenced-code-blocks', 'mermaid', "code-friendly"])
# TODO:实现完全本地化css和js
# language=html
html = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{title}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css">
<style>
html {{
padding:2vh 10vw;
font-size: 15px;
}}
</style>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({{
messageStyle: "none",
tex2jax: {{
inlineMath: [ ['$','$'], ["\\\\(","\\\\)"] ],
processEscapes: true
}}
}});
</script>
<script type="text/javascript"
src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
</head>
<body>
{markdowner.convert(self.markdown.replace("\\", "\\\\"))}
</body>
<script type="module" defer>
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9/dist/mermaid.esm.min.mjs';
mermaid.initialize({{
securityLevel: 'loose',
startOnLoad: true
}});
let observer = new MutationObserver(mutations => {{
for(let mutation of mutations) {{
mutation.target.style.visibility = "visible";
}}
}});
document.querySelectorAll("pre.mermaid-pre div.mermaid").forEach(item => {{
observer.observe(item, {{
attributes: true,
attributeFilter: ['data-processed']
}});
}});
</script>
</html>
"""
return html
pico=Path(__file__).parent / "static" / "pico.css"
html = Path(__file__).parent / "template" / "markdown.html"
MathJax=Path(__file__).parent / "static" / "MathJax.js"
mermaid=Path(__file__).parent / "static" / "mermaid.js"
render = jinja2.Template(html.read_text()).render(
title=title,
pico=f"<style>{pico.read_text()}</style>",
markdown=markdowner.convert(self.markdown.replace("\\", "\\\\")),
MathJax=f"<script>{MathJax.read_text()}</script>",
mermaid=f"<script>{mermaid.read_text()}</script>",
)
return render
def translate_file(self, file_path: Path | str | None = None, to_lang="中文", output_dir="./output",
formula=True,

View File

@@ -1,6 +1,5 @@
[project]
name = "docutranslate"
version = "0.2.24"
description = "文件翻译工具"
readme = "README.md"
requires-python = ">=3.10"
@@ -9,7 +8,7 @@ dependencies = [
"markdown2>=2.5.3",
"fastapi[standard]>=0.115.12",
]
dynamic=["version"]
[project.optional-dependencies]
docling = [
@@ -35,5 +34,8 @@ backend-path = ["."]
[tool.setuptools]
packages = ["docutranslate"]
[tool.setuptools.package-data]
docutranslate = ["static/**"]
docutranslate = ["static/**", "template/**"]
[tool.setuptools.dynamic]
version = { attr = "docutranslate.__version__" }