refactor(core): use own path replacement

This commit is contained in:
Elian Doran
2026-03-26 21:41:11 +02:00
parent 8b98fdcba1
commit c0593707f2
3 changed files with 64 additions and 6 deletions

View File

@@ -4,7 +4,7 @@ import { encodeBase64 } from "./binary";
import { extensions as mimeToExt, types as extToMime } from "mime-types";
import escape from "escape-html";
import unescape from "unescape";
import path from "path";
import { basename, extname } from "./path";
import { NoteMeta } from "../../meta";
// TODO: Implement platform detection.
@@ -161,8 +161,7 @@ export function formatDownloadTitle(fileName: string, type: string | null, mime:
if (mimeLc === "application/octet-stream") return "";
// if fileName has an extension matching the mime already - reuse it
const dotIdx = fileName.lastIndexOf(".");
const ext = dotIdx !== -1 ? fileName.substring(dotIdx + 1).toLowerCase() : "";
const ext = extname(fileName).toLowerCase().replace(".", "");
if (ext && extToMime[ext] === mimeLc) return "";
// as last resort try to get extension from mimeType
@@ -207,7 +206,7 @@ export function escapeRegExp(str: string) {
}
export function removeFileExtension(filePath: string, mime?: string) {
const extension = path.extname(filePath).toLowerCase();
const extension = extname(filePath).toLowerCase();
if (mime?.startsWith("video/") || mime?.startsWith("audio/")) {
return filePath.substring(0, filePath.length - extension.length);
@@ -233,8 +232,8 @@ export function getNoteTitle(filePath: string, replaceUnderscoresWithSpaces: boo
const trimmedNoteMeta = noteMeta?.title?.trim();
if (trimmedNoteMeta) return trimmedNoteMeta;
const basename = path.basename(removeFileExtension(filePath, noteMeta?.mime));
return replaceUnderscoresWithSpaces ? basename.replace(/_/g, " ").trim() : basename;
const fileBasename = basename(removeFileExtension(filePath, noteMeta?.mime));
return replaceUnderscoresWithSpaces ? fileBasename.replace(/_/g, " ").trim() : fileBasename;
}
// try to turn 'true' and 'false' strings from process.env variables into boolean values or undefined

View File

@@ -0,0 +1,41 @@
import { describe, it, expect } from "vitest";
import { extname, basename } from "./path";
describe("#extname", () => {
const testCases: [input: string, expected: string][] = [
["file.txt", ".txt"],
["file.tar.gz", ".gz"],
["file", ""],
[".hidden", ""],
[".hidden.txt", ".txt"],
["no-ext.", "."],
["path/to/file.ts", ".ts"],
["path\\to\\file.ts", ".ts"],
["path/to/.gitignore", ""],
["", ""],
];
testCases.forEach(([input, expected]) => {
it(`'${input}' should return '${expected}'`, () => {
expect(extname(input)).toBe(expected);
});
});
});
describe("#basename", () => {
const testCases: [input: string, expected: string][] = [
["path/to/file.txt", "file.txt"],
["path\\to\\file.txt", "file.txt"],
["file.txt", "file.txt"],
["/root/file", "file"],
["C:\\Users\\test\\file.md", "file.md"],
["path/to/dir/", ""],
["", ""],
];
testCases.forEach(([input, expected]) => {
it(`'${input}' should return '${expected}'`, () => {
expect(basename(input)).toBe(expected);
});
});
});

View File

@@ -0,0 +1,18 @@
/**
* Browser-safe path utilities that don't depend on Node's `path` module.
* Handles both forward slashes and backslashes.
*/
/** Returns the extension of a file path (e.g. ".txt"), or "" if none. */
export function extname(filePath: string): string {
const base = basename(filePath);
const dotIdx = base.lastIndexOf(".");
if (dotIdx <= 0) return "";
return base.substring(dotIdx);
}
/** Returns the last component of a file path. */
export function basename(filePath: string): string {
const lastSlash = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
return filePath.substring(lastSlash + 1);
}