@ai-matrx/office 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -4
- package/dist/chunk-5T2M6LSI.js +529 -0
- package/dist/chunk-5T2M6LSI.js.map +1 -0
- package/dist/chunk-QZE7HBZB.cjs +529 -0
- package/dist/chunk-QZE7HBZB.cjs.map +1 -0
- package/dist/chunk-WKBWRG7N.js +209 -0
- package/dist/chunk-WKBWRG7N.js.map +1 -0
- package/dist/chunk-ZDZCCOUB.cjs +209 -0
- package/dist/chunk-ZDZCCOUB.cjs.map +1 -0
- package/dist/core.d.cts +5 -1
- package/dist/core.d.ts +5 -1
- package/dist/matrxImagePorts-JDFYE4QI.cjs +59 -0
- package/dist/matrxImagePorts-JDFYE4QI.cjs.map +1 -0
- package/dist/matrxImagePorts-VPBBUADM.js +59 -0
- package/dist/matrxImagePorts-VPBBUADM.js.map +1 -0
- package/dist/sheets-xlsx.cjs +525 -0
- package/dist/sheets-xlsx.cjs.map +1 -0
- package/dist/sheets-xlsx.d.cts +153 -0
- package/dist/sheets-xlsx.d.ts +153 -0
- package/dist/sheets-xlsx.js +525 -0
- package/dist/sheets-xlsx.js.map +1 -0
- package/dist/sheets.cjs +921 -0
- package/dist/sheets.cjs.map +1 -0
- package/dist/sheets.d.cts +605 -0
- package/dist/sheets.d.ts +605 -0
- package/dist/sheets.js +921 -0
- package/dist/sheets.js.map +1 -0
- package/dist/univer-collab.cjs +1 -77
- package/dist/univer-collab.cjs.map +1 -1
- package/dist/univer-collab.d.cts +1 -15
- package/dist/univer-collab.d.ts +1 -15
- package/dist/univer-collab.js +1 -77
- package/dist/univer-collab.js.map +1 -1
- package/dist/univer-realtime.cjs +102 -0
- package/dist/univer-realtime.cjs.map +1 -0
- package/dist/univer-realtime.d.cts +15 -0
- package/dist/univer-realtime.d.ts +15 -0
- package/dist/univer-realtime.js +80 -0
- package/dist/univer-realtime.js.map +1 -0
- package/dist/xlsx-to-univer-AQAXU3TC.cjs +7 -0
- package/dist/xlsx-to-univer-AQAXU3TC.cjs.map +1 -0
- package/dist/xlsx-to-univer-OPMMBWEW.js +7 -0
- package/dist/xlsx-to-univer-OPMMBWEW.js.map +1 -0
- package/package.json +41 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/aidream/aidream/apps/shared/office/dist/matrxImagePorts-JDFYE4QI.cjs","../src/univer/ports.ts","../src/univer/univerImageStore.ts","../src/univer/matrxImagePorts.ts"],"names":[],"mappings":"AAAA;ACwCA,IAAM,KAAA,kBAAO,MAAA,CAAO,GAAA,CAAI,6BAA6B,CAAA;AAErD,IAAM,KAAA,EAAO,CAAA,EAAA,GAAY;AACvB,EAAA,MAAM,EAAA,EAAI,UAAA;AACV,EAAA,OAAQ,CAAA,CAAE,IAAI,EAAA,IAAM,CAAC,CAAA;AACvB,CAAA;AAMO,SAAS,aAAA,CAAA,EAAiC;AAC/C,EAAA,MAAM,MAAA,EAAQ,IAAA,CAAK,CAAA,CAAE,KAAA;AACrB,EAAA,GAAA,CAAI,CAAC,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,8FAA8F,CAAA;AAC1H,EAAA,OAAO,KAAA;AACT;AD5CA;AACA;AEAA;AACE;AACA;AACA;AACA;AACA;AAAA,sCACK;AAEA,IAAM,mBAAA,EAAqB,aAAA;AAE3B,IAAM,mBAAA,EAAqB,CAAC,MAAA,EAAA,GACjC,MAAA,CAAO,UAAA,CAAW,kBAAkB,CAAA;AAE/B,IAAM,iBAAA,EAAmB,CAAC,MAAA,EAAA,GAC/B,MAAA,CAAO,KAAA,CAAM,kBAAA,CAAmB,MAAM,CAAA;AFHxC;AACA;AGpBO,IAAM,gBAAA,EAAmC;AAAA,EAC9C,MAAM,MAAA,CAAO,IAAA,EAAM;AACjB,IAAA,OAAO,aAAA,CAAc,CAAA,CAAE,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AAAA,EAC1C,CAAA;AAAA,EACA,OAAA,CAAQ,MAAA,EAAQ;AACd,IAAA,OAAO,aAAA,CAAc,CAAA,CAAE,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC7C,CAAA;AAAA,EACA,aAAA,CAAc,KAAA,EAAO;AACnB,IAAA,aAAA,CAAc,CAAA,CAAE,iBAAA,CAAkB,KAAK,CAAA;AAAA,EACzC;AACF,CAAA;AAGA,MAAA,SAAsB,kBAAA,CACpB,MAAA,EAC0E;AAC1E,EAAA,IAAI,IAAA;AACJ,EAAA,GAAA,CAAI,kBAAA,CAAmB,MAAM,CAAA,EAAG;AAC9B,IAAA,KAAA,EAAO,MAAM,aAAA,CAAc,CAAA,CAAE,KAAA,CAAM,OAAA,CAAQ,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,EACrE,EAAA,KAAO;AACL,IAAA,MAAM,IAAA,EAAM,MAAM,KAAA,CAAM,MAAM,CAAA;AAC9B,IAAA,GAAA,CAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,IAAA;AACpB,IAAA,KAAA,EAAO,MAAM,GAAA,CAAI,IAAA,CAAK,CAAA;AAAA,EACxB;AACA,EAAA,MAAM,UAAA,EAAY,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,KAAK,EAAA,EAAI,MAAA,EAAQ,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,KAAK,EAAA,EAAI,MAAA,EAAQ,MAAA;AAC1F,EAAA,OAAO,EAAE,KAAA,EAAO,IAAI,UAAA,CAAW,MAAM,IAAA,CAAK,WAAA,CAAY,CAAC,CAAA,EAAG,UAAU,CAAA;AACtE;AAGA,MAAA,SAAsB,mBAAA,CAAoB,KAAA,EAAmB,SAAA,EAAoC;AAC/F,EAAA,MAAM,KAAA,EAAO,UAAA,IAAc,MAAA,EAAQ,aAAA,EAAe,CAAA,MAAA,EAAS,SAAS,CAAA,CAAA;AACa,EAAA;AAC1E,EAAA;AACT;AHgBuE;AACA;AACA;AACA;AACA","file":"/home/runner/work/aidream/aidream/apps/shared/office/dist/matrxImagePorts-JDFYE4QI.cjs","sourcesContent":[null,"/**\n * The host ports of the Univer glue.\n *\n * The glue belongs to the package, but four things belong to the app that mounts an editor: the\n * toast path, the signed-in person, the file store, the snapshot catch-up read and the painted theme. The host states them\n * once at start-up with `configureUniverHost`; the glue reads them here. State sits on a\n * `globalThis` slot so a dual-bundled copy of the package still sees one host (dual-bundle rule).\n * An unconfigured port THROWS naming the port (nothing fails silently).\n */\n\nexport type UniverToastId = string | number;\ntype ToastShow = (title: string, options?: { description?: string; duration?: number }) => UniverToastId;\n\nexport interface UniverHostPorts {\n /** The app's toast path (one toaster per page). */\n toast: {\n success: ToastShow;\n info: ToastShow;\n warning: ToastShow;\n error: ToastShow;\n message: ToastShow;\n dismiss(id: UniverToastId): void;\n };\n /** Who is typing, or null when signed out. `metadata` is the auth user's metadata bag. */\n getSignedInUser(): Promise<{ id: string; email?: string | null; metadata?: Record<string, unknown> | null } | null>;\n /** The file store behind pictures on a sheet or in a document. */\n files: {\n upload(file: File): Promise<{ fileId: string }>;\n getBlob(fileId: string): Promise<Blob>;\n };\n /** The newest snapshot row of a workbook (the realtime catch-up read), or `data: null` when it has none. */\n readNewestWorkbookSnapshot(\n workbookId: string,\n ): Promise<{ data: { id?: string; created_by?: string | null; created_at?: string } | null; error: { message: string } | null }>;\n /** Tell the person a picture did not upload. */\n notifyUploadError(error: unknown): void;\n /** The painted colour mode, as a React hook (re-renders on a switch). */\n useThemeMode(): \"light\" | \"dark\";\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.univer-host\");\ntype Slot = { ports?: UniverHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureUniverHost(ports: UniverHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getUniverHost(): UniverHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/univer: configureUniverHost(ports) was not called before an editor mounted.\");\n return ports;\n}\n","/**\n * univerImageStore — images on a sheet or in a document live in OUR file\n * store; the Univer snapshot holds only a reference (`matrx-file:<fileId>`).\n *\n * Why: Univer's stock image service inlines every picture as base64 into the\n * snapshot, so one 2 MB photo made every autosave, history row and collab\n * mutation ~2 MB. Here `saveImage` uploads the file and hands Univer a URL-type\n * source; Univer's URL-image downloader turns the reference back into bytes\n * (`getBlob` → object URL) when it paints. Images already inline (BASE64\n * sources) are untouched and keep rendering.\n */\n\nimport {\n IImageIoService,\n IURLImageService,\n ImageSourceType,\n ImageUploadStatusType,\n generateRandomId,\n} from \"@univerjs/core\";\n\nexport const MATRX_IMAGE_PREFIX = \"matrx-file:\";\n\nexport const isMatrxImageSource = (source: string): boolean =>\n source.startsWith(MATRX_IMAGE_PREFIX);\n\nexport const matrxImageFileId = (source: string): string =>\n source.slice(MATRX_IMAGE_PREFIX.length);\n\nexport type ImageStorePorts = {\n upload(file: File): Promise<{ fileId: string }>;\n getBlob(fileId: string): Promise<Blob>;\n /** Called when an upload fails, so the person is told (never silent). */\n onUploadError(error: unknown): void;\n};\n\nconst ALLOWED = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/gif\", \"image/bmp\", \"image/webp\"];\n\ntype ImageIo = {\n saveImage(file: File): Promise<unknown>;\n};\ntype UrlImages = {\n registerURLImageDownloader(d: (url: string) => Promise<string>): { dispose(): void };\n};\ntype InjectorLike = { get(id: unknown): unknown };\n\n/** Pure core: the two replacements, given ports. */\nexport function createMatrxImageStore(ports: ImageStorePorts) {\n const blobUrls = new Map<string, Promise<string>>();\n return {\n /** Revoke every object URL this store made (the editor is going away). */\n dispose() {\n for (const pending of blobUrls.values()) void pending.then((url) => URL.revokeObjectURL(url), () => undefined);\n blobUrls.clear();\n },\n async saveImage(file: File) {\n if (!ALLOWED.includes(file.type)) throw new Error(\"ERROR_IMAGE_TYPE\");\n let fileId: string;\n try {\n ({ fileId } = await ports.upload(file));\n } catch (error) {\n ports.onUploadError(error);\n throw error;\n }\n const source = MATRX_IMAGE_PREFIX + fileId;\n // Univer measures the picture from base64Cache before it inserts (an empty one throws, nothing is\n // inserted). A blob URL of the file just chosen serves that and paints it; it is never saved.\n const localUrl = URL.createObjectURL(file);\n blobUrls.set(fileId, Promise.resolve(localUrl));\n return {\n imageId: generateRandomId(6),\n imageSourceType: ImageSourceType.URL,\n source,\n base64Cache: localUrl,\n status: ImageUploadStatusType.SUCCUSS,\n };\n },\n async download(url: string): Promise<string> {\n if (!isMatrxImageSource(url)) return url;\n const fileId = matrxImageFileId(url);\n let pending = blobUrls.get(fileId);\n if (!pending) {\n pending = ports.getBlob(fileId).then((blob) => URL.createObjectURL(blob));\n blobUrls.set(fileId, pending);\n pending.catch(() => blobUrls.delete(fileId));\n }\n return pending;\n },\n };\n}\n\nconst stores = new WeakMap<object, { dispose(): void }>();\n\n/** Release the object URLs of the store wired into this Univer instance (call as the instance is disposed). */\nexport function releaseMatrxImageStore(injector: object | null | undefined): void {\n if (!injector) return;\n stores.get(injector)?.dispose();\n stores.delete(injector);\n}\n\n/** Wire the store into one Univer instance's image services. */\nexport function registerMatrxImageStore(injector: InjectorLike, ports: ImageStorePorts): void {\n const store = createMatrxImageStore(ports);\n stores.set(injector, store);\n const io = injector.get(IImageIoService) as ImageIo;\n io.saveImage = store.saveImage as ImageIo[\"saveImage\"];\n const urls = injector.get(IURLImageService) as UrlImages;\n urls.registerURLImageDownloader(store.download);\n}\n","import { getUniverHost } from \"./ports\";\nimport { isMatrxImageSource, matrxImageFileId, type ImageStorePorts } from \"./univerImageStore\";\n\n/** The real file-store ports (the host's): upload, read back as a blob, tell the person on failure. */\nexport const matrxImagePorts: ImageStorePorts = {\n async upload(file) {\n return getUniverHost().files.upload(file);\n },\n getBlob(fileId) {\n return getUniverHost().files.getBlob(fileId);\n },\n onUploadError(error) {\n getUniverHost().notifyUploadError(error);\n },\n};\n\n/** Export: a snapshot picture source (`matrx-file:<id>` or a URL) as bytes + type, or null if unreadable. */\nexport async function resolveExportImage(\n source: string,\n): Promise<{ bytes: Uint8Array; extension: \"png\" | \"jpeg\" | \"gif\" } | null> {\n let blob: Blob;\n if (isMatrxImageSource(source)) {\n blob = await getUniverHost().files.getBlob(matrxImageFileId(source));\n } else {\n const res = await fetch(source);\n if (!res.ok) return null;\n blob = await res.blob();\n }\n const extension = blob.type.includes(\"gif\") ? \"gif\" : blob.type.includes(\"png\") ? \"png\" : \"jpeg\";\n return { bytes: new Uint8Array(await blob.arrayBuffer()), extension };\n}\n\n/** Import: store a picture from a file, return its file id. */\nexport async function uploadImportedImage(bytes: Uint8Array, extension: string): Promise<string> {\n const mime = extension === \"jpg\" ? \"image/jpeg\" : `image/${extension}`;\n const { fileId } = await getUniverHost().files.upload(new File([bytes as BlobPart], `image.${extension}`, { type: mime }));\n return fileId;\n}\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// src/univer/ports.ts
|
|
2
|
+
var SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.office.univer-host");
|
|
3
|
+
var slot = () => {
|
|
4
|
+
const g = globalThis;
|
|
5
|
+
return g[SLOT] ??= {};
|
|
6
|
+
};
|
|
7
|
+
function getUniverHost() {
|
|
8
|
+
const ports = slot().ports;
|
|
9
|
+
if (!ports) throw new Error("@ai-matrx/office/univer: configureUniverHost(ports) was not called before an editor mounted.");
|
|
10
|
+
return ports;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/univer/univerImageStore.ts
|
|
14
|
+
import {
|
|
15
|
+
IImageIoService,
|
|
16
|
+
IURLImageService,
|
|
17
|
+
ImageSourceType,
|
|
18
|
+
ImageUploadStatusType,
|
|
19
|
+
generateRandomId
|
|
20
|
+
} from "@univerjs/core";
|
|
21
|
+
var MATRX_IMAGE_PREFIX = "matrx-file:";
|
|
22
|
+
var isMatrxImageSource = (source) => source.startsWith(MATRX_IMAGE_PREFIX);
|
|
23
|
+
var matrxImageFileId = (source) => source.slice(MATRX_IMAGE_PREFIX.length);
|
|
24
|
+
|
|
25
|
+
// src/univer/matrxImagePorts.ts
|
|
26
|
+
var matrxImagePorts = {
|
|
27
|
+
async upload(file) {
|
|
28
|
+
return getUniverHost().files.upload(file);
|
|
29
|
+
},
|
|
30
|
+
getBlob(fileId) {
|
|
31
|
+
return getUniverHost().files.getBlob(fileId);
|
|
32
|
+
},
|
|
33
|
+
onUploadError(error) {
|
|
34
|
+
getUniverHost().notifyUploadError(error);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
async function resolveExportImage(source) {
|
|
38
|
+
let blob;
|
|
39
|
+
if (isMatrxImageSource(source)) {
|
|
40
|
+
blob = await getUniverHost().files.getBlob(matrxImageFileId(source));
|
|
41
|
+
} else {
|
|
42
|
+
const res = await fetch(source);
|
|
43
|
+
if (!res.ok) return null;
|
|
44
|
+
blob = await res.blob();
|
|
45
|
+
}
|
|
46
|
+
const extension = blob.type.includes("gif") ? "gif" : blob.type.includes("png") ? "png" : "jpeg";
|
|
47
|
+
return { bytes: new Uint8Array(await blob.arrayBuffer()), extension };
|
|
48
|
+
}
|
|
49
|
+
async function uploadImportedImage(bytes, extension) {
|
|
50
|
+
const mime = extension === "jpg" ? "image/jpeg" : `image/${extension}`;
|
|
51
|
+
const { fileId } = await getUniverHost().files.upload(new File([bytes], `image.${extension}`, { type: mime }));
|
|
52
|
+
return fileId;
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
matrxImagePorts,
|
|
56
|
+
resolveExportImage,
|
|
57
|
+
uploadImportedImage
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=matrxImagePorts-VPBBUADM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/univer/ports.ts","../src/univer/univerImageStore.ts","../src/univer/matrxImagePorts.ts"],"sourcesContent":["/**\n * The host ports of the Univer glue.\n *\n * The glue belongs to the package, but four things belong to the app that mounts an editor: the\n * toast path, the signed-in person, the file store, the snapshot catch-up read and the painted theme. The host states them\n * once at start-up with `configureUniverHost`; the glue reads them here. State sits on a\n * `globalThis` slot so a dual-bundled copy of the package still sees one host (dual-bundle rule).\n * An unconfigured port THROWS naming the port (nothing fails silently).\n */\n\nexport type UniverToastId = string | number;\ntype ToastShow = (title: string, options?: { description?: string; duration?: number }) => UniverToastId;\n\nexport interface UniverHostPorts {\n /** The app's toast path (one toaster per page). */\n toast: {\n success: ToastShow;\n info: ToastShow;\n warning: ToastShow;\n error: ToastShow;\n message: ToastShow;\n dismiss(id: UniverToastId): void;\n };\n /** Who is typing, or null when signed out. `metadata` is the auth user's metadata bag. */\n getSignedInUser(): Promise<{ id: string; email?: string | null; metadata?: Record<string, unknown> | null } | null>;\n /** The file store behind pictures on a sheet or in a document. */\n files: {\n upload(file: File): Promise<{ fileId: string }>;\n getBlob(fileId: string): Promise<Blob>;\n };\n /** The newest snapshot row of a workbook (the realtime catch-up read), or `data: null` when it has none. */\n readNewestWorkbookSnapshot(\n workbookId: string,\n ): Promise<{ data: { id?: string; created_by?: string | null; created_at?: string } | null; error: { message: string } | null }>;\n /** Tell the person a picture did not upload. */\n notifyUploadError(error: unknown): void;\n /** The painted colour mode, as a React hook (re-renders on a switch). */\n useThemeMode(): \"light\" | \"dark\";\n}\n\nconst SLOT = Symbol.for(\"ai-matrx.office.univer-host\");\ntype Slot = { ports?: UniverHostPorts };\nconst slot = (): Slot => {\n const g = globalThis as Record<symbol, Slot | undefined>;\n return (g[SLOT] ??= {});\n};\n\nexport function configureUniverHost(ports: UniverHostPorts): void {\n slot().ports = ports;\n}\n\nexport function getUniverHost(): UniverHostPorts {\n const ports = slot().ports;\n if (!ports) throw new Error(\"@ai-matrx/office/univer: configureUniverHost(ports) was not called before an editor mounted.\");\n return ports;\n}\n","/**\n * univerImageStore — images on a sheet or in a document live in OUR file\n * store; the Univer snapshot holds only a reference (`matrx-file:<fileId>`).\n *\n * Why: Univer's stock image service inlines every picture as base64 into the\n * snapshot, so one 2 MB photo made every autosave, history row and collab\n * mutation ~2 MB. Here `saveImage` uploads the file and hands Univer a URL-type\n * source; Univer's URL-image downloader turns the reference back into bytes\n * (`getBlob` → object URL) when it paints. Images already inline (BASE64\n * sources) are untouched and keep rendering.\n */\n\nimport {\n IImageIoService,\n IURLImageService,\n ImageSourceType,\n ImageUploadStatusType,\n generateRandomId,\n} from \"@univerjs/core\";\n\nexport const MATRX_IMAGE_PREFIX = \"matrx-file:\";\n\nexport const isMatrxImageSource = (source: string): boolean =>\n source.startsWith(MATRX_IMAGE_PREFIX);\n\nexport const matrxImageFileId = (source: string): string =>\n source.slice(MATRX_IMAGE_PREFIX.length);\n\nexport type ImageStorePorts = {\n upload(file: File): Promise<{ fileId: string }>;\n getBlob(fileId: string): Promise<Blob>;\n /** Called when an upload fails, so the person is told (never silent). */\n onUploadError(error: unknown): void;\n};\n\nconst ALLOWED = [\"image/png\", \"image/jpeg\", \"image/jpg\", \"image/gif\", \"image/bmp\", \"image/webp\"];\n\ntype ImageIo = {\n saveImage(file: File): Promise<unknown>;\n};\ntype UrlImages = {\n registerURLImageDownloader(d: (url: string) => Promise<string>): { dispose(): void };\n};\ntype InjectorLike = { get(id: unknown): unknown };\n\n/** Pure core: the two replacements, given ports. */\nexport function createMatrxImageStore(ports: ImageStorePorts) {\n const blobUrls = new Map<string, Promise<string>>();\n return {\n /** Revoke every object URL this store made (the editor is going away). */\n dispose() {\n for (const pending of blobUrls.values()) void pending.then((url) => URL.revokeObjectURL(url), () => undefined);\n blobUrls.clear();\n },\n async saveImage(file: File) {\n if (!ALLOWED.includes(file.type)) throw new Error(\"ERROR_IMAGE_TYPE\");\n let fileId: string;\n try {\n ({ fileId } = await ports.upload(file));\n } catch (error) {\n ports.onUploadError(error);\n throw error;\n }\n const source = MATRX_IMAGE_PREFIX + fileId;\n // Univer measures the picture from base64Cache before it inserts (an empty one throws, nothing is\n // inserted). A blob URL of the file just chosen serves that and paints it; it is never saved.\n const localUrl = URL.createObjectURL(file);\n blobUrls.set(fileId, Promise.resolve(localUrl));\n return {\n imageId: generateRandomId(6),\n imageSourceType: ImageSourceType.URL,\n source,\n base64Cache: localUrl,\n status: ImageUploadStatusType.SUCCUSS,\n };\n },\n async download(url: string): Promise<string> {\n if (!isMatrxImageSource(url)) return url;\n const fileId = matrxImageFileId(url);\n let pending = blobUrls.get(fileId);\n if (!pending) {\n pending = ports.getBlob(fileId).then((blob) => URL.createObjectURL(blob));\n blobUrls.set(fileId, pending);\n pending.catch(() => blobUrls.delete(fileId));\n }\n return pending;\n },\n };\n}\n\nconst stores = new WeakMap<object, { dispose(): void }>();\n\n/** Release the object URLs of the store wired into this Univer instance (call as the instance is disposed). */\nexport function releaseMatrxImageStore(injector: object | null | undefined): void {\n if (!injector) return;\n stores.get(injector)?.dispose();\n stores.delete(injector);\n}\n\n/** Wire the store into one Univer instance's image services. */\nexport function registerMatrxImageStore(injector: InjectorLike, ports: ImageStorePorts): void {\n const store = createMatrxImageStore(ports);\n stores.set(injector, store);\n const io = injector.get(IImageIoService) as ImageIo;\n io.saveImage = store.saveImage as ImageIo[\"saveImage\"];\n const urls = injector.get(IURLImageService) as UrlImages;\n urls.registerURLImageDownloader(store.download);\n}\n","import { getUniverHost } from \"./ports\";\nimport { isMatrxImageSource, matrxImageFileId, type ImageStorePorts } from \"./univerImageStore\";\n\n/** The real file-store ports (the host's): upload, read back as a blob, tell the person on failure. */\nexport const matrxImagePorts: ImageStorePorts = {\n async upload(file) {\n return getUniverHost().files.upload(file);\n },\n getBlob(fileId) {\n return getUniverHost().files.getBlob(fileId);\n },\n onUploadError(error) {\n getUniverHost().notifyUploadError(error);\n },\n};\n\n/** Export: a snapshot picture source (`matrx-file:<id>` or a URL) as bytes + type, or null if unreadable. */\nexport async function resolveExportImage(\n source: string,\n): Promise<{ bytes: Uint8Array; extension: \"png\" | \"jpeg\" | \"gif\" } | null> {\n let blob: Blob;\n if (isMatrxImageSource(source)) {\n blob = await getUniverHost().files.getBlob(matrxImageFileId(source));\n } else {\n const res = await fetch(source);\n if (!res.ok) return null;\n blob = await res.blob();\n }\n const extension = blob.type.includes(\"gif\") ? \"gif\" : blob.type.includes(\"png\") ? \"png\" : \"jpeg\";\n return { bytes: new Uint8Array(await blob.arrayBuffer()), extension };\n}\n\n/** Import: store a picture from a file, return its file id. */\nexport async function uploadImportedImage(bytes: Uint8Array, extension: string): Promise<string> {\n const mime = extension === \"jpg\" ? \"image/jpeg\" : `image/${extension}`;\n const { fileId } = await getUniverHost().files.upload(new File([bytes as BlobPart], `image.${extension}`, { type: mime }));\n return fileId;\n}\n"],"mappings":";AAwCA,IAAM,OAAO,uBAAO,IAAI,6BAA6B;AAErD,IAAM,OAAO,MAAY;AACvB,QAAM,IAAI;AACV,SAAQ,EAAE,IAAI,MAAM,CAAC;AACvB;AAMO,SAAS,gBAAiC;AAC/C,QAAM,QAAQ,KAAK,EAAE;AACrB,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,8FAA8F;AAC1H,SAAO;AACT;;;AC3CA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,IAAM,qBAAqB;AAE3B,IAAM,qBAAqB,CAAC,WACjC,OAAO,WAAW,kBAAkB;AAE/B,IAAM,mBAAmB,CAAC,WAC/B,OAAO,MAAM,mBAAmB,MAAM;;;ACtBjC,IAAM,kBAAmC;AAAA,EAC9C,MAAM,OAAO,MAAM;AACjB,WAAO,cAAc,EAAE,MAAM,OAAO,IAAI;AAAA,EAC1C;AAAA,EACA,QAAQ,QAAQ;AACd,WAAO,cAAc,EAAE,MAAM,QAAQ,MAAM;AAAA,EAC7C;AAAA,EACA,cAAc,OAAO;AACnB,kBAAc,EAAE,kBAAkB,KAAK;AAAA,EACzC;AACF;AAGA,eAAsB,mBACpB,QAC0E;AAC1E,MAAI;AACJ,MAAI,mBAAmB,MAAM,GAAG;AAC9B,WAAO,MAAM,cAAc,EAAE,MAAM,QAAQ,iBAAiB,MAAM,CAAC;AAAA,EACrE,OAAO;AACL,UAAM,MAAM,MAAM,MAAM,MAAM;AAC9B,QAAI,CAAC,IAAI,GAAI,QAAO;AACpB,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB;AACA,QAAM,YAAY,KAAK,KAAK,SAAS,KAAK,IAAI,QAAQ,KAAK,KAAK,SAAS,KAAK,IAAI,QAAQ;AAC1F,SAAO,EAAE,OAAO,IAAI,WAAW,MAAM,KAAK,YAAY,CAAC,GAAG,UAAU;AACtE;AAGA,eAAsB,oBAAoB,OAAmB,WAAoC;AAC/F,QAAM,OAAO,cAAc,QAAQ,eAAe,SAAS,SAAS;AACpE,QAAM,EAAE,OAAO,IAAI,MAAM,cAAc,EAAE,MAAM,OAAO,IAAI,KAAK,CAAC,KAAiB,GAAG,SAAS,SAAS,IAAI,EAAE,MAAM,KAAK,CAAC,CAAC;AACzH,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
var _chunkZDZCCOUBcjs = require('./chunk-ZDZCCOUB.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
var _chunkQZE7HBZBcjs = require('./chunk-QZE7HBZB.cjs');
|
|
28
|
+
|
|
29
|
+
// src/sheets/univer-to-xlsx.ts
|
|
30
|
+
var _operate = require('@ai-matrx/alchemy/operate');
|
|
31
|
+
var _download = require('@ai-matrx/kit/download');
|
|
32
|
+
var _xlsxstyled = require('@ai-matrx/print/xlsx-styled');
|
|
33
|
+
function univerSnapshotToWorkbookJson(snapshot) {
|
|
34
|
+
const sheetOrder = _nullishCoalesce(snapshot.sheetOrder, () => ( Object.keys(_nullishCoalesce(snapshot.sheets, () => ( {})))));
|
|
35
|
+
const sheets = [];
|
|
36
|
+
for (const sheetId of sheetOrder) {
|
|
37
|
+
const sheet = _optionalChain([snapshot, 'access', _ => _.sheets, 'optionalAccess', _2 => _2[sheetId]]);
|
|
38
|
+
if (!sheet) continue;
|
|
39
|
+
sheets.push(sheetToJson(sheet, (_nullishCoalesce(sheet.name, () => ( sheetId))).slice(0, 31) || "Sheet1"));
|
|
40
|
+
}
|
|
41
|
+
return { sheets };
|
|
42
|
+
}
|
|
43
|
+
async function univerSnapshotToXlsxBytes(snapshot, options = {}) {
|
|
44
|
+
return (await buildXlsxFromUniver(snapshot, options)).bytes;
|
|
45
|
+
}
|
|
46
|
+
async function downloadUniverAsXlsx(snapshot, options = {}) {
|
|
47
|
+
if (typeof document === "undefined") return { dropped: [] };
|
|
48
|
+
const filename = `${(_nullishCoalesce(options.filename, () => ( "workbook"))).replace(/\.xlsx$/i, "")}.xlsx`;
|
|
49
|
+
const { bytes, report } = await buildXlsxFromUniver(snapshot, options);
|
|
50
|
+
const blob = new Blob([bytes], {
|
|
51
|
+
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
52
|
+
});
|
|
53
|
+
_download.downloadFile.call(void 0, filename, blob, blob.type);
|
|
54
|
+
return report;
|
|
55
|
+
}
|
|
56
|
+
async function buildXlsxFromUniver(snapshot, options = {}) {
|
|
57
|
+
const ExcelJS = await _xlsxstyled.loadExcelJs.call(void 0, );
|
|
58
|
+
const wb = new ExcelJS.Workbook();
|
|
59
|
+
const dropped = /* @__PURE__ */ new Set();
|
|
60
|
+
const resources = _nullishCoalesce(snapshot.resources, () => ( []));
|
|
61
|
+
const styles = _nullishCoalesce(snapshot.styles, () => ( {}));
|
|
62
|
+
const validation = _nullishCoalesce(_chunkQZE7HBZBcjs.readResource.call(void 0, resources, _chunkQZE7HBZBcjs.RESOURCE.validation), () => ( {}));
|
|
63
|
+
const conditional = _nullishCoalesce(_chunkQZE7HBZBcjs.readResource.call(void 0, resources, _chunkQZE7HBZBcjs.RESOURCE.conditional), () => ( {}));
|
|
64
|
+
const filters = _nullishCoalesce(_chunkQZE7HBZBcjs.readResource.call(void 0, resources, _chunkQZE7HBZBcjs.RESOURCE.filter), () => ( {}));
|
|
65
|
+
const notes = _nullishCoalesce(_chunkQZE7HBZBcjs.readResource.call(void 0, resources, _chunkQZE7HBZBcjs.RESOURCE.note), () => ( {}));
|
|
66
|
+
const comments = _nullishCoalesce(_chunkQZE7HBZBcjs.readResource.call(void 0, resources, _chunkQZE7HBZBcjs.RESOURCE.comments), () => ( {}));
|
|
67
|
+
const drawings = _nullishCoalesce(_chunkQZE7HBZBcjs.readResource.call(void 0, resources, _chunkQZE7HBZBcjs.RESOURCE.drawing), () => ( {}));
|
|
68
|
+
const tables = _nullishCoalesce(_chunkQZE7HBZBcjs.readResource.call(void 0, resources, _chunkQZE7HBZBcjs.RESOURCE.table), () => ( {}));
|
|
69
|
+
const order = _nullishCoalesce(snapshot.sheetOrder, () => ( Object.keys(_nullishCoalesce(snapshot.sheets, () => ( {})))));
|
|
70
|
+
for (const sheetId of order) {
|
|
71
|
+
const sheet = _optionalChain([snapshot, 'access', _3 => _3.sheets, 'optionalAccess', _4 => _4[sheetId]]);
|
|
72
|
+
if (!sheet) continue;
|
|
73
|
+
const ws = wb.addWorksheet(uniqueName(wb, (_nullishCoalesce(sheet.name, () => ( sheetId))).slice(0, 31) || "Sheet1"));
|
|
74
|
+
writeCells(ws, sheet, styles);
|
|
75
|
+
writeLayout(ws, sheet);
|
|
76
|
+
const tab = _chunkQZE7HBZBcjs.colorToArgb.call(void 0, typeof sheet.tabColor === "string" ? sheet.tabColor : void 0);
|
|
77
|
+
if (tab) ws.properties.tabColor = { argb: tab };
|
|
78
|
+
writeValidation(ws, validation[sheetId], dropped);
|
|
79
|
+
writeConditional(ws, conditional[sheetId], dropped);
|
|
80
|
+
writeFilter(ws, filters[sheetId], dropped);
|
|
81
|
+
writeNotes(ws, notes[sheetId], comments[sheetId], dropped);
|
|
82
|
+
await writeImages(wb, ws, drawings[sheetId], options.resolveImage, dropped);
|
|
83
|
+
if (tables[sheetId] && Object.keys(tables[sheetId]).length) {
|
|
84
|
+
dropped.add("Tables are exported as plain ranges (their data and styling are kept)");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const buffer = await wb.xlsx.writeBuffer();
|
|
88
|
+
return { bytes: new Uint8Array(buffer), report: { dropped: [...dropped] } };
|
|
89
|
+
}
|
|
90
|
+
function uniqueName(wb, name) {
|
|
91
|
+
let candidate = name;
|
|
92
|
+
let n = 2;
|
|
93
|
+
while (wb.getWorksheet(candidate)) candidate = `${name.slice(0, 28)} ${n++}`;
|
|
94
|
+
return candidate;
|
|
95
|
+
}
|
|
96
|
+
function styleOf(cell, styles) {
|
|
97
|
+
const s = cell.s;
|
|
98
|
+
if (!s) return void 0;
|
|
99
|
+
return typeof s === "string" ? styles[s] : s;
|
|
100
|
+
}
|
|
101
|
+
function applyStyle(target, st) {
|
|
102
|
+
if (!st) return;
|
|
103
|
+
const font = {};
|
|
104
|
+
if (st.ff) font.name = String(st.ff);
|
|
105
|
+
if (typeof st.fs === "number") font.size = st.fs;
|
|
106
|
+
if (st.bl === 1) font.bold = true;
|
|
107
|
+
if (st.it === 1) font.italic = true;
|
|
108
|
+
if (_optionalChain([st, 'access', _5 => _5.ul, 'optionalAccess', _6 => _6.s]) === 1) font.underline = true;
|
|
109
|
+
if (_optionalChain([st, 'access', _7 => _7.st, 'optionalAccess', _8 => _8.s]) === 1) font.strike = true;
|
|
110
|
+
const fg = _chunkQZE7HBZBcjs.colorToArgb.call(void 0, _optionalChain([st, 'access', _9 => _9.cl, 'optionalAccess', _10 => _10.rgb]));
|
|
111
|
+
if (fg) font.color = { argb: fg };
|
|
112
|
+
if (Object.keys(font).length) target.font = font;
|
|
113
|
+
const bg = _chunkQZE7HBZBcjs.colorToArgb.call(void 0, _optionalChain([st, 'access', _11 => _11.bg, 'optionalAccess', _12 => _12.rgb]));
|
|
114
|
+
if (bg) target.fill = { type: "pattern", pattern: "solid", fgColor: { argb: bg } };
|
|
115
|
+
const alignment = {};
|
|
116
|
+
if (typeof st.ht === "number" && _chunkQZE7HBZBcjs.H_ALIGN_OUT[st.ht]) alignment.horizontal = _chunkQZE7HBZBcjs.H_ALIGN_OUT[st.ht];
|
|
117
|
+
if (typeof st.vt === "number" && _chunkQZE7HBZBcjs.V_ALIGN_OUT[st.vt]) alignment.vertical = _chunkQZE7HBZBcjs.V_ALIGN_OUT[st.vt];
|
|
118
|
+
if (st.tb === 3) alignment.wrapText = true;
|
|
119
|
+
if (Object.keys(alignment).length) target.alignment = alignment;
|
|
120
|
+
const bd = st.bd;
|
|
121
|
+
if (bd) {
|
|
122
|
+
const border = {};
|
|
123
|
+
for (const [key, side] of [["t", "top"], ["b", "bottom"], ["l", "left"], ["r", "right"]]) {
|
|
124
|
+
const b = bd[key];
|
|
125
|
+
const style = _chunkQZE7HBZBcjs.borderToExcel.call(void 0, _optionalChain([b, 'optionalAccess', _13 => _13.s]));
|
|
126
|
+
if (style) {
|
|
127
|
+
border[side] = { style, color: { argb: _nullishCoalesce(_chunkQZE7HBZBcjs.colorToArgb.call(void 0, _optionalChain([b, 'optionalAccess', _14 => _14.cl, 'optionalAccess', _15 => _15.rgb])), () => ( "FF000000")) } };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (Object.keys(border).length) target.border = border;
|
|
131
|
+
}
|
|
132
|
+
const pattern = _optionalChain([st, 'access', _16 => _16.n, 'optionalAccess', _17 => _17.pattern]);
|
|
133
|
+
if (typeof pattern === "string" && pattern && pattern !== "General") target.numFmt = pattern;
|
|
134
|
+
}
|
|
135
|
+
function plainText(p) {
|
|
136
|
+
return String(_nullishCoalesce(_optionalChain([p, 'optionalAccess', _18 => _18.body, 'optionalAccess', _19 => _19.dataStream]), () => ( ""))).replace(/\r\n$/, "").replace(/\r\n/g, "\n");
|
|
137
|
+
}
|
|
138
|
+
function linkOf(p) {
|
|
139
|
+
const ranges = _optionalChain([p, 'optionalAccess', _20 => _20.body, 'optionalAccess', _21 => _21.customRanges]);
|
|
140
|
+
return _optionalChain([ranges, 'optionalAccess', _22 => _22.find, 'call', _23 => _23((r) => r.rangeType === 0 && _optionalChain([r, 'access', _24 => _24.properties, 'optionalAccess', _25 => _25.url])), 'optionalAccess', _26 => _26.properties, 'optionalAccess', _27 => _27.url]);
|
|
141
|
+
}
|
|
142
|
+
function writeCells(ws, sheet, styles) {
|
|
143
|
+
const cellData = _nullishCoalesce(sheet.cellData, () => ( {}));
|
|
144
|
+
for (const rKey of Object.keys(cellData)) {
|
|
145
|
+
const r = Number(rKey);
|
|
146
|
+
const row = cellData[r];
|
|
147
|
+
if (!row || !Number.isFinite(r)) continue;
|
|
148
|
+
for (const cKey of Object.keys(row)) {
|
|
149
|
+
const c = Number(cKey);
|
|
150
|
+
const cell = row[c];
|
|
151
|
+
if (!cell || !Number.isFinite(c)) continue;
|
|
152
|
+
const target = ws.getCell(r + 1, c + 1);
|
|
153
|
+
const formula = typeof cell.f === "string" ? cell.f.replace(/^=/, "") : void 0;
|
|
154
|
+
const rich = cell.p;
|
|
155
|
+
let value = null;
|
|
156
|
+
if (cell.v !== void 0 && cell.v !== null && cell.v !== "") {
|
|
157
|
+
if (cell.t === 3) value = Boolean(cell.v);
|
|
158
|
+
else if (cell.t === 2 || typeof cell.v === "number") value = Number(cell.v);
|
|
159
|
+
else value = String(cell.v);
|
|
160
|
+
} else if (rich) {
|
|
161
|
+
value = plainText(rich);
|
|
162
|
+
}
|
|
163
|
+
const url = linkOf(rich);
|
|
164
|
+
if (url) value = { text: String(_nullishCoalesce(value, () => ( url))), hyperlink: url };
|
|
165
|
+
if (formula) value = { formula, result: _nullishCoalesce(value, () => ( void 0)) };
|
|
166
|
+
if (value !== null && value !== "") target.value = value;
|
|
167
|
+
applyStyle(target, styleOf(cell, styles));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function writeLayout(ws, sheet) {
|
|
172
|
+
const defaultCol = sheet.defaultColumnWidth;
|
|
173
|
+
const columns = _nullishCoalesce(sheet.columnData, () => ( {}));
|
|
174
|
+
for (const key of Object.keys(columns)) {
|
|
175
|
+
const c = Number(key);
|
|
176
|
+
const col = columns[c];
|
|
177
|
+
if (!col) continue;
|
|
178
|
+
const target = ws.getColumn(c + 1);
|
|
179
|
+
if (typeof col.w === "number") target.width = _chunkQZE7HBZBcjs.colPxToChars.call(void 0, col.w);
|
|
180
|
+
else if (defaultCol) target.width = _chunkQZE7HBZBcjs.colPxToChars.call(void 0, defaultCol);
|
|
181
|
+
if (col.hd === 1) target.hidden = true;
|
|
182
|
+
}
|
|
183
|
+
const rows = _nullishCoalesce(sheet.rowData, () => ( {}));
|
|
184
|
+
for (const key of Object.keys(rows)) {
|
|
185
|
+
const r = Number(key);
|
|
186
|
+
const row = rows[r];
|
|
187
|
+
if (!row) continue;
|
|
188
|
+
const target = ws.getRow(r + 1);
|
|
189
|
+
if (typeof row.h === "number") target.height = _chunkQZE7HBZBcjs.rowPxToPt.call(void 0, row.h);
|
|
190
|
+
if (row.hd === 1) target.hidden = true;
|
|
191
|
+
}
|
|
192
|
+
for (const m of _nullishCoalesce(sheet.mergeData, () => ( []))) {
|
|
193
|
+
try {
|
|
194
|
+
ws.mergeCells(m.startRow + 1, m.startColumn + 1, m.endRow + 1, m.endColumn + 1);
|
|
195
|
+
} catch (e2) {
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const freeze = sheet.freeze;
|
|
199
|
+
if (freeze && (freeze.xSplit > 0 || freeze.ySplit > 0)) {
|
|
200
|
+
ws.views = [{ state: "frozen", xSplit: freeze.xSplit, ySplit: freeze.ySplit }];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
var eachCell = (ranges, fn, cap = 1e5) => {
|
|
204
|
+
let n = 0;
|
|
205
|
+
for (const r of ranges) {
|
|
206
|
+
for (let row = r.startRow; row <= r.endRow; row++) {
|
|
207
|
+
for (let col = r.startColumn; col <= r.endColumn; col++) {
|
|
208
|
+
if (++n > cap) return false;
|
|
209
|
+
fn(row, col);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return true;
|
|
214
|
+
};
|
|
215
|
+
function writeValidation(ws, rules, dropped) {
|
|
216
|
+
for (const rule of _nullishCoalesce(rules, () => ( []))) {
|
|
217
|
+
const type = String(rule.type);
|
|
218
|
+
const base = {
|
|
219
|
+
allowBlank: rule.allowBlank !== false,
|
|
220
|
+
showErrorMessage: rule.showErrorMessage !== false,
|
|
221
|
+
errorTitle: rule.errorTitle,
|
|
222
|
+
error: rule.error,
|
|
223
|
+
showInputMessage: Boolean(rule.showInputMessage),
|
|
224
|
+
promptTitle: rule.promptTitle,
|
|
225
|
+
prompt: rule.prompt
|
|
226
|
+
};
|
|
227
|
+
let dv = null;
|
|
228
|
+
if (type === "list" || type === "listMultiple") {
|
|
229
|
+
const f1 = String(_nullishCoalesce(rule.formula1, () => ( "")));
|
|
230
|
+
const isRange = /^=?'?[^,"]*!?\$?[A-Z]+\$?\d+(:\$?[A-Z]+\$?\d+)?$/i.test(f1) && !f1.includes(",");
|
|
231
|
+
dv = { ...base, type: "list", formulae: [isRange ? f1.replace(/^=/, "") : `"${f1.replace(/"/g, "")}"`] };
|
|
232
|
+
if (type === "listMultiple") dropped.add("Multi-select dropdowns become single-select");
|
|
233
|
+
} else if (type === "checkbox") {
|
|
234
|
+
dv = { ...base, type: "list", formulae: ['"TRUE,FALSE"'] };
|
|
235
|
+
dropped.add("Checkboxes become TRUE/FALSE dropdowns");
|
|
236
|
+
} else if (["whole", "decimal", "date", "time", "textLength"].includes(type)) {
|
|
237
|
+
dv = {
|
|
238
|
+
...base,
|
|
239
|
+
type,
|
|
240
|
+
operator: _nullishCoalesce(rule.operator, () => ( "between")),
|
|
241
|
+
formulae: [rule.formula1, rule.formula2].filter((f) => f !== void 0 && f !== "")
|
|
242
|
+
};
|
|
243
|
+
} else if (type === "custom") {
|
|
244
|
+
dv = { ...base, type: "custom", formulae: [String(_nullishCoalesce(rule.formula1, () => ( ""))).replace(/^=/, "")] };
|
|
245
|
+
}
|
|
246
|
+
if (!dv) continue;
|
|
247
|
+
if (!dv.errorTitle) delete dv.errorTitle;
|
|
248
|
+
const complete = eachCell(_nullishCoalesce(rule.ranges, () => ( [])), (r, c) => {
|
|
249
|
+
ws.getCell(r + 1, c + 1).dataValidation = dv;
|
|
250
|
+
});
|
|
251
|
+
if (!complete) dropped.add("Data validation on very large ranges was cut off");
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
var NUMBER_OPS = /* @__PURE__ */ new Set(["greaterThan", "greaterThanOrEqual", "lessThan", "lessThanOrEqual", "equal", "notEqual", "between", "notBetween"]);
|
|
255
|
+
function cfStyle(style) {
|
|
256
|
+
const out = {};
|
|
257
|
+
const font = {};
|
|
258
|
+
const fg = _chunkQZE7HBZBcjs.colorToArgb.call(void 0, _optionalChain([style, 'optionalAccess', _28 => _28.cl, 'optionalAccess', _29 => _29.rgb]));
|
|
259
|
+
if (fg) font.color = { argb: fg };
|
|
260
|
+
if (_optionalChain([style, 'optionalAccess', _30 => _30.bl]) === 1) font.bold = true;
|
|
261
|
+
if (_optionalChain([style, 'optionalAccess', _31 => _31.it]) === 1) font.italic = true;
|
|
262
|
+
if (Object.keys(font).length) out.font = font;
|
|
263
|
+
const bg = _chunkQZE7HBZBcjs.colorToArgb.call(void 0, _optionalChain([style, 'optionalAccess', _32 => _32.bg, 'optionalAccess', _33 => _33.rgb]));
|
|
264
|
+
if (bg) out.fill = { type: "pattern", pattern: "solid", bgColor: { argb: bg } };
|
|
265
|
+
return out;
|
|
266
|
+
}
|
|
267
|
+
function writeConditional(ws, rules, dropped) {
|
|
268
|
+
for (const entry of _nullishCoalesce(rules, () => ( []))) {
|
|
269
|
+
const ranges = _nullishCoalesce(entry.ranges, () => ( []));
|
|
270
|
+
if (!ranges.length) continue;
|
|
271
|
+
const ref = ranges.map(_chunkQZE7HBZBcjs.rangeToA1).join(" ");
|
|
272
|
+
const first = ranges[0];
|
|
273
|
+
const topLeft = _chunkQZE7HBZBcjs.rangeToA1.call(void 0, { ...first, endRow: first.startRow, endColumn: first.startColumn });
|
|
274
|
+
const rule = entry.rule;
|
|
275
|
+
let out = null;
|
|
276
|
+
if (_optionalChain([rule, 'optionalAccess', _34 => _34.type]) === "highlightCell") {
|
|
277
|
+
const style = cfStyle(rule.style);
|
|
278
|
+
switch (rule.subType) {
|
|
279
|
+
case "number":
|
|
280
|
+
if (NUMBER_OPS.has(rule.operator)) {
|
|
281
|
+
out = { type: "cellIs", operator: rule.operator, formulae: Array.isArray(rule.value) ? rule.value : [rule.value], style };
|
|
282
|
+
}
|
|
283
|
+
break;
|
|
284
|
+
case "text":
|
|
285
|
+
if (rule.operator === "containsText") out = { type: "containsText", operator: "containsText", text: String(_nullishCoalesce(rule.value, () => ( ""))), style };
|
|
286
|
+
break;
|
|
287
|
+
case "duplicateValues":
|
|
288
|
+
out = { type: "expression", formulae: [`COUNTIF(${ref.split(" ")[0]},${topLeft})>1`], style };
|
|
289
|
+
break;
|
|
290
|
+
case "uniqueValues":
|
|
291
|
+
out = { type: "expression", formulae: [`COUNTIF(${ref.split(" ")[0]},${topLeft})=1`], style };
|
|
292
|
+
break;
|
|
293
|
+
case "formula":
|
|
294
|
+
out = { type: "expression", formulae: [String(_nullishCoalesce(rule.value, () => ( ""))).replace(/^=/, "")], style };
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
} else if (_optionalChain([rule, 'optionalAccess', _35 => _35.type]) === "colorScale" && Array.isArray(rule.config)) {
|
|
298
|
+
const cfg = [...rule.config].sort((a, b) => a.index - b.index);
|
|
299
|
+
out = {
|
|
300
|
+
type: "colorScale",
|
|
301
|
+
cfvo: cfg.map((c) => ({ type: _nullishCoalesce(_optionalChain([c, 'access', _36 => _36.value, 'optionalAccess', _37 => _37.type]), () => ( "min")), ..._optionalChain([c, 'access', _38 => _38.value, 'optionalAccess', _39 => _39.value]) !== void 0 ? { value: c.value.value } : {} })),
|
|
302
|
+
color: cfg.map((c) => ({ argb: _nullishCoalesce(_chunkQZE7HBZBcjs.colorToArgb.call(void 0, c.color), () => ( "FFFFFFFF")) }))
|
|
303
|
+
};
|
|
304
|
+
} else if (_optionalChain([rule, 'optionalAccess', _40 => _40.type]) === "dataBar") {
|
|
305
|
+
out = {
|
|
306
|
+
type: "dataBar",
|
|
307
|
+
gradient: _optionalChain([rule, 'access', _41 => _41.config, 'optionalAccess', _42 => _42.isGradient]) !== false,
|
|
308
|
+
cfvo: [{ type: _nullishCoalesce(_optionalChain([rule, 'access', _43 => _43.config, 'optionalAccess', _44 => _44.min, 'optionalAccess', _45 => _45.type]), () => ( "min")) }, { type: _nullishCoalesce(_optionalChain([rule, 'access', _46 => _46.config, 'optionalAccess', _47 => _47.max, 'optionalAccess', _48 => _48.type]), () => ( "max")) }],
|
|
309
|
+
color: { argb: _nullishCoalesce(_chunkQZE7HBZBcjs.colorToArgb.call(void 0, _optionalChain([rule, 'access', _49 => _49.config, 'optionalAccess', _50 => _50.positiveColor])), () => ( "FF638EC6")) }
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
if (!out) {
|
|
313
|
+
dropped.add("Some conditional formats (icon sets, top/bottom, average, date rules) are not written");
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
ws.addConditionalFormatting({ ref, rules: [{ ...out, priority: 1 }] });
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
function writeFilter(ws, filter, dropped) {
|
|
320
|
+
const ref = _optionalChain([filter, 'optionalAccess', _51 => _51.ref]);
|
|
321
|
+
if (!ref) return;
|
|
322
|
+
ws.autoFilter = {
|
|
323
|
+
from: { row: ref.startRow + 1, column: ref.startColumn + 1 },
|
|
324
|
+
to: { row: ref.endRow + 1, column: ref.endColumn + 1 }
|
|
325
|
+
};
|
|
326
|
+
if (_optionalChain([filter, 'optionalAccess', _52 => _52.filterColumns, 'optionalAccess', _53 => _53.length])) {
|
|
327
|
+
dropped.add("Which filter choices were applied is not saved (the filter arrows are)");
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function threadText(c) {
|
|
331
|
+
return String(_nullishCoalesce(_optionalChain([c, 'optionalAccess', _54 => _54.text, 'optionalAccess', _55 => _55.dataStream]), () => ( ""))).replace(/\r\n?$/, "").replace(/\r\n?/g, "\n");
|
|
332
|
+
}
|
|
333
|
+
function writeNotes(ws, sheetNotes, sheetComments, dropped) {
|
|
334
|
+
for (const [row, cols] of Object.entries(_nullishCoalesce(sheetNotes, () => ( {})))) {
|
|
335
|
+
for (const [col, note] of Object.entries(cols)) {
|
|
336
|
+
const text = String(_nullishCoalesce(note.note, () => ( "")));
|
|
337
|
+
if (text) ws.getCell(Number(row) + 1, Number(col) + 1).note = text;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const list = Array.isArray(sheetComments) ? sheetComments : sheetComments ? Object.values(sheetComments).flat() : [];
|
|
341
|
+
const threads = /* @__PURE__ */ new Map();
|
|
342
|
+
for (const c of list) {
|
|
343
|
+
if (!_optionalChain([c, 'optionalAccess', _56 => _56.ref])) continue;
|
|
344
|
+
const lines = _nullishCoalesce(threads.get(c.ref), () => ( []));
|
|
345
|
+
const who = _nullishCoalesce(_nullishCoalesce(c.authorName, () => ( c.personId)), () => ( ""));
|
|
346
|
+
lines.push(`${who ? who + ": " : ""}${threadText(c)}`);
|
|
347
|
+
for (const child of _nullishCoalesce(c.children, () => ( []))) {
|
|
348
|
+
lines.push(`${_nullishCoalesce(_nullishCoalesce(child.authorName, () => ( child.personId)), () => ( ""))}: ${threadText(child)}`);
|
|
349
|
+
}
|
|
350
|
+
threads.set(c.ref, lines);
|
|
351
|
+
}
|
|
352
|
+
for (const [ref, lines] of threads) {
|
|
353
|
+
const cell = ws.getCell(ref);
|
|
354
|
+
const existing = typeof cell.note === "string" ? cell.note : "";
|
|
355
|
+
cell.note = [existing, ...lines].filter(Boolean).join("\n");
|
|
356
|
+
}
|
|
357
|
+
if (threads.size) dropped.add("Comment threads are written as cell notes (replies and resolved state are flattened)");
|
|
358
|
+
}
|
|
359
|
+
async function writeImages(wb, ws, sheetDrawings, resolve, dropped) {
|
|
360
|
+
const data = _nullishCoalesce(_optionalChain([sheetDrawings, 'optionalAccess', _57 => _57.data]), () => ( {}));
|
|
361
|
+
for (const d of Object.values(data)) {
|
|
362
|
+
if (d.drawingType !== 0 || !d.source) continue;
|
|
363
|
+
const from = _optionalChain([d, 'access', _58 => _58.sheetTransform, 'optionalAccess', _59 => _59.from]);
|
|
364
|
+
if (!from) continue;
|
|
365
|
+
let bytes = null;
|
|
366
|
+
let extension = "png";
|
|
367
|
+
const dataUrl = /^data:image\/(png|jpeg|jpg|gif);base64,(.+)$/i.exec(String(d.source));
|
|
368
|
+
if (dataUrl) {
|
|
369
|
+
extension = dataUrl[1].toLowerCase() === "gif" ? "gif" : dataUrl[1].toLowerCase() === "png" ? "png" : "jpeg";
|
|
370
|
+
bytes = Uint8Array.from(atob(dataUrl[2]), (ch) => ch.charCodeAt(0));
|
|
371
|
+
} else if (resolve) {
|
|
372
|
+
try {
|
|
373
|
+
const got = await resolve(String(d.source));
|
|
374
|
+
if (got) ({ bytes, extension } = got);
|
|
375
|
+
} catch (e3) {
|
|
376
|
+
bytes = null;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (!bytes) {
|
|
380
|
+
dropped.add("Some pictures could not be read and were left out");
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const id = wb.addImage({ buffer: bytes, extension });
|
|
384
|
+
ws.addImage(id, {
|
|
385
|
+
tl: { col: from.column + (_nullishCoalesce(from.columnOffset, () => ( 0))) / 64, row: from.row + (_nullishCoalesce(from.rowOffset, () => ( 0))) / 20 },
|
|
386
|
+
ext: { width: _nullishCoalesce(_optionalChain([d, 'access', _60 => _60.transform, 'optionalAccess', _61 => _61.width]), () => ( 200)), height: _nullishCoalesce(_optionalChain([d, 'access', _62 => _62.transform, 'optionalAccess', _63 => _63.height]), () => ( 150)) }
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function sheetToJson(sheet, name) {
|
|
391
|
+
const cellData = _nullishCoalesce(sheet.cellData, () => ( {}));
|
|
392
|
+
const rows = [];
|
|
393
|
+
for (const rKey of Object.keys(cellData)) {
|
|
394
|
+
const r = Number(rKey);
|
|
395
|
+
if (!Number.isFinite(r)) continue;
|
|
396
|
+
const row = cellData[r];
|
|
397
|
+
if (!row) continue;
|
|
398
|
+
for (const cKey of Object.keys(row)) {
|
|
399
|
+
const c = Number(cKey);
|
|
400
|
+
if (!Number.isFinite(c)) continue;
|
|
401
|
+
const cell = row[c];
|
|
402
|
+
if (!cell) continue;
|
|
403
|
+
const out = toWorkbookCell(cell);
|
|
404
|
+
if (!out) continue;
|
|
405
|
+
while (rows.length <= r) rows.push([]);
|
|
406
|
+
const line = rows[r];
|
|
407
|
+
while (line.length < c) line.push(null);
|
|
408
|
+
line[c] = out;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const merges = (_nullishCoalesce(sheet.mergeData, () => ( []))).map((m) => ({
|
|
412
|
+
s: { r: m.startRow, c: m.startColumn },
|
|
413
|
+
e: { r: m.endRow, c: m.endColumn }
|
|
414
|
+
}));
|
|
415
|
+
return { name, rows, ...merges.length ? { merges } : {} };
|
|
416
|
+
}
|
|
417
|
+
function toWorkbookCell(cell) {
|
|
418
|
+
const formula = typeof cell.f === "string" ? cell.f.replace(/^=/, "") : void 0;
|
|
419
|
+
let out;
|
|
420
|
+
switch (cell.t) {
|
|
421
|
+
case 2:
|
|
422
|
+
out = { t: "n", v: typeof cell.v === "number" ? cell.v : Number(_nullishCoalesce(cell.v, () => ( 0))) };
|
|
423
|
+
break;
|
|
424
|
+
case 3:
|
|
425
|
+
out = { t: "b", v: Boolean(cell.v) };
|
|
426
|
+
break;
|
|
427
|
+
default:
|
|
428
|
+
out = {
|
|
429
|
+
t: "s",
|
|
430
|
+
v: cell.v === null || cell.v === void 0 ? "" : typeof cell.v === "object" ? JSON.stringify(cell.v) : String(cell.v)
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
if ((out.v === "" || out.v === null || out.v === void 0) && !formula) return null;
|
|
434
|
+
return formula ? { ...out, f: formula } : out;
|
|
435
|
+
}
|
|
436
|
+
async function univerSnapshotToRegisteredXlsxBytes(snapshot) {
|
|
437
|
+
const built = await _operate.buildFile.call(void 0,
|
|
438
|
+
{ kind: "registered", format: "workbook", value: univerSnapshotToWorkbookJson(snapshot) },
|
|
439
|
+
"xlsx-workbook"
|
|
440
|
+
);
|
|
441
|
+
return built.bytes;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/sheets/import-workbook-file.ts
|
|
445
|
+
var _core = require('@ai-matrx/records/core');
|
|
446
|
+
function unsupportedFileReason(file) {
|
|
447
|
+
const name = file.name.toLowerCase();
|
|
448
|
+
if (name.endsWith(".xlsx") || name.endsWith(".xls") || name.endsWith(".csv")) {
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
if (name.endsWith(".tsv") || name.endsWith(".txt")) return null;
|
|
452
|
+
if (name.endsWith(".gsheet")) {
|
|
453
|
+
return "A Google Sheets shortcut can't be uploaded. Use Import from Google Sheets.";
|
|
454
|
+
}
|
|
455
|
+
return `"${file.name}" isn't a spreadsheet file. Supported: .xlsx, .xls, .csv. For a Google Sheet, use Import from Google Sheets.`;
|
|
456
|
+
}
|
|
457
|
+
async function importWorkbookFile(file, organizationId) {
|
|
458
|
+
const capturedOrganizationId = await _chunkZDZCCOUBcjs.getSheetsHost.call(void 0, ).ensureOrgId(organizationId);
|
|
459
|
+
const { xlsxToUniverWorkbook: xlsxToUniverWorkbook2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./xlsx-to-univer-AQAXU3TC.cjs")));
|
|
460
|
+
const droppedOnImport = [];
|
|
461
|
+
const { uploadImportedImage } = await Promise.resolve().then(() => _interopRequireWildcard(require("./matrxImagePorts-JDFYE4QI.cjs")));
|
|
462
|
+
const snapshot = await xlsxToUniverWorkbook2(file, {
|
|
463
|
+
uploadImage: uploadImportedImage,
|
|
464
|
+
onDropped: (what) => droppedOnImport.push(what)
|
|
465
|
+
});
|
|
466
|
+
let originalFileId;
|
|
467
|
+
try {
|
|
468
|
+
const uploaded = await _chunkZDZCCOUBcjs.getSheetsHost.call(void 0, ).uploadOriginalFile(file, { folderPath: "Workbooks/Imports" });
|
|
469
|
+
originalFileId = uploaded.fileId;
|
|
470
|
+
} catch (uploadErr) {
|
|
471
|
+
console.warn(
|
|
472
|
+
"Workbook import: stashing original failed; continuing without link.",
|
|
473
|
+
uploadErr
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
const cleanName = file.name.replace(/\.[^.]+$/, "") || "Imported workbook";
|
|
477
|
+
const created = await _chunkZDZCCOUBcjs.createWorkbook.call(void 0, {
|
|
478
|
+
name: cleanName,
|
|
479
|
+
description: `Imported from ${file.name}`,
|
|
480
|
+
source: file.name.toLowerCase().endsWith(".csv") ? "imported_csv" : "imported_xlsx",
|
|
481
|
+
organizationId: capturedOrganizationId,
|
|
482
|
+
...originalFileId ? { originalFileId } : {}
|
|
483
|
+
});
|
|
484
|
+
if (_core.isServiceFailure.call(void 0, created)) throw new Error(created.error);
|
|
485
|
+
const saved = await _chunkZDZCCOUBcjs.saveSnapshot.call(void 0, {
|
|
486
|
+
workbookId: created.data.id,
|
|
487
|
+
snapshot,
|
|
488
|
+
origin: "imported",
|
|
489
|
+
label: file.name
|
|
490
|
+
});
|
|
491
|
+
if (_core.isServiceFailure.call(void 0, saved)) {
|
|
492
|
+
await _chunkZDZCCOUBcjs.discardFailedWorkbook.call(void 0, created.data.id);
|
|
493
|
+
throw new Error(saved.error);
|
|
494
|
+
}
|
|
495
|
+
return { id: created.data.id, name: cleanName, notCarried: droppedOnImport };
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
exports.H_ALIGN_IN = _chunkQZE7HBZBcjs.H_ALIGN_IN; exports.H_ALIGN_OUT = _chunkQZE7HBZBcjs.H_ALIGN_OUT; exports.RESOURCE = _chunkQZE7HBZBcjs.RESOURCE; exports.V_ALIGN_IN = _chunkQZE7HBZBcjs.V_ALIGN_IN; exports.V_ALIGN_OUT = _chunkQZE7HBZBcjs.V_ALIGN_OUT; exports.a1 = _chunkQZE7HBZBcjs.a1; exports.argbToColor = _chunkQZE7HBZBcjs.argbToColor; exports.borderFromExcel = _chunkQZE7HBZBcjs.borderFromExcel; exports.borderToExcel = _chunkQZE7HBZBcjs.borderToExcel; exports.buildXlsxFromUniver = buildXlsxFromUniver; exports.colCharsToPx = _chunkQZE7HBZBcjs.colCharsToPx; exports.colPxToChars = _chunkQZE7HBZBcjs.colPxToChars; exports.colorToArgb = _chunkQZE7HBZBcjs.colorToArgb; exports.downloadUniverAsXlsx = downloadUniverAsXlsx; exports.importWorkbookFile = importWorkbookFile; exports.parseA1Range = _chunkQZE7HBZBcjs.parseA1Range; exports.rangeToA1 = _chunkQZE7HBZBcjs.rangeToA1; exports.readResource = _chunkQZE7HBZBcjs.readResource; exports.rowPtToPx = _chunkQZE7HBZBcjs.rowPtToPx; exports.rowPxToPt = _chunkQZE7HBZBcjs.rowPxToPt; exports.univerSnapshotToRegisteredXlsxBytes = univerSnapshotToRegisteredXlsxBytes; exports.univerSnapshotToWorkbookJson = univerSnapshotToWorkbookJson; exports.univerSnapshotToXlsxBytes = univerSnapshotToXlsxBytes; exports.unsupportedFileReason = unsupportedFileReason; exports.writeResource = _chunkQZE7HBZBcjs.writeResource; exports.xlsxToUniverWorkbook = _chunkQZE7HBZBcjs.xlsxToUniverWorkbook;
|
|
525
|
+
//# sourceMappingURL=sheets-xlsx.cjs.map
|