Support imported YAML properties without adding a toolbar entry. Keep ordinary single-note exports body-only and retain full metadata for ZIP backups.
57 lines
2.8 KiB
TypeScript
57 lines
2.8 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { splitMarkdownFrontMatter } from "@edgeever/shared";
|
|
import {
|
|
buildMarkdownFilename,
|
|
buildSingleNoteMarkdown,
|
|
createMarkdownFile,
|
|
} from "../apps/web/src/lib/note-markdown-export";
|
|
|
|
describe("single-note Markdown export", () => {
|
|
test("creates a UTF-8 Markdown file with the current content", async () => {
|
|
const file = createMarkdownFile("# 标题\n\n当前未保存内容", "项目 / 计划", "Untitled note");
|
|
|
|
expect(file.filename).toBe("项目 - 计划.md");
|
|
expect(file.blob.type).toBe("text/markdown;charset=utf-8");
|
|
expect(await file.blob.text()).toBe("# 标题\n\n当前未保存内容");
|
|
});
|
|
|
|
test("sanitizes unsafe and reserved filenames", () => {
|
|
expect(buildMarkdownFilename("CON", "Untitled note")).toBe("_CON.md");
|
|
expect(buildMarkdownFilename('<>:"/\\|?*', "Untitled note")).toBe("---------.md");
|
|
expect(buildMarkdownFilename("...", "Untitled note")).toBe("Untitled note.md");
|
|
expect(buildMarkdownFilename("README.md", "Untitled note")).toBe("README.md");
|
|
});
|
|
});
|
|
|
|
describe("single-note Markdown properties", () => {
|
|
test("ordinary notes export only their body", async () => {
|
|
const body = "# Article\n\nBody with **formatting**.\n";
|
|
const markdown = buildSingleNoteMarkdown(body, "Article", ["work"]);
|
|
expect(markdown).toBe(body);
|
|
expect(await createMarkdownFile(markdown, "Article", "Untitled").blob.text()).toBe(body);
|
|
});
|
|
|
|
test("retains comments and custom properties while updating existing title and tags", () => {
|
|
const markdown = buildSingleNoteMarkdown("---\n# Preserve this comment\ntitle: Old\ntags: [old]\nauthor: Alice\ncustom:\n reviewed: true\n---\n\nBody", "New", ["new"]);
|
|
const header = splitMarkdownFrontMatter(markdown)!;
|
|
expect(header.values).toEqual({ title: "New", tags: ["new"], author: "Alice", custom: { reviewed: true } });
|
|
expect(header.source).toContain("# Preserve this comment");
|
|
expect(header.body.trim()).toBe("Body");
|
|
});
|
|
|
|
test("does not add title, tags or system fields to a custom-only header", () => {
|
|
const markdown = "---\nsource: https://example.com\n---\n\nBody";
|
|
expect(buildSingleNoteMarkdown(markdown, "Article", ["work"])).toBe(markdown);
|
|
});
|
|
|
|
test("retains original system fields without replacing or supplementing them", () => {
|
|
const markdown = buildSingleNoteMarkdown("---\ntitle: Old\ncreated: 2020-01-01\nedgeever_id: original\n---\n\nBody", "New", ["work"]);
|
|
expect(splitMarkdownFrontMatter(markdown)!.values).toEqual({ title: "New", created: "2020-01-01", edgeever_id: "original" });
|
|
});
|
|
|
|
test("invalid properties remain recoverable verbatim", () => {
|
|
const markdown = "---\ntitle: [broken\n---\n\nBody";
|
|
expect(buildSingleNoteMarkdown(markdown, "Article", [])).toBe(markdown);
|
|
});
|
|
});
|