2026-04-22 05:57:06 +08:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
const fs = require("fs/promises");
|
|
|
|
|
const path = require("path");
|
|
|
|
|
const { spawnSync } = require("child_process");
|
|
|
|
|
|
|
|
|
|
const REPO_ROOT = path.resolve(__dirname, "..", "..");
|
|
|
|
|
const SPIKE_ROOT = path.join(REPO_ROOT, "rust", "spikes", "leptos-tiptap-spike");
|
|
|
|
|
const GENERATED_ROOT = path.join(SPIKE_ROOT, "generated", "island");
|
|
|
|
|
const TOOLCHAIN = "1.89.0-x86_64-unknown-linux-gnu";
|
|
|
|
|
const TARGET = "wasm32-unknown-unknown";
|
|
|
|
|
const OUT_NAME = "mnote-leptos-tiptap-spike-island";
|
|
|
|
|
const MANIFEST_PATH = path.join(SPIKE_ROOT, "Cargo.toml");
|
|
|
|
|
const WASM_PATH = path.join(
|
|
|
|
|
SPIKE_ROOT,
|
|
|
|
|
"target",
|
|
|
|
|
TARGET,
|
|
|
|
|
"debug",
|
|
|
|
|
"mnote_leptos_tiptap_spike.wasm",
|
|
|
|
|
);
|
|
|
|
|
const ENTRY_PATH = path.join(GENERATED_ROOT, `${OUT_NAME}.js`);
|
|
|
|
|
|
|
|
|
|
function run(command, args, options = {}) {
|
|
|
|
|
const result = spawnSync(command, args, {
|
|
|
|
|
cwd: options.cwd ?? REPO_ROOT,
|
|
|
|
|
env: process.env,
|
|
|
|
|
encoding: "utf8",
|
|
|
|
|
stdio: "pipe",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (result.status === 0) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const stdout = (result.stdout || "").trim();
|
|
|
|
|
const stderr = (result.stderr || "").trim();
|
|
|
|
|
const details = [stdout, stderr].filter(Boolean).join("\n");
|
|
|
|
|
throw new Error(
|
|
|
|
|
[`命令失败:${command} ${args.join(" ")}`, details].filter(Boolean).join("\n"),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function ensureGeneratedDir() {
|
|
|
|
|
await fs.rm(GENERATED_ROOT, { recursive: true, force: true });
|
|
|
|
|
await fs.mkdir(GENERATED_ROOT, { recursive: true });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function verifyEntry() {
|
|
|
|
|
const source = await fs.readFile(ENTRY_PATH, "utf8");
|
|
|
|
|
if (!source.includes("export function mount(container, options)")) {
|
|
|
|
|
throw new Error("island 入口缺少 mount 导出");
|
|
|
|
|
}
|
|
|
|
|
if (!source.includes("export function unmount(mount_id)")) {
|
|
|
|
|
throw new Error("island 入口缺少 unmount 导出");
|
|
|
|
|
}
|
2026-05-11 12:27:40 +08:00
|
|
|
if (!source.includes("export function mount_mindmap_shell(container, options)")) {
|
|
|
|
|
throw new Error("island 入口缺少 mount_mindmap_shell 导出");
|
|
|
|
|
}
|
|
|
|
|
if (!source.includes("export function unmount_mindmap_shell(mount_id)")) {
|
|
|
|
|
throw new Error("island 入口缺少 unmount_mindmap_shell 导出");
|
|
|
|
|
}
|
2026-04-22 05:57:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function buildLeptosTiptapIsland() {
|
|
|
|
|
// 说明:正式主链直接消费 lib.rs 的 wasm-bindgen 产物,不再把 trunk 演示页产物当作页面内 island 入口。
|
|
|
|
|
run("rustup", ["target", "add", TARGET, "--toolchain", TOOLCHAIN]);
|
|
|
|
|
run(
|
|
|
|
|
"cargo",
|
|
|
|
|
[
|
|
|
|
|
`+${TOOLCHAIN}`,
|
|
|
|
|
"build",
|
|
|
|
|
"--manifest-path",
|
|
|
|
|
MANIFEST_PATH,
|
|
|
|
|
"--lib",
|
|
|
|
|
"--target",
|
|
|
|
|
TARGET,
|
|
|
|
|
],
|
|
|
|
|
{ cwd: SPIKE_ROOT },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await ensureGeneratedDir();
|
|
|
|
|
|
|
|
|
|
run(
|
|
|
|
|
"wasm-bindgen",
|
|
|
|
|
[
|
|
|
|
|
WASM_PATH,
|
|
|
|
|
"--target",
|
|
|
|
|
"web",
|
|
|
|
|
"--out-dir",
|
|
|
|
|
GENERATED_ROOT,
|
|
|
|
|
"--out-name",
|
|
|
|
|
OUT_NAME,
|
|
|
|
|
],
|
|
|
|
|
{ cwd: SPIKE_ROOT },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await verifyEntry();
|
|
|
|
|
return {
|
|
|
|
|
generatedRoot: GENERATED_ROOT,
|
|
|
|
|
entryPath: ENTRY_PATH,
|
|
|
|
|
wasmPath: path.join(GENERATED_ROOT, `${OUT_NAME}_bg.wasm`),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
|
buildLeptosTiptapIsland,
|
|
|
|
|
GENERATED_ROOT,
|
|
|
|
|
OUT_NAME,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (require.main === module) {
|
|
|
|
|
buildLeptosTiptapIsland()
|
|
|
|
|
.then(({ generatedRoot }) => {
|
|
|
|
|
process.stdout.write(`leptos-tiptap island 已生成:${generatedRoot}\n`);
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
});
|
|
|
|
|
}
|