(root: string, rel: string)
| 3050 | * is left in place. Returns the new drawing's metadata. (#266) |
| 3051 | */ |
| 3052 | export async function convertObsidianExcalidraw(root: string, rel: string): Promise<NoteMeta> { |
| 3053 | const abs = resolveSafe(root, rel) |
| 3054 | const folder = folderOf(root, abs) |
| 3055 | if (!folder) throw new Error(`Drawing is not in a known folder: ${rel}`) |
| 3056 | const markdown = await fs.readFile(abs, 'utf8') |
| 3057 | if (!isObsidianExcalidrawPath(rel) && !isObsidianExcalidrawMarkdown(markdown)) { |
| 3058 | throw new Error('This file is not an Obsidian Excalidraw drawing.') |
| 3059 | } |
| 3060 | const scene = extractObsidianExcalidrawScene(markdown) |
| 3061 | if (!scene) { |
| 3062 | throw new Error('Could not read an Excalidraw scene from this file.') |
| 3063 | } |
| 3064 | |
| 3065 | const fileName = path.basename(abs) |
| 3066 | const base = |
| 3067 | (fileName.toLowerCase().endsWith('.excalidraw.md') |
| 3068 | ? fileName.slice(0, -'.excalidraw.md'.length) |
| 3069 | : path.basename(fileName, path.extname(fileName))) || 'Untitled drawing' |
| 3070 | const dir = path.dirname(abs) |
| 3071 | let finalTitle = base |
| 3072 | for (let n = 2; ; n++) { |
| 3073 | try { |
| 3074 | await fs.access(path.join(dir, `${finalTitle}.excalidraw`)) |
| 3075 | finalTitle = `${base} ${n}` |
| 3076 | } catch { |
| 3077 | break |
| 3078 | } |
| 3079 | } |
| 3080 | const destAbs = path.join(dir, `${finalTitle}.excalidraw`) |
| 3081 | await fs.writeFile(destAbs, JSON.stringify(scene, null, 2), 'utf8') |
| 3082 | invalidateNoteMetaCache(root, toPosix(path.relative(root, destAbs))) |
| 3083 | return await readMeta(root, destAbs, folder) |
| 3084 | } |
| 3085 | |
| 3086 | /** |
| 3087 | * Move a markdown file that lives outside the vault into the vault's |
no test coverage detected