js、css完全本地化,显示元信息
This commit is contained in:
134
.idea/workspace.xml
generated
134
.idea/workspace.xml
generated
@@ -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">{
|
||||
"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>
|
||||
}</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" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
__version__="0.2.25"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class PromptsCount:
|
||||
self.lock.release()
|
||||
|
||||
|
||||
TIMEOUT = 500
|
||||
TIMEOUT = 600
|
||||
|
||||
|
||||
class Agent:
|
||||
|
||||
@@ -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] = {
|
||||
@@ -46,7 +45,7 @@ class QueueAndHistoryHandler(logging.Handler):
|
||||
|
||||
def emit(self, record: logging.LogRecord):
|
||||
log_entry = self.format(record)
|
||||
print(log_entry) # Keep console log for server visibility
|
||||
print(log_entry) # Keep console log for server visibility
|
||||
self.history_list.append(log_entry)
|
||||
if len(self.history_list) > self.max_history:
|
||||
del self.history_list[:len(self.history_list) - self.max_history]
|
||||
@@ -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):
|
||||
@@ -179,23 +180,23 @@ async def _perform_translation(params: Dict[str, Any], file_contents: bytes, ori
|
||||
# --- API Endpoints ---
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
async def main_page(request: Request):
|
||||
index_path = Path("index.html") # Adjust if index.html is elsewhere
|
||||
index_path = Path("index.html") # Adjust if index.html is elsewhere
|
||||
if not index_path.exists():
|
||||
# Fallback to static dir if not in root
|
||||
# Fallback to static dir if not in root
|
||||
index_path = STATIC_DIR / "index.html"
|
||||
if not index_path.exists():
|
||||
raise HTTPException(status_code=404, detail="index.html not found")
|
||||
no_cache_headers = {
|
||||
"Cache-Control": "no-store, no-cache, must-revalidate, max-age=0",
|
||||
"Pragma": "no-cache", # 兼容 HTTP/1.0
|
||||
"Expires": "0", # 兼容旧版代理/缓存
|
||||
"Expires": "0", # 兼容旧版代理/缓存
|
||||
}
|
||||
return FileResponse(index_path,headers=no_cache_headers)
|
||||
return FileResponse(index_path, headers=no_cache_headers)
|
||||
|
||||
|
||||
@app.post("/translate")
|
||||
async def handle_translate(
|
||||
request: Request, # Added request for potential future use, not strictly needed now
|
||||
request: Request, # Added request for potential future use, not strictly needed now
|
||||
base_url: str = Form(...),
|
||||
apikey: str = Form(...),
|
||||
model_id: str = Form(...),
|
||||
@@ -203,8 +204,8 @@ async def handle_translate(
|
||||
formula_ocr: bool = Form(False),
|
||||
code_ocr: bool = Form(False),
|
||||
refine_markdown: bool = Form(False),
|
||||
convert_engin: str = Form(...), # New parameter
|
||||
mineru_token: Optional[str] = Form(None), # New parameter
|
||||
convert_engin: str = Form(...), # New parameter
|
||||
mineru_token: Optional[str] = Form(None), # New parameter
|
||||
file: UploadFile = File(...)
|
||||
):
|
||||
global current_state, log_queue, log_history
|
||||
@@ -270,8 +271,8 @@ async def handle_translate(
|
||||
"base_url": base_url, "apikey": apikey, "model_id": model_id,
|
||||
"to_lang": to_lang, "formula_ocr": formula_ocr,
|
||||
"code_ocr": code_ocr, "refine_markdown": refine_markdown,
|
||||
"convert_engin": convert_engin, # Pass to task
|
||||
"mineru_token": mineru_token, # Pass to task
|
||||
"convert_engin": convert_engin, # Pass to task
|
||||
"mineru_token": mineru_token, # Pass to task
|
||||
}
|
||||
|
||||
loop = asyncio.get_running_loop()
|
||||
@@ -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()
|
||||
1
docutranslate/static/MathJax.js
Normal file
1
docutranslate/static/MathJax.js
Normal file
File diff suppressed because one or more lines are too long
@@ -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) {
|
||||
|
||||
2607
docutranslate/static/mermaid.js
Normal file
2607
docutranslate/static/mermaid.js
Normal file
File diff suppressed because one or more lines are too long
0
docutranslate/template/__init__.py
Normal file
0
docutranslate/template/__init__.py
Normal file
46
docutranslate/template/markdown.html
Normal file
46
docutranslate/template/markdown.html
Normal 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>
|
||||
@@ -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,
|
||||
|
||||
@@ -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__" }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user