diff --git a/.changes/core-path-basename-replace.md b/.changes/core-path-basename-replace.md new file mode 100644 index 00000000000..4f2b513289b --- /dev/null +++ b/.changes/core-path-basename-replace.md @@ -0,0 +1,6 @@ +--- +'tauri': 'patch:bug' +'@tauri-apps/api': patch:bug +--- + +Fix `basename(path, 'ext')` JS API when removing all occurances of `ext` where it should only remove the last one. diff --git a/core/tauri/src/path/plugin.rs b/core/tauri/src/path/plugin.rs index 2e413ba4732..cacd4638935 100644 --- a/core/tauri/src/path/plugin.rs +++ b/core/tauri/src/path/plugin.rs @@ -179,16 +179,17 @@ pub fn extname(path: String) -> Result { } #[command(root = "crate")] -pub fn basename(path: String, ext: Option) -> Result { - match Path::new(&path) - .file_name() - .and_then(std::ffi::OsStr::to_str) - { - Some(p) => Ok(if let Some(ext) = ext { - p.replace(ext.as_str(), "") - } else { - p.to_string() - }), +pub fn basename(path: &str, ext: Option<&str>) -> Result { + let file_name = Path::new(path).file_name().map(|f| f.to_string_lossy()); + match file_name { + Some(p) => { + let maybe_stripped = if let Some(ext) = ext { + p.strip_suffix(ext).unwrap_or(&p).to_string() + } else { + p.to_string() + }; + Ok(maybe_stripped) + } None => Err(Error::NoBasename), } } @@ -245,3 +246,40 @@ pub(crate) fn init() -> TauriPlugin { }) .build() } + +#[cfg(test)] +mod tests { + + #[test] + fn basename() { + let path = "/path/to/some-json-file.json"; + assert_eq!( + super::basename(path, Some(".json")).unwrap(), + "some-json-file" + ); + + let path = "/path/to/some-json-file.json"; + assert_eq!( + super::basename(path, Some("json")).unwrap(), + "some-json-file." + ); + + let path = "/path/to/some-json-file.html.json"; + assert_eq!( + super::basename(path, Some(".json")).unwrap(), + "some-json-file.html" + ); + + let path = "/path/to/some-json-file.json.json"; + assert_eq!( + super::basename(path, Some(".json")).unwrap(), + "some-json-file.json" + ); + + let path = "/path/to/some-json-file.json.html"; + assert_eq!( + super::basename(path, Some(".json")).unwrap(), + "some-json-file.json.html" + ); + } +} diff --git a/tooling/api/src/path.ts b/tooling/api/src/path.ts index 74566d77ae7..ca91c4e78d4 100644 --- a/tooling/api/src/path.ts +++ b/tooling/api/src/path.ts @@ -609,9 +609,9 @@ async function join(...paths: string[]): Promise { * Returns the directory name of a `path`. Trailing directory separators are ignored. * @example * ```typescript - * import { dirname, appDataDir } from '@tauri-apps/api/path'; - * const appDataDirPath = await appDataDir(); - * const dir = await dirname(appDataDirPath); + * import { dirname } from '@tauri-apps/api/path'; + * const dir = await dirname('/path/to/somedir/'); + * assert(dir === 'somedir'); * ``` * * @since 1.0.0 @@ -624,10 +624,9 @@ async function dirname(path: string): Promise { * Returns the extension of the `path`. * @example * ```typescript - * import { extname, resolveResource } from '@tauri-apps/api/path'; - * const resourcePath = await resolveResource('app.conf'); - * const ext = await extname(resourcePath); - * assert(ext === 'conf'); + * import { extname } from '@tauri-apps/api/path'; + * const ext = await extname('/path/to/file.html'); + * assert(ext === 'html'); * ``` * * @since 1.0.0 @@ -640,12 +639,10 @@ async function extname(path: string): Promise { * Returns the last portion of a `path`. Trailing directory separators are ignored. * @example * ```typescript - * import { basename, resolveResource } from '@tauri-apps/api/path'; - * const resourcePath = await resolveResource('app.conf'); - * const base = await basename(resourcePath); + * import { basename } from '@tauri-apps/api/path'; + * const base = await basename('path/to/app.conf'); * assert(base === 'app.conf'); * ``` - * * @param ext An optional file extension to be removed from the returned path. * * @since 1.0.0