mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
Merge 6bd6d91f3c into 5c9e590856
This commit is contained in:
commit
85e7022f34
@ -1107,8 +1107,11 @@
|
||||
"textRtf": "Text/RTF",
|
||||
"grayscale": "Greyscale",
|
||||
"errorConversion": "An error occurred while converting the file.",
|
||||
"cbzOptions": "CBZ to PDF Options",
|
||||
"cbrOptions": "CBR to PDF Options",
|
||||
"optimizeForEbook": "Optimize PDF for ebook readers (uses Ghostscript)",
|
||||
"cbrOutputOptions": "PDF to CBR Options",
|
||||
"cbrDpi": "DPI for image rendering",
|
||||
"cbzOptions": "CBZ to PDF Options",
|
||||
"cbzOutputOptions": "PDF to CBZ Options",
|
||||
"cbzDpi": "DPI for image rendering"
|
||||
},
|
||||
@ -2206,7 +2209,7 @@
|
||||
},
|
||||
"cta": "Compare",
|
||||
"loading": "Comparing...",
|
||||
|
||||
|
||||
"summary": {
|
||||
"baseHeading": "Original document",
|
||||
"comparisonHeading": "Edited document",
|
||||
@ -2262,7 +2265,7 @@
|
||||
"body": "This comparison is taking longer than usual. You can let it continue or cancel it.",
|
||||
"cancel": "Cancel comparison"
|
||||
},
|
||||
|
||||
|
||||
"newLine": "new-line",
|
||||
"complex": {
|
||||
"message": "One or both of the provided documents are large files, accuracy of comparison may be reduced"
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
import { Stack, Text, Checkbox } from '@mantine/core';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ConvertParameters } from "@app/hooks/tools/convert/useConvertParameters";
|
||||
|
||||
interface ConvertFromCbrSettingsProps {
|
||||
parameters: ConvertParameters;
|
||||
onParameterChange: <K extends keyof ConvertParameters>(key: K, value: ConvertParameters[K]) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const ConvertFromCbrSettings = ({
|
||||
parameters,
|
||||
onParameterChange,
|
||||
disabled = false
|
||||
}: ConvertFromCbrSettingsProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Stack gap="sm" data-testid="cbr-settings">
|
||||
<Text size="sm" fw={500}>{t("convert.cbrOptions", "CBR Options")}:</Text>
|
||||
|
||||
<Checkbox
|
||||
label={t('convert.optimizeForEbook', 'Optimize PDF for ebook readers (uses Ghostscript)')}
|
||||
checked={parameters.cbrOptions.optimizeForEbook}
|
||||
onChange={(event) => onParameterChange('cbrOptions', {
|
||||
...parameters.cbrOptions,
|
||||
optimizeForEbook: event.currentTarget.checked
|
||||
})}
|
||||
disabled={disabled}
|
||||
data-testid="optimize-ebook-checkbox"
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConvertFromCbrSettings;
|
||||
@ -16,6 +16,8 @@ import ConvertFromEmailSettings from "@app/components/tools/convert/ConvertFromE
|
||||
import ConvertFromCbzSettings from "@app/components/tools/convert/ConvertFromCbzSettings";
|
||||
import ConvertToCbzSettings from "@app/components/tools/convert/ConvertToCbzSettings";
|
||||
import ConvertToPdfaSettings from "@app/components/tools/convert/ConvertToPdfaSettings";
|
||||
import ConvertFromCbrSettings from "@app/components/tools/convert/ConvertFromCbrSettings";
|
||||
import ConvertToCbrSettings from "@app/components/tools/convert/ConvertToCbrSettings";
|
||||
import { ConvertParameters } from "@app/hooks/tools/convert/useConvertParameters";
|
||||
import {
|
||||
FROM_FORMAT_OPTIONS,
|
||||
@ -120,6 +122,12 @@ const ConvertSettings = ({
|
||||
onParameterChange('pdfaOptions', {
|
||||
outputFormat: 'pdfa-1',
|
||||
});
|
||||
onParameterChange('cbrOptions', {
|
||||
optimizeForEbook: false,
|
||||
});
|
||||
onParameterChange('pdfToCbrOptions', {
|
||||
dpi: 150,
|
||||
});
|
||||
onParameterChange('cbzOptions', {
|
||||
optimizeForEbook: false,
|
||||
});
|
||||
@ -188,6 +196,12 @@ const ConvertSettings = ({
|
||||
onParameterChange('pdfaOptions', {
|
||||
outputFormat: 'pdfa-1',
|
||||
});
|
||||
onParameterChange('cbrOptions', {
|
||||
optimizeForEbook: false,
|
||||
});
|
||||
onParameterChange('pdfToCbrOptions', {
|
||||
dpi: 150,
|
||||
});
|
||||
onParameterChange('cbzOptions', {
|
||||
optimizeForEbook: false,
|
||||
});
|
||||
@ -344,6 +358,30 @@ const ConvertSettings = ({
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* CBR to PDF options */}
|
||||
{parameters.fromExtension === 'cbr' && parameters.toExtension === 'pdf' && (
|
||||
<>
|
||||
<Divider />
|
||||
<ConvertFromCbrSettings
|
||||
parameters={parameters}
|
||||
onParameterChange={onParameterChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* PDF to CBR options */}
|
||||
{parameters.fromExtension === 'pdf' && parameters.toExtension === 'cbr' && (
|
||||
<>
|
||||
<Divider />
|
||||
<ConvertToCbrSettings
|
||||
parameters={parameters}
|
||||
onParameterChange={onParameterChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
import { Stack, Text, NumberInput } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ConvertParameters } from "@app/hooks/tools/convert/useConvertParameters";
|
||||
|
||||
interface ConvertToCbrSettingsProps {
|
||||
parameters: ConvertParameters;
|
||||
onParameterChange: <K extends keyof ConvertParameters>(key: K, value: ConvertParameters[K]) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const ConvertToCbrSettings = ({
|
||||
parameters,
|
||||
onParameterChange,
|
||||
disabled = false
|
||||
}: ConvertToCbrSettingsProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Stack gap="sm" data-testid="cbr-output-settings">
|
||||
<Text size="sm" fw={500}>{t("convert.cbrOutputOptions", "PDF to CBR Options")}:</Text>
|
||||
|
||||
<NumberInput
|
||||
data-testid="cbr-dpi-input"
|
||||
label={t("convert.cbrDpi", "DPI for image rendering")}
|
||||
value={parameters.pdfToCbrOptions.dpi}
|
||||
onChange={(val) =>
|
||||
typeof val === 'number' &&
|
||||
onParameterChange('pdfToCbrOptions', { ...parameters.pdfToCbrOptions, dpi: val })
|
||||
}
|
||||
min={72}
|
||||
max={600}
|
||||
step={50}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConvertToCbrSettings;
|
||||
@ -33,7 +33,9 @@ export const CONVERSION_ENDPOINTS = {
|
||||
'pdf-pdfa': '/api/v1/convert/pdf/pdfa',
|
||||
'html-pdf': '/api/v1/convert/html/pdf',
|
||||
'markdown-pdf': '/api/v1/convert/markdown/pdf',
|
||||
'eml-pdf': '/api/v1/convert/eml/pdf'
|
||||
'eml-pdf': '/api/v1/convert/eml/pdf',
|
||||
'cbr-pdf': '/api/v1/convert/cbr/pdf',
|
||||
'pdf-cbr': '/api/v1/convert/pdf/cbr'
|
||||
} as const;
|
||||
|
||||
export const ENDPOINT_NAMES = {
|
||||
@ -52,7 +54,9 @@ export const ENDPOINT_NAMES = {
|
||||
'pdf-pdfa': 'pdf-to-pdfa',
|
||||
'html-pdf': 'html-to-pdf',
|
||||
'markdown-pdf': 'markdown-to-pdf',
|
||||
'eml-pdf': 'eml-to-pdf'
|
||||
'eml-pdf': 'eml-to-pdf',
|
||||
'cbr-pdf': 'cbr-to-pdf',
|
||||
'pdf-cbr': 'pdf-to-cbr'
|
||||
} as const;
|
||||
|
||||
|
||||
@ -62,6 +66,7 @@ export const FROM_FORMAT_OPTIONS = [
|
||||
{ value: 'image', label: 'Images', group: 'Multiple Files' },
|
||||
{ value: 'pdf', label: 'PDF', group: 'Document' },
|
||||
{ value: 'cbz', label: 'CBZ', group: 'Archive' },
|
||||
{ value: 'cbr', label: 'CBR', group: 'Archive' },
|
||||
{ value: 'docx', label: 'DOCX', group: 'Document' },
|
||||
{ value: 'doc', label: 'DOC', group: 'Document' },
|
||||
{ value: 'odt', label: 'ODT', group: 'Document' },
|
||||
@ -93,6 +98,7 @@ export const TO_FORMAT_OPTIONS = [
|
||||
{ value: 'docx', label: 'DOCX', group: 'Document' },
|
||||
{ value: 'odt', label: 'ODT', group: 'Document' },
|
||||
{ value: 'cbz', label: 'CBZ', group: 'Archive' },
|
||||
{ value: 'cbr', label: 'CBR', group: 'Archive' },
|
||||
{ value: 'csv', label: 'CSV', group: 'Spreadsheet' },
|
||||
{ value: 'pptx', label: 'PPTX', group: 'Presentation' },
|
||||
{ value: 'odp', label: 'ODP', group: 'Presentation' },
|
||||
@ -113,7 +119,7 @@ export const TO_FORMAT_OPTIONS = [
|
||||
export const CONVERSION_MATRIX: Record<string, string[]> = {
|
||||
'any': ['pdf'], // Mixed files always convert to PDF
|
||||
'image': ['pdf'], // Multiple images always convert to PDF
|
||||
'pdf': ['png', 'jpg', 'gif', 'tiff', 'bmp', 'webp', 'docx', 'odt', 'pptx', 'odp', 'csv', 'txt', 'rtf', 'md', 'html', 'xml', 'pdfa', 'cbz'],
|
||||
'pdf': ['png', 'jpg', 'gif', 'tiff', 'bmp', 'webp', 'docx', 'odt', 'pptx', 'odp', 'csv', 'txt', 'rtf', 'md', 'html', 'xml', 'pdfa', 'cbz', 'cbr'],
|
||||
'cbz': ['pdf'],
|
||||
'docx': ['pdf'], 'doc': ['pdf'], 'odt': ['pdf'],
|
||||
'xlsx': ['pdf'], 'xls': ['pdf'], 'ods': ['pdf'],
|
||||
@ -123,7 +129,8 @@ export const CONVERSION_MATRIX: Record<string, string[]> = {
|
||||
'zip': ['pdf'],
|
||||
'md': ['pdf'],
|
||||
'txt': ['pdf'], 'rtf': ['pdf'],
|
||||
'eml': ['pdf']
|
||||
'eml': ['pdf'],
|
||||
'cbr': ['pdf']
|
||||
};
|
||||
|
||||
// Map extensions to endpoint keys
|
||||
@ -138,6 +145,7 @@ export const EXTENSION_TO_ENDPOINT: Record<string, Record<string, string>> = {
|
||||
'txt': 'pdf-to-text', 'rtf': 'pdf-to-text', 'md': 'pdf-to-markdown',
|
||||
'html': 'pdf-to-html', 'xml': 'pdf-to-xml',
|
||||
'pdfa': 'pdf-to-pdfa',
|
||||
'cbr': 'pdf-to-cbr',
|
||||
'cbz': 'pdf-to-cbz'
|
||||
},
|
||||
'cbz': { 'pdf': 'cbz-to-pdf' },
|
||||
@ -150,7 +158,8 @@ export const EXTENSION_TO_ENDPOINT: Record<string, Record<string, string>> = {
|
||||
'zip': { 'pdf': 'html-to-pdf' },
|
||||
'md': { 'pdf': 'markdown-to-pdf' },
|
||||
'txt': { 'pdf': 'file-to-pdf' }, 'rtf': { 'pdf': 'file-to-pdf' },
|
||||
'eml': { 'pdf': 'eml-to-pdf' }
|
||||
'eml': { 'pdf': 'eml-to-pdf' },
|
||||
'cbr': { 'pdf': 'cbr-to-pdf' }
|
||||
};
|
||||
|
||||
export type ColorType = typeof COLOR_TYPES[keyof typeof COLOR_TYPES];
|
||||
|
||||
@ -13,9 +13,7 @@ export const CONVERT_SUPPORTED_FORMATS = [
|
||||
// Email formats
|
||||
'eml',
|
||||
// Archive formats
|
||||
'zip', 'cbz',
|
||||
'zip', 'cbr', 'cbz',
|
||||
// Other
|
||||
'dbf', 'fods', 'vsd', 'vor', 'vor3', 'vor4', 'uop', 'pct', 'ps', 'pdf',
|
||||
];
|
||||
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@ export const shouldProcessFilesSeparately = (
|
||||
(parameters.fromExtension === 'pdf' && parameters.toExtension === 'pdfa') ||
|
||||
// PDF to text-like formats should be one output per input
|
||||
(parameters.fromExtension === 'pdf' && ['txt', 'rtf', 'csv'].includes(parameters.toExtension)) ||
|
||||
// PDF to CBR conversions (each PDF should generate its own archive)
|
||||
(parameters.fromExtension === 'pdf' && parameters.toExtension === 'cbr') ||
|
||||
// Web files to PDF conversions (each web file should generate its own PDF)
|
||||
((isWebFormat(parameters.fromExtension) || parameters.fromExtension === 'web') &&
|
||||
parameters.toExtension === 'pdf') ||
|
||||
@ -34,12 +36,12 @@ export const shouldProcessFilesSeparately = (
|
||||
// Static function that can be used by both the hook and automation executor
|
||||
export const buildConvertFormData = (parameters: ConvertParameters, selectedFiles: File[]): FormData => {
|
||||
const formData = new FormData();
|
||||
const { fromExtension, toExtension, imageOptions, htmlOptions, emailOptions, pdfaOptions, cbrOptions, pdfToCbrOptions, cbzOptions, cbzOutputOptions } = parameters;
|
||||
|
||||
selectedFiles.forEach(file => {
|
||||
formData.append("fileInput", file);
|
||||
});
|
||||
|
||||
const { fromExtension, toExtension, imageOptions, htmlOptions, emailOptions, pdfaOptions, cbzOptions, cbzOutputOptions } = parameters;
|
||||
|
||||
if (isImageFormat(toExtension)) {
|
||||
formData.append("imageFormat", toExtension);
|
||||
@ -67,6 +69,10 @@ export const buildConvertFormData = (parameters: ConvertParameters, selectedFile
|
||||
formData.append("outputFormat", pdfaOptions.outputFormat);
|
||||
} else if (fromExtension === 'pdf' && toExtension === 'csv') {
|
||||
formData.append("pageNumbers", "all");
|
||||
} else if (fromExtension === 'cbr' && toExtension === 'pdf') {
|
||||
formData.append("optimizeForEbook", cbrOptions.optimizeForEbook.toString());
|
||||
} else if (fromExtension === 'pdf' && toExtension === 'cbr') {
|
||||
formData.append("dpi", pdfToCbrOptions.dpi.toString());
|
||||
} else if (fromExtension === 'cbz' && toExtension === 'pdf') {
|
||||
formData.append("optimizeForEbook", (cbzOptions?.optimizeForEbook ?? false).toString());
|
||||
} else if (fromExtension === 'pdf' && toExtension === 'cbz') {
|
||||
|
||||
@ -36,6 +36,12 @@ export interface ConvertParameters extends BaseParameters {
|
||||
pdfaOptions: {
|
||||
outputFormat: string;
|
||||
};
|
||||
cbrOptions: {
|
||||
optimizeForEbook: boolean;
|
||||
};
|
||||
pdfToCbrOptions: {
|
||||
dpi: number;
|
||||
};
|
||||
cbzOptions: {
|
||||
optimizeForEbook: boolean;
|
||||
};
|
||||
@ -75,6 +81,12 @@ export const defaultParameters: ConvertParameters = {
|
||||
pdfaOptions: {
|
||||
outputFormat: 'pdfa-1',
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false,
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150,
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false,
|
||||
},
|
||||
|
||||
@ -152,6 +152,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -225,6 +231,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -276,6 +288,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -336,6 +354,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -400,6 +424,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -462,6 +492,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -520,6 +556,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -575,6 +617,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -632,6 +680,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -686,6 +740,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -746,6 +806,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
@ -805,6 +871,12 @@ describe('Convert Tool Integration Tests', () => {
|
||||
pdfaOptions: {
|
||||
outputFormat: ''
|
||||
},
|
||||
cbrOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
pdfToCbrOptions: {
|
||||
dpi: 150
|
||||
},
|
||||
cbzOptions: {
|
||||
optimizeForEbook: false
|
||||
},
|
||||
|
||||
@ -28,6 +28,8 @@ export const URL_TO_TOOL_MAP: Record<string, ToolId> = {
|
||||
'/pdf-to-pdfa': 'convert',
|
||||
'/pdf-to-word': 'convert',
|
||||
'/pdf-to-xml': 'convert',
|
||||
'/cbr-to-pdf': 'convert',
|
||||
'/pdf-to-cbr': 'convert',
|
||||
'/cbz-to-pdf': 'convert',
|
||||
'/pdf-to-cbz': 'convert',
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user