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
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Canonical format discriminator for textmode document files.
3
+ *
4
+ * @see {@link https://code.textmode.art/api/textmode.export.js/variables/TEXTMODE_DOCUMENT_FORMAT | TEXTMODE_DOCUMENT_FORMAT API reference}
5
+ */
6
+ export declare const TEXTMODE_DOCUMENT_FORMAT: "textmode.document";
7
+ /**
8
+ * Current textmode document schema revision.
9
+ *
10
+ * @see {@link https://code.textmode.art/api/textmode.export.js/variables/TEXTMODE_DOCUMENT_FORMAT_VERSION | TEXTMODE_DOCUMENT_FORMAT_VERSION API reference}
11
+ */
12
+ export declare const TEXTMODE_DOCUMENT_FORMAT_VERSION: "2.0.0";
13
+ /** Legacy format discriminator accepted by the compatibility decoder. */
14
+ export declare const LEGACY_TEXTMODE_LAYER_FORMAT: "textmode.layer";
15
+ /** Legacy selected-layer schema revision. */
16
+ export declare const LEGACY_TEXTMODE_SELECTED_VERSION: "1.0.0";
17
+ /** Legacy layer-stack schema revision. */
18
+ export declare const LEGACY_TEXTMODE_ALL_VERSION: "1.1.0";
19
+ /**
20
+ * Canonical dense row encoding used by textmode document v2.
21
+ *
22
+ * @see {@link https://code.textmode.art/api/textmode.export.js/variables/TEXTMODE_OBJECT_ROWS_ENCODING | TEXTMODE_OBJECT_ROWS_ENCODING API reference}
23
+ */
24
+ export declare const TEXTMODE_OBJECT_ROWS_ENCODING: "object-rows-v1";
25
+ /** Default protocol safety limits. Product-specific limits belong to callers. */
26
+ export declare const DEFAULT_TEXTMODE_DOCUMENT_LIMITS: {
27
+ readonly maxCells: 16777216;
28
+ readonly maxLayers: 4096;
29
+ readonly maxLayerIdLength: 1024;
30
+ readonly maxCharacterLength: 64;
31
+ readonly maxMetadataStringLength: 4096;
32
+ };
@@ -0,0 +1,4 @@
1
+ import type { DecodeContext, UnknownRecord } from './validation';
2
+ import type { CanonicalTextmodeAllDocument, CanonicalTextmodeSelectedDocument } from './types';
3
+ export declare function decodeSelectedDocument(root: UnknownRecord, context: DecodeContext): CanonicalTextmodeSelectedDocument;
4
+ export declare function decodeAllDocument(root: UnknownRecord, context: DecodeContext): CanonicalTextmodeAllDocument;
@@ -0,0 +1,5 @@
1
+ import type { TextmodeDocumentDecodeOptions, TextmodeDocumentDecodeResult, TextmodeDocumentParseResult } from './types';
2
+ /** Decode a parsed JSON value into the canonical textmode document union. */
3
+ export declare function decodeTextmodeDocument(value: unknown, options?: TextmodeDocumentDecodeOptions): TextmodeDocumentDecodeResult;
4
+ /** Parse JSON syntax and decode its value in one convenience call. */
5
+ export declare function parseTextmodeDocumentJSON(json: string, options?: TextmodeDocumentDecodeOptions): TextmodeDocumentParseResult;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Dependency-free textmode document protocol codec.
3
+ *
4
+ * This entry point contains no DOM, renderer, textmode.js, or media encoder
5
+ * dependencies. It decodes every valid v2 document variant; product-specific
6
+ * import policy belongs to callers.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ export { DEFAULT_TEXTMODE_DOCUMENT_LIMITS, LEGACY_TEXTMODE_ALL_VERSION, LEGACY_TEXTMODE_LAYER_FORMAT, LEGACY_TEXTMODE_SELECTED_VERSION, TEXTMODE_DOCUMENT_FORMAT, TEXTMODE_DOCUMENT_FORMAT_VERSION, TEXTMODE_OBJECT_ROWS_ENCODING, } from './constants';
11
+ export { decodeTextmodeDocument, parseTextmodeDocumentJSON } from './decode';
12
+ export { parseJSON } from './parse';
13
+ export type { CanonicalTextmodeAllDocument, CanonicalTextmodeCell, CanonicalTextmodeCellCollection, CanonicalTextmodeDocument, CanonicalTextmodeDocumentLayer, CanonicalTextmodeSelectedDocument, JSONCellCollection, JSONCellTransform, JSONColorValue, JSONDocumentFormat, JSONDocumentVersion, JSONExportMetadata, JSONExportTarget, JSONLayerGrid, JSONObjectRowCell, JSONObjectRowsCellCollection, JSONParseResult, JSONRGBAColor, LegacyTextmodeAllDocumentJSON, LegacyTextmodeSelectedDocumentJSON, TextmodeAllDocumentJSON, TextmodeDocumentDecodeOptions, TextmodeDocumentDecodeResult, TextmodeDocumentCell, TextmodeDocumentCellCollection, TextmodeDocumentCellTransform, TextmodeDocumentColor, TextmodeDocumentError, TextmodeDocumentErrorCode, TextmodeDocumentFormat, TextmodeDocumentGrid, TextmodeDocumentJSON, TextmodeDocumentLayer, TextmodeDocumentLimits, TextmodeDocumentMetadata, TextmodeDocumentParseResult, TextmodeDocumentRGBAColor, TextmodeDocumentTarget, TextmodeDocumentVersion, TextmodeDocumentWarning, TextmodeSelectedDocumentJSON, TextmodeSelectedDocumentLayer, } from './types';
@@ -0,0 +1,3 @@
1
+ import type { JSONParseResult } from './types';
2
+ /** Parse JSON syntax once before routing the resulting value by discriminator. */
3
+ export declare function parseJSON(json: string): JSONParseResult;
@@ -0,0 +1,209 @@
1
+ import type { LEGACY_TEXTMODE_ALL_VERSION, LEGACY_TEXTMODE_LAYER_FORMAT, LEGACY_TEXTMODE_SELECTED_VERSION, TEXTMODE_DOCUMENT_FORMAT, TEXTMODE_DOCUMENT_FORMAT_VERSION, TEXTMODE_OBJECT_ROWS_ENCODING } from './constants';
2
+ /**
3
+ * Scope encoded by a textmode document.
4
+ *
5
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/TextmodeDocumentTarget | TextmodeDocumentTarget API reference}
6
+ */
7
+ export type TextmodeDocumentTarget = 'selected' | 'all';
8
+ /** Format discriminator encoded in a document. */
9
+ export type TextmodeDocumentFormat = typeof TEXTMODE_DOCUMENT_FORMAT;
10
+ /** Current on-disk format version, independent of the npm package version. */
11
+ export type TextmodeDocumentVersion = typeof TEXTMODE_DOCUMENT_FORMAT_VERSION;
12
+ /** RGBA color channels, each an integer from 0 through 255. */
13
+ export interface TextmodeDocumentRGBAColor {
14
+ r: number;
15
+ g: number;
16
+ b: number;
17
+ a: number;
18
+ }
19
+ /** On-disk color notation; decoded colors use RGBA channels. */
20
+ export type TextmodeDocumentColor = string | TextmodeDocumentRGBAColor;
21
+ /** Per-cell transform in degrees. */
22
+ export interface TextmodeDocumentCellTransform {
23
+ invert: boolean;
24
+ flipX: boolean;
25
+ flipY: boolean;
26
+ rotation: number;
27
+ }
28
+ /** Cell at its redundant row-major x/y coordinates. */
29
+ export interface TextmodeDocumentCell {
30
+ x: number;
31
+ y: number;
32
+ character: string;
33
+ foreground: TextmodeDocumentColor;
34
+ background: TextmodeDocumentColor;
35
+ transform: TextmodeDocumentCellTransform;
36
+ }
37
+ /** Dense row-major cell collection. */
38
+ export interface TextmodeDocumentCellCollection {
39
+ encoding: typeof TEXTMODE_OBJECT_ROWS_ENCODING;
40
+ rows: TextmodeDocumentCell[][];
41
+ }
42
+ /** Logical grid dimensions and pixel extent of each cell. */
43
+ export interface TextmodeDocumentGrid {
44
+ cols: number;
45
+ rows: number;
46
+ cellWidth: number;
47
+ cellHeight: number;
48
+ }
49
+ /** Optional producer information; it does not control decoding behavior. */
50
+ export interface TextmodeDocumentMetadata {
51
+ createdAt: string;
52
+ generator: {
53
+ name: string;
54
+ version: string;
55
+ };
56
+ }
57
+ /**
58
+ * Scope selected by the JSON exporter.
59
+ *
60
+ * @deprecated Use TextmodeDocumentTarget.
61
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/JSONExportTarget | JSONExportTarget API reference}
62
+ */
63
+ export type JSONExportTarget = TextmodeDocumentTarget;
64
+ /** @deprecated Use TextmodeDocumentFormat. */
65
+ export type JSONDocumentFormat = TextmodeDocumentFormat;
66
+ /** @deprecated Use TextmodeDocumentVersion. */
67
+ export type JSONDocumentVersion = TextmodeDocumentVersion;
68
+ /** @deprecated Use TextmodeDocumentRGBAColor. */
69
+ export type JSONRGBAColor = TextmodeDocumentRGBAColor;
70
+ /** @deprecated Use TextmodeDocumentColor. */
71
+ export type JSONColorValue = TextmodeDocumentColor;
72
+ /** @deprecated Use TextmodeDocumentCellTransform. */
73
+ export type JSONCellTransform = TextmodeDocumentCellTransform;
74
+ /** @deprecated Use TextmodeDocumentCell. */
75
+ export type JSONObjectRowCell = TextmodeDocumentCell;
76
+ /** @deprecated Use TextmodeDocumentCellCollection. */
77
+ export type JSONObjectRowsCellCollection = TextmodeDocumentCellCollection;
78
+ /** @deprecated Use TextmodeDocumentCellCollection. */
79
+ export type JSONCellCollection = TextmodeDocumentCellCollection;
80
+ /** @deprecated Use TextmodeDocumentGrid. */
81
+ export type JSONLayerGrid = TextmodeDocumentGrid;
82
+ /** @deprecated Use TextmodeDocumentMetadata. */
83
+ export type JSONExportMetadata = TextmodeDocumentMetadata;
84
+ export interface TextmodeSelectedDocumentLayer {
85
+ id: string;
86
+ cells: JSONCellCollection;
87
+ }
88
+ export interface TextmodeSelectedDocumentJSON {
89
+ format: JSONDocumentFormat;
90
+ formatVersion: JSONDocumentVersion;
91
+ target: 'selected';
92
+ metadata?: JSONExportMetadata;
93
+ canvas: {
94
+ width: number;
95
+ height: number;
96
+ };
97
+ grid: JSONLayerGrid;
98
+ layer: TextmodeSelectedDocumentLayer;
99
+ }
100
+ export interface TextmodeDocumentLayer {
101
+ id: string;
102
+ visible: boolean;
103
+ opacity: number;
104
+ blendMode: string;
105
+ offsetX: number;
106
+ offsetY: number;
107
+ rotationZ: number;
108
+ grid: JSONLayerGrid;
109
+ cells: JSONCellCollection;
110
+ }
111
+ export interface TextmodeAllDocumentJSON {
112
+ format: JSONDocumentFormat;
113
+ formatVersion: JSONDocumentVersion;
114
+ target: 'all';
115
+ metadata?: JSONExportMetadata;
116
+ canvas: {
117
+ width: number;
118
+ height: number;
119
+ };
120
+ layers: TextmodeDocumentLayer[];
121
+ }
122
+ /**
123
+ * JSON document produced by the selected-layer or layer-stack exporter.
124
+ *
125
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/TextmodeDocumentJSON | TextmodeDocumentJSON API reference}
126
+ */
127
+ export type TextmodeDocumentJSON = TextmodeSelectedDocumentJSON | TextmodeAllDocumentJSON;
128
+ export interface CanonicalTextmodeCell extends Omit<JSONObjectRowCell, 'foreground' | 'background' | 'transform'> {
129
+ foreground: JSONRGBAColor;
130
+ background: JSONRGBAColor;
131
+ transform: JSONCellTransform;
132
+ }
133
+ export interface CanonicalTextmodeCellCollection {
134
+ encoding: typeof TEXTMODE_OBJECT_ROWS_ENCODING;
135
+ rows: CanonicalTextmodeCell[][];
136
+ }
137
+ export interface CanonicalTextmodeSelectedDocument extends Omit<TextmodeSelectedDocumentJSON, 'layer'> {
138
+ layer: {
139
+ id: string;
140
+ cells: CanonicalTextmodeCellCollection;
141
+ };
142
+ }
143
+ export interface CanonicalTextmodeDocumentLayer extends Omit<TextmodeDocumentLayer, 'cells'> {
144
+ cells: CanonicalTextmodeCellCollection;
145
+ }
146
+ export interface CanonicalTextmodeAllDocument extends Omit<TextmodeAllDocumentJSON, 'layers'> {
147
+ layers: CanonicalTextmodeDocumentLayer[];
148
+ }
149
+ export type CanonicalTextmodeDocument = CanonicalTextmodeSelectedDocument | CanonicalTextmodeAllDocument;
150
+ export interface TextmodeDocumentLimits {
151
+ maxCells?: number;
152
+ maxLayers?: number;
153
+ maxLayerIdLength?: number;
154
+ maxCharacterLength?: number;
155
+ maxMetadataStringLength?: number;
156
+ }
157
+ export interface TextmodeDocumentDecodeOptions {
158
+ limits?: TextmodeDocumentLimits;
159
+ acceptLegacy?: boolean;
160
+ }
161
+ export type TextmodeDocumentErrorCode = 'INVALID_JSON' | 'INVALID_DOCUMENT' | 'UNSUPPORTED_FORMAT' | 'UNSUPPORTED_VERSION' | 'UNSUPPORTED_TARGET' | 'UNSUPPORTED_ENCODING' | 'LIMIT_EXCEEDED';
162
+ export interface TextmodeDocumentError {
163
+ code: TextmodeDocumentErrorCode;
164
+ message: string;
165
+ path?: string;
166
+ }
167
+ export interface TextmodeDocumentWarning {
168
+ code: 'LEGACY_DOCUMENT_MIGRATED';
169
+ message: string;
170
+ }
171
+ export type JSONParseResult = {
172
+ ok: true;
173
+ value: unknown;
174
+ } | {
175
+ ok: false;
176
+ error: TextmodeDocumentError;
177
+ };
178
+ export type TextmodeDocumentDecodeResult = {
179
+ ok: true;
180
+ document: CanonicalTextmodeDocument;
181
+ warnings: TextmodeDocumentWarning[];
182
+ } | {
183
+ ok: false;
184
+ error: TextmodeDocumentError;
185
+ };
186
+ export type TextmodeDocumentParseResult = TextmodeDocumentDecodeResult;
187
+ export interface LegacyTextmodeSelectedDocumentJSON {
188
+ $schema?: string;
189
+ format: typeof LEGACY_TEXTMODE_LAYER_FORMAT;
190
+ formatVersion: typeof LEGACY_TEXTMODE_SELECTED_VERSION;
191
+ metadata?: JSONExportMetadata;
192
+ canvas: {
193
+ width: number;
194
+ height: number;
195
+ };
196
+ grid: JSONLayerGrid;
197
+ layer: TextmodeSelectedDocumentLayer;
198
+ }
199
+ export interface LegacyTextmodeAllDocumentJSON {
200
+ $schema?: string;
201
+ format: typeof LEGACY_TEXTMODE_LAYER_FORMAT;
202
+ formatVersion: typeof LEGACY_TEXTMODE_ALL_VERSION;
203
+ metadata?: JSONExportMetadata;
204
+ canvas: {
205
+ width: number;
206
+ height: number;
207
+ };
208
+ layers: TextmodeDocumentLayer[];
209
+ }
@@ -0,0 +1,37 @@
1
+ import type { JSONExportMetadata, JSONLayerGrid, JSONRGBAColor, TextmodeDocumentDecodeResult, TextmodeDocumentError, TextmodeDocumentErrorCode, TextmodeDocumentLimits } from './types';
2
+ export type UnknownRecord = Record<string, unknown>;
3
+ export type ResolvedLimits = Required<TextmodeDocumentLimits>;
4
+ export type DecodeContext = {
5
+ limits: ResolvedLimits;
6
+ remainingCells: number;
7
+ };
8
+ export declare class DocumentDecodeFailure extends Error {
9
+ readonly detail: TextmodeDocumentError;
10
+ constructor(detail: TextmodeDocumentError);
11
+ }
12
+ export declare function decodeColor(value: unknown, path: string): JSONRGBAColor;
13
+ export declare function decodeCanvas(value: unknown, path: string): {
14
+ width: number;
15
+ height: number;
16
+ };
17
+ export declare function decodeGrid(value: unknown, path: string): JSONLayerGrid;
18
+ export declare function decodeMetadata(value: unknown, path: string, limits: ResolvedLimits): JSONExportMetadata;
19
+ export declare function decodeLayerId(value: unknown, path: string, limits: ResolvedLimits): string;
20
+ export declare function assertCanvasMatchesGrid(canvas: {
21
+ width: number;
22
+ height: number;
23
+ }, grid: JSONLayerGrid, path: string): void;
24
+ export declare function resolveLimits(limits: TextmodeDocumentLimits | undefined): ResolvedLimits;
25
+ export declare function checkedProduct(left: number, right: number, path: string): number;
26
+ export declare function normalizeRotation(rotation: number): number;
27
+ export declare function requireRecord(value: unknown, path: string): UnknownRecord;
28
+ export declare function requireArray(value: unknown, path: string): unknown[];
29
+ export declare function requireString(value: unknown, path: string): string;
30
+ export declare function requireBoundedString(value: unknown, path: string, maxLength: number): string;
31
+ export declare function requireCharacter(value: unknown, path: string, limits: ResolvedLimits): string;
32
+ export declare function requireBoolean(value: unknown, path: string): boolean;
33
+ export declare function requireFiniteNumber(value: unknown, path: string): number;
34
+ export declare function requireNumberInRange(value: unknown, path: string, minimum: number, maximum: number): number;
35
+ export declare function requireSafeInteger(value: unknown, path: string): number;
36
+ export declare function failure(code: TextmodeDocumentErrorCode, message: string, path?: string): TextmodeDocumentDecodeResult;
37
+ export declare function fail(code: TextmodeDocumentErrorCode, message: string, path?: string): never;
@@ -9,18 +9,5 @@ export declare class FileHandler {
9
9
  * @param blob The content to download
10
10
  * @param filename The filename to use for the downloaded file
11
11
  */
12
- $downloadFile(blob: Blob, filename: string | undefined): void;
13
- /**
14
- * Validates and sanitizes filename for safety and compatibility
15
- *
16
- * @param filename The filename to validate
17
- * @returns Sanitized filename
18
- */
19
- private _sanitizeFilename;
20
- /**
21
- * Generates a default filename with timestamp
22
- *
23
- * @returns Generated filename
24
- */
25
- private _generateDefaultFilename;
12
+ $downloadFile(blob: Blob, filename: string | undefined, extension?: `.${string}`): void;
26
13
  }
@@ -0,0 +1,6 @@
1
+ /** Central filename normalization and canonical-extension policy. */
2
+ export declare class FilenamePolicy {
3
+ $resolve(filename: string | undefined, extension: `.${string}`, createdAt?: Date): string;
4
+ $sanitizeStem(filename: string | undefined, createdAt?: Date, maximumBytes?: number): string;
5
+ $defaultStem(createdAt?: Date): string;
6
+ }
@@ -4,8 +4,6 @@ import type { TextmodeLayer } from 'textmode.js';
4
4
  /**
5
5
  * Shared option for exporters that read layer framebuffer data.
6
6
  *
7
- * @category Layer data export
8
- *
9
7
  * @see {@link https://code.textmode.art/api/textmode.export.js/interfaces/LayerExportOptions | LayerExportOptions API reference}
10
8
  */
11
9
  export interface LayerExportOptions {
@@ -0,0 +1,7 @@
1
+ /** Rejects overlapping deterministic captures for one installed plugin instance. */
2
+ export declare class ExclusiveCaptureGate {
3
+ private _active;
4
+ private _disposed;
5
+ acquire(): () => void;
6
+ dispose(): void;
7
+ }
@@ -1,8 +1,8 @@
1
- export interface VideoFrameTiming {
1
+ export interface FrameTiming {
2
2
  startSeconds: number;
3
3
  centerSeconds: number;
4
4
  endSeconds: number;
5
5
  durationSeconds: number;
6
6
  }
7
7
  /** Produces one stable microsecond-rounded interval for an output frame. */
8
- export declare function videoFrameTiming(frameIndex: number, frameRate: number): VideoFrameTiming;
8
+ export declare function frameTiming(frameIndex: number, frameRate: number): FrameTiming;
@@ -1,13 +1,7 @@
1
1
  import type { Textmodifier } from 'textmode.js';
2
- import type { VideoRenderFrameOptions } from './types';
3
- export type PostDrawSubscription = (callback: () => void) => () => void;
4
- /**
5
- * Drives deterministic video export frames through public textmode APIs.
6
- *
7
- * The visible textmode canvas remains untouched. Each presented frame is copied
8
- * into a staging canvas sized for the requested video output.
9
- */
10
- export declare class VideoFrameDriver {
2
+ import type { FrameSequenceRenderOptions, FrameSequenceStagingSurface, PostDrawSubscription } from './types';
3
+ /** Drives deterministic export frames through public textmode.js lifecycle APIs. */
4
+ export declare class FrameSequenceDriver {
11
5
  readonly canvas: HTMLCanvasElement;
12
6
  private readonly _textmodifier;
13
7
  private readonly _registerPostDrawHook;
@@ -16,8 +10,8 @@ export declare class VideoFrameDriver {
16
10
  private _pendingFrame;
17
11
  private _syntheticFrameCount;
18
12
  private _syntheticMillis;
19
- constructor(textmodifier: Textmodifier, registerPostDrawHook: PostDrawSubscription, width: number, height: number);
20
- $render(options: VideoRenderFrameOptions): Promise<void>;
13
+ constructor(textmodifier: Textmodifier, registerPostDrawHook: PostDrawSubscription, stagingSurface?: FrameSequenceStagingSurface);
14
+ $render(options: FrameSequenceRenderOptions): Promise<void>;
21
15
  private _renderOneFrame;
22
16
  private _capturePendingFrame;
23
17
  private _createStagingCanvas;
@@ -0,0 +1,12 @@
1
+ export type FrameSequenceErrorCode = 'FRAME_SEQUENCE_ABORTED' | 'FRAME_SEQUENCE_TIMEOUT' | 'FRAME_SEQUENCE_BUSY' | 'FRAME_SEQUENCE_DISPOSED';
2
+ /** Internal error used by deterministic capture infrastructure. */
3
+ export declare class FrameSequenceError extends Error {
4
+ readonly code: FrameSequenceErrorCode;
5
+ readonly cause?: unknown;
6
+ constructor(code: FrameSequenceErrorCode, message: string, cause?: unknown);
7
+ }
8
+ export declare function createFrameSequenceAbortError(): FrameSequenceError;
9
+ export declare function createFrameSequenceTimeoutError(message: string, cause?: unknown): FrameSequenceError;
10
+ export declare function createFrameSequenceBusyError(): FrameSequenceError;
11
+ export declare function createFrameSequenceDisposedError(): FrameSequenceError;
12
+ export declare function isFrameSequenceAbortError(error: unknown): boolean;
@@ -0,0 +1,5 @@
1
+ export { ExclusiveCaptureGate } from './ExclusiveCaptureGate';
2
+ export { FrameSequenceDriver } from './FrameSequenceDriver';
3
+ export { frameTiming } from './FrameSchedule';
4
+ export { FrameSequenceError, createFrameSequenceAbortError, isFrameSequenceAbortError } from './errors';
5
+ export type { FrameSequenceDriverLike, FrameSequenceRenderOptions, FrameSequenceStagingSurface, PostDrawSubscription, } from './types';
@@ -0,0 +1,20 @@
1
+ import type { PrepareExportFrame } from '../FramePreparation';
2
+ export type PostDrawSubscription = (callback: () => void) => () => void;
3
+ export interface FrameSequenceStagingSurface {
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export interface FrameSequenceRenderOptions {
8
+ frameCount: number;
9
+ frameRate: number;
10
+ signal?: AbortSignal;
11
+ prepareFrame?: PrepareExportFrame;
12
+ onFrame(frame: {
13
+ frameIndex: number;
14
+ canvas: HTMLCanvasElement;
15
+ }): Promise<void> | void;
16
+ }
17
+ export interface FrameSequenceDriverLike {
18
+ readonly canvas: HTMLCanvasElement;
19
+ $render(options: FrameSequenceRenderOptions): Promise<void>;
20
+ }
@@ -0,0 +1 @@
1
+ export declare function withAbortableFrameTimeout<T>(promise: Promise<T>, message: string, signal: AbortSignal | undefined, timeoutMs: number): Promise<T>;
@@ -1,6 +1,9 @@
1
1
  export { DataExtractor } from './DataExtractor';
2
2
  export { FileHandler } from './FileHandler';
3
+ export { FilenamePolicy } from './FilenamePolicy';
3
4
  export { getEncodedGlyphValueFromColor, resolveGlyphByEncodedValue } from './CharacterResolver';
4
5
  export { createLayerTargetProvider, getLayerTargetId, getLayerTargetOptions, resolveLayerExportTarget, resolveLayerStackExportTargets, } from './LayerTarget';
5
6
  export type { LayerExportOptions, LayerTargetOption, LayerTargetProvider, ResolvedLayerExportTarget, ResolvedLayerStackExportTarget, } from './LayerTarget';
6
7
  export type { ExportFrameContext, PrepareExportFrame } from './FramePreparation';
8
+ export { ExclusiveCaptureGate, FrameSequenceDriver, FrameSequenceError, createFrameSequenceAbortError, frameTiming, isFrameSequenceAbortError, } from './frame-sequence';
9
+ export type { FrameSequenceDriverLike, FrameSequenceRenderOptions, FrameSequenceStagingSurface, PostDrawSubscription, } from './frame-sequence';
@@ -1,5 +1,5 @@
1
1
  import type { Textmodifier } from 'textmode.js';
2
- import { type PostDrawSubscription } from '../video/VideoFrameDriver';
2
+ import { type PostDrawSubscription } from '../base';
3
3
  import type { GIFExportOptions } from './types';
4
4
  /** Deterministic, bounded-memory GIF exporter. */
5
5
  export declare class GIFExporter {
@@ -1,3 +1,2 @@
1
1
  export { GIFExporter } from './GIFExporter';
2
- export { GIFRecorder } from './GIFRecorder';
3
2
  export type { GIFExportOptions, GIFExportProgress, GIFGenerationOptions, GIFRecordingState } from './types';
@@ -3,8 +3,6 @@ export type GIFRecordingState = 'idle' | 'recording' | 'encoding' | 'completed'
3
3
  /**
4
4
  * Progress information emitted while deterministic frames are captured and encoded as an animated GIF.
5
5
  *
6
- * @category GIF export
7
- *
8
6
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/GIFExportProgress | GIFExportProgress API reference}
9
7
  */
10
8
  export type GIFExportProgress = {
@@ -36,8 +34,6 @@ export type GIFExportProgress = {
36
34
  /**
37
35
  * Options for capturing deterministic textmode frames as an animated GIF.
38
36
  *
39
- * @category GIF export
40
- *
41
37
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/GIFExportOptions | GIFExportOptions API reference}
42
38
  */
43
39
  export type GIFExportOptions = {
@@ -103,9 +99,3 @@ export interface GIFGenerationOptions {
103
99
  signal?: AbortSignal;
104
100
  prepareFrame?: PrepareExportFrame;
105
101
  }
106
- export interface GIFFrame {
107
- imageData: ImageData;
108
- width: number;
109
- height: number;
110
- delayMs?: number;
111
- }
@@ -8,8 +8,6 @@ export type ImageFormat = 'png' | 'jpg' | 'webp';
8
8
  /**
9
9
  * Options for exporting the textmode content to image format.
10
10
  *
11
- * @category Canvas capture
12
- *
13
11
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/ImageExportOptions | ImageExportOptions API reference}
14
12
  */
15
13
  export type ImageExportOptions = {
@@ -41,7 +41,7 @@ export declare class JSONExporter {
41
41
  * @param options Export options
42
42
  * @returns Structured JSON document for the selected layer or layer stack
43
43
  */
44
- $generateJSONData(textmodifier: Textmodifier, options?: JSONExportOptions): TextmodeDocumentJSON;
44
+ $generateJSONData(textmodifier: Textmodifier, options?: JSONExportOptions, createdAt?: Date): TextmodeDocumentJSON;
45
45
  /**
46
46
  * Generates the serialized JSON string for the selected layer or layer stack.
47
47
  *
@@ -49,7 +49,7 @@ export declare class JSONExporter {
49
49
  * @param options Export options
50
50
  * @returns Serialized JSON string
51
51
  */
52
- $generateJSONString(textmodifier: Textmodifier, options?: JSONExportOptions): string;
52
+ $generateJSONString(textmodifier: Textmodifier, options?: JSONExportOptions, createdAt?: Date): string;
53
53
  /**
54
54
  * Exports the generated JSON to a downloadable file.
55
55
  *