0.1.14 上线前更改
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "MNOTE AI Bridge",
|
||||
"guid": "asc.{F2B9A7B4-3A22-4E0E-8B32-3B0DE7AE8A60}",
|
||||
"version": "1.0.0",
|
||||
"baseUrl": "",
|
||||
"variations": [
|
||||
{
|
||||
"description": "MNOTE AI 工具桥接(选区读写)",
|
||||
"url": "index.html",
|
||||
"icons": ["icon.svg"],
|
||||
"isViewer": true,
|
||||
"EditorsSupport": ["word", "cell", "slide", "pdf"],
|
||||
"isVisual": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
||||
<path d="M16 14h32a4 4 0 0 1 4 4v28a4 4 0 0 1-4 4H16a4 4 0 0 1-4-4V18a4 4 0 0 1 4-4Z" stroke="currentColor" stroke-width="4"/>
|
||||
<path d="M22 28h20M22 36h14" stroke="currentColor" stroke-width="4" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 305 B |
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>MNOTE OnlyOffice Agent Tools</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="plugin.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// 说明:该插件用于把 ONLYOFFICE 编辑器“选区读/写”能力暴露给宿主页面(MNOTE)。
|
||||
// 宿主页面通过 postMessage 下发 oo_* 工具调用;插件执行后再 postMessage 回传结果。
|
||||
(function () {
|
||||
const CHANNEL = "mnote_onlyoffice_agent_tools_v1";
|
||||
|
||||
const safePostToTop = (payload) => {
|
||||
try {
|
||||
if (typeof window === "undefined") return;
|
||||
if (!window.top) return;
|
||||
window.top.postMessage({ channel: CHANNEL, ...payload }, "*");
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
const execMethod = (method, args) =>
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
if (!window.Asc || !window.Asc.plugin) throw new Error("ONLYOFFICE 插件 API 未就绪");
|
||||
window.Asc.plugin.executeMethod(method, Array.isArray(args) ? args : [], (res) => resolve(res));
|
||||
} catch (e) {
|
||||
reject(e instanceof Error ? e : new Error(String(e)));
|
||||
}
|
||||
});
|
||||
|
||||
const handleTool = async (tool, args) => {
|
||||
const a = args && typeof args === "object" ? args : {};
|
||||
if (tool === "oo_get_selection") {
|
||||
// 说明:先做最基础的“纯文本选区读取”,HTML 可在后续升级(需要更复杂的导出方式)。
|
||||
const text = await execMethod("GetSelectedText", []);
|
||||
return { format: "text", text: String(text ?? "") };
|
||||
}
|
||||
|
||||
if (tool === "oo_replace_selection") {
|
||||
const format = String(a.format ?? "text");
|
||||
const text = String(a.text ?? "");
|
||||
if (format === "html") {
|
||||
await execMethod("PasteHtml", [text]);
|
||||
return { ok: true, format: "html", length: text.length };
|
||||
}
|
||||
await execMethod("PasteText", [text]);
|
||||
return { ok: true, format: "text", length: text.length };
|
||||
}
|
||||
|
||||
if (tool === "oo_insert_text") {
|
||||
const text = String(a.text ?? "");
|
||||
await execMethod("PasteText", [text]);
|
||||
return { ok: true, length: text.length };
|
||||
}
|
||||
|
||||
if (tool === "oo_insert_html") {
|
||||
const html = String(a.html ?? "");
|
||||
await execMethod("PasteHtml", [html]);
|
||||
return { ok: true, length: html.length };
|
||||
}
|
||||
|
||||
if (tool === "oo_insert_image") {
|
||||
// 说明:优先用 HTML 插入 <img>,避免依赖 PutImageDataToSelection 的参数差异。
|
||||
const src = String(a.src ?? a.imageData ?? "");
|
||||
if (!src) throw new Error("缺少图片数据(src/imageData)");
|
||||
const w = Number(a.width ?? 0);
|
||||
const h = Number(a.height ?? 0);
|
||||
const widthAttr = Number.isFinite(w) && w > 0 ? ` width=\"${Math.floor(w)}\"` : "";
|
||||
const heightAttr = Number.isFinite(h) && h > 0 ? ` height=\"${Math.floor(h)}\"` : "";
|
||||
const html = `<img src=\"${src}\"${widthAttr}${heightAttr} />`;
|
||||
await execMethod("PasteHtml", [html]);
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
throw new Error(`未知工具:${tool}`);
|
||||
};
|
||||
|
||||
window.Asc = window.Asc || {};
|
||||
window.Asc.plugin = window.Asc.plugin || {};
|
||||
|
||||
window.Asc.plugin.init = function () {
|
||||
safePostToTop({ type: "ready" });
|
||||
};
|
||||
|
||||
window.addEventListener("message", async (ev) => {
|
||||
const msg = ev && ev.data ? ev.data : null;
|
||||
if (!msg || typeof msg !== "object") return;
|
||||
if (msg.channel !== CHANNEL) return;
|
||||
if (msg.type !== "call") return;
|
||||
|
||||
const callId = String(msg.callId ?? "").trim();
|
||||
const tool = String(msg.tool ?? "").trim();
|
||||
const args = msg.args && typeof msg.args === "object" ? msg.args : {};
|
||||
if (!callId || !tool) return;
|
||||
|
||||
try {
|
||||
const result = await handleTool(tool, args);
|
||||
safePostToTop({ type: "result", callId, ok: true, result });
|
||||
} catch (e) {
|
||||
const err = e instanceof Error ? e.message : String(e);
|
||||
safePostToTop({ type: "result", callId, ok: false, error: err });
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user