@wafflebase/cli 0.4.8 → 0.5.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/dist/bin.js +99693 -11
- package/package.json +7 -6
- package/dist/bin.d.ts +0 -2
- package/dist/client/dry-run.d.ts +0 -5
- package/dist/client/dry-run.js +0 -16
- package/dist/client/http-client.d.ts +0 -59
- package/dist/client/http-client.js +0 -178
- package/dist/commands/api-keys.d.ts +0 -2
- package/dist/commands/api-keys.js +0 -54
- package/dist/commands/cells.d.ts +0 -2
- package/dist/commands/cells.js +0 -108
- package/dist/commands/ctx.d.ts +0 -5
- package/dist/commands/ctx.js +0 -56
- package/dist/commands/docs.d.ts +0 -3
- package/dist/commands/docs.js +0 -320
- package/dist/commands/login.d.ts +0 -2
- package/dist/commands/login.js +0 -220
- package/dist/commands/logout.d.ts +0 -2
- package/dist/commands/logout.js +0 -10
- package/dist/commands/root.d.ts +0 -18
- package/dist/commands/root.js +0 -37
- package/dist/commands/schema.d.ts +0 -2
- package/dist/commands/schema.js +0 -28
- package/dist/commands/sheets-export.d.ts +0 -2
- package/dist/commands/sheets-export.js +0 -52
- package/dist/commands/sheets-import.d.ts +0 -2
- package/dist/commands/sheets-import.js +0 -88
- package/dist/commands/sheets.d.ts +0 -2
- package/dist/commands/sheets.js +0 -17
- package/dist/commands/slides.d.ts +0 -3
- package/dist/commands/slides.js +0 -227
- package/dist/commands/status.d.ts +0 -2
- package/dist/commands/status.js +0 -22
- package/dist/commands/tabs.d.ts +0 -2
- package/dist/commands/tabs.js +0 -20
- package/dist/config/config.d.ts +0 -38
- package/dist/config/config.js +0 -135
- package/dist/config/session.d.ts +0 -49
- package/dist/config/session.js +0 -74
- package/dist/docs/content.d.ts +0 -37
- package/dist/docs/content.js +0 -90
- package/dist/docs/docx-export.d.ts +0 -23
- package/dist/docs/docx-export.js +0 -14
- package/dist/docs/docx-import.d.ts +0 -36
- package/dist/docs/docx-import.js +0 -70
- package/dist/docs/dom-polyfill.d.ts +0 -1
- package/dist/docs/dom-polyfill.js +0 -29
- package/dist/docs/fontkit-measurer.d.ts +0 -41
- package/dist/docs/fontkit-measurer.js +0 -64
- package/dist/docs/image-fetcher.d.ts +0 -37
- package/dist/docs/image-fetcher.js +0 -38
- package/dist/docs/import.d.ts +0 -72
- package/dist/docs/import.js +0 -146
- package/dist/docs/page-range.d.ts +0 -29
- package/dist/docs/page-range.js +0 -74
- package/dist/docs/page-slice.d.ts +0 -45
- package/dist/docs/page-slice.js +0 -61
- package/dist/docs/paginate.d.ts +0 -13
- package/dist/docs/paginate.js +0 -19
- package/dist/docs/pdf-export.d.ts +0 -47
- package/dist/docs/pdf-export.js +0 -95
- package/dist/output/binary.d.ts +0 -37
- package/dist/output/binary.js +0 -47
- package/dist/output/csv.d.ts +0 -4
- package/dist/output/csv.js +0 -25
- package/dist/output/formatter.d.ts +0 -4
- package/dist/output/formatter.js +0 -41
- package/dist/output/json.d.ts +0 -1
- package/dist/output/json.js +0 -3
- package/dist/output/table.d.ts +0 -4
- package/dist/output/table.js +0 -14
- package/dist/schema/registry.d.ts +0 -42
- package/dist/schema/registry.js +0 -375
- package/dist/slides/content.d.ts +0 -41
- package/dist/slides/content.js +0 -122
- package/dist/slides/import.d.ts +0 -82
- package/dist/slides/import.js +0 -170
- package/dist/slides/pptx-export.d.ts +0 -6
- package/dist/slides/pptx-export.js +0 -10
- package/dist/slides/pptx-import.d.ts +0 -35
- package/dist/slides/pptx-import.js +0 -49
- package/dist/util/csv-parse.d.ts +0 -21
- package/dist/util/csv-parse.js +0 -99
package/dist/slides/import.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import type { SlidesDocument, UploadImage } from '@wafflebase/slides/node';
|
|
2
|
-
import { type CliPptxImportOptions } from './pptx-import.js';
|
|
3
|
-
import type { ImportReport } from '@wafflebase/slides/node';
|
|
4
|
-
/**
|
|
5
|
-
* Parsing surface — split out so tests can inject a stub that returns
|
|
6
|
-
* a synthetic `SlidesDocument` without building a real `.pptx` byte
|
|
7
|
-
* buffer. Production callers use the default (`importPptx` from
|
|
8
|
-
* `./pptx-import.js`).
|
|
9
|
-
*/
|
|
10
|
-
export type SlidesImportParser = (buf: Uint8Array, opts?: CliPptxImportOptions) => Promise<{
|
|
11
|
-
document: SlidesDocument;
|
|
12
|
-
report: ImportReport;
|
|
13
|
-
}>;
|
|
14
|
-
/**
|
|
15
|
-
* Minimal HTTP surface `runSlidesImport` needs from the CLI's
|
|
16
|
-
* `HttpClient`. Spelled out so tests can pass a stub without depending
|
|
17
|
-
* on the full client. Mirrors `ImportClient` in `../docs/import.ts`.
|
|
18
|
-
*/
|
|
19
|
-
export interface SlidesImportClient {
|
|
20
|
-
createDocument: (title: string, type?: 'doc' | 'sheet' | 'slides') => Promise<{
|
|
21
|
-
ok: boolean;
|
|
22
|
-
status: number;
|
|
23
|
-
data: unknown;
|
|
24
|
-
}>;
|
|
25
|
-
putSlidesContent: (docId: string, deck: SlidesDocument) => Promise<{
|
|
26
|
-
ok: boolean;
|
|
27
|
-
status: number;
|
|
28
|
-
data: unknown;
|
|
29
|
-
}>;
|
|
30
|
-
}
|
|
31
|
-
export interface SlidesImportIO {
|
|
32
|
-
/** Final structured payload — written to stdout as JSON. */
|
|
33
|
-
stdout: (line: string) => void;
|
|
34
|
-
stderr: (line: string) => void;
|
|
35
|
-
/**
|
|
36
|
-
* Read the pptx bytes for `path`. `'-'` reads from stdin.
|
|
37
|
-
*
|
|
38
|
-
* Split out so tests can inject in-memory buffers without juggling
|
|
39
|
-
* tmp files; the default reads `process.stdin` (or the file
|
|
40
|
-
* synchronously) at the action site.
|
|
41
|
-
*/
|
|
42
|
-
readBytes: (path: string) => Promise<Uint8Array>;
|
|
43
|
-
/**
|
|
44
|
-
* Prompt the user for a yes/no answer when running interactively.
|
|
45
|
-
* Returns `true` for affirmative responses (case-insensitive `y` /
|
|
46
|
-
* `yes`); anything else (including end-of-stream) → `false`.
|
|
47
|
-
*/
|
|
48
|
-
confirm: (prompt: string) => Promise<boolean>;
|
|
49
|
-
/** Whether the current process is interactive (a TTY on stdin). */
|
|
50
|
-
isTTY: boolean;
|
|
51
|
-
}
|
|
52
|
-
export declare const defaultSlidesImportIO: SlidesImportIO;
|
|
53
|
-
export interface RunSlidesImportArgs {
|
|
54
|
-
/** Source path. `'-'` reads from stdin. */
|
|
55
|
-
file: string;
|
|
56
|
-
/** Override the deck title. Falls back to the file basename. */
|
|
57
|
-
title?: string;
|
|
58
|
-
/** Existing document ID to overwrite. Pairs with `--yes`. */
|
|
59
|
-
replace?: string;
|
|
60
|
-
/** Skip the interactive `--replace` confirmation. */
|
|
61
|
-
yes?: boolean;
|
|
62
|
-
/** Override the default base64 image uploader. Tests pass a no-op. */
|
|
63
|
-
uploadImage?: UploadImage;
|
|
64
|
-
/** Suppress informational stderr output (errors still reported). */
|
|
65
|
-
quiet?: boolean;
|
|
66
|
-
/** Print the request that *would* fire instead of issuing it. */
|
|
67
|
-
dryRun?: boolean;
|
|
68
|
-
/** Override the .pptx parser — primarily for tests. */
|
|
69
|
-
parser?: SlidesImportParser;
|
|
70
|
-
}
|
|
71
|
-
export interface RunSlidesImportResult {
|
|
72
|
-
/** Process exit code. The action sets `process.exitCode` accordingly. */
|
|
73
|
-
exitCode: number;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Pure orchestration for `slides import`. Reads the source `.pptx`,
|
|
77
|
-
* parses it into a `SlidesDocument`, then either creates a new deck
|
|
78
|
-
* (default) or overwrites an existing one (`--replace`). Mirrors
|
|
79
|
-
* `runDocsImport` — see that file for the rationale behind the split
|
|
80
|
-
* between this function and the Commander action.
|
|
81
|
-
*/
|
|
82
|
-
export declare function runSlidesImport(args: RunSlidesImportArgs, client: SlidesImportClient, io?: SlidesImportIO): Promise<RunSlidesImportResult>;
|
package/dist/slides/import.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { basename, extname } from 'node:path';
|
|
3
|
-
import { createInterface } from 'node:readline';
|
|
4
|
-
import { importPptx as defaultImportPptx, InvalidPptxError, } from './pptx-import.js';
|
|
5
|
-
export const defaultSlidesImportIO = {
|
|
6
|
-
stdout: (line) => {
|
|
7
|
-
process.stdout.write(line);
|
|
8
|
-
if (!line.endsWith('\n'))
|
|
9
|
-
process.stdout.write('\n');
|
|
10
|
-
},
|
|
11
|
-
stderr: (line) => {
|
|
12
|
-
console.error(line);
|
|
13
|
-
},
|
|
14
|
-
readBytes: async (path) => {
|
|
15
|
-
if (path === '-') {
|
|
16
|
-
return new Promise((resolve, reject) => {
|
|
17
|
-
const chunks = [];
|
|
18
|
-
process.stdin.on('data', (c) => chunks.push(c));
|
|
19
|
-
process.stdin.on('end', () => resolve(new Uint8Array(Buffer.concat(chunks))));
|
|
20
|
-
process.stdin.on('error', reject);
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
return new Uint8Array(readFileSync(path));
|
|
24
|
-
},
|
|
25
|
-
confirm: (prompt) => {
|
|
26
|
-
return new Promise((resolve) => {
|
|
27
|
-
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
28
|
-
rl.question(prompt, (answer) => {
|
|
29
|
-
rl.close();
|
|
30
|
-
const a = answer.trim().toLowerCase();
|
|
31
|
-
resolve(a === 'y' || a === 'yes');
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
},
|
|
35
|
-
isTTY: process.stdin.isTTY ?? false,
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Pure orchestration for `slides import`. Reads the source `.pptx`,
|
|
39
|
-
* parses it into a `SlidesDocument`, then either creates a new deck
|
|
40
|
-
* (default) or overwrites an existing one (`--replace`). Mirrors
|
|
41
|
-
* `runDocsImport` — see that file for the rationale behind the split
|
|
42
|
-
* between this function and the Commander action.
|
|
43
|
-
*/
|
|
44
|
-
export async function runSlidesImport(args, client, io = defaultSlidesImportIO) {
|
|
45
|
-
const { file, replace, yes = false, uploadImage, quiet = false, dryRun = false, parser = defaultImportPptx, } = args;
|
|
46
|
-
const inferredTitle = args.title ?? defaultTitleFor(file);
|
|
47
|
-
if (replace) {
|
|
48
|
-
// `--replace` is destructive: confirm interactively unless `--yes`.
|
|
49
|
-
if (!yes) {
|
|
50
|
-
if (!io.isTTY) {
|
|
51
|
-
io.stderr(JSON.stringify({
|
|
52
|
-
error: {
|
|
53
|
-
code: 'CONFIRMATION_REQ',
|
|
54
|
-
message: `Pass --yes to confirm replacing deck "${replace}".`,
|
|
55
|
-
},
|
|
56
|
-
}, null, 2));
|
|
57
|
-
return { exitCode: 1 };
|
|
58
|
-
}
|
|
59
|
-
const ok = await io.confirm(`This will replace content of ${replace}. Continue? [y/N] `);
|
|
60
|
-
if (!ok) {
|
|
61
|
-
if (!quiet)
|
|
62
|
-
io.stderr('Aborted.');
|
|
63
|
-
return { exitCode: 0 };
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
const buf = await io.readBytes(file);
|
|
67
|
-
const parsed = await safeImportPptx(buf, uploadImage, io, parser);
|
|
68
|
-
if (parsed === null)
|
|
69
|
-
return { exitCode: 1 };
|
|
70
|
-
const { document: deck, report } = parsed;
|
|
71
|
-
if (dryRun) {
|
|
72
|
-
io.stdout(JSON.stringify({
|
|
73
|
-
method: 'PUT',
|
|
74
|
-
path: `/documents/${replace}/content`,
|
|
75
|
-
body: deck,
|
|
76
|
-
report: summariseReport(report),
|
|
77
|
-
}, null, 2));
|
|
78
|
-
return { exitCode: 0 };
|
|
79
|
-
}
|
|
80
|
-
const res = await client.putSlidesContent(replace, deck);
|
|
81
|
-
if (!res.ok) {
|
|
82
|
-
io.stderr(JSON.stringify(res.data ?? { error: { code: 'HTTP_ERROR' } }, null, 2));
|
|
83
|
-
return { exitCode: 1 };
|
|
84
|
-
}
|
|
85
|
-
io.stdout(JSON.stringify({ id: replace, replaced: true, report: summariseReport(report) }, null, 2));
|
|
86
|
-
return { exitCode: 0 };
|
|
87
|
-
}
|
|
88
|
-
// Default flow: POST + PUT.
|
|
89
|
-
const buf = await io.readBytes(file);
|
|
90
|
-
const parsedNew = await safeImportPptx(buf, uploadImage, io, parser);
|
|
91
|
-
if (parsedNew === null)
|
|
92
|
-
return { exitCode: 1 };
|
|
93
|
-
const { document: deck, report } = parsedNew;
|
|
94
|
-
// The parser fills `meta.title` with whatever string the .pptx carries
|
|
95
|
-
// (often "PowerPoint Presentation" or "Imported deck"). The user's
|
|
96
|
-
// `--title` flag is the source of truth for the deck name — keep the
|
|
97
|
-
// Yorkie root's title in lock-step with the Document row so the deck
|
|
98
|
-
// list, editor header, and GET /content all agree.
|
|
99
|
-
deck.meta.title = inferredTitle;
|
|
100
|
-
if (dryRun) {
|
|
101
|
-
io.stdout(JSON.stringify({
|
|
102
|
-
method: 'POST',
|
|
103
|
-
path: '/documents',
|
|
104
|
-
body: { title: inferredTitle, type: 'slides' },
|
|
105
|
-
followUp: { method: 'PUT', path: '/documents/<new-id>/content' },
|
|
106
|
-
report: summariseReport(report),
|
|
107
|
-
}, null, 2));
|
|
108
|
-
return { exitCode: 0 };
|
|
109
|
-
}
|
|
110
|
-
const created = await client.createDocument(inferredTitle, 'slides');
|
|
111
|
-
if (!created.ok) {
|
|
112
|
-
io.stderr(JSON.stringify(created.data ?? { error: { code: 'HTTP_ERROR' } }, null, 2));
|
|
113
|
-
return { exitCode: 1 };
|
|
114
|
-
}
|
|
115
|
-
const newId = created.data?.id;
|
|
116
|
-
if (!newId) {
|
|
117
|
-
io.stderr(JSON.stringify({ error: { code: 'INVALID_RESPONSE', message: 'Server did not return an id' } }, null, 2));
|
|
118
|
-
return { exitCode: 1 };
|
|
119
|
-
}
|
|
120
|
-
const put = await client.putSlidesContent(newId, deck);
|
|
121
|
-
if (!put.ok) {
|
|
122
|
-
io.stderr(JSON.stringify(put.data ?? { error: { code: 'HTTP_ERROR' } }, null, 2));
|
|
123
|
-
return { exitCode: 1 };
|
|
124
|
-
}
|
|
125
|
-
io.stdout(JSON.stringify({ id: newId, title: inferredTitle, report: summariseReport(report) }, null, 2));
|
|
126
|
-
return { exitCode: 0 };
|
|
127
|
-
}
|
|
128
|
-
function defaultTitleFor(file) {
|
|
129
|
-
if (file === '-')
|
|
130
|
-
return 'Untitled';
|
|
131
|
-
return basename(file, extname(file)) || 'Untitled';
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Collect the parser's `ImportReport` counters into a plain object so
|
|
135
|
-
* the CLI can print them as JSON. We surface every counter rather than
|
|
136
|
-
* the `.summary()` string so agentic callers can parse without
|
|
137
|
-
* regex-matching prose.
|
|
138
|
-
*/
|
|
139
|
-
function summariseReport(report) {
|
|
140
|
-
// `tablesFlattened` / `tableMergesIgnored` / `tableBordersApproximated`
|
|
141
|
-
// were retired when the structured-TableElement importer landed
|
|
142
|
-
// (slides-tables P2). Tables now round-trip without lossy fallbacks,
|
|
143
|
-
// so there's no per-table counter to surface — a clean import shows
|
|
144
|
-
// empty parts and the standard "no fallbacks" line.
|
|
145
|
-
return {
|
|
146
|
-
groupsFlattened: report.groupsFlattened,
|
|
147
|
-
textBoxesPreScaled: report.textBoxesPreScaled,
|
|
148
|
-
unknownShapes: report.unknownShapes,
|
|
149
|
-
unknownLayoutTypes: report.unknownLayoutTypes,
|
|
150
|
-
skippedImages: report.skippedImages,
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Run `importPptx` and turn `InvalidPptxError` into a structured stderr
|
|
155
|
-
* body + `null` return so callers can short-circuit with `exitCode: 1`
|
|
156
|
-
* while keeping the rest of the error envelope (`HTTP_ERROR`,
|
|
157
|
-
* `INVALID_RESPONSE`, etc.) consistent.
|
|
158
|
-
*/
|
|
159
|
-
async function safeImportPptx(buf, uploadImage, io, parser) {
|
|
160
|
-
try {
|
|
161
|
-
return await parser(buf, { uploadImage });
|
|
162
|
-
}
|
|
163
|
-
catch (e) {
|
|
164
|
-
if (e instanceof InvalidPptxError) {
|
|
165
|
-
io.stderr(JSON.stringify({ error: { code: e.code, message: e.message } }, null, 2));
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
throw e;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type SlidesDocument } from '@wafflebase/slides/node';
|
|
2
|
-
export interface CliPptxExportOptions {
|
|
3
|
-
/** Blob-returning fetcher (the CLI's shared image fetcher). */
|
|
4
|
-
imageFetcher?: (url: string) => Promise<Blob>;
|
|
5
|
-
}
|
|
6
|
-
export declare function exportPptxCli(deck: SlidesDocument, opts?: CliPptxExportOptions): Promise<Uint8Array>;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { exportPptx } from '@wafflebase/slides/node';
|
|
2
|
-
export async function exportPptxCli(deck, opts = {}) {
|
|
3
|
-
const fetchImage = opts.imageFetcher
|
|
4
|
-
? async (src) => {
|
|
5
|
-
const blob = await opts.imageFetcher(src);
|
|
6
|
-
return { bytes: new Uint8Array(await blob.arrayBuffer()), mime: blob.type || 'image/png' };
|
|
7
|
-
}
|
|
8
|
-
: undefined;
|
|
9
|
-
return exportPptx(deck, { fetchImage });
|
|
10
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import '../docs/dom-polyfill.js';
|
|
2
|
-
import { type ImportPptxResult, type UploadImage } from '@wafflebase/slides/node';
|
|
3
|
-
/**
|
|
4
|
-
* Default `UploadImage` for the CLI: encodes each embedded image as a
|
|
5
|
-
* `data:` URL. Matches the docs CLI's `inlineBase64Uploader` — the
|
|
6
|
-
* frontend treats slide image `src` values as opaque strings, so a
|
|
7
|
-
* self-contained data URL round-trips cleanly through the API and
|
|
8
|
-
* renders without needing the workspace's `/images` endpoint.
|
|
9
|
-
*
|
|
10
|
-
* The trade-off is payload size: a benchmark deck with 25 unique
|
|
11
|
-
* images and 63 references gains roughly the image-byte total to the
|
|
12
|
-
* Yorkie document. Acceptable for a v1 CLI import — power users who
|
|
13
|
-
* want hosted URLs can pass a custom uploader.
|
|
14
|
-
*/
|
|
15
|
-
export declare const inlineBase64SlidesUploader: UploadImage;
|
|
16
|
-
export interface CliPptxImportOptions {
|
|
17
|
-
/** Override the default base64 uploader — primarily for tests. */
|
|
18
|
-
uploadImage?: UploadImage;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Parse a .pptx byte buffer into a `SlidesDocument` via the slides
|
|
22
|
-
* parser. The DOM polyfill side-effect import installs xmldom's
|
|
23
|
-
* `DOMParser` globally so the parser's browser-targeted XML reads work
|
|
24
|
-
* in Node.
|
|
25
|
-
*
|
|
26
|
-
* Throws a wrapped `INVALID_PPTX` error when the underlying parser
|
|
27
|
-
* cannot make sense of the buffer. The CLI command translates that
|
|
28
|
-
* into the documented `{ error.code: 'INVALID_PPTX' }` exit body
|
|
29
|
-
* without leaking implementation details.
|
|
30
|
-
*/
|
|
31
|
-
export declare function importPptx(buf: Uint8Array, opts?: CliPptxImportOptions): Promise<ImportPptxResult>;
|
|
32
|
-
export declare class InvalidPptxError extends Error {
|
|
33
|
-
readonly code = "INVALID_PPTX";
|
|
34
|
-
constructor(message: string);
|
|
35
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import '../docs/dom-polyfill.js';
|
|
2
|
-
import { importPptx as importPptxFromSlides, } from '@wafflebase/slides/node';
|
|
3
|
-
/**
|
|
4
|
-
* Default `UploadImage` for the CLI: encodes each embedded image as a
|
|
5
|
-
* `data:` URL. Matches the docs CLI's `inlineBase64Uploader` — the
|
|
6
|
-
* frontend treats slide image `src` values as opaque strings, so a
|
|
7
|
-
* self-contained data URL round-trips cleanly through the API and
|
|
8
|
-
* renders without needing the workspace's `/images` endpoint.
|
|
9
|
-
*
|
|
10
|
-
* The trade-off is payload size: a benchmark deck with 25 unique
|
|
11
|
-
* images and 63 references gains roughly the image-byte total to the
|
|
12
|
-
* Yorkie document. Acceptable for a v1 CLI import — power users who
|
|
13
|
-
* want hosted URLs can pass a custom uploader.
|
|
14
|
-
*/
|
|
15
|
-
export const inlineBase64SlidesUploader = async (bytes, mime) => {
|
|
16
|
-
const base64 = Buffer.from(bytes).toString('base64');
|
|
17
|
-
const mediaType = mime || 'application/octet-stream';
|
|
18
|
-
return `data:${mediaType};base64,${base64}`;
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Parse a .pptx byte buffer into a `SlidesDocument` via the slides
|
|
22
|
-
* parser. The DOM polyfill side-effect import installs xmldom's
|
|
23
|
-
* `DOMParser` globally so the parser's browser-targeted XML reads work
|
|
24
|
-
* in Node.
|
|
25
|
-
*
|
|
26
|
-
* Throws a wrapped `INVALID_PPTX` error when the underlying parser
|
|
27
|
-
* cannot make sense of the buffer. The CLI command translates that
|
|
28
|
-
* into the documented `{ error.code: 'INVALID_PPTX' }` exit body
|
|
29
|
-
* without leaking implementation details.
|
|
30
|
-
*/
|
|
31
|
-
export async function importPptx(buf, opts = {}) {
|
|
32
|
-
const arrayBuf = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
33
|
-
try {
|
|
34
|
-
return await importPptxFromSlides(arrayBuf, {
|
|
35
|
-
uploadImage: opts.uploadImage ?? inlineBase64SlidesUploader,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
catch (e) {
|
|
39
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
40
|
-
throw new InvalidPptxError(message);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
export class InvalidPptxError extends Error {
|
|
44
|
-
code = 'INVALID_PPTX';
|
|
45
|
-
constructor(message) {
|
|
46
|
-
super(message);
|
|
47
|
-
this.name = 'InvalidPptxError';
|
|
48
|
-
}
|
|
49
|
-
}
|
package/dist/util/csv-parse.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse CSV text into a 2D array of strings.
|
|
3
|
-
*/
|
|
4
|
-
export declare function parseCsv(text: string): string[][];
|
|
5
|
-
/**
|
|
6
|
-
* Convert a 1-based column number to a column label (1→A, 2→B, 27→AA).
|
|
7
|
-
*/
|
|
8
|
-
export declare function toColumnLabel(col: number): string;
|
|
9
|
-
/**
|
|
10
|
-
* Parse a cell reference like "A1" into 1-based row and column numbers.
|
|
11
|
-
*/
|
|
12
|
-
export declare function parseStartRef(ref: string): {
|
|
13
|
-
row: number;
|
|
14
|
-
col: number;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Build a cell map from a 2D array for batch API.
|
|
18
|
-
*/
|
|
19
|
-
export declare function buildCellMap(data: string[][], startRow: number, startCol: number): Record<string, {
|
|
20
|
-
value: string;
|
|
21
|
-
}>;
|
package/dist/util/csv-parse.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse CSV text into a 2D array of strings.
|
|
3
|
-
*/
|
|
4
|
-
export function parseCsv(text) {
|
|
5
|
-
const rows = [];
|
|
6
|
-
let current = '';
|
|
7
|
-
let inQuotes = false;
|
|
8
|
-
let row = [];
|
|
9
|
-
for (let i = 0; i < text.length; i++) {
|
|
10
|
-
const ch = text[i];
|
|
11
|
-
if (inQuotes) {
|
|
12
|
-
if (ch === '"') {
|
|
13
|
-
if (i + 1 < text.length && text[i + 1] === '"') {
|
|
14
|
-
current += '"';
|
|
15
|
-
i++;
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
inQuotes = false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
current += ch;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
else if (ch === '"') {
|
|
26
|
-
inQuotes = true;
|
|
27
|
-
}
|
|
28
|
-
else if (ch === ',') {
|
|
29
|
-
row.push(current);
|
|
30
|
-
current = '';
|
|
31
|
-
}
|
|
32
|
-
else if (ch === '\n' || ch === '\r') {
|
|
33
|
-
if (ch === '\r' && i + 1 < text.length && text[i + 1] === '\n') {
|
|
34
|
-
i++;
|
|
35
|
-
}
|
|
36
|
-
row.push(current);
|
|
37
|
-
current = '';
|
|
38
|
-
if (row.length > 0)
|
|
39
|
-
rows.push(row);
|
|
40
|
-
row = [];
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
current += ch;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
// last field/row
|
|
47
|
-
row.push(current);
|
|
48
|
-
if (row.some((cell) => cell !== ''))
|
|
49
|
-
rows.push(row);
|
|
50
|
-
return rows;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Convert a 1-based column number to a column label (1→A, 2→B, 27→AA).
|
|
54
|
-
*/
|
|
55
|
-
export function toColumnLabel(col) {
|
|
56
|
-
let label = '';
|
|
57
|
-
while (col > 0) {
|
|
58
|
-
const rem = col % 26;
|
|
59
|
-
if (rem === 0) {
|
|
60
|
-
label = 'Z' + label;
|
|
61
|
-
col = Math.floor(col / 26) - 1;
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
label = String.fromCharCode(rem + 64) + label;
|
|
65
|
-
col = Math.floor(col / 26);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return label;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Parse a cell reference like "A1" into 1-based row and column numbers.
|
|
72
|
-
*/
|
|
73
|
-
export function parseStartRef(ref) {
|
|
74
|
-
const match = ref.match(/^([A-Z]+)(\d+)$/i);
|
|
75
|
-
if (!match)
|
|
76
|
-
return { row: 1, col: 1 };
|
|
77
|
-
const letters = match[1].toUpperCase();
|
|
78
|
-
let col = 0;
|
|
79
|
-
for (const ch of letters) {
|
|
80
|
-
col = col * 26 + (ch.charCodeAt(0) - 64);
|
|
81
|
-
}
|
|
82
|
-
return { row: parseInt(match[2], 10), col };
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Build a cell map from a 2D array for batch API.
|
|
86
|
-
*/
|
|
87
|
-
export function buildCellMap(data, startRow, startCol) {
|
|
88
|
-
const cells = {};
|
|
89
|
-
for (let r = 0; r < data.length; r++) {
|
|
90
|
-
for (let c = 0; c < data[r].length; c++) {
|
|
91
|
-
const value = data[r][c];
|
|
92
|
-
if (value === '')
|
|
93
|
-
continue;
|
|
94
|
-
const ref = toColumnLabel(startCol + c) + (startRow + r);
|
|
95
|
-
cells[ref] = { value };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return cells;
|
|
99
|
-
}
|