diff --git a/src/data-index/index.ts b/src/data-index/index.ts index fb1d04681..1aa081123 100644 --- a/src/data-index/index.ts +++ b/src/data-index/index.ts @@ -276,15 +276,41 @@ export class PrefixIndex extends Component { /** * Use the in-memory prefix index to convert a relative path to an absolute one. + * - Absolute paths start with "/" and are resolved from the vault root (the leading "/" is stripped). + * - Relative paths starting with "./" or "../" are resolved relative to the origin file's parent folder. + * - Other paths are treated as absolute (from vault root) for backward compatibility. */ public resolveRelative(path: string, origin?: string): string { if (!origin) return path; else if (path.startsWith("/")) return path.substring(1); + // Only resolve as relative if the path explicitly starts with "./" or "../". + // This preserves backward compatibility for absolute paths like "projects/folder". + let relativePath = getParentFolder(origin) + "/" + path; + if (path.startsWith("./") || path.startsWith("../")) { + // Normalize the path by resolving ".." and "." segments. + relativePath = this.normalizePath(relativePath); + } + if (this.pathExists(relativePath)) return relativePath; else return path; } + + /** Normalize a path by resolving ".." and "." segments. */ + private normalizePath(path: string): string { + let parts = path.split("/").filter(p => p.length > 0); + let stack: string[] = []; + for (let part of parts) { + if (part === ".") continue; + else if (part === "..") { + if (stack.length > 0) stack.pop(); + } else { + stack.push(part); + } + } + return stack.join("/"); + } } /** Simple path filters which filter file types. */ diff --git a/src/data-index/resolver.ts b/src/data-index/resolver.ts index 5a4070990..3e25eb172 100644 --- a/src/data-index/resolver.ts +++ b/src/data-index/resolver.ts @@ -22,14 +22,18 @@ export function matchingSourcePaths( case "csv": return Result.success(new Set([index.prefix.resolveRelative(source.path, originFile)])); case "folder": + // Resolve relative/absolute paths: paths starting with "/" are absolute (from vault root), + // paths containing ".." or starting with "./" are relative to the origin file. + let resolvedFolder = index.prefix.resolveRelative(source.folder, originFile); + // Prefer loading from the folder at the given path. - if (index.prefix.nodeExists(source.folder)) - return Result.success(index.prefix.get(source.folder, PathFilters.markdown)); + if (index.prefix.nodeExists(resolvedFolder)) + return Result.success(index.prefix.get(resolvedFolder, PathFilters.markdown)); // But allow for loading individual files if they exist. - if (index.prefix.pathExists(source.folder)) return Result.success(new Set([source.folder])); - else if (index.prefix.pathExists(source.folder + ".md")) - return Result.success(new Set([source.folder + ".md"])); + if (index.prefix.pathExists(resolvedFolder)) return Result.success(new Set([resolvedFolder])); + else if (index.prefix.pathExists(resolvedFolder + ".md")) + return Result.success(new Set([resolvedFolder + ".md"])); // For backwards-compat, return an empty result even if the folder does not exist. return Result.success(new Set());