From aba4b4200a960ba9ec726d21e61af57cd8e370c0 Mon Sep 17 00:00:00 2001 From: MurakamiShinyu Date: Thu, 15 Jan 2026 00:31:25 +0900 Subject: [PATCH] fix: Fix error when input file is on different drive on Windows Fixes #725. On Windows, when the input file is on a different drive than the current working directory (e.g., running from D: with input on C:), the CLI would fail with a confusing error about overwriting the working directory. This was caused by two issues: 1. `pathContains()` incorrectly returned true when comparing paths on different drives, because `upath.relative()` returns an absolute path in such cases. 2. `getSourceUrl()` tried to compute a relative path for webbook inputs that already had a URL path format. Changes: - Fix `pathContains()` to check if the relative path is absolute (indicating different drives) and return false in that case - Fix `getSourceUrl()` to use `webbookEntryUrl` directly as a URL path instead of computing a relative path from `workspaceDir` --- .changeset/fine-flies-drum.md | 5 +++++ src/server.ts | 14 ++++++++++---- src/util.ts | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 .changeset/fine-flies-drum.md diff --git a/.changeset/fine-flies-drum.md b/.changeset/fine-flies-drum.md new file mode 100644 index 00000000..fa3604e3 --- /dev/null +++ b/.changeset/fine-flies-drum.md @@ -0,0 +1,5 @@ +--- +'@vivliostyle/cli': patch +--- + +Fix error when input file is on different drive on Windows diff --git a/src/server.ts b/src/server.ts index b4d925b2..b5dcbd3d 100644 --- a/src/server.ts +++ b/src/server.ts @@ -122,12 +122,16 @@ export async function getSourceUrl({ 'viewerInput' | 'base' | 'workspaceDir' | 'rootUrl' >) { let input: string; + let isUrlPath = false; switch (viewerInput.type) { case 'webpub': input = viewerInput.manifestPath; break; case 'webbook': input = viewerInput.webbookEntryUrl; + // webbookEntryUrl is already a URL path (e.g., "/vivliostyle/test.html") + // or a full URL (e.g., "https://example.com/test.html") + isUrlPath = !isValidUri(input); break; case 'epub-opf': input = viewerInput.epubOpfPath; @@ -145,10 +149,12 @@ export async function getSourceUrl({ return ( isValidUri(input) ? new URL(input) - : new URL( - upath.posix.join(base, upath.relative(workspaceDir, input)), - rootUrl, - ) + : isUrlPath + ? new URL(input, rootUrl) + : new URL( + upath.posix.join(base, upath.relative(workspaceDir, input)), + rootUrl, + ) ).href; } diff --git a/src/util.ts b/src/util.ts index 53883e22..ed4782e8 100644 --- a/src/util.ts +++ b/src/util.ts @@ -218,7 +218,8 @@ export function pathEquals(path1: string, path2: string): boolean { export function pathContains(parentPath: string, childPath: string): boolean { const rel = upath.relative(parentPath, childPath); - return rel !== '' && !rel.startsWith('..'); + // If relative path is absolute (different drives on Windows), they are not related + return rel !== '' && !rel.startsWith('..') && !upath.isAbsolute(rel); } export function isValidUri(str: string): boolean {