textmode.export.js 1.8.1 → 1.9.0-beta.2

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.
Files changed (54) hide show
  1. package/README.md +11 -2
  2. package/dist/textmode.document.esm.js +1 -0
  3. package/dist/textmode.export.esm.js +1 -1
  4. package/dist/textmode.export.umd.js +1 -1
  5. package/dist/types/document/constants.d.ts +32 -0
  6. package/dist/types/document/decode-shapes.d.ts +4 -0
  7. package/dist/types/document/decode.d.ts +5 -0
  8. package/dist/types/document/index.d.ts +13 -0
  9. package/dist/types/document/parse.d.ts +3 -0
  10. package/dist/types/document/types.d.ts +209 -0
  11. package/dist/types/document/validation.d.ts +37 -0
  12. package/dist/types/exporters/base/FileHandler.d.ts +1 -14
  13. package/dist/types/exporters/base/FilenamePolicy.d.ts +6 -0
  14. package/dist/types/exporters/base/LayerTarget.d.ts +0 -2
  15. package/dist/types/exporters/base/frame-sequence/ExclusiveCaptureGate.d.ts +7 -0
  16. package/dist/types/exporters/{video/VideoFrameSchedule.d.ts → base/frame-sequence/FrameSchedule.d.ts} +2 -2
  17. package/dist/types/exporters/{video/VideoFrameDriver.d.ts → base/frame-sequence/FrameSequenceDriver.d.ts} +5 -11
  18. package/dist/types/exporters/base/frame-sequence/errors.d.ts +12 -0
  19. package/dist/types/exporters/base/frame-sequence/index.d.ts +5 -0
  20. package/dist/types/exporters/base/frame-sequence/types.d.ts +20 -0
  21. package/dist/types/exporters/base/frame-sequence/withAbortableTimeout.d.ts +1 -0
  22. package/dist/types/exporters/base/index.d.ts +3 -0
  23. package/dist/types/exporters/gif/GIFExporter.d.ts +1 -1
  24. package/dist/types/exporters/gif/index.d.ts +0 -1
  25. package/dist/types/exporters/gif/types.d.ts +0 -10
  26. package/dist/types/exporters/image/types.d.ts +0 -2
  27. package/dist/types/exporters/json/JSONExporter.d.ts +2 -2
  28. package/dist/types/exporters/json/types.d.ts +14 -204
  29. package/dist/types/exporters/svg/types.d.ts +1 -3
  30. package/dist/types/exporters/txt/types.d.ts +0 -2
  31. package/dist/types/exporters/video/VideoExporter.d.ts +1 -2
  32. package/dist/types/exporters/video/errors.d.ts +1 -0
  33. package/dist/types/exporters/video/types.d.ts +3 -35
  34. package/dist/types/exporters/zip/FrameSerializerRegistry.d.ts +4 -0
  35. package/dist/types/exporters/zip/ZIPArchiveWriter.d.ts +21 -0
  36. package/dist/types/exporters/zip/ZIPExporter.d.ts +32 -0
  37. package/dist/types/exporters/zip/ZIPManifest.d.ts +12 -0
  38. package/dist/types/exporters/zip/errors.d.ts +13 -0
  39. package/dist/types/exporters/zip/index.d.ts +3 -0
  40. package/dist/types/exporters/zip/types.d.ts +170 -0
  41. package/dist/types/index.d.ts +5 -24
  42. package/dist/types/runtime/TextmodeExportController.d.ts +3 -0
  43. package/dist/types/types.d.ts +43 -24
  44. package/package.json +50 -11
  45. package/protocol/textmode-document/2.0/SPECIFICATION.md +233 -0
  46. package/protocol/textmode-document/2.0/fixture.d.ts +3 -0
  47. package/protocol/textmode-document/2.0/fixtures/textmode-document-all-v2.json +94 -0
  48. package/protocol/textmode-document/2.0/fixtures/textmode-document-create-integration-v2.json +112 -0
  49. package/protocol/textmode-document/2.0/fixtures/textmode-document-selected-v2.json +86 -0
  50. package/protocol/textmode-document/2.0/fixtures/textmode-layer-all-v1.1.json +46 -0
  51. package/protocol/textmode-document/2.0/fixtures/textmode-layer-selected-v1.json +38 -0
  52. package/protocol/textmode-document/2.0/textmode-document-2.0.schema.d.ts +3 -0
  53. package/protocol/textmode-document/2.0/textmode-document-2.0.schema.json +171 -0
  54. package/dist/types/exporters/gif/GIFRecorder.d.ts +0 -23
@@ -1,225 +1,37 @@
1
1
  import type { LayerExportOptions } from '../base';
2
+ import type { JSONCellTransform, JSONExportTarget, JSONRGBAColor } from '../../document';
2
3
  /**
3
- * Target scope for JSON export.
4
- *
5
- * @category JSON document data
6
- *
7
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONExportTarget | JSONExportTarget API reference}
8
- */
9
- export type JSONExportTarget = 'selected' | 'all';
10
- /**
11
- * Canonical JSON document format identifier.
12
- *
13
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONDocumentFormat | JSONDocumentFormat API reference}
14
- */
15
- export type JSONDocumentFormat = 'textmode.document';
16
- /**
17
- * Canonical JSON document format version.
18
- *
19
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONDocumentVersion | JSONDocumentVersion API reference}
20
- */
21
- export type JSONDocumentVersion = '2.0.0';
22
- /**
23
- * Supported JSON color output modes.
24
- *
25
- * @category JSON document data
4
+ * Color representation written by the JSON exporter: hexadecimal strings or
5
+ * RGBA channel objects.
26
6
  *
27
7
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONExportColorMode | JSONExportColorMode API reference}
28
8
  */
29
9
  export type JSONExportColorMode = 'hex' | 'rgba';
10
+ export type { JSONCellCollection, JSONCellTransform, JSONColorValue, JSONDocumentFormat, JSONDocumentVersion, JSONExportMetadata, JSONExportTarget, JSONLayerGrid, JSONObjectRowCell, JSONObjectRowsCellCollection, JSONRGBAColor, TextmodeAllDocumentJSON, TextmodeDocumentJSON, TextmodeDocumentLayer, TextmodeSelectedDocumentJSON, TextmodeSelectedDocumentLayer, } from '../../document';
30
11
  /**
31
- * RGBA color representation used in JSON exports.
32
- *
33
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/JSONRGBAColor | JSONRGBAColor API reference}
34
- */
35
- export interface JSONRGBAColor {
36
- r: number;
37
- g: number;
38
- b: number;
39
- a: number;
40
- }
41
- /**
42
- * Color value used in the exported JSON document.
43
- *
44
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONColorValue | JSONColorValue API reference}
45
- */
46
- export type JSONColorValue = string | JSONRGBAColor;
47
- /**
48
- * Cell transform data for JSON exports.
49
- *
50
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/JSONCellTransform | JSONCellTransform API reference}
51
- */
52
- export interface JSONCellTransform {
53
- invert: boolean;
54
- flipX: boolean;
55
- flipY: boolean;
56
- rotation: number;
57
- }
58
- /**
59
- * Rich per-cell representation for readable JSON exports.
60
- *
61
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/JSONObjectRowCell | JSONObjectRowCell API reference}
62
- */
63
- export interface JSONObjectRowCell {
64
- x: number;
65
- y: number;
66
- character: string;
67
- foreground: JSONColorValue;
68
- background: JSONColorValue;
69
- transform: JSONCellTransform;
70
- }
71
- /**
72
- * Row-based cell encoding.
73
- *
74
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/JSONObjectRowsCellCollection | JSONObjectRowsCellCollection API reference}
75
- */
76
- export interface JSONObjectRowsCellCollection {
77
- encoding: 'object-rows-v1';
78
- rows: JSONObjectRowCell[][];
79
- }
80
- /**
81
- * Supported JSON cell collection variants.
82
- *
83
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONCellCollection | JSONCellCollection API reference}
84
- */
85
- export type JSONCellCollection = JSONObjectRowsCellCollection;
86
- /**
87
- * Grid dimensions exported for a layer.
88
- *
89
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/JSONLayerGrid | JSONLayerGrid API reference}
90
- */
91
- export interface JSONLayerGrid {
92
- cols: number;
93
- rows: number;
94
- cellWidth: number;
95
- cellHeight: number;
96
- }
97
- /**
98
- * Optional export metadata.
99
- *
100
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/JSONExportMetadata | JSONExportMetadata API reference}
101
- */
102
- export interface JSONExportMetadata {
103
- createdAt: string;
104
- generator: {
105
- name: 'textmode.export.js';
106
- version: string;
107
- };
108
- }
109
- /**
110
- * Selected-layer entry in a JSON document export.
111
- *
112
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/TextmodeSelectedDocumentLayer | TextmodeSelectedDocumentLayer API reference}
113
- */
114
- export interface TextmodeSelectedDocumentLayer {
115
- id: string;
116
- cells: JSONCellCollection;
117
- }
118
- /**
119
- * Selected-layer document exported by the JSON exporter.
120
- *
121
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/TextmodeSelectedDocumentJSON | TextmodeSelectedDocumentJSON API reference}
122
- */
123
- export interface TextmodeSelectedDocumentJSON {
124
- format: JSONDocumentFormat;
125
- formatVersion: JSONDocumentVersion;
126
- target: 'selected';
127
- metadata?: JSONExportMetadata;
128
- canvas: {
129
- width: number;
130
- height: number;
131
- };
132
- grid: JSONLayerGrid;
133
- layer: TextmodeSelectedDocumentLayer;
134
- }
135
- /**
136
- * Single layer entry in an all-layers JSON export.
137
- *
138
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/TextmodeDocumentLayer | TextmodeDocumentLayer API reference}
139
- */
140
- export interface TextmodeDocumentLayer {
141
- id: string;
142
- visible: boolean;
143
- opacity: number;
144
- blendMode: string;
145
- offsetX: number;
146
- offsetY: number;
147
- rotationZ: number;
148
- grid: JSONLayerGrid;
149
- cells: JSONCellCollection;
150
- }
151
- /**
152
- * Layer stack document exported by the JSON exporter.
153
- *
154
- * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/TextmodeAllDocumentJSON | TextmodeAllDocumentJSON API reference}
155
- */
156
- export interface TextmodeAllDocumentJSON {
157
- format: JSONDocumentFormat;
158
- formatVersion: JSONDocumentVersion;
159
- target: 'all';
160
- metadata?: JSONExportMetadata;
161
- canvas: {
162
- width: number;
163
- height: number;
164
- };
165
- layers: TextmodeDocumentLayer[];
166
- }
167
- /**
168
- * JSON document exported by the JSON exporter.
169
- *
170
- * @category JSON document data
171
- *
172
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/TextmodeDocumentJSON | TextmodeDocumentJSON API reference}
173
- */
174
- export type TextmodeDocumentJSON = TextmodeSelectedDocumentJSON | TextmodeAllDocumentJSON;
175
- /**
176
- * Options for exporting the textmode content to JSON format.
177
- *
178
- * @category JSON document data
12
+ * Options for exporting textmode content to JSON.
179
13
  *
180
14
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONExportOptions | JSONExportOptions API reference}
181
15
  */
182
16
  export type JSONExportOptions = LayerExportOptions & {
183
17
  /**
184
- * Scope of the JSON export.
185
- *
186
- * Use `'selected'` to export one layer, or `'all'` to export the base layer and every user-created layer.
187
- *
188
- * Defaults to `'selected'`.
18
+ * Export one selected layer or the complete layer stack.
19
+ * Defaults to `selected`.
189
20
  */
190
21
  target?: JSONExportTarget;
191
- /**
192
- * The filename to save the JSON file as.
193
- *
194
- * If not provided, a default filename is used.
195
- */
22
+ /** Filename used by the download helper. A default name is used when omitted. */
196
23
  filename?: string;
197
24
  /**
198
- * Pretty-print the generated JSON.
199
- *
200
- * When set to `true`, output uses two-space indentation.
201
- * When set to a number, that value is used as indentation width.
202
- * When `false`, the output is minified.
203
- *
204
- * Defaults to `true`.
25
+ * Pretty-print with two spaces when `true`, use the given indentation width
26
+ * when numeric, or produce compact JSON when `false`. Defaults to `true`.
205
27
  */
206
28
  pretty?: boolean | number;
207
- /**
208
- * Color representation used for foreground and background values.
209
- *
210
- * Defaults to `'hex'`.
211
- */
29
+ /** Foreground and background color representation. Defaults to `hex`. */
212
30
  colorMode?: JSONExportColorMode;
213
- /**
214
- * Whether to include export metadata such as timestamp and generator details.
215
- *
216
- * Defaults to `true`.
217
- */
31
+ /** Include the creation timestamp and generator metadata. Defaults to `true`. */
218
32
  includeMetadata?: boolean;
219
33
  };
220
- /**
221
- * Internal options used by JSON generation (with all defaults applied).
222
- */
34
+ /** Internal JSON generation options after defaults have been applied. */
223
35
  export interface JSONGenerationOptions {
224
36
  target: JSONExportTarget;
225
37
  pretty: boolean | number;
@@ -228,9 +40,7 @@ export interface JSONGenerationOptions {
228
40
  filename?: string;
229
41
  layer?: LayerExportOptions['layer'];
230
42
  }
231
- /**
232
- * Internal extracted cell data used while building the JSON document.
233
- */
43
+ /** Internal framebuffer cell data used while building a document. */
234
44
  export interface JSONCellData {
235
45
  x: number;
236
46
  y: number;
@@ -1,4 +1,4 @@
1
- import type { LayerExportOptions } from '../base';
1
+ import type { LayerExportOptions } from '../base/LayerTarget';
2
2
  /**
3
3
  * RGBA color representation.
4
4
  */
@@ -54,8 +54,6 @@ export interface FramebufferData {
54
54
  /**
55
55
  * Options for exporting the textmode content to SVG format.
56
56
  *
57
- * @category Layer data export
58
- *
59
57
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/SVGExportOptions | SVGExportOptions API reference}
60
58
  */
61
59
  export type SVGExportOptions = LayerExportOptions & {
@@ -2,8 +2,6 @@ import type { LayerExportOptions } from '../base';
2
2
  /**
3
3
  * Options for exporting the textmode content to TXT format.
4
4
  *
5
- * @category Layer data export
6
- *
7
5
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/TXTExportOptions | TXTExportOptions API reference}
8
6
  */
9
7
  export type TXTExportOptions = LayerExportOptions & {
@@ -1,5 +1,5 @@
1
1
  import type { Textmodifier } from 'textmode.js';
2
- import { type PostDrawSubscription } from './VideoFrameDriver';
2
+ import { type PostDrawSubscription } from '../base';
3
3
  import type { VideoExportOptions } from './types';
4
4
  /** Main video exporter for the textmode.js library. */
5
5
  export declare class VideoExporter {
@@ -20,6 +20,5 @@ export declare class VideoExporter {
20
20
  private _hardwareAcceleration;
21
21
  private _keyFrameInterval;
22
22
  private _currentPixelDensity;
23
- private _withExtension;
24
23
  private _createFileSystemDestination;
25
24
  }
@@ -7,3 +7,4 @@ export declare class VideoExportError extends Error {
7
7
  export declare function createAbortError(): VideoExportError;
8
8
  export declare function createTimeoutError(message: string, cause?: unknown): VideoExportError;
9
9
  export declare function isAbortError(error: unknown): boolean;
10
+ export declare function normalizeVideoExportError(error: unknown): VideoExportError;
@@ -1,9 +1,7 @@
1
- import type { PrepareExportFrame } from '../base';
1
+ import type { FrameSequenceDriverLike, FrameSequenceRenderOptions, PrepareExportFrame } from '../base';
2
2
  /**
3
3
  * High-level lifecycle state reported while a video export is captured, encoded, or completed.
4
4
  *
5
- * @category Video export
6
- *
7
5
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoRecordingState | VideoRecordingState API reference}
8
6
  */
9
7
  export type VideoRecordingState = 'idle' | 'recording' | 'encoding' | 'completed' | 'error';
@@ -14,8 +12,6 @@ export type VideoRecordingState = 'idle' | 'recording' | 'encoding' | 'completed
14
12
  * for buffered output. `rendering`, `encoding`, and `draining` remain available for compatibility with older progress
15
13
  * producers.
16
14
  *
17
- * @category Video export
18
- *
19
15
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportPhase | VideoExportPhase API reference}
20
16
  */
21
17
  export type VideoExportPhase = 'probing' | 'rendering' | 'capturing' | 'encoding' | 'draining' | 'writing' | 'finalizing';
@@ -26,8 +22,6 @@ export type VideoCodec = 'vp8' | 'vp9' | 'avc' | (string & {});
26
22
  * Higher levels generally preserve more detail and produce larger, content-dependent files. Mediabunny may use
27
23
  * quantizer-based encoding or a codec-adjusted bitrate, depending on codec and browser support.
28
24
  *
29
- * @category Video export
30
- *
31
25
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoQualityLevel | VideoQualityLevel API reference}
32
26
  */
33
27
  export type VideoQualityLevel = 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
@@ -49,8 +43,6 @@ export type VideoQualityLevel = 'very-low' | 'low' | 'medium' | 'high' | 'very-h
49
43
  * await t.saveVideo({ quality: { bitrate: 8_000_000, bitrateMode: 'constant' } });
50
44
  * ```
51
45
  *
52
- * @category Video export
53
- *
54
46
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoQuality | VideoQuality API reference}
55
47
  */
56
48
  export type VideoQuality = VideoQualityLevel | {
@@ -66,8 +58,6 @@ export type VideoQuality = VideoQualityLevel | {
66
58
  *
67
59
  * This setting does not affect `toVideoBlob()`, which always returns an in-memory `Blob`.
68
60
  *
69
- * @category Video export
70
- *
71
61
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoSaveDestination | VideoSaveDestination API reference}
72
62
  */
73
63
  export type VideoSaveDestination = 'download' | 'file-system';
@@ -77,8 +67,6 @@ export type VideoSaveDestination = 'download' | 'file-system';
77
67
  * MP4 uses AVC/H.264 and requires even coded dimensions. WebM selects VP9 when available and falls back to VP8; it
78
68
  * is the only format that can be requested with transparency.
79
69
  *
80
- * @category Video export
81
- *
82
70
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportFormat | VideoExportFormat API reference}
83
71
  */
84
72
  export type VideoExportFormat = 'webm' | 'mp4';
@@ -92,8 +80,6 @@ export type VideoExportFormat = 'webm' | 'mp4';
92
80
  *
93
81
  * If omitted for an explicit target bitrate, Mediabunny uses `'variable'`.
94
82
  *
95
- * @category Video export
96
- *
97
83
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoBitrateMode | VideoBitrateMode API reference}
98
84
  */
99
85
  export type VideoBitrateMode = 'variable' | 'constant';
@@ -106,8 +92,6 @@ export type VideoBitrateMode = 'variable' | 'constant';
106
92
  * availability and output characteristics vary by device.
107
93
  * - `'prefer-software'`: prefer CPU encoding, often more consistent across machines, but usually slower.
108
94
  *
109
- * @category Video export
110
- *
111
95
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoHardwareAcceleration | VideoHardwareAcceleration API reference}
112
96
  */
113
97
  export type VideoHardwareAcceleration = 'no-preference' | 'prefer-hardware' | 'prefer-software';
@@ -115,8 +99,6 @@ export type VideoExportErrorCode = 'VIDEO_EXPORT_UNSUPPORTED' | 'VIDEO_CODEC_UNS
115
99
  /**
116
100
  * Progress information emitted while a deterministic video is probed, captured, and written.
117
101
  *
118
- * @category Video export
119
- *
120
102
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress | VideoExportProgress API reference}
121
103
  */
122
104
  export type VideoExportProgress = {
@@ -192,8 +174,6 @@ export type VideoExportProgress = {
192
174
  /**
193
175
  * Options for capturing deterministic textmode frames as MP4 or WebM video.
194
176
  *
195
- * @category Video export
196
- *
197
177
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions | VideoExportOptions API reference}
198
178
  */
199
179
  export type VideoExportOptions = {
@@ -325,17 +305,5 @@ export interface VideoEncodingPlan {
325
305
  height: number;
326
306
  transparent: boolean;
327
307
  }
328
- export interface VideoRenderFrameOptions {
329
- frameCount: number;
330
- frameRate: number;
331
- signal?: AbortSignal;
332
- prepareFrame?: PrepareExportFrame;
333
- onFrame(frame: {
334
- frameIndex: number;
335
- canvas: HTMLCanvasElement;
336
- }): Promise<void> | void;
337
- }
338
- export interface VideoFrameDriverLike {
339
- readonly canvas: HTMLCanvasElement;
340
- $render(options: VideoRenderFrameOptions): Promise<void>;
341
- }
308
+ export type VideoRenderFrameOptions = FrameSequenceRenderOptions;
309
+ export type VideoFrameDriverLike = FrameSequenceDriverLike;
@@ -0,0 +1,4 @@
1
+ import type { Textmodifier } from 'textmode.js';
2
+ import type { ZIPFrameFormat, ZIPFrameSerializer } from './types';
3
+ /** Resolves the thin adapter for one supported ZIP frame format. */
4
+ export declare function createZIPFrameSerializerRegistry(textmodifier: Textmodifier): Record<ZIPFrameFormat, ZIPFrameSerializer>;
@@ -0,0 +1,21 @@
1
+ import type { ZIPEntryCompression } from './types';
2
+ /** Streaming ZIP wrapper that retains only compressed archive output chunks. */
3
+ export declare class ZIPArchiveWriter {
4
+ private readonly _archive;
5
+ private readonly _chunks;
6
+ private readonly _entryNames;
7
+ private readonly _modifiedAt;
8
+ private readonly _maxArchiveBytes;
9
+ private _state;
10
+ private _archiveBytes;
11
+ private _failure;
12
+ private _resolveFinal?;
13
+ private _rejectFinal?;
14
+ constructor(modifiedAt: Date, maxArchiveBytes?: number);
15
+ $addEntry(path: string, data: Uint8Array, compression: ZIPEntryCompression): Promise<void>;
16
+ $finalize(): Promise<Blob>;
17
+ $abort(reason?: unknown): void;
18
+ private _assertOpen;
19
+ private _validateEntryPath;
20
+ private _fail;
21
+ }
@@ -0,0 +1,32 @@
1
+ import type { Textmodifier } from 'textmode.js';
2
+ import { type FrameSequenceDriverLike, type PostDrawSubscription } from '../base';
3
+ import type { ZIPExportOptions, ZIPFrameFormat, ZIPFrameSerializer } from './types';
4
+ interface ZIPExporterDependencies {
5
+ createDriver?: () => FrameSequenceDriverLike;
6
+ createWriter?: (createdAt: Date) => ZIPArchiveWriterLike;
7
+ resolveSerializer?: (format: ZIPFrameFormat) => ZIPFrameSerializer;
8
+ now?: () => Date;
9
+ }
10
+ interface ZIPArchiveWriterLike {
11
+ $addEntry(path: string, data: Uint8Array, compression: 'store' | 'deflate'): Promise<void>;
12
+ $finalize(): Promise<Blob>;
13
+ $abort(reason?: unknown): void;
14
+ }
15
+ /** Captures deterministic frames and archives them in capture order. */
16
+ export declare class ZIPExporter {
17
+ private readonly _textmodifier;
18
+ private readonly _registerPostDrawHook;
19
+ private readonly _dependencies;
20
+ constructor(_textmodifier: Textmodifier, _registerPostDrawHook: PostDrawSubscription, dependencies?: ZIPExporterDependencies);
21
+ $saveZIP(options: ZIPExportOptions): Promise<void>;
22
+ /** Generates a deterministic ZIP archive without initiating a download. */
23
+ $generateZIPBlob(options: ZIPExportOptions): Promise<Blob>;
24
+ private _export;
25
+ private _executeExport;
26
+ private _validateAndNormalize;
27
+ private _emitProgress;
28
+ private _progressFrameCount;
29
+ private _throwIfAborted;
30
+ private _yieldToBrowser;
31
+ }
32
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { ZIPFrameFormat, ZIPFrameSequenceManifest } from './types';
2
+ export declare function createZIPFramePath(rootStem: string, frameIndex: number, extension: string): string;
3
+ export declare function createZIPManifest(options: {
4
+ createdAt: Date;
5
+ format: ZIPFrameFormat;
6
+ frameCount: number;
7
+ frameRate: number;
8
+ width: number;
9
+ height: number;
10
+ extension: string;
11
+ }): ZIPFrameSequenceManifest;
12
+ export declare function encodeZIPManifest(manifest: ZIPFrameSequenceManifest): Uint8Array;
@@ -0,0 +1,13 @@
1
+ import type { ZIPExportErrorCode } from './types';
2
+ /**
3
+ * Error raised by ZIP frame-sequence validation, capture, or archive creation.
4
+ *
5
+ * @see {@link https://code.textmode.art/api/textmode.export.js/classes/ZIPExportError | ZIPExportError API reference}
6
+ */
7
+ export declare class ZIPExportError extends Error {
8
+ readonly code: ZIPExportErrorCode;
9
+ readonly cause?: unknown;
10
+ constructor(code: ZIPExportErrorCode, message: string, cause?: unknown);
11
+ }
12
+ export declare function createZIPAbortError(cause?: unknown): ZIPExportError;
13
+ export declare function normalizeZIPExportError(error: unknown): ZIPExportError;
@@ -0,0 +1,3 @@
1
+ export { ZIPExporter } from './ZIPExporter';
2
+ export { ZIPExportError } from './errors';
3
+ export type { ZIPCaptureOptions, ZIPExportErrorCode, ZIPExportOptions, ZIPExportProgress, ZIPExportState, ZIPFrameFormat, ZIPFrameOptionsMap, } from './types';
@@ -0,0 +1,170 @@
1
+ import type { PrepareExportFrame } from '../base';
2
+ import type { ImageExportOptions } from '../image';
3
+ import type { JSONExportOptions } from '../json';
4
+ import type { SVGExportOptions } from '../svg';
5
+ import type { TXTExportOptions } from '../txt';
6
+ /**
7
+ * File format used for every frame in a ZIP frame-sequence export.
8
+ *
9
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/ZIPFrameFormat | ZIPFrameFormat API reference}
10
+ */
11
+ export type ZIPFrameFormat = 'png' | 'jpg' | 'webp' | 'svg' | 'json' | 'txt';
12
+ /**
13
+ * Lifecycle state reported by a ZIP frame-sequence export.
14
+ *
15
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/ZIPExportState | ZIPExportState API reference}
16
+ */
17
+ export type ZIPExportState = 'capturing' | 'finalizing' | 'completed' | 'error';
18
+ /**
19
+ * Machine-readable ZIP export failure category.
20
+ *
21
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/ZIPExportErrorCode | ZIPExportErrorCode API reference}
22
+ */
23
+ export type ZIPExportErrorCode = 'ZIP_EXPORT_INVALID_OPTIONS' | 'ZIP_EXPORT_ENCODING_UNSUPPORTED' | 'ZIP_EXPORT_TOO_LARGE' | 'ZIP_EXPORT_ABORTED' | 'ZIP_EXPORT_TIMEOUT' | 'ZIP_EXPORT_BUSY' | 'ZIP_EXPORT_DISPOSED' | 'ZIP_EXPORT_FAILED';
24
+ /**
25
+ * Progress information emitted while ZIP frames are captured and archived.
26
+ *
27
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPExportProgress | ZIPExportProgress API reference}
28
+ */
29
+ export interface ZIPExportProgress {
30
+ /**
31
+ * Current ZIP export state.
32
+ *
33
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPExportProgress#state | ZIPExportProgress.state API reference}
34
+ */
35
+ state: ZIPExportState;
36
+ /**
37
+ * Number of completed frame entries.
38
+ *
39
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPExportProgress#frameindex | ZIPExportProgress.frameIndex API reference}
40
+ */
41
+ frameIndex: number;
42
+ /**
43
+ * Total number of frame entries planned for the archive.
44
+ *
45
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPExportProgress#totalframes | ZIPExportProgress.totalFrames API reference}
46
+ */
47
+ totalFrames: number;
48
+ /**
49
+ * Normalized completed-frame ratio from `0` through `1`.
50
+ *
51
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPExportProgress#progress | ZIPExportProgress.progress API reference}
52
+ */
53
+ progress: number;
54
+ /**
55
+ * Optional failure message for an `error` event.
56
+ *
57
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPExportProgress#message | ZIPExportProgress.message API reference}
58
+ */
59
+ message?: string;
60
+ }
61
+ /**
62
+ * Options shared by all ZIP frame formats.
63
+ *
64
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPCaptureOptions | ZIPCaptureOptions API reference}
65
+ */
66
+ export interface ZIPCaptureOptions {
67
+ /**
68
+ * Target archive filename, with or without `.zip`.
69
+ *
70
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPCaptureOptions#filename | ZIPCaptureOptions.filename API reference}
71
+ */
72
+ filename?: string;
73
+ /**
74
+ * Number of frames to capture. Defaults to `300`.
75
+ *
76
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPCaptureOptions#framecount | ZIPCaptureOptions.frameCount API reference}
77
+ */
78
+ frameCount?: number;
79
+ /**
80
+ * Deterministic sampling rate. Defaults to `60`.
81
+ *
82
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPCaptureOptions#framerate | ZIPCaptureOptions.frameRate API reference}
83
+ */
84
+ frameRate?: number;
85
+ /**
86
+ * Prepares external state before each deterministic redraw.
87
+ *
88
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPCaptureOptions#prepareframe | ZIPCaptureOptions.prepareFrame API reference}
89
+ */
90
+ prepareFrame?: PrepareExportFrame;
91
+ /**
92
+ * Cancels capture, serialization, or archive finalization.
93
+ *
94
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPCaptureOptions#signal | ZIPCaptureOptions.signal API reference}
95
+ */
96
+ signal?: AbortSignal;
97
+ /**
98
+ * Receives capture and archive lifecycle updates.
99
+ *
100
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPCaptureOptions#onprogress | ZIPCaptureOptions.onProgress API reference}
101
+ */
102
+ onProgress?: (progress: ZIPExportProgress) => void;
103
+ }
104
+ /**
105
+ * Format-specific options forwarded to each existing still exporter.
106
+ *
107
+ * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/ZIPFrameOptionsMap | ZIPFrameOptionsMap API reference}
108
+ */
109
+ export interface ZIPFrameOptionsMap {
110
+ png: Omit<ImageExportOptions, 'filename' | 'format'>;
111
+ jpg: Omit<ImageExportOptions, 'filename' | 'format'>;
112
+ webp: Omit<ImageExportOptions, 'filename' | 'format'>;
113
+ svg: Omit<SVGExportOptions, 'filename'>;
114
+ json: Omit<JSONExportOptions, 'filename'>;
115
+ txt: Omit<TXTExportOptions, 'filename'>;
116
+ }
117
+ /**
118
+ * Discriminated options for a deterministic ZIP frame-sequence export.
119
+ *
120
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/ZIPExportOptions | ZIPExportOptions API reference}
121
+ */
122
+ export type ZIPExportOptions = {
123
+ [F in ZIPFrameFormat]: ZIPCaptureOptions & {
124
+ format: F;
125
+ frameOptions?: ZIPFrameOptionsMap[F];
126
+ };
127
+ }[ZIPFrameFormat];
128
+ export interface ZIPGenerationOptions {
129
+ format: ZIPFrameFormat;
130
+ filename?: string;
131
+ frameCount: number;
132
+ frameRate: number;
133
+ frameOptions: unknown;
134
+ prepareFrame?: PrepareExportFrame;
135
+ signal?: AbortSignal;
136
+ onProgress?: (progress: ZIPExportProgress) => void;
137
+ }
138
+ export type ZIPEntryCompression = 'store' | 'deflate';
139
+ export interface ZIPFrameSerializer {
140
+ readonly extension: `.${ZIPFrameFormat}`;
141
+ readonly compression: ZIPEntryCompression;
142
+ getDimensions(context: {
143
+ canvas: HTMLCanvasElement;
144
+ frameOptions: unknown;
145
+ }): {
146
+ width: number;
147
+ height: number;
148
+ };
149
+ serialize(context: {
150
+ canvas: HTMLCanvasElement;
151
+ frameOptions: unknown;
152
+ createdAt: Date;
153
+ }): Promise<Uint8Array>;
154
+ }
155
+ export interface ZIPFrameSequenceManifest {
156
+ schema: 'textmode.frame-sequence';
157
+ schemaVersion: '1.0.0';
158
+ generator: {
159
+ name: 'textmode.export.js';
160
+ version: string;
161
+ };
162
+ createdAt: string;
163
+ format: ZIPFrameFormat;
164
+ frameCount: number;
165
+ frameRate: number;
166
+ width: number;
167
+ height: number;
168
+ indexBase: 1;
169
+ filePattern: string;
170
+ }