Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/vscode/conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,14 @@ export class Configuration implements IRawConfigProvider {
/**
* Converts Windows-style absolute paths to a runtime-compatible path when
* the extension is running on a non-Windows host (e.g. WSL remote).
*
* Detection uses both `process.platform` and `vscode.env.remoteName` so that
* the normalization fires whenever the extension host is Linux-based — whether
* that is a native Linux installation, an SSH remote, or a WSL remote session
* where the user stored their journal base path as a Windows drive path.
*/
private normalizeBasePathForRuntime(basePath: string): string {
// Running natively on Windows: separators are already correct.
if (process.platform === 'win32') {
return basePath;
}
Expand All @@ -106,11 +112,15 @@ export class Configuration implements IRawConfigProvider {
const trimmed = basePath.replace(/^\/+/, '');
const isWindowsAbsPath = /^[a-zA-Z]:[\\/]/.test(trimmed);
if (!isWindowsAbsPath) {
return basePath;
// Not a Windows-style absolute path — nothing to convert.
// Still replace any stray backslashes so mixed-separator strings
// (e.g. from a ${workspaceFolder} expansion) become valid POSIX paths.
return basePath.replace(/\\/g, '/');
}

// Non-Windows remotes (WSL/SSH/containers): map Windows drive path to
// Linux mount style to avoid invalid paths such as /c:\Users\...
// the Linux /mnt/<drive>/... convention used by WSL, avoiding invalid
// mixed paths such as /C:\Users\...\journal/2026/05/20.md.
const drive = trimmed.charAt(0).toLowerCase();
const rest = trimmed.substring(2).replace(/\\/g, '/').replace(/^\/+/, '');
return `/mnt/${drive}/${rest}`;
Expand Down
18 changes: 18 additions & 0 deletions src/vscode/template-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ export class TemplateService {
scopedTemplate.value = replaceVariableValue("homeDir", os.homedir(), scopedTemplate.value);
scopedTemplate.value = replaceVariableValue("base", this.raw.getBasePath(scopeId), scopedTemplate.value);
scopedTemplate.value = resolveDate(scopedTemplate.value, date, this.raw.getLocale());
// On non-Windows hosts, eliminate any residual backslashes so that the
// fully-resolved path is a valid POSIX path (covers WSL remote sessions).
if (process.platform !== 'win32') {
scopedTemplate.value = scopedTemplate.value.replace(/\\/g, '/');
}
return scopedTemplate;
}

Expand All @@ -65,6 +70,9 @@ export class TemplateService {
scopedTemplate.value = replaceVariableValue("base", this.raw.getBasePath(scopeId), scopedTemplate.value);
scopedTemplate.value = replaceVariableValue("year", String(year), scopedTemplate.value);
scopedTemplate.value = replaceVariableValue("week", String(week), scopedTemplate.value);
if (process.platform !== 'win32') {
scopedTemplate.value = scopedTemplate.value.replace(/\\/g, '/');
}
return scopedTemplate;
}

Expand Down Expand Up @@ -116,6 +124,9 @@ export class TemplateService {
scopedTemplate.value = replaceVariableValue("base", this.raw.getBasePath(scopeId), scopedTemplate.value);
scopedTemplate.value = replaceVariableValue("week", week + "", scopedTemplate.value);
scopedTemplate.value = resolveDate(scopedTemplate.value, new Date(), this.raw.getLocale());
if (process.platform !== 'win32') {
scopedTemplate.value = scopedTemplate.value.replace(/\\/g, '/');
}
scopedTemplate.value = Path.normalize(scopedTemplate.value);
return scopedTemplate;
}
Expand All @@ -127,6 +138,13 @@ export class TemplateService {
};
scopedTemplate.value = replaceVariableValue("base", this.raw.getBasePath(scopeId), scopedTemplate.template);
scopedTemplate.value = resolveDate(scopedTemplate.value, date, this.raw.getLocale());
// On non-Windows hosts, convert any residual backslashes to forward slashes
// before normalization so that Windows-style base paths configured for WSL
// remote sessions (e.g. C:\Users\...) do not produce mixed-separator paths
// like /C:\Users\...\journal/2026/05 (see issue #228).
if (process.platform !== 'win32') {
scopedTemplate.value = scopedTemplate.value.replace(/\\/g, '/');
}
scopedTemplate.value = Path.normalize(scopedTemplate.value);
return scopedTemplate;
}
Expand Down