12 Commits

Author SHA1 Message Date
xfy
8f6c864f22 chore(tiptap): 移除未使用的 RunCodeOptsJs 重导出
RunCodeOptsJs 只在 mod wasm 内部用作 Closure 类型参数,无外部消费者,
从 pub use 重导出列表移除以消除 unused_imports warning。
2026-07-07 18:34:17 +08:00
xfy
0c1e8b7640 feat(bridge): 新增 make_run_code_closure 桥接编辑器内运行代码
tiptap_bridge.rs:
- EditorOptions extern 追加 set_on_run_code setter (js_name=onRunCode)
- 新增 RunCodeOptsJs 映射(language/source/overridesJson getter)
- 新增 format_run_result + make_run_code_closure
  · start_exec + 500ms 轮询 get_exec_result,30s 上限
  · overridesJson 空串视为 None,畸形 JSON 静默降级
  · 不依赖 server-only 的 languages 模块(前端 extractLang 已提取纯语言名)
- EditorHandle 加 _on_run_code 字段 + new 参数
- pub use 导出 make_run_code_closure + RunCodeOptsJs

write.rs: 跟进 EditorHandle::new 新签名(构造 on_run_code + set_on_run_code)。
2026-07-06 18:11:28 +08:00
xfy
373498870a style: apply cargo fmt to workspace
Some checks failed
CI / check (push) Failing after 5m35s
CI / build (push) Has been skipped
2026-06-29 13:47:40 +08:00
xfy
96da2f27d5 docs: 补齐 tiptap_bridge 文档注释并新增 make doc 目标
- tiptap_bridge.rs: 为 wasm-bindgen 桥接层全部 19 处 pub 项补文档
  (JS 类型映射、getter/setter、EditorHandle::new、pub use 重导出)
- markdown.rs: 用反引号包裹注释内字面量 <span>,消除 rustdoc 警告
- Makefile: 新增 doc / doc-open,纯 binary crate 需 --document-private-items
  才能让内部模块进文档
2026-06-25 18:26:56 +08:00
xfy
8971fbe1a2 feat(write): 支持封面图上传(拖拽/点击/粘贴)
将编辑页封面图从纯 URL 输入框升级为完整的上传控件:
- 16:9 拖拽区,支持拖拽文件、点击选择、剪贴板粘贴三种上传入口
- 完整交互状态:空态/上传中(骨架占位)/预览/错误提示
- 保留外链 URL 输入(内联折叠),覆盖图床/CDN 场景
- 上传复用现有 POST /api/upload,服务端零改动

tiptap_bridge 提取 upload_image_file 通用上传函数,
make_upload_upload 改为薄包装,消除 fetch 逻辑重复。

Cargo.toml 补 web-sys feature(ClipboardEvent/DataTransfer/FileList/
HtmlInputElement),供粘贴/拖拽读取文件。
2026-06-24 15:09:47 +08:00
xfy
1cc09e4cbc fix(bridge): use unchecked_into for TiptapEditorModule (not dyn_into)
Some checks failed
CI / check (push) Failing after 4m44s
CI / build (push) Has been skipped
dyn_into runs 'instanceof TiptapEditorModule', but the IIFE TiptapEditor
is a plain object literal — not an instance of wasm-bindgen's registered
constructor — so the check always fails with a panic.

unchecked_into does only the compile-time type annotation; Reflect::get
already guarantees we have the right object.
2026-06-24 10:38:33 +08:00
xfy
410d594ac0 fix(bridge): read window.TiptapEditor via Reflect.get, not function call
The extern 'fn get_module() -> TiptapEditorModule' was compiled by
wasm-bindgen to 'window.TiptapEditor()' — a function call. But
TiptapEditor is the IIFE module object, not a function, so this threw
'window.TiptapEditor is not a function'.

Replace with js_sys::Reflect::get(&window, "TiptapEditor") +
dyn_into, which reads the property without invoking it.

This bug predated the Vite 8 upgrade but only surfaced after the
EditorOptions fix let initialization progress further.
2026-06-24 10:35:11 +08:00
xfy
975e331dd5 fix(write): split tags on fullwidth punctuation
The tag splitter matched ASCII ',' and ';' twice instead of the
fullwidth ',' (U+FF0C) / ';' (U+FF1B) the comment intended, so tags
separated by fullwidth punctuation (common under Chinese IMEs)
collapsed into a single tag.

Also resolves the compiler warnings surfaced in the same build:
- tiptap_bridge: drop unused Readable/Writable imports and
  EditorInstance/TiptapEditorModule re-exports
- tiptap_bridge: migrate deprecated RequestInit::method/body/
  credentials builders to set_method/set_body/set_credentials
- write: remove redundant `mut` on Dioxus signals that are only
  read/set, never reassigned
- image_viewer: gate the server-only `mut` reassignment so the WASM
  build (which strips the cfg block) doesn't warn
2026-06-23 14:44:18 +08:00
xfy
ef6a3f0da2 fix(home,editor): repair post card nested anchors and editor upload state
首页审查修复(home/post_card/image_viewer/search/home_skeleton):
- PostCard 消除嵌套 <a>:外层 Link 包裹改为绝对定位覆盖层链接,
  标题/摘要/封面降级为普通元素,标签用 z-10 叠在覆盖层之上并
  stop_propagation,整卡点击跳转文章详情。
- ImageViewer 新增 lightbox prop(默认 true),卡片封面传 false
  禁用灯箱以归一为单一跳转交互;文章详情页零改动。
- home.rs 越界页码守卫:分页仅在 total>0 渲染,避免 /page/9999
  出现孤立空分页;错误文案脱敏为"加载失败"。
- search.rs 错误文案脱敏为"搜索失败",与首页/标签页一致。
- HomeSkeleton 卡片 5→10,对齐 POSTS_PER_PAGE。

编辑器上传重构(write/tiptap_bridge):
- consume_upload_event 改用 upload_errors Vec 自身判重,移除
  seen_error_ids 副本状态;Signal 参数加 mut 修复 E0596 编译错误。
- make_upload_closure 构造阶段错误以 rejected Promise 返回而非
  panic,单张坏文件不再拖垮整个编辑器。
- write.rs 移除未用的 success signal,编辑保存后统一跳转 Posts,
  标签分隔符支持半角/全角逗号与分号,提取 META_*_CLASS 常量去重。
- Makefile dev 目标清理 static/ 目录。
2026-06-23 14:14:28 +08:00
xfy
a6d30ed5d9 refactor(write): address code review feedback
- remove duplicate `use dioxus::prelude::*` (keep #[allow] inline with comment)
- update write_editor doc comment: callback-driven init, EditorHandle::drop cleanup
  (no more polling/globals)
- restore empty-url check in make_upload_closure (match original JS `success && url`):
  empty url on success now rejects with clear message instead of inserting broken image
- update AGENTS.md tiptap section: write.rs uses tiptap_bridge, no eval/polling
2026-06-23 13:32:34 +08:00
xfy
a3896c24a5 refactor(write): replace all js_sys::eval with tiptap_bridge bindings
write.rs changes (Tasks 7-11):
- use_drop: EditorHandle::drop replaces eval destroy + global reset (#1)
- init use_effect: closure-driven bridge.create replaces eval initEditor
  script + 100ms ready polling (#2/#3/#4/#5)
- getMarkdown: read via EditorHandle instead of eval (#8)
- delete upload polling use_future: driven by onUploadEvent closure (#6/#7)
- removeUploadByUploadId: call via EditorHandle instead of eval (#9)

Bridge fixes during integration:
- UploadCountsJs: drop Copy derive (wasm_bindgen types can't be Copy)
- split module: shared types compile on both targets, wasm externs gated
- add WritableExt/Readable/Writable trait imports for .write()/.set()
- use FnMut closures (Signal write/set take &mut self)
- consume_upload_event takes &mut Signal params

Also: remove stale window.__tiptap_content in index.ts source-mode handler.
2026-06-23 11:25:06 +08:00
xfy
84eea3272a feat(bridge): wasm-bindgen layer for TiptapEditor
Adds src/tiptap_bridge.rs with extern bindings for window.TiptapEditor
module, EditorInstance, EditorOptions (builder), UploadEventJs.
EditorHandle unifies instance + 4 closures lifecycle (Drop calls destroy).
consume_upload_event replaces the old polling body. make_upload_closure
does the /api/upload fetch in Rust (web_sys) instead of eval'd JS.
2026-06-23 10:56:00 +08:00