fix: robust UUID trimming and safer markdown/csv link conversion - #37
fix: robust UUID trimming and safer markdown/csv link conversion#37DragonBaiMo wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refines Notion export cleanup by trimming only Notion’s UUID suffix from file/folder names and improving link conversion so imported Obsidian vaults resolve more consistently.
Changes:
- Introduces a UUID-suffix-aware trimming regex and updates file/dir truncation to use it.
- Preserves media filenames while trimming text-like files, and attempts to skip no-op renames.
- Improves relative path and notion.so link conversion by decoding/normalizing paths and stripping UUID suffixes (with
.csvhandling added in wiki links).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let dest = truncateDirName(dir); | ||
| if (dest === dir) { | ||
| continue; | ||
| } | ||
| while (fs.existsSync(dest)) { |
There was a problem hiding this comment.
truncateDirName() returns a resolved (absolute) path, but dir is often a relative path (built via npath.format without resolve). When no trimming occurs, dest points to the same directory but dest !== dir, so the continue won’t trigger and fs.existsSync(dest) will be true, causing the loop to append a random suffix and rename directories unnecessarily (especially when exportPath is relative). Consider comparing normalized absolute paths (e.g., const src = npath.resolve(dir)), skipping when dest === src, and ensuring the collision loop treats dest === src as non-colliding.
| let dest = truncateDirName(dir); | |
| if (dest === dir) { | |
| continue; | |
| } | |
| while (fs.existsSync(dest)) { | |
| const src = npath.resolve(dir); | |
| let dest = truncateDirName(dir); | |
| // If truncateDirName did not effectively change the directory name, | |
| // skip renaming to avoid unnecessary collisions and renames. | |
| if (dest === src || dest === dir) { | |
| continue; | |
| } | |
| while (fs.existsSync(dest) && dest !== src) { |
| // Preserve media file names. Only trim Notion UUID suffix on markdown/csv and other text files. | ||
| if (!/\.(png|jpg|jpeg|gif|webp|svg|mp4|mov|m4a|mp3|wav|pdf)$/i.test(file)) { | ||
| let trunc = truncateFileName(file); | ||
| vlog(3, `Renaming file ${file} -> ${trunc}`); | ||
| fs.renameSync(file, trunc); | ||
| file = trunc; | ||
| files[i] = trunc; | ||
| if (trunc !== file) { | ||
| vlog(3, `Renaming file ${file} -> ${trunc}`); | ||
| fs.renameSync(file, trunc); | ||
| file = trunc; | ||
| files[i] = trunc; | ||
| } |
There was a problem hiding this comment.
truncateFileName() returns an absolute path (npath.resolve(...)), while file may be relative. That makes if (trunc !== file) almost always true even when the basename didn’t change, so the code will still attempt a rename and rewrite files[i] to an absolute path. To make the “skip rename when destination equals source” logic work reliably, compare trunc against npath.resolve(file) (or stop resolving inside truncateFileName).
| if (ext.toLowerCase() === '.csv') { | ||
| return `[[${cleanStem}.csv]]`; | ||
| } | ||
| return `[[${cleanStem}]]`; |
There was a problem hiding this comment.
convertRelativePath() can return an empty wiki link if the filename stem is only the UUID (or becomes empty after trimming). cleanStem isn’t given the same fallback used in truncateFileName/convertNotionLinks, so this can produce [[]] (or [[.csv]]). Consider falling back to the original stem when cleanStem is empty.
| if (ext.toLowerCase() === '.csv') { | |
| return `[[${cleanStem}.csv]]`; | |
| } | |
| return `[[${cleanStem}]]`; | |
| const safeStem = cleanStem || stem; | |
| if (ext.toLowerCase() === '.csv') { | |
| return `[[${safeStem}.csv]]`; | |
| } | |
| return `[[${safeStem}]]`; |
Summary
This PR improves Notion export path/name cleanup and link conversion so imported Obsidian vaults are more stable and readable.
What changed
/[\s-]?[0-9a-f]{32}$/i) for files and directories..csvextension in wiki links.Why
When converting large exports (especially with Chinese names), the previous logic could over-truncate names or create random suffixes, and generated links could still point to UUID-suffixed names. This made Obsidian navigation inconsistent.
Validation