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}
|
{#if files.requiredConverters.length === 1}
|
||||||
<!-- cannot convert to svg or heif -->
|
<!-- cannot convert to svg or heif -->
|
||||||
{@const supported = files.files[0]?.converters
|
{@const supported = files.files[0]?.converters
|
||||||
.flatMap((c) => c.supportedFormats)
|
.flatMap((c) => c.formatStrings((f) => f.toSupported))
|
||||||
?.filter(
|
?.filter(
|
||||||
(format) => format !== ".svg" && format !== ".heif",
|
(format) => format !== ".svg" && format !== ".heif",
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -62,8 +62,8 @@
|
||||||
: 'justify-center'} overflow-hidden relative cursor-pointer {settingsStyle
|
: 'justify-center'} overflow-hidden relative cursor-pointer {settingsStyle
|
||||||
? 'px-4'
|
? 'px-4'
|
||||||
: 'px-3'} py-3.5 bg-button {disabled
|
: 'px-3'} py-3.5 bg-button {disabled
|
||||||
? 'opacity-50'
|
? 'opacity-50 cursor-auto'
|
||||||
: ''} flex items-center {settingsStyle
|
: 'cursor-pointer'} flex items-center {settingsStyle
|
||||||
? 'rounded-xl'
|
? 'rounded-xl'
|
||||||
: 'rounded-full'} focus:!outline-none"
|
: 'rounded-full'} focus:!outline-none"
|
||||||
onclick={toggle}
|
onclick={toggle}
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
)
|
)
|
||||||
).filter((c) => typeof c !== "undefined");
|
).filter((c) => typeof c !== "undefined");
|
||||||
acceptedTypes = filteredConverters
|
acceptedTypes = filteredConverters
|
||||||
.map((c) => c.supportedFormats.join(","))
|
.map((c) => c.formatStrings((f) => f.fromSupported).join(","))
|
||||||
.join(",");
|
.join(",");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,24 @@
|
||||||
import type { VertFile } from "$lib/types";
|
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.
|
* Base class for all converters.
|
||||||
*/
|
*/
|
||||||
|
@ -11,7 +30,7 @@ export class Converter {
|
||||||
/**
|
/**
|
||||||
* List of supported formats.
|
* List of supported formats.
|
||||||
*/
|
*/
|
||||||
public supportedFormats: string[] = [];
|
public supportedFormats: FormatInfo[] = [];
|
||||||
/**
|
/**
|
||||||
* Convert a file to a different format.
|
* Convert a file to a different format.
|
||||||
* @param input The input file.
|
* @param input The input file.
|
||||||
|
@ -34,4 +53,11 @@ export class Converter {
|
||||||
public async valid(): Promise<boolean> {
|
public async valid(): Promise<boolean> {
|
||||||
return true;
|
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 { VertFile } from "$lib/types";
|
||||||
import { Converter } from "./converter.svelte";
|
import { Converter, FormatInfo } from "./converter.svelte";
|
||||||
import { FFmpeg } from "@ffmpeg/ffmpeg";
|
import { FFmpeg } from "@ffmpeg/ffmpeg";
|
||||||
import { browser } from "$app/environment";
|
import { browser } from "$app/environment";
|
||||||
import { error, log } from "$lib/logger";
|
import { error, log } from "$lib/logger";
|
||||||
|
@ -11,17 +11,17 @@ export class FFmpegConverter extends Converter {
|
||||||
public ready = $state(false);
|
public ready = $state(false);
|
||||||
|
|
||||||
public supportedFormats = [
|
public supportedFormats = [
|
||||||
".mp3",
|
new FormatInfo("mp3", true, true),
|
||||||
".wav",
|
new FormatInfo("wav", true, true),
|
||||||
".flac",
|
new FormatInfo("flac", true, true),
|
||||||
".ogg",
|
new FormatInfo("ogg", true, true),
|
||||||
".aac",
|
new FormatInfo("aac", true, true),
|
||||||
".m4a",
|
new FormatInfo("m4a", true, true),
|
||||||
".wma",
|
new FormatInfo("wma", true, true),
|
||||||
".amr",
|
new FormatInfo("amr", true, true),
|
||||||
".ac3",
|
new FormatInfo("ac3", true, true),
|
||||||
".alac",
|
new FormatInfo("alac", true, true),
|
||||||
".aiff",
|
new FormatInfo("aiff", true, true),
|
||||||
];
|
];
|
||||||
|
|
||||||
public readonly reportsProgress = true;
|
public readonly reportsProgress = true;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { VertFile } from "$lib/types";
|
import { VertFile } from "$lib/types";
|
||||||
import { Converter } from "./converter.svelte";
|
import { Converter, FormatInfo } from "./converter.svelte";
|
||||||
import { browser } from "$app/environment";
|
import { browser } from "$app/environment";
|
||||||
import PandocWorker from "$lib/workers/pandoc?worker";
|
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 = [
|
public supportedFormats = [
|
||||||
".docx",
|
new FormatInfo("docx", true, true),
|
||||||
".doc",
|
new FormatInfo("doc", true, true),
|
||||||
".md",
|
new FormatInfo("md", true, true),
|
||||||
".html",
|
new FormatInfo("html", true, true),
|
||||||
".rtf",
|
new FormatInfo("rtf", true, true),
|
||||||
".csv",
|
new FormatInfo("csv", true, true),
|
||||||
".tsv",
|
new FormatInfo("tsv", true, true),
|
||||||
".json",
|
new FormatInfo("json", true, true),
|
||||||
".rst",
|
new FormatInfo("rst", true, true),
|
||||||
".epub",
|
new FormatInfo("epub", true, true),
|
||||||
".odt",
|
new FormatInfo("odt", true, true),
|
||||||
".docbook",
|
new FormatInfo("docbook", true, true),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { log } from "$lib/logger";
|
import { log } from "$lib/logger";
|
||||||
import { Settings } from "$lib/sections/settings/index.svelte";
|
import { Settings } from "$lib/sections/settings/index.svelte";
|
||||||
import { VertFile } from "$lib/types";
|
import { VertFile } from "$lib/types";
|
||||||
import { Converter } from "./converter.svelte";
|
import { Converter, FormatInfo } from "./converter.svelte";
|
||||||
|
|
||||||
interface VertdError {
|
interface VertdError {
|
||||||
type: "error";
|
type: "error";
|
||||||
|
@ -200,16 +200,18 @@ export class VertdConverter extends Converter {
|
||||||
public name = "vertd";
|
public name = "vertd";
|
||||||
public ready = $state(false);
|
public ready = $state(false);
|
||||||
public reportsProgress = true;
|
public reportsProgress = true;
|
||||||
|
|
||||||
public supportedFormats = [
|
public supportedFormats = [
|
||||||
".mkv",
|
new FormatInfo("mkv", true, true),
|
||||||
".mp4",
|
new FormatInfo("mp4", true, true),
|
||||||
".webm",
|
new FormatInfo("webm", true, true),
|
||||||
".avi",
|
new FormatInfo("avi", true, true),
|
||||||
".wmv",
|
new FormatInfo("wmv", true, true),
|
||||||
".mov",
|
new FormatInfo("mov", true, true),
|
||||||
".gif",
|
new FormatInfo("gif", true, true),
|
||||||
".mts",
|
new FormatInfo("mts", true, true),
|
||||||
];
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
private log: (...msg: any[]) => void = () => {};
|
private log: (...msg: any[]) => void = () => {};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { addToast } from "$lib/store/ToastProvider";
|
||||||
import type { OmitBetterStrict, WorkerMessage } from "$lib/types";
|
import type { OmitBetterStrict, WorkerMessage } from "$lib/types";
|
||||||
import { VertFile } from "$lib/types";
|
import { VertFile } from "$lib/types";
|
||||||
import VipsWorker from "$lib/workers/vips?worker&url";
|
import VipsWorker from "$lib/workers/vips?worker&url";
|
||||||
import { Converter } from "./converter.svelte";
|
import { Converter, FormatInfo } from "./converter.svelte";
|
||||||
|
|
||||||
export class VipsConverter extends Converter {
|
export class VipsConverter extends Converter {
|
||||||
private worker: Worker = browser
|
private worker: Worker = browser
|
||||||
|
@ -15,34 +15,32 @@ export class VipsConverter extends Converter {
|
||||||
private id = 0;
|
private id = 0;
|
||||||
public name = "libvips";
|
public name = "libvips";
|
||||||
public ready = $state(false);
|
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;
|
public readonly reportsProgress = false;
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,12 @@ class Files {
|
||||||
this.thumbnailQueue.add(async () => {
|
this.thumbnailQueue.add(async () => {
|
||||||
const isAudio = converters
|
const isAudio = converters
|
||||||
.find((c) => c.name === "ffmpeg")
|
.find((c) => c.name === "ffmpeg")
|
||||||
?.supportedFormats?.includes(file.from.toLowerCase());
|
?.formatStrings()
|
||||||
|
?.includes(file.from.toLowerCase());
|
||||||
const isVideo = converters
|
const isVideo = converters
|
||||||
.find((c) => c.name === "vertd")
|
.find((c) => c.name === "vertd")
|
||||||
?.supportedFormats?.includes(file.from.toLowerCase());
|
?.formatStrings()
|
||||||
|
?.includes(file.from.toLowerCase());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isAudio) {
|
if (isAudio) {
|
||||||
|
@ -119,16 +121,16 @@ class Files {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const converter = converters.find((c) =>
|
const converter = converters.find((c) =>
|
||||||
c.supportedFormats.includes(
|
c
|
||||||
format || ".somenonexistentextension",
|
.formatStrings()
|
||||||
),
|
.includes(format || ".somenonexistentextension"),
|
||||||
);
|
);
|
||||||
if (!converter) {
|
if (!converter) {
|
||||||
log(["files"], `no converter found for ${file.name}`);
|
log(["files"], `no converter found for ${file.name}`);
|
||||||
this.files.push(new VertFile(file, format));
|
this.files.push(new VertFile(file, format));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const to = converter.supportedFormats.find((f) => f !== format);
|
const to = converter.formatStrings().find((f) => f !== format);
|
||||||
if (!to) {
|
if (!to) {
|
||||||
log(["files"], `no output format found for ${file.name}`);
|
log(["files"], `no output format found for ${file.name}`);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class VertFile {
|
||||||
|
|
||||||
public findConverters(supportedFormats: string[] = [this.from]) {
|
public findConverters(supportedFormats: string[] = [this.from]) {
|
||||||
const converter = this.converters.filter((converter) =>
|
const converter = this.converters.filter((converter) =>
|
||||||
converter.supportedFormats.map((f) => supportedFormats.includes(f)),
|
converter.formatStrings().map((f) => supportedFormats.includes(f)),
|
||||||
);
|
);
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ export class VertFile {
|
||||||
public findConverter() {
|
public findConverter() {
|
||||||
const converter = this.converters.find(
|
const converter = this.converters.find(
|
||||||
(converter) =>
|
(converter) =>
|
||||||
converter.supportedFormats.includes(this.from) &&
|
converter.formatStrings().includes(this.from) &&
|
||||||
converter.supportedFormats.includes(this.to),
|
converter.formatStrings().includes(this.to),
|
||||||
);
|
);
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ export class VertFile {
|
||||||
this.file = newFile;
|
this.file = newFile;
|
||||||
this.to = to;
|
this.to = to;
|
||||||
this.converters = converters.filter((c) =>
|
this.converters = converters.filter((c) =>
|
||||||
c.supportedFormats.includes(this.from),
|
c.formatStrings().includes(this.from),
|
||||||
);
|
);
|
||||||
this.convert = this.convert.bind(this);
|
this.convert = this.convert.bind(this);
|
||||||
this.download = this.download.bind(this);
|
this.download = this.download.bind(this);
|
||||||
|
|
|
@ -8,8 +8,13 @@
|
||||||
const { data } = $props();
|
const { data } = $props();
|
||||||
|
|
||||||
const getSupportedFormats = (name: string) =>
|
const getSupportedFormats = (name: string) =>
|
||||||
converters.find((c) => c.name === name)?.supportedFormats.join(", ") ||
|
converters
|
||||||
"none";
|
.find((c) => c.name === name)
|
||||||
|
?.supportedFormats.map(
|
||||||
|
(f) =>
|
||||||
|
`${f.name}${f.fromSupported && f.toSupported ? "" : "*"}`,
|
||||||
|
)
|
||||||
|
.join(", ") || "none";
|
||||||
|
|
||||||
const status: {
|
const status: {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
|
|
|
@ -89,21 +89,25 @@
|
||||||
{@const availableConverters = file.findConverters()}
|
{@const availableConverters = file.findConverters()}
|
||||||
{@const currentConverter = converters.find(
|
{@const currentConverter = converters.find(
|
||||||
(c) =>
|
(c) =>
|
||||||
c.supportedFormats.includes(file.from) &&
|
c.formatStrings((f) => f.fromSupported).includes(file.from) &&
|
||||||
c.supportedFormats.includes(file.to),
|
c.formatStrings((f) => f.toSupported).includes(file.to),
|
||||||
)}
|
)}
|
||||||
{@const isAudio = converters
|
{@const isAudio = converters
|
||||||
.find((c) => c.name === "ffmpeg")
|
.find((c) => c.name === "ffmpeg")
|
||||||
?.supportedFormats.includes(file.from)}
|
?.formatStrings((f) => f.fromSupported)
|
||||||
|
.includes(file.from)}
|
||||||
{@const isVideo = converters
|
{@const isVideo = converters
|
||||||
.find((c) => c.name === "vertd")
|
.find((c) => c.name === "vertd")
|
||||||
?.supportedFormats.includes(file.from)}
|
?.formatStrings((f) => f.fromSupported)
|
||||||
|
.includes(file.from)}
|
||||||
{@const isImage = converters
|
{@const isImage = converters
|
||||||
.find((c) => c.name === "libvips")
|
.find((c) => c.name === "libvips")
|
||||||
?.supportedFormats.includes(file.from)}
|
?.formatStrings((f) => f.fromSupported)
|
||||||
|
.includes(file.from)}
|
||||||
{@const isDocument = converters
|
{@const isDocument = converters
|
||||||
.find((c) => c.name === "pandoc")
|
.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">
|
<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">
|
<div class="flex-shrink-0 h-8 w-full flex items-center gap-2">
|
||||||
{#if !converters.length}
|
{#if !converters.length}
|
||||||
|
@ -222,7 +226,9 @@
|
||||||
<!-- cannot convert to svg or heif -->
|
<!-- cannot convert to svg or heif -->
|
||||||
<Dropdown
|
<Dropdown
|
||||||
options={availableConverters
|
options={availableConverters
|
||||||
.flatMap((c) => c.supportedFormats)
|
.flatMap((c) =>
|
||||||
|
c.formatStrings((f) => f.toSupported),
|
||||||
|
)
|
||||||
.filter(
|
.filter(
|
||||||
(format) =>
|
(format) =>
|
||||||
format !== ".svg" && format !== ".heif",
|
format !== ".svg" && format !== ".heif",
|
||||||
|
|
Loading…
Reference in New Issue