fix(desktop): sanitize Obsidian file path separators
This commit is contained in:
parent
ed1cc36af6
commit
9bfcfc805b
|
|
@ -0,0 +1,74 @@
|
|||
import fsp from "node:fs/promises"
|
||||
import os from "node:os"
|
||||
|
||||
import type { IpcContext } from "electron-ipc-decorator"
|
||||
import path from "pathe"
|
||||
import { afterEach, describe, expect, it, vi } from "vitest"
|
||||
|
||||
import { IntegrationService } from "./integration"
|
||||
|
||||
vi.mock("electron", () => ({
|
||||
ipcMain: {
|
||||
handle: vi.fn(),
|
||||
},
|
||||
shell: {
|
||||
openExternal: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock("electron-ipc-decorator", () => ({
|
||||
IpcMethod: () => (_target: unknown, _propertyKey: string, descriptor: PropertyDescriptor) =>
|
||||
descriptor,
|
||||
IpcService: class {},
|
||||
}))
|
||||
|
||||
vi.mock("~/lib/store", () => ({
|
||||
store: {
|
||||
get: vi.fn(),
|
||||
set: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock("~/logger", () => ({
|
||||
logger: {
|
||||
debug: vi.fn(),
|
||||
error: vi.fn(),
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
describe("IntegrationService", () => {
|
||||
let vaultPath: string | undefined
|
||||
|
||||
afterEach(async () => {
|
||||
if (!vaultPath) return
|
||||
|
||||
await fsp.rm(vaultPath, { force: true, recursive: true })
|
||||
vaultPath = undefined
|
||||
})
|
||||
|
||||
it("saves Obsidian titles with path separators as one markdown file", async () => {
|
||||
vaultPath = await fsp.mkdtemp(path.join(os.tmpdir(), "folo-obsidian-"))
|
||||
const service = new IntegrationService()
|
||||
const context = {} as IpcContext
|
||||
|
||||
await expect(
|
||||
service.saveToObsidian(context, {
|
||||
url: "https://example.com",
|
||||
title: "KAWA DESIGN 少女前线2:追放 索米·雪兔献礼 1/6比例手办",
|
||||
content: "content",
|
||||
author: "Folo",
|
||||
publishedAt: "2026-05-14T04:20:44.405Z",
|
||||
vaultPath,
|
||||
}),
|
||||
).resolves.toEqual({ success: true })
|
||||
|
||||
await expect(fsp.readdir(vaultPath)).resolves.toEqual([
|
||||
"KAWA DESIGN 少女前线2:追放 索米·雪兔献礼 1_6比例手办.md",
|
||||
])
|
||||
await expect(
|
||||
fsp.stat(path.join(vaultPath, "KAWA DESIGN 少女前线2:追放 索米·雪兔献礼 1")),
|
||||
).rejects.toThrow()
|
||||
})
|
||||
})
|
||||
|
|
@ -14,7 +14,7 @@ import { createObsidianFrontmatter } from "./obsidian-frontmatter"
|
|||
// Taken from https://github.com/rollup/rollup/blob/4f69d33af3b2ec9320c43c9e6c65ea23a02bdde3/src/utils/sanitizeFileName.ts
|
||||
// https://datatracker.ietf.org/doc/html/rfc2396
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$%&*+,:;<=>?[\]^`{|}\u007F]/g
|
||||
const INVALID_CHAR_REGEX = /[\u0000-\u001F"#$%&*+,:;<=>?[\]^`{|}\u007F/\\]/g
|
||||
const DRIVE_LETTER_REGEX = /^[a-z]:/i
|
||||
|
||||
function sanitizeFileName(name: string): string {
|
||||
|
|
|
|||
Loading…
Reference in New Issue