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

@@ -12,12 +12,11 @@ import uvicorn
from fastapi import FastAPI, File, Form, UploadFile, Request, HTTPException
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,12 +91,14 @@ async def lifespan(app: FastAPI):
translater_logger.info("应用启动完成,日志队列/历史处理器已正确配置。")
yield
app = FastAPI(lifespan=lifespan)
STATIC_DIR = resource_path("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):
global current_state
@@ -332,6 +333,7 @@ async def get_engin_list():
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
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__" }