import { ParsingOptions, read, Sheet2JSONOpts, utils, type WorkSheet, } from "../deps/sheetjs.ts"; import { merge } from "../core/utils/object.ts"; import loadText from "../core/loaders/text.ts"; import loadBinary from "../core/loaders/binary.ts"; import type Site from "../core/site.ts"; import type { RawData } from "../core/file.ts"; export interface Options { /** File extensions to load */ extensions?: string[]; /** Return the first sheet only or all sheets if the document have more */ sheets?: "first" | "auto"; /** * Parsing options passed to Sheetjs * @see https://docs.sheetjs.com/docs/api/parse-options#parsing-options */ options?: ParsingOptions; /** * Options passed to `utils.sheet_to_json` * @see https://docs.sheetjs.com/docs/api/utilities/array#array-output */ outputOptions?: Sheet2JSONOpts; } export const defaults: Options = { extensions: [".xlsx", ".numbers", ".csv"], sheets: "auto", options: {}, outputOptions: { UTC: true, }, }; /** * A plugin to load Excel, Numbers, and CSV files * @see https://lume.land/plugins/sheets/ */ export function sheets(userOptions?: Options) { const options = merge(defaults, userOptions); function sheetToJson(sheet: WorkSheet) { return utils.sheet_to_json(sheet, options.outputOptions); } async function loader(path: string): Promise { const type = path.endsWith(".csv") ? "string" : "array"; const { content } = type === "string" ? await loadText(path) : await loadBinary(path); const wb = read(content, { ...options.options, type, }); // Return only the first sheet if (options.sheets === "first" || wb.SheetNames.length === 1) { const sheet = wb.Sheets[wb.SheetNames[0]]; return sheetToJson(sheet) as unknown as RawData; } // Return all sheets by name const sheets: Record = {}; wb.SheetNames.forEach((name) => { sheets[name] = sheetToJson(wb.Sheets[name]); }); return { content: sheets }; } return (site: Site) => { site.loadData(options.extensions, loader); // Ignore temp files generated by Numbers (https://github.com/lumeland/lume/issues/245) if (options.extensions.includes(".numbers")) { site.options.watcher.ignore.push((path) => !!path.match(/\.numbers\.[\w-]+$/) ); } }; } export default sheets;