tinysaver
Version:
Modern replacement of file-saver.js.
85 lines (80 loc) • 2.52 kB
JavaScript
//#region node_modules/.pnpm/@ntnyq+utils@0.8.0/node_modules/@ntnyq/utils/dist/index.js
function isString(value) {
return typeof value === "string";
}
let prev = Date.now();
const ONE_MINUTE_MILLSECONDS = 60 * 1e3;
const ONE_HOUR_MILLSECONDS = 60 * 60 * 1e3;
const ONE_DAY_MILLSECONDS = 24 * 60 * 60 * 1e3;
const ONE_WEEK_MILLSECONDS = 7 * 24 * 60 * 60 * 1e3;
//#endregion
//#region src/core.ts
const RE_BOM_EXTENSION = /^\s*(?:text\/\S*|application\/json|[^\s/]*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i;
/**
* @param data - data to save
* @param filename - filename
* @param options - options
*/
function saveAs(data, filename, options = {}) {
const { autoBom = true, type = "", lastModified = Date.now() } = options;
if (isString(data)) {
if (autoBom && RE_BOM_EXTENSION.test(type)) data = `\uFEFF${data}`;
data = new Blob([data], { type });
}
let blob = data;
if (!(blob instanceof File)) blob = new File([blob], filename, {
type: type || blob.type || "",
lastModified
});
if ("msSaveOrOpenBlob" in navigator) return navigator.msSaveOrOpenBlob(blob, filename);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.style.display = "none";
a.href = url;
a.download = filename;
a.rel = "noopener";
const clickHandler = () => {
setTimeout(() => {
URL.revokeObjectURL(url);
a.removeEventListener("click", clickHandler);
a.remove();
}, 100);
};
a.addEventListener("click", clickHandler, false);
document.body.append(a);
a.click();
if (/Version\/\d.*Safari/.test(navigator.userAgent)) {
const timeout = setTimeout(() => {
a.remove();
clearTimeout(timeout);
}, 1e3);
}
}
//#endregion
//#region src/extensions/csv.ts
function saveAsCsv(rows, filename, options = {}) {
const data = rows.map((row) => row.map((cell) => `"${String(cell).replace(/"/g, "\"\"")}"`).join(",")).join("\n");
return saveAs(data, filename, {
type: "text/csv;charset=utf-8",
autoBom: options.autoBom
});
}
//#endregion
//#region src/extensions/json.ts
function saveAsJson(data, filename, options = {}) {
const { replacer = null, space = 2 } = options;
return saveAs(JSON.stringify(data, replacer, space), filename, {
type: "application/json;charset=utf-8",
autoBom: options?.autoBom
});
}
//#endregion
//#region src/extensions/text.ts
function saveAsText(data, filename, options = {}) {
return saveAs(data, filename, {
type: "text/plain;charset=utf-8",
autoBom: options.autoBom
});
}
//#endregion
export { saveAs, saveAsCsv, saveAsJson, saveAsText };