mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-10 10:22:29 +08:00
Merge branch 'develop' of ssh://github.com/TriliumNext/Notes into develop
This commit is contained in:
commit
2590a4cb05
16
package-lock.json
generated
16
package-lock.json
generated
@ -67,7 +67,7 @@
|
||||
"katex": "0.16.19",
|
||||
"knockout": "3.5.1",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "15.0.4",
|
||||
"marked": "15.0.5",
|
||||
"mermaid": "11.4.1",
|
||||
"mime-types": "2.1.35",
|
||||
"mind-elixir": "4.3.3",
|
||||
@ -133,7 +133,7 @@
|
||||
"@types/jsdom": "21.1.7",
|
||||
"@types/mime-types": "2.1.4",
|
||||
"@types/multer": "1.4.12",
|
||||
"@types/node": "22.10.3",
|
||||
"@types/node": "22.10.5",
|
||||
"@types/safe-compare": "1.1.2",
|
||||
"@types/sanitize-html": "2.13.0",
|
||||
"@types/sax": "1.2.7",
|
||||
@ -4389,9 +4389,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.3.tgz",
|
||||
"integrity": "sha512-DifAyw4BkrufCILvD3ucnuN8eydUfc/C1GlyrnI+LK6543w5/L3VeVgf05o3B4fqSXP1dKYLOZsKfutpxPzZrw==",
|
||||
"version": "22.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz",
|
||||
"integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -12909,9 +12909,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "15.0.4",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.4.tgz",
|
||||
"integrity": "sha512-TCHvDqmb3ZJ4PWG7VEGVgtefA5/euFmsIhxtD0XsBxI39gUSKL81mIRFdt0AiNQozUahd4ke98ZdirExd/vSEw==",
|
||||
"version": "15.0.5",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.5.tgz",
|
||||
"integrity": "sha512-xN+kSuqHjxWg+Q47yhhZMUP+kO1qHobvXkkm6FX+7N6lDvanLDd8H7AQ0jWDDyq+fDt/cSrJaBGyWYHXy0KQWA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
|
@ -110,7 +110,7 @@
|
||||
"katex": "0.16.19",
|
||||
"knockout": "3.5.1",
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "15.0.4",
|
||||
"marked": "15.0.5",
|
||||
"mermaid": "11.4.1",
|
||||
"mime-types": "2.1.35",
|
||||
"mind-elixir": "4.3.3",
|
||||
@ -173,7 +173,7 @@
|
||||
"@types/jsdom": "21.1.7",
|
||||
"@types/mime-types": "2.1.4",
|
||||
"@types/multer": "1.4.12",
|
||||
"@types/node": "22.10.3",
|
||||
"@types/node": "22.10.5",
|
||||
"@types/safe-compare": "1.1.2",
|
||||
"@types/sanitize-html": "2.13.0",
|
||||
"@types/sax": "1.2.7",
|
||||
|
129
spec-es6/utils/formatDownloadTitle.spec.ts
Normal file
129
spec-es6/utils/formatDownloadTitle.spec.ts
Normal file
@ -0,0 +1,129 @@
|
||||
import { formatDownloadTitle } from "../../src/services/utils.ts";
|
||||
import { describe, it, execute, expect } from "../mini_test.ts";
|
||||
|
||||
const testCases: [fnValue: Parameters<typeof formatDownloadTitle>, expectedValue: ReturnType<typeof formatDownloadTitle>][] = [
|
||||
// empty fileName tests
|
||||
[
|
||||
["", "text", ""],
|
||||
"untitled.html"
|
||||
],
|
||||
|
||||
[
|
||||
["", "canvas", ""],
|
||||
"untitled.json"
|
||||
],
|
||||
|
||||
[
|
||||
["", null, ""],
|
||||
"untitled"
|
||||
],
|
||||
|
||||
// json extension from type tests
|
||||
[
|
||||
["test_file", "canvas", ""],
|
||||
"test_file.json"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file", "relationMap", ""],
|
||||
"test_file.json"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file", "search", ""],
|
||||
"test_file.json"
|
||||
],
|
||||
|
||||
// extension based on mime type
|
||||
[
|
||||
["test_file", null, "text/csv"],
|
||||
"test_file.csv"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file_wo_ext", "image", "image/svg+xml"],
|
||||
"test_file_wo_ext.svg"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file_wo_ext", "file", "application/json"],
|
||||
"test_file_wo_ext.json"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file_w_fake_ext.ext", "image", "image/svg+xml"],
|
||||
"test_file_w_fake_ext.ext.svg"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file_w_correct_ext.svg", "image", "image/svg+xml"],
|
||||
"test_file_w_correct_ext.svg"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file_w_correct_ext.svgz", "image", "image/svg+xml"],
|
||||
"test_file_w_correct_ext.svgz"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file.zip", "file", "application/zip"],
|
||||
"test_file.zip"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file", "file", "application/zip"],
|
||||
"test_file.zip"
|
||||
],
|
||||
|
||||
// application/octet-stream tests
|
||||
[
|
||||
["test_file", "file", "application/octet-stream"],
|
||||
"test_file"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file.zip", "file", "application/octet-stream"],
|
||||
"test_file.zip"
|
||||
],
|
||||
|
||||
[
|
||||
["test_file.unknown", null, "application/octet-stream"],
|
||||
"test_file.unknown"
|
||||
],
|
||||
|
||||
// sanitized filename tests
|
||||
[
|
||||
["test/file", null, "application/octet-stream"],
|
||||
"testfile"
|
||||
],
|
||||
|
||||
[
|
||||
["test:file.zip", "file", "application/zip"],
|
||||
"testfile.zip"
|
||||
],
|
||||
|
||||
[
|
||||
[":::", "file", "application/zip"],
|
||||
".zip"
|
||||
],
|
||||
|
||||
[
|
||||
[":::a", "file", "application/zip"],
|
||||
"a.zip"
|
||||
],
|
||||
]
|
||||
|
||||
|
||||
describe("utils/formatDownloadTitle unit tests", () => {
|
||||
|
||||
testCases.forEach(testCase => {
|
||||
return it(`With args '${JSON.stringify(testCase[0])}' it should return '${testCase[1]}'`, () => {
|
||||
const [value, expected] = testCase;
|
||||
const actual = formatDownloadTitle(...value);
|
||||
expect(actual).toEqual(expected);
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
execute()
|
@ -178,45 +178,29 @@ export function replaceAll(string: string, replaceWhat: string, replaceWith: str
|
||||
}
|
||||
|
||||
export function formatDownloadTitle(fileName: string, type: string | null, mime: string) {
|
||||
if (!fileName) {
|
||||
fileName = "untitled";
|
||||
}
|
||||
const fileNameBase = (!fileName) ? "untitled" : sanitize(fileName);
|
||||
|
||||
fileName = sanitize(fileName);
|
||||
const getExtension = () => {
|
||||
if (type === "text") return ".html";
|
||||
if (type === "relationMap" || type === "canvas" || type === "search") return ".json";
|
||||
if (!mime) return "";
|
||||
|
||||
if (type === 'text') {
|
||||
return `${fileName}.html`;
|
||||
} else if (type && ['relationMap', 'canvas', 'search'].includes(type)) {
|
||||
return `${fileName}.json`;
|
||||
} else {
|
||||
if (!mime) {
|
||||
return fileName;
|
||||
}
|
||||
const mimeLc = mime.toLowerCase();
|
||||
|
||||
mime = mime.toLowerCase();
|
||||
const filenameLc = fileName.toLowerCase();
|
||||
const extensions = mimeTypes.extensions[mime];
|
||||
// better to just return the current name without a fake extension
|
||||
// it's possible that the title still preserves the correct extension anyways
|
||||
if (mimeLc === 'application/octet-stream') return "";
|
||||
|
||||
if (!extensions || extensions.length === 0) {
|
||||
return fileName;
|
||||
}
|
||||
// if fileName has an extension matching the mime already - reuse it
|
||||
const mimeTypeFromFileName = mimeTypes.lookup(fileName);
|
||||
if (mimeTypeFromFileName === mimeLc) return "";
|
||||
|
||||
for (const ext of extensions) {
|
||||
if (filenameLc.endsWith(`.${ext}`)) {
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
// as last resort try to get extension from mimeType
|
||||
const extensions = mimeTypes.extension(mime);
|
||||
return extensions ? `.${extensions}` : "";
|
||||
};
|
||||
|
||||
if (mime === 'application/octet-stream') {
|
||||
// we didn't find any good guess for this one, it will be better to just return
|
||||
// the current name without a fake extension. It's possible that the title still preserves the correct
|
||||
// extension too
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
return `${fileName}.${extensions[0]}`;
|
||||
}
|
||||
return `${fileNameBase}${getExtension()}`;
|
||||
}
|
||||
|
||||
export function removeTextFileExtension(filePath: string) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user