mirror of https://github.com/VERT-sh/VERT.git
feat: conversion resolver improvements
This commit is contained in:
parent
61c548eed9
commit
b89e55c997
|
@ -69,7 +69,7 @@
|
|||
{#if files.requiredConverters.length === 1}
|
||||
<!-- cannot convert to svg or heif -->
|
||||
{@const supported = files.files[0]?.converters
|
||||
.flatMap((c) => c.supportedFormats)
|
||||
.flatMap((c) => c.formatStrings((f) => f.toSupported))
|
||||
?.filter(
|
||||
(format) => format !== ".svg" && format !== ".heif",
|
||||
)}
|
||||
|
|
|
@ -62,8 +62,8 @@
|
|||
: 'justify-center'} overflow-hidden relative cursor-pointer {settingsStyle
|
||||
? 'px-4'
|
||||
: 'px-3'} py-3.5 bg-button {disabled
|
||||
? 'opacity-50'
|
||||
: ''} flex items-center {settingsStyle
|
||||
? 'opacity-50 cursor-auto'
|
||||
: 'cursor-pointer'} flex items-center {settingsStyle
|
||||
? 'rounded-xl'
|
||||
: 'rounded-full'} focus:!outline-none"
|
||||
onclick={toggle}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
)
|
||||
).filter((c) => typeof c !== "undefined");
|
||||
acceptedTypes = filteredConverters
|
||||
.map((c) => c.supportedFormats.join(","))
|
||||
.map((c) => c.formatStrings((f) => f.fromSupported).join(","))
|
||||
.join(",");
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,24 @@
|
|||
import type { VertFile } from "$lib/types";
|
||||
|
||||
export class FormatInfo {
|
||||
public name: string;
|
||||
|
||||
constructor(
|
||||
name: string,
|
||||
public fromSupported: boolean,
|
||||
public toSupported: boolean,
|
||||
) {
|
||||
this.name = name;
|
||||
if (!this.name.startsWith(".")) {
|
||||
this.name = `.${this.name}`;
|
||||
}
|
||||
|
||||
if (!this.fromSupported && !this.toSupported) {
|
||||
throw new Error("Format must support at least one direction");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for all converters.
|
||||
*/
|
||||
|
@ -11,7 +30,7 @@ export class Converter {
|
|||
/**
|
||||
* List of supported formats.
|
||||
*/
|
||||
public supportedFormats: string[] = [];
|
||||
public supportedFormats: FormatInfo[] = [];
|
||||
/**
|
||||
* Convert a file to a different format.
|
||||
* @param input The input file.
|
||||
|
@ -34,4 +53,11 @@ export class Converter {
|
|||
public async valid(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
public formatStrings(predicate?: (f: FormatInfo) => boolean) {
|
||||
if (predicate) {
|
||||
return this.supportedFormats.filter(predicate).map((f) => f.name);
|
||||
}
|
||||
return this.supportedFormats.map((f) => f.name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { VertFile } from "$lib/types";
|
||||
import { Converter } from "./converter.svelte";
|
||||
import { Converter, FormatInfo } from "./converter.svelte";
|
||||
import { FFmpeg } from "@ffmpeg/ffmpeg";
|
||||
import { browser } from "$app/environment";
|
||||
import { error, log } from "$lib/logger";
|
||||
|
@ -11,17 +11,17 @@ export class FFmpegConverter extends Converter {
|
|||
public ready = $state(false);
|
||||
|
||||
public supportedFormats = [
|
||||
".mp3",
|
||||
".wav",
|
||||
".flac",
|
||||
".ogg",
|
||||
".aac",
|
||||
".m4a",
|
||||
".wma",
|
||||
".amr",
|
||||
".ac3",
|
||||
".alac",
|
||||
".aiff",
|
||||
new FormatInfo("mp3", true, true),
|
||||
new FormatInfo("wav", true, true),
|
||||
new FormatInfo("flac", true, true),
|
||||
new FormatInfo("ogg", true, true),
|
||||
new FormatInfo("aac", true, true),
|
||||
new FormatInfo("m4a", true, true),
|
||||
new FormatInfo("wma", true, true),
|
||||
new FormatInfo("amr", true, true),
|
||||
new FormatInfo("ac3", true, true),
|
||||
new FormatInfo("alac", true, true),
|
||||
new FormatInfo("aiff", true, true),
|
||||
];
|
||||
|
||||
public readonly reportsProgress = true;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { VertFile } from "$lib/types";
|
||||
import { Converter } from "./converter.svelte";
|
||||
import { Converter, FormatInfo } from "./converter.svelte";
|
||||
import { browser } from "$app/environment";
|
||||
import PandocWorker from "$lib/workers/pandoc?worker";
|
||||
|
||||
|
@ -61,23 +61,19 @@ export class PandocConverter extends Converter {
|
|||
);
|
||||
}
|
||||
|
||||
// public name = "pandoc";
|
||||
// public ready = $state(false);
|
||||
// public wasm: ArrayBuffer = null!;
|
||||
|
||||
public supportedFormats = [
|
||||
".docx",
|
||||
".doc",
|
||||
".md",
|
||||
".html",
|
||||
".rtf",
|
||||
".csv",
|
||||
".tsv",
|
||||
".json",
|
||||
".rst",
|
||||
".epub",
|
||||
".odt",
|
||||
".docbook",
|
||||
new FormatInfo("docx", true, true),
|
||||
new FormatInfo("doc", true, true),
|
||||
new FormatInfo("md", true, true),
|
||||
new FormatInfo("html", true, true),
|
||||
new FormatInfo("rtf", true, true),
|
||||
new FormatInfo("csv", true, true),
|
||||
new FormatInfo("tsv", true, true),
|
||||
new FormatInfo("json", true, true),
|
||||
new FormatInfo("rst", true, true),
|
||||
new FormatInfo("epub", true, true),
|
||||
new FormatInfo("odt", true, true),
|
||||
new FormatInfo("docbook", true, true),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { log } from "$lib/logger";
|
||||
import { Settings } from "$lib/sections/settings/index.svelte";
|
||||
import { VertFile } from "$lib/types";
|
||||
import { Converter } from "./converter.svelte";
|
||||
import { Converter, FormatInfo } from "./converter.svelte";
|
||||
|
||||
interface VertdError {
|
||||
type: "error";
|
||||
|
@ -200,16 +200,18 @@ export class VertdConverter extends Converter {
|
|||
public name = "vertd";
|
||||
public ready = $state(false);
|
||||
public reportsProgress = true;
|
||||
|
||||
public supportedFormats = [
|
||||
".mkv",
|
||||
".mp4",
|
||||
".webm",
|
||||
".avi",
|
||||
".wmv",
|
||||
".mov",
|
||||
".gif",
|
||||
".mts",
|
||||
new FormatInfo("mkv", true, true),
|
||||
new FormatInfo("mp4", true, true),
|
||||
new FormatInfo("webm", true, true),
|
||||
new FormatInfo("avi", true, true),
|
||||
new FormatInfo("wmv", true, true),
|
||||
new FormatInfo("mov", true, true),
|
||||
new FormatInfo("gif", true, true),
|
||||
new FormatInfo("mts", true, true),
|
||||
];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private log: (...msg: any[]) => void = () => {};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { addToast } from "$lib/store/ToastProvider";
|
|||
import type { OmitBetterStrict, WorkerMessage } from "$lib/types";
|
||||
import { VertFile } from "$lib/types";
|
||||
import VipsWorker from "$lib/workers/vips?worker&url";
|
||||
import { Converter } from "./converter.svelte";
|
||||
import { Converter, FormatInfo } from "./converter.svelte";
|
||||
|
||||
export class VipsConverter extends Converter {
|
||||
private worker: Worker = browser
|
||||
|
@ -15,34 +15,32 @@ export class VipsConverter extends Converter {
|
|||
private id = 0;
|
||||
public name = "libvips";
|
||||
public ready = $state(false);
|
||||
public static supportedFormatsStatic = [
|
||||
...new Set([
|
||||
".png",
|
||||
".jpeg",
|
||||
".jpg",
|
||||
".webp",
|
||||
".gif",
|
||||
".ico",
|
||||
".cur",
|
||||
".ani",
|
||||
".heic",
|
||||
".hdr",
|
||||
".jpe",
|
||||
".dng",
|
||||
".mat",
|
||||
".pbm",
|
||||
".pfm",
|
||||
".pgm",
|
||||
".pnm",
|
||||
".ppm",
|
||||
".raw",
|
||||
".tif",
|
||||
".tiff",
|
||||
".jfif",
|
||||
]),
|
||||
];
|
||||
|
||||
public supportedFormats = VipsConverter.supportedFormatsStatic;
|
||||
public supportedFormats = [
|
||||
new FormatInfo("png", true, true),
|
||||
new FormatInfo("jpeg", true, true),
|
||||
new FormatInfo("jpg", true, true),
|
||||
new FormatInfo("webp", true, true),
|
||||
new FormatInfo("gif", true, true),
|
||||
new FormatInfo("ico", true, false),
|
||||
new FormatInfo("cur", true, false),
|
||||
new FormatInfo("ani", true, false),
|
||||
new FormatInfo("heic", true, false),
|
||||
new FormatInfo("hdr", true, true),
|
||||
new FormatInfo("jpe", true, true),
|
||||
new FormatInfo("dng", true, false),
|
||||
new FormatInfo("mat", true, true),
|
||||
new FormatInfo("pbm", true, true),
|
||||
new FormatInfo("pfm", true, true),
|
||||
new FormatInfo("pgm", true, true),
|
||||
new FormatInfo("pnm", true, true),
|
||||
new FormatInfo("ppm", true, true),
|
||||
new FormatInfo("raw", false, true),
|
||||
new FormatInfo("tif", true, true),
|
||||
new FormatInfo("tiff", true, true),
|
||||
new FormatInfo("jfif", true, true),
|
||||
new FormatInfo("avif", true, true),
|
||||
];
|
||||
|
||||
public readonly reportsProgress = false;
|
||||
|
||||
|
|
|
@ -32,10 +32,12 @@ class Files {
|
|||
this.thumbnailQueue.add(async () => {
|
||||
const isAudio = converters
|
||||
.find((c) => c.name === "ffmpeg")
|
||||
?.supportedFormats?.includes(file.from.toLowerCase());
|
||||
?.formatStrings()
|
||||
?.includes(file.from.toLowerCase());
|
||||
const isVideo = converters
|
||||
.find((c) => c.name === "vertd")
|
||||
?.supportedFormats?.includes(file.from.toLowerCase());
|
||||
?.formatStrings()
|
||||
?.includes(file.from.toLowerCase());
|
||||
|
||||
try {
|
||||
if (isAudio) {
|
||||
|
@ -119,16 +121,16 @@ class Files {
|
|||
return;
|
||||
}
|
||||
const converter = converters.find((c) =>
|
||||
c.supportedFormats.includes(
|
||||
format || ".somenonexistentextension",
|
||||
),
|
||||
c
|
||||
.formatStrings()
|
||||
.includes(format || ".somenonexistentextension"),
|
||||
);
|
||||
if (!converter) {
|
||||
log(["files"], `no converter found for ${file.name}`);
|
||||
this.files.push(new VertFile(file, format));
|
||||
return;
|
||||
}
|
||||
const to = converter.supportedFormats.find((f) => f !== format);
|
||||
const to = converter.formatStrings().find((f) => f !== format);
|
||||
if (!to) {
|
||||
log(["files"], `no output format found for ${file.name}`);
|
||||
return;
|
||||
|
|
|
@ -28,7 +28,7 @@ export class VertFile {
|
|||
|
||||
public findConverters(supportedFormats: string[] = [this.from]) {
|
||||
const converter = this.converters.filter((converter) =>
|
||||
converter.supportedFormats.map((f) => supportedFormats.includes(f)),
|
||||
converter.formatStrings().map((f) => supportedFormats.includes(f)),
|
||||
);
|
||||
return converter;
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ export class VertFile {
|
|||
public findConverter() {
|
||||
const converter = this.converters.find(
|
||||
(converter) =>
|
||||
converter.supportedFormats.includes(this.from) &&
|
||||
converter.supportedFormats.includes(this.to),
|
||||
converter.formatStrings().includes(this.from) &&
|
||||
converter.formatStrings().includes(this.to),
|
||||
);
|
||||
return converter;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ export class VertFile {
|
|||
this.file = newFile;
|
||||
this.to = to;
|
||||
this.converters = converters.filter((c) =>
|
||||
c.supportedFormats.includes(this.from),
|
||||
c.formatStrings().includes(this.from),
|
||||
);
|
||||
this.convert = this.convert.bind(this);
|
||||
this.download = this.download.bind(this);
|
||||
|
|
|
@ -8,8 +8,13 @@
|
|||
const { data } = $props();
|
||||
|
||||
const getSupportedFormats = (name: string) =>
|
||||
converters.find((c) => c.name === name)?.supportedFormats.join(", ") ||
|
||||
"none";
|
||||
converters
|
||||
.find((c) => c.name === name)
|
||||
?.supportedFormats.map(
|
||||
(f) =>
|
||||
`${f.name}${f.fromSupported && f.toSupported ? "" : "*"}`,
|
||||
)
|
||||
.join(", ") || "none";
|
||||
|
||||
const status: {
|
||||
[key: string]: {
|
||||
|
|
|
@ -89,21 +89,25 @@
|
|||
{@const availableConverters = file.findConverters()}
|
||||
{@const currentConverter = converters.find(
|
||||
(c) =>
|
||||
c.supportedFormats.includes(file.from) &&
|
||||
c.supportedFormats.includes(file.to),
|
||||
c.formatStrings((f) => f.fromSupported).includes(file.from) &&
|
||||
c.formatStrings((f) => f.toSupported).includes(file.to),
|
||||
)}
|
||||
{@const isAudio = converters
|
||||
.find((c) => c.name === "ffmpeg")
|
||||
?.supportedFormats.includes(file.from)}
|
||||
?.formatStrings((f) => f.fromSupported)
|
||||
.includes(file.from)}
|
||||
{@const isVideo = converters
|
||||
.find((c) => c.name === "vertd")
|
||||
?.supportedFormats.includes(file.from)}
|
||||
?.formatStrings((f) => f.fromSupported)
|
||||
.includes(file.from)}
|
||||
{@const isImage = converters
|
||||
.find((c) => c.name === "libvips")
|
||||
?.supportedFormats.includes(file.from)}
|
||||
?.formatStrings((f) => f.fromSupported)
|
||||
.includes(file.from)}
|
||||
{@const isDocument = converters
|
||||
.find((c) => c.name === "pandoc")
|
||||
?.supportedFormats.includes(file.from)}
|
||||
?.formatStrings((f) => f.fromSupported)
|
||||
.includes(file.from)}
|
||||
<Panel class="p-5 flex flex-col min-w-0 gap-4 relative">
|
||||
<div class="flex-shrink-0 h-8 w-full flex items-center gap-2">
|
||||
{#if !converters.length}
|
||||
|
@ -222,7 +226,9 @@
|
|||
<!-- cannot convert to svg or heif -->
|
||||
<Dropdown
|
||||
options={availableConverters
|
||||
.flatMap((c) => c.supportedFormats)
|
||||
.flatMap((c) =>
|
||||
c.formatStrings((f) => f.toSupported),
|
||||
)
|
||||
.filter(
|
||||
(format) =>
|
||||
format !== ".svg" && format !== ".heif",
|
||||
|
|
Loading…
Reference in New Issue