Explorar o código

fix(core/path): remove suffix in `basename` only once (#9165)

* fix(core/path): remove suffix in `basename` only once

closes #9064

* Update tooling/api/src/path.ts

* remove extra assert

---------

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
Amr Bashir hai 1 ano
pai
achega
379cc2b354
Modificáronse 3 ficheiros con 62 adicións e 21 borrados
  1. 6 0
      .changes/core-path-basename-replace.md
  2. 48 10
      core/tauri/src/path/plugin.rs
  3. 8 11
      tooling/api/src/path.ts

+ 6 - 0
.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.

+ 48 - 10
core/tauri/src/path/plugin.rs

@@ -179,16 +179,17 @@ pub fn extname(path: String) -> Result<String> {
 }
 
 #[command(root = "crate")]
-pub fn basename(path: String, ext: Option<String>) -> Result<String> {
-  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<String> {
+  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<R: Runtime>() -> TauriPlugin<R> {
     })
     .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"
+    );
+  }
+}

+ 8 - 11
tooling/api/src/path.ts

@@ -609,9 +609,9 @@ async function join(...paths: string[]): Promise<string> {
  * 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<string> {
  * 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<string> {
  * 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