UNPKG

@zag-js/file-utils

Version:
230 lines (218 loc) 12.6 kB
// src/data-transfer.ts var getItemEntry = (item) => typeof item.getAsEntry === "function" ? item.getAsEntry() : typeof item.webkitGetAsEntry === "function" ? item.webkitGetAsEntry() : null; var isDirectoryEntry = (entry) => entry.isDirectory; var isFileEntry = (entry) => entry.isFile; var addRelativePath = (file, path) => { Object.defineProperty(file, "relativePath", { value: path ? `${path}/${file.name}` : file.name }); return file; }; var getFileEntries = (items, traverseDirectories) => Promise.all( Array.from(items).filter((item) => item.kind === "file").map((item) => { const entry = getItemEntry(item); if (!entry) return null; if (isDirectoryEntry(entry) && traverseDirectories) { return getDirectoryFiles(entry.createReader(), `${entry.name}`); } if (isFileEntry(entry) && typeof item.getAsFile === "function") { const file = item.getAsFile(); return Promise.resolve(file ? addRelativePath(file, "") : null); } if (isFileEntry(entry)) { return new Promise((resolve) => { entry.file((file) => { resolve(addRelativePath(file, "")); }); }); } }).filter((b) => b) ); var getDirectoryFiles = (reader, path = "") => new Promise((resolve) => { const entryPromises = []; const readDirectoryEntries = () => { reader.readEntries((entries) => { if (entries.length === 0) { resolve(Promise.all(entryPromises).then((entries2) => entries2.flat())); return; } const promises = entries.map((entry) => { if (!entry) return null; if (isDirectoryEntry(entry)) { return getDirectoryFiles(entry.createReader(), `${path}${entry.name}`); } if (isFileEntry(entry)) { return new Promise((resolve2) => { entry.file((file) => { resolve2(addRelativePath(file, path)); }); }); } }).filter((b) => b); entryPromises.push(Promise.all(promises)); readDirectoryEntries(); }); }; readDirectoryEntries(); }); // src/data-url-to-blob.ts function dataURItoBlob(uri) { const binary = atob(uri.split(",")[1]); const mimeString = uri.split(",")[0].split(":")[1].split(";")[0]; const buffer = new ArrayBuffer(binary.length); const intArray = new Uint8Array(buffer); for (let i = 0; i < binary.length; i++) { intArray[i] = binary.charCodeAt(i); } return new Blob([buffer], { type: mimeString }); } // src/download-file.ts var BOM_REGEX = /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i; var MAC_REGEX = /Macintosh/; var APPLE_WEBKIT_REGEX = /AppleWebKit/; var SAFARI_REGEX = /Safari/; function getBlob(blobOrString, type, appendBOM) { let blob = typeof blobOrString === "string" ? new Blob([blobOrString], { type }) : blobOrString; if (appendBOM && BOM_REGEX.test(blob.type)) { return new Blob([String.fromCharCode(65279), blob], { type: blob.type }); } return blob; } function isMSEdge(win) { return Boolean(win.navigator && win.navigator.msSaveOrOpenBlob); } function isWebView(win) { return win.navigator && MAC_REGEX.test(win.navigator.userAgent) && APPLE_WEBKIT_REGEX.test(win.navigator.userAgent) && !SAFARI_REGEX.test(win.navigator.userAgent); } function downloadFile(options) { const { file, win = window, type, name, appendBOM, revokeTimeout = 0 } = options; const doc = win.document; const blob = getBlob(file, type, appendBOM); const fileName = (file instanceof File ? name || file.name : name) || "file-download"; if (isMSEdge(win)) { win.navigator.msSaveOrOpenBlob(blob, fileName); return; } const isMacOSWebView = isWebView(win); const anchor = doc.createElement("a"); const canUseDownload = "download" in anchor && !isMacOSWebView; if (canUseDownload) { const url2 = win.URL.createObjectURL(blob); anchor.href = url2; anchor.rel = "noopener"; anchor.download = fileName; anchor.style.display = "none"; doc.body.appendChild(anchor); anchor.dispatchEvent(new win.MouseEvent("click")); setTimeout(() => { win.URL.revokeObjectURL(url2); anchor.remove(); }, revokeTimeout); return; } const url = win.URL.createObjectURL(blob); const popup = win.open(url, "_blank"); if (!popup) { win.location.href = url; } setTimeout(() => { win.URL.revokeObjectURL(url); }, revokeTimeout); } // src/get-accept-attr.ts function isMIMEType(v) { return v === "audio/*" || v === "video/*" || v === "image/*" || v === "text/*" || /\w+\/[-+.\w]+/g.test(v); } function isExt(v) { return /^.*\.[\w]+$/.test(v); } var isValidMIME = (v) => isMIMEType(v) || isExt(v); function getAcceptAttrString(accept) { if (accept == null) return; if (typeof accept === "string") { return accept; } if (Array.isArray(accept)) { return accept.filter(isValidMIME).join(","); } return Object.entries(accept).reduce((a, [mimeType, ext]) => [...a, mimeType, ...ext], []).filter(isValidMIME).join(","); } // src/get-file-data-url.ts var getFileDataUrl = async (file) => { const reader = new FileReader(); return new Promise((resolve, reject) => { reader.onerror = () => { reader.abort(); reject(new Error("There was an error reading a file")); }; reader.onloadend = () => { const { result } = reader; if (result instanceof ArrayBuffer) { reject(new Error("Expected DataURL as string from Blob/File, got ArrayBuffer")); } else { resolve(result || void 0); } }; reader.readAsDataURL(file); }); }; // src/get-total-file-size.ts var getTotalFileSize = (files) => { return files.reduce((acc, file) => acc + file.size, 0); }; // src/is-file-equal.ts var isFileEqual = (file1, file2) => { return file1.name === file2.name && file1.size === file2.size && file1.type === file2.type; }; // src/is-valid-file-size.ts var isDefined = (v) => v !== void 0 && v !== null; function isValidFileSize(file, minSize, maxSize) { if (isDefined(file.size)) { if (isDefined(minSize) && isDefined(maxSize)) { if (file.size > maxSize) return [false, "FILE_TOO_LARGE"]; if (file.size < minSize) return [false, "FILE_TOO_SMALL"]; } else if (isDefined(minSize) && file.size < minSize) { return [false, "FILE_TOO_SMALL"]; } else if (isDefined(maxSize) && file.size > maxSize) { return [false, "FILE_TOO_LARGE"]; } } return [true, null]; } // src/mime-types.ts var mimeTypes = "3g2_video/3gpp2[3gp,3gpp_video/3gpp[3mf_model/3mf[7z_application/x-7z-compressed[aac_audio/aac[ac_application/pkix-attr-cert[adp_audio/adpcm[adts_audio/aac[ai_application/postscript[aml_application/automationml-aml+xml[amlx_application/automationml-amlx+zip[amr_audio/amr[apk_application/vnd.android.package-archive[apng_image/apng[appcache,manifest_text/cache-manifest[appinstaller_application/appinstaller[appx_application/appx[appxbundle_application/appxbundle[asc_application/pgp-keys[atom_application/atom+xml[atomcat_application/atomcat+xml[atomdeleted_application/atomdeleted+xml[atomsvc_application/atomsvc+xml[au,snd_audio/basic[avi_video/x-msvideo[avci_image/avci[avcs_image/avcs[avif_image/avif[aw_application/applixware[bdoc_application/bdoc[bin,bpk,buffer,deb,deploy,dist,distz,dll,dmg,dms,dump,elc,exe,img,iso,lrf,mar,msi,msm,msp,pkg,so_application/octet-stream[bmp,dib_image/bmp[btf,btif_image/prs.btif[bz2_application/x-bzip2[c_text/x-c[ccxml_application/ccxml+xml[cdfx_application/cdfx+xml[cdmia_application/cdmi-capability[cdmic_application/cdmi-container[cdmid_application/cdmi-domain[cdmio_application/cdmi-object[cdmiq_application/cdmi-queue[cer_application/pkix-cert[cgm_image/cgm[cjs_application/node[class_application/java-vm[coffee,litcoffee_text/coffeescript[conf,def,in,ini,list,log,text,txt_text/plain[cpp,cxx,cc_text/x-c++src[cpl_application/cpl+xml[cpt_application/mac-compactpro[crl_application/pkix-crl[css_text/css[csv_text/csv[cu_application/cu-seeme[cwl_application/cwl[cww_application/prs.cww[davmount_application/davmount+xml[dbk_application/docbook+xml[doc_application/msword[docx_application/vnd.openxmlformats-officedocument.wordprocessingml.document[dsc_text/prs.lines.tag[dssc_application/dssc+der[dtd_application/xml-dtd[dwd_application/atsc-dwd+xml[ear,jar,war_application/java-archive[ecma_application/ecmascript[emf_image/emf[eml,mime_message/rfc822[emma_application/emma+xml[emotionml_application/emotionml+xml[eot_application/vnd.ms-fontobject[eps,ps_application/postscript[epub_application/epub+zip[exi_application/exi[exp_application/express[exr_image/aces[ez_application/andrew-inset[fdf_application/fdf[fdt_application/fdt+xml[fits_image/fits[flac_audio/flac[flv_video/x-flv[g3_image/g3fax[geojson_application/geo+json[gif_image/gif[glb_model/gltf-binary[gltf_model/gltf+json[gml_application/gml+xml[go_text/x-go[gpx_application/gpx+xml[gz_application/gzip[h_text/x-h[h261_video/h261[h263_video/h263[h264_video/h264[heic_image/heic[heics_image/heic-sequence[heif_image/heif[heifs_image/heif-sequence[htm,html,shtml_text/html[ico_image/x-icon[icns_image/x-icns[ics,ifb_text/calendar[iges,igs_model/iges[ink,inkml_application/inkml+xml[ipa_application/octet-stream[java_text/x-java-source[jp2,jpg2_image/jp2[jpeg,jpe,jpg_image/jpeg[jpf,jpx_image/jpx[jpm,jpgm_image/jpm[jpgv_video/jpeg[jph_image/jph[js,mjs_text/javascript[json_application/json[json5_application/json5[jsonld_application/ld+json[jsx_text/jsx[jxl_image/jxl[jxr_image/jxr[ktx_image/ktx[ktx2_image/ktx2[less_text/less[m1v,m2v,mpe,mpeg,mpg_video/mpeg[m4a_audio/mp4[m4v_video/x-m4v[md,markdown_text/markdown[mid,midi,kar,rmi_audio/midi[mkv_video/x-matroska[mp2,mp2a,mp3,mpga,m3a,m2a_audio/mpeg[mp4,mp4v,mpg4_video/mp4[mp4a_audio/mp4[mp4s,m4p_application/mp4[odp_application/vnd.oasis.opendocument.presentation[oda_application/oda[ods_application/vnd.oasis.opendocument.spreadsheet[odt_application/vnd.oasis.opendocument.text[oga,ogg,opus,spx_audio/ogg[ogv_video/ogg[ogx_application/ogg[otf_font/otf[p12,pfx_application/x-pkcs12[pdf_application/pdf[pem_application/x-pem-file[php_text/x-php[png_image/png[ppt_application/vnd.ms-powerpoint[pptx_application/vnd.openxmlformats-officedocument.presentationml.presentation[pskcxml_application/pskc+xml[psd_image/vnd.adobe.photoshop[py_text/x-python[qt,mov_video/quicktime[rar_application/vnd.rar[rdf_application/rdf+xml[rtf_text/rtf[sass_text/x-sass[scss_text/x-scss[sgm,sgml_text/sgml[sh_application/x-sh[svg,svgz_image/svg+xml[swf_application/x-shockwave-flash[tar_application/x-tar[tif,tiff_image/tiff[toml_application/toml[ts_video/mp2t[tsx_text/tsx[tsv_text/tab-separated-values[ttc_font/collection[ttf_font/ttf[vtt_text/vtt[wasm_application/wasm[wav_audio/wav[weba_audio/webm[webm_video/webm[webmanifest_application/manifest+json[webp_image/webp[wma_audio/x-ms-wma[wmv_video/x-ms-wmv[woff_font/woff[woff2_font/woff2[xls_application/vnd.ms-excel[xlsx_application/vnd.openxmlformats-officedocument.spreadsheetml.sheet[xml_application/xml[xz_application/x-xz[yaml,yml_text/yaml[zip_application/zip"; var mimeTypesMap = new Map( mimeTypes.split("[").flatMap((mime) => { const [extensions, mimeType] = mime.split("_"); return extensions.split(",").map((ext) => [ext, mimeType]); }) ); // src/get-file-mime-type.ts function getFileMimeType(name) { const extension = name.split(".").pop(); return extension ? mimeTypesMap.get(extension) || null : null; } // src/is-valid-file-type.ts function isFileAccepted(file, accept) { if (file && accept) { const types = Array.isArray(accept) ? accept : typeof accept === "string" ? accept.split(",") : []; if (types.length === 0) return true; const fileName = file.name || ""; const mimeType = (file.type || getFileMimeType(fileName) || "").toLowerCase(); const baseMimeType = mimeType.replace(/\/.*$/, ""); return types.some((type) => { const validType = type.trim().toLowerCase(); if (validType.charAt(0) === ".") { return fileName.toLowerCase().endsWith(validType); } if (validType.endsWith("/*")) { return baseMimeType === validType.replace(/\/.*$/, ""); } return mimeType === validType; }); } return true; } function isValidFileType(file, accept) { const isAcceptable = file.type === "application/x-moz-file" || isFileAccepted(file, accept); return [isAcceptable, isAcceptable ? null : "FILE_INVALID_TYPE"]; } export { dataURItoBlob, downloadFile, getAcceptAttrString, getFileDataUrl, getFileEntries, getFileMimeType, getTotalFileSize, isFileEqual, isValidFileSize, isValidFileType };