Vendor markdown frontend assets
This commit is contained in:
parent
ea89c5f209
commit
ade7f3d1e1
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
> 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。
|
||||
|
||||
最后更新:2026-05-25(dev SPA 上传入口显示进度)
|
||||
最后更新:2026-05-25(dev SPA 前端 CDN 资源本地化)
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
### 2026-05-25
|
||||
|
||||
- **dev SPA 前端 CDN 资源本地化 + 升级稳定版**:`web/static/dev.html` 顶部 markdown 渲染依赖从 jsDelivr CDN 改成本地 `web/static/vendor/markdown/` 文件,避免内网/跨境访问 CDN 抖动导致 Markdown / XSS sanitizer / 代码高亮不可用。版本按 npm/latest 核对后固定为 `marked@16.2.1`(`marked.umd.js`)、`dompurify@3.2.6`、`highlight.js@11.11.1`(含 `github.min.css`),并新增 `tests/test_static_vendor.py` 标准库 unittest 回归检查:HTML 不再出现 `cdn.jsdelivr.net`,且 4 个本地 vendor 文件存在非空。`DESIGN.md` 不动(无架构变化);`RUN.md` 不动(运行方式无变化)。
|
||||
- **dev SPA 三类上传入口显示进度**:`web/static/dev.html` 上传底层从 `fetch` 改为 `XMLHttpRequest` 以使用 `xhr.upload.onprogress`,保留 `/v1/files/upload` 后端 API 不变。`uploadFiles(files,{onProgress})` 统一服务 Ctrl+V 粘贴、右侧上传按钮、右侧拖拽上传;粘贴时 `#chat-hint` 显示 `上传中 N% · 文件名 · 已传/总量`,完成后仍切到可预览/可删除 chip;右侧上传按钮和拖拽入口共用 `#file-upload-status` 状态条,显示总进度条和完成/失败短提示,成功后刷新文件列表。`DESIGN.md` 不动(纯 dev SPA 上传交互);`RUN.md` 不动(运行方式无变化)。
|
||||
- **dev SPA Ctrl+V 粘贴上传 chip 支持删除**:`web/static/dev.html` 粘贴上传成功后的 chip 改成 `paste-chip-wrap` 组合控件:文件名按钮继续预览,右侧 `×` 调 `POST /v1/files/delete` 删除该上传文件(`recursive:false`),删除后移除对应 chip、刷新右侧文件栏;若主/小预览当前正打开这个 rel,同步关闭对应预览。全部 chip 删除完后 `chat-hint` 显示"已删除粘贴文件"。`DESIGN.md` 不动(纯 dev SPA 交互);`RUN.md` 不动(运行方式无变化)。
|
||||
- **dev SPA Ctrl+V 粘贴上传反馈改成可预览 chip**:`web/static/dev.html` `uploadFiles()` 成功时返回 `/v1/files/upload` 的 `saved[]` 元数据,粘贴文件后 `#chat-hint` 显示"已粘贴" + `.art-chip` 文件 chip + "可在右侧文件处查看",不再 4s 自动消失,下一次发送时由原有"发送中…"状态覆盖。chip 点击复用 `openFilePreview`;若主文件预览框已打开,改开新增的 `#mini-preview-modal` 小预览窗(支持 image/video/pdf/text/md,其它格式给下载兜底),避免覆盖用户当前正在看的主预览。`DESIGN.md` 不动(纯 dev SPA 交互);`RUN.md` 不动(运行方式无变化)。
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DEV_HTML = ROOT / "web" / "static" / "dev.html"
|
||||
VENDOR_DIR = ROOT / "web" / "static" / "vendor" / "markdown"
|
||||
|
||||
|
||||
class StaticVendorTests(unittest.TestCase):
|
||||
def test_dev_html_uses_local_markdown_vendor_assets(self) -> None:
|
||||
html = DEV_HTML.read_text(encoding="utf-8")
|
||||
|
||||
self.assertNotIn("cdn.jsdelivr.net", html)
|
||||
self.assertIn('src="vendor/markdown/marked.umd.js"', html)
|
||||
self.assertIn('src="vendor/markdown/purify.min.js"', html)
|
||||
self.assertIn('src="vendor/markdown/highlight.min.js"', html)
|
||||
self.assertIn('href="vendor/markdown/github.min.css"', html)
|
||||
|
||||
for name in (
|
||||
"marked.umd.js",
|
||||
"purify.min.js",
|
||||
"highlight.min.js",
|
||||
"github.min.css",
|
||||
):
|
||||
path = VENDOR_DIR / name
|
||||
self.assertTrue(path.exists(), f"missing vendored asset: {path}")
|
||||
self.assertGreater(path.stat().st_size, 0, f"empty vendored asset: {path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -5,11 +5,11 @@
|
|||
<title>zcbot 控制台</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
|
||||
<!-- markdown + 防 XSS + 代码高亮(纯 CDN,失败优雅降级回 plain text) -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/marked@12/marked.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dompurify@3/dist/purify.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github.min.css" />
|
||||
<!-- markdown + 防 XSS + 代码高亮(本地 vendor,失败优雅降级回 plain text) -->
|
||||
<script src="vendor/markdown/marked.umd.js"></script>
|
||||
<script src="vendor/markdown/purify.min.js"></script>
|
||||
<script src="vendor/markdown/highlight.min.js"></script>
|
||||
<link rel="stylesheet" href="vendor/markdown/github.min.css" />
|
||||
|
||||
<style>
|
||||
:root {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
|
||||
Theme: GitHub
|
||||
Description: Light theme as seen on github.com
|
||||
Author: github.com
|
||||
Maintainer: @Hirse
|
||||
Updated: 2021-05-15
|
||||
|
||||
Outdated base version: https://github.com/primer/github-syntax-light
|
||||
Current colors taken from GitHub's CSS
|
||||
*/.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue