import { Meta } from '../types' import { PdfPage } from '../types/drawing.ts' import { MOST_COMMON_MEDIA_TYPES } from './const.ts' import { extractMarksFromSignedMeta } from './mark.ts' import { addMarks, groupMarksByFileNamePage, isPdf, pdfToImages } from './pdf.ts' import JSZip from 'jszip' export const getZipWithFiles = async ( meta: Meta, files: { [filename: string]: SigitFile } ): Promise => { const zip = new JSZip() const marks = extractMarksFromSignedMeta(meta) const marksByFileNamePage = groupMarksByFileNamePage(marks) for (const [fileName, file] of Object.entries(files)) { // Handle PDF Files, add marks if (file.isPdf && fileName in marksByFileNamePage) { const blob = await addMarks(file, marksByFileNamePage[fileName]) zip.file(`marked/${fileName}`, blob) } // Save original files zip.file(`files/${fileName}`, file) } return zip } /** * Converts a PDF ArrayBuffer to a generic PDF File * @param arrayBuffer of a PDF * @param fileName identifier of the pdf file * @param type optional file type (defaults to pdf) */ export const toFile = ( arrayBuffer: ArrayBuffer, fileName: string, type: string = 'application/pdf' ): File => { const blob = new Blob([arrayBuffer], { type }) return new File([blob], fileName, { type }) } export class SigitFile extends File { extension: string isPdf: boolean isImage: boolean pages?: PdfPage[] objectUrl?: string constructor(file: File) { super([file], file.name, { type: file.type }) this.isPdf = isPdf(this) this.isImage = isImage(this) this.extension = extractFileExtension(this.name) } async process() { if (this.isPdf) this.pages = await pdfToImages(await this.arrayBuffer()) if (this.isImage) this.objectUrl = URL.createObjectURL(this) } } export const getSigitFile = async (file: File) => { const sigitFile = new SigitFile(file) // Process sigit file // - generate pages for PDF files // - generate ObjectRL for image files await sigitFile.process() return sigitFile } /** * Takes an ArrayBuffer and converts to Sigit's Internal File type * @param arrayBuffer * @param fileName */ export const convertToSigitFile = async ( arrayBuffer: ArrayBuffer, fileName: string ): Promise => { const type = getMediaType(extractFileExtension(fileName)) const file = toFile(arrayBuffer, fileName, type) const sigitFile = await getSigitFile(file) return sigitFile } /** * @param fileNames - List of filenames to check * @returns List of extensions and if all are same */ export const extractFileExtensions = (fileNames: string[]) => { const extensions = fileNames.reduce((result: string[], file: string) => { const extension = file.split('.').pop() if (extension) { result.push(extension) } return result }, []) const isSame = extensions.every((ext) => ext === extensions[0]) return { extensions, isSame } } /** * @param fileName - Filename to check * @returns Extension string */ export const extractFileExtension = (fileName: string) => { const parts = fileName.split('.') return parts[parts.length - 1] } export const getMediaType = (extension: string) => { return MOST_COMMON_MEDIA_TYPES.get(extension) } export const isImage = (file: File) => { const validImageMediaTypes = [ 'image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/svg+xml', 'image/bmp', 'image/x-icon' ] return validImageMediaTypes.includes(file.type.toLowerCase()) }