diff --git a/src/command/render/render.ts b/src/command/render/render.ts index 8cc9538bcf..3da6c73f04 100644 --- a/src/command/render/render.ts +++ b/src/command/render/render.ts @@ -385,8 +385,24 @@ export async function renderPandoc( )); } - // if there is a project context then return paths relative to the project - const projectPath = (path: string) => { + // Compute the project-relative path for the input source file. + // Uses normalizePath to handle both relative and absolute source paths. + const projectRelativeInput = (sourcePath: string) => { + if (context.project) { + return relative( + normalizePath(context.project.dir), + normalizePath(sourcePath), + ); + } + return sourcePath; + }; + + // Resolve an output file path to a project-relative path. + // Output paths (like "page.html") are relative to the source file's + // directory, so we join with dirname(target.source) before computing + // the project-relative result. Absolute output paths pass through + // normalizePath directly. + const projectOutputPath = (path: string) => { if (context.project) { if (isAbsolute(path)) { return relative( @@ -411,7 +427,7 @@ export async function renderPandoc( const result: RenderedFile = { isTransient: recipe.isOutputTransient, - input: projectPath(context.target.source), + input: projectRelativeInput(context.target.source), markdown: executeResult.markdown, format, supporting: supporting @@ -421,7 +437,7 @@ export async function renderPandoc( : undefined, file: recipe.isOutputTransient ? finalOutput! - : projectPath(finalOutput!), + : projectOutputPath(finalOutput!), resourceFiles: { globs: pandocResult.resources, files, diff --git a/tests/unit/project/file-information-cache.test.ts b/tests/unit/project/file-information-cache.test.ts index 8ef119e22e..9f552e9c96 100644 --- a/tests/unit/project/file-information-cache.test.ts +++ b/tests/unit/project/file-information-cache.test.ts @@ -9,7 +9,7 @@ import { unitTest } from "../../test.ts"; import { assert } from "testing/asserts"; -import { join } from "../../../src/deno_ral/path.ts"; +import { join, relative } from "../../../src/deno_ral/path.ts"; import { ensureFileInformationCache, FileInformationCacheMap, @@ -107,3 +107,26 @@ unitTest( ); }, ); + +// deno-lint-ignore require-await +unitTest( + "fileInformationCache - relative and absolute paths share same entry", + async () => { + const project = createMockProjectContext(); + + const absolutePath = join(project.dir, "subdir", "page.qmd"); + const relativePath = relative(Deno.cwd(), absolutePath); + + const entry1 = ensureFileInformationCache(project, relativePath); + const entry2 = ensureFileInformationCache(project, absolutePath); + + assert( + entry1 === entry2, + "Relative and absolute paths to same file should share a cache entry", + ); + assert( + project.fileInformationCache.size === 1, + "Should have exactly one cache entry", + ); + }, +);