feat: 品牌裁剪弹窗/Markdown 行内短代码与详情视频块等
新增: - BrandCropModal 品牌图裁剪弹窗 + cropImage 工具 - Markdown 行内短代码(inlineShortcodes + remark 插件) - MdDetails 折叠块、MdVideo 视频块组件 - directiveBlocks/inlineShortcodes 测试 其它: - 聊天后端(handler/service chat)调整 - Markdown 渲染链路、编辑器、全局样式与品牌相关面板更新
This commit is contained in:
117
frontend/lib/directiveBlocks.test.ts
Normal file
117
frontend/lib/directiveBlocks.test.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import {
|
||||
DETAILS_DEFAULT_TITLE,
|
||||
isDetailsOpen,
|
||||
parseDetailsOpen,
|
||||
parseVideoInput,
|
||||
parseVideoLine,
|
||||
splitContentSegments,
|
||||
} from "./directiveBlocks.ts";
|
||||
|
||||
describe("parseDetailsOpen / isDetailsOpen", () => {
|
||||
it("开标记整行匹配,标题缺省「点击展开」", () => {
|
||||
assert.equal(isDetailsOpen("[details]"), true);
|
||||
assert.equal(parseDetailsOpen("[details]"), DETAILS_DEFAULT_TITLE);
|
||||
assert.equal(parseDetailsOpen("[details 点击展开看结论]"), "点击展开看结论");
|
||||
assert.equal(isDetailsOpen("[details 标题] 后缀"), false);
|
||||
assert.equal(isDetailsOpen("[details]"), true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseVideoInput", () => {
|
||||
it("BV 号与 B站链接", () => {
|
||||
assert.deepEqual(parseVideoInput("BV1GJ411x7h7"), {
|
||||
provider: "bilibili",
|
||||
id: "BV1GJ411x7h7",
|
||||
});
|
||||
assert.deepEqual(parseVideoInput("https://www.bilibili.com/video/BV1GJ411x7h7/?p=1"), {
|
||||
provider: "bilibili",
|
||||
id: "BV1GJ411x7h7",
|
||||
});
|
||||
});
|
||||
it("YouTube ID 与链接", () => {
|
||||
assert.deepEqual(parseVideoInput("dQw4w9WgXcQ"), {
|
||||
provider: "youtube",
|
||||
id: "dQw4w9WgXcQ",
|
||||
});
|
||||
assert.deepEqual(parseVideoInput("https://youtu.be/dQw4w9WgXcQ"), {
|
||||
provider: "youtube",
|
||||
id: "dQw4w9WgXcQ",
|
||||
});
|
||||
assert.deepEqual(parseVideoInput("https://www.youtube.com/watch?v=dQw4w9WgXcQ"), {
|
||||
provider: "youtube",
|
||||
id: "dQw4w9WgXcQ",
|
||||
});
|
||||
});
|
||||
it("非法输入返回 null", () => {
|
||||
assert.equal(parseVideoInput(""), null);
|
||||
assert.equal(parseVideoInput("hello world"), null);
|
||||
assert.equal(parseVideoInput("https://evil.com/<script>"), null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("parseVideoLine", () => {
|
||||
it("整行短代码匹配且大小写不敏感", () => {
|
||||
assert.deepEqual(parseVideoLine("[bilibili]BV1GJ411x7h7[/bilibili]"), {
|
||||
provider: "bilibili",
|
||||
id: "BV1GJ411x7h7",
|
||||
});
|
||||
assert.deepEqual(parseVideoLine("[BILIBILI]https://www.bilibili.com/video/BV1GJ411x7h7[/BILIBILI]"), {
|
||||
provider: "bilibili",
|
||||
id: "BV1GJ411x7h7",
|
||||
});
|
||||
assert.deepEqual(parseVideoLine("[youtube]dQw4w9WgXcQ[/youtube]"), {
|
||||
provider: "youtube",
|
||||
id: "dQw4w9WgXcQ",
|
||||
});
|
||||
});
|
||||
it("标签与平台不一致或内容非法时返回 null", () => {
|
||||
assert.equal(parseVideoLine("[bilibili]dQw4w9WgXcQ[/bilibili]"), null);
|
||||
assert.equal(parseVideoLine("[youtube]BV1GJ411x7h7[/youtube]"), null);
|
||||
assert.equal(parseVideoLine("[bilibili]随便[/bilibili]"), null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("splitContentSegments: details/video", () => {
|
||||
it("[details] 块拆分,正文保留 markdown", () => {
|
||||
const segs = splitContentSegments(
|
||||
"前文\n\n[details 结论]\n**加粗** 内容\n[/details]\n\n后文"
|
||||
);
|
||||
assert.deepEqual(
|
||||
segs.map((s) => s.type),
|
||||
["md", "details", "md"]
|
||||
);
|
||||
const d = segs[1];
|
||||
assert.equal(d.type === "details" ? d.title : "", "结论");
|
||||
assert.equal(d.type === "details" ? d.body : "", "**加粗** 内容");
|
||||
});
|
||||
|
||||
it("details 嵌套开标签:外层按 md,内层与闭合配对(与 timeline 语义一致)", () => {
|
||||
const segs = splitContentSegments("[details A]\n[details B]\n[/details]");
|
||||
assert.deepEqual(segs.map((s) => s.type), ["md", "details"]);
|
||||
});
|
||||
|
||||
it("未闭合的 details 整段按 md", () => {
|
||||
const segs = splitContentSegments("正文\n\n[details A]\n没有闭合标记");
|
||||
assert.deepEqual(segs.map((s) => s.type), ["md"]);
|
||||
});
|
||||
|
||||
it("代码围栏内伪语法不拆", () => {
|
||||
const segs = splitContentSegments("```\n[details 假的]\n[/details]\n```");
|
||||
assert.deepEqual(segs.map((s) => s.type), ["md"]);
|
||||
});
|
||||
|
||||
it("视频整行拆为 video 段;行内出现不拆", () => {
|
||||
const segs = splitContentSegments(
|
||||
"看这个:\n\n[bilibili]BV1GJ411x7h7[/bilibili]\n\n文中 [youtube]dQw4w9WgXcQ[/youtube] 不拆"
|
||||
);
|
||||
assert.deepEqual(
|
||||
segs.map((s) => s.type),
|
||||
["md", "video", "md"]
|
||||
);
|
||||
const v = segs[1];
|
||||
assert.equal(v.type === "video" ? v.provider : "", "bilibili");
|
||||
assert.equal(v.type === "video" ? v.id : "", "BV1GJ411x7h7");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user